mf: Avoid leaking nodes in IMFTopoLoader_Load.
[wine.git] / dlls / mf / tests / mf.c
blob006709f698cf854cb3974f80c6317b541b7450a2
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_callback
1306 IMFAsyncCallback IMFAsyncCallback_iface;
1309 static HRESULT WINAPI testcallback_QueryInterface(IMFAsyncCallback *iface, REFIID riid, void **obj)
1311 if (IsEqualIID(riid, &IID_IMFAsyncCallback) ||
1312 IsEqualIID(riid, &IID_IUnknown))
1314 *obj = iface;
1315 IMFAsyncCallback_AddRef(iface);
1316 return S_OK;
1319 *obj = NULL;
1320 return E_NOINTERFACE;
1323 static ULONG WINAPI testcallback_AddRef(IMFAsyncCallback *iface)
1325 return 2;
1328 static ULONG WINAPI testcallback_Release(IMFAsyncCallback *iface)
1330 return 1;
1333 static HRESULT WINAPI testcallback_GetParameters(IMFAsyncCallback *iface, DWORD *flags, DWORD *queue)
1335 ok(flags != NULL && queue != NULL, "Unexpected arguments.\n");
1336 return E_NOTIMPL;
1339 static HRESULT WINAPI testcallback_Invoke(IMFAsyncCallback *iface, IMFAsyncResult *result)
1341 ok(result != NULL, "Unexpected result object.\n");
1343 return E_NOTIMPL;
1346 static const IMFAsyncCallbackVtbl testcallbackvtbl =
1348 testcallback_QueryInterface,
1349 testcallback_AddRef,
1350 testcallback_Release,
1351 testcallback_GetParameters,
1352 testcallback_Invoke,
1355 static void init_test_callback(struct test_callback *callback)
1357 callback->IMFAsyncCallback_iface.lpVtbl = &testcallbackvtbl;
1360 static void test_session_events(IMFMediaSession *session)
1362 struct test_callback callback, callback2;
1363 IMFAsyncResult *result;
1364 IMFMediaEvent *event;
1365 HRESULT hr;
1367 init_test_callback(&callback);
1368 init_test_callback(&callback2);
1370 hr = IMFMediaSession_GetEvent(session, MF_EVENT_FLAG_NO_WAIT, &event);
1371 ok(hr == MF_E_NO_EVENTS_AVAILABLE, "Unexpected hr %#lx.\n", hr);
1373 /* Async case. */
1374 hr = IMFMediaSession_BeginGetEvent(session, NULL, NULL);
1375 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
1377 hr = IMFMediaSession_BeginGetEvent(session, &callback.IMFAsyncCallback_iface, (IUnknown *)session);
1378 ok(hr == S_OK, "Failed to Begin*, hr %#lx.\n", hr);
1380 /* Same callback, same state. */
1381 hr = IMFMediaSession_BeginGetEvent(session, &callback.IMFAsyncCallback_iface, (IUnknown *)session);
1382 ok(hr == MF_S_MULTIPLE_BEGIN, "Unexpected hr %#lx.\n", hr);
1384 /* Same callback, different state. */
1385 hr = IMFMediaSession_BeginGetEvent(session, &callback.IMFAsyncCallback_iface, (IUnknown *)&callback.IMFAsyncCallback_iface);
1386 ok(hr == MF_E_MULTIPLE_BEGIN, "Unexpected hr %#lx.\n", hr);
1388 /* Different callback, same state. */
1389 hr = IMFMediaSession_BeginGetEvent(session, &callback2.IMFAsyncCallback_iface, (IUnknown *)session);
1390 ok(hr == MF_E_MULTIPLE_SUBSCRIBERS, "Unexpected hr %#lx.\n", hr);
1392 /* Different callback, different state. */
1393 hr = IMFMediaSession_BeginGetEvent(session, &callback2.IMFAsyncCallback_iface, (IUnknown *)&callback.IMFAsyncCallback_iface);
1394 ok(hr == MF_E_MULTIPLE_SUBSCRIBERS, "Unexpected hr %#lx.\n", hr);
1396 hr = MFCreateAsyncResult(NULL, &callback.IMFAsyncCallback_iface, NULL, &result);
1397 ok(hr == S_OK, "Failed to create result, hr %#lx.\n", hr);
1399 hr = IMFMediaSession_EndGetEvent(session, result, &event);
1400 ok(hr == E_FAIL, "Unexpected hr %#lx.\n", hr);
1402 /* Shutdown behavior. */
1403 hr = IMFMediaSession_Shutdown(session);
1404 ok(hr == S_OK, "Failed to shut down, hr %#lx.\n", hr);
1407 static void test_media_session(void)
1409 IMFRateSupport *rate_support;
1410 IMFAttributes *attributes;
1411 IMFMediaSession *session;
1412 MFSHUTDOWN_STATUS status;
1413 IMFTopology *topology;
1414 IMFShutdown *shutdown;
1415 PROPVARIANT propvar;
1416 IMFGetService *gs;
1417 IMFClock *clock;
1418 DWORD caps;
1419 HRESULT hr;
1421 hr = MFStartup(MF_VERSION, MFSTARTUP_FULL);
1422 ok(hr == S_OK, "Startup failure, hr %#lx.\n", hr);
1424 hr = MFCreateMediaSession(NULL, &session);
1425 ok(hr == S_OK, "Failed to create media session, hr %#lx.\n", hr);
1427 check_interface(session, &IID_IMFGetService, TRUE);
1428 check_interface(session, &IID_IMFRateSupport, TRUE);
1429 check_interface(session, &IID_IMFRateControl, TRUE);
1430 check_interface(session, &IID_IMFAttributes, FALSE);
1431 check_interface(session, &IID_IMFTopologyNodeAttributeEditor, FALSE);
1432 check_interface(session, &IID_IMFLocalMFTRegistration, FALSE);
1433 check_service_interface(session, &MF_RATE_CONTROL_SERVICE, &IID_IMFRateSupport, TRUE);
1434 check_service_interface(session, &MF_RATE_CONTROL_SERVICE, &IID_IMFRateControl, TRUE);
1435 check_service_interface(session, &MF_TOPONODE_ATTRIBUTE_EDITOR_SERVICE, &IID_IMFTopologyNodeAttributeEditor, TRUE);
1436 check_service_interface(session, &MF_LOCAL_MFT_REGISTRATION_SERVICE, &IID_IMFLocalMFTRegistration, TRUE);
1438 hr = IMFMediaSession_GetClock(session, &clock);
1439 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1441 hr = IMFClock_QueryInterface(clock, &IID_IMFShutdown, (void **)&shutdown);
1442 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1444 hr = IMFShutdown_GetShutdownStatus(shutdown, &status);
1445 ok(hr == MF_E_INVALIDREQUEST, "Unexpected hr %#lx.\n", hr);
1447 hr = IMFMediaSession_Shutdown(session);
1448 ok(hr == S_OK, "Failed to shut down, hr %#lx.\n", hr);
1450 check_interface(session, &IID_IMFGetService, TRUE);
1452 hr = IMFMediaSession_QueryInterface(session, &IID_IMFGetService, (void **)&gs);
1453 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1455 hr = IMFGetService_GetService(gs, &MF_RATE_CONTROL_SERVICE, &IID_IMFRateSupport, (void **)&rate_support);
1456 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
1458 IMFGetService_Release(gs);
1460 hr = IMFShutdown_GetShutdownStatus(shutdown, &status);
1461 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1462 ok(status == MFSHUTDOWN_COMPLETED, "Unexpected shutdown status %u.\n", status);
1464 IMFShutdown_Release(shutdown);
1466 hr = IMFMediaSession_ClearTopologies(session);
1467 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
1469 hr = IMFMediaSession_Start(session, &GUID_NULL, NULL);
1470 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
1472 propvar.vt = VT_EMPTY;
1473 hr = IMFMediaSession_Start(session, &GUID_NULL, &propvar);
1474 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
1476 hr = IMFMediaSession_Pause(session);
1477 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
1479 hr = IMFMediaSession_Stop(session);
1480 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
1482 hr = IMFMediaSession_Close(session);
1483 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
1485 hr = IMFMediaSession_GetClock(session, &clock);
1486 ok(hr == MF_E_SHUTDOWN || broken(hr == E_UNEXPECTED) /* Win7 */, "Unexpected hr %#lx.\n", hr);
1488 hr = IMFMediaSession_GetSessionCapabilities(session, &caps);
1489 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
1491 hr = IMFMediaSession_GetSessionCapabilities(session, NULL);
1492 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
1494 hr = IMFMediaSession_GetFullTopology(session, MFSESSION_GETFULLTOPOLOGY_CURRENT, 0, &topology);
1495 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
1497 hr = IMFMediaSession_Shutdown(session);
1498 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
1500 IMFMediaSession_Release(session);
1502 /* Custom topology loader, GUID is not registered. */
1503 hr = MFCreateAttributes(&attributes, 1);
1504 ok(hr == S_OK, "Failed to create attributes, hr %#lx.\n", hr);
1506 hr = IMFAttributes_SetGUID(attributes, &MF_SESSION_TOPOLOADER, &MF_SESSION_TOPOLOADER);
1507 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
1509 hr = MFCreateMediaSession(attributes, &session);
1510 ok(hr == S_OK, "Failed to create media session, hr %#lx.\n", hr);
1511 IMFMediaSession_Release(session);
1513 /* Disabled quality manager. */
1514 hr = IMFAttributes_SetGUID(attributes, &MF_SESSION_QUALITY_MANAGER, &GUID_NULL);
1515 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
1517 hr = MFCreateMediaSession(attributes, &session);
1518 ok(hr == S_OK, "Failed to create media session, hr %#lx.\n", hr);
1519 IMFMediaSession_Release(session);
1521 IMFAttributes_Release(attributes);
1523 /* Basic events behavior. */
1524 hr = MFCreateMediaSession(NULL, &session);
1525 ok(hr == S_OK, "Failed to create media session, hr %#lx.\n", hr);
1527 test_session_events(session);
1529 IMFMediaSession_Release(session);
1531 hr = MFShutdown();
1532 ok(hr == S_OK, "Shutdown failure, hr %#lx.\n", hr);
1535 static void test_media_session_rate_control(void)
1537 IMFRateControl *rate_control, *clock_rate_control;
1538 IMFPresentationClock *presentation_clock;
1539 IMFPresentationTimeSource *time_source;
1540 MFCLOCK_PROPERTIES clock_props;
1541 IMFRateSupport *rate_support;
1542 IMFMediaSession *session;
1543 IMFClock *clock;
1544 HRESULT hr;
1545 float rate;
1546 BOOL thin;
1548 hr = MFStartup(MF_VERSION, MFSTARTUP_FULL);
1549 ok(hr == S_OK, "Startup failure, hr %#lx.\n", hr);
1551 hr = MFCreateMediaSession(NULL, &session);
1552 ok(hr == S_OK, "Failed to create media session, hr %#lx.\n", hr);
1554 hr = MFGetService((IUnknown *)session, &MF_RATE_CONTROL_SERVICE, &IID_IMFRateSupport, (void **)&rate_support);
1555 ok(hr == S_OK, "Failed to get rate support interface, hr %#lx.\n", hr);
1557 hr = MFGetService((IUnknown *)session, &MF_RATE_CONTROL_SERVICE, &IID_IMFRateControl, (void **)&rate_control);
1558 ok(hr == S_OK, "Failed to get rate control interface, hr %#lx.\n", hr);
1560 hr = IMFRateControl_GetRate(rate_control, NULL, NULL);
1561 ok(FAILED(hr), "Unexpected hr %#lx.\n", hr);
1563 rate = 0.0f;
1564 hr = IMFRateControl_GetRate(rate_control, NULL, &rate);
1565 ok(hr == S_OK, "Failed to get playback rate, hr %#lx.\n", hr);
1566 ok(rate == 1.0f, "Unexpected rate %f.\n", rate);
1568 hr = IMFRateControl_GetRate(rate_control, &thin, NULL);
1569 ok(FAILED(hr), "Unexpected hr %#lx.\n", hr);
1571 thin = TRUE;
1572 rate = 0.0f;
1573 hr = IMFRateControl_GetRate(rate_control, &thin, &rate);
1574 ok(hr == S_OK, "Failed to get playback rate, hr %#lx.\n", hr);
1575 ok(!thin, "Unexpected thinning.\n");
1576 ok(rate == 1.0f, "Unexpected rate %f.\n", rate);
1578 hr = IMFMediaSession_GetClock(session, &clock);
1579 ok(hr == S_OK, "Failed to get clock, hr %#lx.\n", hr);
1581 hr = IMFClock_QueryInterface(clock, &IID_IMFPresentationClock, (void **)&presentation_clock);
1582 ok(hr == S_OK, "Failed to get rate control, hr %#lx.\n", hr);
1584 hr = IMFClock_QueryInterface(clock, &IID_IMFRateControl, (void **)&clock_rate_control);
1585 ok(hr == S_OK, "Failed to get rate control, hr %#lx.\n", hr);
1587 rate = 0.0f;
1588 hr = IMFRateControl_GetRate(clock_rate_control, NULL, &rate);
1589 ok(hr == S_OK, "Failed to get clock rate, hr %#lx.\n", hr);
1590 ok(rate == 1.0f, "Unexpected rate %f.\n", rate);
1592 hr = IMFRateControl_SetRate(clock_rate_control, FALSE, 1.5f);
1593 ok(hr == MF_E_CLOCK_NO_TIME_SOURCE, "Unexpected hr %#lx.\n", hr);
1595 hr = IMFRateControl_SetRate(rate_control, FALSE, 1.5f);
1596 ok(hr == S_OK, "Failed to set rate, hr %#lx.\n", hr);
1598 hr = IMFClock_GetProperties(clock, &clock_props);
1599 ok(hr == MF_E_CLOCK_NO_TIME_SOURCE, "Unexpected hr %#lx.\n", hr);
1601 hr = MFCreateSystemTimeSource(&time_source);
1602 ok(hr == S_OK, "Failed to create time source, hr %#lx.\n", hr);
1604 hr = IMFPresentationClock_SetTimeSource(presentation_clock, time_source);
1605 ok(hr == S_OK, "Failed to set time source, hr %#lx.\n", hr);
1607 hr = IMFRateControl_SetRate(rate_control, FALSE, 1.5f);
1608 ok(hr == S_OK, "Failed to set rate, hr %#lx.\n", hr);
1610 rate = 0.0f;
1611 hr = IMFRateControl_GetRate(clock_rate_control, NULL, &rate);
1612 ok(hr == S_OK, "Failed to get clock rate, hr %#lx.\n", hr);
1613 ok(rate == 1.0f, "Unexpected rate %f.\n", rate);
1615 IMFPresentationTimeSource_Release(time_source);
1617 IMFRateControl_Release(clock_rate_control);
1618 IMFPresentationClock_Release(presentation_clock);
1619 IMFClock_Release(clock);
1621 IMFRateControl_Release(rate_control);
1622 IMFRateSupport_Release(rate_support);
1624 IMFMediaSession_Release(session);
1626 hr = MFShutdown();
1627 ok(hr == S_OK, "Shutdown failure, hr %#lx.\n", hr);
1630 static HRESULT WINAPI test_grabber_callback_QueryInterface(IMFSampleGrabberSinkCallback *iface, REFIID riid,
1631 void **obj)
1633 if (IsEqualIID(riid, &IID_IMFSampleGrabberSinkCallback) ||
1634 IsEqualIID(riid, &IID_IMFClockStateSink) ||
1635 IsEqualIID(riid, &IID_IUnknown))
1637 *obj = iface;
1638 IMFSampleGrabberSinkCallback_AddRef(iface);
1639 return S_OK;
1642 *obj = NULL;
1643 return E_NOINTERFACE;
1646 static ULONG WINAPI test_grabber_callback_AddRef(IMFSampleGrabberSinkCallback *iface)
1648 return 2;
1651 static ULONG WINAPI test_grabber_callback_Release(IMFSampleGrabberSinkCallback *iface)
1653 return 1;
1656 static HRESULT WINAPI test_grabber_callback_OnClockStart(IMFSampleGrabberSinkCallback *iface, MFTIME systime,
1657 LONGLONG offset)
1659 return E_NOTIMPL;
1662 static HRESULT WINAPI test_grabber_callback_OnClockStop(IMFSampleGrabberSinkCallback *iface, MFTIME systime)
1664 return E_NOTIMPL;
1667 static HRESULT WINAPI test_grabber_callback_OnClockPause(IMFSampleGrabberSinkCallback *iface, MFTIME systime)
1669 return E_NOTIMPL;
1672 static HRESULT WINAPI test_grabber_callback_OnClockRestart(IMFSampleGrabberSinkCallback *iface, MFTIME systime)
1674 return E_NOTIMPL;
1677 static HRESULT WINAPI test_grabber_callback_OnClockSetRate(IMFSampleGrabberSinkCallback *iface, MFTIME systime, float rate)
1679 return E_NOTIMPL;
1682 static HRESULT WINAPI test_grabber_callback_OnSetPresentationClock(IMFSampleGrabberSinkCallback *iface,
1683 IMFPresentationClock *clock)
1685 return E_NOTIMPL;
1688 static HRESULT WINAPI test_grabber_callback_OnProcessSample(IMFSampleGrabberSinkCallback *iface, REFGUID major_type,
1689 DWORD sample_flags, LONGLONG sample_time, LONGLONG sample_duration, const BYTE *buffer, DWORD sample_size)
1691 return E_NOTIMPL;
1694 static HRESULT WINAPI test_grabber_callback_OnShutdown(IMFSampleGrabberSinkCallback *iface)
1696 return E_NOTIMPL;
1699 static const IMFSampleGrabberSinkCallbackVtbl test_grabber_callback_vtbl =
1701 test_grabber_callback_QueryInterface,
1702 test_grabber_callback_AddRef,
1703 test_grabber_callback_Release,
1704 test_grabber_callback_OnClockStart,
1705 test_grabber_callback_OnClockStop,
1706 test_grabber_callback_OnClockPause,
1707 test_grabber_callback_OnClockRestart,
1708 test_grabber_callback_OnClockSetRate,
1709 test_grabber_callback_OnSetPresentationClock,
1710 test_grabber_callback_OnProcessSample,
1711 test_grabber_callback_OnShutdown,
1714 struct test_source
1716 IMFMediaSource IMFMediaSource_iface;
1717 LONG refcount;
1720 static struct test_source *impl_from_IMFMediaSource(IMFMediaSource *iface)
1722 return CONTAINING_RECORD(iface, struct test_source, IMFMediaSource_iface);
1725 static HRESULT WINAPI test_source_QueryInterface(IMFMediaSource *iface, REFIID riid, void **out)
1727 if (IsEqualIID(riid, &IID_IMFMediaSource)
1728 || IsEqualIID(riid, &IID_IMFMediaEventGenerator)
1729 || IsEqualIID(riid, &IID_IUnknown))
1731 *out = iface;
1733 else
1735 *out = NULL;
1736 return E_NOINTERFACE;
1739 IMFMediaSource_AddRef(iface);
1740 return S_OK;
1743 static ULONG WINAPI test_source_AddRef(IMFMediaSource *iface)
1745 struct test_source *source = impl_from_IMFMediaSource(iface);
1746 return InterlockedIncrement(&source->refcount);
1749 static ULONG WINAPI test_source_Release(IMFMediaSource *iface)
1751 struct test_source *source = impl_from_IMFMediaSource(iface);
1752 ULONG refcount = InterlockedDecrement(&source->refcount);
1754 if (!refcount)
1755 free(source);
1757 return refcount;
1760 static HRESULT WINAPI test_source_GetEvent(IMFMediaSource *iface, DWORD flags, IMFMediaEvent **event)
1762 ok(0, "Unexpected call.\n");
1763 return E_NOTIMPL;
1766 static HRESULT WINAPI test_source_BeginGetEvent(IMFMediaSource *iface, IMFAsyncCallback *callback, IUnknown *state)
1768 ok(0, "Unexpected call.\n");
1769 return E_NOTIMPL;
1772 static HRESULT WINAPI test_source_EndGetEvent(IMFMediaSource *iface, IMFAsyncResult *result, IMFMediaEvent **event)
1774 ok(0, "Unexpected call.\n");
1775 return E_NOTIMPL;
1778 static HRESULT WINAPI test_source_QueueEvent(IMFMediaSource *iface, MediaEventType event_type, REFGUID ext_type,
1779 HRESULT hr, const PROPVARIANT *value)
1781 ok(0, "Unexpected call.\n");
1782 return E_NOTIMPL;
1785 static HRESULT WINAPI test_source_GetCharacteristics(IMFMediaSource *iface, DWORD *flags)
1787 ok(0, "Unexpected call.\n");
1788 return E_NOTIMPL;
1791 static HRESULT WINAPI test_source_CreatePresentationDescriptor(IMFMediaSource *iface, IMFPresentationDescriptor **pd)
1793 ok(0, "Unexpected call.\n");
1794 return E_NOTIMPL;
1797 static HRESULT WINAPI test_source_Start(IMFMediaSource *iface, IMFPresentationDescriptor *pd, const GUID *time_format,
1798 const PROPVARIANT *start_position)
1800 ok(0, "Unexpected call.\n");
1801 return E_NOTIMPL;
1804 static HRESULT WINAPI test_source_Stop(IMFMediaSource *iface)
1806 ok(0, "Unexpected call.\n");
1807 return E_NOTIMPL;
1810 static HRESULT WINAPI test_source_Pause(IMFMediaSource *iface)
1812 ok(0, "Unexpected call.\n");
1813 return E_NOTIMPL;
1816 static HRESULT WINAPI test_source_Shutdown(IMFMediaSource *iface)
1818 ok(0, "Unexpected call.\n");
1819 return E_NOTIMPL;
1822 static const IMFMediaSourceVtbl test_source_vtbl =
1824 test_source_QueryInterface,
1825 test_source_AddRef,
1826 test_source_Release,
1827 test_source_GetEvent,
1828 test_source_BeginGetEvent,
1829 test_source_EndGetEvent,
1830 test_source_QueueEvent,
1831 test_source_GetCharacteristics,
1832 test_source_CreatePresentationDescriptor,
1833 test_source_Start,
1834 test_source_Stop,
1835 test_source_Pause,
1836 test_source_Shutdown,
1839 static IMFMediaSource *create_test_source(void)
1841 struct test_source *source;
1843 source = calloc(1, sizeof(*source));
1844 source->IMFMediaSource_iface.lpVtbl = &test_source_vtbl;
1845 source->refcount = 1;
1847 return &source->IMFMediaSource_iface;
1850 static void init_media_type(IMFMediaType *mediatype, const struct attribute_desc *desc, ULONG limit)
1852 HRESULT hr;
1853 ULONG i;
1855 hr = IMFMediaType_DeleteAllItems(mediatype);
1856 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1858 for (i = 0; i < limit && desc[i].key; ++i)
1860 hr = IMFMediaType_SetItem(mediatype, desc[i].key, &desc[i].value);
1861 ok(hr == S_OK, "SetItem %s returned %#lx\n", debugstr_a(desc[i].name), hr);
1865 static void init_source_node(IMFMediaType *mediatype, IMFMediaSource *source, IMFTopologyNode *node)
1867 IMFPresentationDescriptor *pd;
1868 IMFMediaTypeHandler *handler;
1869 IMFStreamDescriptor *sd;
1870 HRESULT hr;
1872 hr = IMFTopologyNode_DeleteAllItems(node);
1873 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1875 hr = MFCreateStreamDescriptor(0, 1, &mediatype, &sd);
1876 ok(hr == S_OK, "Failed to create stream descriptor, hr %#lx.\n", hr);
1878 hr = IMFStreamDescriptor_GetMediaTypeHandler(sd, &handler);
1879 ok(hr == S_OK, "Failed to get media type handler, hr %#lx.\n", hr);
1881 hr = IMFMediaTypeHandler_SetCurrentMediaType(handler, mediatype);
1882 ok(hr == S_OK, "Failed to set current media type, hr %#lx.\n", hr);
1884 IMFMediaTypeHandler_Release(handler);
1886 hr = MFCreatePresentationDescriptor(1, &sd, &pd);
1887 ok(hr == S_OK, "Failed to create presentation descriptor, hr %#lx.\n", hr);
1889 hr = IMFTopologyNode_SetUnknown(node, &MF_TOPONODE_PRESENTATION_DESCRIPTOR, (IUnknown *)pd);
1890 ok(hr == S_OK, "Failed to set node pd, hr %#lx.\n", hr);
1892 IMFPresentationDescriptor_Release(pd);
1894 hr = IMFTopologyNode_SetUnknown(node, &MF_TOPONODE_STREAM_DESCRIPTOR, (IUnknown *)sd);
1895 ok(hr == S_OK, "Failed to set node sd, hr %#lx.\n", hr);
1897 if (source)
1899 hr = IMFTopologyNode_SetUnknown(node, &MF_TOPONODE_SOURCE, (IUnknown *)source);
1900 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1903 IMFStreamDescriptor_Release(sd);
1906 static void init_sink_node(IMFActivate *sink_activate, unsigned int method, IMFTopologyNode *node)
1908 IMFStreamSink *stream_sink;
1909 IMFMediaSink *sink;
1910 HRESULT hr;
1912 hr = IMFTopologyNode_DeleteAllItems(node);
1913 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1915 hr = IMFActivate_ActivateObject(sink_activate, &IID_IMFMediaSink, (void **)&sink);
1916 ok(hr == S_OK, "Failed to activate, hr %#lx.\n", hr);
1918 hr = IMFMediaSink_GetStreamSinkByIndex(sink, 0, &stream_sink);
1919 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1921 IMFMediaSink_Release(sink);
1923 hr = IMFTopologyNode_SetObject(node, (IUnknown *)stream_sink);
1924 ok(hr == S_OK, "Failed to set object, hr %#lx.\n", hr);
1926 IMFStreamSink_Release(stream_sink);
1928 hr = IMFTopologyNode_SetUINT32(node, &MF_TOPONODE_CONNECT_METHOD, method);
1929 ok(hr == S_OK, "Failed to set connect method, hr %#lx.\n", hr);
1932 enum loader_test_flags
1934 LOADER_EXPECTED_DECODER = 0x1,
1935 LOADER_EXPECTED_CONVERTER = 0x2,
1936 LOADER_TODO = 0x4,
1937 LOADER_NEEDS_VIDEO_PROCESSOR = 0x8,
1940 static void test_topology_loader(void)
1942 static const struct loader_test
1944 media_type_desc input_type;
1945 media_type_desc output_type;
1946 MF_CONNECT_METHOD method;
1947 HRESULT expected_result;
1948 unsigned int flags;
1950 loader_tests[] =
1953 /* PCM -> PCM, same type */
1955 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
1956 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_PCM),
1957 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 1),
1958 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 44100),
1959 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 44100),
1960 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 1),
1961 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 8),
1964 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
1965 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_PCM),
1966 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 1),
1967 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 44100),
1968 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 44100),
1969 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 1),
1970 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 8),
1973 MF_CONNECT_DIRECT,
1974 S_OK,
1978 /* PCM -> PCM, different bps. */
1980 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
1981 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_PCM),
1982 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 1),
1983 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 44100),
1984 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 44100),
1985 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 1),
1986 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 8),
1989 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
1990 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_PCM),
1991 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 1),
1992 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 48000),
1993 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 48000),
1994 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 1),
1995 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 8),
1998 MF_CONNECT_DIRECT,
1999 MF_E_INVALIDMEDIATYPE,
2003 /* PCM -> PCM, different bps. */
2005 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
2006 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_PCM),
2007 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 1),
2008 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 44100),
2009 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 44100),
2010 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 1),
2011 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 8),
2014 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
2015 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_PCM),
2016 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 1),
2017 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 48000),
2018 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 48000),
2019 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 1),
2020 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 8),
2023 MF_CONNECT_ALLOW_CONVERTER,
2024 S_OK,
2025 LOADER_NEEDS_VIDEO_PROCESSOR | LOADER_EXPECTED_CONVERTER | LOADER_TODO,
2029 /* MP3 -> PCM */
2031 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
2032 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_MP3),
2033 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 2),
2034 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 44100),
2035 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 16000),
2036 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 1),
2039 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
2040 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_PCM),
2041 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 1),
2042 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 44100),
2043 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 44100),
2044 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 1),
2045 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 8),
2048 MF_CONNECT_DIRECT,
2049 MF_E_INVALIDMEDIATYPE,
2053 /* MP3 -> PCM */
2055 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
2056 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_MP3),
2057 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 2),
2058 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 44100),
2059 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 16000),
2060 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 1),
2063 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
2064 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_PCM),
2065 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 1),
2066 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 44100),
2067 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 44100),
2068 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 1),
2069 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 8),
2072 MF_CONNECT_ALLOW_CONVERTER,
2073 MF_E_TRANSFORM_NOT_POSSIBLE_FOR_CURRENT_MEDIATYPE_COMBINATION,
2074 LOADER_NEEDS_VIDEO_PROCESSOR | LOADER_TODO,
2078 /* MP3 -> PCM */
2080 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
2081 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_MP3),
2082 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 2),
2083 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 44100),
2084 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 16000),
2085 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 1),
2088 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
2089 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_PCM),
2090 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 1),
2091 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 44100),
2092 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 44100),
2093 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 1),
2094 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 8),
2097 MF_CONNECT_ALLOW_DECODER,
2098 S_OK,
2099 LOADER_EXPECTED_DECODER | LOADER_TODO,
2103 IMFSampleGrabberSinkCallback test_grabber_callback = { &test_grabber_callback_vtbl };
2104 IMFTopologyNode *src_node, *sink_node, *src_node2, *sink_node2, *mft_node;
2105 IMFTopology *topology, *topology2, *full_topology;
2106 IMFMediaType *media_type, *input_type, *output_type;
2107 IMFPresentationDescriptor *pd;
2108 unsigned int i, count, value;
2109 IMFActivate *sink_activate;
2110 MF_TOPOLOGY_TYPE node_type;
2111 IMFStreamDescriptor *sd;
2112 IMFTransform *transform;
2113 IMFMediaSource *source;
2114 IMFTopoLoader *loader;
2115 IUnknown *node_object;
2116 WORD node_count;
2117 TOPOID node_id;
2118 DWORD index;
2119 HRESULT hr;
2120 BOOL ret;
2121 LONG ref;
2123 hr = MFStartup(MF_VERSION, MFSTARTUP_FULL);
2124 ok(hr == S_OK, "Startup failure, hr %#lx.\n", hr);
2126 hr = MFCreateTopoLoader(NULL);
2127 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
2129 hr = MFCreateTopoLoader(&loader);
2130 ok(hr == S_OK, "Failed to create topology loader, hr %#lx.\n", hr);
2132 hr = MFCreateTopology(&topology);
2133 ok(hr == S_OK, "Failed to create topology, hr %#lx.\n", hr);
2135 /* Empty topology */
2136 hr = IMFTopoLoader_Load(loader, topology, &full_topology, NULL);
2137 todo_wine_if(hr == S_OK)
2138 ok(hr == MF_E_TOPO_UNSUPPORTED, "Unexpected hr %#lx.\n", hr);
2139 if (hr == S_OK) IMFTopology_Release(full_topology);
2141 /* Add source node. */
2142 hr = MFCreateTopologyNode(MF_TOPOLOGY_SOURCESTREAM_NODE, &src_node);
2143 ok(hr == S_OK, "Failed to create topology node, hr %#lx.\n", hr);
2145 /* When a decoder is involved, windows requires this attribute to be present */
2146 source = create_test_source();
2148 hr = IMFTopologyNode_SetUnknown(src_node, &MF_TOPONODE_SOURCE, (IUnknown *)source);
2149 ok(hr == S_OK, "Failed to set node source, hr %#lx.\n", hr);
2151 hr = MFCreateMediaType(&media_type);
2152 ok(hr == S_OK, "Failed to create media type, hr %#lx.\n", hr);
2154 hr = IMFMediaType_SetGUID(media_type, &MF_MT_MAJOR_TYPE, &MFMediaType_Audio);
2155 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
2156 hr = IMFMediaType_SetGUID(media_type, &MF_MT_SUBTYPE, &MFAudioFormat_PCM);
2157 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
2159 hr = MFCreateStreamDescriptor(0, 1, &media_type, &sd);
2160 ok(hr == S_OK, "Failed to create stream descriptor, hr %#lx.\n", hr);
2162 hr = IMFTopologyNode_SetUnknown(src_node, &MF_TOPONODE_STREAM_DESCRIPTOR, (IUnknown *)sd);
2163 ok(hr == S_OK, "Failed to set node sd, hr %#lx.\n", hr);
2165 hr = MFCreatePresentationDescriptor(1, &sd, &pd);
2166 ok(hr == S_OK, "Failed to create presentation descriptor, hr %#lx.\n", hr);
2168 hr = IMFTopologyNode_SetUnknown(src_node, &MF_TOPONODE_PRESENTATION_DESCRIPTOR, (IUnknown *)pd);
2169 ok(hr == S_OK, "Failed to set node pd, hr %#lx.\n", hr);
2171 IMFMediaType_Release(media_type);
2173 hr = IMFTopology_AddNode(topology, src_node);
2174 ok(hr == S_OK, "Failed to add a node, hr %#lx.\n", hr);
2176 /* Source node only. */
2177 hr = IMFTopoLoader_Load(loader, topology, &full_topology, NULL);
2178 todo_wine_if(hr == E_INVALIDARG)
2179 ok(hr == MF_E_TOPO_UNSUPPORTED, "Unexpected hr %#lx.\n", hr);
2181 hr = MFCreateTopologyNode(MF_TOPOLOGY_OUTPUT_NODE, &sink_node);
2182 ok(hr == S_OK, "Failed to create output node, hr %#lx.\n", hr);
2184 hr = MFCreateMediaType(&media_type);
2185 ok(hr == S_OK, "Failed to create media type, hr %#lx.\n", hr);
2187 hr = IMFMediaType_SetGUID(media_type, &MF_MT_MAJOR_TYPE, &MFMediaType_Audio);
2188 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
2189 hr = IMFMediaType_SetGUID(media_type, &MF_MT_SUBTYPE, &MFAudioFormat_PCM);
2190 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
2192 hr = MFCreateSampleGrabberSinkActivate(media_type, &test_grabber_callback, &sink_activate);
2193 ok(hr == S_OK, "Failed to create grabber sink, hr %#lx.\n", hr);
2195 hr = IMFTopologyNode_SetObject(sink_node, (IUnknown *)sink_activate);
2196 ok(hr == S_OK, "Failed to set object, hr %#lx.\n", hr);
2198 IMFMediaType_Release(media_type);
2200 hr = IMFTopology_AddNode(topology, sink_node);
2201 ok(hr == S_OK, "Failed to add sink node, hr %#lx.\n", hr);
2203 hr = IMFTopoLoader_Load(loader, topology, &full_topology, NULL);
2204 todo_wine_if(hr == MF_E_TOPO_SINK_ACTIVATES_UNSUPPORTED)
2205 ok(hr == MF_E_TOPO_UNSUPPORTED, "Unexpected hr %#lx.\n", hr);
2207 hr = IMFTopologyNode_ConnectOutput(src_node, 0, sink_node, 0);
2208 ok(hr == S_OK, "Failed to connect nodes, hr %#lx.\n", hr);
2210 /* Sink was not resolved. */
2211 hr = IMFTopoLoader_Load(loader, topology, &full_topology, NULL);
2212 ok(hr == MF_E_TOPO_SINK_ACTIVATES_UNSUPPORTED, "Unexpected hr %#lx.\n", hr);
2214 hr = MFCreateMediaType(&input_type);
2215 ok(hr == S_OK, "Failed to create media type, hr %#lx.\n", hr);
2217 hr = MFCreateMediaType(&output_type);
2218 ok(hr == S_OK, "Failed to create media type, hr %#lx.\n", hr);
2220 for (i = 0; i < ARRAY_SIZE(loader_tests); ++i)
2222 const struct loader_test *test = &loader_tests[i];
2224 init_media_type(input_type, test->input_type, -1);
2225 init_media_type(output_type, test->output_type, -1);
2227 hr = MFCreateSampleGrabberSinkActivate(output_type, &test_grabber_callback, &sink_activate);
2228 ok(hr == S_OK, "Failed to create grabber sink, hr %#lx.\n", hr);
2230 init_source_node(input_type, source, src_node);
2231 init_sink_node(sink_activate, test->method, sink_node);
2233 hr = IMFTopology_GetCount(topology, &count);
2234 ok(hr == S_OK, "Failed to get attribute count, hr %#lx.\n", hr);
2235 ok(!count, "Unexpected count %u.\n", count);
2237 hr = IMFTopoLoader_Load(loader, topology, &full_topology, NULL);
2238 if (test->flags & LOADER_NEEDS_VIDEO_PROCESSOR && !has_video_processor)
2239 ok(hr == MF_E_INVALIDMEDIATYPE, "Unexpected hr %#lx on test %u.\n", hr, i);
2240 else
2242 todo_wine_if(test->flags & LOADER_TODO)
2243 ok(hr == test->expected_result, "Unexpected hr %#lx on test %u.\n", hr, i);
2244 ok(full_topology != topology, "Unexpected instance.\n");
2247 if (test->expected_result != hr)
2249 if (hr != S_OK) ref = 0;
2250 else ref = IMFTopology_Release(full_topology);
2251 ok(ref == 0, "Release returned %ld\n", ref);
2253 else if (test->expected_result == S_OK)
2255 hr = IMFTopology_GetCount(full_topology, &count);
2256 ok(hr == S_OK, "Failed to get attribute count, hr %#lx.\n", hr);
2257 todo_wine
2258 ok(count == 1, "Unexpected count %u.\n", count);
2260 value = 0xdeadbeef;
2261 hr = IMFTopology_GetUINT32(full_topology, &MF_TOPOLOGY_RESOLUTION_STATUS, &value);
2262 todo_wine {
2263 ok(hr == S_OK, "Failed to get attribute, hr %#lx.\n", hr);
2264 ok(value == MF_TOPOLOGY_RESOLUTION_SUCCEEDED, "Unexpected value %#x.\n", value);
2266 count = 2;
2267 if (test->flags & LOADER_EXPECTED_DECODER)
2268 count++;
2269 if (test->flags & LOADER_EXPECTED_CONVERTER)
2270 count++;
2272 hr = IMFTopology_GetNodeCount(full_topology, &node_count);
2273 ok(hr == S_OK, "Failed to get node count, hr %#lx.\n", hr);
2274 todo_wine_if(test->flags & (LOADER_EXPECTED_CONVERTER | LOADER_EXPECTED_DECODER))
2275 ok(node_count == count, "Unexpected node count %u.\n", node_count);
2277 hr = IMFTopologyNode_GetTopoNodeID(src_node, &node_id);
2278 ok(hr == S_OK, "Failed to get source node id, hr %#lx.\n", hr);
2280 hr = IMFTopology_GetNodeByID(full_topology, node_id, &src_node2);
2281 ok(hr == S_OK, "Failed to get source in resolved topology, hr %#lx.\n", hr);
2283 hr = IMFTopologyNode_GetTopoNodeID(sink_node, &node_id);
2284 ok(hr == S_OK, "Failed to get sink node id, hr %#lx.\n", hr);
2286 hr = IMFTopology_GetNodeByID(full_topology, node_id, &sink_node2);
2287 ok(hr == S_OK, "Failed to get sink in resolved topology, hr %#lx.\n", hr);
2289 if (test->flags & (LOADER_EXPECTED_DECODER | LOADER_EXPECTED_CONVERTER) && strcmp(winetest_platform, "wine"))
2291 hr = IMFTopologyNode_GetOutput(src_node2, 0, &mft_node, &index);
2292 ok(hr == S_OK, "Failed to get transform node in resolved topology, hr %#lx.\n", hr);
2293 ok(!index, "Unexpected stream index %lu.\n", index);
2295 hr = IMFTopologyNode_GetNodeType(mft_node, &node_type);
2296 ok(hr == S_OK, "Failed to get transform node type in resolved topology, hr %#lx.\n", hr);
2297 ok(node_type == MF_TOPOLOGY_TRANSFORM_NODE, "Unexpected node type %u.\n", node_type);
2299 hr = IMFTopologyNode_GetObject(mft_node, &node_object);
2300 ok(hr == S_OK, "Failed to get object of transform node, hr %#lx.\n", hr);
2302 if (test->flags & LOADER_EXPECTED_DECODER)
2304 value = 0;
2305 hr = IMFTopologyNode_GetUINT32(mft_node, &MF_TOPONODE_DECODER, &value);
2306 ok(hr == S_OK, "Failed to get attribute, hr %#lx.\n", hr);
2307 ok(value == 1, "Unexpected value.\n");
2310 hr = IMFTopologyNode_GetItem(mft_node, &MF_TOPONODE_TRANSFORM_OBJECTID, NULL);
2311 ok(hr == S_OK, "Failed to get attribute, hr %#lx.\n", hr);
2313 hr = IUnknown_QueryInterface(node_object, &IID_IMFTransform, (void **)&transform);
2314 ok(hr == S_OK, "Failed to get IMFTransform from transform node's object, hr %#lx.\n", hr);
2315 IUnknown_Release(node_object);
2317 hr = IMFTransform_GetInputCurrentType(transform, 0, &media_type);
2318 ok(hr == S_OK, "Failed to get transform input type, hr %#lx.\n", hr);
2320 hr = IMFMediaType_Compare(input_type, (IMFAttributes *)media_type, MF_ATTRIBUTES_MATCH_OUR_ITEMS, &ret);
2321 ok(hr == S_OK, "Failed to compare media types, hr %#lx.\n", hr);
2322 ok(ret, "Input type of first transform doesn't match source node type.\n");
2324 IMFTopologyNode_Release(mft_node);
2325 IMFMediaType_Release(media_type);
2326 IMFTransform_Release(transform);
2328 hr = IMFTopologyNode_GetInput(sink_node2, 0, &mft_node, &index);
2329 ok(hr == S_OK, "Failed to get transform node in resolved topology, hr %#lx.\n", hr);
2330 ok(!index, "Unexpected stream index %lu.\n", index);
2332 hr = IMFTopologyNode_GetNodeType(mft_node, &node_type);
2333 ok(hr == S_OK, "Failed to get transform node type in resolved topology, hr %#lx.\n", hr);
2334 ok(node_type == MF_TOPOLOGY_TRANSFORM_NODE, "Unexpected node type %u.\n", node_type);
2336 hr = IMFTopologyNode_GetItem(mft_node, &MF_TOPONODE_TRANSFORM_OBJECTID, NULL);
2337 ok(hr == S_OK, "Failed to get attribute, hr %#lx.\n", hr);
2339 hr = IMFTopologyNode_GetObject(mft_node, &node_object);
2340 ok(hr == S_OK, "Failed to get object of transform node, hr %#lx.\n", hr);
2342 hr = IUnknown_QueryInterface(node_object, &IID_IMFTransform, (void**) &transform);
2343 ok(hr == S_OK, "Failed to get IMFTransform from transform node's object, hr %#lx.\n", hr);
2344 IUnknown_Release(node_object);
2346 hr = IMFTransform_GetOutputCurrentType(transform, 0, &media_type);
2347 ok(hr == S_OK, "Failed to get transform output type, hr %#lx.\n", hr);
2349 hr = IMFMediaType_Compare(output_type, (IMFAttributes *)media_type, MF_ATTRIBUTES_MATCH_OUR_ITEMS, &ret);
2350 ok(hr == S_OK, "Failed to compare media types, hr %#lx.\n", hr);
2351 ok(ret, "Output type of last transform doesn't match sink node type.\n");
2353 IMFTopologyNode_Release(mft_node);
2354 IMFMediaType_Release(media_type);
2355 IMFTransform_Release(transform);
2358 IMFTopologyNode_Release(src_node2);
2359 IMFTopologyNode_Release(sink_node2);
2361 hr = IMFTopology_SetUINT32(full_topology, &IID_IMFTopology, 123);
2362 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2363 hr = IMFTopoLoader_Load(loader, full_topology, &topology2, NULL);
2364 ok(hr == S_OK, "Failed to resolve topology, hr %#lx.\n", hr);
2365 ok(full_topology != topology2, "Unexpected instance.\n");
2366 hr = IMFTopology_GetUINT32(topology2, &IID_IMFTopology, &value);
2367 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2369 ref = IMFTopology_Release(topology2);
2370 ok(ref == 0, "Release returned %ld\n", ref);
2371 ref = IMFTopology_Release(full_topology);
2372 ok(ref == 0, "Release returned %ld\n", ref);
2375 hr = IMFTopology_GetCount(topology, &count);
2376 ok(hr == S_OK, "Failed to get attribute count, hr %#lx.\n", hr);
2377 ok(!count, "Unexpected count %u.\n", count);
2379 hr = IMFActivate_ShutdownObject(sink_activate);
2380 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2381 ref = IMFActivate_Release(sink_activate);
2382 ok(ref == 0, "Release returned %ld\n", ref);
2385 ref = IMFTopology_Release(topology);
2386 ok(ref == 0, "Release returned %ld\n", ref);
2387 ref = IMFTopoLoader_Release(loader);
2388 ok(ref == 0, "Release returned %ld\n", ref);
2389 ref = IMFTopologyNode_Release(src_node);
2390 ok(ref == 0, "Release returned %ld\n", ref);
2391 ref = IMFTopologyNode_Release(sink_node);
2392 ok(ref == 0, "Release returned %ld\n", ref);
2394 ref = IMFMediaSource_Release(source);
2395 ok(ref == 0, "Release returned %ld\n", ref);
2397 ref = IMFPresentationDescriptor_Release(pd);
2398 ok(ref == 0, "Release returned %ld\n", ref);
2399 ref = IMFStreamDescriptor_Release(sd);
2400 ok(ref == 0, "Release returned %ld\n", ref);
2402 ref = IMFMediaType_Release(input_type);
2403 ok(ref == 0, "Release returned %ld\n", ref);
2404 /* FIXME: is native really leaking refs here, or are we? */
2405 ref = IMFMediaType_Release(output_type);
2406 todo_wine
2407 ok(ref != 0, "Release returned %ld\n", ref);
2409 hr = MFShutdown();
2410 ok(hr == S_OK, "Shutdown failure, hr %#lx.\n", hr);
2413 static void test_topology_loader_evr(void)
2415 IMFTopologyNode *node, *source_node, *evr_node;
2416 IMFTopology *topology, *full_topology;
2417 IMFMediaTypeHandler *handler;
2418 unsigned int i, count, value;
2419 IMFStreamSink *stream_sink;
2420 IMFMediaType *media_type;
2421 IMFActivate *activate;
2422 IMFTopoLoader *loader;
2423 IMFMediaSink *sink;
2424 WORD node_count;
2425 UINT64 value64;
2426 HWND window;
2427 HRESULT hr;
2428 LONG ref;
2430 hr = CoInitialize(NULL);
2431 ok(hr == S_OK, "Failed to initialize, hr %#lx.\n", hr);
2433 hr = MFCreateTopoLoader(&loader);
2434 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2436 /* Source node. */
2437 hr = MFCreateTopologyNode(MF_TOPOLOGY_SOURCESTREAM_NODE, &source_node);
2438 ok(hr == S_OK, "Failed to create topology node, hr %#lx.\n", hr);
2440 hr = MFCreateMediaType(&media_type);
2441 ok(hr == S_OK, "Failed to create media type, hr %#lx.\n", hr);
2443 hr = IMFMediaType_SetGUID(media_type, &MF_MT_MAJOR_TYPE, &MFMediaType_Video);
2444 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2445 hr = IMFMediaType_SetGUID(media_type, &MF_MT_SUBTYPE, &MFVideoFormat_RGB32);
2446 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2447 hr = IMFMediaType_SetUINT64(media_type, &MF_MT_FRAME_SIZE, (UINT64)640 << 32 | 480);
2448 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2449 hr = IMFMediaType_SetUINT32(media_type, &MF_MT_ALL_SAMPLES_INDEPENDENT, TRUE);
2450 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2452 init_source_node(media_type, NULL, source_node);
2454 /* EVR sink node. */
2455 window = create_window();
2457 hr = MFCreateVideoRendererActivate(window, &activate);
2458 ok(hr == S_OK, "Failed to create activate object, hr %#lx.\n", hr);
2460 hr = IMFActivate_ActivateObject(activate, &IID_IMFMediaSink, (void **)&sink);
2461 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2463 hr = IMFMediaSink_GetStreamSinkById(sink, 0, &stream_sink);
2464 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2466 hr = MFCreateTopologyNode(MF_TOPOLOGY_OUTPUT_NODE, &evr_node);
2467 ok(hr == S_OK, "Failed to create topology node, hr %#lx.\n", hr);
2469 hr = IMFTopologyNode_SetObject(evr_node, (IUnknown *)stream_sink);
2470 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2472 hr = IMFStreamSink_GetMediaTypeHandler(stream_sink, &handler);
2473 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2474 hr = IMFMediaTypeHandler_SetCurrentMediaType(handler, media_type);
2475 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2476 IMFMediaTypeHandler_Release(handler);
2478 IMFStreamSink_Release(stream_sink);
2480 hr = MFCreateTopology(&topology);
2481 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2483 hr = IMFTopology_AddNode(topology, source_node);
2484 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2485 hr = IMFTopology_AddNode(topology, evr_node);
2486 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2487 hr = IMFTopologyNode_ConnectOutput(source_node, 0, evr_node, 0);
2488 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2490 hr = IMFTopologyNode_SetUINT32(evr_node, &MF_TOPONODE_CONNECT_METHOD, MF_CONNECT_DIRECT);
2491 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2493 hr = IMFTopologyNode_GetCount(evr_node, &count);
2494 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2495 ok(count == 1, "Unexpected attribute count %u.\n", count);
2497 hr = IMFTopoLoader_Load(loader, topology, &full_topology, NULL);
2498 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2500 hr = IMFTopology_GetNodeCount(full_topology, &node_count);
2501 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2502 ok(node_count == 3, "Unexpected node count %u.\n", node_count);
2504 for (i = 0; i < node_count; ++i)
2506 MF_TOPOLOGY_TYPE node_type;
2508 hr = IMFTopology_GetNode(full_topology, i, &node);
2509 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2511 hr = IMFTopologyNode_GetNodeType(node, &node_type);
2512 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2514 if (node_type == MF_TOPOLOGY_OUTPUT_NODE)
2516 value = 1;
2517 hr = IMFTopologyNode_GetUINT32(node, &MF_TOPONODE_STREAMID, &value);
2518 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2519 ok(!value, "Unexpected stream id %u.\n", value);
2521 else if (node_type == MF_TOPOLOGY_SOURCESTREAM_NODE)
2523 value64 = 1;
2524 hr = IMFTopologyNode_GetUINT64(node, &MF_TOPONODE_MEDIASTART, &value64);
2525 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2526 ok(!value64, "Unexpected value.\n");
2529 IMFTopologyNode_Release(node);
2532 ref = IMFTopology_Release(full_topology);
2533 ok(ref == 0, "Release returned %ld\n", ref);
2534 ref = IMFTopoLoader_Release(loader);
2535 ok(ref == 0, "Release returned %ld\n", ref);
2536 ref = IMFTopology_Release(topology);
2537 ok(ref == 0, "Release returned %ld\n", ref);
2538 ref = IMFTopologyNode_Release(source_node);
2539 ok(ref == 0, "Release returned %ld\n", ref);
2540 ref = IMFTopologyNode_Release(evr_node);
2541 ok(ref == 0, "Release returned %ld\n", ref);
2543 hr = IMFActivate_ShutdownObject(activate);
2544 ok(hr == S_OK, "Failed to shut down, hr %#lx.\n", hr);
2545 ref = IMFActivate_Release(activate);
2546 ok(ref == 0, "Release returned %ld\n", ref);
2547 ref = IMFMediaSink_Release(sink);
2548 ok(ref == 0, "Release returned %ld\n", ref);
2550 ref = IMFMediaType_Release(media_type);
2551 ok(ref == 0, "Release returned %ld\n", ref);
2553 DestroyWindow(window);
2555 CoUninitialize();
2558 static HRESULT WINAPI testshutdown_QueryInterface(IMFShutdown *iface, REFIID riid, void **obj)
2560 if (IsEqualIID(riid, &IID_IMFShutdown) ||
2561 IsEqualIID(riid, &IID_IUnknown))
2563 *obj = iface;
2564 IMFShutdown_AddRef(iface);
2565 return S_OK;
2568 *obj = NULL;
2569 return E_NOINTERFACE;
2572 static ULONG WINAPI testshutdown_AddRef(IMFShutdown *iface)
2574 return 2;
2577 static ULONG WINAPI testshutdown_Release(IMFShutdown *iface)
2579 return 1;
2582 static HRESULT WINAPI testshutdown_Shutdown(IMFShutdown *iface)
2584 return 0xdead;
2587 static HRESULT WINAPI testshutdown_GetShutdownStatus(IMFShutdown *iface, MFSHUTDOWN_STATUS *status)
2589 ok(0, "Unexpected call.\n");
2590 return E_NOTIMPL;
2593 static const IMFShutdownVtbl testshutdownvtbl =
2595 testshutdown_QueryInterface,
2596 testshutdown_AddRef,
2597 testshutdown_Release,
2598 testshutdown_Shutdown,
2599 testshutdown_GetShutdownStatus,
2602 static void test_MFShutdownObject(void)
2604 IMFShutdown testshutdown = { &testshutdownvtbl };
2605 IUnknown testshutdown2 = { &testservicevtbl };
2606 HRESULT hr;
2608 hr = MFShutdownObject(NULL);
2609 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2611 hr = MFShutdownObject((IUnknown *)&testshutdown);
2612 ok(hr == S_OK, "Failed to shut down, hr %#lx.\n", hr);
2614 hr = MFShutdownObject(&testshutdown2);
2615 ok(hr == S_OK, "Failed to shut down, hr %#lx.\n", hr);
2618 enum clock_action
2620 CLOCK_START,
2621 CLOCK_STOP,
2622 CLOCK_PAUSE,
2625 static HRESULT WINAPI test_clock_sink_QueryInterface(IMFClockStateSink *iface, REFIID riid, void **obj)
2627 if (IsEqualIID(riid, &IID_IMFClockStateSink) ||
2628 IsEqualIID(riid, &IID_IUnknown))
2630 *obj = iface;
2631 IMFClockStateSink_AddRef(iface);
2632 return S_OK;
2635 *obj = NULL;
2636 return E_NOINTERFACE;
2639 static ULONG WINAPI test_clock_sink_AddRef(IMFClockStateSink *iface)
2641 return 2;
2644 static ULONG WINAPI test_clock_sink_Release(IMFClockStateSink *iface)
2646 return 1;
2649 static HRESULT WINAPI test_clock_sink_OnClockStart(IMFClockStateSink *iface, MFTIME system_time, LONGLONG offset)
2651 return E_NOTIMPL;
2654 static HRESULT WINAPI test_clock_sink_OnClockStop(IMFClockStateSink *iface, MFTIME system_time)
2656 return E_NOTIMPL;
2659 static HRESULT WINAPI test_clock_sink_OnClockPause(IMFClockStateSink *iface, MFTIME system_time)
2661 return E_NOTIMPL;
2664 static HRESULT WINAPI test_clock_sink_OnClockRestart(IMFClockStateSink *iface, MFTIME system_time)
2666 return E_NOTIMPL;
2669 static HRESULT WINAPI test_clock_sink_OnClockSetRate(IMFClockStateSink *iface, MFTIME system_time, float rate)
2671 return E_NOTIMPL;
2674 static const IMFClockStateSinkVtbl test_clock_sink_vtbl =
2676 test_clock_sink_QueryInterface,
2677 test_clock_sink_AddRef,
2678 test_clock_sink_Release,
2679 test_clock_sink_OnClockStart,
2680 test_clock_sink_OnClockStop,
2681 test_clock_sink_OnClockPause,
2682 test_clock_sink_OnClockRestart,
2683 test_clock_sink_OnClockSetRate,
2686 static void test_presentation_clock(void)
2688 static const struct clock_state_test
2690 enum clock_action action;
2691 MFCLOCK_STATE clock_state;
2692 MFCLOCK_STATE source_state;
2693 HRESULT hr;
2695 clock_state_change[] =
2697 { CLOCK_STOP, MFCLOCK_STATE_STOPPED, MFCLOCK_STATE_INVALID },
2698 { CLOCK_PAUSE, MFCLOCK_STATE_STOPPED, MFCLOCK_STATE_INVALID, MF_E_INVALIDREQUEST },
2699 { CLOCK_STOP, MFCLOCK_STATE_STOPPED, MFCLOCK_STATE_INVALID, MF_E_CLOCK_STATE_ALREADY_SET },
2700 { CLOCK_START, MFCLOCK_STATE_RUNNING, MFCLOCK_STATE_RUNNING },
2701 { CLOCK_START, MFCLOCK_STATE_RUNNING, MFCLOCK_STATE_RUNNING },
2702 { CLOCK_PAUSE, MFCLOCK_STATE_PAUSED, MFCLOCK_STATE_PAUSED },
2703 { CLOCK_PAUSE, MFCLOCK_STATE_PAUSED, MFCLOCK_STATE_PAUSED, MF_E_CLOCK_STATE_ALREADY_SET },
2704 { CLOCK_STOP, MFCLOCK_STATE_STOPPED, MFCLOCK_STATE_STOPPED },
2705 { CLOCK_START, MFCLOCK_STATE_RUNNING, MFCLOCK_STATE_RUNNING },
2706 { CLOCK_STOP, MFCLOCK_STATE_STOPPED, MFCLOCK_STATE_STOPPED },
2707 { CLOCK_STOP, MFCLOCK_STATE_STOPPED, MFCLOCK_STATE_STOPPED, MF_E_CLOCK_STATE_ALREADY_SET },
2708 { CLOCK_PAUSE, MFCLOCK_STATE_STOPPED, MFCLOCK_STATE_STOPPED, MF_E_INVALIDREQUEST },
2709 { CLOCK_START, MFCLOCK_STATE_RUNNING, MFCLOCK_STATE_RUNNING },
2710 { CLOCK_PAUSE, MFCLOCK_STATE_PAUSED, MFCLOCK_STATE_PAUSED },
2711 { CLOCK_START, MFCLOCK_STATE_RUNNING, MFCLOCK_STATE_RUNNING },
2713 IMFClockStateSink test_sink = { &test_clock_sink_vtbl };
2714 IMFPresentationTimeSource *time_source;
2715 MFCLOCK_PROPERTIES props, props2;
2716 IMFRateControl *rate_control;
2717 IMFPresentationClock *clock;
2718 MFSHUTDOWN_STATUS status;
2719 IMFShutdown *shutdown;
2720 MFTIME systime, time;
2721 LONGLONG clock_time;
2722 MFCLOCK_STATE state;
2723 unsigned int i;
2724 DWORD value;
2725 float rate;
2726 HRESULT hr;
2727 BOOL thin;
2729 hr = MFStartup(MF_VERSION, MFSTARTUP_FULL);
2730 ok(hr == S_OK, "Failed to start up, hr %#lx.\n", hr);
2732 hr = MFCreatePresentationClock(&clock);
2733 ok(hr == S_OK, "Failed to create presentation clock, hr %#lx.\n", hr);
2735 check_interface(clock, &IID_IMFTimer, TRUE);
2736 check_interface(clock, &IID_IMFRateControl, TRUE);
2737 check_interface(clock, &IID_IMFPresentationClock, TRUE);
2738 check_interface(clock, &IID_IMFShutdown, TRUE);
2739 check_interface(clock, &IID_IMFClock, TRUE);
2741 hr = IMFPresentationClock_QueryInterface(clock, &IID_IMFRateControl, (void **)&rate_control);
2742 ok(hr == S_OK, "Failed to get rate control interface, hr %#lx.\n", hr);
2744 hr = IMFPresentationClock_GetTimeSource(clock, &time_source);
2745 ok(hr == MF_E_CLOCK_NO_TIME_SOURCE, "Unexpected hr %#lx.\n", hr);
2747 hr = IMFPresentationClock_GetTimeSource(clock, NULL);
2748 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
2750 hr = IMFPresentationClock_GetClockCharacteristics(clock, &value);
2751 ok(hr == MF_E_CLOCK_NO_TIME_SOURCE, "Unexpected hr %#lx.\n", hr);
2753 hr = IMFPresentationClock_GetClockCharacteristics(clock, NULL);
2754 ok(hr == MF_E_CLOCK_NO_TIME_SOURCE, "Unexpected hr %#lx.\n", hr);
2756 hr = IMFPresentationClock_GetTime(clock, &time);
2757 ok(hr == MF_E_CLOCK_NO_TIME_SOURCE, "Unexpected hr %#lx.\n", hr);
2759 hr = IMFPresentationClock_GetTime(clock, NULL);
2760 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
2762 value = 1;
2763 hr = IMFPresentationClock_GetContinuityKey(clock, &value);
2764 ok(hr == S_OK, "Failed to get continuity key, hr %#lx.\n", hr);
2765 ok(value == 0, "Unexpected value %lu.\n", value);
2767 hr = IMFPresentationClock_GetProperties(clock, &props);
2768 ok(hr == MF_E_CLOCK_NO_TIME_SOURCE, "Unexpected hr %#lx.\n", hr);
2770 hr = IMFPresentationClock_GetState(clock, 0, &state);
2771 ok(hr == S_OK, "Failed to get state, hr %#lx.\n", hr);
2772 ok(state == MFCLOCK_STATE_INVALID, "Unexpected state %d.\n", state);
2774 hr = IMFPresentationClock_GetCorrelatedTime(clock, 0, &clock_time, &systime);
2775 ok(hr == MF_E_CLOCK_NO_TIME_SOURCE, "Unexpected hr %#lx.\n", hr);
2777 hr = IMFPresentationClock_GetCorrelatedTime(clock, 0, NULL, &systime);
2778 ok(hr == MF_E_CLOCK_NO_TIME_SOURCE, "Unexpected hr %#lx.\n", hr);
2780 hr = IMFPresentationClock_GetCorrelatedTime(clock, 0, &time, NULL);
2781 ok(hr == MF_E_CLOCK_NO_TIME_SOURCE, "Unexpected hr %#lx.\n", hr);
2783 /* Sinks. */
2784 hr = IMFPresentationClock_AddClockStateSink(clock, NULL);
2785 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
2787 hr = IMFPresentationClock_AddClockStateSink(clock, &test_sink);
2788 ok(hr == S_OK, "Failed to add a sink, hr %#lx.\n", hr);
2790 hr = IMFPresentationClock_AddClockStateSink(clock, &test_sink);
2791 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
2793 hr = IMFPresentationClock_RemoveClockStateSink(clock, NULL);
2794 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
2796 hr = IMFPresentationClock_RemoveClockStateSink(clock, &test_sink);
2797 ok(hr == S_OK, "Failed to remove sink, hr %#lx.\n", hr);
2799 hr = IMFPresentationClock_RemoveClockStateSink(clock, &test_sink);
2800 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2802 /* State change commands, time source is not set yet. */
2803 hr = IMFPresentationClock_Start(clock, 0);
2804 ok(hr == MF_E_CLOCK_NO_TIME_SOURCE, "Unexpected hr %#lx.\n", hr);
2806 hr = IMFPresentationClock_Pause(clock);
2807 ok(hr == MF_E_CLOCK_NO_TIME_SOURCE, "Unexpected hr %#lx.\n", hr);
2809 hr = IMFPresentationClock_Stop(clock);
2810 ok(hr == MF_E_CLOCK_NO_TIME_SOURCE, "Unexpected hr %#lx.\n", hr);
2812 hr = IMFRateControl_SetRate(rate_control, FALSE, 0.0f);
2813 ok(hr == MF_E_CLOCK_NO_TIME_SOURCE, "Unexpected hr %#lx.\n", hr);
2815 /* Set default time source. */
2816 hr = MFCreateSystemTimeSource(&time_source);
2817 ok(hr == S_OK, "Failed to create time source, hr %#lx.\n", hr);
2819 hr = IMFPresentationTimeSource_GetClockCharacteristics(time_source, &value);
2820 ok(hr == S_OK, "Failed to get time source flags, hr %#lx.\n", hr);
2821 ok(value == (MFCLOCK_CHARACTERISTICS_FLAG_FREQUENCY_10MHZ | MFCLOCK_CHARACTERISTICS_FLAG_IS_SYSTEM_CLOCK),
2822 "Unexpected clock flags %#lx.\n", value);
2824 hr = IMFPresentationClock_SetTimeSource(clock, time_source);
2825 ok(hr == S_OK, "Failed to set time source, hr %#lx.\n", hr);
2827 hr = IMFPresentationTimeSource_GetProperties(time_source, &props2);
2828 ok(hr == S_OK, "Failed to get time source properties, hr %#lx.\n", hr);
2830 hr = IMFPresentationClock_GetClockCharacteristics(clock, &value);
2831 ok(hr == S_OK, "Failed to get clock flags, hr %#lx.\n", hr);
2832 ok(value == (MFCLOCK_CHARACTERISTICS_FLAG_FREQUENCY_10MHZ | MFCLOCK_CHARACTERISTICS_FLAG_IS_SYSTEM_CLOCK),
2833 "Unexpected clock flags %#lx.\n", value);
2835 hr = IMFPresentationClock_GetProperties(clock, &props);
2836 ok(hr == S_OK, "Failed to get clock properties, hr %#lx.\n", hr);
2837 ok(!memcmp(&props, &props2, sizeof(props)), "Unexpected clock properties.\n");
2839 /* Changing rate at initial state. */
2840 hr = IMFPresentationClock_GetState(clock, 0, &state);
2841 ok(hr == S_OK, "Failed to get clock state, hr %#lx.\n", hr);
2842 ok(state == MFCLOCK_STATE_INVALID, "Unexpected state %d.\n", state);
2844 hr = IMFRateControl_SetRate(rate_control, FALSE, 0.0f);
2845 ok(hr == S_OK, "Failed to set clock rate, hr %#lx.\n", hr);
2846 hr = IMFRateControl_GetRate(rate_control, &thin, &rate);
2847 ok(hr == S_OK, "Failed to get clock rate, hr %#lx.\n", hr);
2848 ok(rate == 0.0f, "Unexpected rate.\n");
2849 hr = IMFRateControl_SetRate(rate_control, FALSE, 1.0f);
2850 ok(hr == S_OK, "Failed to set clock rate, hr %#lx.\n", hr);
2852 /* State changes. */
2853 for (i = 0; i < ARRAY_SIZE(clock_state_change); ++i)
2855 switch (clock_state_change[i].action)
2857 case CLOCK_STOP:
2858 hr = IMFPresentationClock_Stop(clock);
2859 break;
2860 case CLOCK_PAUSE:
2861 hr = IMFPresentationClock_Pause(clock);
2862 break;
2863 case CLOCK_START:
2864 hr = IMFPresentationClock_Start(clock, 0);
2865 break;
2866 default:
2869 ok(hr == clock_state_change[i].hr, "%u: unexpected hr %#lx.\n", i, hr);
2871 hr = IMFPresentationTimeSource_GetState(time_source, 0, &state);
2872 ok(hr == S_OK, "%u: failed to get state, hr %#lx.\n", i, hr);
2873 ok(state == clock_state_change[i].source_state, "%u: unexpected state %d.\n", i, state);
2875 hr = IMFPresentationClock_GetState(clock, 0, &state);
2876 ok(hr == S_OK, "%u: failed to get state, hr %#lx.\n", i, hr);
2877 ok(state == clock_state_change[i].clock_state, "%u: unexpected state %d.\n", i, state);
2880 /* Clock time stamps. */
2881 hr = IMFPresentationClock_Start(clock, 10);
2882 ok(hr == S_OK, "Failed to start presentation clock, hr %#lx.\n", hr);
2884 hr = IMFPresentationClock_Pause(clock);
2885 ok(hr == S_OK, "Failed to pause presentation clock, hr %#lx.\n", hr);
2887 hr = IMFPresentationClock_GetTime(clock, &time);
2888 ok(hr == S_OK, "Failed to get clock time, hr %#lx.\n", hr);
2890 hr = IMFPresentationTimeSource_GetCorrelatedTime(time_source, 0, &clock_time, &systime);
2891 ok(hr == S_OK, "Failed to get time source time, hr %#lx.\n", hr);
2892 ok(time == clock_time, "Unexpected clock time.\n");
2894 hr = IMFPresentationClock_GetCorrelatedTime(clock, 0, &time, &systime);
2895 ok(hr == S_OK, "Failed to get clock time, hr %#lx.\n", hr);
2896 ok(time == clock_time, "Unexpected clock time.\n");
2898 IMFPresentationTimeSource_Release(time_source);
2900 hr = IMFRateControl_GetRate(rate_control, NULL, &rate);
2901 ok(hr == S_OK, "Failed to get clock rate, hr %#lx.\n", hr);
2903 hr = IMFRateControl_GetRate(rate_control, &thin, NULL);
2904 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
2906 hr = IMFRateControl_GetRate(rate_control, &thin, &rate);
2907 ok(hr == S_OK, "Failed to get clock rate, hr %#lx.\n", hr);
2908 ok(rate == 1.0f, "Unexpected rate.\n");
2909 ok(!thin, "Unexpected thinning.\n");
2911 hr = IMFPresentationClock_GetState(clock, 0, &state);
2912 ok(hr == S_OK, "Failed to get clock state, hr %#lx.\n", hr);
2913 ok(state == MFCLOCK_STATE_PAUSED, "Unexpected state %d.\n", state);
2915 hr = IMFPresentationClock_Start(clock, 0);
2916 ok(hr == S_OK, "Failed to stop, hr %#lx.\n", hr);
2918 hr = IMFRateControl_SetRate(rate_control, FALSE, 0.0f);
2919 ok(hr == S_OK, "Failed to set clock rate, hr %#lx.\n", hr);
2920 hr = IMFRateControl_GetRate(rate_control, &thin, &rate);
2921 ok(hr == S_OK, "Failed to get clock rate, hr %#lx.\n", hr);
2922 ok(rate == 0.0f, "Unexpected rate.\n");
2923 hr = IMFRateControl_SetRate(rate_control, FALSE, 1.0f);
2924 ok(hr == S_OK, "Failed to set clock rate, hr %#lx.\n", hr);
2925 hr = IMFRateControl_SetRate(rate_control, FALSE, 0.0f);
2926 ok(hr == S_OK, "Failed to set clock rate, hr %#lx.\n", hr);
2927 hr = IMFRateControl_SetRate(rate_control, FALSE, 0.5f);
2928 ok(hr == S_OK, "Failed to set clock rate, hr %#lx.\n", hr);
2929 hr = IMFRateControl_SetRate(rate_control, TRUE, -1.0f);
2930 ok(hr == MF_E_THINNING_UNSUPPORTED, "Unexpected hr %#lx.\n", hr);
2931 hr = IMFRateControl_SetRate(rate_control, TRUE, 0.0f);
2932 ok(hr == MF_E_THINNING_UNSUPPORTED, "Unexpected hr %#lx.\n", hr);
2933 hr = IMFRateControl_SetRate(rate_control, TRUE, 1.0f);
2934 ok(hr == MF_E_THINNING_UNSUPPORTED, "Unexpected hr %#lx.\n", hr);
2936 hr = IMFPresentationClock_GetState(clock, 0, &state);
2937 ok(hr == S_OK, "Failed to get clock state, hr %#lx.\n", hr);
2938 ok(state == MFCLOCK_STATE_RUNNING, "Unexpected state %d.\n", state);
2940 hr = IMFRateControl_GetRate(rate_control, &thin, &rate);
2941 ok(hr == S_OK, "Failed to get clock rate, hr %#lx.\n", hr);
2942 ok(rate == 0.5f, "Unexpected rate.\n");
2943 ok(!thin, "Unexpected thinning.\n");
2945 IMFRateControl_Release(rate_control);
2947 hr = IMFPresentationClock_QueryInterface(clock, &IID_IMFShutdown, (void **)&shutdown);
2948 ok(hr == S_OK, "Failed to get shutdown interface, hr %#lx.\n", hr);
2950 /* Shutdown behavior. */
2951 hr = IMFShutdown_GetShutdownStatus(shutdown, NULL);
2952 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
2954 hr = IMFShutdown_GetShutdownStatus(shutdown, &status);
2955 ok(hr == MF_E_INVALIDREQUEST, "Unexpected hr %#lx.\n", hr);
2957 hr = IMFShutdown_Shutdown(shutdown);
2958 ok(hr == S_OK, "Failed to shut down, hr %#lx.\n", hr);
2960 time_source = NULL;
2961 hr = IMFPresentationClock_GetTimeSource(clock, &time_source);
2962 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2963 ok(!!time_source, "Unexpected instance %p.\n", time_source);
2964 IMFPresentationTimeSource_Release(time_source);
2966 hr = IMFPresentationClock_GetTime(clock, &time);
2967 ok(hr == S_OK, "Failed to get time, hr %#lx.\n", hr);
2969 hr = IMFShutdown_GetShutdownStatus(shutdown, &status);
2970 ok(hr == S_OK, "Failed to get status, hr %#lx.\n", hr);
2971 ok(status == MFSHUTDOWN_COMPLETED, "Unexpected status.\n");
2973 hr = IMFPresentationClock_Start(clock, 0);
2974 ok(hr == S_OK, "Failed to start the clock, hr %#lx.\n", hr);
2976 hr = IMFShutdown_GetShutdownStatus(shutdown, &status);
2977 ok(hr == S_OK, "Failed to get status, hr %#lx.\n", hr);
2978 ok(status == MFSHUTDOWN_COMPLETED, "Unexpected status.\n");
2980 hr = IMFShutdown_Shutdown(shutdown);
2981 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2983 IMFShutdown_Release(shutdown);
2985 IMFPresentationClock_Release(clock);
2987 hr = MFShutdown();
2988 ok(hr == S_OK, "Failed to shut down, hr %#lx.\n", hr);
2991 static HRESULT WINAPI grabber_callback_QueryInterface(IMFSampleGrabberSinkCallback *iface, REFIID riid, void **obj)
2993 if (IsEqualIID(riid, &IID_IMFSampleGrabberSinkCallback) ||
2994 IsEqualIID(riid, &IID_IMFClockStateSink) ||
2995 IsEqualIID(riid, &IID_IUnknown))
2997 *obj = iface;
2998 IMFSampleGrabberSinkCallback_AddRef(iface);
2999 return S_OK;
3002 *obj = NULL;
3003 return E_NOINTERFACE;
3006 static ULONG WINAPI grabber_callback_AddRef(IMFSampleGrabberSinkCallback *iface)
3008 return 2;
3011 static ULONG WINAPI grabber_callback_Release(IMFSampleGrabberSinkCallback *iface)
3013 return 1;
3016 static HRESULT WINAPI grabber_callback_OnClockStart(IMFSampleGrabberSinkCallback *iface, MFTIME time, LONGLONG offset)
3018 return E_NOTIMPL;
3021 static HRESULT WINAPI grabber_callback_OnClockStop(IMFSampleGrabberSinkCallback *iface, MFTIME time)
3023 return E_NOTIMPL;
3026 static HRESULT WINAPI grabber_callback_OnClockPause(IMFSampleGrabberSinkCallback *iface, MFTIME time)
3028 return E_NOTIMPL;
3031 static HRESULT WINAPI grabber_callback_OnClockRestart(IMFSampleGrabberSinkCallback *iface, MFTIME time)
3033 return E_NOTIMPL;
3036 static HRESULT WINAPI grabber_callback_OnClockSetRate(IMFSampleGrabberSinkCallback *iface, MFTIME time, float rate)
3038 return E_NOTIMPL;
3041 static HRESULT WINAPI grabber_callback_OnSetPresentationClock(IMFSampleGrabberSinkCallback *iface,
3042 IMFPresentationClock *clock)
3044 return S_OK;
3047 static HRESULT WINAPI grabber_callback_OnProcessSample(IMFSampleGrabberSinkCallback *iface, REFGUID major_type,
3048 DWORD sample_flags, LONGLONG sample_time, LONGLONG sample_duration, const BYTE *buffer, DWORD sample_size)
3050 return E_NOTIMPL;
3053 static HRESULT WINAPI grabber_callback_OnShutdown(IMFSampleGrabberSinkCallback *iface)
3055 return S_OK;
3058 static const IMFSampleGrabberSinkCallbackVtbl grabber_callback_vtbl =
3060 grabber_callback_QueryInterface,
3061 grabber_callback_AddRef,
3062 grabber_callback_Release,
3063 grabber_callback_OnClockStart,
3064 grabber_callback_OnClockStop,
3065 grabber_callback_OnClockPause,
3066 grabber_callback_OnClockRestart,
3067 grabber_callback_OnClockSetRate,
3068 grabber_callback_OnSetPresentationClock,
3069 grabber_callback_OnProcessSample,
3070 grabber_callback_OnShutdown,
3073 static IMFSampleGrabberSinkCallback grabber_callback = { &grabber_callback_vtbl };
3075 static void test_sample_grabber(void)
3077 IMFMediaType *media_type, *media_type2, *media_type3;
3078 IMFMediaTypeHandler *handler, *handler2;
3079 IMFPresentationTimeSource *time_source;
3080 IMFPresentationClock *clock, *clock2;
3081 IMFStreamSink *stream, *stream2;
3082 IMFRateSupport *rate_support;
3083 IMFMediaEventGenerator *eg;
3084 IMFMediaSink *sink, *sink2;
3085 DWORD flags, count, id;
3086 IMFActivate *activate;
3087 IMFMediaEvent *event;
3088 UINT32 attr_count;
3089 float rate;
3090 HRESULT hr;
3091 GUID guid;
3092 LONG ref;
3094 hr = MFStartup(MF_VERSION, MFSTARTUP_FULL);
3095 ok(hr == S_OK, "Failed to start up, hr %#lx.\n", hr);
3097 hr = MFCreateMediaType(&media_type);
3098 ok(hr == S_OK, "Failed to create media type, hr %#lx.\n", hr);
3100 hr = MFCreateSampleGrabberSinkActivate(NULL, NULL, &activate);
3101 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
3103 hr = MFCreateSampleGrabberSinkActivate(NULL, &grabber_callback, &activate);
3104 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
3106 hr = IMFMediaType_SetGUID(media_type, &MF_MT_MAJOR_TYPE, &MFMediaType_Audio);
3107 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
3108 hr = IMFMediaType_SetGUID(media_type, &MF_MT_SUBTYPE, &MFAudioFormat_PCM);
3109 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
3111 EXPECT_REF(media_type, 1);
3112 hr = MFCreateSampleGrabberSinkActivate(media_type, &grabber_callback, &activate);
3113 ok(hr == S_OK, "Failed to create grabber activate, hr %#lx.\n", hr);
3114 EXPECT_REF(media_type, 2);
3116 hr = IMFActivate_GetCount(activate, &attr_count);
3117 ok(hr == S_OK, "Failed to get attribute count, hr %#lx.\n", hr);
3118 ok(!attr_count, "Unexpected count %u.\n", attr_count);
3120 hr = IMFActivate_ActivateObject(activate, &IID_IMFMediaSink, (void **)&sink);
3121 ok(hr == S_OK, "Failed to activate object, hr %#lx.\n", hr);
3123 check_interface(sink, &IID_IMFClockStateSink, TRUE);
3124 check_interface(sink, &IID_IMFMediaEventGenerator, TRUE);
3125 check_interface(sink, &IID_IMFGetService, TRUE);
3126 check_interface(sink, &IID_IMFRateSupport, TRUE);
3127 check_service_interface(sink, &MF_RATE_CONTROL_SERVICE, &IID_IMFRateSupport, TRUE);
3129 if (SUCCEEDED(MFGetService((IUnknown *)sink, &MF_RATE_CONTROL_SERVICE, &IID_IMFRateSupport, (void **)&rate_support)))
3131 hr = IMFRateSupport_GetFastestRate(rate_support, MFRATE_FORWARD, FALSE, &rate);
3132 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3133 ok(rate == FLT_MAX, "Unexpected rate %f.\n", rate);
3135 hr = IMFRateSupport_GetFastestRate(rate_support, MFRATE_FORWARD, TRUE, &rate);
3136 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3137 ok(rate == FLT_MAX, "Unexpected rate %f.\n", rate);
3139 hr = IMFRateSupport_GetFastestRate(rate_support, MFRATE_REVERSE, FALSE, &rate);
3140 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3141 ok(rate == -FLT_MAX, "Unexpected rate %f.\n", rate);
3143 hr = IMFRateSupport_GetFastestRate(rate_support, MFRATE_REVERSE, TRUE, &rate);
3144 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3145 ok(rate == -FLT_MAX, "Unexpected rate %f.\n", rate);
3147 hr = IMFRateSupport_GetSlowestRate(rate_support, MFRATE_FORWARD, FALSE, &rate);
3148 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3149 ok(rate == 0.0f, "Unexpected rate %f.\n", rate);
3151 hr = IMFRateSupport_GetSlowestRate(rate_support, MFRATE_FORWARD, TRUE, &rate);
3152 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3153 ok(rate == 0.0f, "Unexpected rate %f.\n", rate);
3155 hr = IMFRateSupport_GetSlowestRate(rate_support, MFRATE_REVERSE, FALSE, &rate);
3156 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3157 ok(rate == 0.0f, "Unexpected rate %f.\n", rate);
3159 hr = IMFRateSupport_GetSlowestRate(rate_support, MFRATE_REVERSE, TRUE, &rate);
3160 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3161 ok(rate == 0.0f, "Unexpected rate %f.\n", rate);
3163 hr = IMFRateSupport_IsRateSupported(rate_support, TRUE, 1.0f, &rate);
3164 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3165 ok(rate == 1.0f, "Unexpected rate %f.\n", rate);
3167 IMFRateSupport_Release(rate_support);
3170 hr = IMFMediaSink_GetCharacteristics(sink, &flags);
3171 ok(hr == S_OK, "Failed to get sink flags, hr %#lx.\n", hr);
3172 ok(flags & MEDIASINK_FIXED_STREAMS, "Unexpected flags %#lx.\n", flags);
3174 hr = IMFMediaSink_GetStreamSinkCount(sink, &count);
3175 ok(hr == S_OK, "Failed to get stream count, hr %#lx.\n", hr);
3176 ok(count == 1, "Unexpected stream count %lu.\n", count);
3178 hr = IMFMediaSink_GetStreamSinkByIndex(sink, 0, &stream);
3179 ok(hr == S_OK, "Failed to get sink stream, hr %#lx.\n", hr);
3181 check_interface(stream, &IID_IMFMediaEventGenerator, TRUE);
3182 check_interface(stream, &IID_IMFMediaTypeHandler, TRUE);
3184 hr = IMFStreamSink_GetIdentifier(stream, &id);
3185 ok(hr == S_OK, "Failed to get stream id, hr %#lx.\n", hr);
3186 ok(id == 0, "Unexpected id %#lx.\n", id);
3188 hr = IMFStreamSink_GetMediaSink(stream, &sink2);
3189 ok(hr == S_OK, "Failed to get media sink, hr %lx.\n", hr);
3190 ok(sink2 == sink, "Unexpected sink.\n");
3191 IMFMediaSink_Release(sink2);
3193 hr = IMFMediaSink_GetStreamSinkByIndex(sink, 1, &stream2);
3194 ok(hr == MF_E_INVALIDINDEX, "Unexpected hr %#lx.\n", hr);
3196 hr = IMFMediaSink_GetStreamSinkById(sink, 1, &stream2);
3197 ok(hr == MF_E_INVALIDSTREAMNUMBER, "Unexpected hr %#lx.\n", hr);
3199 hr = IMFMediaSink_AddStreamSink(sink, 1, NULL, &stream2);
3200 ok(hr == MF_E_STREAMSINKS_FIXED, "Unexpected hr %#lx.\n", hr);
3202 hr = IMFMediaSink_RemoveStreamSink(sink, 0);
3203 ok(hr == MF_E_STREAMSINKS_FIXED, "Unexpected hr %#lx.\n", hr);
3205 hr = IMFMediaSink_RemoveStreamSink(sink, 1);
3206 ok(hr == MF_E_STREAMSINKS_FIXED, "Unexpected hr %#lx.\n", hr);
3208 check_interface(sink, &IID_IMFClockStateSink, TRUE);
3210 /* Event generator. */
3211 hr = IMFMediaSink_QueryInterface(sink, &IID_IMFMediaEventGenerator, (void **)&eg);
3212 ok(hr == S_OK, "Failed to get interface, hr %#lx.\n", hr);
3214 hr = IMFMediaEventGenerator_GetEvent(eg, MF_EVENT_FLAG_NO_WAIT, &event);
3215 ok(hr == MF_E_NO_EVENTS_AVAILABLE, "Unexpected hr %#lx.\n", hr);
3217 check_interface(sink, &IID_IMFPresentationTimeSource, FALSE);
3219 hr = IMFStreamSink_QueryInterface(stream, &IID_IMFMediaTypeHandler, (void **)&handler2);
3220 ok(hr == S_OK, "Failed to get handler interface, hr %#lx.\n", hr);
3222 hr = IMFStreamSink_GetMediaTypeHandler(stream, &handler);
3223 ok(hr == S_OK, "Failed to get type handler, hr %#lx.\n", hr);
3224 hr = IMFMediaTypeHandler_GetMediaTypeCount(handler, &count);
3225 ok(hr == S_OK, "Failed to get media type count, hr %#lx.\n", hr);
3226 ok(count == 0, "Unexpected count %lu.\n", count);
3227 ok(handler == handler2, "Unexpected handler.\n");
3229 IMFMediaTypeHandler_Release(handler);
3230 IMFMediaTypeHandler_Release(handler2);
3232 /* Set clock. */
3233 hr = MFCreatePresentationClock(&clock);
3234 ok(hr == S_OK, "Failed to create clock object, hr %#lx.\n", hr);
3236 hr = IMFMediaSink_GetPresentationClock(sink, NULL);
3237 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
3239 hr = IMFMediaSink_GetPresentationClock(sink, &clock2);
3240 ok(hr == MF_E_NO_CLOCK, "Unexpected hr %#lx.\n", hr);
3242 hr = IMFMediaSink_SetPresentationClock(sink, NULL);
3243 ok(hr == S_OK, "Failed to set presentation clock, hr %#lx.\n", hr);
3245 hr = IMFMediaSink_SetPresentationClock(sink, clock);
3246 ok(hr == S_OK, "Failed to set presentation clock, hr %#lx.\n", hr);
3248 hr = MFCreateSystemTimeSource(&time_source);
3249 ok(hr == S_OK, "Failed to create time source, hr %#lx.\n", hr);
3251 hr = IMFPresentationClock_SetTimeSource(clock, time_source);
3252 ok(hr == S_OK, "Failed to set time source, hr %#lx.\n", hr);
3253 IMFPresentationTimeSource_Release(time_source);
3255 hr = IMFMediaSink_GetCharacteristics(sink, &flags);
3256 ok(hr == S_OK, "Failed to get sink flags, hr %#lx.\n", hr);
3258 hr = IMFActivate_ShutdownObject(activate);
3259 ok(hr == S_OK, "Failed to shut down, hr %#lx.\n", hr);
3261 hr = IMFMediaSink_GetCharacteristics(sink, &flags);
3262 ok(hr == S_OK, "Failed to get sink flags, hr %#lx.\n", hr);
3264 hr = IMFStreamSink_GetMediaTypeHandler(stream, &handler);
3265 ok(hr == S_OK, "Failed to get type handler, hr %#lx.\n", hr);
3267 /* On Win8+ this initialization happens automatically. */
3268 hr = IMFMediaTypeHandler_SetCurrentMediaType(handler, media_type);
3269 ok(hr == S_OK, "Failed to set media type, hr %#lx.\n", hr);
3271 hr = IMFMediaTypeHandler_GetMediaTypeCount(handler, NULL);
3272 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
3274 hr = IMFMediaTypeHandler_GetMediaTypeCount(handler, &count);
3275 ok(hr == S_OK, "Failed to get media type count, hr %#lx.\n", hr);
3276 ok(count == 0, "Unexpected count %lu.\n", count);
3278 hr = IMFMediaTypeHandler_GetMajorType(handler, &guid);
3279 ok(hr == S_OK, "Failed to get major type, hr %#lx.\n", hr);
3280 ok(IsEqualGUID(&guid, &MFMediaType_Audio), "Unexpected major type %s.\n", wine_dbgstr_guid(&guid));
3282 hr = IMFMediaTypeHandler_GetCurrentMediaType(handler, &media_type2);
3283 ok(hr == S_OK, "Failed to get current type, hr %#lx.\n", hr);
3284 ok(media_type2 == media_type, "Unexpected media type.\n");
3285 IMFMediaType_Release(media_type2);
3287 hr = MFCreateMediaType(&media_type2);
3288 ok(hr == S_OK, "Failed to create media type, hr %#lx.\n", hr);
3290 hr = IMFMediaTypeHandler_SetCurrentMediaType(handler, media_type2);
3291 ok(hr == MF_E_INVALIDMEDIATYPE, "Unexpected hr %#lx.\n", hr);
3293 hr = IMFMediaType_SetGUID(media_type2, &MF_MT_MAJOR_TYPE, &MFMediaType_Audio);
3294 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
3296 hr = IMFMediaTypeHandler_SetCurrentMediaType(handler, media_type2);
3297 ok(hr == MF_E_INVALIDMEDIATYPE, "Unexpected hr %#lx.\n", hr);
3299 hr = IMFMediaType_SetGUID(media_type2, &MF_MT_SUBTYPE, &MFAudioFormat_Float);
3300 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
3302 hr = IMFMediaTypeHandler_SetCurrentMediaType(handler, media_type2);
3303 ok(hr == MF_E_INVALIDMEDIATYPE, "Unexpected hr %#lx.\n", hr);
3305 hr = IMFMediaType_SetGUID(media_type2, &MF_MT_SUBTYPE, &MFAudioFormat_PCM);
3306 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
3308 hr = IMFMediaType_SetUINT32(media_type2, &MF_MT_AUDIO_SAMPLES_PER_SECOND, 44100);
3309 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
3311 hr = IMFMediaTypeHandler_SetCurrentMediaType(handler, media_type2);
3312 ok(hr == S_OK, "Failed to get current type, hr %#lx.\n", hr);
3313 IMFMediaType_Release(media_type);
3315 hr = IMFMediaTypeHandler_SetCurrentMediaType(handler, NULL);
3316 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
3318 hr = IMFMediaTypeHandler_GetCurrentMediaType(handler, &media_type);
3319 ok(hr == S_OK, "Failed to get current type, hr %#lx.\n", hr);
3320 ok(media_type2 == media_type, "Unexpected media type.\n");
3321 IMFMediaType_Release(media_type);
3323 hr = IMFMediaTypeHandler_GetMediaTypeByIndex(handler, 0, &media_type);
3324 ok(hr == MF_E_NO_MORE_TYPES, "Unexpected hr %#lx.\n", hr);
3326 hr = IMFMediaTypeHandler_GetMediaTypeByIndex(handler, 0, NULL);
3327 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
3329 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, media_type2, NULL);
3330 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3332 hr = MFCreateMediaType(&media_type);
3333 ok(hr == S_OK, "Failed to create media type, hr %#lx.\n", hr);
3335 hr = IMFMediaType_SetGUID(media_type, &MF_MT_MAJOR_TYPE, &MFMediaType_Audio);
3336 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
3338 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, media_type, NULL);
3339 ok(hr == MF_E_INVALIDMEDIATYPE, "Unexpected hr %#lx.\n", hr);
3341 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, media_type, &media_type3);
3342 ok(hr == MF_E_INVALIDMEDIATYPE, "Unexpected hr %#lx.\n", hr);
3344 hr = IMFMediaType_SetGUID(media_type, &MF_MT_SUBTYPE, &MFAudioFormat_PCM);
3345 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
3347 media_type3 = (void *)0xdeadbeef;
3348 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, media_type, &media_type3);
3349 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3350 ok(media_type3 == (void *)0xdeadbeef, "Unexpected media type %p.\n", media_type3);
3352 hr = IMFMediaType_SetUINT32(media_type, &MF_MT_FIXED_SIZE_SAMPLES, 1);
3353 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
3355 hr = IMFMediaType_SetUINT32(media_type, &MF_MT_SAMPLE_SIZE, 1024);
3356 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
3358 media_type3 = (void *)0xdeadbeef;
3359 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, media_type, &media_type3);
3360 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3361 ok(media_type3 == (void *)0xdeadbeef, "Unexpected media type %p.\n", media_type3);
3363 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, NULL, NULL);
3364 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
3366 hr = IMFMediaEventGenerator_GetEvent(eg, MF_EVENT_FLAG_NO_WAIT, &event);
3367 ok(hr == MF_E_NO_EVENTS_AVAILABLE, "Unexpected hr %#lx.\n", hr);
3369 hr = IMFStreamSink_GetEvent(stream, MF_EVENT_FLAG_NO_WAIT, &event);
3370 ok(hr == MF_E_NO_EVENTS_AVAILABLE, "Unexpected hr %#lx.\n", hr);
3372 EXPECT_REF(clock, 3);
3373 hr = IMFMediaSink_Shutdown(sink);
3374 ok(hr == S_OK, "Failed to shut down, hr %#lx.\n", hr);
3376 ref = IMFPresentationClock_Release(clock);
3377 ok(ref == 0, "Release returned %ld\n", ref);
3379 hr = IMFMediaEventGenerator_GetEvent(eg, MF_EVENT_FLAG_NO_WAIT, &event);
3380 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
3382 hr = IMFMediaSink_Shutdown(sink);
3383 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
3385 hr = IMFMediaSink_GetCharacteristics(sink, &flags);
3386 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
3388 hr = IMFMediaSink_AddStreamSink(sink, 1, NULL, &stream2);
3389 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
3391 hr = IMFMediaSink_GetStreamSinkCount(sink, &count);
3392 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
3394 hr = IMFMediaSink_GetStreamSinkByIndex(sink, 0, &stream2);
3395 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
3397 hr = IMFStreamSink_GetEvent(stream, MF_EVENT_FLAG_NO_WAIT, &event);
3398 ok(hr == MF_E_STREAMSINK_REMOVED, "Unexpected hr %#lx.\n", hr);
3400 hr = IMFStreamSink_GetMediaSink(stream, &sink2);
3401 ok(hr == MF_E_STREAMSINK_REMOVED, "Unexpected hr %#lx.\n", hr);
3403 id = 1;
3404 hr = IMFStreamSink_GetIdentifier(stream, &id);
3405 ok(hr == MF_E_STREAMSINK_REMOVED, "Unexpected hr %#lx.\n", hr);
3406 ok(id == 1, "Unexpected id %lu.\n", id);
3408 media_type3 = (void *)0xdeadbeef;
3409 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, media_type, &media_type3);
3410 ok(hr == MF_E_STREAMSINK_REMOVED, "Unexpected hr %#lx.\n", hr);
3411 ok(media_type3 == (void *)0xdeadbeef, "Unexpected media type %p.\n", media_type3);
3413 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, NULL, NULL);
3414 ok(hr == MF_E_STREAMSINK_REMOVED, "Unexpected hr %#lx.\n", hr);
3416 hr = IMFMediaTypeHandler_SetCurrentMediaType(handler, NULL);
3417 ok(hr == MF_E_STREAMSINK_REMOVED, "Unexpected hr %#lx.\n", hr);
3419 hr = IMFMediaTypeHandler_GetMediaTypeCount(handler, &count);
3420 ok(hr == S_OK, "Failed to get type count, hr %#lx.\n", hr);
3422 ref = IMFMediaType_Release(media_type2);
3423 todo_wine
3424 ok(ref == 0, "Release returned %ld\n", ref);
3425 ref = IMFMediaType_Release(media_type);
3426 ok(ref == 0, "Release returned %ld\n", ref);
3428 hr = IMFMediaTypeHandler_GetMediaTypeByIndex(handler, 0, &media_type);
3429 ok(hr == MF_E_NO_MORE_TYPES, "Unexpected hr %#lx.\n", hr);
3431 hr = IMFMediaTypeHandler_GetCurrentMediaType(handler, &media_type);
3432 ok(hr == MF_E_STREAMSINK_REMOVED, "Unexpected hr %#lx.\n", hr);
3434 hr = IMFMediaTypeHandler_GetCurrentMediaType(handler, NULL);
3435 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
3437 hr = IMFMediaTypeHandler_GetMajorType(handler, NULL);
3438 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
3440 hr = IMFMediaTypeHandler_GetMajorType(handler, &guid);
3441 ok(hr == MF_E_STREAMSINK_REMOVED, "Unexpected hr %#lx.\n", hr);
3443 IMFMediaTypeHandler_Release(handler);
3445 handler = (void *)0xdeadbeef;
3446 hr = IMFStreamSink_GetMediaTypeHandler(stream, &handler);
3447 ok(hr == MF_E_STREAMSINK_REMOVED, "Unexpected hr %#lx.\n", hr);
3448 ok(handler == (void *)0xdeadbeef, "Unexpected pointer.\n");
3450 hr = IMFStreamSink_GetMediaTypeHandler(stream, NULL);
3451 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
3453 IMFMediaEventGenerator_Release(eg);
3454 IMFStreamSink_Release(stream);
3456 ref = IMFActivate_Release(activate);
3457 ok(ref == 0, "Release returned %ld\n", ref);
3458 ref = IMFMediaSink_Release(sink);
3459 ok(ref == 0, "Release returned %ld\n", ref);
3461 /* Rateless mode with MF_SAMPLEGRABBERSINK_IGNORE_CLOCK. */
3462 hr = MFCreateMediaType(&media_type);
3463 ok(hr == S_OK, "Failed to create media type, hr %#lx.\n", hr);
3465 hr = IMFMediaType_SetGUID(media_type, &MF_MT_MAJOR_TYPE, &MFMediaType_Audio);
3466 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
3467 hr = IMFMediaType_SetGUID(media_type, &MF_MT_SUBTYPE, &MFAudioFormat_PCM);
3468 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
3470 hr = MFCreateSampleGrabberSinkActivate(media_type, &grabber_callback, &activate);
3471 ok(hr == S_OK, "Failed to create grabber activate, hr %#lx.\n", hr);
3473 hr = IMFActivate_SetUINT32(activate, &MF_SAMPLEGRABBERSINK_IGNORE_CLOCK, 1);
3474 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
3476 hr = IMFActivate_ActivateObject(activate, &IID_IMFMediaSink, (void **)&sink);
3477 ok(hr == S_OK, "Failed to activate object, hr %#lx.\n", hr);
3479 hr = IMFMediaSink_GetCharacteristics(sink, &flags);
3480 ok(hr == S_OK, "Failed to get sink flags, hr %#lx.\n", hr);
3481 ok(flags & MEDIASINK_RATELESS, "Unexpected flags %#lx.\n", flags);
3483 hr = IMFActivate_ShutdownObject(activate);
3484 ok(hr == S_OK, "Failed to shut down, hr %#lx.\n", hr);
3486 /* required for the sink to be fully released */
3487 hr = IMFMediaSink_Shutdown(sink);
3488 ok(hr == S_OK, "Failed to shut down, hr %#lx.\n", hr);
3490 ref = IMFActivate_Release(activate);
3491 ok(ref == 0, "Release returned %ld\n", ref);
3492 ref = IMFMediaSink_Release(sink);
3493 ok(ref == 0, "Release returned %ld\n", ref);
3495 /* Detaching */
3496 hr = MFCreateSampleGrabberSinkActivate(media_type, &grabber_callback, &activate);
3497 ok(hr == S_OK, "Failed to create grabber activate, hr %#lx.\n", hr);
3499 hr = IMFActivate_ActivateObject(activate, &IID_IMFMediaSink, (void **)&sink);
3500 ok(hr == S_OK, "Failed to activate object, hr %#lx.\n", hr);
3502 hr = IMFActivate_ShutdownObject(activate);
3503 ok(hr == S_OK, "Failed to shut down, hr %#lx.\n", hr);
3505 hr = IMFActivate_ActivateObject(activate, &IID_IMFMediaSink, (void **)&sink2);
3506 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
3508 hr = IMFActivate_GetCount(activate, &attr_count);
3509 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3511 hr = IMFActivate_DetachObject(activate);
3512 ok(hr == E_NOTIMPL, "Unexpected hr %#lx.\n", hr);
3514 ref = IMFActivate_Release(activate);
3515 ok(ref == 0, "Release returned %ld\n", ref);
3517 /* required for the sink to be fully released */
3518 hr = IMFMediaSink_Shutdown(sink);
3519 ok(hr == S_OK, "Failed to shut down, hr %#lx.\n", hr);
3521 ref = IMFMediaSink_Release(sink);
3522 ok(ref == 0, "Release returned %ld\n", ref);
3524 ref = IMFMediaType_Release(media_type);
3525 ok(ref == 0, "Release returned %ld\n", ref);
3527 hr = MFShutdown();
3528 ok(hr == S_OK, "Failed to shut down, hr %#lx.\n", hr);
3531 static void test_sample_grabber_is_mediatype_supported(void)
3533 IMFMediaType *media_type, *media_type2, *media_type3;
3534 IMFMediaTypeHandler *handler;
3535 IMFActivate *activate;
3536 IMFStreamSink *stream;
3537 IMFMediaSink *sink;
3538 HRESULT hr;
3539 GUID guid;
3540 LONG ref;
3542 /* IsMediaTypeSupported checks are done against the creation type, and check format data */
3543 hr = MFCreateMediaType(&media_type);
3544 ok(hr == S_OK, "Failed to create media type, hr %#lx.\n", hr);
3546 hr = IMFMediaType_SetGUID(media_type, &MF_MT_MAJOR_TYPE, &MFMediaType_Audio);
3547 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
3548 hr = IMFMediaType_SetGUID(media_type, &MF_MT_SUBTYPE, &MFAudioFormat_PCM);
3549 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
3550 hr = IMFMediaType_SetUINT32(media_type, &MF_MT_AUDIO_SAMPLES_PER_SECOND, 44100);
3551 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
3553 hr = MFCreateSampleGrabberSinkActivate(media_type, &grabber_callback, &activate);
3554 ok(hr == S_OK, "Failed to create grabber activate, hr %#lx.\n", hr);
3556 hr = IMFActivate_ActivateObject(activate, &IID_IMFMediaSink, (void **)&sink);
3557 ok(hr == S_OK, "Failed to activate object, hr %#lx.\n", hr);
3559 hr = IMFMediaSink_GetStreamSinkByIndex(sink, 0, &stream);
3560 ok(hr == S_OK, "Failed to get sink stream, hr %#lx.\n", hr);
3561 hr = IMFStreamSink_GetMediaTypeHandler(stream, &handler);
3562 ok(hr == S_OK, "Failed to get type handler, hr %#lx.\n", hr);
3563 IMFStreamSink_Release(stream);
3565 /* On Win8+ this initialization happens automatically. */
3566 hr = IMFMediaTypeHandler_SetCurrentMediaType(handler, media_type);
3567 ok(hr == S_OK, "Failed to set media type, hr %#lx.\n", hr);
3569 hr = MFCreateMediaType(&media_type2);
3570 ok(hr == S_OK, "Failed to create media type, hr %#lx.\n", hr);
3572 hr = IMFMediaType_SetGUID(media_type2, &MF_MT_MAJOR_TYPE, &MFMediaType_Audio);
3573 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
3574 hr = IMFMediaType_SetGUID(media_type2, &MF_MT_SUBTYPE, &MFAudioFormat_PCM);
3575 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
3576 hr = IMFMediaType_SetUINT32(media_type2, &MF_MT_AUDIO_SAMPLES_PER_SECOND, 48000);
3577 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
3579 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, media_type2, NULL);
3580 ok(hr == MF_E_INVALIDMEDIATYPE, "Unexpected hr %#lx.\n", hr);
3582 hr = IMFMediaTypeHandler_SetCurrentMediaType(handler, media_type2);
3583 ok(hr == MF_E_INVALIDMEDIATYPE, "Failed to set media type, hr %#lx.\n", hr);
3585 /* Make it match grabber type sample rate. */
3586 hr = IMFMediaType_SetUINT32(media_type2, &MF_MT_AUDIO_SAMPLES_PER_SECOND, 44100);
3587 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
3589 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, media_type2, NULL);
3590 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3592 hr = IMFMediaTypeHandler_SetCurrentMediaType(handler, media_type2);
3593 ok(hr == S_OK, "Failed to set media type, hr %#lx.\n", hr);
3594 hr = IMFMediaTypeHandler_GetCurrentMediaType(handler, &media_type3);
3595 ok(hr == S_OK, "Failed to set media type, hr %#lx.\n", hr);
3596 ok(media_type3 == media_type2, "Unexpected media type instance.\n");
3597 IMFMediaType_Release(media_type3);
3599 /* Change original type. */
3600 hr = IMFMediaType_SetUINT32(media_type, &MF_MT_AUDIO_SAMPLES_PER_SECOND, 48000);
3601 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
3603 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, media_type2, NULL);
3604 ok(hr == MF_E_INVALIDMEDIATYPE, "Unexpected hr %#lx.\n", hr);
3606 hr = IMFMediaType_SetUINT32(media_type2, &MF_MT_AUDIO_SAMPLES_PER_SECOND, 48000);
3607 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
3609 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, media_type2, NULL);
3610 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3612 hr = IMFMediaTypeHandler_GetMajorType(handler, &guid);
3613 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3614 ok(IsEqualGUID(&guid, &MFMediaType_Audio), "Unexpected major type.\n");
3616 hr = IMFMediaType_SetGUID(media_type, &MF_MT_MAJOR_TYPE, &MFMediaType_Video);
3617 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3619 hr = IMFMediaTypeHandler_GetMajorType(handler, &guid);
3620 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3621 ok(IsEqualGUID(&guid, &MFMediaType_Audio), "Unexpected major type.\n");
3623 IMFMediaTypeHandler_Release(handler);
3625 hr = IMFActivate_ShutdownObject(activate);
3626 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3628 ref = IMFActivate_Release(activate);
3629 ok(ref == 0, "Release returned %ld\n", ref);
3631 /* required for the sink to be fully released */
3632 hr = IMFMediaSink_Shutdown(sink);
3633 ok(hr == S_OK, "Failed to shut down, hr %#lx.\n", hr);
3635 ref = IMFMediaSink_Release(sink);
3636 ok(ref == 0, "Release returned %ld\n", ref);
3638 ref = IMFMediaType_Release(media_type2);
3639 ok(ref == 0, "Release returned %ld\n", ref);
3640 ref = IMFMediaType_Release(media_type);
3641 ok(ref == 0, "Release returned %ld\n", ref);
3644 static BOOL is_supported_video_type(const GUID *guid)
3646 return IsEqualGUID(guid, &MFVideoFormat_L8)
3647 || IsEqualGUID(guid, &MFVideoFormat_L16)
3648 || IsEqualGUID(guid, &MFVideoFormat_D16)
3649 || IsEqualGUID(guid, &MFVideoFormat_IYUV)
3650 || IsEqualGUID(guid, &MFVideoFormat_YV12)
3651 || IsEqualGUID(guid, &MFVideoFormat_NV12)
3652 || IsEqualGUID(guid, &MFVideoFormat_NV21)
3653 || IsEqualGUID(guid, &MFVideoFormat_420O)
3654 || IsEqualGUID(guid, &MFVideoFormat_P010)
3655 || IsEqualGUID(guid, &MFVideoFormat_P016)
3656 || IsEqualGUID(guid, &MFVideoFormat_UYVY)
3657 || IsEqualGUID(guid, &MFVideoFormat_YUY2)
3658 || IsEqualGUID(guid, &MFVideoFormat_P208)
3659 || IsEqualGUID(guid, &MFVideoFormat_NV11)
3660 || IsEqualGUID(guid, &MFVideoFormat_AYUV)
3661 || IsEqualGUID(guid, &MFVideoFormat_ARGB32)
3662 || IsEqualGUID(guid, &MFVideoFormat_RGB32)
3663 || IsEqualGUID(guid, &MFVideoFormat_A2R10G10B10)
3664 || IsEqualGUID(guid, &MFVideoFormat_A16B16G16R16F)
3665 || IsEqualGUID(guid, &MFVideoFormat_RGB24)
3666 || IsEqualGUID(guid, &MFVideoFormat_I420)
3667 || IsEqualGUID(guid, &MFVideoFormat_YVYU)
3668 || IsEqualGUID(guid, &MFVideoFormat_RGB555)
3669 || IsEqualGUID(guid, &MFVideoFormat_RGB565)
3670 || IsEqualGUID(guid, &MFVideoFormat_RGB8)
3671 || IsEqualGUID(guid, &MFVideoFormat_Y216)
3672 || IsEqualGUID(guid, &MFVideoFormat_v410)
3673 || IsEqualGUID(guid, &MFVideoFormat_Y41P)
3674 || IsEqualGUID(guid, &MFVideoFormat_Y41T)
3675 || IsEqualGUID(guid, &MFVideoFormat_Y42T)
3676 || IsEqualGUID(guid, &MFVideoFormat_ABGR32);
3679 static void test_video_processor(void)
3681 const GUID transform_inputs[22] =
3683 MFVideoFormat_IYUV,
3684 MFVideoFormat_YV12,
3685 MFVideoFormat_NV12,
3686 MFVideoFormat_YUY2,
3687 MFVideoFormat_ARGB32,
3688 MFVideoFormat_RGB32,
3689 MFVideoFormat_NV11,
3690 MFVideoFormat_AYUV,
3691 MFVideoFormat_UYVY,
3692 MEDIASUBTYPE_P208,
3693 MFVideoFormat_RGB24,
3694 MFVideoFormat_RGB555,
3695 MFVideoFormat_RGB565,
3696 MFVideoFormat_RGB8,
3697 MFVideoFormat_I420,
3698 MFVideoFormat_Y216,
3699 MFVideoFormat_v410,
3700 MFVideoFormat_Y41P,
3701 MFVideoFormat_Y41T,
3702 MFVideoFormat_Y42T,
3703 MFVideoFormat_YVYU,
3704 MFVideoFormat_420O,
3706 const GUID transform_outputs[21] =
3708 MFVideoFormat_IYUV,
3709 MFVideoFormat_YV12,
3710 MFVideoFormat_NV12,
3711 MFVideoFormat_YUY2,
3712 MFVideoFormat_ARGB32,
3713 MFVideoFormat_RGB32,
3714 MFVideoFormat_NV11,
3715 MFVideoFormat_AYUV,
3716 MFVideoFormat_UYVY,
3717 MEDIASUBTYPE_P208,
3718 MFVideoFormat_RGB24,
3719 MFVideoFormat_RGB555,
3720 MFVideoFormat_RGB565,
3721 MFVideoFormat_RGB8,
3722 MFVideoFormat_I420,
3723 MFVideoFormat_Y216,
3724 MFVideoFormat_v410,
3725 MFVideoFormat_Y41P,
3726 MFVideoFormat_Y41T,
3727 MFVideoFormat_Y42T,
3728 MFVideoFormat_YVYU,
3730 MFT_REGISTER_TYPE_INFO output_type = {MFMediaType_Video, MFVideoFormat_NV12};
3731 MFT_REGISTER_TYPE_INFO input_type = {MFMediaType_Video, MFVideoFormat_I420};
3732 DWORD input_count, output_count, input_id, output_id, flags;
3733 DWORD input_min, input_max, output_min, output_max, i;
3734 IMFAttributes *attributes, *attributes2;
3735 IMFMediaType *media_type, *media_type2;
3736 MFT_OUTPUT_DATA_BUFFER output_buffer;
3737 MFT_OUTPUT_STREAM_INFO output_info;
3738 MFT_INPUT_STREAM_INFO input_info;
3739 IMFSample *sample, *sample2;
3740 IMFTransform *transform;
3741 IMFMediaBuffer *buffer;
3742 IMFMediaEvent *event;
3743 unsigned int value;
3744 GUID class_id;
3745 UINT32 count;
3746 HRESULT hr;
3747 GUID guid;
3748 LONG ref;
3750 hr = CoInitialize(NULL);
3751 ok(hr == S_OK, "Failed to initialize, hr %#lx.\n", hr);
3753 if (!create_transform(MFT_CATEGORY_VIDEO_PROCESSOR, &input_type, &output_type, L"Microsoft Video Processor MFT", &MFMediaType_Video,
3754 transform_inputs, ARRAY_SIZE(transform_inputs), transform_outputs, ARRAY_SIZE(transform_outputs),
3755 &transform, &CLSID_VideoProcessorMFT, &class_id))
3756 goto failed;
3757 has_video_processor = TRUE;
3759 todo_wine
3760 check_interface(transform, &IID_IMFVideoProcessorControl, TRUE);
3761 todo_wine
3762 check_interface(transform, &IID_IMFRealTimeClientEx, TRUE);
3763 check_interface(transform, &IID_IMFMediaEventGenerator, FALSE);
3764 check_interface(transform, &IID_IMFShutdown, FALSE);
3766 /* Transform global attributes. */
3767 hr = IMFTransform_GetAttributes(transform, &attributes);
3768 ok(hr == S_OK, "Failed to get attributes, hr %#lx.\n", hr);
3770 hr = IMFAttributes_GetCount(attributes, &count);
3771 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3772 todo_wine
3773 ok(!!count, "Unexpected attribute count %u.\n", count);
3775 value = 0;
3776 hr = IMFAttributes_GetUINT32(attributes, &MF_SA_D3D11_AWARE, &value);
3777 todo_wine {
3778 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3779 ok(value == 1, "Unexpected attribute value %u.\n", value);
3781 hr = IMFTransform_GetAttributes(transform, &attributes2);
3782 ok(hr == S_OK, "Failed to get attributes, hr %#lx.\n", hr);
3783 ok(attributes == attributes2, "Unexpected instance.\n");
3784 IMFAttributes_Release(attributes);
3785 IMFAttributes_Release(attributes2);
3787 hr = IMFTransform_GetStreamLimits(transform, &input_min, &input_max, &output_min, &output_max);
3788 ok(hr == S_OK, "Failed to get stream limits, hr %#lx.\n", hr);
3789 ok(input_min == input_max && input_min == 1 && output_min == output_max && output_min == 1,
3790 "Unexpected stream limits.\n");
3792 hr = IMFTransform_GetStreamCount(transform, &input_count, &output_count);
3793 ok(hr == S_OK, "Failed to get stream count, hr %#lx.\n", hr);
3794 ok(input_count == 1 && output_count == 1, "Unexpected stream count %lu, %lu.\n", input_count, output_count);
3796 hr = IMFTransform_GetStreamIDs(transform, 1, &input_id, 1, &output_id);
3797 ok(hr == E_NOTIMPL, "Unexpected hr %#lx.\n", hr);
3799 input_id = 100;
3800 hr = IMFTransform_AddInputStreams(transform, 1, &input_id);
3801 ok(hr == E_NOTIMPL, "Unexpected hr %#lx.\n", hr);
3803 hr = IMFTransform_DeleteInputStream(transform, 0);
3804 ok(hr == E_NOTIMPL, "Unexpected hr %#lx.\n", hr);
3806 hr = IMFTransform_GetInputStatus(transform, 0, &flags);
3807 todo_wine
3808 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "Unexpected hr %#lx.\n", hr);
3810 hr = IMFTransform_GetInputStreamAttributes(transform, 0, &attributes);
3811 ok(hr == E_NOTIMPL, "Unexpected hr %#lx.\n", hr);
3813 hr = IMFTransform_GetOutputStatus(transform, &flags);
3814 todo_wine
3815 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "Unexpected hr %#lx.\n", hr);
3817 hr = IMFTransform_GetOutputStreamAttributes(transform, 0, &attributes);
3818 ok(hr == S_OK, "Failed to get output attributes, hr %#lx.\n", hr);
3819 hr = IMFTransform_GetOutputStreamAttributes(transform, 0, &attributes2);
3820 ok(hr == S_OK, "Failed to get output attributes, hr %#lx.\n", hr);
3821 ok(attributes == attributes2, "Unexpected instance.\n");
3822 IMFAttributes_Release(attributes);
3823 IMFAttributes_Release(attributes2);
3825 hr = IMFTransform_GetOutputAvailableType(transform, 0, 0, &media_type);
3826 todo_wine
3827 ok(hr == MF_E_NO_MORE_TYPES, "Unexpected hr %#lx.\n", hr);
3829 hr = IMFTransform_GetInputCurrentType(transform, 0, &media_type);
3830 todo_wine
3831 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "Unexpected hr %#lx.\n", hr);
3833 hr = IMFTransform_GetInputCurrentType(transform, 1, &media_type);
3834 todo_wine
3835 ok(hr == MF_E_INVALIDSTREAMNUMBER, "Unexpected hr %#lx.\n", hr);
3837 hr = IMFTransform_GetOutputCurrentType(transform, 0, &media_type);
3838 todo_wine
3839 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "Unexpected hr %#lx.\n", hr);
3841 hr = IMFTransform_GetOutputCurrentType(transform, 1, &media_type);
3842 todo_wine
3843 ok(hr == MF_E_INVALIDSTREAMNUMBER, "Unexpected hr %#lx.\n", hr);
3845 hr = IMFTransform_GetInputStreamInfo(transform, 1, &input_info);
3846 todo_wine
3847 ok(hr == MF_E_INVALIDSTREAMNUMBER, "Unexpected hr %#lx.\n", hr);
3849 memset(&input_info, 0xcc, sizeof(input_info));
3850 hr = IMFTransform_GetInputStreamInfo(transform, 0, &input_info);
3851 todo_wine {
3852 ok(hr == S_OK, "Failed to get stream info, hr %#lx.\n", hr);
3853 ok(input_info.dwFlags == 0, "Unexpected flag %#lx.\n", input_info.dwFlags);
3854 ok(input_info.cbSize == 0, "Unexpected size %lu.\n", input_info.cbSize);
3855 ok(input_info.cbMaxLookahead == 0, "Unexpected lookahead length %lu.\n", input_info.cbMaxLookahead);
3856 ok(input_info.cbAlignment == 0, "Unexpected alignment %lu.\n", input_info.cbAlignment);
3858 hr = MFCreateMediaEvent(MEUnknown, &GUID_NULL, S_OK, NULL, &event);
3859 ok(hr == S_OK, "Failed to create event object, hr %#lx.\n", hr);
3860 hr = IMFTransform_ProcessEvent(transform, 0, event);
3861 ok(hr == E_NOTIMPL, "Unexpected hr %#lx.\n", hr);
3862 hr = IMFTransform_ProcessEvent(transform, 1, event);
3863 ok(hr == E_NOTIMPL, "Unexpected hr %#lx.\n", hr);
3864 ref = IMFMediaEvent_Release(event);
3865 ok(ref == 0, "Release returned %ld\n", ref);
3867 /* Configure stream types. */
3868 for (i = 0;;++i)
3870 if (FAILED(hr = IMFTransform_GetInputAvailableType(transform, 0, i, &media_type)))
3872 todo_wine
3873 ok(hr == MF_E_NO_MORE_TYPES, "Unexpected hr %#lx.\n", hr);
3874 break;
3877 hr = IMFTransform_GetInputAvailableType(transform, 0, i, &media_type2);
3878 ok(hr == S_OK, "Failed to get available type, hr %#lx.\n", hr);
3879 ok(media_type != media_type2, "Unexpected instance.\n");
3880 ref = IMFMediaType_Release(media_type2);
3881 ok(ref == 0, "Release returned %ld\n", ref);
3883 hr = IMFMediaType_GetMajorType(media_type, &guid);
3884 ok(hr == S_OK, "Failed to get major type, hr %#lx.\n", hr);
3885 ok(IsEqualGUID(&guid, &MFMediaType_Video), "Unexpected major type.\n");
3887 hr = IMFMediaType_GetCount(media_type, &count);
3888 ok(hr == S_OK, "Failed to get attributes count, hr %#lx.\n", hr);
3889 ok(count == 2, "Unexpected count %u.\n", count);
3891 hr = IMFMediaType_GetGUID(media_type, &MF_MT_SUBTYPE, &guid);
3892 ok(hr == S_OK, "Failed to get subtype, hr %#lx.\n", hr);
3893 ok(is_supported_video_type(&guid), "Unexpected media type %s.\n", wine_dbgstr_guid(&guid));
3895 hr = IMFTransform_SetInputType(transform, 0, media_type, MFT_SET_TYPE_TEST_ONLY);
3896 ok(FAILED(hr), "Unexpected hr %#lx.\n", hr);
3898 hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
3899 ok(FAILED(hr), "Unexpected hr %#lx.\n", hr);
3901 hr = IMFTransform_GetOutputCurrentType(transform, 0, &media_type2);
3902 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "Unexpected hr %#lx.\n", hr);
3904 /* FIXME: figure out if those require additional attributes or simply advertised but not supported */
3905 if (IsEqualGUID(&guid, &MFVideoFormat_L8) || IsEqualGUID(&guid, &MFVideoFormat_L16)
3906 || IsEqualGUID(&guid, &MFVideoFormat_D16) || IsEqualGUID(&guid, &MFVideoFormat_420O)
3907 || IsEqualGUID(&guid, &MFVideoFormat_A16B16G16R16F))
3909 ref = IMFMediaType_Release(media_type);
3910 ok(ref == 0, "Release returned %ld\n", ref);
3911 continue;
3914 hr = IMFMediaType_SetUINT64(media_type, &MF_MT_FRAME_SIZE, ((UINT64)16 << 32) | 16);
3915 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
3917 hr = IMFTransform_SetInputType(transform, 0, media_type, MFT_SET_TYPE_TEST_ONLY);
3918 ok(hr == S_OK, "Failed to test input type %s, hr %#lx.\n", wine_dbgstr_guid(&guid), hr);
3920 hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
3921 ok(hr == S_OK, "Failed to test input type, hr %#lx.\n", hr);
3923 hr = IMFTransform_GetInputCurrentType(transform, 0, &media_type2);
3924 ok(hr == S_OK, "Failed to get current type, hr %#lx.\n", hr);
3925 ok(media_type != media_type2, "Unexpected instance.\n");
3926 IMFMediaType_Release(media_type2);
3928 hr = IMFTransform_GetInputStatus(transform, 0, &flags);
3929 ok(hr == S_OK, "Failed to get input status, hr %#lx.\n", hr);
3930 ok(flags == MFT_INPUT_STATUS_ACCEPT_DATA, "Unexpected input status %#lx.\n", flags);
3932 hr = IMFTransform_GetInputStreamInfo(transform, 0, &input_info);
3933 ok(hr == S_OK, "Failed to get stream info, hr %#lx.\n", hr);
3934 ok(input_info.dwFlags == 0, "Unexpected flags %#lx.\n", input_info.dwFlags);
3935 ok(input_info.cbMaxLookahead == 0, "Unexpected lookahead length %lu.\n", input_info.cbMaxLookahead);
3936 ok(input_info.cbAlignment == 0, "Unexpected alignment %lu.\n", input_info.cbAlignment);
3938 IMFMediaType_Release(media_type);
3941 /* IYUV -> RGB32 */
3942 hr = MFCreateMediaType(&media_type);
3943 ok(hr == S_OK, "Failed to create media type, hr %#lx.\n", hr);
3945 hr = IMFMediaType_SetGUID(media_type, &MF_MT_MAJOR_TYPE, &MFMediaType_Video);
3946 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
3948 hr = IMFMediaType_SetGUID(media_type, &MF_MT_SUBTYPE, &MFVideoFormat_IYUV);
3949 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
3951 hr = IMFMediaType_SetUINT64(media_type, &MF_MT_FRAME_SIZE, ((UINT64)16 << 32) | 16);
3952 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
3954 hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
3955 todo_wine
3956 ok(hr == S_OK, "Failed to set input type, hr %#lx.\n", hr);
3958 hr = IMFMediaType_SetGUID(media_type, &MF_MT_SUBTYPE, &MFVideoFormat_RGB32);
3959 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
3961 hr = IMFTransform_SetOutputType(transform, 0, media_type, 0);
3962 todo_wine
3963 ok(hr == S_OK, "Failed to set output type, hr %#lx.\n", hr);
3965 memset(&output_info, 0, sizeof(output_info));
3966 hr = IMFTransform_GetOutputStreamInfo(transform, 0, &output_info);
3967 todo_wine
3968 ok(hr == S_OK, "Failed to get stream info, hr %#lx.\n", hr);
3969 ok(output_info.dwFlags == 0, "Unexpected flags %#lx.\n", output_info.dwFlags);
3970 todo_wine
3971 ok(output_info.cbSize > 0, "Unexpected size %lu.\n", output_info.cbSize);
3972 ok(output_info.cbAlignment == 0, "Unexpected alignment %lu.\n", output_info.cbAlignment);
3974 hr = MFCreateSample(&sample);
3975 ok(hr == S_OK, "Failed to create a sample, hr %#lx.\n", hr);
3977 hr = MFCreateSample(&sample2);
3978 ok(hr == S_OK, "Failed to create a sample, hr %#lx.\n", hr);
3980 memset(&output_buffer, 0, sizeof(output_buffer));
3981 output_buffer.pSample = sample;
3982 flags = 0;
3983 hr = IMFTransform_ProcessOutput(transform, 0, 1, &output_buffer, &flags);
3984 todo_wine
3985 ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "Unexpected hr %#lx.\n", hr);
3986 ok(output_buffer.dwStatus == 0, "Unexpected buffer status, %#lx.\n", output_buffer.dwStatus);
3987 ok(flags == 0, "Unexpected status %#lx.\n", flags);
3989 hr = IMFTransform_ProcessInput(transform, 0, sample2, 0);
3990 todo_wine
3991 ok(hr == S_OK, "Failed to push a sample, hr %#lx.\n", hr);
3993 hr = IMFTransform_ProcessInput(transform, 0, sample2, 0);
3994 todo_wine
3995 ok(hr == MF_E_NOTACCEPTING, "Unexpected hr %#lx.\n", hr);
3997 memset(&output_buffer, 0, sizeof(output_buffer));
3998 output_buffer.pSample = sample;
3999 flags = 0;
4000 hr = IMFTransform_ProcessOutput(transform, 0, 1, &output_buffer, &flags);
4001 todo_wine
4002 ok(hr == MF_E_NO_SAMPLE_TIMESTAMP, "Unexpected hr %#lx.\n", hr);
4003 ok(output_buffer.dwStatus == 0, "Unexpected buffer status, %#lx.\n", output_buffer.dwStatus);
4004 ok(flags == 0, "Unexpected status %#lx.\n", flags);
4006 hr = IMFSample_SetSampleTime(sample2, 0);
4007 ok(hr == S_OK, "Failed to set sample time, hr %#lx.\n", hr);
4008 memset(&output_buffer, 0, sizeof(output_buffer));
4009 output_buffer.pSample = sample;
4010 flags = 0;
4011 hr = IMFTransform_ProcessOutput(transform, 0, 1, &output_buffer, &flags);
4012 todo_wine
4013 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
4014 ok(output_buffer.dwStatus == 0, "Unexpected buffer status, %#lx.\n", output_buffer.dwStatus);
4015 ok(flags == 0, "Unexpected status %#lx.\n", flags);
4017 hr = MFCreateMemoryBuffer(1024 * 1024, &buffer);
4018 ok(hr == S_OK, "Failed to create a buffer, hr %#lx.\n", hr);
4020 hr = IMFSample_AddBuffer(sample2, buffer);
4021 ok(hr == S_OK, "Failed to add a buffer, hr %#lx.\n", hr);
4023 hr = IMFSample_AddBuffer(sample, buffer);
4024 ok(hr == S_OK, "Failed to add a buffer, hr %#lx.\n", hr);
4026 memset(&output_buffer, 0, sizeof(output_buffer));
4027 output_buffer.pSample = sample;
4028 flags = 0;
4029 hr = IMFTransform_ProcessOutput(transform, 0, 1, &output_buffer, &flags);
4030 todo_wine
4031 ok(hr == S_OK || broken(FAILED(hr)) /* Win8 */, "Failed to get output buffer, hr %#lx.\n", hr);
4032 ok(output_buffer.dwStatus == 0, "Unexpected buffer status, %#lx.\n", output_buffer.dwStatus);
4033 ok(flags == 0, "Unexpected status %#lx.\n", flags);
4035 if (SUCCEEDED(hr))
4037 memset(&output_buffer, 0, sizeof(output_buffer));
4038 output_buffer.pSample = sample;
4039 flags = 0;
4040 hr = IMFTransform_ProcessOutput(transform, 0, 1, &output_buffer, &flags);
4041 ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "Unexpected hr %#lx.\n", hr);
4042 ok(output_buffer.dwStatus == 0, "Unexpected buffer status, %#lx.\n", output_buffer.dwStatus);
4043 ok(flags == 0, "Unexpected status %#lx.\n", flags);
4046 ref = IMFTransform_Release(transform);
4047 ok(ref == 0, "Release returned %ld\n", ref);
4049 ref = IMFMediaType_Release(media_type);
4050 ok(ref == 0, "Release returned %ld\n", ref);
4051 ref = IMFSample_Release(sample2);
4052 ok(ref == 0, "Release returned %ld\n", ref);
4053 ref = IMFSample_Release(sample);
4054 ok(ref == 0, "Release returned %ld\n", ref);
4055 ref = IMFMediaBuffer_Release(buffer);
4056 ok(ref == 0, "Release returned %ld\n", ref);
4058 failed:
4059 CoUninitialize();
4062 static void test_quality_manager(void)
4064 IMFPresentationClock *clock;
4065 IMFQualityManager *manager;
4066 IMFTopology *topology;
4067 HRESULT hr;
4068 LONG ref;
4070 hr = MFStartup(MF_VERSION, MFSTARTUP_FULL);
4071 ok(hr == S_OK, "Startup failure, hr %#lx.\n", hr);
4073 hr = MFCreatePresentationClock(&clock);
4074 ok(hr == S_OK, "Failed to create presentation clock, hr %#lx.\n", hr);
4076 hr = MFCreateStandardQualityManager(&manager);
4077 ok(hr == S_OK, "Failed to create quality manager, hr %#lx.\n", hr);
4079 check_interface(manager, &IID_IMFQualityManager, TRUE);
4080 check_interface(manager, &IID_IMFClockStateSink, TRUE);
4082 hr = IMFQualityManager_NotifyPresentationClock(manager, NULL);
4083 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
4085 hr = IMFQualityManager_NotifyTopology(manager, NULL);
4086 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4088 /* Set clock, then shutdown. */
4089 EXPECT_REF(clock, 1);
4090 EXPECT_REF(manager, 1);
4091 hr = IMFQualityManager_NotifyPresentationClock(manager, clock);
4092 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4093 EXPECT_REF(clock, 2);
4094 EXPECT_REF(manager, 2);
4096 hr = IMFQualityManager_Shutdown(manager);
4097 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4098 EXPECT_REF(clock, 1);
4100 hr = IMFQualityManager_NotifyPresentationClock(manager, clock);
4101 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
4103 hr = IMFQualityManager_NotifyTopology(manager, NULL);
4104 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
4106 hr = IMFQualityManager_NotifyPresentationClock(manager, NULL);
4107 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
4109 hr = IMFQualityManager_Shutdown(manager);
4110 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4112 ref = IMFQualityManager_Release(manager);
4113 ok(ref == 0, "Release returned %ld\n", ref);
4115 hr = MFCreateStandardQualityManager(&manager);
4116 ok(hr == S_OK, "Failed to create quality manager, hr %#lx.\n", hr);
4118 EXPECT_REF(clock, 1);
4119 EXPECT_REF(manager, 1);
4120 hr = IMFQualityManager_NotifyPresentationClock(manager, clock);
4121 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4122 EXPECT_REF(manager, 2);
4123 EXPECT_REF(clock, 2);
4124 hr = IMFQualityManager_Shutdown(manager);
4125 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4127 ref = IMFQualityManager_Release(manager);
4128 ok(ref == 0, "Release returned %ld\n", ref);
4129 ref = IMFPresentationClock_Release(clock);
4130 ok(ref == 0, "Release returned %ld\n", ref);
4132 /* Set topology. */
4133 hr = MFCreateStandardQualityManager(&manager);
4134 ok(hr == S_OK, "Failed to create quality manager, hr %#lx.\n", hr);
4136 hr = MFCreateTopology(&topology);
4137 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4139 EXPECT_REF(topology, 1);
4140 hr = IMFQualityManager_NotifyTopology(manager, topology);
4141 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4142 EXPECT_REF(topology, 2);
4144 hr = IMFQualityManager_NotifyTopology(manager, NULL);
4145 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4146 EXPECT_REF(topology, 1);
4148 hr = IMFQualityManager_NotifyTopology(manager, topology);
4149 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4151 EXPECT_REF(topology, 2);
4152 hr = IMFQualityManager_Shutdown(manager);
4153 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4154 EXPECT_REF(topology, 1);
4156 hr = IMFQualityManager_NotifyTopology(manager, topology);
4157 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
4159 ref = IMFQualityManager_Release(manager);
4160 ok(ref == 0, "Release returned %ld\n", ref);
4162 hr = MFCreateStandardQualityManager(&manager);
4163 ok(hr == S_OK, "Failed to create quality manager, hr %#lx.\n", hr);
4165 EXPECT_REF(topology, 1);
4166 hr = IMFQualityManager_NotifyTopology(manager, topology);
4167 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4168 EXPECT_REF(topology, 2);
4170 ref = IMFQualityManager_Release(manager);
4171 ok(ref == 0, "Release returned %ld\n", ref);
4172 ref = IMFTopology_Release(topology);
4173 ok(ref == 0, "Release returned %ld\n", ref);
4175 hr = MFShutdown();
4176 ok(hr == S_OK, "Shutdown failure, hr %#lx.\n", hr);
4179 static void check_sar_rate_support(IMFMediaSink *sink)
4181 IMFRateSupport *rate_support;
4182 IMFMediaTypeHandler *handler;
4183 IMFStreamSink *stream_sink;
4184 IMFMediaType *media_type;
4185 HRESULT hr;
4186 float rate;
4188 hr = IMFMediaSink_QueryInterface(sink, &IID_IMFRateSupport, (void **)&rate_support);
4189 todo_wine
4190 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4191 if (FAILED(hr)) return;
4193 hr = IMFMediaSink_GetStreamSinkByIndex(sink, 0, &stream_sink);
4194 if (hr == MF_E_SHUTDOWN)
4196 hr = IMFRateSupport_GetSlowestRate(rate_support, MFRATE_FORWARD, FALSE, NULL);
4197 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
4199 hr = IMFRateSupport_GetSlowestRate(rate_support, MFRATE_FORWARD, FALSE, &rate);
4200 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
4202 hr = IMFRateSupport_GetFastestRate(rate_support, MFRATE_FORWARD, FALSE, &rate);
4203 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
4205 IMFRateSupport_Release(rate_support);
4206 return;
4208 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4210 hr = IMFStreamSink_GetMediaTypeHandler(stream_sink, &handler);
4211 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4213 IMFStreamSink_Release(stream_sink);
4215 hr = IMFRateSupport_GetSlowestRate(rate_support, MFRATE_FORWARD, FALSE, NULL);
4216 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
4218 hr = IMFRateSupport_GetFastestRate(rate_support, MFRATE_FORWARD, FALSE, NULL);
4219 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
4221 hr = IMFMediaTypeHandler_GetCurrentMediaType(handler, &media_type);
4222 if (SUCCEEDED(hr))
4224 hr = IMFRateSupport_GetSlowestRate(rate_support, MFRATE_FORWARD, FALSE, &rate);
4225 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4227 hr = IMFRateSupport_GetSlowestRate(rate_support, MFRATE_FORWARD, TRUE, &rate);
4228 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4230 hr = IMFRateSupport_GetSlowestRate(rate_support, MFRATE_REVERSE, FALSE, &rate);
4231 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4233 hr = IMFRateSupport_GetSlowestRate(rate_support, MFRATE_REVERSE, TRUE, &rate);
4234 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4236 hr = IMFRateSupport_GetFastestRate(rate_support, MFRATE_FORWARD, FALSE, &rate);
4237 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4239 hr = IMFRateSupport_GetFastestRate(rate_support, MFRATE_FORWARD, TRUE, &rate);
4240 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4242 hr = IMFRateSupport_GetFastestRate(rate_support, MFRATE_REVERSE, FALSE, &rate);
4243 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4245 hr = IMFRateSupport_GetFastestRate(rate_support, MFRATE_REVERSE, TRUE, &rate);
4246 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4248 IMFMediaType_Release(media_type);
4250 else
4252 hr = IMFRateSupport_GetSlowestRate(rate_support, MFRATE_FORWARD, FALSE, &rate);
4253 ok(hr == MF_E_NOT_INITIALIZED, "Unexpected hr %#lx.\n", hr);
4255 hr = IMFRateSupport_GetSlowestRate(rate_support, MFRATE_FORWARD, TRUE, &rate);
4256 ok(hr == MF_E_NOT_INITIALIZED, "Unexpected hr %#lx.\n", hr);
4258 hr = IMFRateSupport_GetSlowestRate(rate_support, MFRATE_REVERSE, FALSE, &rate);
4259 ok(hr == MF_E_NOT_INITIALIZED, "Unexpected hr %#lx.\n", hr);
4261 hr = IMFRateSupport_GetSlowestRate(rate_support, MFRATE_REVERSE, TRUE, &rate);
4262 ok(hr == MF_E_NOT_INITIALIZED, "Unexpected hr %#lx.\n", hr);
4264 hr = IMFRateSupport_GetFastestRate(rate_support, MFRATE_FORWARD, FALSE, &rate);
4265 ok(hr == MF_E_NOT_INITIALIZED, "Unexpected hr %#lx.\n", hr);
4267 hr = IMFRateSupport_GetFastestRate(rate_support, MFRATE_FORWARD, TRUE, &rate);
4268 ok(hr == MF_E_NOT_INITIALIZED, "Unexpected hr %#lx.\n", hr);
4270 hr = IMFRateSupport_GetFastestRate(rate_support, MFRATE_REVERSE, FALSE, &rate);
4271 ok(hr == MF_E_NOT_INITIALIZED, "Unexpected hr %#lx.\n", hr);
4273 hr = IMFRateSupport_GetFastestRate(rate_support, MFRATE_REVERSE, TRUE, &rate);
4274 ok(hr == MF_E_NOT_INITIALIZED, "Unexpected hr %#lx.\n", hr);
4277 IMFMediaTypeHandler_Release(handler);
4278 IMFRateSupport_Release(rate_support);
4281 static void test_sar(void)
4283 IMFPresentationClock *present_clock, *present_clock2;
4284 IMFMediaType *mediatype, *mediatype2, *mediatype3;
4285 IMFClockStateSink *state_sink, *state_sink2;
4286 IMFMediaTypeHandler *handler, *handler2;
4287 IMFPresentationTimeSource *time_source;
4288 IMFSimpleAudioVolume *simple_volume;
4289 IMFAudioStreamVolume *stream_volume;
4290 IMFMediaSink *sink, *sink2;
4291 IMFStreamSink *stream_sink;
4292 IMFAttributes *attributes;
4293 DWORD i, id, flags, count;
4294 IMFActivate *activate;
4295 UINT32 channel_count;
4296 MFCLOCK_STATE state;
4297 IMFClock *clock;
4298 IUnknown *unk;
4299 HRESULT hr;
4300 GUID guid;
4301 BOOL mute;
4302 int found;
4303 LONG ref;
4305 hr = CoInitialize(NULL);
4306 ok(hr == S_OK, "Failed to initialize, hr %#lx.\n", hr);
4308 hr = MFCreateAudioRenderer(NULL, &sink);
4309 if (hr == MF_E_NO_AUDIO_PLAYBACK_DEVICE)
4311 skip("No audio playback device available.\n");
4312 CoUninitialize();
4313 return;
4315 ok(hr == S_OK, "Failed to create renderer, hr %#lx.\n", hr);
4317 hr = MFStartup(MF_VERSION, MFSTARTUP_FULL);
4318 ok(hr == S_OK, "Startup failure, hr %#lx.\n", hr);
4320 hr = MFCreatePresentationClock(&present_clock);
4321 ok(hr == S_OK, "Failed to create presentation clock, hr %#lx.\n", hr);
4323 hr = IMFMediaSink_QueryInterface(sink, &IID_IMFPresentationTimeSource, (void **)&time_source);
4324 todo_wine
4325 ok(hr == S_OK, "Failed to get time source interface, hr %#lx.\n", hr);
4327 if (SUCCEEDED(hr))
4329 hr = IMFPresentationTimeSource_QueryInterface(time_source, &IID_IMFClockStateSink, (void **)&state_sink2);
4330 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4331 hr = IMFPresentationTimeSource_QueryInterface(time_source, &IID_IMFClockStateSink, (void **)&state_sink);
4332 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4333 ok(state_sink == state_sink2, "Unexpected clock sink.\n");
4334 IMFClockStateSink_Release(state_sink2);
4335 IMFClockStateSink_Release(state_sink);
4337 hr = IMFPresentationTimeSource_GetUnderlyingClock(time_source, &clock);
4338 ok(hr == MF_E_NO_CLOCK, "Unexpected hr %#lx.\n", hr);
4340 hr = IMFPresentationTimeSource_GetClockCharacteristics(time_source, &flags);
4341 ok(hr == S_OK, "Failed to get flags, hr %#lx.\n", hr);
4342 ok(flags == MFCLOCK_CHARACTERISTICS_FLAG_FREQUENCY_10MHZ, "Unexpected flags %#lx.\n", flags);
4344 hr = IMFPresentationTimeSource_GetState(time_source, 0, &state);
4345 ok(hr == S_OK, "Failed to get clock state, hr %#lx.\n", hr);
4346 ok(state == MFCLOCK_STATE_INVALID, "Unexpected state %d.\n", state);
4348 hr = IMFPresentationTimeSource_QueryInterface(time_source, &IID_IMFClockStateSink, (void **)&state_sink);
4349 ok(hr == S_OK, "Failed to get state sink, hr %#lx.\n", hr);
4351 hr = IMFClockStateSink_OnClockStart(state_sink, 0, 0);
4352 ok(hr == MF_E_NOT_INITIALIZED, "Unexpected hr %#lx.\n", hr);
4354 IMFClockStateSink_Release(state_sink);
4356 IMFPresentationTimeSource_Release(time_source);
4358 hr = IMFMediaSink_AddStreamSink(sink, 123, NULL, &stream_sink);
4359 ok(hr == MF_E_STREAMSINKS_FIXED, "Unexpected hr %#lx.\n", hr);
4361 hr = IMFMediaSink_RemoveStreamSink(sink, 0);
4362 ok(hr == MF_E_STREAMSINKS_FIXED, "Unexpected hr %#lx.\n", hr);
4364 hr = IMFMediaSink_GetStreamSinkCount(sink, NULL);
4365 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
4367 hr = IMFMediaSink_GetStreamSinkCount(sink, &count);
4368 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4369 ok(count == 1, "Unexpected count %lu.\n", count);
4371 hr = IMFMediaSink_GetCharacteristics(sink, &flags);
4372 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4373 ok(flags == (MEDIASINK_FIXED_STREAMS | MEDIASINK_CAN_PREROLL), "Unexpected flags %#lx.\n", flags);
4375 check_interface(sink, &IID_IMFMediaSinkPreroll, TRUE);
4376 check_interface(sink, &IID_IMFMediaEventGenerator, TRUE);
4377 check_interface(sink, &IID_IMFClockStateSink, TRUE);
4378 check_interface(sink, &IID_IMFGetService, TRUE);
4379 todo_wine check_interface(sink, &IID_IMFPresentationTimeSource, TRUE);
4380 todo_wine check_service_interface(sink, &MF_RATE_CONTROL_SERVICE, &IID_IMFRateSupport, TRUE);
4381 check_service_interface(sink, &MF_RATE_CONTROL_SERVICE, &IID_IMFRateControl, FALSE);
4382 check_service_interface(sink, &MR_POLICY_VOLUME_SERVICE, &IID_IMFSimpleAudioVolume, TRUE);
4383 check_service_interface(sink, &MR_STREAM_VOLUME_SERVICE, &IID_IMFAudioStreamVolume, TRUE);
4385 /* Clock */
4386 hr = IMFMediaSink_QueryInterface(sink, &IID_IMFClockStateSink, (void **)&state_sink);
4387 ok(hr == S_OK, "Failed to get interface, hr %#lx.\n", hr);
4389 hr = IMFClockStateSink_OnClockStart(state_sink, 0, 0);
4390 ok(hr == MF_E_NOT_INITIALIZED, "Unexpected hr %#lx.\n", hr);
4392 hr = IMFClockStateSink_OnClockPause(state_sink, 0);
4393 ok(hr == MF_E_INVALID_STATE_TRANSITION, "Unexpected hr %#lx.\n", hr);
4395 hr = IMFClockStateSink_OnClockStop(state_sink, 0);
4396 ok(hr == MF_E_NOT_INITIALIZED, "Unexpected hr %#lx.\n", hr);
4398 hr = IMFClockStateSink_OnClockRestart(state_sink, 0);
4399 ok(hr == MF_E_NOT_INITIALIZED, "Unexpected hr %#lx.\n", hr);
4401 IMFClockStateSink_Release(state_sink);
4403 hr = IMFMediaSink_SetPresentationClock(sink, NULL);
4404 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4406 hr = IMFMediaSink_SetPresentationClock(sink, present_clock);
4407 todo_wine
4408 ok(hr == MF_E_CLOCK_NO_TIME_SOURCE, "Unexpected hr %#lx.\n", hr);
4410 hr = MFCreateSystemTimeSource(&time_source);
4411 ok(hr == S_OK, "Failed to create time source, hr %#lx.\n", hr);
4413 hr = IMFPresentationClock_SetTimeSource(present_clock, time_source);
4414 ok(hr == S_OK, "Failed to set time source, hr %#lx.\n", hr);
4415 IMFPresentationTimeSource_Release(time_source);
4417 hr = IMFMediaSink_SetPresentationClock(sink, present_clock);
4418 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4420 hr = IMFMediaSink_GetPresentationClock(sink, NULL);
4421 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
4423 hr = IMFMediaSink_GetPresentationClock(sink, &present_clock2);
4424 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4425 ok(present_clock == present_clock2, "Unexpected instance.\n");
4426 IMFPresentationClock_Release(present_clock2);
4428 /* Stream */
4429 hr = IMFMediaSink_GetStreamSinkByIndex(sink, 0, &stream_sink);
4430 ok(hr == S_OK, "Failed to get a stream, hr %#lx.\n", hr);
4432 check_interface(stream_sink, &IID_IMFMediaEventGenerator, TRUE);
4433 check_interface(stream_sink, &IID_IMFMediaTypeHandler, TRUE);
4434 todo_wine check_interface(stream_sink, &IID_IMFGetService, TRUE);
4436 hr = IMFStreamSink_GetIdentifier(stream_sink, &id);
4437 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4438 ok(!id, "Unexpected id.\n");
4440 hr = IMFStreamSink_GetMediaSink(stream_sink, &sink2);
4441 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4442 ok(sink == sink2, "Unexpected object.\n");
4443 IMFMediaSink_Release(sink2);
4445 hr = IMFStreamSink_GetMediaTypeHandler(stream_sink, &handler);
4446 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4448 hr = IMFStreamSink_QueryInterface(stream_sink, &IID_IMFMediaTypeHandler, (void **)&handler2);
4449 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4450 ok(handler2 == handler, "Unexpected instance.\n");
4451 IMFMediaTypeHandler_Release(handler2);
4453 hr = IMFMediaTypeHandler_GetMajorType(handler, &guid);
4454 ok(hr == S_OK, "Failed to get major type, hr %#lx.\n", hr);
4455 ok(IsEqualGUID(&guid, &MFMediaType_Audio), "Unexpected type %s.\n", wine_dbgstr_guid(&guid));
4457 count = 0;
4458 hr = IMFMediaTypeHandler_GetMediaTypeCount(handler, &count);
4459 ok(hr == S_OK, "Failed to get type count, hr %#lx.\n", hr);
4460 ok(!!count, "Unexpected type count %lu.\n", count);
4462 /* A number of same major/subtype entries are returned, with different degrees of finer format
4463 details. Some incomplete types are not accepted, check that at least one of them is considered supported. */
4465 for (i = 0, found = -1; i < count; ++i)
4467 hr = IMFMediaTypeHandler_GetMediaTypeByIndex(handler, i, &mediatype);
4468 ok(hr == S_OK, "Failed to get media type, hr %#lx.\n", hr);
4470 if (SUCCEEDED(IMFMediaTypeHandler_IsMediaTypeSupported(handler, mediatype, NULL)))
4471 found = i;
4472 IMFMediaType_Release(mediatype);
4474 if (found != -1) break;
4476 ok(found != -1, "Haven't found a supported type.\n");
4478 hr = IMFMediaTypeHandler_GetCurrentMediaType(handler, &mediatype);
4479 ok(hr == MF_E_NOT_INITIALIZED, "Unexpected hr %#lx.\n", hr);
4481 hr = MFCreateMediaType(&mediatype);
4482 ok(hr == S_OK, "Failed to create media type, hr %#lx.\n", hr);
4484 /* Actual return value is MF_E_ATRIBUTENOTFOUND triggered by missing MF_MT_MAJOR_TYPE */
4485 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, mediatype, NULL);
4486 ok(FAILED(hr), "Unexpected hr %#lx.\n", hr);
4488 hr = IMFMediaType_SetGUID(mediatype, &MF_MT_MAJOR_TYPE, &MFMediaType_Video);
4489 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4490 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, mediatype, NULL);
4491 ok(hr == MF_E_INVALIDMEDIATYPE, "Unexpected hr %#lx.\n", hr);
4493 hr = IMFMediaType_SetGUID(mediatype, &MF_MT_MAJOR_TYPE, &MFMediaType_Audio);
4494 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4495 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, mediatype, NULL);
4496 ok(hr == MF_E_INVALIDMEDIATYPE, "Unexpected hr %#lx.\n", hr);
4498 hr = IMFMediaTypeHandler_SetCurrentMediaType(handler, mediatype);
4499 ok(hr == MF_E_INVALIDMEDIATYPE, "Unexpected hr %#lx.\n", hr);
4501 hr = IMFMediaTypeHandler_GetMediaTypeByIndex(handler, found, &mediatype2);
4502 ok(hr == S_OK, "Failed to get media type, hr %#lx.\n", hr);
4504 hr = IMFMediaTypeHandler_GetMediaTypeByIndex(handler, found, &mediatype3);
4505 ok(hr == S_OK, "Failed to get media type, hr %#lx.\n", hr);
4506 ok(mediatype2 == mediatype3, "Unexpected instance.\n");
4507 IMFMediaType_Release(mediatype3);
4509 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, mediatype2, NULL);
4510 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4512 IMFMediaType_Release(mediatype);
4514 check_sar_rate_support(sink);
4516 hr = IMFMediaTypeHandler_SetCurrentMediaType(handler, mediatype2);
4517 ok(hr == S_OK, "Failed to set current type, hr %#lx.\n", hr);
4519 check_sar_rate_support(sink);
4521 hr = IMFMediaTypeHandler_GetCurrentMediaType(handler, &mediatype);
4522 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4523 ok(mediatype == mediatype2, "Unexpected instance.\n");
4524 IMFMediaType_Release(mediatype);
4526 IMFMediaType_Release(mediatype2);
4528 /* Reset back to uninitialized state. */
4529 hr = IMFMediaTypeHandler_SetCurrentMediaType(handler, NULL);
4530 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
4532 IMFMediaTypeHandler_Release(handler);
4534 /* State change with initialized stream. */
4535 hr = IMFMediaSink_QueryInterface(sink, &IID_IMFClockStateSink, (void **)&state_sink);
4536 ok(hr == S_OK, "Failed to get interface, hr %#lx.\n", hr);
4538 hr = IMFClockStateSink_OnClockStart(state_sink, 0, 0);
4539 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4541 hr = IMFClockStateSink_OnClockStart(state_sink, 0, 0);
4542 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4544 hr = IMFClockStateSink_OnClockPause(state_sink, 0);
4545 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4547 hr = IMFClockStateSink_OnClockStop(state_sink, 0);
4548 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4550 hr = IMFClockStateSink_OnClockStop(state_sink, 0);
4551 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4553 hr = IMFClockStateSink_OnClockPause(state_sink, 0);
4554 ok(hr == MF_E_INVALID_STATE_TRANSITION, "Unexpected hr %#lx.\n", hr);
4556 hr = IMFClockStateSink_OnClockRestart(state_sink, 0);
4557 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4559 hr = IMFClockStateSink_OnClockRestart(state_sink, 0);
4560 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4562 hr = IMFClockStateSink_OnClockStop(state_sink, 0);
4563 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4565 IMFClockStateSink_Release(state_sink);
4567 IMFStreamSink_Release(stream_sink);
4569 /* Volume control */
4570 hr = MFGetService((IUnknown *)sink, &MR_POLICY_VOLUME_SERVICE, &IID_IMFSimpleAudioVolume, (void **)&simple_volume);
4571 ok(hr == S_OK, "Failed to get interface, hr %#lx.\n", hr);
4573 hr = IMFSimpleAudioVolume_GetMute(simple_volume, &mute);
4574 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4576 IMFSimpleAudioVolume_Release(simple_volume);
4578 hr = MFGetService((IUnknown *)sink, &MR_STREAM_VOLUME_SERVICE, &IID_IMFAudioStreamVolume, (void **)&stream_volume);
4579 ok(hr == S_OK, "Failed to get interface, hr %#lx.\n", hr);
4581 hr = IMFAudioStreamVolume_GetChannelCount(stream_volume, &channel_count);
4582 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4584 hr = IMFAudioStreamVolume_GetChannelCount(stream_volume, NULL);
4585 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
4587 IMFAudioStreamVolume_Release(stream_volume);
4589 hr = MFGetService((IUnknown *)sink, &MR_AUDIO_POLICY_SERVICE, &IID_IMFAudioPolicy, (void **)&unk);
4590 ok(hr == S_OK, "Failed to get interface, hr %#lx.\n", hr);
4591 IUnknown_Release(unk);
4593 /* Shutdown */
4594 EXPECT_REF(present_clock, 2);
4595 hr = IMFMediaSink_Shutdown(sink);
4596 ok(hr == S_OK, "Failed to shut down, hr %#lx.\n", hr);
4597 EXPECT_REF(present_clock, 1);
4599 hr = IMFMediaSink_Shutdown(sink);
4600 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
4602 hr = IMFMediaSink_AddStreamSink(sink, 123, NULL, &stream_sink);
4603 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
4605 hr = IMFMediaSink_RemoveStreamSink(sink, 0);
4606 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
4608 hr = IMFMediaSink_GetStreamSinkCount(sink, NULL);
4609 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
4611 hr = IMFMediaSink_GetStreamSinkCount(sink, &count);
4612 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
4614 hr = IMFMediaSink_GetCharacteristics(sink, &flags);
4615 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
4617 hr = IMFMediaSink_SetPresentationClock(sink, NULL);
4618 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
4620 hr = IMFMediaSink_SetPresentationClock(sink, present_clock);
4621 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
4623 hr = IMFMediaSink_GetPresentationClock(sink, NULL);
4624 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
4626 hr = IMFMediaSink_GetPresentationClock(sink, &present_clock2);
4627 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
4629 check_sar_rate_support(sink);
4631 ref = IMFMediaSink_Release(sink);
4632 todo_wine
4633 ok(ref == 0, "Release returned %ld\n", ref);
4635 /* Activation */
4636 hr = MFCreateAudioRendererActivate(&activate);
4637 ok(hr == S_OK, "Failed to create activation object, hr %#lx.\n", hr);
4639 hr = IMFActivate_ActivateObject(activate, &IID_IMFMediaSink, (void **)&sink);
4640 ok(hr == S_OK, "Failed to activate, hr %#lx.\n", hr);
4642 hr = IMFActivate_ActivateObject(activate, &IID_IMFMediaSink, (void **)&sink2);
4643 ok(hr == S_OK, "Failed to activate, hr %#lx.\n", hr);
4644 ok(sink == sink2, "Unexpected instance.\n");
4645 IMFMediaSink_Release(sink2);
4647 hr = IMFMediaSink_GetCharacteristics(sink, &flags);
4648 ok(hr == S_OK, "Failed to get sink flags, hr %#lx.\n", hr);
4650 hr = IMFActivate_ShutdownObject(activate);
4651 ok(hr == S_OK, "Failed to shut down, hr %#lx.\n", hr);
4653 hr = IMFMediaSink_GetCharacteristics(sink, &flags);
4654 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
4656 hr = IMFActivate_ActivateObject(activate, &IID_IMFMediaSink, (void **)&sink2);
4657 ok(hr == S_OK, "Failed to activate, hr %#lx.\n", hr);
4658 todo_wine
4659 ok(sink == sink2, "Unexpected instance.\n");
4661 hr = IMFMediaSink_GetCharacteristics(sink2, &flags);
4662 todo_wine
4663 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
4665 IMFMediaSink_Release(sink2);
4667 hr = IMFActivate_DetachObject(activate);
4668 ok(hr == E_NOTIMPL, "Unexpected hr %#lx.\n", hr);
4670 hr = IMFActivate_ShutdownObject(activate);
4671 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4673 ref = IMFActivate_Release(activate);
4674 ok(ref == 0, "Release returned %ld\n", ref);
4675 ref = IMFMediaSink_Release(sink);
4676 ok(ref == 0, "Release returned %ld\n", ref);
4678 ref = IMFPresentationClock_Release(present_clock);
4679 ok(ref == 0, "Release returned %ld\n", ref);
4681 hr = MFShutdown();
4682 ok(hr == S_OK, "Shutdown failure, hr %#lx.\n", hr);
4684 /* SAR attributes */
4685 hr = MFCreateAttributes(&attributes, 0);
4686 ok(hr == S_OK, "Failed to create attributes, hr %#lx.\n", hr);
4688 /* Specify role. */
4689 hr = IMFAttributes_SetUINT32(attributes, &MF_AUDIO_RENDERER_ATTRIBUTE_ENDPOINT_ROLE, eMultimedia);
4690 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
4692 hr = MFCreateAudioRenderer(attributes, &sink);
4693 ok(hr == S_OK, "Failed to create a sink, hr %#lx.\n", hr);
4695 /* required for the sink to be fully released */
4696 hr = IMFMediaSink_Shutdown(sink);
4697 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4699 ref = IMFMediaSink_Release(sink);
4700 ok(ref == 0, "Release returned %ld\n", ref);
4702 /* Invalid endpoint. */
4703 hr = IMFAttributes_SetString(attributes, &MF_AUDIO_RENDERER_ATTRIBUTE_ENDPOINT_ID, L"endpoint");
4704 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
4706 hr = MFCreateAudioRenderer(attributes, &sink);
4707 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
4709 hr = IMFAttributes_DeleteItem(attributes, &MF_AUDIO_RENDERER_ATTRIBUTE_ENDPOINT_ROLE);
4710 ok(hr == S_OK, "Failed to remove attribute, hr %#lx.\n", hr);
4712 hr = MFCreateAudioRenderer(attributes, &sink);
4713 ok(hr == MF_E_NO_AUDIO_PLAYBACK_DEVICE, "Failed to create a sink, hr %#lx.\n", hr);
4715 ref = IMFAttributes_Release(attributes);
4716 ok(ref == 0, "Release returned %ld\n", ref);
4718 CoUninitialize();
4721 static void test_evr(void)
4723 static const float supported_rates[] =
4725 0.0f, 1.0f, -20.0f, 20.0f, 1000.0f, -1000.0f,
4727 IMFVideoSampleAllocatorCallback *allocator_callback;
4728 IMFStreamSink *stream_sink, *stream_sink2;
4729 IMFVideoDisplayControl *display_control;
4730 IMFMediaType *media_type, *media_type2;
4731 IMFPresentationTimeSource *time_source;
4732 IMFVideoSampleAllocator *allocator;
4733 IMFMediaTypeHandler *type_handler;
4734 IMFVideoRenderer *video_renderer;
4735 IMFPresentationClock *clock;
4736 IMFMediaSink *sink, *sink2;
4737 IMFAttributes *attributes;
4738 UINT32 attr_count, value;
4739 IMFActivate *activate;
4740 HWND window, window2;
4741 IMFRateSupport *rs;
4742 DWORD flags, count;
4743 LONG sample_count;
4744 IMFSample *sample;
4745 unsigned int i;
4746 UINT64 window3;
4747 float rate;
4748 HRESULT hr;
4749 GUID guid;
4750 LONG ref;
4752 hr = MFStartup(MF_VERSION, MFSTARTUP_FULL);
4753 ok(hr == S_OK, "Startup failure, hr %#lx.\n", hr);
4755 hr = MFCreateVideoRenderer(&IID_IMFVideoRenderer, (void **)&video_renderer);
4756 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4758 hr = IMFVideoRenderer_InitializeRenderer(video_renderer, NULL, NULL);
4759 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4761 /* required for the video renderer to be fully released */
4762 hr = IMFVideoRenderer_QueryInterface(video_renderer, &IID_IMFMediaSink, (void **)&sink);
4763 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4764 hr = IMFMediaSink_Shutdown(sink);
4765 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4766 IMFMediaSink_Release(sink);
4768 ref = IMFVideoRenderer_Release(video_renderer);
4769 todo_wine
4770 ok(ref == 0, "Release returned %ld\n", ref);
4772 hr = MFCreateVideoRendererActivate(NULL, NULL);
4773 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
4775 /* Window */
4776 window = create_window();
4777 hr = MFCreateVideoRendererActivate(window, &activate);
4778 ok(hr == S_OK, "Failed to create activate object, hr %#lx.\n", hr);
4780 hr = IMFActivate_GetUINT64(activate, &MF_ACTIVATE_VIDEO_WINDOW, &window3);
4781 ok(hr == S_OK, "Failed to get attribute, hr %#lx.\n", hr);
4782 ok(UlongToHandle(window3) == window, "Unexpected value.\n");
4784 hr = IMFActivate_ActivateObject(activate, &IID_IMFMediaSink, (void **)&sink);
4785 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4787 check_interface(sink, &IID_IMFMediaSinkPreroll, TRUE);
4788 check_interface(sink, &IID_IMFVideoRenderer, TRUE);
4789 check_interface(sink, &IID_IMFMediaEventGenerator, TRUE);
4790 check_interface(sink, &IID_IMFClockStateSink, TRUE);
4791 check_interface(sink, &IID_IMFGetService, TRUE);
4792 check_interface(sink, &IID_IMFQualityAdvise, TRUE);
4793 check_interface(sink, &IID_IMFRateSupport, TRUE);
4794 check_interface(sink, &IID_IMFRateControl, FALSE);
4795 check_service_interface(sink, &MR_VIDEO_MIXER_SERVICE, &IID_IMFVideoProcessor, TRUE);
4796 check_service_interface(sink, &MR_VIDEO_MIXER_SERVICE, &IID_IMFVideoMixerBitmap, TRUE);
4797 check_service_interface(sink, &MR_VIDEO_MIXER_SERVICE, &IID_IMFVideoMixerControl, TRUE);
4798 check_service_interface(sink, &MR_VIDEO_MIXER_SERVICE, &IID_IMFVideoMixerControl2, TRUE);
4799 check_service_interface(sink, &MR_VIDEO_RENDER_SERVICE, &IID_IMFVideoDisplayControl, TRUE);
4800 check_service_interface(sink, &MR_VIDEO_RENDER_SERVICE, &IID_IMFVideoPositionMapper, TRUE);
4801 check_service_interface(sink, &MR_VIDEO_ACCELERATION_SERVICE, &IID_IMFVideoSampleAllocator, FALSE);
4802 check_service_interface(sink, &MR_VIDEO_ACCELERATION_SERVICE, &IID_IDirect3DDeviceManager9, TRUE);
4803 check_service_interface(sink, &MF_RATE_CONTROL_SERVICE, &IID_IMFRateSupport, TRUE);
4805 hr = MFGetService((IUnknown *)sink, &MR_VIDEO_RENDER_SERVICE, &IID_IMFVideoDisplayControl,
4806 (void **)&display_control);
4807 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4809 window2 = NULL;
4810 hr = IMFVideoDisplayControl_GetVideoWindow(display_control, &window2);
4811 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4812 ok(window2 == window, "Unexpected window %p.\n", window2);
4814 IMFVideoDisplayControl_Release(display_control);
4816 hr = IMFActivate_ShutdownObject(activate);
4817 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4819 ref = IMFActivate_Release(activate);
4820 ok(ref == 0, "Release returned %ld\n", ref);
4821 ref = IMFMediaSink_Release(sink);
4822 ok(ref == 0, "Release returned %ld\n", ref);
4823 DestroyWindow(window);
4825 hr = MFCreateVideoRendererActivate(NULL, &activate);
4826 ok(hr == S_OK, "Failed to create activate object, hr %#lx.\n", hr);
4828 hr = IMFActivate_GetCount(activate, &attr_count);
4829 ok(hr == S_OK, "Failed to get attribute count, hr %#lx.\n", hr);
4830 ok(attr_count == 1, "Unexpected count %u.\n", attr_count);
4832 hr = IMFActivate_GetUINT64(activate, &MF_ACTIVATE_VIDEO_WINDOW, &window3);
4833 ok(hr == S_OK, "Failed to get attribute, hr %#lx.\n", hr);
4834 ok(!window3, "Unexpected value.\n");
4836 hr = IMFActivate_ActivateObject(activate, &IID_IMFMediaSink, (void **)&sink);
4837 ok(hr == S_OK, "Failed to activate, hr %#lx.\n", hr);
4839 hr = IMFMediaSink_QueryInterface(sink, &IID_IMFAttributes, (void **)&attributes);
4840 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4841 check_interface(attributes, &IID_IMFMediaSink, TRUE);
4843 hr = IMFAttributes_GetCount(attributes, &attr_count);
4844 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4845 ok(!!attr_count, "Unexpected count %u.\n", attr_count);
4846 /* Rendering preferences are not immediately propagated to the presenter. */
4847 hr = IMFAttributes_SetUINT32(attributes, &EVRConfig_ForceBob, 1);
4848 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4849 hr = MFGetService((IUnknown *)sink, &MR_VIDEO_RENDER_SERVICE, &IID_IMFVideoDisplayControl, (void **)&display_control);
4850 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4851 hr = IMFVideoDisplayControl_GetRenderingPrefs(display_control, &flags);
4852 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4853 ok(!flags, "Unexpected flags %#lx.\n", flags);
4854 IMFVideoDisplayControl_Release(display_control);
4855 IMFAttributes_Release(attributes);
4857 /* Primary stream type handler. */
4858 hr = IMFMediaSink_GetStreamSinkById(sink, 0, &stream_sink);
4859 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4861 hr = IMFStreamSink_QueryInterface(stream_sink, &IID_IMFAttributes, (void **)&attributes);
4862 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4863 hr = IMFAttributes_GetCount(attributes, &attr_count);
4864 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4865 ok(attr_count == 2, "Unexpected count %u.\n", attr_count);
4866 value = 0;
4867 hr = IMFAttributes_GetUINT32(attributes, &MF_SA_REQUIRED_SAMPLE_COUNT, &value);
4868 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4869 ok(value == 1, "Unexpected attribute value %u.\n", value);
4870 value = 0;
4871 hr = IMFAttributes_GetUINT32(attributes, &MF_SA_D3D_AWARE, &value);
4872 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4873 ok(value == 1, "Unexpected attribute value %u.\n", value);
4875 check_interface(attributes, &IID_IMFStreamSink, TRUE);
4876 IMFAttributes_Release(attributes);
4878 hr = IMFStreamSink_GetMediaTypeHandler(stream_sink, &type_handler);
4879 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4881 hr = IMFMediaTypeHandler_GetMajorType(type_handler, NULL);
4882 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
4884 hr = IMFMediaTypeHandler_GetMajorType(type_handler, &guid);
4885 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4886 ok(IsEqualGUID(&guid, &MFMediaType_Video), "Unexpected type %s.\n", wine_dbgstr_guid(&guid));
4888 /* Supported types are not advertised. */
4889 hr = IMFMediaTypeHandler_GetMediaTypeCount(type_handler, NULL);
4890 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
4892 count = 1;
4893 hr = IMFMediaTypeHandler_GetMediaTypeCount(type_handler, &count);
4894 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4895 ok(!count, "Unexpected count %lu.\n", count);
4897 hr = IMFMediaTypeHandler_GetMediaTypeByIndex(type_handler, 0, NULL);
4898 ok(hr == MF_E_NO_MORE_TYPES, "Unexpected hr %#lx.\n", hr);
4900 hr = IMFMediaTypeHandler_GetMediaTypeByIndex(type_handler, 0, &media_type);
4901 ok(hr == MF_E_NO_MORE_TYPES, "Unexpected hr %#lx.\n", hr);
4903 hr = IMFMediaTypeHandler_GetCurrentMediaType(type_handler, NULL);
4904 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
4906 hr = IMFMediaTypeHandler_GetCurrentMediaType(type_handler, &media_type);
4907 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "Unexpected hr %#lx.\n", hr);
4909 hr = IMFMediaTypeHandler_SetCurrentMediaType(type_handler, NULL);
4910 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
4912 hr = MFCreateMediaType(&media_type);
4913 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4915 hr = IMFMediaType_SetGUID(media_type, &MF_MT_MAJOR_TYPE, &MFMediaType_Video);
4916 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4918 hr = IMFMediaType_SetGUID(media_type, &MF_MT_SUBTYPE, &MFVideoFormat_RGB32);
4919 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4921 hr = IMFMediaType_SetUINT64(media_type, &MF_MT_FRAME_SIZE, (UINT64)640 << 32 | 480);
4922 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4924 hr = IMFMediaTypeHandler_IsMediaTypeSupported(type_handler, NULL, NULL);
4925 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
4927 hr = IMFMediaTypeHandler_IsMediaTypeSupported(type_handler, media_type, &media_type2);
4928 ok(hr == MF_E_INVALIDMEDIATYPE, "Unexpected hr %#lx.\n", hr);
4930 hr = IMFMediaType_SetUINT32(media_type, &MF_MT_ALL_SAMPLES_INDEPENDENT, TRUE);
4931 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4933 media_type2 = (void *)0x1;
4934 hr = IMFMediaTypeHandler_IsMediaTypeSupported(type_handler, media_type, &media_type2);
4935 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4936 ok(!media_type2, "Unexpected media type %p.\n", media_type2);
4938 hr = IMFMediaTypeHandler_SetCurrentMediaType(type_handler, media_type);
4939 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4941 hr = IMFMediaTypeHandler_GetCurrentMediaType(type_handler, &media_type2);
4942 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4943 check_interface(media_type2, &IID_IMFVideoMediaType, TRUE);
4944 IMFMediaType_Release(media_type2);
4946 IMFMediaType_Release(media_type);
4948 IMFMediaTypeHandler_Release(type_handler);
4950 /* Stream uses an allocator. */
4951 check_service_interface(stream_sink, &MR_VIDEO_ACCELERATION_SERVICE, &IID_IMFVideoSampleAllocator, TRUE);
4952 check_service_interface(stream_sink, &MR_VIDEO_ACCELERATION_SERVICE, &IID_IDirect3DDeviceManager9, TRUE);
4953 todo_wine {
4954 check_service_interface(stream_sink, &MR_VIDEO_MIXER_SERVICE, &IID_IMFVideoProcessor, TRUE);
4955 check_service_interface(stream_sink, &MR_VIDEO_MIXER_SERVICE, &IID_IMFVideoMixerBitmap, TRUE);
4956 check_service_interface(stream_sink, &MR_VIDEO_MIXER_SERVICE, &IID_IMFVideoMixerControl, TRUE);
4957 check_service_interface(stream_sink, &MR_VIDEO_MIXER_SERVICE, &IID_IMFVideoMixerControl2, TRUE);
4958 check_service_interface(stream_sink, &MR_VIDEO_RENDER_SERVICE, &IID_IMFVideoDisplayControl, TRUE);
4959 check_service_interface(stream_sink, &MR_VIDEO_RENDER_SERVICE, &IID_IMFVideoPositionMapper, TRUE);
4960 check_service_interface(stream_sink, &MF_RATE_CONTROL_SERVICE, &IID_IMFRateSupport, TRUE);
4962 hr = MFGetService((IUnknown *)stream_sink, &MR_VIDEO_ACCELERATION_SERVICE, &IID_IMFVideoSampleAllocator,
4963 (void **)&allocator);
4964 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4966 hr = IMFVideoSampleAllocator_QueryInterface(allocator, &IID_IMFVideoSampleAllocatorCallback, (void **)&allocator_callback);
4967 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4969 sample_count = 0;
4970 hr = IMFVideoSampleAllocatorCallback_GetFreeSampleCount(allocator_callback, &sample_count);
4971 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4972 ok(!sample_count, "Unexpected sample count %ld.\n", sample_count);
4974 hr = IMFVideoSampleAllocator_AllocateSample(allocator, &sample);
4975 ok(hr == MF_E_NOT_INITIALIZED, "Unexpected hr %#lx.\n", hr);
4977 IMFVideoSampleAllocatorCallback_Release(allocator_callback);
4978 IMFVideoSampleAllocator_Release(allocator);
4979 IMFStreamSink_Release(stream_sink);
4981 /* Same test for a substream. */
4982 hr = IMFMediaSink_AddStreamSink(sink, 1, NULL, &stream_sink2);
4983 ok(hr == S_OK || broken(hr == E_INVALIDARG), "Unexpected hr %#lx.\n", hr);
4985 if (SUCCEEDED(hr))
4987 hr = MFGetService((IUnknown *)stream_sink2, &MR_VIDEO_ACCELERATION_SERVICE, &IID_IMFVideoSampleAllocator,
4988 (void **)&allocator);
4989 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4990 IMFVideoSampleAllocator_Release(allocator);
4992 hr = IMFMediaSink_RemoveStreamSink(sink, 1);
4993 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4995 ref = IMFStreamSink_Release(stream_sink2);
4996 ok(ref == 0, "Release returned %ld\n", ref);
4999 hr = IMFMediaSink_GetCharacteristics(sink, &flags);
5000 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5001 ok(flags == (MEDIASINK_CAN_PREROLL | MEDIASINK_CLOCK_REQUIRED), "Unexpected flags %#lx.\n", flags);
5003 hr = IMFActivate_ShutdownObject(activate);
5004 ok(hr == S_OK, "Failed to shut down, hr %#lx.\n", hr);
5006 hr = IMFMediaSink_GetCharacteristics(sink, &flags);
5007 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
5009 /* Activate again. */
5010 hr = IMFActivate_ActivateObject(activate, &IID_IMFMediaSink, (void **)&sink2);
5011 ok(hr == S_OK, "Failed to activate, hr %#lx.\n", hr);
5012 todo_wine
5013 ok(sink == sink2, "Unexpected instance.\n");
5014 IMFMediaSink_Release(sink2);
5016 hr = IMFActivate_DetachObject(activate);
5017 ok(hr == E_NOTIMPL, "Unexpected hr %#lx.\n", hr);
5019 hr = IMFMediaSink_GetCharacteristics(sink, &flags);
5020 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
5022 hr = IMFActivate_ActivateObject(activate, &IID_IMFMediaSink, (void **)&sink2);
5023 ok(hr == S_OK, "Failed to activate, hr %#lx.\n", hr);
5024 todo_wine
5025 ok(sink == sink2, "Unexpected instance.\n");
5026 IMFMediaSink_Release(sink2);
5028 hr = IMFActivate_ShutdownObject(activate);
5029 ok(hr == S_OK, "Failed to shut down, hr %#lx.\n", hr);
5031 ref = IMFActivate_Release(activate);
5032 ok(ref == 0, "Release returned %ld\n", ref);
5033 ref = IMFMediaSink_Release(sink);
5034 todo_wine
5035 ok(ref == 0, "Release returned %ld\n", ref);
5037 /* Set clock. */
5038 window = create_window();
5040 hr = MFCreateVideoRendererActivate(window, &activate);
5041 ok(hr == S_OK, "Failed to create activate object, hr %#lx.\n", hr);
5043 hr = IMFActivate_ActivateObject(activate, &IID_IMFMediaSink, (void **)&sink);
5044 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5045 ref = IMFActivate_Release(activate);
5046 ok(ref == 0, "Release returned %ld\n", ref);
5048 hr = MFCreateSystemTimeSource(&time_source);
5049 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5051 hr = MFCreatePresentationClock(&clock);
5052 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5054 hr = IMFPresentationClock_SetTimeSource(clock, time_source);
5055 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5056 IMFPresentationTimeSource_Release(time_source);
5058 hr = IMFMediaSink_SetPresentationClock(sink, clock);
5059 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5061 hr = IMFMediaSink_QueryInterface(sink, &IID_IMFRateSupport, (void **)&rs);
5062 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5064 rate = 1.0f;
5065 hr = IMFRateSupport_GetSlowestRate(rs, MFRATE_FORWARD, FALSE, &rate);
5066 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5067 ok(rate == 0.0f, "Unexpected rate %f.\n", rate);
5069 rate = 1.0f;
5070 hr = IMFRateSupport_GetSlowestRate(rs, MFRATE_REVERSE, FALSE, &rate);
5071 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5072 ok(rate == 0.0f, "Unexpected rate %f.\n", rate);
5074 rate = 1.0f;
5075 hr = IMFRateSupport_GetSlowestRate(rs, MFRATE_FORWARD, TRUE, &rate);
5076 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5077 ok(rate == 0.0f, "Unexpected rate %f.\n", rate);
5079 rate = 1.0f;
5080 hr = IMFRateSupport_GetSlowestRate(rs, MFRATE_REVERSE, TRUE, &rate);
5081 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5082 ok(rate == 0.0f, "Unexpected rate %f.\n", rate);
5084 hr = IMFRateSupport_GetFastestRate(rs, MFRATE_FORWARD, FALSE, &rate);
5085 ok(hr == MF_E_INVALIDREQUEST, "Unexpected hr %#lx.\n", hr);
5087 hr = IMFRateSupport_GetFastestRate(rs, MFRATE_REVERSE, FALSE, &rate);
5088 ok(hr == MF_E_INVALIDREQUEST, "Unexpected hr %#lx.\n", hr);
5090 hr = IMFRateSupport_GetFastestRate(rs, MFRATE_FORWARD, TRUE, &rate);
5091 ok(hr == MF_E_INVALIDREQUEST, "Unexpected hr %#lx.\n", hr);
5093 hr = IMFRateSupport_GetFastestRate(rs, MFRATE_REVERSE, TRUE, &rate);
5094 ok(hr == MF_E_INVALIDREQUEST, "Unexpected hr %#lx.\n", hr);
5096 hr = IMFRateSupport_GetFastestRate(rs, MFRATE_REVERSE, TRUE, NULL);
5097 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
5099 for (i = 0; i < ARRAY_SIZE(supported_rates); ++i)
5101 rate = supported_rates[i] + 1.0f;
5102 hr = IMFRateSupport_IsRateSupported(rs, TRUE, supported_rates[i], &rate);
5103 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5104 ok(rate == supported_rates[i], "Unexpected rate %f.\n", rate);
5106 rate = supported_rates[i] + 1.0f;
5107 hr = IMFRateSupport_IsRateSupported(rs, FALSE, supported_rates[i], &rate);
5108 ok(hr == MF_E_INVALIDREQUEST, "Unexpected hr %#lx.\n", hr);
5109 ok(rate == supported_rates[i], "Unexpected rate %f.\n", rate);
5111 hr = IMFRateSupport_IsRateSupported(rs, TRUE, supported_rates[i], NULL);
5112 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5114 hr = IMFRateSupport_IsRateSupported(rs, FALSE, supported_rates[i], NULL);
5115 ok(hr == MF_E_INVALIDREQUEST, "Unexpected hr %#lx.\n", hr);
5118 /* Configuring stream type make rate support work. */
5119 hr = IMFMediaSink_GetStreamSinkById(sink, 0, &stream_sink);
5120 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5121 hr = IMFStreamSink_GetMediaTypeHandler(stream_sink, &type_handler);
5122 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5123 hr = MFCreateMediaType(&media_type);
5124 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5125 hr = IMFMediaType_SetGUID(media_type, &MF_MT_MAJOR_TYPE, &MFMediaType_Video);
5126 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5127 hr = IMFMediaType_SetGUID(media_type, &MF_MT_SUBTYPE, &MFVideoFormat_RGB32);
5128 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5129 hr = IMFMediaType_SetUINT64(media_type, &MF_MT_FRAME_SIZE, (UINT64)64 << 32 | 64);
5130 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5131 hr = IMFMediaType_SetUINT32(media_type, &MF_MT_ALL_SAMPLES_INDEPENDENT, TRUE);
5132 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5133 hr = IMFMediaTypeHandler_SetCurrentMediaType(type_handler, media_type);
5134 ok(hr == S_OK, "Failed to set current type, hr %#lx.\n", hr);
5135 IMFMediaType_Release(media_type);
5136 IMFMediaTypeHandler_Release(type_handler);
5137 IMFStreamSink_Release(stream_sink);
5139 rate = 1.0f;
5140 hr = IMFRateSupport_GetSlowestRate(rs, MFRATE_FORWARD, TRUE, &rate);
5141 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5142 ok(rate == 0.0f, "Unexpected rate %f.\n", rate);
5144 rate = 1.0f;
5145 hr = IMFRateSupport_GetSlowestRate(rs, MFRATE_REVERSE, TRUE, &rate);
5146 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5147 ok(rate == 0.0f, "Unexpected rate %f.\n", rate);
5149 rate = 0.0f;
5150 hr = IMFRateSupport_GetFastestRate(rs, MFRATE_FORWARD, TRUE, &rate);
5151 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5152 ok(rate == FLT_MAX, "Unexpected rate %f.\n", rate);
5154 rate = 0.0f;
5155 hr = IMFRateSupport_GetFastestRate(rs, MFRATE_REVERSE, TRUE, &rate);
5156 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5157 ok(rate == -FLT_MAX, "Unexpected rate %f.\n", rate);
5159 hr = IMFRateSupport_GetFastestRate(rs, MFRATE_REVERSE, TRUE, NULL);
5160 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
5162 hr = IMFRateSupport_GetSlowestRate(rs, MFRATE_REVERSE, TRUE, NULL);
5163 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
5165 for (i = 0; i < ARRAY_SIZE(supported_rates); ++i)
5167 rate = supported_rates[i] + 1.0f;
5168 hr = IMFRateSupport_IsRateSupported(rs, TRUE, supported_rates[i], &rate);
5169 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5170 ok(rate == supported_rates[i], "Unexpected rate %f.\n", rate);
5172 rate = supported_rates[i] + 1.0f;
5173 hr = IMFRateSupport_IsRateSupported(rs, FALSE, supported_rates[i], &rate);
5174 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5175 ok(rate == supported_rates[i], "Unexpected rate %f.\n", rate);
5177 hr = IMFRateSupport_IsRateSupported(rs, TRUE, supported_rates[i], NULL);
5178 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5180 hr = IMFRateSupport_IsRateSupported(rs, FALSE, supported_rates[i], NULL);
5181 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5184 hr = IMFMediaSink_Shutdown(sink);
5185 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5187 hr = IMFMediaSink_GetStreamSinkCount(sink, NULL);
5188 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
5190 hr = IMFMediaSink_GetStreamSinkCount(sink, &count);
5191 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
5193 hr = IMFRateSupport_GetSlowestRate(rs, MFRATE_FORWARD, FALSE, &rate);
5194 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
5196 hr = IMFRateSupport_GetFastestRate(rs, MFRATE_FORWARD, FALSE, &rate);
5197 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
5199 hr = IMFRateSupport_GetSlowestRate(rs, MFRATE_FORWARD, FALSE, NULL);
5200 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
5202 hr = IMFRateSupport_GetFastestRate(rs, MFRATE_FORWARD, FALSE, NULL);
5203 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
5205 hr = IMFRateSupport_IsRateSupported(rs, TRUE, 1.0f, &rate);
5206 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
5208 ref = IMFRateSupport_Release(rs);
5209 ok(ref == 1, "Release returned %ld\n", ref);
5210 ref = IMFMediaSink_Release(sink);
5211 ok(ref == 0, "Release returned %ld\n", ref);
5212 ref = IMFPresentationClock_Release(clock);
5213 ok(ref == 0, "Release returned %ld\n", ref);
5215 DestroyWindow(window);
5217 hr = MFShutdown();
5218 ok(hr == S_OK, "Shutdown failure, hr %#lx.\n", hr);
5221 static void test_MFCreateSimpleTypeHandler(void)
5223 IMFMediaType *media_type, *media_type2, *media_type3;
5224 IMFMediaTypeHandler *handler;
5225 DWORD count;
5226 HRESULT hr;
5227 GUID guid;
5228 LONG ref;
5230 hr = MFCreateSimpleTypeHandler(&handler);
5231 ok(hr == S_OK, "Failed to create object, hr %#lx.\n", hr);
5233 hr = IMFMediaTypeHandler_GetMediaTypeCount(handler, NULL);
5234 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
5236 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, NULL, NULL);
5237 ok(hr == MF_E_UNEXPECTED, "Unexpected hr %#lx.\n", hr);
5239 count = 0;
5240 hr = IMFMediaTypeHandler_GetMediaTypeCount(handler, &count);
5241 ok(hr == S_OK, "Failed to get type count, hr %#lx.\n", hr);
5242 ok(count == 1, "Unexpected count %lu.\n", count);
5244 hr = IMFMediaTypeHandler_GetCurrentMediaType(handler, NULL);
5245 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
5247 media_type = (void *)0xdeadbeef;
5248 hr = IMFMediaTypeHandler_GetCurrentMediaType(handler, &media_type);
5249 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5250 ok(!media_type, "Unexpected pointer.\n");
5252 hr = MFCreateMediaType(&media_type);
5253 ok(hr == S_OK, "Failed to create media type, hr %#lx.\n", hr);
5255 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, media_type, NULL);
5256 ok(hr == MF_E_UNEXPECTED, "Unexpected hr %#lx.\n", hr);
5258 hr = IMFMediaTypeHandler_SetCurrentMediaType(handler, media_type);
5259 ok(hr == S_OK, "Failed to set current type, hr %#lx.\n", hr);
5261 hr = IMFMediaTypeHandler_GetMediaTypeByIndex(handler, 0, &media_type2);
5262 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5263 ok(media_type2 == media_type, "Unexpected type.\n");
5264 IMFMediaType_Release(media_type2);
5266 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, NULL, NULL);
5267 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
5269 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, media_type, NULL);
5270 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
5272 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, media_type, &media_type2);
5273 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
5275 hr = IMFMediaTypeHandler_GetMediaTypeByIndex(handler, 1, &media_type2);
5276 ok(hr == MF_E_NO_MORE_TYPES, "Unexpected hr %#lx.\n", hr);
5278 hr = IMFMediaTypeHandler_GetCurrentMediaType(handler, &media_type2);
5279 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5280 ok(media_type == media_type2, "Unexpected pointer.\n");
5281 IMFMediaType_Release(media_type2);
5283 hr = IMFMediaTypeHandler_GetMajorType(handler, &guid);
5284 ok(hr == MF_E_ATTRIBUTENOTFOUND, "Unexpected hr %#lx.\n", hr);
5286 hr = IMFMediaType_SetGUID(media_type, &MF_MT_MAJOR_TYPE, &MFMediaType_Video);
5287 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
5289 hr = IMFMediaTypeHandler_GetMajorType(handler, &guid);
5290 ok(hr == S_OK, "Failed to get major type, hr %#lx.\n", hr);
5291 ok(IsEqualGUID(&guid, &MFMediaType_Video), "Unexpected major type.\n");
5293 hr = MFCreateMediaType(&media_type3);
5294 ok(hr == S_OK, "Failed to create media type, hr %#lx.\n", hr);
5296 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, media_type3, NULL);
5297 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
5299 hr = IMFMediaType_SetGUID(media_type3, &MF_MT_MAJOR_TYPE, &MFMediaType_Audio);
5300 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
5302 /* Different major types. */
5303 media_type2 = (void *)0xdeadbeef;
5304 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, media_type3, &media_type2);
5305 ok(hr == E_FAIL, "Unexpected hr %#lx.\n", hr);
5306 ok(!media_type2, "Unexpected pointer.\n");
5308 hr = IMFMediaType_SetGUID(media_type3, &MF_MT_MAJOR_TYPE, &MFMediaType_Video);
5309 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
5311 media_type2 = (void *)0xdeadbeef;
5312 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, media_type3, &media_type2);
5313 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5314 ok(!media_type2, "Unexpected pointer.\n");
5316 /* Handler missing subtype. */
5317 hr = IMFMediaType_SetGUID(media_type3, &MF_MT_SUBTYPE, &MFVideoFormat_RGB8);
5318 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
5320 media_type2 = (void *)0xdeadbeef;
5321 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, media_type3, &media_type2);
5322 ok(hr == E_FAIL, "Unexpected hr %#lx.\n", hr);
5323 ok(!media_type2, "Unexpected pointer.\n");
5325 /* Different subtypes. */
5326 hr = IMFMediaType_SetGUID(media_type, &MF_MT_SUBTYPE, &MFVideoFormat_RGB24);
5327 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
5329 media_type2 = (void *)0xdeadbeef;
5330 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, media_type3, &media_type2);
5331 ok(hr == E_FAIL, "Unexpected hr %#lx.\n", hr);
5332 ok(!media_type2, "Unexpected pointer.\n");
5334 /* Same major/subtype. */
5335 hr = IMFMediaType_SetGUID(media_type3, &MF_MT_SUBTYPE, &MFVideoFormat_RGB24);
5336 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
5338 media_type2 = (void *)0xdeadbeef;
5339 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, media_type3, &media_type2);
5340 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5341 ok(!media_type2, "Unexpected pointer.\n");
5343 /* Set one more attribute. */
5344 hr = IMFMediaType_SetUINT64(media_type, &MF_MT_FRAME_SIZE, (UINT64)4 << 32 | 4);
5345 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
5347 media_type2 = (void *)0xdeadbeef;
5348 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, media_type3, &media_type2);
5349 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5350 ok(!media_type2, "Unexpected pointer.\n");
5352 ref = IMFMediaType_Release(media_type3);
5353 ok(ref == 0, "Release returned %ld\n", ref);
5355 hr = IMFMediaTypeHandler_SetCurrentMediaType(handler, NULL);
5356 ok(hr == S_OK, "Failed to set current type, hr %#lx.\n", hr);
5358 media_type2 = (void *)0xdeadbeef;
5359 hr = IMFMediaTypeHandler_GetCurrentMediaType(handler, &media_type2);
5360 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5361 ok(!media_type2, "Unexpected pointer.\n");
5363 hr = IMFMediaTypeHandler_GetMajorType(handler, &guid);
5364 ok(hr == MF_E_NOT_INITIALIZED, "Unexpected hr %#lx.\n", hr);
5366 ref = IMFMediaTypeHandler_Release(handler);
5367 ok(ref == 0, "Release returned %ld\n", ref);
5368 ref = IMFMediaType_Release(media_type);
5369 ok(ref == 0, "Release returned %ld\n", ref);
5372 static void test_MFGetSupportedMimeTypes(void)
5374 PROPVARIANT value;
5375 HRESULT hr;
5377 hr = MFGetSupportedMimeTypes(NULL);
5378 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
5380 value.vt = VT_EMPTY;
5381 hr = MFGetSupportedMimeTypes(&value);
5382 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5383 ok(value.vt == (VT_VECTOR | VT_LPWSTR), "Unexpected value type %#x.\n", value.vt);
5385 PropVariantClear(&value);
5388 static void test_MFGetSupportedSchemes(void)
5390 PROPVARIANT value;
5391 HRESULT hr;
5393 hr = MFGetSupportedSchemes(NULL);
5394 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
5396 value.vt = VT_EMPTY;
5397 hr = MFGetSupportedSchemes(&value);
5398 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5399 ok(value.vt == (VT_VECTOR | VT_LPWSTR), "Unexpected value type %#x.\n", value.vt);
5401 PropVariantClear(&value);
5404 static BOOL is_sample_copier_available_type(IMFMediaType *type)
5406 GUID major = { 0 };
5407 UINT32 count;
5408 HRESULT hr;
5410 hr = IMFMediaType_GetMajorType(type, &major);
5411 ok(hr == S_OK, "Failed to get major type, hr %#lx.\n", hr);
5413 hr = IMFMediaType_GetCount(type, &count);
5414 ok(hr == S_OK, "Failed to get attribute count, hr %#lx.\n", hr);
5415 ok(count == 1, "Unexpected attribute count %u.\n", count);
5417 return IsEqualGUID(&major, &MFMediaType_Video) || IsEqualGUID(&major, &MFMediaType_Audio);
5420 static void test_sample_copier(void)
5422 IMFAttributes *attributes, *attributes2;
5423 DWORD in_min, in_max, out_min, out_max;
5424 IMFMediaType *mediatype, *mediatype2;
5425 MFT_OUTPUT_STREAM_INFO output_info;
5426 IMFSample *sample, *client_sample;
5427 MFT_INPUT_STREAM_INFO input_info;
5428 DWORD input_count, output_count;
5429 MFT_OUTPUT_DATA_BUFFER buffer;
5430 IMFMediaBuffer *media_buffer;
5431 IMFTransform *copier;
5432 DWORD flags, status;
5433 UINT32 value, count;
5434 HRESULT hr;
5435 LONG ref;
5437 if (!pMFCreateSampleCopierMFT)
5439 win_skip("MFCreateSampleCopierMFT() is not available.\n");
5440 return;
5443 hr = pMFCreateSampleCopierMFT(&copier);
5444 ok(hr == S_OK, "Failed to create sample copier, hr %#lx.\n", hr);
5446 hr = IMFTransform_GetAttributes(copier, &attributes);
5447 ok(hr == S_OK, "Failed to get transform attributes, hr %#lx.\n", hr);
5448 hr = IMFTransform_GetAttributes(copier, &attributes2);
5449 ok(hr == S_OK, "Failed to get transform attributes, hr %#lx.\n", hr);
5450 ok(attributes == attributes2, "Unexpected instance.\n");
5451 IMFAttributes_Release(attributes2);
5452 hr = IMFAttributes_GetCount(attributes, &count);
5453 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5454 ok(count == 1, "Unexpected attribute count %u.\n", count);
5455 hr = IMFAttributes_GetUINT32(attributes, &MFT_SUPPORT_DYNAMIC_FORMAT_CHANGE, &value);
5456 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5457 ok(!!value, "Unexpected value %u.\n", value);
5458 ref = IMFAttributes_Release(attributes);
5459 ok(ref == 1, "Release returned %ld\n", ref);
5461 hr = IMFTransform_GetInputStreamAttributes(copier, 0, &attributes);
5462 ok(hr == E_NOTIMPL, "Unexpected hr %#lx.\n", hr);
5464 hr = IMFTransform_GetInputStreamAttributes(copier, 1, &attributes);
5465 ok(hr == E_NOTIMPL, "Unexpected hr %#lx.\n", hr);
5467 hr = IMFTransform_GetOutputStreamAttributes(copier, 0, &attributes);
5468 ok(hr == E_NOTIMPL, "Unexpected hr %#lx.\n", hr);
5470 hr = IMFTransform_GetOutputStreamAttributes(copier, 1, &attributes);
5471 ok(hr == E_NOTIMPL, "Unexpected hr %#lx.\n", hr);
5473 hr = IMFTransform_SetOutputBounds(copier, 0, 0);
5474 ok(hr == E_NOTIMPL, "Unexpected hr %#lx.\n", hr);
5476 /* No dynamic streams. */
5477 input_count = output_count = 0;
5478 hr = IMFTransform_GetStreamCount(copier, &input_count, &output_count);
5479 ok(hr == S_OK, "Failed to get stream count, hr %#lx.\n", hr);
5480 ok(input_count == 1 && output_count == 1, "Unexpected streams count.\n");
5482 hr = IMFTransform_GetStreamLimits(copier, &in_min, &in_max, &out_min, &out_max);
5483 ok(hr == S_OK, "Failed to get stream limits, hr %#lx.\n", hr);
5484 ok(in_min == in_max && in_min == 1 && out_min == out_max && out_min == 1, "Unexpected stream limits.\n");
5486 hr = IMFTransform_GetStreamIDs(copier, 1, &input_count, 1, &output_count);
5487 ok(hr == E_NOTIMPL, "Unexpected hr %#lx.\n", hr);
5489 hr = IMFTransform_DeleteInputStream(copier, 0);
5490 ok(hr == E_NOTIMPL, "Unexpected hr %#lx.\n", hr);
5492 /* Available types. */
5493 hr = IMFTransform_GetInputAvailableType(copier, 0, 0, &mediatype);
5494 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5495 ok(is_sample_copier_available_type(mediatype), "Unexpected type.\n");
5496 IMFMediaType_Release(mediatype);
5498 hr = IMFTransform_GetInputAvailableType(copier, 0, 1, &mediatype);
5499 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5500 ok(is_sample_copier_available_type(mediatype), "Unexpected type.\n");
5501 IMFMediaType_Release(mediatype);
5503 hr = IMFTransform_GetInputAvailableType(copier, 0, 2, &mediatype);
5504 ok(hr == MF_E_NO_MORE_TYPES, "Unexpected hr %#lx.\n", hr);
5506 hr = IMFTransform_GetInputAvailableType(copier, 1, 0, &mediatype);
5507 ok(hr == MF_E_INVALIDSTREAMNUMBER, "Unexpected hr %#lx.\n", hr);
5509 hr = IMFTransform_GetOutputAvailableType(copier, 0, 0, &mediatype);
5510 ok(hr == MF_E_NO_MORE_TYPES, "Unexpected hr %#lx.\n", hr);
5512 hr = IMFTransform_GetOutputAvailableType(copier, 1, 0, &mediatype);
5513 ok(hr == MF_E_INVALIDSTREAMNUMBER, "Unexpected hr %#lx.\n", hr);
5515 hr = IMFTransform_GetInputCurrentType(copier, 0, &mediatype);
5516 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "Unexpected hr %#lx.\n", hr);
5518 hr = IMFTransform_GetInputCurrentType(copier, 1, &mediatype);
5519 ok(hr == MF_E_INVALIDSTREAMNUMBER, "Unexpected hr %#lx.\n", hr);
5521 hr = IMFTransform_GetOutputCurrentType(copier, 0, &mediatype);
5522 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "Unexpected hr %#lx.\n", hr);
5524 hr = IMFTransform_GetOutputCurrentType(copier, 1, &mediatype);
5525 ok(hr == MF_E_INVALIDSTREAMNUMBER, "Unexpected hr %#lx.\n", hr);
5527 hr = MFCreateSample(&sample);
5528 ok(hr == S_OK, "Failed to create a sample, hr %#lx.\n", hr);
5530 hr = IMFTransform_ProcessInput(copier, 0, sample, 0);
5531 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "Unexpected hr %#lx.\n", hr);
5533 hr = MFCreateMediaType(&mediatype);
5534 ok(hr == S_OK, "Failed to create media type, hr %#lx.\n", hr);
5536 hr = IMFTransform_SetOutputType(copier, 0, mediatype, 0);
5537 ok(hr == MF_E_ATTRIBUTENOTFOUND, "Unexpected hr %#lx.\n", hr);
5539 hr = IMFMediaType_SetGUID(mediatype, &MF_MT_MAJOR_TYPE, &MFMediaType_Video);
5540 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
5542 hr = IMFMediaType_SetGUID(mediatype, &MF_MT_SUBTYPE, &MFVideoFormat_RGB8);
5543 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
5545 hr = IMFMediaType_SetUINT64(mediatype, &MF_MT_FRAME_SIZE, ((UINT64)16) << 32 | 16);
5546 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
5548 hr = IMFTransform_GetOutputStreamInfo(copier, 0, &output_info);
5549 ok(hr == S_OK, "Failed to get stream info, hr %#lx.\n", hr);
5550 ok(!output_info.dwFlags, "Unexpected flags %#lx.\n", output_info.dwFlags);
5551 ok(!output_info.cbSize, "Unexpected size %lu.\n", output_info.cbSize);
5552 ok(!output_info.cbAlignment, "Unexpected alignment %lu.\n", output_info.cbAlignment);
5554 hr = IMFTransform_GetInputStreamInfo(copier, 0, &input_info);
5555 ok(hr == S_OK, "Failed to get stream info, hr %#lx.\n", hr);
5557 ok(!input_info.hnsMaxLatency, "Unexpected latency %s.\n", wine_dbgstr_longlong(input_info.hnsMaxLatency));
5558 ok(!input_info.dwFlags, "Unexpected flags %#lx.\n", input_info.dwFlags);
5559 ok(!input_info.cbSize, "Unexpected size %lu.\n", input_info.cbSize);
5560 ok(!input_info.cbMaxLookahead, "Unexpected lookahead size %lu.\n", input_info.cbMaxLookahead);
5561 ok(!input_info.cbAlignment, "Unexpected alignment %lu.\n", input_info.cbAlignment);
5563 hr = IMFTransform_SetOutputType(copier, 0, mediatype, 0);
5564 ok(hr == S_OK, "Failed to set input type, hr %#lx.\n", hr);
5566 hr = IMFTransform_GetOutputStreamInfo(copier, 0, &output_info);
5567 ok(hr == S_OK, "Failed to get stream info, hr %#lx.\n", hr);
5568 ok(!output_info.dwFlags, "Unexpected flags %#lx.\n", output_info.dwFlags);
5569 ok(output_info.cbSize == 16 * 16, "Unexpected size %lu.\n", output_info.cbSize);
5570 ok(!output_info.cbAlignment, "Unexpected alignment %lu.\n", output_info.cbAlignment);
5572 hr = IMFTransform_GetOutputCurrentType(copier, 0, &mediatype2);
5573 ok(hr == S_OK, "Failed to get current type, hr %#lx.\n", hr);
5574 IMFMediaType_Release(mediatype2);
5576 hr = IMFTransform_GetInputCurrentType(copier, 0, &mediatype2);
5577 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "Unexpected hr %#lx.\n", hr);
5579 hr = IMFTransform_GetInputStatus(copier, 0, &flags);
5580 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "Unexpected hr %#lx.\n", hr);
5582 /* Setting input type resets output type. */
5583 hr = IMFTransform_GetOutputCurrentType(copier, 0, &mediatype2);
5584 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5585 IMFMediaType_Release(mediatype2);
5587 hr = IMFTransform_SetInputType(copier, 0, mediatype, 0);
5588 ok(hr == S_OK, "Failed to set input type, hr %#lx.\n", hr);
5590 hr = IMFTransform_GetOutputCurrentType(copier, 0, &mediatype2);
5591 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "Unexpected hr %#lx.\n", hr);
5593 hr = IMFTransform_GetInputAvailableType(copier, 0, 1, &mediatype2);
5594 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5595 ok(is_sample_copier_available_type(mediatype2), "Unexpected type.\n");
5596 IMFMediaType_Release(mediatype2);
5598 hr = IMFTransform_GetInputStreamInfo(copier, 0, &input_info);
5599 ok(hr == S_OK, "Failed to get stream info, hr %#lx.\n", hr);
5600 ok(!input_info.hnsMaxLatency, "Unexpected latency %s.\n", wine_dbgstr_longlong(input_info.hnsMaxLatency));
5601 ok(!input_info.dwFlags, "Unexpected flags %#lx.\n", input_info.dwFlags);
5602 ok(input_info.cbSize == 16 * 16, "Unexpected size %lu.\n", input_info.cbSize);
5603 ok(!input_info.cbMaxLookahead, "Unexpected lookahead size %lu.\n", input_info.cbMaxLookahead);
5604 ok(!input_info.cbAlignment, "Unexpected alignment %lu.\n", input_info.cbAlignment);
5606 hr = IMFTransform_GetOutputAvailableType(copier, 0, 0, &mediatype2);
5607 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5608 hr = IMFMediaType_IsEqual(mediatype2, mediatype, &flags);
5609 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5610 IMFMediaType_Release(mediatype2);
5612 hr = IMFTransform_GetInputStatus(copier, 0, &flags);
5613 ok(hr == S_OK, "Failed to get input status, hr %#lx.\n", hr);
5614 ok(flags == MFT_INPUT_STATUS_ACCEPT_DATA, "Unexpected flags %#lx.\n", flags);
5616 hr = IMFTransform_GetInputCurrentType(copier, 0, &mediatype2);
5617 ok(hr == S_OK, "Failed to get current type, hr %#lx.\n", hr);
5618 IMFMediaType_Release(mediatype2);
5620 hr = IMFTransform_GetOutputStatus(copier, &flags);
5621 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "Unexpected hr %#lx.\n", hr);
5623 hr = IMFTransform_SetOutputType(copier, 0, mediatype, 0);
5624 ok(hr == S_OK, "Failed to set output type, hr %#lx.\n", hr);
5626 hr = IMFTransform_GetOutputStatus(copier, &flags);
5627 ok(hr == S_OK, "Failed to get output status, hr %#lx.\n", hr);
5628 ok(!flags, "Unexpected flags %#lx.\n", flags);
5630 /* Pushing samples. */
5631 hr = MFCreateAlignedMemoryBuffer(output_info.cbSize, output_info.cbAlignment, &media_buffer);
5632 ok(hr == S_OK, "Failed to create media buffer, hr %#lx.\n", hr);
5634 hr = IMFSample_AddBuffer(sample, media_buffer);
5635 ok(hr == S_OK, "Failed to add a buffer, hr %#lx.\n", hr);
5636 IMFMediaBuffer_Release(media_buffer);
5638 EXPECT_REF(sample, 1);
5639 hr = IMFTransform_ProcessInput(copier, 0, sample, 0);
5640 ok(hr == S_OK, "Failed to process input, hr %#lx.\n", hr);
5641 EXPECT_REF(sample, 2);
5643 hr = IMFTransform_GetInputStatus(copier, 0, &flags);
5644 ok(hr == S_OK, "Failed to get input status, hr %#lx.\n", hr);
5645 ok(!flags, "Unexpected flags %#lx.\n", flags);
5647 hr = IMFTransform_GetOutputStatus(copier, &flags);
5648 ok(hr == S_OK, "Failed to get output status, hr %#lx.\n", hr);
5649 ok(flags == MFT_OUTPUT_STATUS_SAMPLE_READY, "Unexpected flags %#lx.\n", flags);
5651 hr = IMFTransform_ProcessInput(copier, 0, sample, 0);
5652 ok(hr == MF_E_NOTACCEPTING, "Unexpected hr %#lx.\n", hr);
5654 hr = IMFTransform_GetOutputStreamInfo(copier, 0, &output_info);
5655 ok(hr == S_OK, "Failed to get output info, hr %#lx.\n", hr);
5657 hr = MFCreateAlignedMemoryBuffer(output_info.cbSize, output_info.cbAlignment, &media_buffer);
5658 ok(hr == S_OK, "Failed to create media buffer, hr %#lx.\n", hr);
5660 hr = MFCreateSample(&client_sample);
5661 ok(hr == S_OK, "Failed to create a sample, hr %#lx.\n", hr);
5663 hr = IMFSample_AddBuffer(client_sample, media_buffer);
5664 ok(hr == S_OK, "Failed to add a buffer, hr %#lx.\n", hr);
5665 IMFMediaBuffer_Release(media_buffer);
5667 status = 0;
5668 memset(&buffer, 0, sizeof(buffer));
5669 buffer.pSample = client_sample;
5670 hr = IMFTransform_ProcessOutput(copier, 0, 1, &buffer, &status);
5671 ok(hr == S_OK, "Failed to get output, hr %#lx.\n", hr);
5672 EXPECT_REF(sample, 1);
5674 hr = IMFTransform_ProcessOutput(copier, 0, 1, &buffer, &status);
5675 ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "Failed to get output, hr %#lx.\n", hr);
5677 /* Flushing. */
5678 hr = IMFTransform_ProcessInput(copier, 0, sample, 0);
5679 ok(hr == S_OK, "Failed to process input, hr %#lx.\n", hr);
5680 EXPECT_REF(sample, 2);
5682 hr = IMFTransform_ProcessMessage(copier, MFT_MESSAGE_COMMAND_FLUSH, 0);
5683 ok(hr == S_OK, "Failed to flush, hr %#lx.\n", hr);
5685 ref = IMFSample_Release(sample);
5686 ok(ref == 0, "Release returned %ld\n", ref);
5687 ref = IMFSample_Release(client_sample);
5688 ok(ref == 0, "Release returned %ld\n", ref);
5690 ref = IMFTransform_Release(copier);
5691 ok(ref == 0, "Release returned %ld\n", ref);
5692 ref = IMFMediaType_Release(mediatype);
5693 ok(ref == 0, "Release returned %ld\n", ref);
5696 struct sample_metadata
5698 unsigned int flags;
5699 LONGLONG duration;
5700 LONGLONG time;
5703 static void sample_copier_process(IMFTransform *copier, IMFMediaBuffer *input_buffer,
5704 IMFMediaBuffer *output_buffer, const struct sample_metadata *md)
5706 static const struct sample_metadata zero_md = { 0, ~0u, ~0u };
5707 IMFSample *input_sample, *output_sample;
5708 MFT_OUTPUT_DATA_BUFFER buffer;
5709 DWORD flags, status;
5710 LONGLONG time;
5711 HRESULT hr;
5712 LONG ref;
5714 hr = MFCreateSample(&input_sample);
5715 ok(hr == S_OK, "Failed to create a sample, hr %#lx.\n", hr);
5717 if (md)
5719 hr = IMFSample_SetSampleFlags(input_sample, md->flags);
5720 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5722 hr = IMFSample_SetSampleTime(input_sample, md->time);
5723 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5725 hr = IMFSample_SetSampleDuration(input_sample, md->duration);
5726 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5729 hr = MFCreateSample(&output_sample);
5730 ok(hr == S_OK, "Failed to create a sample, hr %#lx.\n", hr);
5732 hr = IMFSample_SetSampleFlags(output_sample, ~0u);
5733 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5735 hr = IMFSample_SetSampleTime(output_sample, ~0u);
5736 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5738 hr = IMFSample_SetSampleDuration(output_sample, ~0u);
5739 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5741 hr = IMFSample_AddBuffer(input_sample, input_buffer);
5742 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5744 hr = IMFSample_AddBuffer(output_sample, output_buffer);
5745 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5747 hr = IMFTransform_ProcessInput(copier, 0, input_sample, 0);
5748 ok(hr == S_OK, "Failed to process input, hr %#lx.\n", hr);
5750 status = 0;
5751 memset(&buffer, 0, sizeof(buffer));
5752 buffer.pSample = output_sample;
5753 hr = IMFTransform_ProcessOutput(copier, 0, 1, &buffer, &status);
5754 ok(hr == S_OK, "Failed to get output, hr %#lx.\n", hr);
5756 if (!md) md = &zero_md;
5758 hr = IMFSample_GetSampleFlags(output_sample, &flags);
5759 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5760 ok(md->flags == flags, "Unexpected flags.\n");
5761 hr = IMFSample_GetSampleTime(output_sample, &time);
5762 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5763 ok(md->time == time, "Unexpected time.\n");
5764 hr = IMFSample_GetSampleDuration(output_sample, &time);
5765 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5766 ok(md->duration == time, "Unexpected duration.\n");
5768 ref = IMFSample_Release(input_sample);
5769 ok(ref == 0, "Release returned %ld\n", ref);
5770 ref = IMFSample_Release(output_sample);
5771 ok(ref == 0, "Release returned %ld\n", ref);
5774 static void test_sample_copier_output_processing(void)
5776 IMFMediaBuffer *input_buffer, *output_buffer;
5777 MFT_OUTPUT_STREAM_INFO output_info;
5778 struct sample_metadata md;
5779 IMFMediaType *mediatype;
5780 IMFTransform *copier;
5781 DWORD max_length;
5782 HRESULT hr;
5783 BYTE *ptr;
5784 LONG ref;
5786 if (!pMFCreateSampleCopierMFT)
5787 return;
5789 hr = pMFCreateSampleCopierMFT(&copier);
5790 ok(hr == S_OK, "Failed to create sample copier, hr %#lx.\n", hr);
5792 /* Configure for 16 x 16 of D3DFMT_X8R8G8B8. */
5793 hr = MFCreateMediaType(&mediatype);
5794 ok(hr == S_OK, "Failed to create media type, hr %#lx.\n", hr);
5796 hr = IMFMediaType_SetGUID(mediatype, &MF_MT_MAJOR_TYPE, &MFMediaType_Video);
5797 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
5799 hr = IMFMediaType_SetGUID(mediatype, &MF_MT_SUBTYPE, &MFVideoFormat_RGB32);
5800 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
5802 hr = IMFMediaType_SetUINT64(mediatype, &MF_MT_FRAME_SIZE, ((UINT64)16) << 32 | 16);
5803 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
5805 hr = IMFTransform_SetInputType(copier, 0, mediatype, 0);
5806 ok(hr == S_OK, "Failed to set input type, hr %#lx.\n", hr);
5808 hr = IMFTransform_SetOutputType(copier, 0, mediatype, 0);
5809 ok(hr == S_OK, "Failed to set input type, hr %#lx.\n", hr);
5811 /* Source and destination are linear buffers, destination is twice as large. */
5812 hr = IMFTransform_GetOutputStreamInfo(copier, 0, &output_info);
5813 ok(hr == S_OK, "Failed to get output info, hr %#lx.\n", hr);
5815 hr = MFCreateAlignedMemoryBuffer(output_info.cbSize, output_info.cbAlignment, &output_buffer);
5816 ok(hr == S_OK, "Failed to create media buffer, hr %#lx.\n", hr);
5818 hr = IMFMediaBuffer_Lock(output_buffer, &ptr, &max_length, NULL);
5819 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5820 memset(ptr, 0xcc, max_length);
5821 hr = IMFMediaBuffer_Unlock(output_buffer);
5822 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5824 hr = MFCreateAlignedMemoryBuffer(output_info.cbSize, output_info.cbAlignment, &input_buffer);
5825 ok(hr == S_OK, "Failed to create media buffer, hr %#lx.\n", hr);
5827 hr = IMFMediaBuffer_Lock(input_buffer, &ptr, &max_length, NULL);
5828 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5829 memset(ptr, 0xaa, max_length);
5830 hr = IMFMediaBuffer_Unlock(input_buffer);
5831 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5832 hr = IMFMediaBuffer_SetCurrentLength(input_buffer, 4);
5833 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5835 sample_copier_process(copier, input_buffer, output_buffer, NULL);
5837 hr = IMFMediaBuffer_Lock(output_buffer, &ptr, &max_length, NULL);
5838 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5839 ok(ptr[0] == 0xaa && ptr[4] == 0xcc, "Unexpected buffer contents.\n");
5841 hr = IMFMediaBuffer_Unlock(output_buffer);
5842 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5844 md.flags = 123;
5845 md.time = 10;
5846 md.duration = 2;
5847 sample_copier_process(copier, input_buffer, output_buffer, &md);
5849 ref = IMFMediaBuffer_Release(input_buffer);
5850 ok(ref == 0, "Release returned %ld\n", ref);
5851 ref = IMFMediaBuffer_Release(output_buffer);
5852 ok(ref == 0, "Release returned %ld\n", ref);
5854 ref = IMFTransform_Release(copier);
5855 ok(ref == 0, "Release returned %ld\n", ref);
5856 ref = IMFMediaType_Release(mediatype);
5857 ok(ref == 0, "Release returned %ld\n", ref);
5860 static void test_MFGetTopoNodeCurrentType(void)
5862 IMFMediaType *media_type, *media_type2;
5863 IMFTopologyNode *node;
5864 HRESULT hr;
5865 LONG ref;
5867 if (!pMFGetTopoNodeCurrentType)
5869 win_skip("MFGetTopoNodeCurrentType() is unsupported.\n");
5870 return;
5873 /* Tee node. */
5874 hr = MFCreateTopologyNode(MF_TOPOLOGY_TEE_NODE, &node);
5875 ok(hr == S_OK, "Failed to create a node, hr %#lx.\n", hr);
5877 hr = pMFGetTopoNodeCurrentType(node, 0, TRUE, &media_type);
5878 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
5880 hr = pMFGetTopoNodeCurrentType(node, 0, FALSE, &media_type);
5881 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
5883 hr = MFCreateMediaType(&media_type2);
5884 ok(hr == S_OK, "Failed to create media type, hr %#lx.\n", hr);
5886 hr = IMFMediaType_SetGUID(media_type2, &MF_MT_MAJOR_TYPE, &MFMediaType_Video);
5887 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
5889 /* Input type returned, if set. */
5890 hr = IMFTopologyNode_SetInputPrefType(node, 0, media_type2);
5891 ok(hr == S_OK, "Failed to set media type, hr %#lx.\n", hr);
5893 hr = pMFGetTopoNodeCurrentType(node, 0, FALSE, &media_type);
5894 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5895 ok(media_type == media_type2, "Unexpected pointer.\n");
5896 IMFMediaType_Release(media_type);
5898 hr = IMFTopologyNode_SetInputPrefType(node, 0, NULL);
5899 ok(hr == S_OK, "Failed to set media type, hr %#lx.\n", hr);
5901 hr = pMFGetTopoNodeCurrentType(node, 0, FALSE, &media_type);
5902 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
5904 /* Set second output. */
5905 hr = IMFTopologyNode_SetOutputPrefType(node, 1, media_type2);
5906 ok(hr == S_OK, "Failed to set media type, hr %#lx.\n", hr);
5908 hr = pMFGetTopoNodeCurrentType(node, 0, FALSE, &media_type);
5909 ok(hr == E_FAIL, "Unexpected hr %#lx.\n", hr);
5911 hr = IMFTopologyNode_SetOutputPrefType(node, 1, NULL);
5912 ok(hr == S_OK, "Failed to set media type, hr %#lx.\n", hr);
5914 /* Set first output. */
5915 hr = IMFTopologyNode_SetOutputPrefType(node, 0, media_type2);
5916 ok(hr == S_OK, "Failed to set media type, hr %#lx.\n", hr);
5918 hr = pMFGetTopoNodeCurrentType(node, 0, FALSE, &media_type);
5919 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5920 ok(media_type == media_type2, "Unexpected pointer.\n");
5921 IMFMediaType_Release(media_type);
5923 hr = IMFTopologyNode_SetOutputPrefType(node, 0, NULL);
5924 ok(hr == S_OK, "Failed to set media type, hr %#lx.\n", hr);
5926 /* Set primary output. */
5927 hr = IMFTopologyNode_SetOutputPrefType(node, 1, media_type2);
5928 ok(hr == S_OK, "Failed to set media type, hr %#lx.\n", hr);
5930 hr = IMFTopologyNode_SetUINT32(node, &MF_TOPONODE_PRIMARYOUTPUT, 1);
5931 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
5933 hr = pMFGetTopoNodeCurrentType(node, 0, FALSE, &media_type);
5934 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5935 ok(media_type == media_type2, "Unexpected pointer.\n");
5936 IMFMediaType_Release(media_type);
5938 hr = pMFGetTopoNodeCurrentType(node, 0, TRUE, &media_type);
5939 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5940 ok(media_type == media_type2, "Unexpected pointer.\n");
5941 IMFMediaType_Release(media_type);
5943 ref = IMFTopologyNode_Release(node);
5944 ok(ref == 0, "Release returned %ld\n", ref);
5945 ref = IMFMediaType_Release(media_type2);
5946 ok(ref == 0, "Release returned %ld\n", ref);
5949 static void init_functions(void)
5951 HMODULE mod = GetModuleHandleA("mf.dll");
5953 #define X(f) p##f = (void*)GetProcAddress(mod, #f)
5954 X(MFCreateSampleCopierMFT);
5955 X(MFGetTopoNodeCurrentType);
5956 #undef X
5959 static void test_MFRequireProtectedEnvironment(void)
5961 IMFPresentationDescriptor *pd;
5962 IMFMediaType *mediatype;
5963 IMFStreamDescriptor *sd;
5964 HRESULT hr;
5965 LONG ref;
5967 hr = MFCreateMediaType(&mediatype);
5968 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5970 hr = MFCreateStreamDescriptor(0, 1, &mediatype, &sd);
5971 ok(hr == S_OK, "Failed to create stream descriptor, hr %#lx.\n", hr);
5973 hr = MFCreatePresentationDescriptor(1, &sd, &pd);
5974 ok(hr == S_OK, "Failed to create presentation descriptor, hr %#lx.\n", hr);
5976 hr = IMFPresentationDescriptor_SelectStream(pd, 0);
5977 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5979 hr = MFRequireProtectedEnvironment(pd);
5980 ok(hr == S_FALSE, "Unexpected hr %#lx.\n", hr);
5982 hr = IMFStreamDescriptor_SetUINT32(sd, &MF_SD_PROTECTED, 1);
5983 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5985 hr = MFRequireProtectedEnvironment(pd);
5986 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5988 hr = IMFPresentationDescriptor_DeselectStream(pd, 0);
5989 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5991 hr = MFRequireProtectedEnvironment(pd);
5992 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5994 ref = IMFPresentationDescriptor_Release(pd);
5995 ok(ref == 0, "Release returned %ld\n", ref);
5996 ref = IMFStreamDescriptor_Release(sd);
5997 ok(ref == 0, "Release returned %ld\n", ref);
5998 ref = IMFMediaType_Release(mediatype);
5999 ok(ref == 0, "Release returned %ld\n", ref);
6002 static IMFSample *create_sample(const BYTE *data, ULONG size)
6004 IMFMediaBuffer *media_buffer;
6005 IMFSample *sample;
6006 DWORD length;
6007 BYTE *buffer;
6008 HRESULT hr;
6009 ULONG ret;
6011 hr = MFCreateSample(&sample);
6012 ok(hr == S_OK, "MFCreateSample returned %#lx\n", hr);
6013 hr = MFCreateMemoryBuffer(size, &media_buffer);
6014 ok(hr == S_OK, "MFCreateMemoryBuffer returned %#lx\n", hr);
6015 hr = IMFMediaBuffer_Lock(media_buffer, &buffer, NULL, &length);
6016 ok(hr == S_OK, "Lock returned %#lx\n", hr);
6017 ok(length == 0, "got length %lu\n", length);
6018 if (!data) memset(buffer, 0xcd, size);
6019 else memcpy(buffer, data, size);
6020 hr = IMFMediaBuffer_Unlock(media_buffer);
6021 ok(hr == S_OK, "Unlock returned %#lx\n", hr);
6022 hr = IMFMediaBuffer_SetCurrentLength(media_buffer, data ? size : 0);
6023 ok(hr == S_OK, "SetCurrentLength returned %#lx\n", hr);
6024 hr = IMFSample_AddBuffer(sample, media_buffer);
6025 ok(hr == S_OK, "AddBuffer returned %#lx\n", hr);
6026 ret = IMFMediaBuffer_Release(media_buffer);
6027 ok(ret == 1, "Release returned %lu\n", ret);
6029 return sample;
6032 #define check_sample(a, b, c) check_sample_(__LINE__, a, b, c)
6033 static void check_sample_(int line, IMFSample *sample, const BYTE *expect_buf, HANDLE output_file)
6035 IMFMediaBuffer *media_buffer;
6036 DWORD length;
6037 BYTE *buffer;
6038 HRESULT hr;
6039 ULONG ret;
6041 hr = IMFSample_ConvertToContiguousBuffer(sample, &media_buffer);
6042 ok_(__FILE__, line)(hr == S_OK, "ConvertToContiguousBuffer returned %#lx\n", hr);
6043 hr = IMFMediaBuffer_Lock(media_buffer, &buffer, NULL, &length);
6044 ok_(__FILE__, line)(hr == S_OK, "Lock returned %#lx\n", hr);
6045 ok_(__FILE__, line)(!memcmp(expect_buf, buffer, length), "unexpected buffer data\n");
6046 if (output_file) WriteFile(output_file, buffer, length, &length, NULL);
6047 hr = IMFMediaBuffer_Unlock(media_buffer);
6048 ok_(__FILE__, line)(hr == S_OK, "Unlock returned %#lx\n", hr);
6049 ret = IMFMediaBuffer_Release(media_buffer);
6050 ok_(__FILE__, line)(ret == 1, "Release returned %lu\n", ret);
6053 #define check_sample_rgb32(a, b, c) check_sample_rgb32_(__LINE__, a, b, c)
6054 static void check_sample_rgb32_(int line, IMFSample *sample, const BYTE *expect_buf, HANDLE output_file)
6056 DWORD i, length, diff = 0, max_diff;
6057 IMFMediaBuffer *media_buffer;
6058 BYTE *buffer;
6059 HRESULT hr;
6060 ULONG ret;
6062 hr = IMFSample_ConvertToContiguousBuffer(sample, &media_buffer);
6063 ok_(__FILE__, line)(hr == S_OK, "ConvertToContiguousBuffer returned %#lx\n", hr);
6064 hr = IMFMediaBuffer_Lock(media_buffer, &buffer, NULL, &length);
6065 ok_(__FILE__, line)(hr == S_OK, "Lock returned %#lx\n", hr);
6067 /* check that buffer values are "close" enough, there's some pretty big
6068 * differences with the color converter between ffmpeg and native.
6070 for (i = 0; i < length; i++)
6072 if (i % 4 == 3) continue; /* ignore alpha diff */
6073 diff += abs((int)expect_buf[i] - (int)buffer[i]);
6075 max_diff = length * 3 * 256;
6076 ok_(__FILE__, line)(diff * 100 / max_diff == 0, "unexpected buffer data\n");
6078 if (output_file) WriteFile(output_file, buffer, length, &length, NULL);
6079 hr = IMFMediaBuffer_Unlock(media_buffer);
6080 ok_(__FILE__, line)(hr == S_OK, "Unlock returned %#lx\n", hr);
6081 ret = IMFMediaBuffer_Release(media_buffer);
6082 ok_(__FILE__, line)(ret == 1, "Release returned %lu\n", ret);
6085 #define check_sample_pcm16(a, b, c, d) check_sample_pcm16_(__LINE__, a, b, c, d)
6086 static void check_sample_pcm16_(int line, IMFSample *sample, const BYTE *expect_buf, HANDLE output_file, BOOL todo)
6088 IMFMediaBuffer *media_buffer;
6089 DWORD i, length;
6090 BYTE *buffer;
6091 HRESULT hr;
6092 ULONG ret;
6094 hr = IMFSample_ConvertToContiguousBuffer(sample, &media_buffer);
6095 ok_(__FILE__, line)(hr == S_OK, "ConvertToContiguousBuffer returned %#lx\n", hr);
6096 hr = IMFMediaBuffer_Lock(media_buffer, &buffer, NULL, &length);
6097 ok_(__FILE__, line)(hr == S_OK, "Lock returned %#lx\n", hr);
6099 /* check that buffer values are close enough, there's some differences in
6100 * the output of audio DSP between 32bit and 64bit implementation
6102 for (i = 0; i < length; i += 2)
6104 DWORD expect = *(INT16 *)(expect_buf + i), value = *(INT16 *)(buffer + i);
6105 if (expect - value + 512 > 1024) break;
6108 todo_wine_if(todo)
6109 ok_(__FILE__, line)(i == length, "unexpected buffer data\n");
6111 if (output_file) WriteFile(output_file, buffer, length, &length, NULL);
6112 hr = IMFMediaBuffer_Unlock(media_buffer);
6113 ok_(__FILE__, line)(hr == S_OK, "Unlock returned %#lx\n", hr);
6114 ret = IMFMediaBuffer_Release(media_buffer);
6115 ok_(__FILE__, line)(ret == 1, "Release returned %lu\n", ret);
6118 static const BYTE wma_codec_data[10] = {0, 0x44, 0, 0, 0x17, 0, 0, 0, 0, 0};
6119 static const ULONG wmaenc_block_size = 1487;
6120 static const ULONG wmadec_block_size = 0x2000;
6122 static void test_wma_encoder(void)
6124 const GUID transform_inputs[] =
6126 MFAudioFormat_PCM,
6127 MFAudioFormat_Float,
6129 const GUID transform_outputs[] =
6131 MFAudioFormat_WMAudioV8,
6132 MFAudioFormat_WMAudioV9,
6133 MFAudioFormat_WMAudio_Lossless,
6135 const GUID dmo_inputs[] =
6137 MEDIASUBTYPE_PCM,
6139 const GUID dmo_outputs[] =
6141 MEDIASUBTYPE_WMAUDIO2,
6142 MEDIASUBTYPE_WMAUDIO3,
6143 MEDIASUBTYPE_WMAUDIO_LOSSLESS,
6146 static const struct attribute_desc input_type_desc[] =
6148 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
6149 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_Float),
6150 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 32),
6151 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 2),
6152 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 22050),
6153 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 176400),
6154 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 8),
6155 {0},
6157 const struct attribute_desc output_type_desc[] =
6159 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
6160 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_WMAudioV8),
6161 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 2),
6162 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 22050),
6163 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 4003),
6164 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, wmaenc_block_size),
6165 ATTR_BLOB(MF_MT_USER_DATA, wma_codec_data, sizeof(wma_codec_data)),
6166 {0},
6169 MFT_REGISTER_TYPE_INFO output_type = {MFMediaType_Audio, MFAudioFormat_WMAudioV8};
6170 MFT_REGISTER_TYPE_INFO input_type = {MFMediaType_Audio, MFAudioFormat_Float};
6171 ULONG audio_data_len, wmaenc_data_len;
6172 const BYTE *audio_data, *wmaenc_data;
6173 MFT_OUTPUT_STREAM_INFO output_info;
6174 MFT_INPUT_STREAM_INFO input_info;
6175 MFT_OUTPUT_DATA_BUFFER output;
6176 WCHAR output_path[MAX_PATH];
6177 IMFMediaType *media_type;
6178 IMFTransform *transform;
6179 DWORD status, length;
6180 HANDLE output_file;
6181 IMFSample *sample;
6182 HRSRC resource;
6183 GUID class_id;
6184 ULONG i, ret;
6185 HRESULT hr;
6186 LONG ref;
6188 hr = CoInitialize(NULL);
6189 ok(hr == S_OK, "Failed to initialize, hr %#lx.\n", hr);
6191 if (!create_transform(MFT_CATEGORY_AUDIO_ENCODER, &input_type, &output_type, L"WMAudio Encoder MFT", &MFMediaType_Audio,
6192 transform_inputs, ARRAY_SIZE(transform_inputs), transform_outputs, ARRAY_SIZE(transform_outputs),
6193 &transform, &CLSID_CWMAEncMediaObject, &class_id))
6194 goto failed;
6196 check_dmo(&class_id, L"WMAudio Encoder DMO", &MEDIATYPE_Audio, dmo_inputs, ARRAY_SIZE(dmo_inputs),
6197 dmo_outputs, ARRAY_SIZE(dmo_outputs));
6199 check_interface(transform, &IID_IMFTransform, TRUE);
6200 check_interface(transform, &IID_IMediaObject, TRUE);
6201 check_interface(transform, &IID_IPropertyStore, TRUE);
6202 check_interface(transform, &IID_IPropertyBag, TRUE);
6204 hr = MFCreateMediaType(&media_type);
6205 ok(hr == S_OK, "MFCreateMediaType returned %#lx\n", hr);
6206 init_media_type(media_type, input_type_desc, -1);
6207 hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
6208 ok(hr == S_OK, "SetInputType returned %#lx.\n", hr);
6209 init_media_type(media_type, output_type_desc, -1);
6210 hr = IMFTransform_SetOutputType(transform, 0, media_type, 0);
6211 ok(hr == S_OK, "SetOutputType returned %#lx.\n", hr);
6212 ret = IMFMediaType_Release(media_type);
6213 ok(ret == 0, "Release returned %lu\n", ret);
6215 memset(&input_info, 0xcd, sizeof(input_info));
6216 hr = IMFTransform_GetInputStreamInfo(transform, 0, &input_info);
6217 ok(hr == S_OK, "GetInputStreamInfo returned %#lx\n", hr);
6218 ok(input_info.hnsMaxLatency == 19969161, "got hnsMaxLatency %s\n",
6219 wine_dbgstr_longlong(input_info.hnsMaxLatency));
6220 ok(input_info.dwFlags == 0, "got dwFlags %#lx\n", input_info.dwFlags);
6221 ok(input_info.cbSize == 8, "got cbSize %lu\n", input_info.cbSize);
6222 ok(input_info.cbMaxLookahead == 0, "got cbMaxLookahead %#lx\n", input_info.cbMaxLookahead);
6223 ok(input_info.cbAlignment == 1, "got cbAlignment %#lx\n", input_info.cbAlignment);
6225 memset(&output_info, 0xcd, sizeof(output_info));
6226 hr = IMFTransform_GetOutputStreamInfo(transform, 0, &output_info);
6227 ok(hr == S_OK, "GetOutputStreamInfo returned %#lx\n", hr);
6228 ok(output_info.dwFlags == 0, "got dwFlags %#lx\n", output_info.dwFlags);
6229 ok(output_info.cbSize == wmaenc_block_size, "got cbSize %#lx\n", output_info.cbSize);
6230 ok(output_info.cbAlignment == 1, "got cbAlignment %#lx\n", output_info.cbAlignment);
6232 resource = FindResourceW(NULL, L"audiodata.bin", (const WCHAR *)RT_RCDATA);
6233 ok(resource != 0, "FindResourceW failed, error %lu\n", GetLastError());
6234 audio_data = LockResource(LoadResource(GetModuleHandleW(NULL), resource));
6235 audio_data_len = SizeofResource(GetModuleHandleW(NULL), resource);
6236 ok(audio_data_len == 179928, "got length %lu\n", audio_data_len);
6238 sample = create_sample(audio_data, audio_data_len);
6239 hr = IMFSample_SetSampleTime(sample, 0);
6240 ok(hr == S_OK, "SetSampleTime returned %#lx\n", hr);
6241 hr = IMFSample_SetSampleDuration(sample, 10000000);
6242 ok(hr == S_OK, "SetSampleDuration returned %#lx\n", hr);
6243 hr = IMFTransform_ProcessInput(transform, 0, sample, 0);
6244 ok(hr == S_OK, "ProcessInput returned %#lx\n", hr);
6245 hr = IMFTransform_ProcessMessage(transform, MFT_MESSAGE_COMMAND_DRAIN, 0);
6246 ok(hr == S_OK, "ProcessMessage returned %#lx\n", hr);
6247 hr = IMFTransform_ProcessInput(transform, 0, sample, 0);
6248 ok(hr == MF_E_NOTACCEPTING, "ProcessInput returned %#lx\n", hr);
6249 ref = IMFSample_Release(sample);
6250 ok(ref <= 1, "Release returned %ld\n", ref);
6252 status = 0xdeadbeef;
6253 sample = create_sample(NULL, output_info.cbSize);
6254 memset(&output, 0, sizeof(output));
6255 output.pSample = sample;
6257 resource = FindResourceW(NULL, L"wmaencdata.bin", (const WCHAR *)RT_RCDATA);
6258 ok(resource != 0, "FindResourceW failed, error %lu\n", GetLastError());
6259 wmaenc_data = LockResource(LoadResource(GetModuleHandleW(NULL), resource));
6260 wmaenc_data_len = SizeofResource(GetModuleHandleW(NULL), resource);
6261 ok(wmaenc_data_len % wmaenc_block_size == 0, "got length %lu\n", wmaenc_data_len);
6263 /* and generate a new one as well in a temporary directory */
6264 GetTempPathW(ARRAY_SIZE(output_path), output_path);
6265 lstrcatW(output_path, L"wmaencdata.bin");
6266 output_file = CreateFileW(output_path, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0);
6267 ok(output_file != INVALID_HANDLE_VALUE, "CreateFileW failed, error %lu\n", GetLastError());
6269 i = 0;
6270 while (SUCCEEDED(hr = IMFTransform_ProcessOutput(transform, 0, 1, &output, &status)))
6272 winetest_push_context("%lu", i);
6273 ok(hr == S_OK, "ProcessOutput returned %#lx\n", hr);
6274 ok(output.pSample == sample, "got pSample %p\n", output.pSample);
6275 ok(output.dwStatus == MFT_OUTPUT_DATA_BUFFER_INCOMPLETE ||
6276 broken(output.dwStatus == (MFT_OUTPUT_DATA_BUFFER_INCOMPLETE|7)) /* win7 */,
6277 "got dwStatus %#lx\n", output.dwStatus);
6278 ok(status == 0, "got status %#lx\n", status);
6279 hr = IMFSample_GetTotalLength(sample, &length);
6280 ok(hr == S_OK, "GetTotalLength returned %#lx\n", hr);
6281 ok(length == wmaenc_block_size, "got length %lu\n", length);
6282 ok(wmaenc_data_len > i * wmaenc_block_size, "got %lu blocks\n", i);
6283 check_sample(sample, wmaenc_data + i * wmaenc_block_size, output_file);
6284 winetest_pop_context();
6285 i++;
6288 trace("created %s\n", debugstr_w(output_path));
6289 CloseHandle(output_file);
6291 ret = IMFSample_Release(sample);
6292 ok(ret == 0, "Release returned %lu\n", ret);
6294 status = 0xdeadbeef;
6295 sample = create_sample(NULL, output_info.cbSize);
6296 memset(&output, 0, sizeof(output));
6297 output.pSample = sample;
6298 hr = IMFTransform_ProcessOutput(transform, 0, 1, &output, &status);
6299 ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "ProcessOutput returned %#lx\n", hr);
6300 ok(output.pSample == sample, "got pSample %p\n", output.pSample);
6301 ok(output.dwStatus == 0, "got dwStatus %#lx\n", output.dwStatus);
6302 ok(status == 0, "got status %#lx\n", status);
6303 hr = IMFSample_GetTotalLength(sample, &length);
6304 ok(hr == S_OK, "GetTotalLength returned %#lx\n", hr);
6305 ok(length == 0, "got length %lu\n", length);
6306 ret = IMFSample_Release(sample);
6307 ok(ret == 0, "Release returned %lu\n", ret);
6309 ret = IMFTransform_Release(transform);
6310 ok(ret == 0, "Release returned %lu\n", ret);
6312 failed:
6313 CoUninitialize();
6316 static void test_wma_decoder(void)
6318 const GUID transform_inputs[] =
6320 MEDIASUBTYPE_MSAUDIO1,
6321 MFAudioFormat_WMAudioV8,
6322 MFAudioFormat_WMAudioV9,
6323 MFAudioFormat_WMAudio_Lossless,
6325 const GUID transform_outputs[] =
6327 MFAudioFormat_PCM,
6328 MFAudioFormat_Float,
6330 const GUID dmo_inputs[] =
6332 MEDIASUBTYPE_MSAUDIO1,
6333 MEDIASUBTYPE_WMAUDIO2,
6334 MEDIASUBTYPE_WMAUDIO3,
6335 MEDIASUBTYPE_WMAUDIO_LOSSLESS,
6337 const GUID dmo_outputs[] =
6339 MEDIASUBTYPE_PCM,
6340 MEDIASUBTYPE_IEEE_FLOAT,
6343 static const media_type_desc expect_available_inputs[] =
6346 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
6347 ATTR_GUID(MF_MT_SUBTYPE, MEDIASUBTYPE_MSAUDIO1),
6348 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
6351 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
6352 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_WMAudioV8),
6353 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
6356 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
6357 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_WMAudioV9),
6358 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
6361 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
6362 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_WMAudio_Lossless),
6363 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
6366 static const media_type_desc expect_available_outputs[] =
6369 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
6370 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_Float),
6371 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 32),
6372 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 2),
6373 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 22050),
6374 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 176400),
6375 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 8),
6376 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
6377 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
6378 ATTR_UINT32(MF_MT_AUDIO_PREFER_WAVEFORMATEX, 1),
6381 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
6382 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_PCM),
6383 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 16),
6384 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 2),
6385 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 22050),
6386 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 88200),
6387 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 4),
6388 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
6389 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
6390 ATTR_UINT32(MF_MT_AUDIO_PREFER_WAVEFORMATEX, 1),
6394 const struct attribute_desc input_type_desc[] =
6396 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
6397 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_WMAudioV8),
6398 ATTR_BLOB(MF_MT_USER_DATA, wma_codec_data, sizeof(wma_codec_data)),
6399 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, wmaenc_block_size),
6400 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 22050),
6401 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 2),
6402 {0},
6404 static const struct attribute_desc output_type_desc[] =
6406 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
6407 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_PCM),
6408 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 88200),
6409 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 16),
6410 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 2),
6411 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 22050),
6412 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 4),
6413 {0},
6416 MFT_REGISTER_TYPE_INFO input_type = {MFMediaType_Audio, MFAudioFormat_WMAudioV8};
6417 MFT_REGISTER_TYPE_INFO output_type = {MFMediaType_Audio, MFAudioFormat_Float};
6418 IUnknown *unknown, *tmp_unknown, outer = {&test_unk_vtbl};
6419 ULONG wmadec_data_len, wmaenc_data_len;
6420 const BYTE *wmadec_data, *wmaenc_data;
6421 MFT_OUTPUT_STREAM_INFO output_info;
6422 MFT_OUTPUT_DATA_BUFFER outputs[2];
6423 MFT_INPUT_STREAM_INFO input_info;
6424 MFT_OUTPUT_DATA_BUFFER output;
6425 DWORD status, flags, length;
6426 WCHAR output_path[MAX_PATH];
6427 IMediaObject *media_object;
6428 IPropertyBag *property_bag;
6429 IMFMediaType *media_type;
6430 IMFTransform *transform;
6431 LONGLONG time, duration;
6432 HANDLE output_file;
6433 IMFSample *sample;
6434 ULONG i, ret, ref;
6435 HRSRC resource;
6436 GUID class_id;
6437 UINT32 value;
6438 HRESULT hr;
6440 hr = CoInitialize(NULL);
6441 ok(hr == S_OK, "Failed to initialize, hr %#lx.\n", hr);
6443 if (!create_transform(MFT_CATEGORY_AUDIO_DECODER, &input_type, &output_type, L"WMAudio Decoder MFT", &MFMediaType_Audio,
6444 transform_inputs, ARRAY_SIZE(transform_inputs), transform_outputs, ARRAY_SIZE(transform_outputs),
6445 &transform, &CLSID_CWMADecMediaObject, &class_id))
6446 goto failed;
6448 check_dmo(&class_id, L"WMAudio Decoder DMO", &MEDIATYPE_Audio, dmo_inputs, ARRAY_SIZE(dmo_inputs),
6449 dmo_outputs, ARRAY_SIZE(dmo_outputs));
6451 check_interface(transform, &IID_IMFTransform, TRUE);
6452 check_interface(transform, &IID_IMediaObject, TRUE);
6453 todo_wine
6454 check_interface(transform, &IID_IPropertyStore, TRUE);
6455 check_interface(transform, &IID_IPropertyBag, TRUE);
6457 /* check default media types */
6459 hr = IMFTransform_GetInputStreamInfo(transform, 0, &input_info);
6460 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "GetInputStreamInfo returned %#lx\n", hr);
6461 hr = IMFTransform_GetOutputStreamInfo(transform, 0, &output_info);
6462 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "GetOutputStreamInfo returned %#lx\n", hr);
6463 hr = IMFTransform_GetOutputAvailableType(transform, 0, 0, &media_type);
6464 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "GetOutputAvailableType returned %#lx\n", hr);
6466 i = -1;
6467 while (SUCCEEDED(hr = IMFTransform_GetInputAvailableType(transform, 0, ++i, &media_type)))
6469 winetest_push_context("in %lu", i);
6470 ok(hr == S_OK, "GetInputAvailableType returned %#lx\n", hr);
6471 check_media_type(media_type, expect_available_inputs[i], -1);
6472 hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
6473 ok(hr == MF_E_INVALIDMEDIATYPE, "SetInputType returned %#lx.\n", hr);
6474 ret = IMFMediaType_Release(media_type);
6475 ok(ret == 0, "Release returned %lu\n", ret);
6476 winetest_pop_context();
6478 todo_wine
6479 ok(hr == MF_E_NO_MORE_TYPES, "GetInputAvailableType returned %#lx\n", hr);
6480 todo_wine
6481 ok(i == 4, "%lu input media types\n", i);
6483 /* setting output media type first doesn't work */
6485 hr = MFCreateMediaType(&media_type);
6486 ok(hr == S_OK, "MFCreateMediaType returned %#lx\n", hr);
6487 init_media_type(media_type, output_type_desc, -1);
6488 hr = IMFTransform_SetOutputType(transform, 0, media_type, 0);
6489 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "SetOutputType returned %#lx.\n", hr);
6490 ret = IMFMediaType_Release(media_type);
6491 ok(ret == 0, "Release returned %lu\n", ret);
6493 /* check required input media type attributes */
6495 hr = MFCreateMediaType(&media_type);
6496 ok(hr == S_OK, "MFCreateMediaType returned %#lx\n", hr);
6497 hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
6498 ok(hr == MF_E_ATTRIBUTENOTFOUND, "SetInputType returned %#lx.\n", hr);
6499 init_media_type(media_type, input_type_desc, 1);
6500 hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
6501 ok(hr == MF_E_ATTRIBUTENOTFOUND, "SetInputType returned %#lx.\n", hr);
6502 init_media_type(media_type, input_type_desc, 2);
6503 for (i = 2; i < ARRAY_SIZE(input_type_desc) - 1; ++i)
6505 hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
6506 ok(hr == MF_E_INVALIDMEDIATYPE, "SetInputType returned %#lx.\n", hr);
6507 init_media_type(media_type, input_type_desc, i + 1);
6509 hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
6510 ok(hr == S_OK, "SetInputType returned %#lx.\n", hr);
6511 ret = IMFMediaType_Release(media_type);
6512 ok(ret == 0, "Release returned %lu\n", ret);
6514 hr = IMFTransform_GetInputStreamInfo(transform, 0, &input_info);
6515 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "GetInputStreamInfo returned %#lx\n", hr);
6516 hr = IMFTransform_GetOutputStreamInfo(transform, 0, &output_info);
6517 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "GetOutputStreamInfo returned %#lx\n", hr);
6519 /* check new output media types */
6521 i = -1;
6522 while (SUCCEEDED(hr = IMFTransform_GetOutputAvailableType(transform, 0, ++i, &media_type)))
6524 winetest_push_context("out %lu", i);
6525 ok(hr == S_OK, "GetOutputAvailableType returned %#lx\n", hr);
6526 check_media_type(media_type, expect_available_outputs[i], -1);
6527 ret = IMFMediaType_Release(media_type);
6528 ok(ret == 0, "Release returned %lu\n", ret);
6529 winetest_pop_context();
6531 ok(hr == MF_E_NO_MORE_TYPES, "GetOutputAvailableType returned %#lx\n", hr);
6532 ok(i == 2, "%lu output media types\n", i);
6534 /* check required output media type attributes */
6536 hr = MFCreateMediaType(&media_type);
6537 ok(hr == S_OK, "MFCreateMediaType returned %#lx\n", hr);
6538 hr = IMFTransform_SetOutputType(transform, 0, media_type, 0);
6539 ok(hr == MF_E_ATTRIBUTENOTFOUND, "SetOutputType returned %#lx.\n", hr);
6540 init_media_type(media_type, output_type_desc, 1);
6541 hr = IMFTransform_SetOutputType(transform, 0, media_type, 0);
6542 ok(hr == MF_E_ATTRIBUTENOTFOUND, "SetOutputType returned %#lx.\n", hr);
6543 init_media_type(media_type, output_type_desc, 2);
6544 for (i = 2; i < ARRAY_SIZE(output_type_desc) - 1; ++i)
6546 hr = IMFTransform_SetOutputType(transform, 0, media_type, 0);
6547 ok(hr == MF_E_INVALIDMEDIATYPE, "SetOutputType returned %#lx.\n", hr);
6548 init_media_type(media_type, output_type_desc, i + 1);
6550 hr = IMFTransform_SetOutputType(transform, 0, media_type, 0);
6551 ok(hr == S_OK, "SetOutputType returned %#lx.\n", hr);
6552 ret = IMFMediaType_Release(media_type);
6553 ok(ret == 0, "Release returned %lu\n", ret);
6555 memset(&input_info, 0xcd, sizeof(input_info));
6556 hr = IMFTransform_GetInputStreamInfo(transform, 0, &input_info);
6557 ok(hr == S_OK, "GetInputStreamInfo returned %#lx\n", hr);
6558 ok(input_info.hnsMaxLatency == 0, "got hnsMaxLatency %s\n", wine_dbgstr_longlong(input_info.hnsMaxLatency));
6559 ok(input_info.dwFlags == 0, "got dwFlags %#lx\n", input_info.dwFlags);
6560 ok(input_info.cbSize == wmaenc_block_size, "got cbSize %lu\n", input_info.cbSize);
6561 ok(input_info.cbMaxLookahead == 0, "got cbMaxLookahead %#lx\n", input_info.cbMaxLookahead);
6562 ok(input_info.cbAlignment == 1, "got cbAlignment %#lx\n", input_info.cbAlignment);
6564 memset(&output_info, 0xcd, sizeof(output_info));
6565 hr = IMFTransform_GetOutputStreamInfo(transform, 0, &output_info);
6566 ok(hr == S_OK, "GetOutputStreamInfo returned %#lx\n", hr);
6567 ok(output_info.dwFlags == 0, "got dwFlags %#lx\n", output_info.dwFlags);
6568 todo_wine
6569 ok(output_info.cbSize == 0, "got cbSize %#lx\n", output_info.cbSize);
6570 ok(output_info.cbAlignment == 1, "got cbAlignment %#lx\n", output_info.cbAlignment);
6572 /* MF_MT_AUDIO_AVG_BYTES_PER_SECOND isn't required by SetInputType, but is needed for the transform to work */
6574 hr = MFCreateMediaType(&media_type);
6575 ok(hr == S_OK, "MFCreateMediaType returned %#lx\n", hr);
6576 init_media_type(media_type, input_type_desc, -1);
6577 hr = IMFMediaType_SetUINT32(media_type, &MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 4003);
6578 ok(hr == S_OK, "SetUINT32 returned %#lx\n", hr);
6579 hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
6580 ok(hr == S_OK, "SetInputType returned %#lx.\n", hr);
6582 hr = IMFTransform_GetOutputStreamInfo(transform, 0, &output_info);
6583 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "GetOutputStreamInfo returned %#lx\n", hr);
6585 init_media_type(media_type, output_type_desc, -1);
6586 hr = IMFTransform_SetOutputType(transform, 0, media_type, 0);
6587 ok(hr == S_OK, "SetInputType returned %#lx.\n", hr);
6588 ret = IMFMediaType_Release(media_type);
6589 ok(ret == 0, "Release returned %lu\n", ret);
6591 memset(&output_info, 0xcd, sizeof(output_info));
6592 hr = IMFTransform_GetOutputStreamInfo(transform, 0, &output_info);
6593 ok(hr == S_OK, "GetOutputStreamInfo returned %#lx\n", hr);
6594 ok(output_info.dwFlags == 0, "got dwFlags %#lx\n", output_info.dwFlags);
6595 ok(output_info.cbSize == wmadec_block_size, "got cbSize %#lx\n", output_info.cbSize);
6596 ok(output_info.cbAlignment == 1, "got cbAlignment %#lx\n", output_info.cbAlignment);
6598 resource = FindResourceW(NULL, L"wmaencdata.bin", (const WCHAR *)RT_RCDATA);
6599 ok(resource != 0, "FindResourceW failed, error %lu\n", GetLastError());
6600 wmaenc_data = LockResource(LoadResource(GetModuleHandleW(NULL), resource));
6601 wmaenc_data_len = SizeofResource(GetModuleHandleW(NULL), resource);
6602 ok(wmaenc_data_len % wmaenc_block_size == 0, "got length %lu\n", wmaenc_data_len);
6604 sample = create_sample(wmaenc_data, wmaenc_block_size / 2);
6605 hr = IMFTransform_ProcessInput(transform, 0, sample, 0);
6606 ok(hr == S_OK, "ProcessInput returned %#lx\n", hr);
6607 ret = IMFSample_Release(sample);
6608 ok(ret == 0, "Release returned %lu\n", ret);
6609 sample = create_sample(wmaenc_data, wmaenc_block_size + 1);
6610 hr = IMFTransform_ProcessInput(transform, 0, sample, 0);
6611 ok(hr == S_OK, "ProcessInput returned %#lx\n", hr);
6612 ret = IMFSample_Release(sample);
6613 ok(ret == 0, "Release returned %lu\n", ret);
6614 sample = create_sample(wmaenc_data, wmaenc_block_size);
6615 hr = IMFTransform_ProcessInput(transform, 0, sample, 0);
6616 ok(hr == S_OK, "ProcessInput returned %#lx\n", hr);
6617 hr = IMFTransform_ProcessInput(transform, 0, sample, 0);
6618 ok(hr == MF_E_NOTACCEPTING, "ProcessInput returned %#lx\n", hr);
6619 ret = IMFSample_Release(sample);
6620 ok(ret == 1, "Release returned %lu\n", ret);
6622 /* As output_info.dwFlags doesn't have MFT_OUTPUT_STREAM_CAN_PROVIDE_SAMPLES
6623 * IMFTransform_ProcessOutput needs a sample or returns MF_E_TRANSFORM_NEED_MORE_INPUT */
6625 status = 0xdeadbeef;
6626 memset(&output, 0, sizeof(output));
6627 hr = IMFTransform_ProcessOutput(transform, 0, 1, &output, &status);
6628 ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "ProcessOutput returned %#lx\n", hr);
6629 ok(output.dwStreamID == 0, "got dwStreamID %lu\n", output.dwStreamID);
6630 ok(!output.pSample, "got pSample %p\n", output.pSample);
6631 ok(output.dwStatus == MFT_OUTPUT_DATA_BUFFER_NO_SAMPLE ||
6632 broken(output.dwStatus == (MFT_OUTPUT_DATA_BUFFER_INCOMPLETE|MFT_OUTPUT_DATA_BUFFER_NO_SAMPLE)) /* Win7 */,
6633 "got dwStatus %#lx\n", output.dwStatus);
6634 ok(!output.pEvents, "got pEvents %p\n", output.pEvents);
6635 ok(status == 0, "got status %#lx\n", status);
6637 sample = create_sample(wmaenc_data, wmaenc_block_size);
6638 hr = IMFTransform_ProcessInput(transform, 0, sample, 0);
6639 ok(hr == MF_E_NOTACCEPTING, "ProcessInput returned %#lx\n", hr);
6640 ret = IMFSample_Release(sample);
6641 ok(ret == 0, "Release returned %lu\n", ret);
6643 status = 0xdeadbeef;
6644 memset(&output, 0, sizeof(output));
6645 hr = IMFTransform_ProcessOutput(transform, 0, 1, &output, &status);
6646 ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "ProcessOutput returned %#lx\n", hr);
6647 ok(!output.pSample, "got pSample %p\n", output.pSample);
6648 ok(output.dwStatus == MFT_OUTPUT_DATA_BUFFER_NO_SAMPLE ||
6649 broken(output.dwStatus == (MFT_OUTPUT_DATA_BUFFER_INCOMPLETE|MFT_OUTPUT_DATA_BUFFER_NO_SAMPLE)) /* Win7 */,
6650 "got dwStatus %#lx\n", output.dwStatus);
6651 ok(status == 0, "got status %#lx\n", status);
6653 status = 0xdeadbeef;
6654 memset(&output, 0, sizeof(output));
6655 output_info.cbSize = wmadec_block_size;
6656 sample = create_sample(NULL, output_info.cbSize);
6657 outputs[0].pSample = sample;
6658 sample = create_sample(NULL, output_info.cbSize);
6659 outputs[1].pSample = sample;
6660 hr = IMFTransform_ProcessOutput(transform, 0, 2, outputs, &status);
6661 ok(hr == E_INVALIDARG, "ProcessOutput returned %#lx\n", hr);
6662 ref = IMFSample_Release(outputs[0].pSample);
6663 ok(ref == 0, "Release returned %ld\n", ref);
6664 ref = IMFSample_Release(outputs[1].pSample);
6665 ok(ref == 0, "Release returned %ld\n", ref);
6667 resource = FindResourceW(NULL, L"wmadecdata.bin", (const WCHAR *)RT_RCDATA);
6668 ok(resource != 0, "FindResourceW failed, error %lu\n", GetLastError());
6669 wmadec_data = LockResource(LoadResource(GetModuleHandleW(NULL), resource));
6670 wmadec_data_len = SizeofResource(GetModuleHandleW(NULL), resource);
6671 ok(wmadec_data_len == wmadec_block_size * 7 / 2, "got length %lu\n", wmadec_data_len);
6673 /* and generate a new one as well in a temporary directory */
6674 GetTempPathW(ARRAY_SIZE(output_path), output_path);
6675 lstrcatW(output_path, L"wmadecdata.bin");
6676 output_file = CreateFileW(output_path, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0);
6677 ok(output_file != INVALID_HANDLE_VALUE, "CreateFileW failed, error %lu\n", GetLastError());
6679 status = 0xdeadbeef;
6680 output_info.cbSize = wmadec_block_size;
6681 sample = create_sample(NULL, output_info.cbSize);
6682 memset(&output, 0, sizeof(output));
6683 output.pSample = sample;
6684 hr = IMFTransform_ProcessOutput(transform, 0, 1, &output, &status);
6686 for (i = 0; i < 4; ++i)
6688 winetest_push_context("%lu", i);
6690 ok(hr == S_OK, "ProcessOutput returned %#lx\n", hr);
6691 ok(output.pSample == sample, "got pSample %p\n", output.pSample);
6692 ok(output.dwStatus == MFT_OUTPUT_DATA_BUFFER_INCOMPLETE || output.dwStatus == 0 ||
6693 broken(output.dwStatus == (MFT_OUTPUT_DATA_BUFFER_INCOMPLETE|7) || output.dwStatus == 7) /* Win7 */,
6694 "got dwStatus %#lx\n", output.dwStatus);
6695 ok(status == 0, "got status %#lx\n", status);
6696 value = 0xdeadbeef;
6697 hr = IMFSample_GetUINT32(sample, &MFSampleExtension_CleanPoint, &value);
6698 ok(hr == S_OK, "GetUINT32 MFSampleExtension_CleanPoint returned %#lx\n", hr);
6699 ok(value == 1, "got MFSampleExtension_CleanPoint %u\n", value);
6700 hr = IMFSample_GetTotalLength(sample, &length);
6701 ok(hr == S_OK, "GetTotalLength returned %#lx\n", hr);
6702 flags = 0xdeadbeef;
6703 hr = IMFSample_GetSampleFlags(sample, &flags);
6704 ok(hr == S_OK, "GetSampleFlags returned %#lx\n", hr);
6705 ok(flags == 0, "got flags %#lx\n", flags);
6706 time = 0xdeadbeef;
6707 hr = IMFSample_GetSampleTime(sample, &time);
6708 ok(hr == S_OK, "GetSampleTime returned %#lx\n", hr);
6709 ok(time == i * 928798, "got time %I64d\n", time);
6710 duration = 0xdeadbeef;
6711 hr = IMFSample_GetSampleDuration(sample, &duration);
6712 ok(hr == S_OK, "GetSampleDuration returned %#lx\n", hr);
6713 if (output.dwStatus == MFT_OUTPUT_DATA_BUFFER_INCOMPLETE ||
6714 broken(output.dwStatus == (MFT_OUTPUT_DATA_BUFFER_INCOMPLETE|7)))
6716 ok(length == wmadec_block_size, "got length %lu\n", length);
6717 ok(duration == 928798, "got duration %I64d\n", duration);
6718 check_sample_pcm16(sample, wmadec_data, output_file, TRUE);
6719 wmadec_data += wmadec_block_size;
6720 wmadec_data_len -= wmadec_block_size;
6722 else
6724 /* FFmpeg doesn't seem to decode WMA buffers in the same way as native */
6725 todo_wine
6726 ok(length == wmadec_block_size / 2, "got length %lu\n", length);
6727 todo_wine
6728 ok(duration == 464399, "got duration %I64d\n", duration);
6730 if (length == wmadec_block_size / 2)
6731 check_sample_pcm16(sample, wmadec_data, output_file, FALSE);
6732 wmadec_data += length;
6733 wmadec_data_len -= length;
6735 ret = IMFSample_Release(sample);
6736 ok(ret == 0, "Release returned %lu\n", ret);
6738 status = 0xdeadbeef;
6739 sample = create_sample(NULL, output_info.cbSize);
6740 memset(&output, 0, sizeof(output));
6741 output.pSample = sample;
6742 hr = IMFTransform_ProcessOutput(transform, 0, 1, &output, &status);
6744 winetest_pop_context();
6746 todo_wine
6747 ok(wmadec_data_len == 0, "missing %#lx bytes\n", wmadec_data_len);
6749 trace("created %s\n", debugstr_w(output_path));
6750 CloseHandle(output_file);
6752 ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "ProcessOutput returned %#lx\n", hr);
6753 ok(output.pSample == sample, "got pSample %p\n", output.pSample);
6754 ok(output.dwStatus == 0, "got dwStatus %#lx\n", output.dwStatus);
6755 ok(status == 0, "got status %#lx\n", status);
6756 ret = IMFSample_Release(sample);
6757 ok(ret == 0, "Release returned %lu\n", ret);
6759 status = 0xdeadbeef;
6760 sample = create_sample(NULL, output_info.cbSize);
6761 memset(&output, 0, sizeof(output));
6762 output.pSample = sample;
6763 hr = IMFTransform_ProcessOutput(transform, 0, 1, &output, &status);
6764 ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "ProcessOutput returned %#lx\n", hr);
6765 ok(output.pSample == sample, "got pSample %p\n", output.pSample);
6766 ok(output.dwStatus == 0 ||
6767 broken(output.dwStatus == (MFT_OUTPUT_DATA_BUFFER_INCOMPLETE|7)) /* Win7 */,
6768 "got dwStatus %#lx\n", output.dwStatus);
6769 ok(status == 0, "got status %#lx\n", status);
6770 hr = IMFSample_GetTotalLength(sample, &length);
6771 ok(hr == S_OK, "GetTotalLength returned %#lx\n", hr);
6772 ok(length == 0, "got length %lu\n", length);
6773 ret = IMFSample_Release(sample);
6774 ok(ret == 0, "Release returned %lu\n", ret);
6776 sample = create_sample(wmaenc_data, wmaenc_block_size);
6777 hr = IMFTransform_ProcessInput(transform, 0, sample, 0);
6778 ok(hr == S_OK, "ProcessInput returned %#lx\n", hr);
6780 ret = IMFTransform_Release(transform);
6781 ok(ret == 0, "Release returned %lu\n", ret);
6782 ret = IMFSample_Release(sample);
6783 ok(ret == 0, "Release returned %lu\n", ret);
6785 hr = CoCreateInstance( &CLSID_CWMADecMediaObject, &outer, CLSCTX_INPROC_SERVER, &IID_IUnknown,
6786 (void **)&unknown );
6787 ok( hr == S_OK, "CoCreateInstance returned %#lx\n", hr );
6788 hr = IUnknown_QueryInterface( unknown, &IID_IMFTransform, (void **)&transform );
6789 ok( hr == S_OK, "QueryInterface returned %#lx\n", hr );
6790 hr = IUnknown_QueryInterface( unknown, &IID_IMediaObject, (void **)&media_object );
6791 ok( hr == S_OK, "QueryInterface returned %#lx\n", hr );
6792 hr = IUnknown_QueryInterface( unknown, &IID_IPropertyBag, (void **)&property_bag );
6793 ok( hr == S_OK, "QueryInterface returned %#lx\n", hr );
6794 hr = IUnknown_QueryInterface( media_object, &IID_IUnknown, (void **)&tmp_unknown );
6795 ok( hr == S_OK, "QueryInterface returned %#lx\n", hr );
6797 ok( unknown != &outer, "got outer IUnknown\n" );
6798 ok( transform != (void *)unknown, "got IUnknown == IMFTransform\n" );
6799 ok( media_object != (void *)unknown, "got IUnknown == IMediaObject\n" );
6800 ok( property_bag != (void *)unknown, "got IUnknown == IPropertyBag\n" );
6801 ok( tmp_unknown != unknown, "got inner IUnknown\n" );
6803 check_interface( unknown, &IID_IPersistPropertyBag, FALSE );
6804 check_interface( unknown, &IID_IAMFilterMiscFlags, FALSE );
6805 check_interface( unknown, &IID_IMediaSeeking, FALSE );
6806 check_interface( unknown, &IID_IMediaPosition, FALSE );
6807 check_interface( unknown, &IID_IReferenceClock, FALSE );
6808 check_interface( unknown, &IID_IBasicAudio, FALSE );
6810 ref = IUnknown_Release( tmp_unknown );
6811 ok( ref == 1, "Release returned %lu\n", ref );
6812 ref = IPropertyBag_Release( property_bag );
6813 ok( ref == 1, "Release returned %lu\n", ref );
6814 ref = IMediaObject_Release( media_object );
6815 ok( ref == 1, "Release returned %lu\n", ref );
6816 ref = IMFTransform_Release( transform );
6817 ok( ref == 1, "Release returned %lu\n", ref );
6818 ref = IUnknown_Release( unknown );
6819 ok( ref == 0, "Release returned %lu\n", ref );
6821 failed:
6822 CoUninitialize();
6825 #define next_h264_sample(a, b) next_h264_sample_(__LINE__, a, b)
6826 static IMFSample *next_h264_sample_(int line, const BYTE **h264_buf, ULONG *h264_len)
6828 const BYTE *sample_data;
6830 ok_(__FILE__, line)(*h264_len > 4, "invalid h264 length\n");
6831 ok_(__FILE__, line)(*(UINT32 *)*h264_buf == 0x01000000, "invalid h264 buffer\n");
6832 sample_data = *h264_buf;
6834 (*h264_len) -= 4;
6835 (*h264_buf) += 4;
6837 while (*h264_len >= 4 && *(UINT32 *)*h264_buf != 0x01000000)
6839 (*h264_len)--;
6840 (*h264_buf)++;
6843 return create_sample(sample_data, *h264_buf - sample_data);
6846 static void test_h264_decoder(void)
6848 const GUID transform_inputs[] =
6850 MFVideoFormat_H264,
6851 MFVideoFormat_H264_ES,
6853 const GUID transform_outputs[] =
6855 MFVideoFormat_NV12,
6856 MFVideoFormat_YV12,
6857 MFVideoFormat_IYUV,
6858 MFVideoFormat_I420,
6859 MFVideoFormat_YUY2,
6861 static const media_type_desc default_inputs[] =
6864 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
6865 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_H264),
6868 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
6869 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_H264_ES),
6872 static const media_type_desc default_outputs[] =
6875 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
6876 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_NV12),
6877 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
6878 ATTR_RATIO(MF_MT_FRAME_RATE, 30000, 1001),
6879 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, 1920),
6880 ATTR_UINT32(MF_MT_INTERLACE_MODE, 7),
6881 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
6882 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
6885 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
6886 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_YV12),
6887 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
6888 ATTR_RATIO(MF_MT_FRAME_RATE, 30000, 1001),
6889 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, 1920),
6890 ATTR_UINT32(MF_MT_INTERLACE_MODE, 7),
6891 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
6892 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
6895 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
6896 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_IYUV),
6897 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
6898 ATTR_RATIO(MF_MT_FRAME_RATE, 30000, 1001),
6899 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, 1920),
6900 ATTR_UINT32(MF_MT_INTERLACE_MODE, 7),
6901 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
6902 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
6905 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
6906 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_I420),
6907 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
6908 ATTR_RATIO(MF_MT_FRAME_RATE, 30000, 1001),
6909 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, 1920),
6910 ATTR_UINT32(MF_MT_INTERLACE_MODE, 7),
6911 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
6912 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
6915 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
6916 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_YUY2),
6917 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
6918 ATTR_RATIO(MF_MT_FRAME_RATE, 30000, 1001),
6919 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, 3840),
6920 ATTR_UINT32(MF_MT_INTERLACE_MODE, 7),
6921 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
6922 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
6925 static const media_type_desc default_outputs_extra[] =
6928 ATTR_RATIO(MF_MT_FRAME_SIZE, 1920, 1080),
6929 ATTR_UINT32(MF_MT_SAMPLE_SIZE, 3110400),
6930 ATTR_UINT32(MF_MT_VIDEO_ROTATION, 0),
6933 ATTR_RATIO(MF_MT_FRAME_SIZE, 1920, 1080),
6934 ATTR_UINT32(MF_MT_SAMPLE_SIZE, 3110400),
6935 ATTR_UINT32(MF_MT_VIDEO_ROTATION, 0),
6938 ATTR_RATIO(MF_MT_FRAME_SIZE, 1920, 1080),
6939 ATTR_UINT32(MF_MT_SAMPLE_SIZE, 3110400),
6940 ATTR_UINT32(MF_MT_VIDEO_ROTATION, 0),
6943 ATTR_RATIO(MF_MT_FRAME_SIZE, 1920, 1080),
6944 ATTR_UINT32(MF_MT_SAMPLE_SIZE, 3110400),
6945 ATTR_UINT32(MF_MT_VIDEO_ROTATION, 0),
6948 ATTR_RATIO(MF_MT_FRAME_SIZE, 1920, 1080),
6949 ATTR_UINT32(MF_MT_SAMPLE_SIZE, 4147200),
6950 ATTR_UINT32(MF_MT_VIDEO_ROTATION, 0),
6953 static const media_type_desc default_outputs_win7[] =
6956 ATTR_RATIO(MF_MT_FRAME_SIZE, 1920, 1088),
6957 ATTR_UINT32(MF_MT_SAMPLE_SIZE, 3133440),
6960 ATTR_RATIO(MF_MT_FRAME_SIZE, 1920, 1088),
6961 ATTR_UINT32(MF_MT_SAMPLE_SIZE, 3133440),
6964 ATTR_RATIO(MF_MT_FRAME_SIZE, 1920, 1088),
6965 ATTR_UINT32(MF_MT_SAMPLE_SIZE, 3133440),
6968 ATTR_RATIO(MF_MT_FRAME_SIZE, 1920, 1088),
6969 ATTR_UINT32(MF_MT_SAMPLE_SIZE, 3133440),
6972 ATTR_RATIO(MF_MT_FRAME_SIZE, 1920, 1088),
6973 ATTR_UINT32(MF_MT_SAMPLE_SIZE, 4177920),
6976 static const struct attribute_desc input_type_desc[] =
6978 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
6979 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_H264),
6980 {0},
6982 static const struct attribute_desc minimal_output_type_desc[] =
6984 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
6985 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_NV12),
6986 ATTR_RATIO(MF_MT_FRAME_SIZE, 1920, 1080),
6987 {0},
6989 static const struct attribute_desc output_type_desc[] =
6991 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
6992 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_NV12),
6993 ATTR_RATIO(MF_MT_FRAME_SIZE, 1920, 1080),
6994 ATTR_RATIO(MF_MT_FRAME_RATE, 60000, 1000),
6995 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 2, 1),
6996 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, 3840),
6997 ATTR_UINT32(MF_MT_SAMPLE_SIZE, 3840 * 1080 * 3 / 2),
6998 ATTR_UINT32(MF_MT_VIDEO_ROTATION, 0),
6999 {0},
7001 static const struct attribute_desc output_type_desc_win7[] =
7003 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
7004 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_NV12),
7005 ATTR_RATIO(MF_MT_FRAME_SIZE, 1920, 1088),
7006 ATTR_RATIO(MF_MT_FRAME_RATE, 60000, 1000),
7007 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 2, 1),
7008 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, 3840),
7009 ATTR_UINT32(MF_MT_SAMPLE_SIZE, 3840 * 1088 * 3 / 2),
7010 ATTR_UINT32(MF_MT_VIDEO_ROTATION, 0),
7011 {0},
7013 static const struct attribute_desc new_output_type_desc[] =
7015 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
7016 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_I420),
7017 ATTR_RATIO(MF_MT_FRAME_SIZE, 96, 96),
7018 ATTR_RATIO(MF_MT_FRAME_RATE, 1, 1),
7019 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 2),
7020 {0},
7022 static const struct attribute_desc new_output_type_desc_win7[] =
7024 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
7025 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_I420),
7026 ATTR_RATIO(MF_MT_FRAME_SIZE, 96, 96),
7027 ATTR_RATIO(MF_MT_FRAME_RATE, 1, 1),
7028 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 2),
7029 {0},
7031 static const MFVideoArea actual_aperture = {.Area={82,84}};
7032 static const DWORD actual_width = 96, actual_height = 96;
7033 const media_type_desc actual_outputs[] =
7036 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
7037 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_NV12),
7038 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
7039 ATTR_RATIO(MF_MT_FRAME_RATE, 60000, 1000),
7040 ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height),
7041 ATTR_UINT32(MF_MT_SAMPLE_SIZE, actual_width * actual_height * 3 / 2),
7042 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, actual_width),
7043 /* ATTR_UINT32(MF_MT_VIDEO_ROTATION, 0), missing on Win7 */
7044 ATTR_UINT32(MF_MT_INTERLACE_MODE, 7),
7045 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
7046 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
7047 ATTR_BLOB(MF_MT_MINIMUM_DISPLAY_APERTURE, &actual_aperture, 16),
7050 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
7051 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_YV12),
7052 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
7053 ATTR_RATIO(MF_MT_FRAME_RATE, 60000, 1000),
7054 ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height),
7055 ATTR_UINT32(MF_MT_SAMPLE_SIZE, actual_width * actual_height * 3 / 2),
7056 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, actual_width),
7057 /* ATTR_UINT32(MF_MT_VIDEO_ROTATION, 0), missing on Win7 */
7058 ATTR_UINT32(MF_MT_INTERLACE_MODE, 7),
7059 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
7060 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
7061 ATTR_BLOB(MF_MT_MINIMUM_DISPLAY_APERTURE, &actual_aperture, 16),
7064 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
7065 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_IYUV),
7066 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
7067 ATTR_RATIO(MF_MT_FRAME_RATE, 60000, 1000),
7068 ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height),
7069 ATTR_UINT32(MF_MT_SAMPLE_SIZE, actual_width * actual_height * 3 / 2),
7070 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, actual_width),
7071 /* ATTR_UINT32(MF_MT_VIDEO_ROTATION, 0), missing on Win7 */
7072 ATTR_UINT32(MF_MT_INTERLACE_MODE, 7),
7073 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
7074 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
7075 ATTR_BLOB(MF_MT_MINIMUM_DISPLAY_APERTURE, &actual_aperture, 16),
7078 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
7079 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_I420),
7080 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
7081 ATTR_RATIO(MF_MT_FRAME_RATE, 60000, 1000),
7082 ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height),
7083 ATTR_UINT32(MF_MT_SAMPLE_SIZE, actual_width * actual_height * 3 / 2),
7084 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, actual_width),
7085 /* ATTR_UINT32(MF_MT_VIDEO_ROTATION, 0), missing on Win7 */
7086 ATTR_UINT32(MF_MT_INTERLACE_MODE, 7),
7087 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
7088 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
7089 ATTR_BLOB(MF_MT_MINIMUM_DISPLAY_APERTURE, &actual_aperture, 16),
7092 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
7093 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_YUY2),
7094 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
7095 ATTR_RATIO(MF_MT_FRAME_RATE, 60000, 1000),
7096 ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height),
7097 ATTR_UINT32(MF_MT_SAMPLE_SIZE, actual_width * actual_height * 2),
7098 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, actual_width * 2),
7099 /* ATTR_UINT32(MF_MT_VIDEO_ROTATION, 0), missing on Win7 */
7100 ATTR_UINT32(MF_MT_INTERLACE_MODE, 7),
7101 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
7102 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
7103 ATTR_BLOB(MF_MT_MINIMUM_DISPLAY_APERTURE, &actual_aperture, 16),
7107 MFT_REGISTER_TYPE_INFO input_type = {MFMediaType_Video, MFVideoFormat_H264};
7108 MFT_REGISTER_TYPE_INFO output_type = {MFMediaType_Video, MFVideoFormat_NV12};
7109 const BYTE *h264_encoded_data, *nv12_frame_data, *i420_frame_data;
7110 ULONG h264_encoded_data_len, nv12_frame_len, i420_frame_len;
7111 DWORD input_id, output_id, input_count, output_count;
7112 MFT_OUTPUT_STREAM_INFO output_info;
7113 MFT_INPUT_STREAM_INFO input_info;
7114 MFT_OUTPUT_DATA_BUFFER output;
7115 IMFMediaBuffer *media_buffer;
7116 DWORD status, length, count;
7117 WCHAR output_path[MAX_PATH];
7118 IMFAttributes *attributes;
7119 IMFMediaType *media_type;
7120 LONGLONG time, duration;
7121 IMFTransform *transform;
7122 BOOL is_win7 = FALSE;
7123 ULONG i, ret, flags;
7124 HANDLE output_file;
7125 IMFSample *sample;
7126 HRSRC resource;
7127 GUID class_id;
7128 UINT32 value;
7129 BYTE *data;
7130 HRESULT hr;
7132 hr = CoInitialize(NULL);
7133 ok(hr == S_OK, "Failed to initialize, hr %#lx.\n", hr);
7135 if (!create_transform(MFT_CATEGORY_VIDEO_DECODER, &input_type, &output_type, L"Microsoft H264 Video Decoder MFT", &MFMediaType_Video,
7136 transform_inputs, ARRAY_SIZE(transform_inputs), transform_outputs, ARRAY_SIZE(transform_outputs),
7137 &transform, &CLSID_MSH264DecoderMFT, &class_id))
7138 goto failed;
7140 hr = IMFTransform_GetAttributes(transform, &attributes);
7141 ok(hr == S_OK, "GetAttributes returned %#lx\n", hr);
7142 hr = IMFAttributes_SetUINT32(attributes, &MF_LOW_LATENCY, 1);
7143 ok(hr == S_OK, "SetUINT32 returned %#lx\n", hr);
7144 ret = IMFAttributes_Release(attributes);
7145 todo_wine
7146 ok(ret == 1, "Release returned %ld\n", ret);
7148 /* no output type is available before an input type is set */
7150 hr = IMFTransform_GetOutputAvailableType(transform, 0, 0, &media_type);
7151 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "GetOutputAvailableType returned %#lx\n", hr);
7152 hr = IMFTransform_GetOutputCurrentType(transform, 0, &media_type);
7153 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "GetOutputCurrentType returned %#lx\n", hr);
7155 /* setting output media type first doesn't work */
7157 hr = MFCreateMediaType(&media_type);
7158 ok(hr == S_OK, "MFCreateMediaType returned %#lx\n", hr);
7159 init_media_type(media_type, default_outputs[0], -1);
7160 hr = IMFTransform_SetOutputType(transform, 0, media_type, 0);
7161 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "SetOutputType returned %#lx.\n", hr);
7162 ret = IMFMediaType_Release(media_type);
7163 ok(ret == 0, "Release returned %lu\n", ret);
7165 /* check available input types */
7167 flags = MFT_INPUT_STREAM_WHOLE_SAMPLES | MFT_INPUT_STREAM_SINGLE_SAMPLE_PER_BUFFER | MFT_INPUT_STREAM_FIXED_SAMPLE_SIZE;
7168 memset(&input_info, 0xcd, sizeof(input_info));
7169 hr = IMFTransform_GetInputStreamInfo(transform, 0, &input_info);
7170 todo_wine
7171 ok(hr == S_OK, "GetInputStreamInfo returned %#lx\n", hr);
7172 todo_wine
7173 ok(input_info.hnsMaxLatency == 0, "got hnsMaxLatency %s\n", wine_dbgstr_longlong(input_info.hnsMaxLatency));
7174 todo_wine
7175 ok(input_info.dwFlags == flags, "got dwFlags %#lx\n", input_info.dwFlags);
7176 todo_wine
7177 ok(input_info.cbSize == 0x1000, "got cbSize %lu\n", input_info.cbSize);
7178 todo_wine
7179 ok(input_info.cbMaxLookahead == 0, "got cbMaxLookahead %#lx\n", input_info.cbMaxLookahead);
7180 todo_wine
7181 ok(input_info.cbAlignment == 0, "got cbAlignment %#lx\n", input_info.cbAlignment);
7183 flags = MFT_OUTPUT_STREAM_WHOLE_SAMPLES | MFT_OUTPUT_STREAM_SINGLE_SAMPLE_PER_BUFFER | MFT_OUTPUT_STREAM_FIXED_SAMPLE_SIZE;
7184 memset(&output_info, 0xcd, sizeof(output_info));
7185 hr = IMFTransform_GetOutputStreamInfo(transform, 0, &output_info);
7186 ok(hr == S_OK, "GetOutputStreamInfo returned %#lx\n", hr);
7187 ok(output_info.dwFlags == flags, "got dwFlags %#lx\n", output_info.dwFlags);
7188 ok(output_info.cbSize == 1920 * 1088 * 2, "got cbSize %#lx\n", output_info.cbSize);
7189 ok(output_info.cbAlignment == 0, "got cbAlignment %#lx\n", output_info.cbAlignment);
7191 i = -1;
7192 while (SUCCEEDED(hr = IMFTransform_GetInputAvailableType(transform, 0, ++i, &media_type)))
7194 winetest_push_context("in %lu", i);
7195 ok(hr == S_OK, "GetInputAvailableType returned %#lx\n", hr);
7196 check_media_type(media_type, default_inputs[i], -1);
7197 ret = IMFMediaType_Release(media_type);
7198 ok(ret == 0, "Release returned %lu\n", ret);
7199 winetest_pop_context();
7201 ok(hr == MF_E_NO_MORE_TYPES, "GetInputAvailableType returned %#lx\n", hr);
7202 ok(i == 2 || broken(i == 1) /* Win7 */, "%lu input media types\n", i);
7204 /* check required input media type attributes */
7206 hr = MFCreateMediaType(&media_type);
7207 ok(hr == S_OK, "MFCreateMediaType returned %#lx\n", hr);
7208 hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
7209 ok(hr == E_INVALIDARG, "SetInputType returned %#lx.\n", hr);
7210 init_media_type(media_type, input_type_desc, 1);
7211 hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
7212 todo_wine
7213 ok(hr == MF_E_INVALIDMEDIATYPE, "SetInputType returned %#lx.\n", hr);
7214 init_media_type(media_type, input_type_desc, 2);
7215 hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
7216 ok(hr == S_OK, "SetInputType returned %#lx.\n", hr);
7217 ret = IMFMediaType_Release(media_type);
7218 ok(ret == 1, "Release returned %lu\n", ret);
7220 flags = MFT_OUTPUT_STREAM_WHOLE_SAMPLES | MFT_OUTPUT_STREAM_SINGLE_SAMPLE_PER_BUFFER | MFT_OUTPUT_STREAM_FIXED_SAMPLE_SIZE;
7221 memset(&output_info, 0xcd, sizeof(output_info));
7222 hr = IMFTransform_GetOutputStreamInfo(transform, 0, &output_info);
7223 ok(hr == S_OK, "GetOutputStreamInfo returned %#lx\n", hr);
7224 ok(output_info.dwFlags == flags, "got dwFlags %#lx\n", output_info.dwFlags);
7225 todo_wine
7226 ok(output_info.cbSize == 1920 * 1080 * 2 || broken(output_info.cbSize == 1920 * 1088 * 2) /* Win7 */,
7227 "got cbSize %#lx\n", output_info.cbSize);
7228 ok(output_info.cbAlignment == 0, "got cbAlignment %#lx\n", output_info.cbAlignment);
7230 /* output types can now be enumerated (though they are actually the same for all input types) */
7232 i = -1;
7233 while (SUCCEEDED(hr = IMFTransform_GetOutputAvailableType(transform, 0, ++i, &media_type)))
7235 winetest_push_context("out %lu", i);
7236 ok(hr == S_OK, "GetOutputAvailableType returned %#lx\n", hr);
7237 check_media_type(media_type, default_outputs[i], -1);
7238 hr = IMFMediaType_GetItem(media_type, &MF_MT_VIDEO_ROTATION, NULL);
7239 is_win7 = broken(FAILED(hr));
7240 check_media_type(media_type, is_win7 ? default_outputs_win7[i] : default_outputs_extra[i], -1);
7241 ret = IMFMediaType_Release(media_type);
7242 ok(ret == 0, "Release returned %lu\n", ret);
7243 winetest_pop_context();
7245 ok(hr == MF_E_NO_MORE_TYPES, "GetOutputAvailableType returned %#lx\n", hr);
7246 ok(i == 5, "%lu output media types\n", i);
7248 /* check required output media type attributes */
7250 hr = MFCreateMediaType(&media_type);
7251 ok(hr == S_OK, "MFCreateMediaType returned %#lx\n", hr);
7252 hr = IMFTransform_SetOutputType(transform, 0, media_type, 0);
7253 todo_wine
7254 ok(hr == E_INVALIDARG, "SetOutputType returned %#lx.\n", hr);
7255 init_media_type(media_type, minimal_output_type_desc, 1);
7256 hr = IMFTransform_SetOutputType(transform, 0, media_type, 0);
7257 todo_wine
7258 ok(hr == MF_E_INVALIDMEDIATYPE, "SetOutputType returned %#lx.\n", hr);
7259 init_media_type(media_type, minimal_output_type_desc, 2);
7260 for (i = 2; i < ARRAY_SIZE(minimal_output_type_desc) - 1; ++i)
7262 hr = IMFTransform_SetOutputType(transform, 0, media_type, 0);
7263 todo_wine
7264 ok(hr == MF_E_ATTRIBUTENOTFOUND, "SetOutputType returned %#lx.\n", hr);
7265 init_media_type(media_type, minimal_output_type_desc, i + 1);
7267 hr = IMFTransform_SetOutputType(transform, 0, media_type, 0);
7268 ok(hr == (is_win7 ? MF_E_INVALIDMEDIATYPE : S_OK), "SetOutputType returned %#lx.\n", hr);
7269 init_media_type(media_type, is_win7 ? output_type_desc_win7 : output_type_desc, -1);
7270 hr = IMFTransform_SetOutputType(transform, 0, media_type, 0);
7271 ok(hr == S_OK, "SetOutputType returned %#lx.\n", hr);
7272 ret = IMFMediaType_Release(media_type);
7273 ok(ret == 1, "Release returned %lu\n", ret);
7275 hr = IMFTransform_GetOutputCurrentType(transform, 0, &media_type);
7276 ok(hr == S_OK, "GetOutputCurrentType returned %#lx\n", hr);
7277 check_media_type(media_type, is_win7 ? output_type_desc_win7 : output_type_desc, -1);
7278 ret = IMFMediaType_Release(media_type);
7279 ok(ret == 0, "Release returned %lu\n", ret);
7281 /* check that the output media type we've selected don't change the enumeration */
7283 i = -1;
7284 while (SUCCEEDED(hr = IMFTransform_GetOutputAvailableType(transform, 0, ++i, &media_type)))
7286 winetest_push_context("out %lu", i);
7287 ok(hr == S_OK, "GetOutputAvailableType returned %#lx\n", hr);
7288 check_media_type(media_type, default_outputs[i], -1);
7289 check_media_type(media_type, is_win7 ? default_outputs_win7[i] : default_outputs_extra[i], -1);
7290 ret = IMFMediaType_Release(media_type);
7291 ok(ret == 0, "Release returned %lu\n", ret);
7292 winetest_pop_context();
7294 ok(hr == MF_E_NO_MORE_TYPES, "GetOutputAvailableType returned %#lx\n", hr);
7295 ok(i == 5, "%lu output media types\n", i);
7297 flags = MFT_INPUT_STREAM_WHOLE_SAMPLES | MFT_INPUT_STREAM_SINGLE_SAMPLE_PER_BUFFER | MFT_INPUT_STREAM_FIXED_SAMPLE_SIZE;
7298 memset(&input_info, 0xcd, sizeof(input_info));
7299 hr = IMFTransform_GetInputStreamInfo(transform, 0, &input_info);
7300 ok(hr == S_OK, "GetInputStreamInfo returned %#lx\n", hr);
7301 ok(input_info.hnsMaxLatency == 0, "got hnsMaxLatency %s\n", wine_dbgstr_longlong(input_info.hnsMaxLatency));
7302 ok(input_info.dwFlags == flags, "got dwFlags %#lx\n", input_info.dwFlags);
7303 ok(input_info.cbSize == 0x1000, "got cbSize %lu\n", input_info.cbSize);
7304 ok(input_info.cbMaxLookahead == 0, "got cbMaxLookahead %#lx\n", input_info.cbMaxLookahead);
7305 ok(input_info.cbAlignment == 0, "got cbAlignment %#lx\n", input_info.cbAlignment);
7307 flags = MFT_OUTPUT_STREAM_WHOLE_SAMPLES | MFT_OUTPUT_STREAM_SINGLE_SAMPLE_PER_BUFFER | MFT_OUTPUT_STREAM_FIXED_SAMPLE_SIZE;
7308 memset(&output_info, 0xcd, sizeof(output_info));
7309 hr = IMFTransform_GetOutputStreamInfo(transform, 0, &output_info);
7310 ok(hr == S_OK, "GetOutputStreamInfo returned %#lx\n", hr);
7311 ok(output_info.dwFlags == flags, "got dwFlags %#lx\n", output_info.dwFlags);
7312 todo_wine
7313 ok(output_info.cbSize == 1920 * 1080 * 2 || broken(output_info.cbSize == 1920 * 1088 * 2) /* Win7 */,
7314 "got cbSize %#lx\n", output_info.cbSize);
7315 ok(output_info.cbAlignment == 0, "got cbAlignment %#lx\n", output_info.cbAlignment);
7317 input_count = output_count = 0xdeadbeef;
7318 hr = IMFTransform_GetStreamCount(transform, &input_count, &output_count);
7319 todo_wine
7320 ok(hr == S_OK, "GetStreamCount returned %#lx\n", hr);
7321 todo_wine
7322 ok(input_count == 1, "got input_count %lu\n", input_count);
7323 todo_wine
7324 ok(output_count == 1, "got output_count %lu\n", output_count);
7325 hr = IMFTransform_GetStreamIDs(transform, 1, &input_id, 1, &output_id);
7326 ok(hr == E_NOTIMPL, "GetStreamIDs returned %#lx\n", hr);
7328 resource = FindResourceW(NULL, L"h264data.bin", (const WCHAR *)RT_RCDATA);
7329 ok(resource != 0, "FindResourceW failed, error %lu\n", GetLastError());
7330 h264_encoded_data = LockResource(LoadResource(GetModuleHandleW(NULL), resource));
7331 h264_encoded_data_len = SizeofResource(GetModuleHandleW(NULL), resource);
7333 /* As output_info.dwFlags doesn't have MFT_OUTPUT_STREAM_CAN_PROVIDE_SAMPLES
7334 * IMFTransform_ProcessOutput needs a sample or returns an error */
7336 status = 0;
7337 memset(&output, 0, sizeof(output));
7338 hr = IMFTransform_ProcessOutput(transform, 0, 1, &output, &status);
7339 ok(hr == E_INVALIDARG || hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "ProcessOutput returned %#lx\n", hr);
7340 ok(output.dwStreamID == 0, "got dwStreamID %lu\n", output.dwStreamID);
7341 ok(!output.pSample, "got pSample %p\n", output.pSample);
7342 ok(output.dwStatus == 0, "got dwStatus %#lx\n", output.dwStatus);
7343 ok(!output.pEvents, "got pEvents %p\n", output.pEvents);
7344 ok(status == 0, "got status %#lx\n", status);
7346 i = 0;
7347 sample = next_h264_sample(&h264_encoded_data, &h264_encoded_data_len);
7348 while (1)
7350 status = 0;
7351 memset(&output, 0, sizeof(output));
7352 output.pSample = create_sample(NULL, output_info.cbSize);
7353 hr = IMFTransform_ProcessOutput(transform, 0, 1, &output, &status);
7354 if (hr != MF_E_TRANSFORM_NEED_MORE_INPUT) break;
7355 ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "ProcessOutput returned %#lx\n", hr);
7356 ok(output.dwStreamID == 0, "got dwStreamID %lu\n", output.dwStreamID);
7357 ok(!!output.pSample, "got pSample %p\n", output.pSample);
7358 ok(output.dwStatus == 0, "got dwStatus %#lx\n", output.dwStatus);
7359 ok(!output.pEvents, "got pEvents %p\n", output.pEvents);
7360 ok(status == 0, "got status %#lx\n", status);
7361 hr = IMFSample_GetTotalLength(output.pSample, &length);
7362 ok(hr == S_OK, "GetTotalLength returned %#lx\n", hr);
7363 ok(length == 0, "got length %lu\n", length);
7364 ret = IMFSample_Release(output.pSample);
7365 ok(ret == 0, "Release returned %lu\n", ret);
7367 hr = IMFTransform_ProcessInput(transform, 0, sample, 0);
7368 ok(hr == S_OK, "ProcessInput returned %#lx\n", hr);
7369 ret = IMFSample_Release(sample);
7370 ok(ret <= 1, "Release returned %lu\n", ret);
7371 sample = next_h264_sample(&h264_encoded_data, &h264_encoded_data_len);
7373 hr = IMFTransform_ProcessInput(transform, 0, sample, 0);
7374 ok(hr == S_OK, "ProcessInput returned %#lx\n", hr);
7375 ret = IMFSample_Release(sample);
7376 ok(ret <= 1, "Release returned %lu\n", ret);
7377 sample = next_h264_sample(&h264_encoded_data, &h264_encoded_data_len);
7378 i++;
7380 hr = IMFTransform_ProcessMessage(transform, MFT_MESSAGE_COMMAND_DRAIN, 0);
7381 ok(hr == S_OK, "ProcessMessage returned %#lx\n", hr);
7383 todo_wine
7384 ok(i == 2, "got %lu iterations\n", i);
7385 todo_wine
7386 ok(h264_encoded_data_len == 1180, "got h264_encoded_data_len %lu\n", h264_encoded_data_len);
7387 ok(hr == MF_E_TRANSFORM_STREAM_CHANGE, "ProcessOutput returned %#lx\n", hr);
7388 ok(output.dwStreamID == 0, "got dwStreamID %lu\n", output.dwStreamID);
7389 ok(!!output.pSample, "got pSample %p\n", output.pSample);
7390 ok(output.dwStatus == MFT_OUTPUT_DATA_BUFFER_FORMAT_CHANGE,
7391 "got dwStatus %#lx\n", output.dwStatus);
7392 ok(!output.pEvents, "got pEvents %p\n", output.pEvents);
7393 ok(status == MFT_PROCESS_OUTPUT_STATUS_NEW_STREAMS,
7394 "got status %#lx\n", status);
7395 hr = IMFSample_GetTotalLength(output.pSample, &length);
7396 ok(hr == S_OK, "GetTotalLength returned %#lx\n", hr);
7397 ok(length == 0, "got length %lu\n", length);
7398 ret = IMFSample_Release(output.pSample);
7399 ok(ret == 0, "Release returned %lu\n", ret);
7401 flags = MFT_OUTPUT_STREAM_WHOLE_SAMPLES | MFT_OUTPUT_STREAM_SINGLE_SAMPLE_PER_BUFFER | MFT_OUTPUT_STREAM_FIXED_SAMPLE_SIZE;
7402 memset(&output_info, 0xcd, sizeof(output_info));
7403 hr = IMFTransform_GetOutputStreamInfo(transform, 0, &output_info);
7404 ok(hr == S_OK, "GetOutputStreamInfo returned %#lx\n", hr);
7405 ok(output_info.dwFlags == flags, "got dwFlags %#lx\n", output_info.dwFlags);
7406 ok(output_info.cbSize == actual_width * actual_height * 2, "got cbSize %#lx\n", output_info.cbSize);
7407 ok(output_info.cbAlignment == 0, "got cbAlignment %#lx\n", output_info.cbAlignment);
7409 i = -1;
7410 while (SUCCEEDED(hr = IMFTransform_GetOutputAvailableType(transform, 0, ++i, &media_type)))
7412 winetest_push_context("out %lu", i);
7413 ok(hr == S_OK, "GetOutputAvailableType returned %#lx\n", hr);
7414 check_media_type(media_type, actual_outputs[i], -1);
7415 ret = IMFMediaType_Release(media_type);
7416 ok(ret == 0, "Release returned %lu\n", ret);
7417 winetest_pop_context();
7419 ok(hr == MF_E_NO_MORE_TYPES, "GetOutputAvailableType returned %#lx\n", hr);
7420 ok(i == 5, "%lu output media types\n", i);
7422 /* current output type is still the one we selected */
7423 hr = IMFTransform_GetOutputCurrentType(transform, 0, &media_type);
7424 ok(hr == S_OK, "GetOutputCurrentType returned %#lx\n", hr);
7425 check_media_type(media_type, is_win7 ? output_type_desc_win7 : output_type_desc, -1);
7426 hr = IMFMediaType_GetItemType(media_type, &MF_MT_MINIMUM_DISPLAY_APERTURE, NULL);
7427 ok(hr == MF_E_ATTRIBUTENOTFOUND, "GetItemType returned %#lx\n", hr);
7428 ret = IMFMediaType_Release(media_type);
7429 ok(ret == 0, "Release returned %lu\n", ret);
7431 /* and generate a new one as well in a temporary directory */
7432 GetTempPathW(ARRAY_SIZE(output_path), output_path);
7433 lstrcatW(output_path, L"nv12frame.bin");
7434 output_file = CreateFileW(output_path, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0);
7435 ok(output_file != INVALID_HANDLE_VALUE, "CreateFileW failed, error %lu\n", GetLastError());
7437 resource = FindResourceW(NULL, L"nv12frame.bin", (const WCHAR *)RT_RCDATA);
7438 ok(resource != 0, "FindResourceW failed, error %lu\n", GetLastError());
7439 nv12_frame_data = LockResource(LoadResource(GetModuleHandleW(NULL), resource));
7440 nv12_frame_len = SizeofResource(GetModuleHandleW(NULL), resource);
7441 ok(nv12_frame_len == actual_width * actual_height * 3 / 2, "got frame length %lu\n", nv12_frame_len);
7443 status = 0;
7444 memset(&output, 0, sizeof(output));
7445 output.pSample = create_sample(NULL, actual_width * actual_height * 2);
7446 hr = IMFTransform_ProcessOutput(transform, 0, 1, &output, &status);
7447 ok(hr == S_OK, "ProcessOutput returned %#lx\n", hr);
7448 ok(output.dwStreamID == 0, "got dwStreamID %lu\n", output.dwStreamID);
7449 ok(!!output.pSample, "got pSample %p\n", output.pSample);
7450 ok(output.dwStatus == 0, "got dwStatus %#lx\n", output.dwStatus);
7451 ok(!output.pEvents, "got pEvents %p\n", output.pEvents);
7452 ok(status == 0, "got status %#lx\n", status);
7454 hr = IMFSample_GetUINT32(sample, &MFSampleExtension_CleanPoint, &value);
7455 ok(hr == MF_E_ATTRIBUTENOTFOUND, "GetUINT32 MFSampleExtension_CleanPoint returned %#lx\n", hr);
7457 count = 0xdeadbeef;
7458 hr = IMFSample_GetBufferCount(output.pSample, &count);
7459 ok(hr == S_OK, "GetBufferCount returned %#lx\n", hr);
7460 ok(count == 1, "got count %#lx\n", count);
7462 flags = 0xdeadbeef;
7463 hr = IMFSample_GetSampleFlags(output.pSample, &flags);
7464 ok(hr == S_OK, "GetSampleFlags returned %#lx\n", hr);
7465 ok(flags == 0, "got flags %#lx\n", flags);
7467 time = 0xdeadbeef;
7468 hr = IMFSample_GetSampleTime(output.pSample, &time);
7469 ok(hr == S_OK, "GetSampleTime returned %#lx\n", hr);
7470 ok(time == 0, "got time %I64d\n", time);
7472 /* doesn't matter what frame rate we've selected, duration is defined by the stream */
7473 duration = 0xdeadbeef;
7474 hr = IMFSample_GetSampleDuration(output.pSample, &duration);
7475 ok(hr == S_OK, "GetSampleDuration returned %#lx\n", hr);
7476 ok(duration - 333666 <= 2, "got duration %I64d\n", duration);
7478 /* Win8 and before pad the data with garbage instead of original
7479 * buffer data, make sure it's consistent. */
7480 hr = IMFSample_ConvertToContiguousBuffer(output.pSample, &media_buffer);
7481 ok(hr == S_OK, "ConvertToContiguousBuffer returned %#lx\n", hr);
7482 hr = IMFMediaBuffer_Lock(media_buffer, &data, NULL, &length);
7483 ok(hr == S_OK, "Lock returned %#lx\n", hr);
7484 ok(length == nv12_frame_len, "got length %lu\n", length);
7486 for (i = 0; i < actual_aperture.Area.cy; ++i)
7488 memset(data + actual_width * i + actual_aperture.Area.cx, 0xcd, actual_width - actual_aperture.Area.cx);
7489 memset(data + actual_width * (actual_height + i) + actual_aperture.Area.cx, 0xcd, actual_width - actual_aperture.Area.cx);
7491 memset(data + actual_width * actual_aperture.Area.cy, 0xcd, (actual_height - actual_aperture.Area.cy) * actual_width);
7492 memset(data + actual_width * (actual_height + actual_aperture.Area.cy / 2), 0xcd, (actual_height - actual_aperture.Area.cy) / 2 * actual_width);
7494 hr = IMFMediaBuffer_Unlock(media_buffer);
7495 ok(hr == S_OK, "Unlock returned %#lx\n", hr);
7496 IMFMediaBuffer_Release(media_buffer);
7498 check_sample(output.pSample, nv12_frame_data, output_file);
7500 ret = IMFSample_Release(output.pSample);
7501 ok(ret == 0, "Release returned %lu\n", ret);
7503 trace("created %s\n", debugstr_w(output_path));
7504 CloseHandle(output_file);
7506 /* we can change it, but only with the correct frame size */
7507 hr = MFCreateMediaType(&media_type);
7508 ok(hr == S_OK, "MFCreateMediaType returned %#lx\n", hr);
7509 init_media_type(media_type, is_win7 ? output_type_desc_win7 : output_type_desc, -1);
7510 hr = IMFTransform_SetOutputType(transform, 0, media_type, 0);
7511 ok(hr == MF_E_INVALIDMEDIATYPE, "SetOutputType returned %#lx.\n", hr);
7512 init_media_type(media_type, is_win7 ? new_output_type_desc_win7 : new_output_type_desc, -1);
7513 hr = IMFTransform_SetOutputType(transform, 0, media_type, 0);
7514 ok(hr == S_OK, "SetOutputType returned %#lx.\n", hr);
7515 ret = IMFMediaType_Release(media_type);
7516 ok(ret == 1, "Release returned %lu\n", ret);
7518 hr = IMFTransform_GetOutputCurrentType(transform, 0, &media_type);
7519 ok(hr == S_OK, "GetOutputCurrentType returned %#lx\n", hr);
7520 check_media_type(media_type, is_win7 ? new_output_type_desc_win7 : new_output_type_desc, -1);
7521 hr = IMFMediaType_GetItemType(media_type, &MF_MT_MINIMUM_DISPLAY_APERTURE, NULL);
7522 ok(hr == MF_E_ATTRIBUTENOTFOUND, "GetItemType returned %#lx\n", hr);
7523 ret = IMFMediaType_Release(media_type);
7524 ok(ret == 0, "Release returned %lu\n", ret);
7526 status = 0;
7527 memset(&output, 0, sizeof(output));
7528 output.pSample = create_sample(NULL, actual_width * actual_height * 2);
7529 hr = IMFTransform_ProcessOutput(transform, 0, 1, &output, &status);
7530 todo_wine
7531 ok(hr == MF_E_TRANSFORM_STREAM_CHANGE, "ProcessOutput returned %#lx\n", hr);
7533 if (hr == MF_E_TRANSFORM_NEED_MORE_INPUT)
7535 hr = IMFTransform_ProcessInput(transform, 0, sample, 0);
7536 ok(hr == S_OK, "ProcessInput returned %#lx\n", hr);
7537 ret = IMFSample_Release(sample);
7538 ok(ret <= 1, "Release returned %lu\n", ret);
7539 sample = next_h264_sample(&h264_encoded_data, &h264_encoded_data_len);
7540 hr = IMFTransform_ProcessOutput(transform, 0, 1, &output, &status);
7541 todo_wine
7542 ok(hr == MF_E_TRANSFORM_STREAM_CHANGE, "ProcessOutput returned %#lx\n", hr);
7545 ok(output.dwStreamID == 0, "got dwStreamID %lu\n", output.dwStreamID);
7546 ok(!!output.pSample, "got pSample %p\n", output.pSample);
7547 todo_wine
7548 ok(output.dwStatus == MFT_OUTPUT_DATA_BUFFER_FORMAT_CHANGE, "got dwStatus %#lx\n", output.dwStatus);
7549 ok(!output.pEvents, "got pEvents %p\n", output.pEvents);
7550 todo_wine
7551 ok(status == MFT_PROCESS_OUTPUT_STATUS_NEW_STREAMS, "got status %#lx\n", status);
7552 hr = IMFSample_GetTotalLength(output.pSample, &length);
7553 ok(hr == S_OK, "GetTotalLength returned %#lx\n", hr);
7554 ok(length == 0, "got length %lu\n", length);
7555 ret = IMFSample_Release(output.pSample);
7556 ok(ret == 0, "Release returned %lu\n", ret);
7558 GetTempPathW(ARRAY_SIZE(output_path), output_path);
7559 lstrcatW(output_path, L"i420frame.bin");
7560 output_file = CreateFileW(output_path, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0);
7561 ok(output_file != INVALID_HANDLE_VALUE, "CreateFileW failed, error %lu\n", GetLastError());
7563 resource = FindResourceW(NULL, L"i420frame.bin", (const WCHAR *)RT_RCDATA);
7564 ok(resource != 0, "FindResourceW failed, error %lu\n", GetLastError());
7565 i420_frame_data = LockResource(LoadResource(GetModuleHandleW(NULL), resource));
7566 i420_frame_len = SizeofResource(GetModuleHandleW(NULL), resource);
7567 ok(i420_frame_len == actual_width * actual_height * 3 / 2, "got frame length %lu\n", i420_frame_len);
7569 status = 0;
7570 memset(&output, 0, sizeof(output));
7571 output.pSample = create_sample(NULL, actual_width * actual_height * 2);
7572 hr = IMFTransform_ProcessOutput(transform, 0, 1, &output, &status);
7573 todo_wine
7574 ok(hr == S_OK, "ProcessOutput returned %#lx\n", hr);
7575 ok(output.dwStreamID == 0, "got dwStreamID %lu\n", output.dwStreamID);
7576 ok(!!output.pSample, "got pSample %p\n", output.pSample);
7577 ok(output.dwStatus == 0, "got dwStatus %#lx\n", output.dwStatus);
7578 ok(!output.pEvents, "got pEvents %p\n", output.pEvents);
7579 ok(status == 0, "got status %#lx\n", status);
7580 if (hr != S_OK) goto skip_i420_tests;
7582 hr = IMFSample_GetSampleTime(output.pSample, &time);
7583 ok(hr == S_OK, "GetSampleTime returned %#lx\n", hr);
7584 ok(time - 333666 <= 2, "got time %I64d\n", time);
7586 duration = 0xdeadbeef;
7587 hr = IMFSample_GetSampleDuration(output.pSample, &duration);
7588 ok(hr == S_OK, "GetSampleDuration returned %#lx\n", hr);
7589 ok(duration - 333666 <= 2, "got duration %I64d\n", duration);
7591 /* Win8 and before pad the data with garbage instead of original
7592 * buffer data, make sure it's consistent. */
7593 hr = IMFSample_ConvertToContiguousBuffer(output.pSample, &media_buffer);
7594 ok(hr == S_OK, "ConvertToContiguousBuffer returned %#lx\n", hr);
7595 hr = IMFMediaBuffer_Lock(media_buffer, &data, NULL, &length);
7596 ok(hr == S_OK, "Lock returned %#lx\n", hr);
7597 ok(length == i420_frame_len, "got length %lu\n", length);
7599 for (i = 0; i < actual_aperture.Area.cy; ++i)
7601 memset(data + actual_width * i + actual_aperture.Area.cx, 0xcd, actual_width - actual_aperture.Area.cx);
7602 memset(data + actual_width * actual_height + actual_width / 2 * i + actual_aperture.Area.cx / 2, 0xcd,
7603 actual_width / 2 - actual_aperture.Area.cx / 2);
7604 memset(data + actual_width * actual_height + actual_width / 2 * (actual_height / 2 + i) + actual_aperture.Area.cx / 2, 0xcd,
7605 actual_width / 2 - actual_aperture.Area.cx / 2);
7607 memset(data + actual_width * actual_aperture.Area.cy, 0xcd, (actual_height - actual_aperture.Area.cy) * actual_width);
7608 memset(data + actual_width * actual_height + actual_width / 2 * actual_aperture.Area.cy / 2, 0xcd,
7609 (actual_height - actual_aperture.Area.cy) / 2 * actual_width / 2);
7610 memset(data + actual_width * actual_height + actual_width / 2 * (actual_height / 2 + actual_aperture.Area.cy / 2), 0xcd,
7611 (actual_height - actual_aperture.Area.cy) / 2 * actual_width / 2);
7613 hr = IMFMediaBuffer_Unlock(media_buffer);
7614 ok(hr == S_OK, "Unlock returned %#lx\n", hr);
7615 IMFMediaBuffer_Release(media_buffer);
7617 check_sample(output.pSample, i420_frame_data, output_file);
7619 skip_i420_tests:
7620 ret = IMFSample_Release(output.pSample);
7621 ok(ret == 0, "Release returned %lu\n", ret);
7623 trace("created %s\n", debugstr_w(output_path));
7624 CloseHandle(output_file);
7626 status = 0;
7627 memset(&output, 0, sizeof(output));
7628 output.pSample = create_sample(NULL, actual_width * actual_height * 2);
7629 hr = IMFTransform_ProcessOutput(transform, 0, 1, &output, &status);
7630 ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "ProcessOutput returned %#lx\n", hr);
7631 ok(output.dwStreamID == 0, "got dwStreamID %lu\n", output.dwStreamID);
7632 ok(!!output.pSample, "got pSample %p\n", output.pSample);
7633 ok(output.dwStatus == 0, "got dwStatus %#lx\n", output.dwStatus);
7634 ok(!output.pEvents, "got pEvents %p\n", output.pEvents);
7635 ok(status == 0, "got status %#lx\n", status);
7636 ret = IMFSample_Release(output.pSample);
7637 ok(ret == 0, "Release returned %lu\n", ret);
7639 ret = IMFTransform_Release(transform);
7640 ok(ret == 0, "Release returned %lu\n", ret);
7641 ret = IMFSample_Release(sample);
7642 ok(ret == 0, "Release returned %lu\n", ret);
7644 failed:
7645 CoUninitialize();
7648 static void test_audio_convert(void)
7650 const GUID transform_inputs[2] =
7652 MFAudioFormat_PCM,
7653 MFAudioFormat_Float,
7655 const GUID transform_outputs[2] =
7657 MFAudioFormat_PCM,
7658 MFAudioFormat_Float,
7661 static const media_type_desc expect_available_inputs[] =
7664 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
7665 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_Float),
7666 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
7669 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
7670 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_PCM),
7671 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
7674 static const media_type_desc expect_available_outputs[] =
7677 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
7678 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_Float),
7679 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
7682 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
7683 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_PCM),
7684 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
7687 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
7688 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_Float),
7689 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 32),
7690 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 2),
7691 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 48000),
7692 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 384000),
7693 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 8),
7694 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
7695 ATTR_UINT32(MF_MT_AUDIO_PREFER_WAVEFORMATEX, 1),
7698 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
7699 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_PCM),
7700 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 16),
7701 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 2),
7702 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 48000),
7703 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 192000),
7704 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 4),
7705 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
7706 ATTR_UINT32(MF_MT_AUDIO_PREFER_WAVEFORMATEX, 1),
7710 static const struct attribute_desc input_type_desc[] =
7712 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
7713 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_Float),
7714 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 32),
7715 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 2),
7716 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 22050),
7717 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 176400),
7718 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 8),
7719 {0},
7721 const struct attribute_desc output_type_desc[] =
7723 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
7724 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_PCM),
7725 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 16),
7726 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 2),
7727 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 44100),
7728 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 176400),
7729 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 4),
7730 {0},
7733 MFT_REGISTER_TYPE_INFO output_type = {MFMediaType_Audio, MFAudioFormat_PCM};
7734 MFT_REGISTER_TYPE_INFO input_type = {MFMediaType_Audio, MFAudioFormat_Float};
7735 static const ULONG audioconv_block_size = 0x4000;
7736 ULONG audio_data_len, audioconv_data_len;
7737 const BYTE *audio_data, *audioconv_data;
7738 MFT_OUTPUT_STREAM_INFO output_info;
7739 MFT_INPUT_STREAM_INFO input_info;
7740 MFT_OUTPUT_DATA_BUFFER output;
7741 WCHAR output_path[MAX_PATH];
7742 IMFMediaType *media_type;
7743 LONGLONG time, duration;
7744 IMFTransform *transform;
7745 DWORD length, status;
7746 HANDLE output_file;
7747 IMFSample *sample;
7748 HRSRC resource;
7749 GUID class_id;
7750 ULONG i, ret;
7751 HRESULT hr;
7753 hr = CoInitialize(NULL);
7754 ok(hr == S_OK, "Failed to initialize, hr %#lx.\n", hr);
7756 if (!create_transform(MFT_CATEGORY_AUDIO_EFFECT, &input_type, &output_type, L"Resampler MFT", &MFMediaType_Audio,
7757 transform_inputs, ARRAY_SIZE(transform_inputs), transform_outputs, ARRAY_SIZE(transform_outputs),
7758 &transform, &CLSID_CResamplerMediaObject, &class_id))
7759 goto failed;
7761 check_dmo(&class_id, L"Resampler DMO", &MEDIATYPE_Audio, transform_inputs, ARRAY_SIZE(transform_inputs),
7762 transform_outputs, ARRAY_SIZE(transform_outputs));
7764 check_interface(transform, &IID_IMFTransform, TRUE);
7765 check_interface(transform, &IID_IMediaObject, TRUE);
7766 check_interface(transform, &IID_IPropertyStore, TRUE);
7767 check_interface(transform, &IID_IPropertyBag, TRUE);
7768 /* check_interface(transform, &IID_IWMResamplerProps, TRUE); */
7770 /* check default media types */
7772 hr = IMFTransform_GetInputStreamInfo(transform, 0, &input_info);
7773 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "GetInputStreamInfo returned %#lx\n", hr);
7774 hr = IMFTransform_GetOutputStreamInfo(transform, 0, &output_info);
7775 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "GetOutputStreamInfo returned %#lx\n", hr);
7777 i = -1;
7778 while (SUCCEEDED(hr = IMFTransform_GetOutputAvailableType(transform, 0, ++i, &media_type)))
7780 winetest_push_context("out %lu", i);
7781 ok(hr == S_OK, "GetOutputAvailableType returned %#lx\n", hr);
7782 check_media_type(media_type, expect_available_outputs[i], -1);
7783 ret = IMFMediaType_Release(media_type);
7784 ok(ret == 0, "Release returned %lu\n", ret);
7785 winetest_pop_context();
7787 ok(hr == MF_E_NO_MORE_TYPES, "GetOutputAvailableType returned %#lx\n", hr);
7788 ok(i == 4, "%lu output media types\n", i);
7790 i = -1;
7791 while (SUCCEEDED(hr = IMFTransform_GetInputAvailableType(transform, 0, ++i, &media_type)))
7793 winetest_push_context("in %lu", i);
7794 ok(hr == S_OK, "GetInputAvailableType returned %#lx\n", hr);
7795 check_media_type(media_type, expect_available_inputs[i], -1);
7796 hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
7797 ok(hr == MF_E_INVALIDMEDIATYPE, "SetInputType returned %#lx.\n", hr);
7798 ret = IMFMediaType_Release(media_type);
7799 ok(ret == 0, "Release returned %lu\n", ret);
7800 winetest_pop_context();
7802 ok(hr == MF_E_NO_MORE_TYPES, "GetInputAvailableType returned %#lx\n", hr);
7803 ok(i == 2, "%lu input media types\n", i);
7805 /* setting output media type first doesn't work */
7807 hr = MFCreateMediaType(&media_type);
7808 ok(hr == S_OK, "MFCreateMediaType returned %#lx\n", hr);
7809 init_media_type(media_type, output_type_desc, -1);
7810 hr = IMFTransform_SetOutputType(transform, 0, media_type, 0);
7811 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "SetOutputType returned %#lx.\n", hr);
7812 ret = IMFMediaType_Release(media_type);
7813 ok(ret == 0, "Release returned %lu\n", ret);
7815 /* check required input media type attributes */
7817 hr = MFCreateMediaType(&media_type);
7818 ok(hr == S_OK, "MFCreateMediaType returned %#lx\n", hr);
7819 hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
7820 ok(hr == MF_E_ATTRIBUTENOTFOUND, "SetInputType returned %#lx.\n", hr);
7821 init_media_type(media_type, input_type_desc, 1);
7822 hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
7823 ok(hr == MF_E_ATTRIBUTENOTFOUND, "SetInputType returned %#lx.\n", hr);
7824 init_media_type(media_type, input_type_desc, 2);
7825 for (i = 2; i < ARRAY_SIZE(input_type_desc) - 1; ++i)
7827 hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
7828 ok(hr == MF_E_INVALIDMEDIATYPE, "SetInputType returned %#lx.\n", hr);
7829 init_media_type(media_type, input_type_desc, i + 1);
7831 hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
7832 ok(hr == S_OK, "SetInputType returned %#lx.\n", hr);
7833 ret = IMFMediaType_Release(media_type);
7834 ok(ret == 0, "Release returned %lu\n", ret);
7836 hr = IMFTransform_GetInputStreamInfo(transform, 0, &input_info);
7837 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "GetInputStreamInfo returned %#lx\n", hr);
7838 hr = IMFTransform_GetOutputStreamInfo(transform, 0, &output_info);
7839 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "GetOutputStreamInfo returned %#lx\n", hr);
7841 /* check new output media types */
7843 i = -1;
7844 while (SUCCEEDED(hr = IMFTransform_GetOutputAvailableType(transform, 0, ++i, &media_type)))
7846 winetest_push_context("out %lu", i);
7847 ok(hr == S_OK, "GetOutputAvailableType returned %#lx\n", hr);
7848 check_media_type(media_type, expect_available_outputs[i], -1);
7849 ret = IMFMediaType_Release(media_type);
7850 ok(ret == 0, "Release returned %lu\n", ret);
7851 winetest_pop_context();
7853 ok(hr == MF_E_NO_MORE_TYPES, "GetOutputAvailableType returned %#lx\n", hr);
7854 ok(i == 4, "%lu output media types\n", i);
7856 /* check required output media type attributes */
7858 hr = MFCreateMediaType(&media_type);
7859 ok(hr == S_OK, "MFCreateMediaType returned %#lx\n", hr);
7860 hr = IMFTransform_SetOutputType(transform, 0, media_type, 0);
7861 ok(hr == MF_E_ATTRIBUTENOTFOUND, "SetOutputType returned %#lx.\n", hr);
7862 init_media_type(media_type, output_type_desc, 1);
7863 hr = IMFTransform_SetOutputType(transform, 0, media_type, 0);
7864 ok(hr == MF_E_ATTRIBUTENOTFOUND, "SetOutputType returned %#lx.\n", hr);
7865 init_media_type(media_type, output_type_desc, 2);
7866 for (i = 2; i < ARRAY_SIZE(output_type_desc) - 1; ++i)
7868 hr = IMFTransform_SetOutputType(transform, 0, media_type, 0);
7869 ok(hr == MF_E_INVALIDMEDIATYPE, "SetOutputType returned %#lx.\n", hr);
7870 init_media_type(media_type, output_type_desc, i + 1);
7872 hr = IMFTransform_SetOutputType(transform, 0, media_type, 0);
7873 ok(hr == S_OK, "SetOutputType returned %#lx.\n", hr);
7874 ret = IMFMediaType_Release(media_type);
7875 ok(ret == 0, "Release returned %lu\n", ret);
7877 memset(&input_info, 0xcd, sizeof(input_info));
7878 hr = IMFTransform_GetInputStreamInfo(transform, 0, &input_info);
7879 ok(hr == S_OK, "GetInputStreamInfo returned %#lx\n", hr);
7880 ok(input_info.hnsMaxLatency == 0, "got hnsMaxLatency %s\n", wine_dbgstr_longlong(input_info.hnsMaxLatency));
7881 ok(input_info.dwFlags == 0, "got dwFlags %#lx\n", input_info.dwFlags);
7882 ok(input_info.cbSize == 8, "got cbSize %lu\n", input_info.cbSize);
7883 ok(input_info.cbMaxLookahead == 0, "got cbMaxLookahead %#lx\n", input_info.cbMaxLookahead);
7884 ok(input_info.cbAlignment == 1, "got cbAlignment %#lx\n", input_info.cbAlignment);
7886 memset(&output_info, 0xcd, sizeof(output_info));
7887 hr = IMFTransform_GetOutputStreamInfo(transform, 0, &output_info);
7888 ok(hr == S_OK, "GetOutputStreamInfo returned %#lx\n", hr);
7889 ok(output_info.dwFlags == 0, "got dwFlags %#lx\n", output_info.dwFlags);
7890 ok(output_info.cbSize == 4, "got cbSize %#lx\n", output_info.cbSize);
7891 ok(output_info.cbAlignment == 1, "got cbAlignment %#lx\n", output_info.cbAlignment);
7893 resource = FindResourceW(NULL, L"audiodata.bin", (const WCHAR *)RT_RCDATA);
7894 ok(resource != 0, "FindResourceW failed, error %lu\n", GetLastError());
7895 audio_data = LockResource(LoadResource(GetModuleHandleW(NULL), resource));
7896 audio_data_len = SizeofResource(GetModuleHandleW(NULL), resource);
7897 ok(audio_data_len == 179928, "got length %lu\n", audio_data_len);
7899 sample = create_sample(audio_data, audio_data_len);
7900 hr = IMFSample_SetSampleTime(sample, 0);
7901 ok(hr == S_OK, "SetSampleTime returned %#lx\n", hr);
7902 hr = IMFSample_SetSampleDuration(sample, 10000000);
7903 ok(hr == S_OK, "SetSampleDuration returned %#lx\n", hr);
7904 hr = IMFTransform_ProcessInput(transform, 0, sample, 0);
7905 ok(hr == S_OK, "ProcessInput returned %#lx\n", hr);
7906 hr = IMFTransform_ProcessMessage(transform, MFT_MESSAGE_COMMAND_DRAIN, 0);
7907 ok(hr == S_OK, "ProcessMessage returned %#lx\n", hr);
7908 hr = IMFTransform_ProcessInput(transform, 0, sample, 0);
7909 ok(hr == MF_E_NOTACCEPTING, "ProcessInput returned %#lx\n", hr);
7910 ret = IMFSample_Release(sample);
7911 ok(ret <= 1, "Release returned %ld\n", ret);
7913 status = 0xdeadbeef;
7914 sample = create_sample(NULL, audioconv_block_size);
7915 memset(&output, 0, sizeof(output));
7916 output.pSample = sample;
7918 resource = FindResourceW(NULL, L"audioconvdata.bin", (const WCHAR *)RT_RCDATA);
7919 ok(resource != 0, "FindResourceW failed, error %lu\n", GetLastError());
7920 audioconv_data = LockResource(LoadResource(GetModuleHandleW(NULL), resource));
7921 audioconv_data_len = SizeofResource(GetModuleHandleW(NULL), resource);
7922 ok(audioconv_data_len == 179924, "got length %lu\n", audioconv_data_len);
7924 /* and generate a new one as well in a temporary directory */
7925 GetTempPathW(ARRAY_SIZE(output_path), output_path);
7926 lstrcatW(output_path, L"audioconvdata.bin");
7927 output_file = CreateFileW(output_path, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0);
7928 ok(output_file != INVALID_HANDLE_VALUE, "CreateFileW failed, error %lu\n", GetLastError());
7930 i = 0;
7931 while (SUCCEEDED(hr = IMFTransform_ProcessOutput(transform, 0, 1, &output, &status)))
7933 winetest_push_context("%lu", i);
7934 ok(hr == S_OK, "ProcessOutput returned %#lx\n", hr);
7935 ok(output.pSample == sample, "got pSample %p\n", output.pSample);
7936 ok(output.dwStatus == MFT_OUTPUT_DATA_BUFFER_INCOMPLETE || output.dwStatus == 0 ||
7937 broken(output.dwStatus == (MFT_OUTPUT_DATA_BUFFER_INCOMPLETE|6) || output.dwStatus == 6) /* win7 */,
7938 "got dwStatus %#lx\n", output.dwStatus);
7939 ok(status == 0, "got status %#lx\n", status);
7940 if (!(output.dwStatus & MFT_OUTPUT_DATA_BUFFER_INCOMPLETE))
7942 winetest_pop_context();
7943 break;
7946 hr = IMFSample_GetSampleTime(sample, &time);
7947 ok(hr == S_OK, "GetSampleTime returned %#lx\n", hr);
7948 ok(time == i * 928798, "got time %I64d\n", time);
7949 hr = IMFSample_GetSampleDuration(sample, &duration);
7950 ok(hr == S_OK, "GetSampleDuration returned %#lx\n", hr);
7951 ok(duration == 928798, "got duration %I64d\n", duration);
7952 hr = IMFSample_GetTotalLength(sample, &length);
7953 ok(hr == S_OK, "GetTotalLength returned %#lx\n", hr);
7954 ok(length == audioconv_block_size, "got length %lu\n", length);
7955 ok(audioconv_data_len > audioconv_block_size, "got remaining length %lu\n", audioconv_data_len);
7956 check_sample_pcm16(sample, audioconv_data, output_file, FALSE);
7957 audioconv_data_len -= audioconv_block_size;
7958 audioconv_data += audioconv_block_size;
7960 winetest_pop_context();
7961 i++;
7964 hr = IMFSample_GetSampleTime(sample, &time);
7965 ok(hr == S_OK, "GetSampleTime returned %#lx\n", hr);
7966 ok(time == i * 928798, "got time %I64d\n", time);
7967 hr = IMFSample_GetSampleDuration(sample, &duration);
7968 ok(hr == S_OK, "GetSampleDuration returned %#lx\n", hr);
7969 todo_wine
7970 ok(duration == 897506, "got duration %I64d\n", duration);
7971 hr = IMFSample_GetTotalLength(sample, &length);
7972 ok(hr == S_OK, "GetTotalLength returned %#lx\n", hr);
7973 todo_wine
7974 ok(length == 15832, "got length %lu\n", length);
7975 ok(audioconv_data_len == 16084, "got remaining length %lu\n", audioconv_data_len);
7976 check_sample_pcm16(sample, audioconv_data, output_file, FALSE);
7977 audioconv_data_len -= length;
7978 audioconv_data += length;
7980 memset(&output, 0, sizeof(output));
7981 output.pSample = sample;
7982 hr = IMFTransform_ProcessOutput(transform, 0, 1, &output, &status);
7983 todo_wine
7984 ok(hr == S_OK || broken(hr == MF_E_TRANSFORM_NEED_MORE_INPUT) /* win7 */, "ProcessOutput returned %#lx\n", hr);
7985 ok(output.pSample == sample, "got pSample %p\n", output.pSample);
7986 todo_wine
7987 ok(output.dwStatus == MFT_OUTPUT_DATA_BUFFER_INCOMPLETE || broken(output.dwStatus == 0) /* win7 */,
7988 "got dwStatus %#lx\n", output.dwStatus);
7989 ok(status == 0, "got status %#lx\n", status);
7991 if (hr == S_OK)
7993 hr = IMFSample_GetSampleTime(sample, &time);
7994 ok(hr == S_OK, "GetSampleTime returned %#lx\n", hr);
7995 todo_wine
7996 ok(time == 10185486, "got time %I64d\n", time);
7997 hr = IMFSample_GetSampleDuration(sample, &duration);
7998 ok(hr == S_OK, "GetSampleDuration returned %#lx\n", hr);
7999 todo_wine
8000 ok(duration == 14286, "got duration %I64d\n", duration);
8001 hr = IMFSample_GetTotalLength(sample, &length);
8002 ok(hr == S_OK, "GetTotalLength returned %#lx\n", hr);
8003 todo_wine
8004 ok(length == audioconv_data_len, "got length %lu\n", length);
8005 if (length == audioconv_data_len)
8006 check_sample_pcm16(sample, audioconv_data, output_file, FALSE);
8009 trace("created %s\n", debugstr_w(output_path));
8010 CloseHandle(output_file);
8012 ret = IMFSample_Release(sample);
8013 ok(ret == 0, "Release returned %lu\n", ret);
8015 status = 0xdeadbeef;
8016 sample = create_sample(NULL, audioconv_block_size);
8017 memset(&output, 0, sizeof(output));
8018 output.pSample = sample;
8019 hr = IMFTransform_ProcessOutput(transform, 0, 1, &output, &status);
8020 ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "ProcessOutput returned %#lx\n", hr);
8021 ok(output.pSample == sample, "got pSample %p\n", output.pSample);
8022 ok(output.dwStatus == 0, "got dwStatus %#lx\n", output.dwStatus);
8023 ok(status == 0, "got status %#lx\n", status);
8024 hr = IMFSample_GetTotalLength(sample, &length);
8025 ok(hr == S_OK, "GetTotalLength returned %#lx\n", hr);
8026 ok(length == 0, "got length %lu\n", length);
8027 ret = IMFSample_Release(sample);
8028 ok(ret == 0, "Release returned %lu\n", ret);
8030 ret = IMFTransform_Release(transform);
8031 ok(ret == 0, "Release returned %lu\n", ret);
8033 failed:
8034 CoUninitialize();
8037 static void test_color_convert(void)
8039 const GUID transform_inputs[20] =
8041 MFVideoFormat_YV12,
8042 MFVideoFormat_YUY2,
8043 MFVideoFormat_UYVY,
8044 MFVideoFormat_AYUV,
8045 MFVideoFormat_NV12,
8046 DMOVideoFormat_RGB32,
8047 DMOVideoFormat_RGB565,
8048 MFVideoFormat_I420,
8049 MFVideoFormat_IYUV,
8050 MFVideoFormat_YVYU,
8051 DMOVideoFormat_RGB24,
8052 DMOVideoFormat_RGB555,
8053 DMOVideoFormat_RGB8,
8054 MEDIASUBTYPE_V216,
8055 MEDIASUBTYPE_V410,
8056 MFVideoFormat_NV11,
8057 MFVideoFormat_Y41P,
8058 MFVideoFormat_Y41T,
8059 MFVideoFormat_Y42T,
8060 MFVideoFormat_YVU9,
8062 const GUID transform_outputs[16] =
8064 MFVideoFormat_YV12,
8065 MFVideoFormat_YUY2,
8066 MFVideoFormat_UYVY,
8067 MFVideoFormat_AYUV,
8068 MFVideoFormat_NV12,
8069 DMOVideoFormat_RGB32,
8070 DMOVideoFormat_RGB565,
8071 MFVideoFormat_I420,
8072 MFVideoFormat_IYUV,
8073 MFVideoFormat_YVYU,
8074 DMOVideoFormat_RGB24,
8075 DMOVideoFormat_RGB555,
8076 DMOVideoFormat_RGB8,
8077 MEDIASUBTYPE_V216,
8078 MEDIASUBTYPE_V410,
8079 MFVideoFormat_NV11,
8081 const GUID dmo_inputs[20] =
8083 MEDIASUBTYPE_YV12,
8084 MEDIASUBTYPE_YUY2,
8085 MEDIASUBTYPE_UYVY,
8086 MEDIASUBTYPE_AYUV,
8087 MEDIASUBTYPE_NV12,
8088 MEDIASUBTYPE_RGB32,
8089 MEDIASUBTYPE_RGB565,
8090 MEDIASUBTYPE_I420,
8091 MEDIASUBTYPE_IYUV,
8092 MEDIASUBTYPE_YVYU,
8093 MEDIASUBTYPE_RGB24,
8094 MEDIASUBTYPE_RGB555,
8095 MEDIASUBTYPE_RGB8,
8096 MEDIASUBTYPE_V216,
8097 MEDIASUBTYPE_V410,
8098 MEDIASUBTYPE_NV11,
8099 MEDIASUBTYPE_Y41P,
8100 MEDIASUBTYPE_Y41T,
8101 MEDIASUBTYPE_Y42T,
8102 MEDIASUBTYPE_YVU9,
8104 const GUID dmo_outputs[16] =
8106 MEDIASUBTYPE_YV12,
8107 MEDIASUBTYPE_YUY2,
8108 MEDIASUBTYPE_UYVY,
8109 MEDIASUBTYPE_AYUV,
8110 MEDIASUBTYPE_NV12,
8111 MEDIASUBTYPE_RGB32,
8112 MEDIASUBTYPE_RGB565,
8113 MEDIASUBTYPE_I420,
8114 MEDIASUBTYPE_IYUV,
8115 MEDIASUBTYPE_YVYU,
8116 MEDIASUBTYPE_RGB24,
8117 MEDIASUBTYPE_RGB555,
8118 MEDIASUBTYPE_RGB8,
8119 MEDIASUBTYPE_V216,
8120 MEDIASUBTYPE_V410,
8121 MEDIASUBTYPE_NV11,
8124 static const media_type_desc expect_available_inputs[20] =
8126 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_YV12), },
8127 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_YUY2), },
8128 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_UYVY), },
8129 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_AYUV), },
8130 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_NV12), },
8131 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_RGB32), },
8132 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_RGB565), },
8133 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_I420), },
8134 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_IYUV), },
8135 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_YVYU), },
8136 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_RGB24), },
8137 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_RGB555), },
8138 { ATTR_GUID(MF_MT_SUBTYPE, MEDIASUBTYPE_RGB8), },
8139 { ATTR_GUID(MF_MT_SUBTYPE, MEDIASUBTYPE_V216), },
8140 { ATTR_GUID(MF_MT_SUBTYPE, MEDIASUBTYPE_V410), },
8141 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_NV11), },
8142 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_Y41P), },
8143 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_Y41T), },
8144 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_Y42T), },
8145 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_YVU9), },
8147 static const media_type_desc expect_available_outputs[16] =
8149 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_YV12), },
8150 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_YUY2), },
8151 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_UYVY), },
8152 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_AYUV), },
8153 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_NV12), },
8154 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_RGB32), },
8155 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_RGB565), },
8156 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_I420), },
8157 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_IYUV), },
8158 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_YVYU), },
8159 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_RGB24), },
8160 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_RGB555), },
8161 { ATTR_GUID(MF_MT_SUBTYPE, MEDIASUBTYPE_RGB8), },
8162 { ATTR_GUID(MF_MT_SUBTYPE, MEDIASUBTYPE_V216), },
8163 { ATTR_GUID(MF_MT_SUBTYPE, MEDIASUBTYPE_V410), },
8164 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_NV11), },
8166 static const media_type_desc expect_available_common =
8168 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
8169 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
8170 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
8173 static const MFVideoArea actual_aperture = {.Area={82,84}};
8174 static const DWORD actual_width = 96, actual_height = 96;
8175 const struct attribute_desc input_type_desc[] =
8177 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
8178 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_NV12),
8179 ATTR_BLOB(MF_MT_MINIMUM_DISPLAY_APERTURE, &actual_aperture, 16),
8180 ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height),
8181 {0},
8183 const struct attribute_desc output_type_desc[] =
8185 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
8186 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_RGB32),
8187 ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height),
8188 {0},
8191 MFT_REGISTER_TYPE_INFO output_type = {MFMediaType_Video, MFVideoFormat_NV12};
8192 MFT_REGISTER_TYPE_INFO input_type = {MFMediaType_Video, MFVideoFormat_I420};
8193 ULONG nv12frame_data_len, rgb32_data_len;
8194 const BYTE *nv12frame_data, *rgb32_data;
8195 MFT_OUTPUT_STREAM_INFO output_info;
8196 MFT_INPUT_STREAM_INFO input_info;
8197 MFT_OUTPUT_DATA_BUFFER output;
8198 WCHAR output_path[MAX_PATH];
8199 IMFMediaType *media_type;
8200 LONGLONG time, duration;
8201 IMFTransform *transform;
8202 DWORD length, status;
8203 HANDLE output_file;
8204 IMFSample *sample;
8205 HRSRC resource;
8206 GUID class_id;
8207 ULONG i, ret;
8208 HRESULT hr;
8210 hr = CoInitialize(NULL);
8211 ok(hr == S_OK, "Failed to initialize, hr %#lx.\n", hr);
8213 if (!create_transform(MFT_CATEGORY_VIDEO_EFFECT, &input_type, &output_type, L"Color Converter MFT", &MFMediaType_Video,
8214 transform_inputs, ARRAY_SIZE(transform_inputs), transform_outputs, ARRAY_SIZE(transform_outputs),
8215 &transform, &CLSID_CColorConvertDMO, &class_id))
8216 goto failed;
8218 check_dmo(&CLSID_CColorConvertDMO, L"Color Converter DMO", &MEDIATYPE_Video, dmo_inputs, ARRAY_SIZE(dmo_inputs),
8219 dmo_outputs, ARRAY_SIZE(dmo_outputs));
8221 check_interface(transform, &IID_IMFTransform, TRUE);
8222 check_interface(transform, &IID_IMediaObject, TRUE);
8223 check_interface(transform, &IID_IPropertyStore, TRUE);
8224 todo_wine
8225 check_interface(transform, &IID_IMFRealTimeClient, TRUE);
8226 /* check_interface(transform, &IID_IWMColorConvProps, TRUE); */
8228 /* check default media types */
8230 hr = IMFTransform_GetInputStreamInfo(transform, 0, &input_info);
8231 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "GetInputStreamInfo returned %#lx\n", hr);
8232 hr = IMFTransform_GetOutputStreamInfo(transform, 0, &output_info);
8233 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "GetOutputStreamInfo returned %#lx\n", hr);
8235 i = -1;
8236 while (SUCCEEDED(hr = IMFTransform_GetOutputAvailableType(transform, 0, ++i, &media_type)))
8238 winetest_push_context("out %lu", i);
8239 ok(hr == S_OK, "GetOutputAvailableType returned %#lx\n", hr);
8240 check_media_type(media_type, expect_available_common, -1);
8241 check_media_type(media_type, expect_available_outputs[i], -1);
8242 ret = IMFMediaType_Release(media_type);
8243 ok(ret == 0, "Release returned %lu\n", ret);
8244 winetest_pop_context();
8246 ok(hr == MF_E_NO_MORE_TYPES, "GetOutputAvailableType returned %#lx\n", hr);
8247 ok(i == 16, "%lu output media types\n", i);
8249 i = -1;
8250 while (SUCCEEDED(hr = IMFTransform_GetInputAvailableType(transform, 0, ++i, &media_type)))
8252 winetest_push_context("in %lu", i);
8253 ok(hr == S_OK, "GetInputAvailableType returned %#lx\n", hr);
8254 check_media_type(media_type, expect_available_common, -1);
8255 check_media_type(media_type, expect_available_inputs[i], -1);
8256 hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
8257 if (i == 12)
8259 todo_wine
8260 ok(hr == MF_E_INVALIDMEDIATYPE, "SetInputType returned %#lx.\n", hr);
8262 else
8263 ok(hr == E_INVALIDARG, "SetInputType returned %#lx.\n", hr);
8264 ret = IMFMediaType_Release(media_type);
8265 ok(ret == 0, "Release returned %lu\n", ret);
8266 winetest_pop_context();
8268 ok(hr == MF_E_NO_MORE_TYPES, "GetInputAvailableType returned %#lx\n", hr);
8269 ok(i == 20, "%lu input media types\n", i);
8271 /* check required output media type attributes */
8273 hr = MFCreateMediaType(&media_type);
8274 ok(hr == S_OK, "MFCreateMediaType returned %#lx\n", hr);
8275 hr = IMFTransform_SetOutputType(transform, 0, media_type, 0);
8276 ok(hr == MF_E_ATTRIBUTENOTFOUND, "SetOutputType returned %#lx.\n", hr);
8277 init_media_type(media_type, output_type_desc, 1);
8278 hr = IMFTransform_SetOutputType(transform, 0, media_type, 0);
8279 ok(hr == MF_E_ATTRIBUTENOTFOUND, "SetOutputType returned %#lx.\n", hr);
8280 init_media_type(media_type, output_type_desc, 2);
8281 for (i = 2; i < ARRAY_SIZE(output_type_desc) - 1; ++i)
8283 hr = IMFTransform_SetOutputType(transform, 0, media_type, 0);
8284 ok(hr == E_INVALIDARG, "SetOutputType returned %#lx.\n", hr);
8285 init_media_type(media_type, output_type_desc, i + 1);
8287 hr = IMFTransform_SetOutputType(transform, 0, media_type, 0);
8288 ok(hr == S_OK, "SetOutputType returned %#lx.\n", hr);
8289 ret = IMFMediaType_Release(media_type);
8290 ok(ret == 0, "Release returned %lu\n", ret);
8292 /* check required input media type attributes */
8294 hr = MFCreateMediaType(&media_type);
8295 ok(hr == S_OK, "MFCreateMediaType returned %#lx\n", hr);
8296 hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
8297 ok(hr == MF_E_ATTRIBUTENOTFOUND, "SetInputType returned %#lx.\n", hr);
8298 init_media_type(media_type, input_type_desc, 1);
8299 hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
8300 ok(hr == MF_E_ATTRIBUTENOTFOUND, "SetInputType returned %#lx.\n", hr);
8301 init_media_type(media_type, input_type_desc, 2);
8302 for (i = 2; i < ARRAY_SIZE(input_type_desc) - 1; ++i)
8304 hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
8305 ok(hr == E_INVALIDARG, "SetInputType returned %#lx.\n", hr);
8306 init_media_type(media_type, input_type_desc, i + 1);
8308 hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
8309 ok(hr == S_OK, "SetInputType returned %#lx.\n", hr);
8310 ret = IMFMediaType_Release(media_type);
8311 ok(ret == 0, "Release returned %lu\n", ret);
8313 memset(&input_info, 0xcd, sizeof(input_info));
8314 hr = IMFTransform_GetInputStreamInfo(transform, 0, &input_info);
8315 ok(hr == S_OK, "GetInputStreamInfo returned %#lx\n", hr);
8316 ok(input_info.hnsMaxLatency == 0, "got hnsMaxLatency %s\n", wine_dbgstr_longlong(input_info.hnsMaxLatency));
8317 ok(input_info.dwFlags == 0, "got dwFlags %#lx\n", input_info.dwFlags);
8318 ok(input_info.cbSize == actual_width * actual_height * 3 / 2, "got cbSize %#lx\n", input_info.cbSize);
8319 ok(input_info.cbMaxLookahead == 0, "got cbMaxLookahead %#lx\n", input_info.cbMaxLookahead);
8320 ok(input_info.cbAlignment == 1, "got cbAlignment %#lx\n", input_info.cbAlignment);
8322 memset(&output_info, 0xcd, sizeof(output_info));
8323 hr = IMFTransform_GetOutputStreamInfo(transform, 0, &output_info);
8324 ok(hr == S_OK, "GetOutputStreamInfo returned %#lx\n", hr);
8325 ok(output_info.dwFlags == 0, "got dwFlags %#lx\n", output_info.dwFlags);
8326 ok(output_info.cbSize == actual_width * actual_height * 4, "got cbSize %#lx\n", output_info.cbSize);
8327 ok(output_info.cbAlignment == 1, "got cbAlignment %#lx\n", output_info.cbAlignment);
8329 resource = FindResourceW(NULL, L"nv12frame.bin", (const WCHAR *)RT_RCDATA);
8330 ok(resource != 0, "FindResourceW failed, error %lu\n", GetLastError());
8331 nv12frame_data = LockResource(LoadResource(GetModuleHandleW(NULL), resource));
8332 nv12frame_data_len = SizeofResource(GetModuleHandleW(NULL), resource);
8333 ok(nv12frame_data_len == 13824, "got length %lu\n", nv12frame_data_len);
8335 sample = create_sample(nv12frame_data, nv12frame_data_len);
8336 hr = IMFSample_SetSampleTime(sample, 0);
8337 ok(hr == S_OK, "SetSampleTime returned %#lx\n", hr);
8338 hr = IMFSample_SetSampleDuration(sample, 10000000);
8339 ok(hr == S_OK, "SetSampleDuration returned %#lx\n", hr);
8340 hr = IMFTransform_ProcessInput(transform, 0, sample, 0);
8341 ok(hr == S_OK, "ProcessInput returned %#lx\n", hr);
8342 hr = IMFTransform_ProcessInput(transform, 0, sample, 0);
8343 ok(hr == MF_E_NOTACCEPTING, "ProcessInput returned %#lx\n", hr);
8344 hr = IMFTransform_ProcessMessage(transform, MFT_MESSAGE_COMMAND_DRAIN, 0);
8345 ok(hr == S_OK, "ProcessMessage returned %#lx\n", hr);
8346 ret = IMFSample_Release(sample);
8347 ok(ret <= 1, "Release returned %ld\n", ret);
8349 resource = FindResourceW(NULL, L"rgb32frame.bin", (const WCHAR *)RT_RCDATA);
8350 ok(resource != 0, "FindResourceW failed, error %lu\n", GetLastError());
8351 rgb32_data = LockResource(LoadResource(GetModuleHandleW(NULL), resource));
8352 rgb32_data_len = SizeofResource(GetModuleHandleW(NULL), resource);
8353 ok(rgb32_data_len == output_info.cbSize, "got length %lu\n", rgb32_data_len);
8355 /* and generate a new one as well in a temporary directory */
8356 GetTempPathW(ARRAY_SIZE(output_path), output_path);
8357 lstrcatW(output_path, L"rgb32frame.bin");
8358 output_file = CreateFileW(output_path, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0);
8359 ok(output_file != INVALID_HANDLE_VALUE, "CreateFileW failed, error %lu\n", GetLastError());
8361 status = 0xdeadbeef;
8362 sample = create_sample(NULL, output_info.cbSize);
8363 memset(&output, 0, sizeof(output));
8364 output.pSample = sample;
8365 hr = IMFTransform_ProcessOutput(transform, 0, 1, &output, &status);
8366 ok(hr == S_OK, "ProcessOutput returned %#lx\n", hr);
8367 ok(output.pSample == sample, "got pSample %p\n", output.pSample);
8368 ok(output.dwStatus == 0 || broken(output.dwStatus == 6) /* win7 */, "got dwStatus %#lx\n", output.dwStatus);
8369 ok(status == 0, "got status %#lx\n", status);
8371 hr = IMFSample_GetSampleTime(sample, &time);
8372 ok(hr == S_OK, "GetSampleTime returned %#lx\n", hr);
8373 ok(time == 0, "got time %I64d\n", time);
8374 hr = IMFSample_GetSampleDuration(sample, &duration);
8375 ok(hr == S_OK, "GetSampleDuration returned %#lx\n", hr);
8376 ok(duration == 10000000, "got duration %I64d\n", duration);
8377 hr = IMFSample_GetTotalLength(sample, &length);
8378 ok(hr == S_OK, "GetTotalLength returned %#lx\n", hr);
8379 ok(length == output_info.cbSize, "got length %lu\n", length);
8380 check_sample_rgb32(sample, rgb32_data, output_file);
8381 rgb32_data_len -= output_info.cbSize;
8382 rgb32_data += output_info.cbSize;
8384 trace("created %s\n", debugstr_w(output_path));
8385 CloseHandle(output_file);
8387 ret = IMFSample_Release(sample);
8388 ok(ret == 0, "Release returned %lu\n", ret);
8390 status = 0xdeadbeef;
8391 sample = create_sample(NULL, output_info.cbSize);
8392 memset(&output, 0, sizeof(output));
8393 output.pSample = sample;
8394 hr = IMFTransform_ProcessOutput(transform, 0, 1, &output, &status);
8395 ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "ProcessOutput returned %#lx\n", hr);
8396 ok(output.pSample == sample, "got pSample %p\n", output.pSample);
8397 ok(output.dwStatus == 0, "got dwStatus %#lx\n", output.dwStatus);
8398 ok(status == 0, "got status %#lx\n", status);
8399 hr = IMFSample_GetTotalLength(sample, &length);
8400 ok(hr == S_OK, "GetTotalLength returned %#lx\n", hr);
8401 ok(length == 0, "got length %lu\n", length);
8402 ret = IMFSample_Release(sample);
8403 ok(ret == 0, "Release returned %lu\n", ret);
8405 ret = IMFTransform_Release(transform);
8406 ok(ret == 0, "Release returned %ld\n", ret);
8408 failed:
8409 CoUninitialize();
8413 START_TEST(mf)
8415 init_functions();
8417 if (is_vista())
8419 win_skip("Skipping tests on Vista.\n");
8420 return;
8423 test_video_processor();
8424 test_topology();
8425 test_topology_tee_node();
8426 test_topology_loader();
8427 test_topology_loader_evr();
8428 test_MFGetService();
8429 test_sequencer_source();
8430 test_media_session();
8431 test_media_session_rate_control();
8432 test_MFShutdownObject();
8433 test_presentation_clock();
8434 test_sample_grabber();
8435 test_sample_grabber_is_mediatype_supported();
8436 test_quality_manager();
8437 test_sar();
8438 test_evr();
8439 test_MFCreateSimpleTypeHandler();
8440 test_MFGetSupportedMimeTypes();
8441 test_MFGetSupportedSchemes();
8442 test_sample_copier();
8443 test_sample_copier_output_processing();
8444 test_MFGetTopoNodeCurrentType();
8445 test_MFRequireProtectedEnvironment();
8446 test_wma_encoder();
8447 test_wma_decoder();
8448 test_h264_decoder();
8449 test_audio_convert();
8450 test_color_convert();