winegstreamer: Support zero-copy in wg_transform_push_data.
[wine.git] / dlls / mf / tests / mf.c
blob13f0e38b0b8f11a9c0b5ecb21ceddb8767b80f4a
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 todo_wine_if(IsEqualGUID(class_ids, &CLSID_WINEAudioConverter))
258 ok(i < count, "failed to find %s transform\n", debugstr_w(expect_name));
259 if (i == count) return FALSE;
260 *class_id = class_ids[i];
261 CoTaskMemFree(class_ids);
262 ok(IsEqualGUID(class_id, expect_class_id), "got class id %s\n", debugstr_guid(class_id));
264 hr = MFTGetInfo(*class_id, &name, &input_types, &input_count, &output_types, &output_count, NULL);
265 if (FAILED(hr))
267 todo_wine
268 win_skip("Failed to get %s info, skipping tests.\n", debugstr_w(expect_name));
270 else
272 ok(hr == S_OK, "MFTEnum returned %lx\n", hr);
273 ok(!wcscmp(name, expect_name), "got name %s\n", debugstr_w(name));
274 ok(input_count == expect_input_count, "got input_count %u\n", input_count);
275 for (i = 0; i < input_count; ++i)
277 ok(IsEqualGUID(&input_types[i].guidMajorType, expect_major_type),
278 "got input[%u] major %s\n", i, debugstr_guid(&input_types[i].guidMajorType));
279 ok(IsEqualGUID(&input_types[i].guidSubtype, expect_input + i),
280 "got input[%u] subtype %s\n", i, debugstr_guid(&input_types[i].guidSubtype));
282 ok(output_count == expect_output_count, "got output_count %u\n", output_count);
283 for (i = 0; i < output_count; ++i)
285 ok(IsEqualGUID(&output_types[i].guidMajorType, expect_major_type),
286 "got output[%u] major %s\n", i, debugstr_guid(&output_types[i].guidMajorType));
287 ok(IsEqualGUID(&output_types[i].guidSubtype, expect_output + i),
288 "got output[%u] subtype %s\n", i, debugstr_guid(&output_types[i].guidSubtype));
290 CoTaskMemFree(output_types);
291 CoTaskMemFree(input_types);
292 CoTaskMemFree(name);
295 hr = CoCreateInstance(class_id, NULL, CLSCTX_INPROC_SERVER, &IID_IMFTransform, (void **)transform);
296 if (FAILED(hr))
298 todo_wine
299 win_skip("Failed to create %s instance, skipping tests.\n", debugstr_w(expect_name));
300 return FALSE;
303 return TRUE;
306 static HRESULT WINAPI test_unk_QueryInterface(IUnknown *iface, REFIID riid, void **obj)
308 if (IsEqualIID(riid, &IID_IUnknown))
310 *obj = iface;
311 IUnknown_AddRef(iface);
312 return S_OK;
315 *obj = NULL;
316 return E_NOINTERFACE;
319 static ULONG WINAPI test_unk_AddRef(IUnknown *iface)
321 return 2;
324 static ULONG WINAPI test_unk_Release(IUnknown *iface)
326 return 1;
329 static const IUnknownVtbl test_unk_vtbl =
331 test_unk_QueryInterface,
332 test_unk_AddRef,
333 test_unk_Release,
336 static void test_topology(void)
338 IMFMediaType *mediatype, *mediatype2, *mediatype3;
339 IMFCollection *collection, *collection2;
340 IUnknown test_unk2 = { &test_unk_vtbl };
341 IUnknown test_unk = { &test_unk_vtbl };
342 IMFTopologyNode *node, *node2, *node3;
343 IMFTopology *topology, *topology2;
344 DWORD size, io_count, index;
345 MF_TOPOLOGY_TYPE node_type;
346 IUnknown *object;
347 WORD node_count;
348 UINT32 count;
349 HRESULT hr;
350 TOPOID id;
352 hr = MFCreateTopology(NULL);
353 ok(hr == E_POINTER, "got %#lx\n", hr);
355 hr = MFCreateTopology(&topology);
356 ok(hr == S_OK, "Failed to create topology, hr %#lx.\n", hr);
357 hr = IMFTopology_GetTopologyID(topology, &id);
358 ok(hr == S_OK, "Failed to get id, hr %#lx.\n", hr);
359 ok(id == 1, "Unexpected id.\n");
361 hr = MFCreateTopology(&topology2);
362 ok(hr == S_OK, "Failed to create topology, hr %#lx.\n", hr);
363 hr = IMFTopology_GetTopologyID(topology2, &id);
364 ok(hr == S_OK, "Failed to get id, hr %#lx.\n", hr);
365 ok(id == 2, "Unexpected id.\n");
367 IMFTopology_Release(topology);
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 IMFTopology_Release(topology2);
377 /* No attributes by default. */
378 for (node_type = MF_TOPOLOGY_OUTPUT_NODE; node_type < MF_TOPOLOGY_TEE_NODE; ++node_type)
380 hr = MFCreateTopologyNode(node_type, &node);
381 ok(hr == S_OK, "Failed to create a node for type %d, hr %#lx.\n", node_type, hr);
382 hr = IMFTopologyNode_GetCount(node, &count);
383 ok(hr == S_OK, "Failed to get attribute count, hr %#lx.\n", hr);
384 ok(!count, "Unexpected attribute count %u.\n", count);
385 IMFTopologyNode_Release(node);
388 hr = MFCreateTopologyNode(MF_TOPOLOGY_OUTPUT_NODE, NULL);
389 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
391 hr = MFCreateTopologyNode(MF_TOPOLOGY_OUTPUT_NODE, &node);
392 ok(hr == S_OK, "Failed to create topology node, hr %#lx.\n", hr);
394 hr = MFCreateTopologyNode(MF_TOPOLOGY_TEE_NODE, &node2);
395 ok(hr == S_OK, "Failed to create topology node, hr %#lx.\n", hr);
397 hr = IMFTopologyNode_GetTopoNodeID(node, &id);
398 ok(hr == S_OK, "Failed to get node id, hr %#lx.\n", hr);
399 ok(((id >> 32) == GetCurrentProcessId()) && !!(id & 0xffff), "Unexpected node id %s.\n", wine_dbgstr_longlong(id));
401 hr = IMFTopologyNode_SetTopoNodeID(node2, id);
402 ok(hr == S_OK, "Failed to set node id, hr %#lx.\n", hr);
404 hr = IMFTopology_GetNodeCount(topology, NULL);
405 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
407 hr = IMFTopology_AddNode(topology, NULL);
408 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
410 node_count = 1;
411 hr = IMFTopology_GetNodeCount(topology, &node_count);
412 ok(hr == S_OK, "Failed to get node count, hr %#lx.\n", hr);
413 ok(node_count == 0, "Unexpected node count %u.\n", node_count);
415 /* Same id, different nodes. */
416 hr = IMFTopology_AddNode(topology, node);
417 ok(hr == S_OK, "Failed to add a node, hr %#lx.\n", hr);
419 node_count = 0;
420 hr = IMFTopology_GetNodeCount(topology, &node_count);
421 ok(hr == S_OK, "Failed to get node count, hr %#lx.\n", hr);
422 ok(node_count == 1, "Unexpected node count %u.\n", node_count);
424 hr = IMFTopology_AddNode(topology, node2);
425 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
426 IMFTopologyNode_Release(node2);
428 hr = IMFTopology_GetNodeByID(topology, id, &node2);
429 ok(hr == S_OK, "Failed to get a node, hr %#lx.\n", hr);
430 ok(node2 == node, "Unexpected node.\n");
431 IMFTopologyNode_Release(node2);
433 /* Change node id, add it again. */
434 hr = IMFTopologyNode_SetTopoNodeID(node, ++id);
435 ok(hr == S_OK, "Failed to set node id, hr %#lx.\n", hr);
437 hr = IMFTopology_GetNodeByID(topology, id, &node2);
438 ok(hr == S_OK, "Failed to get a node, hr %#lx.\n", hr);
439 ok(node2 == node, "Unexpected node.\n");
440 IMFTopologyNode_Release(node2);
442 hr = IMFTopology_GetNodeByID(topology, id + 1, &node2);
443 ok(hr == MF_E_NOT_FOUND, "Unexpected hr %#lx.\n", hr);
445 hr = IMFTopology_AddNode(topology, node);
446 ok(hr == E_INVALIDARG, "Failed to add a node, hr %#lx.\n", hr);
448 hr = IMFTopology_GetNode(topology, 0, &node2);
449 ok(hr == S_OK, "Failed to get a node, hr %#lx.\n", hr);
450 ok(node2 == node, "Unexpected node.\n");
451 IMFTopologyNode_Release(node2);
453 hr = IMFTopology_GetNode(topology, 1, NULL);
454 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
456 hr = IMFTopology_GetNode(topology, 1, &node2);
457 ok(hr == MF_E_INVALIDINDEX, "Failed to get a node, hr %#lx.\n", hr);
459 hr = IMFTopology_GetNode(topology, -2, &node2);
460 ok(hr == MF_E_INVALIDINDEX, "Failed to get a node, hr %#lx.\n", hr);
462 hr = MFCreateTopologyNode(MF_TOPOLOGY_TEE_NODE, &node2);
463 ok(hr == S_OK, "Failed to create topology node, hr %#lx.\n", hr);
464 hr = IMFTopology_AddNode(topology, node2);
465 ok(hr == S_OK, "Failed to add a node, hr %#lx.\n", hr);
466 IMFTopologyNode_Release(node2);
468 node_count = 0;
469 hr = IMFTopology_GetNodeCount(topology, &node_count);
470 ok(hr == S_OK, "Failed to get node count, hr %#lx.\n", hr);
471 ok(node_count == 2, "Unexpected node count %u.\n", node_count);
473 /* Remove with detached node, existing id. */
474 hr = MFCreateTopologyNode(MF_TOPOLOGY_TEE_NODE, &node2);
475 ok(hr == S_OK, "Failed to create topology node, hr %#lx.\n", hr);
476 hr = IMFTopologyNode_SetTopoNodeID(node2, id);
477 ok(hr == S_OK, "Failed to set node id, hr %#lx.\n", hr);
478 hr = IMFTopology_RemoveNode(topology, node2);
479 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
480 IMFTopologyNode_Release(node2);
482 hr = IMFTopology_RemoveNode(topology, node);
483 ok(hr == S_OK, "Failed to remove a node, hr %#lx.\n", hr);
485 node_count = 0;
486 hr = IMFTopology_GetNodeCount(topology, &node_count);
487 ok(hr == S_OK, "Failed to get node count, hr %#lx.\n", hr);
488 ok(node_count == 1, "Unexpected node count %u.\n", node_count);
490 hr = IMFTopology_Clear(topology);
491 ok(hr == S_OK, "Failed to clear topology, hr %#lx.\n", hr);
493 node_count = 1;
494 hr = IMFTopology_GetNodeCount(topology, &node_count);
495 ok(hr == S_OK, "Failed to get node count, hr %#lx.\n", hr);
496 ok(node_count == 0, "Unexpected node count %u.\n", node_count);
498 hr = IMFTopology_Clear(topology);
499 ok(hr == S_OK, "Failed to clear topology, hr %#lx.\n", hr);
501 hr = IMFTopologyNode_SetTopoNodeID(node, 123);
502 ok(hr == S_OK, "Failed to set node id, hr %#lx.\n", hr);
504 IMFTopologyNode_Release(node);
506 /* Change id for attached node. */
507 hr = MFCreateTopologyNode(MF_TOPOLOGY_OUTPUT_NODE, &node);
508 ok(hr == S_OK, "Failed to create topology node, hr %#lx.\n", hr);
510 hr = MFCreateTopologyNode(MF_TOPOLOGY_TEE_NODE, &node2);
511 ok(hr == S_OK, "Failed to create topology node, hr %#lx.\n", hr);
513 hr = IMFTopology_AddNode(topology, node);
514 ok(hr == S_OK, "Failed to add a node, hr %#lx.\n", hr);
516 hr = IMFTopology_AddNode(topology, node2);
517 ok(hr == S_OK, "Failed to add a node, hr %#lx.\n", hr);
519 hr = IMFTopologyNode_GetTopoNodeID(node, &id);
520 ok(hr == S_OK, "Failed to get node id, hr %#lx.\n", hr);
522 hr = IMFTopologyNode_SetTopoNodeID(node2, id);
523 ok(hr == S_OK, "Failed to get node id, hr %#lx.\n", hr);
525 hr = IMFTopology_GetNodeByID(topology, id, &node3);
526 ok(hr == S_OK, "Failed to get a node, hr %#lx.\n", hr);
527 ok(node3 == node, "Unexpected node.\n");
528 IMFTopologyNode_Release(node3);
530 IMFTopologyNode_Release(node);
531 IMFTopologyNode_Release(node2);
533 /* Source/output collections. */
534 hr = IMFTopology_Clear(topology);
535 ok(hr == S_OK, "Failed to clear topology, hr %#lx.\n", hr);
537 hr = IMFTopology_GetSourceNodeCollection(topology, NULL);
538 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
540 hr = IMFTopology_GetSourceNodeCollection(topology, &collection);
541 ok(hr == S_OK, "Failed to get source node collection, hr %#lx.\n", hr);
542 ok(!!collection, "Unexpected object pointer.\n");
544 hr = IMFTopology_GetSourceNodeCollection(topology, &collection2);
545 ok(hr == S_OK, "Failed to get source node collection, hr %#lx.\n", hr);
546 ok(!!collection2, "Unexpected object pointer.\n");
547 ok(collection2 != collection, "Expected cloned collection.\n");
549 hr = IMFCollection_GetElementCount(collection, &size);
550 ok(hr == S_OK, "Failed to get item count, hr %#lx.\n", hr);
551 ok(!size, "Unexpected item count.\n");
553 hr = IMFCollection_AddElement(collection, (IUnknown *)collection);
554 ok(hr == S_OK, "Failed to add element, hr %#lx.\n", hr);
556 hr = IMFCollection_GetElementCount(collection, &size);
557 ok(hr == S_OK, "Failed to get item count, hr %#lx.\n", hr);
558 ok(size == 1, "Unexpected item count.\n");
560 hr = IMFCollection_GetElementCount(collection2, &size);
561 ok(hr == S_OK, "Failed to get item count, hr %#lx.\n", hr);
562 ok(!size, "Unexpected item count.\n");
564 IMFCollection_Release(collection2);
565 IMFCollection_Release(collection);
567 /* Add some nodes. */
568 hr = IMFTopology_GetSourceNodeCollection(topology, NULL);
569 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
571 hr = IMFTopology_GetOutputNodeCollection(topology, NULL);
572 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
574 hr = MFCreateTopologyNode(MF_TOPOLOGY_SOURCESTREAM_NODE, &node);
575 ok(hr == S_OK, "Failed to create a node, hr %#lx.\n", hr);
576 hr = IMFTopology_AddNode(topology, node);
577 ok(hr == S_OK, "Failed to add a node, hr %#lx.\n", hr);
578 IMFTopologyNode_Release(node);
580 hr = IMFTopology_GetSourceNodeCollection(topology, &collection);
581 ok(hr == S_OK, "Failed to get source node collection, hr %#lx.\n", hr);
582 ok(!!collection, "Unexpected object pointer.\n");
583 hr = IMFCollection_GetElementCount(collection, &size);
584 ok(hr == S_OK, "Failed to get item count, hr %#lx.\n", hr);
585 ok(size == 1, "Unexpected item count.\n");
586 IMFCollection_Release(collection);
588 hr = MFCreateTopologyNode(MF_TOPOLOGY_TEE_NODE, &node);
589 ok(hr == S_OK, "Failed to create a node, hr %#lx.\n", hr);
590 hr = IMFTopology_AddNode(topology, node);
591 ok(hr == S_OK, "Failed to add a node, hr %#lx.\n", hr);
592 IMFTopologyNode_Release(node);
594 hr = IMFTopology_GetSourceNodeCollection(topology, &collection);
595 ok(hr == S_OK, "Failed to get source node collection, hr %#lx.\n", hr);
596 ok(!!collection, "Unexpected object pointer.\n");
597 hr = IMFCollection_GetElementCount(collection, &size);
598 ok(hr == S_OK, "Failed to get item count, hr %#lx.\n", hr);
599 ok(size == 1, "Unexpected item count.\n");
600 IMFCollection_Release(collection);
602 hr = MFCreateTopologyNode(MF_TOPOLOGY_TRANSFORM_NODE, &node);
603 ok(hr == S_OK, "Failed to create a node, hr %#lx.\n", hr);
604 hr = IMFTopology_AddNode(topology, node);
605 ok(hr == S_OK, "Failed to add a node, hr %#lx.\n", hr);
606 IMFTopologyNode_Release(node);
608 hr = IMFTopology_GetSourceNodeCollection(topology, &collection);
609 ok(hr == S_OK, "Failed to get source node collection, hr %#lx.\n", hr);
610 ok(!!collection, "Unexpected object pointer.\n");
611 hr = IMFCollection_GetElementCount(collection, &size);
612 ok(hr == S_OK, "Failed to get item count, hr %#lx.\n", hr);
613 ok(size == 1, "Unexpected item count.\n");
614 IMFCollection_Release(collection);
616 hr = MFCreateTopologyNode(MF_TOPOLOGY_OUTPUT_NODE, &node);
617 ok(hr == S_OK, "Failed to create a node, hr %#lx.\n", hr);
618 hr = IMFTopology_AddNode(topology, node);
619 ok(hr == S_OK, "Failed to add a node, hr %#lx.\n", hr);
621 /* Associated object. */
622 hr = IMFTopologyNode_SetObject(node, NULL);
623 ok(hr == S_OK, "Failed to set object, hr %#lx.\n", hr);
625 hr = IMFTopologyNode_GetObject(node, NULL);
626 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
628 object = (void *)0xdeadbeef;
629 hr = IMFTopologyNode_GetObject(node, &object);
630 ok(hr == E_FAIL, "Unexpected hr %#lx.\n", hr);
631 ok(!object, "Unexpected object %p.\n", object);
633 hr = IMFTopologyNode_SetObject(node, &test_unk);
634 ok(hr == S_OK, "Failed to set object, hr %#lx.\n", hr);
636 hr = IMFTopologyNode_GetObject(node, &object);
637 ok(hr == S_OK, "Failed to get object, hr %#lx.\n", hr);
638 ok(object == &test_unk, "Unexpected object %p.\n", object);
639 IUnknown_Release(object);
641 hr = IMFTopologyNode_SetObject(node, &test_unk2);
642 ok(hr == S_OK, "Failed to set object, hr %#lx.\n", hr);
644 hr = IMFTopologyNode_GetCount(node, &count);
645 ok(hr == S_OK, "Failed to get attribute count, hr %#lx.\n", hr);
646 ok(count == 0, "Unexpected attribute count %u.\n", count);
648 hr = IMFTopologyNode_SetGUID(node, &MF_TOPONODE_TRANSFORM_OBJECTID, &MF_TOPONODE_TRANSFORM_OBJECTID);
649 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
651 hr = IMFTopologyNode_SetObject(node, NULL);
652 ok(hr == S_OK, "Failed to set object, hr %#lx.\n", hr);
654 object = (void *)0xdeadbeef;
655 hr = IMFTopologyNode_GetObject(node, &object);
656 ok(hr == E_FAIL, "Unexpected hr %#lx.\n", hr);
657 ok(!object, "Unexpected object %p.\n", object);
659 hr = IMFTopologyNode_GetCount(node, &count);
660 ok(hr == S_OK, "Failed to get attribute count, hr %#lx.\n", hr);
661 ok(count == 1, "Unexpected attribute count %u.\n", count);
663 /* Preferred stream types. */
664 hr = IMFTopologyNode_GetInputCount(node, &io_count);
665 ok(hr == S_OK, "Failed to get input count, hr %#lx.\n", hr);
666 ok(io_count == 0, "Unexpected count %lu.\n", io_count);
668 hr = IMFTopologyNode_GetInputPrefType(node, 0, &mediatype);
669 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
671 hr = MFCreateMediaType(&mediatype);
672 ok(hr == S_OK, "Failed to create media type, hr %#lx.\n", hr);
674 hr = IMFTopologyNode_SetInputPrefType(node, 0, mediatype);
675 ok(hr == S_OK, "Failed to set preferred type, hr %#lx.\n", hr);
677 hr = IMFTopologyNode_GetInputPrefType(node, 0, &mediatype2);
678 ok(hr == S_OK, "Failed to get preferred type, hr %#lx.\n", hr);
679 ok(mediatype2 == mediatype, "Unexpected mediatype instance.\n");
680 IMFMediaType_Release(mediatype2);
682 hr = IMFTopologyNode_SetInputPrefType(node, 0, NULL);
683 ok(hr == S_OK, "Failed to set preferred type, hr %#lx.\n", hr);
685 hr = IMFTopologyNode_GetInputPrefType(node, 0, &mediatype2);
686 ok(hr == E_FAIL, "Unexpected hr %#lx.\n", hr);
687 ok(!mediatype2, "Unexpected mediatype instance.\n");
689 hr = IMFTopologyNode_SetInputPrefType(node, 1, mediatype);
690 ok(hr == S_OK, "Failed to set preferred type, hr %#lx.\n", hr);
692 hr = IMFTopologyNode_SetInputPrefType(node, 1, mediatype);
693 ok(hr == S_OK, "Failed to set preferred type, hr %#lx.\n", hr);
695 hr = IMFTopologyNode_GetInputCount(node, &io_count);
696 ok(hr == S_OK, "Failed to get input count, hr %#lx.\n", hr);
697 ok(io_count == 2, "Unexpected count %lu.\n", io_count);
699 hr = IMFTopologyNode_GetOutputCount(node, &io_count);
700 ok(hr == S_OK, "Failed to get input count, hr %#lx.\n", hr);
701 ok(io_count == 0, "Unexpected count %lu.\n", io_count);
703 hr = IMFTopologyNode_SetOutputPrefType(node, 0, mediatype);
704 ok(hr == E_NOTIMPL, "Unexpected hr %#lx.\n", hr);
706 IMFTopologyNode_Release(node);
708 /* Source node. */
709 hr = MFCreateTopologyNode(MF_TOPOLOGY_SOURCESTREAM_NODE, &node);
710 ok(hr == S_OK, "Failed to create a node, hr %#lx.\n", hr);
712 hr = IMFTopologyNode_SetInputPrefType(node, 0, mediatype);
713 ok(hr == E_NOTIMPL, "Unexpected hr %#lx.\n", hr);
715 hr = IMFTopologyNode_SetOutputPrefType(node, 2, mediatype);
716 ok(hr == S_OK, "Failed to set preferred type, hr %#lx.\n", hr);
718 hr = IMFTopologyNode_GetOutputPrefType(node, 0, &mediatype2);
719 ok(hr == E_FAIL, "Failed to get preferred type, hr %#lx.\n", hr);
720 ok(!mediatype2, "Unexpected mediatype instance.\n");
722 hr = IMFTopologyNode_GetOutputCount(node, &io_count);
723 ok(hr == S_OK, "Failed to get output count, hr %#lx.\n", hr);
724 ok(io_count == 3, "Unexpected count %lu.\n", io_count);
726 IMFTopologyNode_Release(node);
728 /* Tee node. */
729 hr = MFCreateTopologyNode(MF_TOPOLOGY_TEE_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 == S_OK, "Failed to set preferred type, hr %#lx.\n", hr);
735 hr = IMFTopologyNode_GetInputPrefType(node, 0, &mediatype2);
736 ok(hr == S_OK, "Failed to get preferred type, hr %#lx.\n", hr);
737 ok(mediatype2 == mediatype, "Unexpected mediatype instance.\n");
738 IMFMediaType_Release(mediatype2);
740 hr = IMFTopologyNode_GetOutputPrefType(node, 0, &mediatype2);
741 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
743 hr = IMFTopologyNode_GetInputCount(node, &io_count);
744 ok(hr == S_OK, "Failed to get output count, hr %#lx.\n", hr);
745 ok(io_count == 0, "Unexpected count %lu.\n", io_count);
747 hr = IMFTopologyNode_SetInputPrefType(node, 1, mediatype);
748 ok(hr == MF_E_INVALIDTYPE, "Unexpected hr %#lx.\n", hr);
750 hr = IMFTopologyNode_SetInputPrefType(node, 3, mediatype);
751 ok(hr == MF_E_INVALIDTYPE, "Unexpected hr %#lx.\n", hr);
753 hr = IMFTopologyNode_SetOutputPrefType(node, 4, mediatype);
754 ok(hr == S_OK, "Failed to set preferred type, hr %#lx.\n", hr);
756 hr = IMFTopologyNode_GetOutputPrefType(node, 0, &mediatype2);
757 ok(hr == E_FAIL, "Unexpected hr %#lx.\n", hr);
759 hr = MFCreateMediaType(&mediatype2);
760 ok(hr == S_OK, "Failed to create media type, hr %#lx.\n", hr);
762 /* Changing output type does not change input type. */
763 hr = IMFTopologyNode_SetOutputPrefType(node, 4, mediatype2);
764 ok(hr == S_OK, "Failed to set preferred type, hr %#lx.\n", hr);
766 hr = IMFTopologyNode_GetInputPrefType(node, 0, &mediatype3);
767 ok(hr == S_OK, "Failed to get preferred type, hr %#lx.\n", hr);
768 ok(mediatype3 == mediatype, "Unexpected mediatype instance.\n");
769 IMFMediaType_Release(mediatype3);
771 IMFMediaType_Release(mediatype2);
773 hr = IMFTopologyNode_GetInputCount(node, &io_count);
774 ok(hr == S_OK, "Failed to get output count, hr %#lx.\n", hr);
775 ok(io_count == 0, "Unexpected count %lu.\n", io_count);
777 hr = IMFTopologyNode_GetOutputCount(node, &io_count);
778 ok(hr == S_OK, "Failed to get output count, hr %#lx.\n", hr);
779 ok(io_count == 5, "Unexpected count %lu.\n", io_count);
781 IMFTopologyNode_Release(node);
783 /* Transform node. */
784 hr = MFCreateTopologyNode(MF_TOPOLOGY_TRANSFORM_NODE, &node);
785 ok(hr == S_OK, "Failed to create a node, hr %#lx.\n", hr);
787 hr = IMFTopologyNode_SetInputPrefType(node, 3, mediatype);
788 ok(hr == S_OK, "Failed to set preferred type, hr %#lx.\n", hr);
790 hr = IMFTopologyNode_GetInputCount(node, &io_count);
791 ok(hr == S_OK, "Failed to get input count, hr %#lx.\n", hr);
792 ok(io_count == 4, "Unexpected count %lu.\n", io_count);
794 hr = IMFTopologyNode_SetOutputPrefType(node, 4, mediatype);
795 ok(hr == S_OK, "Failed to set preferred type, hr %#lx.\n", hr);
797 hr = IMFTopologyNode_GetInputCount(node, &io_count);
798 ok(hr == S_OK, "Failed to get output count, hr %#lx.\n", hr);
799 ok(io_count == 4, "Unexpected count %lu.\n", io_count);
801 hr = IMFTopologyNode_GetOutputCount(node, &io_count);
802 ok(hr == S_OK, "Failed to get output count, hr %#lx.\n", hr);
803 ok(io_count == 5, "Unexpected count %lu.\n", io_count);
805 IMFTopologyNode_Release(node);
807 IMFMediaType_Release(mediatype);
809 hr = IMFTopology_GetOutputNodeCollection(topology, &collection);
810 ok(hr == S_OK || broken(hr == E_FAIL) /* before Win8 */, "Failed to get output node collection, hr %#lx.\n", hr);
811 if (SUCCEEDED(hr))
813 ok(!!collection, "Unexpected object pointer.\n");
814 hr = IMFCollection_GetElementCount(collection, &size);
815 ok(hr == S_OK, "Failed to get item count, hr %#lx.\n", hr);
816 ok(size == 1, "Unexpected item count.\n");
817 IMFCollection_Release(collection);
820 IMFTopology_Release(topology);
822 /* Connect nodes. */
823 hr = MFCreateTopologyNode(MF_TOPOLOGY_SOURCESTREAM_NODE, &node);
824 ok(hr == S_OK, "Failed to create topology node, hr %#lx.\n", hr);
826 hr = MFCreateTopologyNode(MF_TOPOLOGY_OUTPUT_NODE, &node2);
827 ok(hr == S_OK, "Failed to create topology node, hr %#lx.\n", hr);
829 EXPECT_REF(node, 1);
830 EXPECT_REF(node2, 1);
832 hr = IMFTopologyNode_ConnectOutput(node, 0, node2, 1);
833 ok(hr == S_OK, "Failed to connect nodes, hr %#lx.\n", hr);
835 EXPECT_REF(node, 2);
836 EXPECT_REF(node2, 2);
838 IMFTopologyNode_Release(node);
840 EXPECT_REF(node, 1);
841 EXPECT_REF(node2, 2);
843 IMFTopologyNode_Release(node2);
845 EXPECT_REF(node, 1);
846 EXPECT_REF(node2, 1);
848 hr = IMFTopologyNode_GetNodeType(node2, &node_type);
849 ok(hr == S_OK, "Failed to get node type, hr %#lx.\n", hr);
851 IMFTopologyNode_Release(node);
853 /* Connect within topology. */
854 hr = MFCreateTopologyNode(MF_TOPOLOGY_SOURCESTREAM_NODE, &node);
855 ok(hr == S_OK, "Failed to create topology node, hr %#lx.\n", hr);
857 hr = MFCreateTopologyNode(MF_TOPOLOGY_OUTPUT_NODE, &node2);
858 ok(hr == S_OK, "Failed to create topology node, hr %#lx.\n", hr);
860 hr = MFCreateTopology(&topology);
861 ok(hr == S_OK, "Failed to create topology, hr %#lx.\n", hr);
863 hr = IMFTopology_AddNode(topology, node);
864 ok(hr == S_OK, "Failed to add a node, hr %#lx.\n", hr);
866 hr = IMFTopology_AddNode(topology, node2);
867 ok(hr == S_OK, "Failed to add a node, hr %#lx.\n", hr);
869 EXPECT_REF(node, 2);
870 EXPECT_REF(node2, 2);
872 hr = IMFTopologyNode_ConnectOutput(node, 0, node2, 1);
873 ok(hr == S_OK, "Failed to connect nodes, hr %#lx.\n", hr);
875 EXPECT_REF(node, 3);
876 EXPECT_REF(node2, 3);
878 hr = IMFTopology_Clear(topology);
879 ok(hr == S_OK, "Failed to clear topology, hr %#lx.\n", hr);
881 EXPECT_REF(node, 1);
882 EXPECT_REF(node2, 1);
884 /* Removing connected node breaks connection. */
885 hr = IMFTopology_AddNode(topology, node);
886 ok(hr == S_OK, "Failed to add a node, hr %#lx.\n", hr);
888 hr = IMFTopology_AddNode(topology, node2);
889 ok(hr == S_OK, "Failed to add a node, hr %#lx.\n", hr);
891 hr = IMFTopologyNode_ConnectOutput(node, 0, node2, 1);
892 ok(hr == S_OK, "Failed to connect nodes, hr %#lx.\n", hr);
894 hr = IMFTopology_RemoveNode(topology, node);
895 ok(hr == S_OK, "Failed to remove a node, hr %#lx.\n", hr);
897 EXPECT_REF(node, 1);
898 EXPECT_REF(node2, 2);
900 hr = IMFTopologyNode_GetOutput(node, 0, &node3, &index);
901 ok(hr == MF_E_NOT_FOUND, "Unexpected hr %#lx.\n", hr);
903 hr = IMFTopology_AddNode(topology, node);
904 ok(hr == S_OK, "Failed to add a node, hr %#lx.\n", hr);
906 hr = IMFTopologyNode_ConnectOutput(node, 0, node2, 1);
907 ok(hr == S_OK, "Failed to connect nodes, hr %#lx.\n", hr);
909 hr = IMFTopology_RemoveNode(topology, node2);
910 ok(hr == S_OK, "Failed to remove a node, hr %#lx.\n", hr);
912 EXPECT_REF(node, 2);
913 EXPECT_REF(node2, 1);
915 IMFTopologyNode_Release(node);
916 IMFTopologyNode_Release(node2);
918 /* Cloning nodes of different types. */
919 hr = MFCreateTopologyNode(MF_TOPOLOGY_SOURCESTREAM_NODE, &node);
920 ok(hr == S_OK, "Failed to create topology node, hr %#lx.\n", hr);
922 hr = MFCreateTopologyNode(MF_TOPOLOGY_OUTPUT_NODE, &node2);
923 ok(hr == S_OK, "Failed to create topology node, hr %#lx.\n", hr);
925 hr = IMFTopologyNode_CloneFrom(node, node2);
926 ok(hr == MF_E_INVALIDREQUEST, "Unexpected hr %#lx.\n", hr);
928 IMFTopologyNode_Release(node2);
930 /* Cloning preferred types. */
931 hr = MFCreateTopologyNode(MF_TOPOLOGY_SOURCESTREAM_NODE, &node2);
932 ok(hr == S_OK, "Failed to create topology node, hr %#lx.\n", hr);
934 hr = MFCreateMediaType(&mediatype);
935 ok(hr == S_OK, "Failed to create media type, hr %#lx.\n", hr);
937 hr = IMFTopologyNode_SetOutputPrefType(node2, 0, mediatype);
938 ok(hr == S_OK, "Failed to set preferred type, hr %#lx.\n", hr);
940 /* Vista checks for additional attributes. */
941 hr = IMFTopologyNode_CloneFrom(node, node2);
942 ok(hr == S_OK || broken(hr == MF_E_ATTRIBUTENOTFOUND) /* Vista */, "Failed to clone a node, hr %#lx.\n", hr);
944 hr = IMFTopologyNode_GetOutputPrefType(node, 0, &mediatype2);
945 ok(hr == S_OK, "Failed to get preferred type, hr %#lx.\n", hr);
946 ok(mediatype == mediatype2, "Unexpected media type.\n");
948 IMFMediaType_Release(mediatype2);
949 IMFMediaType_Release(mediatype);
951 IMFTopologyNode_Release(node2);
953 /* Existing preferred types are not cleared. */
954 hr = MFCreateTopologyNode(MF_TOPOLOGY_SOURCESTREAM_NODE, &node2);
955 ok(hr == S_OK, "Failed to create topology node, hr %#lx.\n", hr);
957 hr = IMFTopologyNode_GetOutputCount(node, &io_count);
958 ok(hr == S_OK, "Failed to get output count, hr %#lx.\n", hr);
959 ok(io_count == 1, "Unexpected output count.\n");
961 hr = IMFTopologyNode_CloneFrom(node, node2);
962 ok(hr == S_OK || broken(hr == MF_E_ATTRIBUTENOTFOUND) /* Vista */, "Failed to clone a node, hr %#lx.\n", hr);
964 hr = IMFTopologyNode_GetOutputCount(node, &io_count);
965 ok(hr == S_OK, "Failed to get output count, hr %#lx.\n", hr);
966 ok(io_count == 1, "Unexpected output count.\n");
968 hr = IMFTopologyNode_GetOutputPrefType(node, 0, &mediatype2);
969 ok(hr == S_OK, "Failed to get preferred type, hr %#lx.\n", hr);
970 ok(!!mediatype2, "Unexpected media type.\n");
971 IMFMediaType_Release(mediatype2);
973 hr = IMFTopologyNode_CloneFrom(node2, node);
974 ok(hr == S_OK || broken(hr == MF_E_ATTRIBUTENOTFOUND) /* Vista */, "Failed to clone a node, hr %#lx.\n", hr);
976 hr = IMFTopologyNode_GetOutputCount(node2, &io_count);
977 ok(hr == S_OK, "Failed to get output count, hr %#lx.\n", hr);
978 ok(io_count == 1, "Unexpected output count.\n");
980 IMFTopologyNode_Release(node2);
981 IMFTopologyNode_Release(node);
983 /* Add one node, connect to another that hasn't been added. */
984 hr = IMFTopology_Clear(topology);
985 ok(hr == S_OK, "Failed to clear topology, hr %#lx.\n", hr);
987 hr = MFCreateTopologyNode(MF_TOPOLOGY_SOURCESTREAM_NODE, &node);
988 ok(hr == S_OK, "Failed to create topology node, hr %#lx.\n", hr);
990 hr = MFCreateTopologyNode(MF_TOPOLOGY_OUTPUT_NODE, &node2);
991 ok(hr == S_OK, "Failed to create topology node, hr %#lx.\n", hr);
993 hr = IMFTopology_AddNode(topology, node);
994 ok(hr == S_OK, "Failed to add a node, hr %#lx.\n", hr);
996 hr = IMFTopology_GetNodeCount(topology, &node_count);
997 ok(hr == S_OK, "Failed to get node count, hr %#lx.\n", hr);
998 ok(node_count == 1, "Unexpected node count.\n");
1000 hr = IMFTopologyNode_ConnectOutput(node, 0, node2, 0);
1001 ok(hr == S_OK, "Failed to connect nodes, hr %#lx.\n", hr);
1003 hr = IMFTopology_GetNodeCount(topology, &node_count);
1004 ok(hr == S_OK, "Failed to get node count, hr %#lx.\n", hr);
1005 ok(node_count == 1, "Unexpected node count.\n");
1007 IMFTopologyNode_Release(node);
1008 IMFTopologyNode_Release(node2);
1010 /* Add same node to different topologies. */
1011 hr = IMFTopology_Clear(topology);
1012 ok(hr == S_OK, "Failed to clear topology, hr %#lx.\n", hr);
1014 hr = MFCreateTopology(&topology2);
1015 ok(hr == S_OK, "Failed to create 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 = IMFTopology_AddNode(topology, node);
1021 ok(hr == S_OK, "Failed to add a node, hr %#lx.\n", hr);
1022 EXPECT_REF(node, 2);
1024 hr = IMFTopology_GetNodeCount(topology, &node_count);
1025 ok(hr == S_OK, "Failed to get node count, hr %#lx.\n", hr);
1026 ok(node_count == 1, "Unexpected node count.\n");
1028 hr = IMFTopology_GetNodeCount(topology2, &node_count);
1029 ok(hr == S_OK, "Failed to get node count, hr %#lx.\n", hr);
1030 ok(node_count == 0, "Unexpected node count.\n");
1032 hr = IMFTopology_AddNode(topology2, node);
1033 ok(hr == S_OK, "Failed to add a node, hr %#lx.\n", hr);
1034 EXPECT_REF(node, 3);
1036 hr = IMFTopology_GetNodeCount(topology, &node_count);
1037 ok(hr == S_OK, "Failed to get node count, hr %#lx.\n", hr);
1038 ok(node_count == 1, "Unexpected node count.\n");
1040 hr = IMFTopology_GetNodeCount(topology2, &node_count);
1041 ok(hr == S_OK, "Failed to get node count, hr %#lx.\n", hr);
1042 ok(node_count == 1, "Unexpected node count.\n");
1044 IMFTopology_Release(topology2);
1045 IMFTopology_Release(topology);
1048 static void test_topology_tee_node(void)
1050 IMFTopologyNode *src_node, *tee_node;
1051 IMFMediaType *mediatype, *mediatype2;
1052 IMFTopology *topology;
1053 DWORD count;
1054 HRESULT hr;
1056 hr = MFCreateTopology(&topology);
1057 ok(hr == S_OK, "Failed to create topology, hr %#lx.\n", hr);
1059 hr = MFCreateMediaType(&mediatype);
1060 ok(hr == S_OK, "Failed to create media type, hr %#lx.\n", hr);
1062 hr = MFCreateTopologyNode(MF_TOPOLOGY_TEE_NODE, &tee_node);
1063 ok(hr == S_OK, "Failed to create topology node, hr %#lx.\n", hr);
1065 hr = MFCreateTopologyNode(MF_TOPOLOGY_SOURCESTREAM_NODE, &src_node);
1066 ok(hr == S_OK, "Failed to create topology node, hr %#lx.\n", hr);
1068 hr = IMFTopologyNode_SetInputPrefType(tee_node, 0, mediatype);
1069 ok(hr == S_OK, "Failed to set type, hr %#lx.\n", hr);
1071 /* Even though tee node has only one input and source has only one output,
1072 it's possible to connect to higher inputs/outputs. */
1074 /* SRC(0) -> TEE(0) */
1075 hr = IMFTopologyNode_ConnectOutput(src_node, 0, tee_node, 0);
1076 ok(hr == S_OK, "Failed to connect nodes, hr %#lx.\n", hr);
1078 hr = IMFTopologyNode_GetInputCount(tee_node, &count);
1079 ok(hr == S_OK, "Failed to get count, hr %#lx.\n", hr);
1080 ok(count == 1, "Unexpected count %lu.\n", count);
1082 hr = IMFTopologyNode_GetInputPrefType(tee_node, 0, &mediatype2);
1083 ok(hr == S_OK, "Failed to get type, hr %#lx.\n", hr);
1084 ok(mediatype2 == mediatype, "Unexpected type.\n");
1085 IMFMediaType_Release(mediatype2);
1087 /* SRC(0) -> TEE(1) */
1088 hr = IMFTopologyNode_ConnectOutput(src_node, 0, tee_node, 1);
1089 ok(hr == S_OK, "Failed to connect nodes, hr %#lx.\n", hr);
1091 hr = IMFTopologyNode_GetInputCount(tee_node, &count);
1092 ok(hr == S_OK, "Failed to get count, hr %#lx.\n", hr);
1093 ok(count == 2, "Unexpected count %lu.\n", count);
1095 hr = IMFTopologyNode_SetInputPrefType(tee_node, 1, mediatype);
1096 ok(hr == MF_E_INVALIDTYPE, "Unexpected hr %#lx.\n", hr);
1098 /* SRC(1) -> TEE(1) */
1099 hr = IMFTopologyNode_ConnectOutput(src_node, 1, tee_node, 1);
1100 ok(hr == S_OK, "Failed to connect nodes, hr %#lx.\n", hr);
1102 hr = IMFTopologyNode_GetOutputCount(src_node, &count);
1103 ok(hr == S_OK, "Failed to get count, hr %#lx.\n", hr);
1104 ok(count == 2, "Unexpected count %lu.\n", count);
1106 IMFMediaType_Release(mediatype);
1107 IMFTopologyNode_Release(src_node);
1108 IMFTopologyNode_Release(tee_node);
1109 IMFTopology_Release(topology);
1112 static HRESULT WINAPI test_getservice_QI(IMFGetService *iface, REFIID riid, void **obj)
1114 if (IsEqualIID(riid, &IID_IMFGetService) || IsEqualIID(riid, &IID_IUnknown))
1116 *obj = iface;
1117 return S_OK;
1120 *obj = NULL;
1121 return E_NOINTERFACE;
1124 static ULONG WINAPI test_getservice_AddRef(IMFGetService *iface)
1126 return 2;
1129 static ULONG WINAPI test_getservice_Release(IMFGetService *iface)
1131 return 1;
1134 static HRESULT WINAPI test_getservice_GetService(IMFGetService *iface, REFGUID service, REFIID riid, void **obj)
1136 *obj = (void *)0xdeadbeef;
1137 return 0x83eddead;
1140 static const IMFGetServiceVtbl testmfgetservicevtbl =
1142 test_getservice_QI,
1143 test_getservice_AddRef,
1144 test_getservice_Release,
1145 test_getservice_GetService,
1148 static IMFGetService test_getservice = { &testmfgetservicevtbl };
1150 static HRESULT WINAPI testservice_QI(IUnknown *iface, REFIID riid, void **obj)
1152 if (IsEqualIID(riid, &IID_IUnknown))
1154 *obj = iface;
1155 return S_OK;
1158 *obj = NULL;
1160 if (IsEqualIID(riid, &IID_IMFGetService))
1161 return 0x82eddead;
1163 return E_NOINTERFACE;
1166 static HRESULT WINAPI testservice2_QI(IUnknown *iface, REFIID riid, void **obj)
1168 if (IsEqualIID(riid, &IID_IUnknown))
1170 *obj = iface;
1171 return S_OK;
1174 if (IsEqualIID(riid, &IID_IMFGetService))
1176 *obj = &test_getservice;
1177 return S_OK;
1180 *obj = NULL;
1181 return E_NOINTERFACE;
1184 static ULONG WINAPI testservice_AddRef(IUnknown *iface)
1186 return 2;
1189 static ULONG WINAPI testservice_Release(IUnknown *iface)
1191 return 1;
1194 static const IUnknownVtbl testservicevtbl =
1196 testservice_QI,
1197 testservice_AddRef,
1198 testservice_Release,
1201 static const IUnknownVtbl testservice2vtbl =
1203 testservice2_QI,
1204 testservice_AddRef,
1205 testservice_Release,
1208 static IUnknown testservice = { &testservicevtbl };
1209 static IUnknown testservice2 = { &testservice2vtbl };
1211 static void test_MFGetService(void)
1213 IUnknown *unk;
1214 HRESULT hr;
1216 hr = MFGetService(NULL, NULL, NULL, NULL);
1217 ok(hr == E_POINTER, "Unexpected return value %#lx.\n", hr);
1219 unk = (void *)0xdeadbeef;
1220 hr = MFGetService(NULL, NULL, NULL, (void **)&unk);
1221 ok(hr == E_POINTER, "Unexpected return value %#lx.\n", hr);
1222 ok(unk == (void *)0xdeadbeef, "Unexpected out object.\n");
1224 hr = MFGetService(&testservice, NULL, NULL, NULL);
1225 ok(hr == 0x82eddead, "Unexpected return value %#lx.\n", hr);
1227 unk = (void *)0xdeadbeef;
1228 hr = MFGetService(&testservice, NULL, NULL, (void **)&unk);
1229 ok(hr == 0x82eddead, "Unexpected return value %#lx.\n", hr);
1230 ok(unk == (void *)0xdeadbeef, "Unexpected out object.\n");
1232 unk = NULL;
1233 hr = MFGetService(&testservice2, NULL, NULL, (void **)&unk);
1234 ok(hr == 0x83eddead, "Unexpected return value %#lx.\n", hr);
1235 ok(unk == (void *)0xdeadbeef, "Unexpected out object.\n");
1238 static void test_sequencer_source(void)
1240 IMFSequencerSource *seq_source;
1241 HRESULT hr;
1243 hr = MFStartup(MF_VERSION, MFSTARTUP_FULL);
1244 ok(hr == S_OK, "Startup failure, hr %#lx.\n", hr);
1246 hr = MFCreateSequencerSource(NULL, &seq_source);
1247 ok(hr == S_OK, "Failed to create sequencer source, hr %#lx.\n", hr);
1249 check_interface(seq_source, &IID_IMFMediaSourceTopologyProvider, TRUE);
1251 IMFSequencerSource_Release(seq_source);
1253 hr = MFShutdown();
1254 ok(hr == S_OK, "Shutdown failure, hr %#lx.\n", hr);
1257 struct test_callback
1259 IMFAsyncCallback IMFAsyncCallback_iface;
1262 static HRESULT WINAPI testcallback_QueryInterface(IMFAsyncCallback *iface, REFIID riid, void **obj)
1264 if (IsEqualIID(riid, &IID_IMFAsyncCallback) ||
1265 IsEqualIID(riid, &IID_IUnknown))
1267 *obj = iface;
1268 IMFAsyncCallback_AddRef(iface);
1269 return S_OK;
1272 *obj = NULL;
1273 return E_NOINTERFACE;
1276 static ULONG WINAPI testcallback_AddRef(IMFAsyncCallback *iface)
1278 return 2;
1281 static ULONG WINAPI testcallback_Release(IMFAsyncCallback *iface)
1283 return 1;
1286 static HRESULT WINAPI testcallback_GetParameters(IMFAsyncCallback *iface, DWORD *flags, DWORD *queue)
1288 ok(flags != NULL && queue != NULL, "Unexpected arguments.\n");
1289 return E_NOTIMPL;
1292 static HRESULT WINAPI testcallback_Invoke(IMFAsyncCallback *iface, IMFAsyncResult *result)
1294 ok(result != NULL, "Unexpected result object.\n");
1296 return E_NOTIMPL;
1299 static const IMFAsyncCallbackVtbl testcallbackvtbl =
1301 testcallback_QueryInterface,
1302 testcallback_AddRef,
1303 testcallback_Release,
1304 testcallback_GetParameters,
1305 testcallback_Invoke,
1308 static void init_test_callback(struct test_callback *callback)
1310 callback->IMFAsyncCallback_iface.lpVtbl = &testcallbackvtbl;
1313 static void test_session_events(IMFMediaSession *session)
1315 struct test_callback callback, callback2;
1316 IMFAsyncResult *result;
1317 IMFMediaEvent *event;
1318 HRESULT hr;
1320 init_test_callback(&callback);
1321 init_test_callback(&callback2);
1323 hr = IMFMediaSession_GetEvent(session, MF_EVENT_FLAG_NO_WAIT, &event);
1324 ok(hr == MF_E_NO_EVENTS_AVAILABLE, "Unexpected hr %#lx.\n", hr);
1326 /* Async case. */
1327 hr = IMFMediaSession_BeginGetEvent(session, NULL, NULL);
1328 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
1330 hr = IMFMediaSession_BeginGetEvent(session, &callback.IMFAsyncCallback_iface, (IUnknown *)session);
1331 ok(hr == S_OK, "Failed to Begin*, hr %#lx.\n", hr);
1333 /* Same callback, same state. */
1334 hr = IMFMediaSession_BeginGetEvent(session, &callback.IMFAsyncCallback_iface, (IUnknown *)session);
1335 ok(hr == MF_S_MULTIPLE_BEGIN, "Unexpected hr %#lx.\n", hr);
1337 /* Same callback, different state. */
1338 hr = IMFMediaSession_BeginGetEvent(session, &callback.IMFAsyncCallback_iface, (IUnknown *)&callback.IMFAsyncCallback_iface);
1339 ok(hr == MF_E_MULTIPLE_BEGIN, "Unexpected hr %#lx.\n", hr);
1341 /* Different callback, same state. */
1342 hr = IMFMediaSession_BeginGetEvent(session, &callback2.IMFAsyncCallback_iface, (IUnknown *)session);
1343 ok(hr == MF_E_MULTIPLE_SUBSCRIBERS, "Unexpected hr %#lx.\n", hr);
1345 /* Different callback, different state. */
1346 hr = IMFMediaSession_BeginGetEvent(session, &callback2.IMFAsyncCallback_iface, (IUnknown *)&callback.IMFAsyncCallback_iface);
1347 ok(hr == MF_E_MULTIPLE_SUBSCRIBERS, "Unexpected hr %#lx.\n", hr);
1349 hr = MFCreateAsyncResult(NULL, &callback.IMFAsyncCallback_iface, NULL, &result);
1350 ok(hr == S_OK, "Failed to create result, hr %#lx.\n", hr);
1352 hr = IMFMediaSession_EndGetEvent(session, result, &event);
1353 ok(hr == E_FAIL, "Unexpected hr %#lx.\n", hr);
1355 /* Shutdown behavior. */
1356 hr = IMFMediaSession_Shutdown(session);
1357 ok(hr == S_OK, "Failed to shut down, hr %#lx.\n", hr);
1360 static void test_media_session(void)
1362 IMFRateSupport *rate_support;
1363 IMFAttributes *attributes;
1364 IMFMediaSession *session;
1365 MFSHUTDOWN_STATUS status;
1366 IMFTopology *topology;
1367 IMFShutdown *shutdown;
1368 PROPVARIANT propvar;
1369 IMFGetService *gs;
1370 IMFClock *clock;
1371 DWORD caps;
1372 HRESULT hr;
1374 hr = MFStartup(MF_VERSION, MFSTARTUP_FULL);
1375 ok(hr == S_OK, "Startup failure, hr %#lx.\n", hr);
1377 hr = MFCreateMediaSession(NULL, &session);
1378 ok(hr == S_OK, "Failed to create media session, hr %#lx.\n", hr);
1380 check_interface(session, &IID_IMFGetService, TRUE);
1381 check_interface(session, &IID_IMFRateSupport, TRUE);
1382 check_interface(session, &IID_IMFRateControl, TRUE);
1383 check_interface(session, &IID_IMFAttributes, FALSE);
1384 check_interface(session, &IID_IMFTopologyNodeAttributeEditor, FALSE);
1385 check_interface(session, &IID_IMFLocalMFTRegistration, FALSE);
1386 check_service_interface(session, &MF_RATE_CONTROL_SERVICE, &IID_IMFRateSupport, TRUE);
1387 check_service_interface(session, &MF_RATE_CONTROL_SERVICE, &IID_IMFRateControl, TRUE);
1388 check_service_interface(session, &MF_TOPONODE_ATTRIBUTE_EDITOR_SERVICE, &IID_IMFTopologyNodeAttributeEditor, TRUE);
1389 check_service_interface(session, &MF_LOCAL_MFT_REGISTRATION_SERVICE, &IID_IMFLocalMFTRegistration, TRUE);
1391 hr = IMFMediaSession_GetClock(session, &clock);
1392 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1394 hr = IMFClock_QueryInterface(clock, &IID_IMFShutdown, (void **)&shutdown);
1395 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1397 hr = IMFShutdown_GetShutdownStatus(shutdown, &status);
1398 ok(hr == MF_E_INVALIDREQUEST, "Unexpected hr %#lx.\n", hr);
1400 hr = IMFMediaSession_Shutdown(session);
1401 ok(hr == S_OK, "Failed to shut down, hr %#lx.\n", hr);
1403 check_interface(session, &IID_IMFGetService, TRUE);
1405 hr = IMFMediaSession_QueryInterface(session, &IID_IMFGetService, (void **)&gs);
1406 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1408 hr = IMFGetService_GetService(gs, &MF_RATE_CONTROL_SERVICE, &IID_IMFRateSupport, (void **)&rate_support);
1409 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
1411 IMFGetService_Release(gs);
1413 hr = IMFShutdown_GetShutdownStatus(shutdown, &status);
1414 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1415 ok(status == MFSHUTDOWN_COMPLETED, "Unexpected shutdown status %u.\n", status);
1417 IMFShutdown_Release(shutdown);
1419 hr = IMFMediaSession_ClearTopologies(session);
1420 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
1422 hr = IMFMediaSession_Start(session, &GUID_NULL, NULL);
1423 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
1425 propvar.vt = VT_EMPTY;
1426 hr = IMFMediaSession_Start(session, &GUID_NULL, &propvar);
1427 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
1429 hr = IMFMediaSession_Pause(session);
1430 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
1432 hr = IMFMediaSession_Stop(session);
1433 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
1435 hr = IMFMediaSession_Close(session);
1436 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
1438 hr = IMFMediaSession_GetClock(session, &clock);
1439 ok(hr == MF_E_SHUTDOWN || broken(hr == E_UNEXPECTED) /* Win7 */, "Unexpected hr %#lx.\n", hr);
1441 hr = IMFMediaSession_GetSessionCapabilities(session, &caps);
1442 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
1444 hr = IMFMediaSession_GetSessionCapabilities(session, NULL);
1445 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
1447 hr = IMFMediaSession_GetFullTopology(session, MFSESSION_GETFULLTOPOLOGY_CURRENT, 0, &topology);
1448 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
1450 hr = IMFMediaSession_Shutdown(session);
1451 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
1453 IMFMediaSession_Release(session);
1455 /* Custom topology loader, GUID is not registered. */
1456 hr = MFCreateAttributes(&attributes, 1);
1457 ok(hr == S_OK, "Failed to create attributes, hr %#lx.\n", hr);
1459 hr = IMFAttributes_SetGUID(attributes, &MF_SESSION_TOPOLOADER, &MF_SESSION_TOPOLOADER);
1460 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
1462 hr = MFCreateMediaSession(attributes, &session);
1463 ok(hr == S_OK, "Failed to create media session, hr %#lx.\n", hr);
1464 IMFMediaSession_Release(session);
1466 /* Disabled quality manager. */
1467 hr = IMFAttributes_SetGUID(attributes, &MF_SESSION_QUALITY_MANAGER, &GUID_NULL);
1468 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
1470 hr = MFCreateMediaSession(attributes, &session);
1471 ok(hr == S_OK, "Failed to create media session, hr %#lx.\n", hr);
1472 IMFMediaSession_Release(session);
1474 IMFAttributes_Release(attributes);
1476 /* Basic events behavior. */
1477 hr = MFCreateMediaSession(NULL, &session);
1478 ok(hr == S_OK, "Failed to create media session, hr %#lx.\n", hr);
1480 test_session_events(session);
1482 IMFMediaSession_Release(session);
1484 hr = MFShutdown();
1485 ok(hr == S_OK, "Shutdown failure, hr %#lx.\n", hr);
1488 static void test_media_session_rate_control(void)
1490 IMFRateControl *rate_control, *clock_rate_control;
1491 IMFPresentationClock *presentation_clock;
1492 IMFPresentationTimeSource *time_source;
1493 MFCLOCK_PROPERTIES clock_props;
1494 IMFRateSupport *rate_support;
1495 IMFMediaSession *session;
1496 IMFClock *clock;
1497 HRESULT hr;
1498 float rate;
1499 BOOL thin;
1501 hr = MFStartup(MF_VERSION, MFSTARTUP_FULL);
1502 ok(hr == S_OK, "Startup failure, hr %#lx.\n", hr);
1504 hr = MFCreateMediaSession(NULL, &session);
1505 ok(hr == S_OK, "Failed to create media session, hr %#lx.\n", hr);
1507 hr = MFGetService((IUnknown *)session, &MF_RATE_CONTROL_SERVICE, &IID_IMFRateSupport, (void **)&rate_support);
1508 ok(hr == S_OK, "Failed to get rate support interface, hr %#lx.\n", hr);
1510 hr = MFGetService((IUnknown *)session, &MF_RATE_CONTROL_SERVICE, &IID_IMFRateControl, (void **)&rate_control);
1511 ok(hr == S_OK, "Failed to get rate control interface, hr %#lx.\n", hr);
1513 hr = IMFRateControl_GetRate(rate_control, NULL, NULL);
1514 ok(FAILED(hr), "Unexpected hr %#lx.\n", hr);
1516 rate = 0.0f;
1517 hr = IMFRateControl_GetRate(rate_control, NULL, &rate);
1518 ok(hr == S_OK, "Failed to get playback rate, hr %#lx.\n", hr);
1519 ok(rate == 1.0f, "Unexpected rate %f.\n", rate);
1521 hr = IMFRateControl_GetRate(rate_control, &thin, NULL);
1522 ok(FAILED(hr), "Unexpected hr %#lx.\n", hr);
1524 thin = TRUE;
1525 rate = 0.0f;
1526 hr = IMFRateControl_GetRate(rate_control, &thin, &rate);
1527 ok(hr == S_OK, "Failed to get playback rate, hr %#lx.\n", hr);
1528 ok(!thin, "Unexpected thinning.\n");
1529 ok(rate == 1.0f, "Unexpected rate %f.\n", rate);
1531 hr = IMFMediaSession_GetClock(session, &clock);
1532 ok(hr == S_OK, "Failed to get clock, hr %#lx.\n", hr);
1534 hr = IMFClock_QueryInterface(clock, &IID_IMFPresentationClock, (void **)&presentation_clock);
1535 ok(hr == S_OK, "Failed to get rate control, hr %#lx.\n", hr);
1537 hr = IMFClock_QueryInterface(clock, &IID_IMFRateControl, (void **)&clock_rate_control);
1538 ok(hr == S_OK, "Failed to get rate control, hr %#lx.\n", hr);
1540 rate = 0.0f;
1541 hr = IMFRateControl_GetRate(clock_rate_control, NULL, &rate);
1542 ok(hr == S_OK, "Failed to get clock rate, hr %#lx.\n", hr);
1543 ok(rate == 1.0f, "Unexpected rate %f.\n", rate);
1545 hr = IMFRateControl_SetRate(clock_rate_control, FALSE, 1.5f);
1546 ok(hr == MF_E_CLOCK_NO_TIME_SOURCE, "Unexpected hr %#lx.\n", hr);
1548 hr = IMFRateControl_SetRate(rate_control, FALSE, 1.5f);
1549 ok(hr == S_OK, "Failed to set rate, hr %#lx.\n", hr);
1551 hr = IMFClock_GetProperties(clock, &clock_props);
1552 ok(hr == MF_E_CLOCK_NO_TIME_SOURCE, "Unexpected hr %#lx.\n", hr);
1554 hr = MFCreateSystemTimeSource(&time_source);
1555 ok(hr == S_OK, "Failed to create time source, hr %#lx.\n", hr);
1557 hr = IMFPresentationClock_SetTimeSource(presentation_clock, time_source);
1558 ok(hr == S_OK, "Failed to set time source, hr %#lx.\n", hr);
1560 hr = IMFRateControl_SetRate(rate_control, FALSE, 1.5f);
1561 ok(hr == S_OK, "Failed to set rate, hr %#lx.\n", hr);
1563 rate = 0.0f;
1564 hr = IMFRateControl_GetRate(clock_rate_control, NULL, &rate);
1565 ok(hr == S_OK, "Failed to get clock rate, hr %#lx.\n", hr);
1566 ok(rate == 1.0f, "Unexpected rate %f.\n", rate);
1568 IMFPresentationTimeSource_Release(time_source);
1570 IMFRateControl_Release(clock_rate_control);
1571 IMFPresentationClock_Release(presentation_clock);
1572 IMFClock_Release(clock);
1574 IMFRateControl_Release(rate_control);
1575 IMFRateSupport_Release(rate_support);
1577 IMFMediaSession_Release(session);
1579 hr = MFShutdown();
1580 ok(hr == S_OK, "Shutdown failure, hr %#lx.\n", hr);
1583 static HRESULT WINAPI test_grabber_callback_QueryInterface(IMFSampleGrabberSinkCallback *iface, REFIID riid,
1584 void **obj)
1586 if (IsEqualIID(riid, &IID_IMFSampleGrabberSinkCallback) ||
1587 IsEqualIID(riid, &IID_IMFClockStateSink) ||
1588 IsEqualIID(riid, &IID_IUnknown))
1590 *obj = iface;
1591 IMFSampleGrabberSinkCallback_AddRef(iface);
1592 return S_OK;
1595 *obj = NULL;
1596 return E_NOINTERFACE;
1599 static ULONG WINAPI test_grabber_callback_AddRef(IMFSampleGrabberSinkCallback *iface)
1601 return 2;
1604 static ULONG WINAPI test_grabber_callback_Release(IMFSampleGrabberSinkCallback *iface)
1606 return 1;
1609 static HRESULT WINAPI test_grabber_callback_OnClockStart(IMFSampleGrabberSinkCallback *iface, MFTIME systime,
1610 LONGLONG offset)
1612 return E_NOTIMPL;
1615 static HRESULT WINAPI test_grabber_callback_OnClockStop(IMFSampleGrabberSinkCallback *iface, MFTIME systime)
1617 return E_NOTIMPL;
1620 static HRESULT WINAPI test_grabber_callback_OnClockPause(IMFSampleGrabberSinkCallback *iface, MFTIME systime)
1622 return E_NOTIMPL;
1625 static HRESULT WINAPI test_grabber_callback_OnClockRestart(IMFSampleGrabberSinkCallback *iface, MFTIME systime)
1627 return E_NOTIMPL;
1630 static HRESULT WINAPI test_grabber_callback_OnClockSetRate(IMFSampleGrabberSinkCallback *iface, MFTIME systime, float rate)
1632 return E_NOTIMPL;
1635 static HRESULT WINAPI test_grabber_callback_OnSetPresentationClock(IMFSampleGrabberSinkCallback *iface,
1636 IMFPresentationClock *clock)
1638 return E_NOTIMPL;
1641 static HRESULT WINAPI test_grabber_callback_OnProcessSample(IMFSampleGrabberSinkCallback *iface, REFGUID major_type,
1642 DWORD sample_flags, LONGLONG sample_time, LONGLONG sample_duration, const BYTE *buffer, DWORD sample_size)
1644 return E_NOTIMPL;
1647 static HRESULT WINAPI test_grabber_callback_OnShutdown(IMFSampleGrabberSinkCallback *iface)
1649 return E_NOTIMPL;
1652 static const IMFSampleGrabberSinkCallbackVtbl test_grabber_callback_vtbl =
1654 test_grabber_callback_QueryInterface,
1655 test_grabber_callback_AddRef,
1656 test_grabber_callback_Release,
1657 test_grabber_callback_OnClockStart,
1658 test_grabber_callback_OnClockStop,
1659 test_grabber_callback_OnClockPause,
1660 test_grabber_callback_OnClockRestart,
1661 test_grabber_callback_OnClockSetRate,
1662 test_grabber_callback_OnSetPresentationClock,
1663 test_grabber_callback_OnProcessSample,
1664 test_grabber_callback_OnShutdown,
1667 struct test_source
1669 IMFMediaSource IMFMediaSource_iface;
1670 LONG refcount;
1673 static struct test_source *impl_from_IMFMediaSource(IMFMediaSource *iface)
1675 return CONTAINING_RECORD(iface, struct test_source, IMFMediaSource_iface);
1678 static HRESULT WINAPI test_source_QueryInterface(IMFMediaSource *iface, REFIID riid, void **out)
1680 if (IsEqualIID(riid, &IID_IMFMediaSource)
1681 || IsEqualIID(riid, &IID_IMFMediaEventGenerator)
1682 || IsEqualIID(riid, &IID_IUnknown))
1684 *out = iface;
1686 else
1688 *out = NULL;
1689 return E_NOINTERFACE;
1692 IMFMediaSource_AddRef(iface);
1693 return S_OK;
1696 static ULONG WINAPI test_source_AddRef(IMFMediaSource *iface)
1698 struct test_source *source = impl_from_IMFMediaSource(iface);
1699 return InterlockedIncrement(&source->refcount);
1702 static ULONG WINAPI test_source_Release(IMFMediaSource *iface)
1704 struct test_source *source = impl_from_IMFMediaSource(iface);
1705 ULONG refcount = InterlockedDecrement(&source->refcount);
1707 if (!refcount)
1708 free(source);
1710 return refcount;
1713 static HRESULT WINAPI test_source_GetEvent(IMFMediaSource *iface, DWORD flags, IMFMediaEvent **event)
1715 ok(0, "Unexpected call.\n");
1716 return E_NOTIMPL;
1719 static HRESULT WINAPI test_source_BeginGetEvent(IMFMediaSource *iface, IMFAsyncCallback *callback, IUnknown *state)
1721 ok(0, "Unexpected call.\n");
1722 return E_NOTIMPL;
1725 static HRESULT WINAPI test_source_EndGetEvent(IMFMediaSource *iface, IMFAsyncResult *result, IMFMediaEvent **event)
1727 ok(0, "Unexpected call.\n");
1728 return E_NOTIMPL;
1731 static HRESULT WINAPI test_source_QueueEvent(IMFMediaSource *iface, MediaEventType event_type, REFGUID ext_type,
1732 HRESULT hr, const PROPVARIANT *value)
1734 ok(0, "Unexpected call.\n");
1735 return E_NOTIMPL;
1738 static HRESULT WINAPI test_source_GetCharacteristics(IMFMediaSource *iface, DWORD *flags)
1740 ok(0, "Unexpected call.\n");
1741 return E_NOTIMPL;
1744 static HRESULT WINAPI test_source_CreatePresentationDescriptor(IMFMediaSource *iface, IMFPresentationDescriptor **pd)
1746 ok(0, "Unexpected call.\n");
1747 return E_NOTIMPL;
1750 static HRESULT WINAPI test_source_Start(IMFMediaSource *iface, IMFPresentationDescriptor *pd, const GUID *time_format,
1751 const PROPVARIANT *start_position)
1753 ok(0, "Unexpected call.\n");
1754 return E_NOTIMPL;
1757 static HRESULT WINAPI test_source_Stop(IMFMediaSource *iface)
1759 ok(0, "Unexpected call.\n");
1760 return E_NOTIMPL;
1763 static HRESULT WINAPI test_source_Pause(IMFMediaSource *iface)
1765 ok(0, "Unexpected call.\n");
1766 return E_NOTIMPL;
1769 static HRESULT WINAPI test_source_Shutdown(IMFMediaSource *iface)
1771 ok(0, "Unexpected call.\n");
1772 return E_NOTIMPL;
1775 static const IMFMediaSourceVtbl test_source_vtbl =
1777 test_source_QueryInterface,
1778 test_source_AddRef,
1779 test_source_Release,
1780 test_source_GetEvent,
1781 test_source_BeginGetEvent,
1782 test_source_EndGetEvent,
1783 test_source_QueueEvent,
1784 test_source_GetCharacteristics,
1785 test_source_CreatePresentationDescriptor,
1786 test_source_Start,
1787 test_source_Stop,
1788 test_source_Pause,
1789 test_source_Shutdown,
1792 static IMFMediaSource *create_test_source(void)
1794 struct test_source *source;
1796 source = calloc(1, sizeof(*source));
1797 source->IMFMediaSource_iface.lpVtbl = &test_source_vtbl;
1798 source->refcount = 1;
1800 return &source->IMFMediaSource_iface;
1803 static void init_media_type(IMFMediaType *mediatype, const struct attribute_desc *desc, ULONG limit)
1805 HRESULT hr;
1806 ULONG i;
1808 hr = IMFMediaType_DeleteAllItems(mediatype);
1809 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1811 for (i = 0; i < limit && desc[i].key; ++i)
1813 hr = IMFMediaType_SetItem(mediatype, desc[i].key, &desc[i].value);
1814 ok(hr == S_OK, "SetItem %s returned %#lx\n", debugstr_a(desc[i].name), hr);
1818 static void init_source_node(IMFMediaType *mediatype, IMFMediaSource *source, IMFTopologyNode *node)
1820 IMFPresentationDescriptor *pd;
1821 IMFMediaTypeHandler *handler;
1822 IMFStreamDescriptor *sd;
1823 HRESULT hr;
1825 hr = IMFTopologyNode_DeleteAllItems(node);
1826 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1828 hr = MFCreateStreamDescriptor(0, 1, &mediatype, &sd);
1829 ok(hr == S_OK, "Failed to create stream descriptor, hr %#lx.\n", hr);
1831 hr = IMFStreamDescriptor_GetMediaTypeHandler(sd, &handler);
1832 ok(hr == S_OK, "Failed to get media type handler, hr %#lx.\n", hr);
1834 hr = IMFMediaTypeHandler_SetCurrentMediaType(handler, mediatype);
1835 ok(hr == S_OK, "Failed to set current media type, hr %#lx.\n", hr);
1837 IMFMediaTypeHandler_Release(handler);
1839 hr = MFCreatePresentationDescriptor(1, &sd, &pd);
1840 ok(hr == S_OK, "Failed to create presentation descriptor, hr %#lx.\n", hr);
1842 hr = IMFTopologyNode_SetUnknown(node, &MF_TOPONODE_PRESENTATION_DESCRIPTOR, (IUnknown *)pd);
1843 ok(hr == S_OK, "Failed to set node pd, hr %#lx.\n", hr);
1845 IMFPresentationDescriptor_Release(pd);
1847 hr = IMFTopologyNode_SetUnknown(node, &MF_TOPONODE_STREAM_DESCRIPTOR, (IUnknown *)sd);
1848 ok(hr == S_OK, "Failed to set node sd, hr %#lx.\n", hr);
1850 if (source)
1852 hr = IMFTopologyNode_SetUnknown(node, &MF_TOPONODE_SOURCE, (IUnknown *)source);
1853 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1856 IMFStreamDescriptor_Release(sd);
1859 static void init_sink_node(IMFActivate *sink_activate, unsigned int method, IMFTopologyNode *node)
1861 IMFStreamSink *stream_sink;
1862 IMFMediaSink *sink;
1863 HRESULT hr;
1865 hr = IMFTopologyNode_DeleteAllItems(node);
1866 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1868 hr = IMFActivate_ActivateObject(sink_activate, &IID_IMFMediaSink, (void **)&sink);
1869 ok(hr == S_OK, "Failed to activate, hr %#lx.\n", hr);
1871 hr = IMFMediaSink_GetStreamSinkByIndex(sink, 0, &stream_sink);
1872 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1874 IMFMediaSink_Release(sink);
1876 hr = IMFTopologyNode_SetObject(node, (IUnknown *)stream_sink);
1877 ok(hr == S_OK, "Failed to set object, hr %#lx.\n", hr);
1879 IMFStreamSink_Release(stream_sink);
1881 hr = IMFTopologyNode_SetUINT32(node, &MF_TOPONODE_CONNECT_METHOD, method);
1882 ok(hr == S_OK, "Failed to set connect method, hr %#lx.\n", hr);
1885 enum loader_test_flags
1887 LOADER_EXPECTED_DECODER = 0x1,
1888 LOADER_EXPECTED_CONVERTER = 0x2,
1889 LOADER_TODO = 0x4,
1890 LOADER_NEEDS_VIDEO_PROCESSOR = 0x8,
1893 static void test_topology_loader(void)
1895 static const struct loader_test
1897 media_type_desc input_type;
1898 media_type_desc output_type;
1899 MF_CONNECT_METHOD method;
1900 HRESULT expected_result;
1901 unsigned int flags;
1903 loader_tests[] =
1906 /* PCM -> PCM, same type */
1908 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
1909 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_PCM),
1910 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 1),
1911 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 44100),
1912 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 44100),
1913 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 1),
1914 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 8),
1917 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
1918 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_PCM),
1919 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 1),
1920 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 44100),
1921 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 44100),
1922 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 1),
1923 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 8),
1926 MF_CONNECT_DIRECT,
1927 S_OK,
1931 /* PCM -> PCM, different bps. */
1933 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
1934 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_PCM),
1935 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 1),
1936 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 44100),
1937 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 44100),
1938 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 1),
1939 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 8),
1942 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
1943 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_PCM),
1944 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 1),
1945 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 48000),
1946 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 48000),
1947 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 1),
1948 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 8),
1951 MF_CONNECT_DIRECT,
1952 MF_E_INVALIDMEDIATYPE,
1956 /* PCM -> PCM, different bps. */
1958 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
1959 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_PCM),
1960 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 1),
1961 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 44100),
1962 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 44100),
1963 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 1),
1964 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 8),
1967 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
1968 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_PCM),
1969 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 1),
1970 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 48000),
1971 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 48000),
1972 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 1),
1973 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 8),
1976 MF_CONNECT_ALLOW_CONVERTER,
1977 S_OK,
1978 LOADER_NEEDS_VIDEO_PROCESSOR | LOADER_EXPECTED_CONVERTER | LOADER_TODO,
1982 /* MP3 -> PCM */
1984 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
1985 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_MP3),
1986 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 2),
1987 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 44100),
1988 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 16000),
1989 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 1),
1992 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
1993 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_PCM),
1994 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 1),
1995 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 44100),
1996 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 44100),
1997 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 1),
1998 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 8),
2001 MF_CONNECT_DIRECT,
2002 MF_E_INVALIDMEDIATYPE,
2006 /* MP3 -> PCM */
2008 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
2009 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_MP3),
2010 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 2),
2011 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 44100),
2012 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 16000),
2013 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 1),
2016 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
2017 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_PCM),
2018 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 1),
2019 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 44100),
2020 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 44100),
2021 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 1),
2022 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 8),
2025 MF_CONNECT_ALLOW_CONVERTER,
2026 MF_E_TRANSFORM_NOT_POSSIBLE_FOR_CURRENT_MEDIATYPE_COMBINATION,
2027 LOADER_NEEDS_VIDEO_PROCESSOR | LOADER_TODO,
2031 /* MP3 -> PCM */
2033 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
2034 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_MP3),
2035 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 2),
2036 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 44100),
2037 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 16000),
2038 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 1),
2041 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
2042 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_PCM),
2043 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 1),
2044 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 44100),
2045 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 44100),
2046 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 1),
2047 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 8),
2050 MF_CONNECT_ALLOW_DECODER,
2051 S_OK,
2052 LOADER_EXPECTED_DECODER | LOADER_TODO,
2056 IMFSampleGrabberSinkCallback test_grabber_callback = { &test_grabber_callback_vtbl };
2057 IMFTopologyNode *src_node, *sink_node, *src_node2, *sink_node2, *mft_node;
2058 IMFTopology *topology, *topology2, *full_topology;
2059 IMFMediaType *media_type, *input_type, *output_type;
2060 IMFPresentationDescriptor *pd;
2061 unsigned int i, count, value;
2062 IMFActivate *sink_activate;
2063 MF_TOPOLOGY_TYPE node_type;
2064 IMFStreamDescriptor *sd;
2065 IMFTransform *transform;
2066 IMFMediaSource *source;
2067 IMFTopoLoader *loader;
2068 IUnknown *node_object;
2069 WORD node_count;
2070 TOPOID node_id;
2071 DWORD index;
2072 HRESULT hr;
2073 BOOL ret;
2075 hr = MFStartup(MF_VERSION, MFSTARTUP_FULL);
2076 ok(hr == S_OK, "Startup failure, hr %#lx.\n", hr);
2078 hr = MFCreateTopoLoader(NULL);
2079 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
2081 hr = MFCreateTopoLoader(&loader);
2082 ok(hr == S_OK, "Failed to create topology loader, hr %#lx.\n", hr);
2084 hr = MFCreateTopology(&topology);
2085 ok(hr == S_OK, "Failed to create topology, hr %#lx.\n", hr);
2087 /* Empty topology */
2088 hr = IMFTopoLoader_Load(loader, topology, &full_topology, NULL);
2089 todo_wine
2090 ok(hr == MF_E_TOPO_UNSUPPORTED, "Unexpected hr %#lx.\n", hr);
2092 /* Add source node. */
2093 hr = MFCreateTopologyNode(MF_TOPOLOGY_SOURCESTREAM_NODE, &src_node);
2094 ok(hr == S_OK, "Failed to create topology node, hr %#lx.\n", hr);
2096 /* When a decoder is involved, windows requires this attribute to be present */
2097 source = create_test_source();
2099 hr = IMFTopologyNode_SetUnknown(src_node, &MF_TOPONODE_SOURCE, (IUnknown *)source);
2100 ok(hr == S_OK, "Failed to set node source, hr %#lx.\n", hr);
2102 hr = MFCreateMediaType(&media_type);
2103 ok(hr == S_OK, "Failed to create media type, hr %#lx.\n", hr);
2105 hr = IMFMediaType_SetGUID(media_type, &MF_MT_MAJOR_TYPE, &MFMediaType_Audio);
2106 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
2107 hr = IMFMediaType_SetGUID(media_type, &MF_MT_SUBTYPE, &MFAudioFormat_PCM);
2108 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
2110 hr = MFCreateStreamDescriptor(0, 1, &media_type, &sd);
2111 ok(hr == S_OK, "Failed to create stream descriptor, hr %#lx.\n", hr);
2113 hr = IMFTopologyNode_SetUnknown(src_node, &MF_TOPONODE_STREAM_DESCRIPTOR, (IUnknown *)sd);
2114 ok(hr == S_OK, "Failed to set node sd, hr %#lx.\n", hr);
2116 hr = MFCreatePresentationDescriptor(1, &sd, &pd);
2117 ok(hr == S_OK, "Failed to create presentation descriptor, hr %#lx.\n", hr);
2119 hr = IMFTopologyNode_SetUnknown(src_node, &MF_TOPONODE_PRESENTATION_DESCRIPTOR, (IUnknown *)pd);
2120 ok(hr == S_OK, "Failed to set node pd, hr %#lx.\n", hr);
2122 IMFPresentationDescriptor_Release(pd);
2123 IMFStreamDescriptor_Release(sd);
2124 IMFMediaType_Release(media_type);
2126 hr = IMFTopology_AddNode(topology, src_node);
2127 ok(hr == S_OK, "Failed to add a node, hr %#lx.\n", hr);
2129 /* Source node only. */
2130 hr = IMFTopoLoader_Load(loader, topology, &full_topology, NULL);
2131 todo_wine
2132 ok(hr == MF_E_TOPO_UNSUPPORTED, "Unexpected hr %#lx.\n", hr);
2134 hr = MFCreateTopologyNode(MF_TOPOLOGY_OUTPUT_NODE, &sink_node);
2135 ok(hr == S_OK, "Failed to create output node, hr %#lx.\n", hr);
2137 hr = MFCreateMediaType(&media_type);
2138 ok(hr == S_OK, "Failed to create media type, hr %#lx.\n", hr);
2140 hr = IMFMediaType_SetGUID(media_type, &MF_MT_MAJOR_TYPE, &MFMediaType_Audio);
2141 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
2142 hr = IMFMediaType_SetGUID(media_type, &MF_MT_SUBTYPE, &MFAudioFormat_PCM);
2143 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
2145 hr = MFCreateSampleGrabberSinkActivate(media_type, &test_grabber_callback, &sink_activate);
2146 ok(hr == S_OK, "Failed to create grabber sink, hr %#lx.\n", hr);
2148 hr = IMFTopologyNode_SetObject(sink_node, (IUnknown *)sink_activate);
2149 ok(hr == S_OK, "Failed to set object, hr %#lx.\n", hr);
2151 IMFMediaType_Release(media_type);
2153 hr = IMFTopology_AddNode(topology, sink_node);
2154 ok(hr == S_OK, "Failed to add sink node, hr %#lx.\n", hr);
2156 hr = IMFTopoLoader_Load(loader, topology, &full_topology, NULL);
2157 todo_wine
2158 ok(hr == MF_E_TOPO_UNSUPPORTED, "Unexpected hr %#lx.\n", hr);
2160 hr = IMFTopologyNode_ConnectOutput(src_node, 0, sink_node, 0);
2161 ok(hr == S_OK, "Failed to connect nodes, hr %#lx.\n", hr);
2163 /* Sink was not resolved. */
2164 hr = IMFTopoLoader_Load(loader, topology, &full_topology, NULL);
2165 ok(hr == MF_E_TOPO_SINK_ACTIVATES_UNSUPPORTED, "Unexpected hr %#lx.\n", hr);
2167 hr = MFCreateMediaType(&input_type);
2168 ok(hr == S_OK, "Failed to create media type, hr %#lx.\n", hr);
2170 hr = MFCreateMediaType(&output_type);
2171 ok(hr == S_OK, "Failed to create media type, hr %#lx.\n", hr);
2173 for (i = 0; i < ARRAY_SIZE(loader_tests); ++i)
2175 const struct loader_test *test = &loader_tests[i];
2177 init_media_type(input_type, test->input_type, -1);
2178 init_media_type(output_type, test->output_type, -1);
2180 hr = MFCreateSampleGrabberSinkActivate(output_type, &test_grabber_callback, &sink_activate);
2181 ok(hr == S_OK, "Failed to create grabber sink, hr %#lx.\n", hr);
2183 init_source_node(input_type, source, src_node);
2184 init_sink_node(sink_activate, test->method, sink_node);
2186 hr = IMFTopology_GetCount(topology, &count);
2187 ok(hr == S_OK, "Failed to get attribute count, hr %#lx.\n", hr);
2188 ok(!count, "Unexpected count %u.\n", count);
2190 hr = IMFTopoLoader_Load(loader, topology, &full_topology, NULL);
2191 if (test->flags & LOADER_NEEDS_VIDEO_PROCESSOR && !has_video_processor)
2192 ok(hr == MF_E_INVALIDMEDIATYPE, "Unexpected hr %#lx on test %u.\n", hr, i);
2193 else
2195 todo_wine_if(test->flags & LOADER_TODO)
2196 ok(hr == test->expected_result, "Unexpected hr %#lx on test %u.\n", hr, i);
2197 ok(full_topology != topology, "Unexpected instance.\n");
2200 if (test->expected_result == S_OK && hr == S_OK)
2202 hr = IMFTopology_GetCount(full_topology, &count);
2203 ok(hr == S_OK, "Failed to get attribute count, hr %#lx.\n", hr);
2204 todo_wine
2205 ok(count == 1, "Unexpected count %u.\n", count);
2207 value = 0xdeadbeef;
2208 hr = IMFTopology_GetUINT32(full_topology, &MF_TOPOLOGY_RESOLUTION_STATUS, &value);
2209 todo_wine {
2210 ok(hr == S_OK, "Failed to get attribute, hr %#lx.\n", hr);
2211 ok(value == MF_TOPOLOGY_RESOLUTION_SUCCEEDED, "Unexpected value %#x.\n", value);
2213 count = 2;
2214 if (test->flags & LOADER_EXPECTED_DECODER)
2215 count++;
2216 if (test->flags & LOADER_EXPECTED_CONVERTER)
2217 count++;
2219 hr = IMFTopology_GetNodeCount(full_topology, &node_count);
2220 ok(hr == S_OK, "Failed to get node count, hr %#lx.\n", hr);
2221 todo_wine_if(test->flags & (LOADER_EXPECTED_CONVERTER | LOADER_EXPECTED_DECODER))
2222 ok(node_count == count, "Unexpected node count %u.\n", node_count);
2224 hr = IMFTopologyNode_GetTopoNodeID(src_node, &node_id);
2225 ok(hr == S_OK, "Failed to get source node id, hr %#lx.\n", hr);
2227 hr = IMFTopology_GetNodeByID(full_topology, node_id, &src_node2);
2228 ok(hr == S_OK, "Failed to get source in resolved topology, hr %#lx.\n", hr);
2230 hr = IMFTopologyNode_GetTopoNodeID(sink_node, &node_id);
2231 ok(hr == S_OK, "Failed to get sink node id, hr %#lx.\n", hr);
2233 hr = IMFTopology_GetNodeByID(full_topology, node_id, &sink_node2);
2234 ok(hr == S_OK, "Failed to get sink in resolved topology, hr %#lx.\n", hr);
2236 if (test->flags & (LOADER_EXPECTED_DECODER | LOADER_EXPECTED_CONVERTER) && strcmp(winetest_platform, "wine"))
2238 hr = IMFTopologyNode_GetOutput(src_node2, 0, &mft_node, &index);
2239 ok(hr == S_OK, "Failed to get transform node in resolved topology, hr %#lx.\n", hr);
2240 ok(!index, "Unexpected stream index %lu.\n", index);
2242 hr = IMFTopologyNode_GetNodeType(mft_node, &node_type);
2243 ok(hr == S_OK, "Failed to get transform node type in resolved topology, hr %#lx.\n", hr);
2244 ok(node_type == MF_TOPOLOGY_TRANSFORM_NODE, "Unexpected node type %u.\n", node_type);
2246 hr = IMFTopologyNode_GetObject(mft_node, &node_object);
2247 ok(hr == S_OK, "Failed to get object of transform node, hr %#lx.\n", hr);
2249 if (test->flags & LOADER_EXPECTED_DECODER)
2251 value = 0;
2252 hr = IMFTopologyNode_GetUINT32(mft_node, &MF_TOPONODE_DECODER, &value);
2253 ok(hr == S_OK, "Failed to get attribute, hr %#lx.\n", hr);
2254 ok(value == 1, "Unexpected value.\n");
2257 hr = IMFTopologyNode_GetItem(mft_node, &MF_TOPONODE_TRANSFORM_OBJECTID, NULL);
2258 ok(hr == S_OK, "Failed to get attribute, hr %#lx.\n", hr);
2260 hr = IUnknown_QueryInterface(node_object, &IID_IMFTransform, (void **)&transform);
2261 ok(hr == S_OK, "Failed to get IMFTransform from transform node's object, hr %#lx.\n", hr);
2262 IUnknown_Release(node_object);
2264 hr = IMFTransform_GetInputCurrentType(transform, 0, &media_type);
2265 ok(hr == S_OK, "Failed to get transform input type, hr %#lx.\n", hr);
2267 hr = IMFMediaType_Compare(input_type, (IMFAttributes *)media_type, MF_ATTRIBUTES_MATCH_OUR_ITEMS, &ret);
2268 ok(hr == S_OK, "Failed to compare media types, hr %#lx.\n", hr);
2269 ok(ret, "Input type of first transform doesn't match source node type.\n");
2271 IMFTopologyNode_Release(mft_node);
2272 IMFMediaType_Release(media_type);
2273 IMFTransform_Release(transform);
2275 hr = IMFTopologyNode_GetInput(sink_node2, 0, &mft_node, &index);
2276 ok(hr == S_OK, "Failed to get transform node in resolved topology, hr %#lx.\n", hr);
2277 ok(!index, "Unexpected stream index %lu.\n", index);
2279 hr = IMFTopologyNode_GetNodeType(mft_node, &node_type);
2280 ok(hr == S_OK, "Failed to get transform node type in resolved topology, hr %#lx.\n", hr);
2281 ok(node_type == MF_TOPOLOGY_TRANSFORM_NODE, "Unexpected node type %u.\n", node_type);
2283 hr = IMFTopologyNode_GetItem(mft_node, &MF_TOPONODE_TRANSFORM_OBJECTID, NULL);
2284 ok(hr == S_OK, "Failed to get attribute, hr %#lx.\n", hr);
2286 hr = IMFTopologyNode_GetObject(mft_node, &node_object);
2287 ok(hr == S_OK, "Failed to get object of transform node, hr %#lx.\n", hr);
2289 hr = IUnknown_QueryInterface(node_object, &IID_IMFTransform, (void**) &transform);
2290 ok(hr == S_OK, "Failed to get IMFTransform from transform node's object, hr %#lx.\n", hr);
2291 IUnknown_Release(node_object);
2293 hr = IMFTransform_GetOutputCurrentType(transform, 0, &media_type);
2294 ok(hr == S_OK, "Failed to get transform output type, hr %#lx.\n", hr);
2296 hr = IMFMediaType_Compare(output_type, (IMFAttributes *)media_type, MF_ATTRIBUTES_MATCH_OUR_ITEMS, &ret);
2297 ok(hr == S_OK, "Failed to compare media types, hr %#lx.\n", hr);
2298 ok(ret, "Output type of last transform doesn't match sink node type.\n");
2300 IMFTopologyNode_Release(mft_node);
2301 IMFMediaType_Release(media_type);
2302 IMFTransform_Release(transform);
2305 IMFTopologyNode_Release(sink_node2);
2307 hr = IMFTopology_SetUINT32(full_topology, &IID_IMFTopology, 123);
2308 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2309 hr = IMFTopoLoader_Load(loader, full_topology, &topology2, NULL);
2310 ok(hr == S_OK, "Failed to resolve topology, hr %#lx.\n", hr);
2311 ok(full_topology != topology2, "Unexpected instance.\n");
2312 hr = IMFTopology_GetUINT32(topology2, &IID_IMFTopology, &value);
2313 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2315 IMFTopology_Release(topology2);
2316 IMFTopology_Release(full_topology);
2319 hr = IMFTopology_GetCount(topology, &count);
2320 ok(hr == S_OK, "Failed to get attribute count, hr %#lx.\n", hr);
2321 ok(!count, "Unexpected count %u.\n", count);
2323 IMFActivate_ShutdownObject(sink_activate);
2324 IMFActivate_Release(sink_activate);
2327 IMFMediaType_Release(input_type);
2328 IMFMediaType_Release(output_type);
2330 IMFMediaSource_Release(source);
2331 IMFTopoLoader_Release(loader);
2333 hr = MFShutdown();
2334 ok(hr == S_OK, "Shutdown failure, hr %#lx.\n", hr);
2337 static void test_topology_loader_evr(void)
2339 IMFTopologyNode *node, *source_node, *evr_node;
2340 IMFTopology *topology, *full_topology;
2341 IMFMediaTypeHandler *handler;
2342 unsigned int i, count, value;
2343 IMFStreamSink *stream_sink;
2344 IMFMediaType *media_type;
2345 IMFActivate *activate;
2346 IMFTopoLoader *loader;
2347 IMFMediaSink *sink;
2348 WORD node_count;
2349 UINT64 value64;
2350 HWND window;
2351 HRESULT hr;
2353 hr = CoInitialize(NULL);
2354 ok(hr == S_OK, "Failed to initialize, hr %#lx.\n", hr);
2356 hr = MFCreateTopoLoader(&loader);
2357 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2359 /* Source node. */
2360 hr = MFCreateTopologyNode(MF_TOPOLOGY_SOURCESTREAM_NODE, &source_node);
2361 ok(hr == S_OK, "Failed to create topology node, hr %#lx.\n", hr);
2363 hr = MFCreateMediaType(&media_type);
2364 ok(hr == S_OK, "Failed to create media type, hr %#lx.\n", hr);
2366 hr = IMFMediaType_SetGUID(media_type, &MF_MT_MAJOR_TYPE, &MFMediaType_Video);
2367 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2368 hr = IMFMediaType_SetGUID(media_type, &MF_MT_SUBTYPE, &MFVideoFormat_RGB32);
2369 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2370 hr = IMFMediaType_SetUINT64(media_type, &MF_MT_FRAME_SIZE, (UINT64)640 << 32 | 480);
2371 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2372 hr = IMFMediaType_SetUINT32(media_type, &MF_MT_ALL_SAMPLES_INDEPENDENT, TRUE);
2373 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2375 init_source_node(media_type, NULL, source_node);
2377 /* EVR sink node. */
2378 window = create_window();
2380 hr = MFCreateVideoRendererActivate(window, &activate);
2381 ok(hr == S_OK, "Failed to create activate object, hr %#lx.\n", hr);
2383 hr = IMFActivate_ActivateObject(activate, &IID_IMFMediaSink, (void **)&sink);
2384 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2386 hr = IMFMediaSink_GetStreamSinkById(sink, 0, &stream_sink);
2387 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2389 hr = MFCreateTopologyNode(MF_TOPOLOGY_OUTPUT_NODE, &evr_node);
2390 ok(hr == S_OK, "Failed to create topology node, hr %#lx.\n", hr);
2392 hr = IMFTopologyNode_SetObject(evr_node, (IUnknown *)stream_sink);
2393 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2395 hr = IMFStreamSink_GetMediaTypeHandler(stream_sink, &handler);
2396 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2397 hr = IMFMediaTypeHandler_SetCurrentMediaType(handler, media_type);
2398 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2399 IMFMediaTypeHandler_Release(handler);
2401 IMFStreamSink_Release(stream_sink);
2402 IMFMediaSink_Release(sink);
2404 hr = MFCreateTopology(&topology);
2405 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2407 hr = IMFTopology_AddNode(topology, source_node);
2408 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2409 hr = IMFTopology_AddNode(topology, evr_node);
2410 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2411 hr = IMFTopologyNode_ConnectOutput(source_node, 0, evr_node, 0);
2412 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2414 hr = IMFTopologyNode_SetUINT32(evr_node, &MF_TOPONODE_CONNECT_METHOD, MF_CONNECT_DIRECT);
2415 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2417 hr = IMFTopologyNode_GetCount(evr_node, &count);
2418 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2419 ok(count == 1, "Unexpected attribute count %u.\n", count);
2421 hr = IMFTopoLoader_Load(loader, topology, &full_topology, NULL);
2422 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2424 hr = IMFTopology_GetNodeCount(full_topology, &node_count);
2425 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2426 ok(node_count == 3, "Unexpected node count %u.\n", node_count);
2428 for (i = 0; i < node_count; ++i)
2430 MF_TOPOLOGY_TYPE node_type;
2432 hr = IMFTopology_GetNode(full_topology, i, &node);
2433 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2435 hr = IMFTopologyNode_GetNodeType(node, &node_type);
2436 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2438 if (node_type == MF_TOPOLOGY_OUTPUT_NODE)
2440 value = 1;
2441 hr = IMFTopologyNode_GetUINT32(node, &MF_TOPONODE_STREAMID, &value);
2442 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2443 ok(!value, "Unexpected stream id %u.\n", value);
2445 else if (node_type == MF_TOPOLOGY_SOURCESTREAM_NODE)
2447 value64 = 1;
2448 hr = IMFTopologyNode_GetUINT64(node, &MF_TOPONODE_MEDIASTART, &value64);
2449 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2450 ok(!value64, "Unexpected value.\n");
2454 IMFTopology_Release(full_topology);
2456 IMFTopoLoader_Release(loader);
2458 IMFTopologyNode_Release(source_node);
2459 IMFTopologyNode_Release(evr_node);
2460 IMFTopology_Release(topology);
2461 IMFMediaType_Release(media_type);
2462 DestroyWindow(window);
2464 CoUninitialize();
2467 static HRESULT WINAPI testshutdown_QueryInterface(IMFShutdown *iface, REFIID riid, void **obj)
2469 if (IsEqualIID(riid, &IID_IMFShutdown) ||
2470 IsEqualIID(riid, &IID_IUnknown))
2472 *obj = iface;
2473 IMFShutdown_AddRef(iface);
2474 return S_OK;
2477 *obj = NULL;
2478 return E_NOINTERFACE;
2481 static ULONG WINAPI testshutdown_AddRef(IMFShutdown *iface)
2483 return 2;
2486 static ULONG WINAPI testshutdown_Release(IMFShutdown *iface)
2488 return 1;
2491 static HRESULT WINAPI testshutdown_Shutdown(IMFShutdown *iface)
2493 return 0xdead;
2496 static HRESULT WINAPI testshutdown_GetShutdownStatus(IMFShutdown *iface, MFSHUTDOWN_STATUS *status)
2498 ok(0, "Unexpected call.\n");
2499 return E_NOTIMPL;
2502 static const IMFShutdownVtbl testshutdownvtbl =
2504 testshutdown_QueryInterface,
2505 testshutdown_AddRef,
2506 testshutdown_Release,
2507 testshutdown_Shutdown,
2508 testshutdown_GetShutdownStatus,
2511 static void test_MFShutdownObject(void)
2513 IMFShutdown testshutdown = { &testshutdownvtbl };
2514 IUnknown testshutdown2 = { &testservicevtbl };
2515 HRESULT hr;
2517 hr = MFShutdownObject(NULL);
2518 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2520 hr = MFShutdownObject((IUnknown *)&testshutdown);
2521 ok(hr == S_OK, "Failed to shut down, hr %#lx.\n", hr);
2523 hr = MFShutdownObject(&testshutdown2);
2524 ok(hr == S_OK, "Failed to shut down, hr %#lx.\n", hr);
2527 enum clock_action
2529 CLOCK_START,
2530 CLOCK_STOP,
2531 CLOCK_PAUSE,
2534 static HRESULT WINAPI test_clock_sink_QueryInterface(IMFClockStateSink *iface, REFIID riid, void **obj)
2536 if (IsEqualIID(riid, &IID_IMFClockStateSink) ||
2537 IsEqualIID(riid, &IID_IUnknown))
2539 *obj = iface;
2540 IMFClockStateSink_AddRef(iface);
2541 return S_OK;
2544 *obj = NULL;
2545 return E_NOINTERFACE;
2548 static ULONG WINAPI test_clock_sink_AddRef(IMFClockStateSink *iface)
2550 return 2;
2553 static ULONG WINAPI test_clock_sink_Release(IMFClockStateSink *iface)
2555 return 1;
2558 static HRESULT WINAPI test_clock_sink_OnClockStart(IMFClockStateSink *iface, MFTIME system_time, LONGLONG offset)
2560 return E_NOTIMPL;
2563 static HRESULT WINAPI test_clock_sink_OnClockStop(IMFClockStateSink *iface, MFTIME system_time)
2565 return E_NOTIMPL;
2568 static HRESULT WINAPI test_clock_sink_OnClockPause(IMFClockStateSink *iface, MFTIME system_time)
2570 return E_NOTIMPL;
2573 static HRESULT WINAPI test_clock_sink_OnClockRestart(IMFClockStateSink *iface, MFTIME system_time)
2575 return E_NOTIMPL;
2578 static HRESULT WINAPI test_clock_sink_OnClockSetRate(IMFClockStateSink *iface, MFTIME system_time, float rate)
2580 return E_NOTIMPL;
2583 static const IMFClockStateSinkVtbl test_clock_sink_vtbl =
2585 test_clock_sink_QueryInterface,
2586 test_clock_sink_AddRef,
2587 test_clock_sink_Release,
2588 test_clock_sink_OnClockStart,
2589 test_clock_sink_OnClockStop,
2590 test_clock_sink_OnClockPause,
2591 test_clock_sink_OnClockRestart,
2592 test_clock_sink_OnClockSetRate,
2595 static void test_presentation_clock(void)
2597 static const struct clock_state_test
2599 enum clock_action action;
2600 MFCLOCK_STATE clock_state;
2601 MFCLOCK_STATE source_state;
2602 HRESULT hr;
2604 clock_state_change[] =
2606 { CLOCK_STOP, MFCLOCK_STATE_STOPPED, MFCLOCK_STATE_INVALID },
2607 { CLOCK_PAUSE, MFCLOCK_STATE_STOPPED, MFCLOCK_STATE_INVALID, MF_E_INVALIDREQUEST },
2608 { CLOCK_STOP, MFCLOCK_STATE_STOPPED, MFCLOCK_STATE_INVALID, MF_E_CLOCK_STATE_ALREADY_SET },
2609 { CLOCK_START, MFCLOCK_STATE_RUNNING, MFCLOCK_STATE_RUNNING },
2610 { CLOCK_START, MFCLOCK_STATE_RUNNING, MFCLOCK_STATE_RUNNING },
2611 { CLOCK_PAUSE, MFCLOCK_STATE_PAUSED, MFCLOCK_STATE_PAUSED },
2612 { CLOCK_PAUSE, MFCLOCK_STATE_PAUSED, MFCLOCK_STATE_PAUSED, MF_E_CLOCK_STATE_ALREADY_SET },
2613 { CLOCK_STOP, MFCLOCK_STATE_STOPPED, MFCLOCK_STATE_STOPPED },
2614 { CLOCK_START, MFCLOCK_STATE_RUNNING, MFCLOCK_STATE_RUNNING },
2615 { CLOCK_STOP, MFCLOCK_STATE_STOPPED, MFCLOCK_STATE_STOPPED },
2616 { CLOCK_STOP, MFCLOCK_STATE_STOPPED, MFCLOCK_STATE_STOPPED, MF_E_CLOCK_STATE_ALREADY_SET },
2617 { CLOCK_PAUSE, MFCLOCK_STATE_STOPPED, MFCLOCK_STATE_STOPPED, MF_E_INVALIDREQUEST },
2618 { CLOCK_START, MFCLOCK_STATE_RUNNING, MFCLOCK_STATE_RUNNING },
2619 { CLOCK_PAUSE, MFCLOCK_STATE_PAUSED, MFCLOCK_STATE_PAUSED },
2620 { CLOCK_START, MFCLOCK_STATE_RUNNING, MFCLOCK_STATE_RUNNING },
2622 IMFClockStateSink test_sink = { &test_clock_sink_vtbl };
2623 IMFPresentationTimeSource *time_source;
2624 MFCLOCK_PROPERTIES props, props2;
2625 IMFRateControl *rate_control;
2626 IMFPresentationClock *clock;
2627 MFSHUTDOWN_STATUS status;
2628 IMFShutdown *shutdown;
2629 MFTIME systime, time;
2630 LONGLONG clock_time;
2631 MFCLOCK_STATE state;
2632 unsigned int i;
2633 DWORD value;
2634 float rate;
2635 HRESULT hr;
2636 BOOL thin;
2638 hr = MFStartup(MF_VERSION, MFSTARTUP_FULL);
2639 ok(hr == S_OK, "Failed to start up, hr %#lx.\n", hr);
2641 hr = MFCreatePresentationClock(&clock);
2642 ok(hr == S_OK, "Failed to create presentation clock, hr %#lx.\n", hr);
2644 check_interface(clock, &IID_IMFTimer, TRUE);
2645 check_interface(clock, &IID_IMFRateControl, TRUE);
2646 check_interface(clock, &IID_IMFPresentationClock, TRUE);
2647 check_interface(clock, &IID_IMFShutdown, TRUE);
2648 check_interface(clock, &IID_IMFClock, TRUE);
2650 hr = IMFPresentationClock_QueryInterface(clock, &IID_IMFRateControl, (void **)&rate_control);
2651 ok(hr == S_OK, "Failed to get rate control interface, hr %#lx.\n", hr);
2653 hr = IMFPresentationClock_GetTimeSource(clock, &time_source);
2654 ok(hr == MF_E_CLOCK_NO_TIME_SOURCE, "Unexpected hr %#lx.\n", hr);
2656 hr = IMFPresentationClock_GetTimeSource(clock, NULL);
2657 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
2659 hr = IMFPresentationClock_GetClockCharacteristics(clock, &value);
2660 ok(hr == MF_E_CLOCK_NO_TIME_SOURCE, "Unexpected hr %#lx.\n", hr);
2662 hr = IMFPresentationClock_GetClockCharacteristics(clock, NULL);
2663 ok(hr == MF_E_CLOCK_NO_TIME_SOURCE, "Unexpected hr %#lx.\n", hr);
2665 hr = IMFPresentationClock_GetTime(clock, &time);
2666 ok(hr == MF_E_CLOCK_NO_TIME_SOURCE, "Unexpected hr %#lx.\n", hr);
2668 hr = IMFPresentationClock_GetTime(clock, NULL);
2669 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
2671 value = 1;
2672 hr = IMFPresentationClock_GetContinuityKey(clock, &value);
2673 ok(hr == S_OK, "Failed to get continuity key, hr %#lx.\n", hr);
2674 ok(value == 0, "Unexpected value %lu.\n", value);
2676 hr = IMFPresentationClock_GetProperties(clock, &props);
2677 ok(hr == MF_E_CLOCK_NO_TIME_SOURCE, "Unexpected hr %#lx.\n", hr);
2679 hr = IMFPresentationClock_GetState(clock, 0, &state);
2680 ok(hr == S_OK, "Failed to get state, hr %#lx.\n", hr);
2681 ok(state == MFCLOCK_STATE_INVALID, "Unexpected state %d.\n", state);
2683 hr = IMFPresentationClock_GetCorrelatedTime(clock, 0, &clock_time, &systime);
2684 ok(hr == MF_E_CLOCK_NO_TIME_SOURCE, "Unexpected hr %#lx.\n", hr);
2686 hr = IMFPresentationClock_GetCorrelatedTime(clock, 0, NULL, &systime);
2687 ok(hr == MF_E_CLOCK_NO_TIME_SOURCE, "Unexpected hr %#lx.\n", hr);
2689 hr = IMFPresentationClock_GetCorrelatedTime(clock, 0, &time, NULL);
2690 ok(hr == MF_E_CLOCK_NO_TIME_SOURCE, "Unexpected hr %#lx.\n", hr);
2692 /* Sinks. */
2693 hr = IMFPresentationClock_AddClockStateSink(clock, NULL);
2694 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
2696 hr = IMFPresentationClock_AddClockStateSink(clock, &test_sink);
2697 ok(hr == S_OK, "Failed to add a sink, hr %#lx.\n", hr);
2699 hr = IMFPresentationClock_AddClockStateSink(clock, &test_sink);
2700 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
2702 hr = IMFPresentationClock_RemoveClockStateSink(clock, NULL);
2703 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
2705 hr = IMFPresentationClock_RemoveClockStateSink(clock, &test_sink);
2706 ok(hr == S_OK, "Failed to remove sink, hr %#lx.\n", hr);
2708 hr = IMFPresentationClock_RemoveClockStateSink(clock, &test_sink);
2709 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2711 /* State change commands, time source is not set yet. */
2712 hr = IMFPresentationClock_Start(clock, 0);
2713 ok(hr == MF_E_CLOCK_NO_TIME_SOURCE, "Unexpected hr %#lx.\n", hr);
2715 hr = IMFPresentationClock_Pause(clock);
2716 ok(hr == MF_E_CLOCK_NO_TIME_SOURCE, "Unexpected hr %#lx.\n", hr);
2718 hr = IMFPresentationClock_Stop(clock);
2719 ok(hr == MF_E_CLOCK_NO_TIME_SOURCE, "Unexpected hr %#lx.\n", hr);
2721 hr = IMFRateControl_SetRate(rate_control, FALSE, 0.0f);
2722 ok(hr == MF_E_CLOCK_NO_TIME_SOURCE, "Unexpected hr %#lx.\n", hr);
2724 /* Set default time source. */
2725 hr = MFCreateSystemTimeSource(&time_source);
2726 ok(hr == S_OK, "Failed to create time source, hr %#lx.\n", hr);
2728 hr = IMFPresentationTimeSource_GetClockCharacteristics(time_source, &value);
2729 ok(hr == S_OK, "Failed to get time source flags, hr %#lx.\n", hr);
2730 ok(value == (MFCLOCK_CHARACTERISTICS_FLAG_FREQUENCY_10MHZ | MFCLOCK_CHARACTERISTICS_FLAG_IS_SYSTEM_CLOCK),
2731 "Unexpected clock flags %#lx.\n", value);
2733 hr = IMFPresentationClock_SetTimeSource(clock, time_source);
2734 ok(hr == S_OK, "Failed to set time source, hr %#lx.\n", hr);
2736 hr = IMFPresentationTimeSource_GetProperties(time_source, &props2);
2737 ok(hr == S_OK, "Failed to get time source properties, hr %#lx.\n", hr);
2739 hr = IMFPresentationClock_GetClockCharacteristics(clock, &value);
2740 ok(hr == S_OK, "Failed to get clock flags, hr %#lx.\n", hr);
2741 ok(value == (MFCLOCK_CHARACTERISTICS_FLAG_FREQUENCY_10MHZ | MFCLOCK_CHARACTERISTICS_FLAG_IS_SYSTEM_CLOCK),
2742 "Unexpected clock flags %#lx.\n", value);
2744 hr = IMFPresentationClock_GetProperties(clock, &props);
2745 ok(hr == S_OK, "Failed to get clock properties, hr %#lx.\n", hr);
2746 ok(!memcmp(&props, &props2, sizeof(props)), "Unexpected clock properties.\n");
2748 /* Changing rate at initial state. */
2749 hr = IMFPresentationClock_GetState(clock, 0, &state);
2750 ok(hr == S_OK, "Failed to get clock state, hr %#lx.\n", hr);
2751 ok(state == MFCLOCK_STATE_INVALID, "Unexpected state %d.\n", state);
2753 hr = IMFRateControl_SetRate(rate_control, FALSE, 0.0f);
2754 ok(hr == S_OK, "Failed to set clock rate, hr %#lx.\n", hr);
2755 hr = IMFRateControl_GetRate(rate_control, &thin, &rate);
2756 ok(hr == S_OK, "Failed to get clock rate, hr %#lx.\n", hr);
2757 ok(rate == 0.0f, "Unexpected rate.\n");
2758 hr = IMFRateControl_SetRate(rate_control, FALSE, 1.0f);
2759 ok(hr == S_OK, "Failed to set clock rate, hr %#lx.\n", hr);
2761 /* State changes. */
2762 for (i = 0; i < ARRAY_SIZE(clock_state_change); ++i)
2764 switch (clock_state_change[i].action)
2766 case CLOCK_STOP:
2767 hr = IMFPresentationClock_Stop(clock);
2768 break;
2769 case CLOCK_PAUSE:
2770 hr = IMFPresentationClock_Pause(clock);
2771 break;
2772 case CLOCK_START:
2773 hr = IMFPresentationClock_Start(clock, 0);
2774 break;
2775 default:
2778 ok(hr == clock_state_change[i].hr, "%u: unexpected hr %#lx.\n", i, hr);
2780 hr = IMFPresentationTimeSource_GetState(time_source, 0, &state);
2781 ok(hr == S_OK, "%u: failed to get state, hr %#lx.\n", i, hr);
2782 ok(state == clock_state_change[i].source_state, "%u: unexpected state %d.\n", i, state);
2784 hr = IMFPresentationClock_GetState(clock, 0, &state);
2785 ok(hr == S_OK, "%u: failed to get state, hr %#lx.\n", i, hr);
2786 ok(state == clock_state_change[i].clock_state, "%u: unexpected state %d.\n", i, state);
2789 /* Clock time stamps. */
2790 hr = IMFPresentationClock_Start(clock, 10);
2791 ok(hr == S_OK, "Failed to start presentation clock, hr %#lx.\n", hr);
2793 hr = IMFPresentationClock_Pause(clock);
2794 ok(hr == S_OK, "Failed to pause presentation clock, hr %#lx.\n", hr);
2796 hr = IMFPresentationClock_GetTime(clock, &time);
2797 ok(hr == S_OK, "Failed to get clock time, hr %#lx.\n", hr);
2799 hr = IMFPresentationTimeSource_GetCorrelatedTime(time_source, 0, &clock_time, &systime);
2800 ok(hr == S_OK, "Failed to get time source time, hr %#lx.\n", hr);
2801 ok(time == clock_time, "Unexpected clock time.\n");
2803 hr = IMFPresentationClock_GetCorrelatedTime(clock, 0, &time, &systime);
2804 ok(hr == S_OK, "Failed to get clock time, hr %#lx.\n", hr);
2805 ok(time == clock_time, "Unexpected clock time.\n");
2807 IMFPresentationTimeSource_Release(time_source);
2809 hr = IMFRateControl_GetRate(rate_control, NULL, &rate);
2810 ok(hr == S_OK, "Failed to get clock rate, hr %#lx.\n", hr);
2812 hr = IMFRateControl_GetRate(rate_control, &thin, NULL);
2813 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
2815 hr = IMFRateControl_GetRate(rate_control, &thin, &rate);
2816 ok(hr == S_OK, "Failed to get clock rate, hr %#lx.\n", hr);
2817 ok(rate == 1.0f, "Unexpected rate.\n");
2818 ok(!thin, "Unexpected thinning.\n");
2820 hr = IMFPresentationClock_GetState(clock, 0, &state);
2821 ok(hr == S_OK, "Failed to get clock state, hr %#lx.\n", hr);
2822 ok(state == MFCLOCK_STATE_PAUSED, "Unexpected state %d.\n", state);
2824 hr = IMFPresentationClock_Start(clock, 0);
2825 ok(hr == S_OK, "Failed to stop, hr %#lx.\n", hr);
2827 hr = IMFRateControl_SetRate(rate_control, FALSE, 0.0f);
2828 ok(hr == S_OK, "Failed to set clock rate, hr %#lx.\n", hr);
2829 hr = IMFRateControl_GetRate(rate_control, &thin, &rate);
2830 ok(hr == S_OK, "Failed to get clock rate, hr %#lx.\n", hr);
2831 ok(rate == 0.0f, "Unexpected rate.\n");
2832 hr = IMFRateControl_SetRate(rate_control, FALSE, 1.0f);
2833 ok(hr == S_OK, "Failed to set clock rate, hr %#lx.\n", hr);
2834 hr = IMFRateControl_SetRate(rate_control, FALSE, 0.0f);
2835 ok(hr == S_OK, "Failed to set clock rate, hr %#lx.\n", hr);
2836 hr = IMFRateControl_SetRate(rate_control, FALSE, 0.5f);
2837 ok(hr == S_OK, "Failed to set clock rate, hr %#lx.\n", hr);
2838 hr = IMFRateControl_SetRate(rate_control, TRUE, -1.0f);
2839 ok(hr == MF_E_THINNING_UNSUPPORTED, "Unexpected hr %#lx.\n", hr);
2840 hr = IMFRateControl_SetRate(rate_control, TRUE, 0.0f);
2841 ok(hr == MF_E_THINNING_UNSUPPORTED, "Unexpected hr %#lx.\n", hr);
2842 hr = IMFRateControl_SetRate(rate_control, TRUE, 1.0f);
2843 ok(hr == MF_E_THINNING_UNSUPPORTED, "Unexpected hr %#lx.\n", hr);
2845 hr = IMFPresentationClock_GetState(clock, 0, &state);
2846 ok(hr == S_OK, "Failed to get clock state, hr %#lx.\n", hr);
2847 ok(state == MFCLOCK_STATE_RUNNING, "Unexpected state %d.\n", state);
2849 hr = IMFRateControl_GetRate(rate_control, &thin, &rate);
2850 ok(hr == S_OK, "Failed to get clock rate, hr %#lx.\n", hr);
2851 ok(rate == 0.5f, "Unexpected rate.\n");
2852 ok(!thin, "Unexpected thinning.\n");
2854 IMFRateControl_Release(rate_control);
2856 hr = IMFPresentationClock_QueryInterface(clock, &IID_IMFShutdown, (void **)&shutdown);
2857 ok(hr == S_OK, "Failed to get shutdown interface, hr %#lx.\n", hr);
2859 /* Shutdown behavior. */
2860 hr = IMFShutdown_GetShutdownStatus(shutdown, NULL);
2861 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
2863 hr = IMFShutdown_GetShutdownStatus(shutdown, &status);
2864 ok(hr == MF_E_INVALIDREQUEST, "Unexpected hr %#lx.\n", hr);
2866 hr = IMFShutdown_Shutdown(shutdown);
2867 ok(hr == S_OK, "Failed to shut down, hr %#lx.\n", hr);
2869 time_source = NULL;
2870 hr = IMFPresentationClock_GetTimeSource(clock, &time_source);
2871 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2872 ok(!!time_source, "Unexpected instance %p.\n", time_source);
2873 IMFPresentationTimeSource_Release(time_source);
2875 hr = IMFPresentationClock_GetTime(clock, &time);
2876 ok(hr == S_OK, "Failed to get time, hr %#lx.\n", hr);
2878 hr = IMFShutdown_GetShutdownStatus(shutdown, &status);
2879 ok(hr == S_OK, "Failed to get status, hr %#lx.\n", hr);
2880 ok(status == MFSHUTDOWN_COMPLETED, "Unexpected status.\n");
2882 hr = IMFPresentationClock_Start(clock, 0);
2883 ok(hr == S_OK, "Failed to start the clock, hr %#lx.\n", hr);
2885 hr = IMFShutdown_GetShutdownStatus(shutdown, &status);
2886 ok(hr == S_OK, "Failed to get status, hr %#lx.\n", hr);
2887 ok(status == MFSHUTDOWN_COMPLETED, "Unexpected status.\n");
2889 hr = IMFShutdown_Shutdown(shutdown);
2890 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2892 IMFShutdown_Release(shutdown);
2894 IMFPresentationClock_Release(clock);
2896 hr = MFShutdown();
2897 ok(hr == S_OK, "Failed to shut down, hr %#lx.\n", hr);
2900 static HRESULT WINAPI grabber_callback_QueryInterface(IMFSampleGrabberSinkCallback *iface, REFIID riid, void **obj)
2902 if (IsEqualIID(riid, &IID_IMFSampleGrabberSinkCallback) ||
2903 IsEqualIID(riid, &IID_IMFClockStateSink) ||
2904 IsEqualIID(riid, &IID_IUnknown))
2906 *obj = iface;
2907 IMFSampleGrabberSinkCallback_AddRef(iface);
2908 return S_OK;
2911 *obj = NULL;
2912 return E_NOINTERFACE;
2915 static ULONG WINAPI grabber_callback_AddRef(IMFSampleGrabberSinkCallback *iface)
2917 return 2;
2920 static ULONG WINAPI grabber_callback_Release(IMFSampleGrabberSinkCallback *iface)
2922 return 1;
2925 static HRESULT WINAPI grabber_callback_OnClockStart(IMFSampleGrabberSinkCallback *iface, MFTIME time, LONGLONG offset)
2927 return E_NOTIMPL;
2930 static HRESULT WINAPI grabber_callback_OnClockStop(IMFSampleGrabberSinkCallback *iface, MFTIME time)
2932 return E_NOTIMPL;
2935 static HRESULT WINAPI grabber_callback_OnClockPause(IMFSampleGrabberSinkCallback *iface, MFTIME time)
2937 return E_NOTIMPL;
2940 static HRESULT WINAPI grabber_callback_OnClockRestart(IMFSampleGrabberSinkCallback *iface, MFTIME time)
2942 return E_NOTIMPL;
2945 static HRESULT WINAPI grabber_callback_OnClockSetRate(IMFSampleGrabberSinkCallback *iface, MFTIME time, float rate)
2947 return E_NOTIMPL;
2950 static HRESULT WINAPI grabber_callback_OnSetPresentationClock(IMFSampleGrabberSinkCallback *iface,
2951 IMFPresentationClock *clock)
2953 return S_OK;
2956 static HRESULT WINAPI grabber_callback_OnProcessSample(IMFSampleGrabberSinkCallback *iface, REFGUID major_type,
2957 DWORD sample_flags, LONGLONG sample_time, LONGLONG sample_duration, const BYTE *buffer, DWORD sample_size)
2959 return E_NOTIMPL;
2962 static HRESULT WINAPI grabber_callback_OnShutdown(IMFSampleGrabberSinkCallback *iface)
2964 return S_OK;
2967 static const IMFSampleGrabberSinkCallbackVtbl grabber_callback_vtbl =
2969 grabber_callback_QueryInterface,
2970 grabber_callback_AddRef,
2971 grabber_callback_Release,
2972 grabber_callback_OnClockStart,
2973 grabber_callback_OnClockStop,
2974 grabber_callback_OnClockPause,
2975 grabber_callback_OnClockRestart,
2976 grabber_callback_OnClockSetRate,
2977 grabber_callback_OnSetPresentationClock,
2978 grabber_callback_OnProcessSample,
2979 grabber_callback_OnShutdown,
2982 static IMFSampleGrabberSinkCallback grabber_callback = { &grabber_callback_vtbl };
2984 static void test_sample_grabber(void)
2986 IMFMediaType *media_type, *media_type2, *media_type3;
2987 IMFMediaTypeHandler *handler, *handler2;
2988 IMFPresentationTimeSource *time_source;
2989 IMFPresentationClock *clock, *clock2;
2990 IMFStreamSink *stream, *stream2;
2991 IMFRateSupport *rate_support;
2992 IMFMediaEventGenerator *eg;
2993 IMFMediaSink *sink, *sink2;
2994 DWORD flags, count, id;
2995 IMFActivate *activate;
2996 IMFMediaEvent *event;
2997 UINT32 attr_count;
2998 ULONG refcount;
2999 IUnknown *unk;
3000 float rate;
3001 HRESULT hr;
3002 GUID guid;
3004 hr = MFStartup(MF_VERSION, MFSTARTUP_FULL);
3005 ok(hr == S_OK, "Failed to start up, hr %#lx.\n", hr);
3007 hr = MFCreateMediaType(&media_type);
3008 ok(hr == S_OK, "Failed to create media type, hr %#lx.\n", hr);
3010 hr = MFCreateSampleGrabberSinkActivate(NULL, NULL, &activate);
3011 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
3013 hr = MFCreateSampleGrabberSinkActivate(NULL, &grabber_callback, &activate);
3014 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
3016 hr = IMFMediaType_SetGUID(media_type, &MF_MT_MAJOR_TYPE, &MFMediaType_Audio);
3017 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
3018 hr = IMFMediaType_SetGUID(media_type, &MF_MT_SUBTYPE, &MFAudioFormat_PCM);
3019 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
3021 EXPECT_REF(media_type, 1);
3022 hr = MFCreateSampleGrabberSinkActivate(media_type, &grabber_callback, &activate);
3023 ok(hr == S_OK, "Failed to create grabber activate, hr %#lx.\n", hr);
3024 EXPECT_REF(media_type, 2);
3026 hr = IMFActivate_GetCount(activate, &attr_count);
3027 ok(hr == S_OK, "Failed to get attribute count, hr %#lx.\n", hr);
3028 ok(!attr_count, "Unexpected count %u.\n", attr_count);
3030 hr = IMFActivate_ActivateObject(activate, &IID_IMFMediaSink, (void **)&sink);
3031 ok(hr == S_OK, "Failed to activate object, hr %#lx.\n", hr);
3033 check_interface(sink, &IID_IMFClockStateSink, TRUE);
3034 check_interface(sink, &IID_IMFMediaEventGenerator, TRUE);
3035 check_interface(sink, &IID_IMFGetService, TRUE);
3036 check_interface(sink, &IID_IMFRateSupport, TRUE);
3037 check_service_interface(sink, &MF_RATE_CONTROL_SERVICE, &IID_IMFRateSupport, TRUE);
3039 if (SUCCEEDED(MFGetService((IUnknown *)sink, &MF_RATE_CONTROL_SERVICE, &IID_IMFRateSupport, (void **)&rate_support)))
3041 hr = IMFRateSupport_GetFastestRate(rate_support, MFRATE_FORWARD, FALSE, &rate);
3042 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3043 ok(rate == FLT_MAX, "Unexpected rate %f.\n", rate);
3045 hr = IMFRateSupport_GetFastestRate(rate_support, MFRATE_FORWARD, TRUE, &rate);
3046 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3047 ok(rate == FLT_MAX, "Unexpected rate %f.\n", rate);
3049 hr = IMFRateSupport_GetFastestRate(rate_support, MFRATE_REVERSE, FALSE, &rate);
3050 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3051 ok(rate == -FLT_MAX, "Unexpected rate %f.\n", rate);
3053 hr = IMFRateSupport_GetFastestRate(rate_support, MFRATE_REVERSE, TRUE, &rate);
3054 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3055 ok(rate == -FLT_MAX, "Unexpected rate %f.\n", rate);
3057 hr = IMFRateSupport_GetSlowestRate(rate_support, MFRATE_FORWARD, FALSE, &rate);
3058 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3059 ok(rate == 0.0f, "Unexpected rate %f.\n", rate);
3061 hr = IMFRateSupport_GetSlowestRate(rate_support, MFRATE_FORWARD, TRUE, &rate);
3062 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3063 ok(rate == 0.0f, "Unexpected rate %f.\n", rate);
3065 hr = IMFRateSupport_GetSlowestRate(rate_support, MFRATE_REVERSE, FALSE, &rate);
3066 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3067 ok(rate == 0.0f, "Unexpected rate %f.\n", rate);
3069 hr = IMFRateSupport_GetSlowestRate(rate_support, MFRATE_REVERSE, TRUE, &rate);
3070 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3071 ok(rate == 0.0f, "Unexpected rate %f.\n", rate);
3073 hr = IMFRateSupport_IsRateSupported(rate_support, TRUE, 1.0f, &rate);
3074 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3075 ok(rate == 1.0f, "Unexpected rate %f.\n", rate);
3077 IMFRateSupport_Release(rate_support);
3080 hr = IMFMediaSink_GetCharacteristics(sink, &flags);
3081 ok(hr == S_OK, "Failed to get sink flags, hr %#lx.\n", hr);
3082 ok(flags & MEDIASINK_FIXED_STREAMS, "Unexpected flags %#lx.\n", flags);
3084 hr = IMFMediaSink_GetStreamSinkCount(sink, &count);
3085 ok(hr == S_OK, "Failed to get stream count, hr %#lx.\n", hr);
3086 ok(count == 1, "Unexpected stream count %lu.\n", count);
3088 hr = IMFMediaSink_GetStreamSinkByIndex(sink, 0, &stream);
3089 ok(hr == S_OK, "Failed to get sink stream, hr %#lx.\n", hr);
3091 check_interface(stream, &IID_IMFMediaEventGenerator, TRUE);
3092 check_interface(stream, &IID_IMFMediaTypeHandler, TRUE);
3094 hr = IMFStreamSink_GetIdentifier(stream, &id);
3095 ok(hr == S_OK, "Failed to get stream id, hr %#lx.\n", hr);
3096 ok(id == 0, "Unexpected id %#lx.\n", id);
3098 hr = IMFStreamSink_GetMediaSink(stream, &sink2);
3099 ok(hr == S_OK, "Failed to get media sink, hr %lx.\n", hr);
3100 ok(sink2 == sink, "Unexpected sink.\n");
3101 IMFMediaSink_Release(sink2);
3103 hr = IMFMediaSink_GetStreamSinkByIndex(sink, 1, &stream2);
3104 ok(hr == MF_E_INVALIDINDEX, "Unexpected hr %#lx.\n", hr);
3106 hr = IMFMediaSink_GetStreamSinkById(sink, 1, &stream2);
3107 ok(hr == MF_E_INVALIDSTREAMNUMBER, "Unexpected hr %#lx.\n", hr);
3109 hr = IMFMediaSink_AddStreamSink(sink, 1, NULL, &stream2);
3110 ok(hr == MF_E_STREAMSINKS_FIXED, "Unexpected hr %#lx.\n", hr);
3112 hr = IMFMediaSink_RemoveStreamSink(sink, 0);
3113 ok(hr == MF_E_STREAMSINKS_FIXED, "Unexpected hr %#lx.\n", hr);
3115 hr = IMFMediaSink_RemoveStreamSink(sink, 1);
3116 ok(hr == MF_E_STREAMSINKS_FIXED, "Unexpected hr %#lx.\n", hr);
3118 check_interface(sink, &IID_IMFClockStateSink, TRUE);
3120 /* Event generator. */
3121 hr = IMFMediaSink_QueryInterface(sink, &IID_IMFMediaEventGenerator, (void **)&eg);
3122 ok(hr == S_OK, "Failed to get interface, hr %#lx.\n", hr);
3124 hr = IMFMediaEventGenerator_GetEvent(eg, MF_EVENT_FLAG_NO_WAIT, &event);
3125 ok(hr == MF_E_NO_EVENTS_AVAILABLE, "Unexpected hr %#lx.\n", hr);
3127 hr = IMFMediaSink_QueryInterface(sink, &IID_IMFPresentationTimeSource, (void **)&unk);
3128 ok(hr == E_NOINTERFACE, "Unexpected hr %#lx.\n", hr);
3130 hr = IMFStreamSink_QueryInterface(stream, &IID_IMFMediaTypeHandler, (void **)&handler2);
3131 ok(hr == S_OK, "Failed to get handler interface, hr %#lx.\n", hr);
3133 hr = IMFStreamSink_GetMediaTypeHandler(stream, &handler);
3134 ok(hr == S_OK, "Failed to get type handler, hr %#lx.\n", hr);
3135 hr = IMFMediaTypeHandler_GetMediaTypeCount(handler, &count);
3136 ok(hr == S_OK, "Failed to get media type count, hr %#lx.\n", hr);
3137 ok(count == 0, "Unexpected count %lu.\n", count);
3138 ok(handler == handler2, "Unexpected handler.\n");
3140 IMFMediaTypeHandler_Release(handler);
3141 IMFMediaTypeHandler_Release(handler2);
3143 /* Set clock. */
3144 hr = MFCreatePresentationClock(&clock);
3145 ok(hr == S_OK, "Failed to create clock object, hr %#lx.\n", hr);
3147 hr = IMFMediaSink_GetPresentationClock(sink, NULL);
3148 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
3150 hr = IMFMediaSink_GetPresentationClock(sink, &clock2);
3151 ok(hr == MF_E_NO_CLOCK, "Unexpected hr %#lx.\n", hr);
3153 hr = IMFMediaSink_SetPresentationClock(sink, NULL);
3154 ok(hr == S_OK, "Failed to set presentation clock, hr %#lx.\n", hr);
3156 hr = IMFMediaSink_SetPresentationClock(sink, clock);
3157 ok(hr == S_OK, "Failed to set presentation clock, hr %#lx.\n", hr);
3159 hr = MFCreateSystemTimeSource(&time_source);
3160 ok(hr == S_OK, "Failed to create time source, hr %#lx.\n", hr);
3162 hr = IMFPresentationClock_SetTimeSource(clock, time_source);
3163 ok(hr == S_OK, "Failed to set time source, hr %#lx.\n", hr);
3164 IMFPresentationTimeSource_Release(time_source);
3166 hr = IMFMediaSink_GetCharacteristics(sink, &flags);
3167 ok(hr == S_OK, "Failed to get sink flags, hr %#lx.\n", hr);
3169 hr = IMFActivate_ShutdownObject(activate);
3170 ok(hr == S_OK, "Failed to shut down, hr %#lx.\n", hr);
3172 hr = IMFMediaSink_GetCharacteristics(sink, &flags);
3173 ok(hr == S_OK, "Failed to get sink flags, hr %#lx.\n", hr);
3175 hr = IMFStreamSink_GetMediaTypeHandler(stream, &handler);
3176 ok(hr == S_OK, "Failed to get type handler, hr %#lx.\n", hr);
3178 /* On Win8+ this initialization happens automatically. */
3179 hr = IMFMediaTypeHandler_SetCurrentMediaType(handler, media_type);
3180 ok(hr == S_OK, "Failed to set media type, hr %#lx.\n", hr);
3182 hr = IMFMediaTypeHandler_GetMediaTypeCount(handler, NULL);
3183 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
3185 hr = IMFMediaTypeHandler_GetMediaTypeCount(handler, &count);
3186 ok(hr == S_OK, "Failed to get media type count, hr %#lx.\n", hr);
3187 ok(count == 0, "Unexpected count %lu.\n", count);
3189 hr = IMFMediaTypeHandler_GetMajorType(handler, &guid);
3190 ok(hr == S_OK, "Failed to get major type, hr %#lx.\n", hr);
3191 ok(IsEqualGUID(&guid, &MFMediaType_Audio), "Unexpected major type %s.\n", wine_dbgstr_guid(&guid));
3193 hr = IMFMediaTypeHandler_GetCurrentMediaType(handler, &media_type2);
3194 ok(hr == S_OK, "Failed to get current type, hr %#lx.\n", hr);
3195 ok(media_type2 == media_type, "Unexpected media type.\n");
3196 IMFMediaType_Release(media_type2);
3198 hr = MFCreateMediaType(&media_type2);
3199 ok(hr == S_OK, "Failed to create media type, hr %#lx.\n", hr);
3201 hr = IMFMediaTypeHandler_SetCurrentMediaType(handler, media_type2);
3202 ok(hr == MF_E_INVALIDMEDIATYPE, "Unexpected hr %#lx.\n", hr);
3204 hr = IMFMediaType_SetGUID(media_type2, &MF_MT_MAJOR_TYPE, &MFMediaType_Audio);
3205 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
3207 hr = IMFMediaTypeHandler_SetCurrentMediaType(handler, media_type2);
3208 ok(hr == MF_E_INVALIDMEDIATYPE, "Unexpected hr %#lx.\n", hr);
3210 hr = IMFMediaType_SetGUID(media_type2, &MF_MT_SUBTYPE, &MFAudioFormat_Float);
3211 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
3213 hr = IMFMediaTypeHandler_SetCurrentMediaType(handler, media_type2);
3214 ok(hr == MF_E_INVALIDMEDIATYPE, "Unexpected hr %#lx.\n", hr);
3216 hr = IMFMediaType_SetGUID(media_type2, &MF_MT_SUBTYPE, &MFAudioFormat_PCM);
3217 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
3219 hr = IMFMediaType_SetUINT32(media_type2, &MF_MT_AUDIO_SAMPLES_PER_SECOND, 44100);
3220 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
3222 hr = IMFMediaTypeHandler_SetCurrentMediaType(handler, media_type2);
3223 ok(hr == S_OK, "Failed to get current type, hr %#lx.\n", hr);
3224 IMFMediaType_Release(media_type);
3226 hr = IMFMediaTypeHandler_SetCurrentMediaType(handler, NULL);
3227 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
3229 hr = IMFMediaTypeHandler_GetCurrentMediaType(handler, &media_type);
3230 ok(hr == S_OK, "Failed to get current type, hr %#lx.\n", hr);
3231 ok(media_type2 == media_type, "Unexpected media type.\n");
3232 IMFMediaType_Release(media_type);
3234 hr = IMFMediaTypeHandler_GetMediaTypeByIndex(handler, 0, &media_type);
3235 ok(hr == MF_E_NO_MORE_TYPES, "Unexpected hr %#lx.\n", hr);
3237 hr = IMFMediaTypeHandler_GetMediaTypeByIndex(handler, 0, NULL);
3238 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
3240 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, media_type2, NULL);
3241 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3243 hr = MFCreateMediaType(&media_type);
3244 ok(hr == S_OK, "Failed to create media type, hr %#lx.\n", hr);
3246 hr = IMFMediaType_SetGUID(media_type, &MF_MT_MAJOR_TYPE, &MFMediaType_Audio);
3247 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
3249 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, media_type, NULL);
3250 ok(hr == MF_E_INVALIDMEDIATYPE, "Unexpected hr %#lx.\n", hr);
3252 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, media_type, &media_type3);
3253 ok(hr == MF_E_INVALIDMEDIATYPE, "Unexpected hr %#lx.\n", hr);
3255 hr = IMFMediaType_SetGUID(media_type, &MF_MT_SUBTYPE, &MFAudioFormat_PCM);
3256 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
3258 media_type3 = (void *)0xdeadbeef;
3259 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, media_type, &media_type3);
3260 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3261 ok(media_type3 == (void *)0xdeadbeef, "Unexpected media type %p.\n", media_type3);
3263 hr = IMFMediaType_SetUINT32(media_type, &MF_MT_FIXED_SIZE_SAMPLES, 1);
3264 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
3266 hr = IMFMediaType_SetUINT32(media_type, &MF_MT_SAMPLE_SIZE, 1024);
3267 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
3269 media_type3 = (void *)0xdeadbeef;
3270 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, media_type, &media_type3);
3271 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3272 ok(media_type3 == (void *)0xdeadbeef, "Unexpected media type %p.\n", media_type3);
3274 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, NULL, NULL);
3275 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
3277 hr = IMFMediaEventGenerator_GetEvent(eg, MF_EVENT_FLAG_NO_WAIT, &event);
3278 ok(hr == MF_E_NO_EVENTS_AVAILABLE, "Unexpected hr %#lx.\n", hr);
3280 hr = IMFStreamSink_GetEvent(stream, MF_EVENT_FLAG_NO_WAIT, &event);
3281 ok(hr == MF_E_NO_EVENTS_AVAILABLE, "Unexpected hr %#lx.\n", hr);
3283 EXPECT_REF(clock, 3);
3284 hr = IMFMediaSink_Shutdown(sink);
3285 ok(hr == S_OK, "Failed to shut down, hr %#lx.\n", hr);
3286 EXPECT_REF(clock, 1);
3288 hr = IMFMediaEventGenerator_GetEvent(eg, MF_EVENT_FLAG_NO_WAIT, &event);
3289 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
3291 hr = IMFMediaSink_Shutdown(sink);
3292 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
3294 hr = IMFMediaSink_GetCharacteristics(sink, &flags);
3295 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
3297 hr = IMFMediaSink_AddStreamSink(sink, 1, NULL, &stream2);
3298 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
3300 hr = IMFMediaSink_GetStreamSinkCount(sink, &count);
3301 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
3303 hr = IMFMediaSink_GetStreamSinkByIndex(sink, 0, &stream2);
3304 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
3306 hr = IMFStreamSink_GetEvent(stream, MF_EVENT_FLAG_NO_WAIT, &event);
3307 ok(hr == MF_E_STREAMSINK_REMOVED, "Unexpected hr %#lx.\n", hr);
3309 hr = IMFStreamSink_GetMediaSink(stream, &sink2);
3310 ok(hr == MF_E_STREAMSINK_REMOVED, "Unexpected hr %#lx.\n", hr);
3312 id = 1;
3313 hr = IMFStreamSink_GetIdentifier(stream, &id);
3314 ok(hr == MF_E_STREAMSINK_REMOVED, "Unexpected hr %#lx.\n", hr);
3315 ok(id == 1, "Unexpected id %lu.\n", id);
3317 media_type3 = (void *)0xdeadbeef;
3318 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, media_type, &media_type3);
3319 ok(hr == MF_E_STREAMSINK_REMOVED, "Unexpected hr %#lx.\n", hr);
3320 ok(media_type3 == (void *)0xdeadbeef, "Unexpected media type %p.\n", media_type3);
3322 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, NULL, NULL);
3323 ok(hr == MF_E_STREAMSINK_REMOVED, "Unexpected hr %#lx.\n", hr);
3325 hr = IMFMediaTypeHandler_SetCurrentMediaType(handler, NULL);
3326 ok(hr == MF_E_STREAMSINK_REMOVED, "Unexpected hr %#lx.\n", hr);
3328 hr = IMFMediaTypeHandler_GetMediaTypeCount(handler, &count);
3329 ok(hr == S_OK, "Failed to get type count, hr %#lx.\n", hr);
3331 IMFMediaType_Release(media_type2);
3332 IMFMediaType_Release(media_type);
3334 hr = IMFMediaTypeHandler_GetMediaTypeByIndex(handler, 0, &media_type);
3335 ok(hr == MF_E_NO_MORE_TYPES, "Unexpected hr %#lx.\n", hr);
3337 hr = IMFMediaTypeHandler_GetCurrentMediaType(handler, &media_type);
3338 ok(hr == MF_E_STREAMSINK_REMOVED, "Unexpected hr %#lx.\n", hr);
3340 hr = IMFMediaTypeHandler_GetCurrentMediaType(handler, NULL);
3341 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
3343 hr = IMFMediaTypeHandler_GetMajorType(handler, NULL);
3344 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
3346 hr = IMFMediaTypeHandler_GetMajorType(handler, &guid);
3347 ok(hr == MF_E_STREAMSINK_REMOVED, "Unexpected hr %#lx.\n", hr);
3349 IMFMediaTypeHandler_Release(handler);
3351 handler = (void *)0xdeadbeef;
3352 hr = IMFStreamSink_GetMediaTypeHandler(stream, &handler);
3353 ok(hr == MF_E_STREAMSINK_REMOVED, "Unexpected hr %#lx.\n", hr);
3354 ok(handler == (void *)0xdeadbeef, "Unexpected pointer.\n");
3356 hr = IMFStreamSink_GetMediaTypeHandler(stream, NULL);
3357 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
3359 IMFMediaEventGenerator_Release(eg);
3360 IMFMediaSink_Release(sink);
3361 IMFStreamSink_Release(stream);
3363 refcount = IMFActivate_Release(activate);
3364 ok(!refcount, "Unexpected refcount %lu.\n", refcount);
3366 /* Rateless mode with MF_SAMPLEGRABBERSINK_IGNORE_CLOCK. */
3367 hr = MFCreateMediaType(&media_type);
3368 ok(hr == S_OK, "Failed to create media type, hr %#lx.\n", hr);
3370 hr = IMFMediaType_SetGUID(media_type, &MF_MT_MAJOR_TYPE, &MFMediaType_Audio);
3371 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
3372 hr = IMFMediaType_SetGUID(media_type, &MF_MT_SUBTYPE, &MFAudioFormat_PCM);
3373 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
3375 hr = MFCreateSampleGrabberSinkActivate(media_type, &grabber_callback, &activate);
3376 ok(hr == S_OK, "Failed to create grabber activate, hr %#lx.\n", hr);
3378 hr = IMFActivate_SetUINT32(activate, &MF_SAMPLEGRABBERSINK_IGNORE_CLOCK, 1);
3379 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
3381 hr = IMFActivate_ActivateObject(activate, &IID_IMFMediaSink, (void **)&sink);
3382 ok(hr == S_OK, "Failed to activate object, hr %#lx.\n", hr);
3384 hr = IMFMediaSink_GetCharacteristics(sink, &flags);
3385 ok(hr == S_OK, "Failed to get sink flags, hr %#lx.\n", hr);
3386 ok(flags & MEDIASINK_RATELESS, "Unexpected flags %#lx.\n", flags);
3388 hr = IMFActivate_ShutdownObject(activate);
3389 ok(hr == S_OK, "Failed to shut down, hr %#lx.\n", hr);
3391 hr = IMFMediaSink_Shutdown(sink);
3392 ok(hr == S_OK, "Failed to shut down, hr %#lx.\n", hr);
3394 IMFMediaSink_Release(sink);
3396 /* Detaching */
3397 hr = MFCreateSampleGrabberSinkActivate(media_type, &grabber_callback, &activate);
3398 ok(hr == S_OK, "Failed to create grabber activate, hr %#lx.\n", hr);
3400 hr = IMFActivate_ActivateObject(activate, &IID_IMFMediaSink, (void **)&sink);
3401 ok(hr == S_OK, "Failed to activate object, hr %#lx.\n", hr);
3402 IMFMediaSink_Release(sink);
3404 hr = IMFActivate_ShutdownObject(activate);
3405 ok(hr == S_OK, "Failed to shut down, hr %#lx.\n", hr);
3407 hr = IMFActivate_ActivateObject(activate, &IID_IMFMediaSink, (void **)&sink);
3408 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
3410 hr = IMFActivate_GetCount(activate, &attr_count);
3411 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3413 hr = IMFActivate_DetachObject(activate);
3414 ok(hr == E_NOTIMPL, "Unexpected hr %#lx.\n", hr);
3416 IMFActivate_Release(activate);
3418 IMFMediaType_Release(media_type);
3419 IMFPresentationClock_Release(clock);
3421 hr = MFShutdown();
3422 ok(hr == S_OK, "Failed to shut down, hr %#lx.\n", hr);
3425 static void test_sample_grabber_is_mediatype_supported(void)
3427 IMFMediaType *media_type, *media_type2, *media_type3;
3428 IMFMediaTypeHandler *handler;
3429 IMFActivate *activate;
3430 IMFStreamSink *stream;
3431 IMFMediaSink *sink;
3432 ULONG refcount;
3433 HRESULT hr;
3434 GUID guid;
3436 /* IsMediaTypeSupported checks are done against the creation type, and check format data */
3437 hr = MFCreateMediaType(&media_type);
3438 ok(hr == S_OK, "Failed to create media type, hr %#lx.\n", hr);
3440 hr = IMFMediaType_SetGUID(media_type, &MF_MT_MAJOR_TYPE, &MFMediaType_Audio);
3441 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
3442 hr = IMFMediaType_SetGUID(media_type, &MF_MT_SUBTYPE, &MFAudioFormat_PCM);
3443 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
3444 hr = IMFMediaType_SetUINT32(media_type, &MF_MT_AUDIO_SAMPLES_PER_SECOND, 44100);
3445 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
3447 hr = MFCreateSampleGrabberSinkActivate(media_type, &grabber_callback, &activate);
3448 ok(hr == S_OK, "Failed to create grabber activate, hr %#lx.\n", hr);
3450 hr = IMFActivate_ActivateObject(activate, &IID_IMFMediaSink, (void **)&sink);
3451 ok(hr == S_OK, "Failed to activate object, hr %#lx.\n", hr);
3453 hr = IMFMediaSink_GetStreamSinkByIndex(sink, 0, &stream);
3454 ok(hr == S_OK, "Failed to get sink stream, hr %#lx.\n", hr);
3455 hr = IMFStreamSink_GetMediaTypeHandler(stream, &handler);
3456 ok(hr == S_OK, "Failed to get type handler, hr %#lx.\n", hr);
3457 IMFStreamSink_Release(stream);
3459 IMFMediaSink_Release(sink);
3461 /* On Win8+ this initialization happens automatically. */
3462 hr = IMFMediaTypeHandler_SetCurrentMediaType(handler, media_type);
3463 ok(hr == S_OK, "Failed to set media type, hr %#lx.\n", hr);
3465 hr = MFCreateMediaType(&media_type2);
3466 ok(hr == S_OK, "Failed to create media type, hr %#lx.\n", hr);
3468 hr = IMFMediaType_SetGUID(media_type2, &MF_MT_MAJOR_TYPE, &MFMediaType_Audio);
3469 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
3470 hr = IMFMediaType_SetGUID(media_type2, &MF_MT_SUBTYPE, &MFAudioFormat_PCM);
3471 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
3472 hr = IMFMediaType_SetUINT32(media_type2, &MF_MT_AUDIO_SAMPLES_PER_SECOND, 48000);
3473 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
3475 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, media_type2, NULL);
3476 ok(hr == MF_E_INVALIDMEDIATYPE, "Unexpected hr %#lx.\n", hr);
3478 hr = IMFMediaTypeHandler_SetCurrentMediaType(handler, media_type2);
3479 ok(hr == MF_E_INVALIDMEDIATYPE, "Failed to set media type, hr %#lx.\n", hr);
3481 /* Make it match grabber type sample rate. */
3482 hr = IMFMediaType_SetUINT32(media_type2, &MF_MT_AUDIO_SAMPLES_PER_SECOND, 44100);
3483 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
3485 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, media_type2, NULL);
3486 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3488 hr = IMFMediaTypeHandler_SetCurrentMediaType(handler, media_type2);
3489 ok(hr == S_OK, "Failed to set media type, hr %#lx.\n", hr);
3490 hr = IMFMediaTypeHandler_GetCurrentMediaType(handler, &media_type3);
3491 ok(hr == S_OK, "Failed to set media type, hr %#lx.\n", hr);
3492 ok(media_type3 == media_type2, "Unexpected media type instance.\n");
3493 IMFMediaType_Release(media_type3);
3495 /* Change original type. */
3496 hr = IMFMediaType_SetUINT32(media_type, &MF_MT_AUDIO_SAMPLES_PER_SECOND, 48000);
3497 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
3499 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, media_type2, NULL);
3500 ok(hr == MF_E_INVALIDMEDIATYPE, "Unexpected hr %#lx.\n", hr);
3502 hr = IMFMediaType_SetUINT32(media_type2, &MF_MT_AUDIO_SAMPLES_PER_SECOND, 48000);
3503 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
3505 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, media_type2, NULL);
3506 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3508 hr = IMFMediaTypeHandler_GetMajorType(handler, &guid);
3509 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3510 ok(IsEqualGUID(&guid, &MFMediaType_Audio), "Unexpected major type.\n");
3512 hr = IMFMediaType_SetGUID(media_type, &MF_MT_MAJOR_TYPE, &MFMediaType_Video);
3513 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3515 hr = IMFMediaTypeHandler_GetMajorType(handler, &guid);
3516 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3517 ok(IsEqualGUID(&guid, &MFMediaType_Audio), "Unexpected major type.\n");
3519 IMFMediaType_Release(media_type2);
3520 IMFMediaType_Release(media_type);
3522 IMFMediaTypeHandler_Release(handler);
3524 refcount = IMFActivate_Release(activate);
3525 ok(!refcount, "Unexpected refcount %lu.\n", refcount);
3528 static BOOL is_supported_video_type(const GUID *guid)
3530 return IsEqualGUID(guid, &MFVideoFormat_L8)
3531 || IsEqualGUID(guid, &MFVideoFormat_L16)
3532 || IsEqualGUID(guid, &MFVideoFormat_D16)
3533 || IsEqualGUID(guid, &MFVideoFormat_IYUV)
3534 || IsEqualGUID(guid, &MFVideoFormat_YV12)
3535 || IsEqualGUID(guid, &MFVideoFormat_NV12)
3536 || IsEqualGUID(guid, &MFVideoFormat_NV21)
3537 || IsEqualGUID(guid, &MFVideoFormat_420O)
3538 || IsEqualGUID(guid, &MFVideoFormat_P010)
3539 || IsEqualGUID(guid, &MFVideoFormat_P016)
3540 || IsEqualGUID(guid, &MFVideoFormat_UYVY)
3541 || IsEqualGUID(guid, &MFVideoFormat_YUY2)
3542 || IsEqualGUID(guid, &MFVideoFormat_P208)
3543 || IsEqualGUID(guid, &MFVideoFormat_NV11)
3544 || IsEqualGUID(guid, &MFVideoFormat_AYUV)
3545 || IsEqualGUID(guid, &MFVideoFormat_ARGB32)
3546 || IsEqualGUID(guid, &MFVideoFormat_RGB32)
3547 || IsEqualGUID(guid, &MFVideoFormat_A2R10G10B10)
3548 || IsEqualGUID(guid, &MFVideoFormat_A16B16G16R16F)
3549 || IsEqualGUID(guid, &MFVideoFormat_RGB24)
3550 || IsEqualGUID(guid, &MFVideoFormat_I420)
3551 || IsEqualGUID(guid, &MFVideoFormat_YVYU)
3552 || IsEqualGUID(guid, &MFVideoFormat_RGB555)
3553 || IsEqualGUID(guid, &MFVideoFormat_RGB565)
3554 || IsEqualGUID(guid, &MFVideoFormat_RGB8)
3555 || IsEqualGUID(guid, &MFVideoFormat_Y216)
3556 || IsEqualGUID(guid, &MFVideoFormat_v410)
3557 || IsEqualGUID(guid, &MFVideoFormat_Y41P)
3558 || IsEqualGUID(guid, &MFVideoFormat_Y41T)
3559 || IsEqualGUID(guid, &MFVideoFormat_Y42T)
3560 || IsEqualGUID(guid, &MFVideoFormat_ABGR32);
3563 static void test_video_processor(void)
3565 const GUID transform_inputs[22] =
3567 MFVideoFormat_IYUV,
3568 MFVideoFormat_YV12,
3569 MFVideoFormat_NV12,
3570 MFVideoFormat_YUY2,
3571 MFVideoFormat_ARGB32,
3572 MFVideoFormat_RGB32,
3573 MFVideoFormat_NV11,
3574 MFVideoFormat_AYUV,
3575 MFVideoFormat_UYVY,
3576 MEDIASUBTYPE_P208,
3577 MFVideoFormat_RGB24,
3578 MFVideoFormat_RGB555,
3579 MFVideoFormat_RGB565,
3580 MFVideoFormat_RGB8,
3581 MFVideoFormat_I420,
3582 MFVideoFormat_Y216,
3583 MFVideoFormat_v410,
3584 MFVideoFormat_Y41P,
3585 MFVideoFormat_Y41T,
3586 MFVideoFormat_Y42T,
3587 MFVideoFormat_YVYU,
3588 MFVideoFormat_420O,
3590 const GUID transform_outputs[21] =
3592 MFVideoFormat_IYUV,
3593 MFVideoFormat_YV12,
3594 MFVideoFormat_NV12,
3595 MFVideoFormat_YUY2,
3596 MFVideoFormat_ARGB32,
3597 MFVideoFormat_RGB32,
3598 MFVideoFormat_NV11,
3599 MFVideoFormat_AYUV,
3600 MFVideoFormat_UYVY,
3601 MEDIASUBTYPE_P208,
3602 MFVideoFormat_RGB24,
3603 MFVideoFormat_RGB555,
3604 MFVideoFormat_RGB565,
3605 MFVideoFormat_RGB8,
3606 MFVideoFormat_I420,
3607 MFVideoFormat_Y216,
3608 MFVideoFormat_v410,
3609 MFVideoFormat_Y41P,
3610 MFVideoFormat_Y41T,
3611 MFVideoFormat_Y42T,
3612 MFVideoFormat_YVYU,
3614 MFT_REGISTER_TYPE_INFO output_type = {MFMediaType_Video, MFVideoFormat_NV12};
3615 MFT_REGISTER_TYPE_INFO input_type = {MFMediaType_Video, MFVideoFormat_I420};
3616 DWORD input_count, output_count, input_id, output_id, flags;
3617 DWORD input_min, input_max, output_min, output_max, i;
3618 IMFAttributes *attributes, *attributes2;
3619 IMFMediaType *media_type, *media_type2;
3620 MFT_OUTPUT_DATA_BUFFER output_buffer;
3621 MFT_OUTPUT_STREAM_INFO output_info;
3622 MFT_INPUT_STREAM_INFO input_info;
3623 IMFSample *sample, *sample2;
3624 IMFTransform *transform;
3625 IMFMediaBuffer *buffer;
3626 IMFMediaEvent *event;
3627 unsigned int value;
3628 GUID class_id;
3629 UINT32 count;
3630 HRESULT hr;
3631 GUID guid;
3633 hr = CoInitialize(NULL);
3634 ok(hr == S_OK, "Failed to initialize, hr %#lx.\n", hr);
3636 if (!create_transform(MFT_CATEGORY_VIDEO_PROCESSOR, &input_type, &output_type, L"Microsoft Video Processor MFT", &MFMediaType_Video,
3637 transform_inputs, ARRAY_SIZE(transform_inputs), transform_outputs, ARRAY_SIZE(transform_outputs),
3638 &transform, &CLSID_VideoProcessorMFT, &class_id))
3639 goto failed;
3640 has_video_processor = TRUE;
3642 todo_wine
3643 check_interface(transform, &IID_IMFVideoProcessorControl, TRUE);
3644 todo_wine
3645 check_interface(transform, &IID_IMFRealTimeClientEx, TRUE);
3646 check_interface(transform, &IID_IMFMediaEventGenerator, FALSE);
3647 check_interface(transform, &IID_IMFShutdown, FALSE);
3649 /* Transform global attributes. */
3650 hr = IMFTransform_GetAttributes(transform, &attributes);
3651 ok(hr == S_OK, "Failed to get attributes, hr %#lx.\n", hr);
3653 hr = IMFAttributes_GetCount(attributes, &count);
3654 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3655 todo_wine
3656 ok(!!count, "Unexpected attribute count %u.\n", count);
3658 value = 0;
3659 hr = IMFAttributes_GetUINT32(attributes, &MF_SA_D3D11_AWARE, &value);
3660 todo_wine {
3661 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3662 ok(value == 1, "Unexpected attribute value %u.\n", value);
3664 hr = IMFTransform_GetAttributes(transform, &attributes2);
3665 ok(hr == S_OK, "Failed to get attributes, hr %#lx.\n", hr);
3666 ok(attributes == attributes2, "Unexpected instance.\n");
3667 IMFAttributes_Release(attributes);
3668 IMFAttributes_Release(attributes2);
3670 hr = IMFTransform_GetStreamLimits(transform, &input_min, &input_max, &output_min, &output_max);
3671 ok(hr == S_OK, "Failed to get stream limits, hr %#lx.\n", hr);
3672 ok(input_min == input_max && input_min == 1 && output_min == output_max && output_min == 1,
3673 "Unexpected stream limits.\n");
3675 hr = IMFTransform_GetStreamCount(transform, &input_count, &output_count);
3676 ok(hr == S_OK, "Failed to get stream count, hr %#lx.\n", hr);
3677 ok(input_count == 1 && output_count == 1, "Unexpected stream count %lu, %lu.\n", input_count, output_count);
3679 hr = IMFTransform_GetStreamIDs(transform, 1, &input_id, 1, &output_id);
3680 ok(hr == E_NOTIMPL, "Unexpected hr %#lx.\n", hr);
3682 input_id = 100;
3683 hr = IMFTransform_AddInputStreams(transform, 1, &input_id);
3684 ok(hr == E_NOTIMPL, "Unexpected hr %#lx.\n", hr);
3686 hr = IMFTransform_DeleteInputStream(transform, 0);
3687 ok(hr == E_NOTIMPL, "Unexpected hr %#lx.\n", hr);
3689 hr = IMFTransform_GetInputStatus(transform, 0, &flags);
3690 todo_wine
3691 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "Unexpected hr %#lx.\n", hr);
3693 hr = IMFTransform_GetInputStreamAttributes(transform, 0, &attributes);
3694 ok(hr == E_NOTIMPL, "Unexpected hr %#lx.\n", hr);
3696 hr = IMFTransform_GetOutputStatus(transform, &flags);
3697 todo_wine
3698 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "Unexpected hr %#lx.\n", hr);
3700 hr = IMFTransform_GetOutputStreamAttributes(transform, 0, &attributes);
3701 ok(hr == S_OK, "Failed to get output attributes, hr %#lx.\n", hr);
3702 hr = IMFTransform_GetOutputStreamAttributes(transform, 0, &attributes2);
3703 ok(hr == S_OK, "Failed to get output attributes, hr %#lx.\n", hr);
3704 ok(attributes == attributes2, "Unexpected instance.\n");
3705 IMFAttributes_Release(attributes);
3706 IMFAttributes_Release(attributes2);
3708 hr = IMFTransform_GetOutputAvailableType(transform, 0, 0, &media_type);
3709 todo_wine
3710 ok(hr == MF_E_NO_MORE_TYPES, "Unexpected hr %#lx.\n", hr);
3712 hr = IMFTransform_GetInputCurrentType(transform, 0, &media_type);
3713 todo_wine
3714 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "Unexpected hr %#lx.\n", hr);
3716 hr = IMFTransform_GetInputCurrentType(transform, 1, &media_type);
3717 todo_wine
3718 ok(hr == MF_E_INVALIDSTREAMNUMBER, "Unexpected hr %#lx.\n", hr);
3720 hr = IMFTransform_GetOutputCurrentType(transform, 0, &media_type);
3721 todo_wine
3722 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "Unexpected hr %#lx.\n", hr);
3724 hr = IMFTransform_GetOutputCurrentType(transform, 1, &media_type);
3725 todo_wine
3726 ok(hr == MF_E_INVALIDSTREAMNUMBER, "Unexpected hr %#lx.\n", hr);
3728 hr = IMFTransform_GetInputStreamInfo(transform, 1, &input_info);
3729 todo_wine
3730 ok(hr == MF_E_INVALIDSTREAMNUMBER, "Unexpected hr %#lx.\n", hr);
3732 memset(&input_info, 0xcc, sizeof(input_info));
3733 hr = IMFTransform_GetInputStreamInfo(transform, 0, &input_info);
3734 todo_wine {
3735 ok(hr == S_OK, "Failed to get stream info, hr %#lx.\n", hr);
3736 ok(input_info.dwFlags == 0, "Unexpected flag %#lx.\n", input_info.dwFlags);
3737 ok(input_info.cbSize == 0, "Unexpected size %lu.\n", input_info.cbSize);
3738 ok(input_info.cbMaxLookahead == 0, "Unexpected lookahead length %lu.\n", input_info.cbMaxLookahead);
3739 ok(input_info.cbAlignment == 0, "Unexpected alignment %lu.\n", input_info.cbAlignment);
3741 hr = MFCreateMediaEvent(MEUnknown, &GUID_NULL, S_OK, NULL, &event);
3742 ok(hr == S_OK, "Failed to create event object, hr %#lx.\n", hr);
3743 hr = IMFTransform_ProcessEvent(transform, 0, event);
3744 ok(hr == E_NOTIMPL, "Unexpected hr %#lx.\n", hr);
3745 hr = IMFTransform_ProcessEvent(transform, 1, event);
3746 ok(hr == E_NOTIMPL, "Unexpected hr %#lx.\n", hr);
3747 IMFMediaEvent_Release(event);
3749 /* Configure stream types. */
3750 for (i = 0;;++i)
3752 if (FAILED(hr = IMFTransform_GetInputAvailableType(transform, 0, i, &media_type)))
3754 todo_wine
3755 ok(hr == MF_E_NO_MORE_TYPES, "Unexpected hr %#lx.\n", hr);
3756 break;
3759 hr = IMFTransform_GetInputAvailableType(transform, 0, i, &media_type2);
3760 ok(hr == S_OK, "Failed to get available type, hr %#lx.\n", hr);
3761 ok(media_type != media_type2, "Unexpected instance.\n");
3762 IMFMediaType_Release(media_type2);
3764 hr = IMFMediaType_GetMajorType(media_type, &guid);
3765 ok(hr == S_OK, "Failed to get major type, hr %#lx.\n", hr);
3766 ok(IsEqualGUID(&guid, &MFMediaType_Video), "Unexpected major type.\n");
3768 hr = IMFMediaType_GetCount(media_type, &count);
3769 ok(hr == S_OK, "Failed to get attributes count, hr %#lx.\n", hr);
3770 ok(count == 2, "Unexpected count %u.\n", count);
3772 hr = IMFMediaType_GetGUID(media_type, &MF_MT_SUBTYPE, &guid);
3773 ok(hr == S_OK, "Failed to get subtype, hr %#lx.\n", hr);
3774 ok(is_supported_video_type(&guid), "Unexpected media type %s.\n", wine_dbgstr_guid(&guid));
3776 hr = IMFTransform_SetInputType(transform, 0, media_type, MFT_SET_TYPE_TEST_ONLY);
3777 ok(FAILED(hr), "Unexpected hr %#lx.\n", hr);
3779 hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
3780 ok(FAILED(hr), "Unexpected hr %#lx.\n", hr);
3782 hr = IMFTransform_GetOutputCurrentType(transform, 0, &media_type2);
3783 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "Unexpected hr %#lx.\n", hr);
3785 /* FIXME: figure out if those require additional attributes or simply advertised but not supported */
3786 if (IsEqualGUID(&guid, &MFVideoFormat_L8) || IsEqualGUID(&guid, &MFVideoFormat_L16)
3787 || IsEqualGUID(&guid, &MFVideoFormat_D16) || IsEqualGUID(&guid, &MFVideoFormat_420O)
3788 || IsEqualGUID(&guid, &MFVideoFormat_A16B16G16R16F))
3790 IMFMediaType_Release(media_type);
3791 continue;
3794 hr = IMFMediaType_SetUINT64(media_type, &MF_MT_FRAME_SIZE, ((UINT64)16 << 32) | 16);
3795 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
3797 hr = IMFTransform_SetInputType(transform, 0, media_type, MFT_SET_TYPE_TEST_ONLY);
3798 ok(hr == S_OK, "Failed to test input type %s, hr %#lx.\n", wine_dbgstr_guid(&guid), hr);
3800 hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
3801 ok(hr == S_OK, "Failed to test input type, hr %#lx.\n", hr);
3803 hr = IMFTransform_GetInputCurrentType(transform, 0, &media_type2);
3804 ok(hr == S_OK, "Failed to get current type, hr %#lx.\n", hr);
3805 ok(media_type != media_type2, "Unexpected instance.\n");
3806 IMFMediaType_Release(media_type2);
3808 hr = IMFTransform_GetInputStatus(transform, 0, &flags);
3809 ok(hr == S_OK, "Failed to get input status, hr %#lx.\n", hr);
3810 ok(flags == MFT_INPUT_STATUS_ACCEPT_DATA, "Unexpected input status %#lx.\n", flags);
3812 hr = IMFTransform_GetInputStreamInfo(transform, 0, &input_info);
3813 ok(hr == S_OK, "Failed to get stream info, hr %#lx.\n", hr);
3814 ok(input_info.dwFlags == 0, "Unexpected flags %#lx.\n", input_info.dwFlags);
3815 ok(input_info.cbMaxLookahead == 0, "Unexpected lookahead length %lu.\n", input_info.cbMaxLookahead);
3816 ok(input_info.cbAlignment == 0, "Unexpected alignment %lu.\n", input_info.cbAlignment);
3818 IMFMediaType_Release(media_type);
3821 /* IYUV -> RGB32 */
3822 hr = MFCreateMediaType(&media_type);
3823 ok(hr == S_OK, "Failed to create media type, hr %#lx.\n", hr);
3825 hr = IMFMediaType_SetGUID(media_type, &MF_MT_MAJOR_TYPE, &MFMediaType_Video);
3826 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
3828 hr = IMFMediaType_SetGUID(media_type, &MF_MT_SUBTYPE, &MFVideoFormat_IYUV);
3829 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
3831 hr = IMFMediaType_SetUINT64(media_type, &MF_MT_FRAME_SIZE, ((UINT64)16 << 32) | 16);
3832 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
3834 hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
3835 todo_wine
3836 ok(hr == S_OK, "Failed to set input type, hr %#lx.\n", hr);
3838 hr = IMFMediaType_SetGUID(media_type, &MF_MT_SUBTYPE, &MFVideoFormat_RGB32);
3839 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
3841 hr = IMFTransform_SetOutputType(transform, 0, media_type, 0);
3842 todo_wine
3843 ok(hr == S_OK, "Failed to set output type, hr %#lx.\n", hr);
3845 memset(&output_info, 0, sizeof(output_info));
3846 hr = IMFTransform_GetOutputStreamInfo(transform, 0, &output_info);
3847 todo_wine
3848 ok(hr == S_OK, "Failed to get stream info, hr %#lx.\n", hr);
3849 ok(output_info.dwFlags == 0, "Unexpected flags %#lx.\n", output_info.dwFlags);
3850 todo_wine
3851 ok(output_info.cbSize > 0, "Unexpected size %lu.\n", output_info.cbSize);
3852 ok(output_info.cbAlignment == 0, "Unexpected alignment %lu.\n", output_info.cbAlignment);
3854 hr = MFCreateSample(&sample);
3855 ok(hr == S_OK, "Failed to create a sample, hr %#lx.\n", hr);
3857 hr = MFCreateSample(&sample2);
3858 ok(hr == S_OK, "Failed to create a sample, hr %#lx.\n", hr);
3860 memset(&output_buffer, 0, sizeof(output_buffer));
3861 output_buffer.pSample = sample;
3862 flags = 0;
3863 hr = IMFTransform_ProcessOutput(transform, 0, 1, &output_buffer, &flags);
3864 todo_wine
3865 ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "Unexpected hr %#lx.\n", hr);
3866 ok(output_buffer.dwStatus == 0, "Unexpected buffer status, %#lx.\n", output_buffer.dwStatus);
3867 ok(flags == 0, "Unexpected status %#lx.\n", flags);
3869 hr = IMFTransform_ProcessInput(transform, 0, sample2, 0);
3870 todo_wine
3871 ok(hr == S_OK, "Failed to push a sample, hr %#lx.\n", hr);
3873 hr = IMFTransform_ProcessInput(transform, 0, sample2, 0);
3874 todo_wine
3875 ok(hr == MF_E_NOTACCEPTING, "Unexpected hr %#lx.\n", hr);
3877 memset(&output_buffer, 0, sizeof(output_buffer));
3878 output_buffer.pSample = sample;
3879 flags = 0;
3880 hr = IMFTransform_ProcessOutput(transform, 0, 1, &output_buffer, &flags);
3881 todo_wine
3882 ok(hr == MF_E_NO_SAMPLE_TIMESTAMP, "Unexpected hr %#lx.\n", hr);
3883 ok(output_buffer.dwStatus == 0, "Unexpected buffer status, %#lx.\n", output_buffer.dwStatus);
3884 ok(flags == 0, "Unexpected status %#lx.\n", flags);
3886 hr = IMFSample_SetSampleTime(sample2, 0);
3887 ok(hr == S_OK, "Failed to set sample time, hr %#lx.\n", hr);
3888 memset(&output_buffer, 0, sizeof(output_buffer));
3889 output_buffer.pSample = sample;
3890 flags = 0;
3891 hr = IMFTransform_ProcessOutput(transform, 0, 1, &output_buffer, &flags);
3892 todo_wine
3893 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
3894 ok(output_buffer.dwStatus == 0, "Unexpected buffer status, %#lx.\n", output_buffer.dwStatus);
3895 ok(flags == 0, "Unexpected status %#lx.\n", flags);
3897 hr = MFCreateMemoryBuffer(1024 * 1024, &buffer);
3898 ok(hr == S_OK, "Failed to create a buffer, hr %#lx.\n", hr);
3900 hr = IMFSample_AddBuffer(sample2, buffer);
3901 ok(hr == S_OK, "Failed to add a buffer, hr %#lx.\n", hr);
3903 hr = IMFSample_AddBuffer(sample, buffer);
3904 ok(hr == S_OK, "Failed to add a buffer, hr %#lx.\n", hr);
3906 memset(&output_buffer, 0, sizeof(output_buffer));
3907 output_buffer.pSample = sample;
3908 flags = 0;
3909 hr = IMFTransform_ProcessOutput(transform, 0, 1, &output_buffer, &flags);
3910 todo_wine
3911 ok(hr == S_OK || broken(FAILED(hr)) /* Win8 */, "Failed to get output buffer, hr %#lx.\n", hr);
3912 ok(output_buffer.dwStatus == 0, "Unexpected buffer status, %#lx.\n", output_buffer.dwStatus);
3913 ok(flags == 0, "Unexpected status %#lx.\n", flags);
3915 if (SUCCEEDED(hr))
3917 memset(&output_buffer, 0, sizeof(output_buffer));
3918 output_buffer.pSample = sample;
3919 flags = 0;
3920 hr = IMFTransform_ProcessOutput(transform, 0, 1, &output_buffer, &flags);
3921 ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "Unexpected hr %#lx.\n", hr);
3922 ok(output_buffer.dwStatus == 0, "Unexpected buffer status, %#lx.\n", output_buffer.dwStatus);
3923 ok(flags == 0, "Unexpected status %#lx.\n", flags);
3926 IMFSample_Release(sample2);
3927 IMFSample_Release(sample);
3928 IMFMediaBuffer_Release(buffer);
3930 IMFMediaType_Release(media_type);
3932 IMFTransform_Release(transform);
3934 failed:
3935 CoUninitialize();
3938 static void test_quality_manager(void)
3940 IMFPresentationClock *clock;
3941 IMFQualityManager *manager;
3942 IMFTopology *topology;
3943 HRESULT hr;
3945 hr = MFStartup(MF_VERSION, MFSTARTUP_FULL);
3946 ok(hr == S_OK, "Startup failure, hr %#lx.\n", hr);
3948 hr = MFCreatePresentationClock(&clock);
3949 ok(hr == S_OK, "Failed to create presentation clock, hr %#lx.\n", hr);
3951 hr = MFCreateStandardQualityManager(&manager);
3952 ok(hr == S_OK, "Failed to create quality manager, hr %#lx.\n", hr);
3954 check_interface(manager, &IID_IMFQualityManager, TRUE);
3955 check_interface(manager, &IID_IMFClockStateSink, TRUE);
3957 hr = IMFQualityManager_NotifyPresentationClock(manager, NULL);
3958 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
3960 hr = IMFQualityManager_NotifyTopology(manager, NULL);
3961 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3963 /* Set clock, then shutdown. */
3964 EXPECT_REF(clock, 1);
3965 EXPECT_REF(manager, 1);
3966 hr = IMFQualityManager_NotifyPresentationClock(manager, clock);
3967 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3968 EXPECT_REF(clock, 2);
3969 EXPECT_REF(manager, 2);
3971 hr = IMFQualityManager_Shutdown(manager);
3972 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3973 EXPECT_REF(clock, 1);
3975 hr = IMFQualityManager_NotifyPresentationClock(manager, clock);
3976 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
3978 hr = IMFQualityManager_NotifyTopology(manager, NULL);
3979 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
3981 hr = IMFQualityManager_NotifyPresentationClock(manager, NULL);
3982 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
3984 hr = IMFQualityManager_Shutdown(manager);
3985 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3987 IMFQualityManager_Release(manager);
3989 /* Set clock, then release without shutting down. */
3990 hr = MFCreateStandardQualityManager(&manager);
3991 ok(hr == S_OK, "Failed to create quality manager, hr %#lx.\n", hr);
3993 EXPECT_REF(clock, 1);
3994 hr = IMFQualityManager_NotifyPresentationClock(manager, clock);
3995 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3996 EXPECT_REF(clock, 2);
3998 IMFQualityManager_Release(manager);
3999 EXPECT_REF(clock, 2);
4001 IMFPresentationClock_Release(clock);
4003 /* Set topology. */
4004 hr = MFCreateStandardQualityManager(&manager);
4005 ok(hr == S_OK, "Failed to create quality manager, hr %#lx.\n", hr);
4007 hr = MFCreateTopology(&topology);
4008 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4010 EXPECT_REF(topology, 1);
4011 hr = IMFQualityManager_NotifyTopology(manager, topology);
4012 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4013 EXPECT_REF(topology, 2);
4015 hr = IMFQualityManager_NotifyTopology(manager, NULL);
4016 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4017 EXPECT_REF(topology, 1);
4019 hr = IMFQualityManager_NotifyTopology(manager, topology);
4020 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4022 EXPECT_REF(topology, 2);
4023 hr = IMFQualityManager_Shutdown(manager);
4024 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4025 EXPECT_REF(topology, 1);
4027 hr = IMFQualityManager_NotifyTopology(manager, topology);
4028 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
4030 IMFQualityManager_Release(manager);
4032 hr = MFCreateStandardQualityManager(&manager);
4033 ok(hr == S_OK, "Failed to create quality manager, hr %#lx.\n", hr);
4035 EXPECT_REF(topology, 1);
4036 hr = IMFQualityManager_NotifyTopology(manager, topology);
4037 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4038 EXPECT_REF(topology, 2);
4040 IMFQualityManager_Release(manager);
4041 EXPECT_REF(topology, 1);
4043 IMFTopology_Release(topology);
4045 hr = MFShutdown();
4046 ok(hr == S_OK, "Shutdown failure, hr %#lx.\n", hr);
4049 static void check_sar_rate_support(IMFMediaSink *sink)
4051 IMFRateSupport *rate_support;
4052 IMFMediaTypeHandler *handler;
4053 IMFStreamSink *stream_sink;
4054 IMFMediaType *media_type;
4055 HRESULT hr;
4056 float rate;
4058 hr = IMFMediaSink_QueryInterface(sink, &IID_IMFRateSupport, (void **)&rate_support);
4059 todo_wine
4060 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4061 if (FAILED(hr)) return;
4063 hr = IMFMediaSink_GetStreamSinkByIndex(sink, 0, &stream_sink);
4064 if (hr == MF_E_SHUTDOWN)
4066 hr = IMFRateSupport_GetSlowestRate(rate_support, MFRATE_FORWARD, FALSE, NULL);
4067 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
4069 hr = IMFRateSupport_GetSlowestRate(rate_support, MFRATE_FORWARD, FALSE, &rate);
4070 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
4072 hr = IMFRateSupport_GetFastestRate(rate_support, MFRATE_FORWARD, FALSE, &rate);
4073 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
4075 IMFRateSupport_Release(rate_support);
4076 return;
4078 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4080 hr = IMFStreamSink_GetMediaTypeHandler(stream_sink, &handler);
4081 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4083 IMFStreamSink_Release(stream_sink);
4085 hr = IMFRateSupport_GetSlowestRate(rate_support, MFRATE_FORWARD, FALSE, NULL);
4086 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
4088 hr = IMFRateSupport_GetFastestRate(rate_support, MFRATE_FORWARD, FALSE, NULL);
4089 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
4091 hr = IMFMediaTypeHandler_GetCurrentMediaType(handler, &media_type);
4092 if (SUCCEEDED(hr))
4094 hr = IMFRateSupport_GetSlowestRate(rate_support, MFRATE_FORWARD, FALSE, &rate);
4095 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4097 hr = IMFRateSupport_GetSlowestRate(rate_support, MFRATE_FORWARD, TRUE, &rate);
4098 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4100 hr = IMFRateSupport_GetSlowestRate(rate_support, MFRATE_REVERSE, FALSE, &rate);
4101 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4103 hr = IMFRateSupport_GetSlowestRate(rate_support, MFRATE_REVERSE, TRUE, &rate);
4104 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4106 hr = IMFRateSupport_GetFastestRate(rate_support, MFRATE_FORWARD, FALSE, &rate);
4107 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4109 hr = IMFRateSupport_GetFastestRate(rate_support, MFRATE_FORWARD, TRUE, &rate);
4110 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4112 hr = IMFRateSupport_GetFastestRate(rate_support, MFRATE_REVERSE, FALSE, &rate);
4113 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4115 hr = IMFRateSupport_GetFastestRate(rate_support, MFRATE_REVERSE, TRUE, &rate);
4116 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4118 IMFMediaType_Release(media_type);
4120 else
4122 hr = IMFRateSupport_GetSlowestRate(rate_support, MFRATE_FORWARD, FALSE, &rate);
4123 ok(hr == MF_E_NOT_INITIALIZED, "Unexpected hr %#lx.\n", hr);
4125 hr = IMFRateSupport_GetSlowestRate(rate_support, MFRATE_FORWARD, TRUE, &rate);
4126 ok(hr == MF_E_NOT_INITIALIZED, "Unexpected hr %#lx.\n", hr);
4128 hr = IMFRateSupport_GetSlowestRate(rate_support, MFRATE_REVERSE, FALSE, &rate);
4129 ok(hr == MF_E_NOT_INITIALIZED, "Unexpected hr %#lx.\n", hr);
4131 hr = IMFRateSupport_GetSlowestRate(rate_support, MFRATE_REVERSE, TRUE, &rate);
4132 ok(hr == MF_E_NOT_INITIALIZED, "Unexpected hr %#lx.\n", hr);
4134 hr = IMFRateSupport_GetFastestRate(rate_support, MFRATE_FORWARD, FALSE, &rate);
4135 ok(hr == MF_E_NOT_INITIALIZED, "Unexpected hr %#lx.\n", hr);
4137 hr = IMFRateSupport_GetFastestRate(rate_support, MFRATE_FORWARD, TRUE, &rate);
4138 ok(hr == MF_E_NOT_INITIALIZED, "Unexpected hr %#lx.\n", hr);
4140 hr = IMFRateSupport_GetFastestRate(rate_support, MFRATE_REVERSE, FALSE, &rate);
4141 ok(hr == MF_E_NOT_INITIALIZED, "Unexpected hr %#lx.\n", hr);
4143 hr = IMFRateSupport_GetFastestRate(rate_support, MFRATE_REVERSE, TRUE, &rate);
4144 ok(hr == MF_E_NOT_INITIALIZED, "Unexpected hr %#lx.\n", hr);
4147 IMFMediaTypeHandler_Release(handler);
4148 IMFRateSupport_Release(rate_support);
4151 static void test_sar(void)
4153 IMFPresentationClock *present_clock, *present_clock2;
4154 IMFMediaType *mediatype, *mediatype2, *mediatype3;
4155 IMFClockStateSink *state_sink, *state_sink2;
4156 IMFMediaTypeHandler *handler, *handler2;
4157 IMFPresentationTimeSource *time_source;
4158 IMFSimpleAudioVolume *simple_volume;
4159 IMFAudioStreamVolume *stream_volume;
4160 IMFMediaSink *sink, *sink2;
4161 IMFStreamSink *stream_sink;
4162 IMFAttributes *attributes;
4163 DWORD i, id, flags, count;
4164 IMFActivate *activate;
4165 UINT32 channel_count;
4166 MFCLOCK_STATE state;
4167 IMFClock *clock;
4168 IUnknown *unk;
4169 HRESULT hr;
4170 GUID guid;
4171 BOOL mute;
4172 int found;
4174 hr = CoInitialize(NULL);
4175 ok(hr == S_OK, "Failed to initialize, hr %#lx.\n", hr);
4177 hr = MFCreateAudioRenderer(NULL, &sink);
4178 if (hr == MF_E_NO_AUDIO_PLAYBACK_DEVICE)
4180 skip("No audio playback device available.\n");
4181 CoUninitialize();
4182 return;
4184 ok(hr == S_OK, "Failed to create renderer, hr %#lx.\n", hr);
4186 hr = MFStartup(MF_VERSION, MFSTARTUP_FULL);
4187 ok(hr == S_OK, "Startup failure, hr %#lx.\n", hr);
4189 hr = MFCreatePresentationClock(&present_clock);
4190 ok(hr == S_OK, "Failed to create presentation clock, hr %#lx.\n", hr);
4192 hr = IMFMediaSink_QueryInterface(sink, &IID_IMFPresentationTimeSource, (void **)&time_source);
4193 todo_wine
4194 ok(hr == S_OK, "Failed to get time source interface, hr %#lx.\n", hr);
4196 if (SUCCEEDED(hr))
4198 hr = IMFPresentationTimeSource_QueryInterface(time_source, &IID_IMFClockStateSink, (void **)&state_sink2);
4199 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4200 hr = IMFPresentationTimeSource_QueryInterface(time_source, &IID_IMFClockStateSink, (void **)&state_sink);
4201 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4202 ok(state_sink == state_sink2, "Unexpected clock sink.\n");
4203 IMFClockStateSink_Release(state_sink2);
4204 IMFClockStateSink_Release(state_sink);
4206 hr = IMFPresentationTimeSource_GetUnderlyingClock(time_source, &clock);
4207 ok(hr == MF_E_NO_CLOCK, "Unexpected hr %#lx.\n", hr);
4209 hr = IMFPresentationTimeSource_GetClockCharacteristics(time_source, &flags);
4210 ok(hr == S_OK, "Failed to get flags, hr %#lx.\n", hr);
4211 ok(flags == MFCLOCK_CHARACTERISTICS_FLAG_FREQUENCY_10MHZ, "Unexpected flags %#lx.\n", flags);
4213 hr = IMFPresentationTimeSource_GetState(time_source, 0, &state);
4214 ok(hr == S_OK, "Failed to get clock state, hr %#lx.\n", hr);
4215 ok(state == MFCLOCK_STATE_INVALID, "Unexpected state %d.\n", state);
4217 hr = IMFPresentationTimeSource_QueryInterface(time_source, &IID_IMFClockStateSink, (void **)&state_sink);
4218 ok(hr == S_OK, "Failed to get state sink, hr %#lx.\n", hr);
4220 hr = IMFClockStateSink_OnClockStart(state_sink, 0, 0);
4221 ok(hr == MF_E_NOT_INITIALIZED, "Unexpected hr %#lx.\n", hr);
4223 IMFClockStateSink_Release(state_sink);
4225 IMFPresentationTimeSource_Release(time_source);
4227 hr = IMFMediaSink_AddStreamSink(sink, 123, NULL, &stream_sink);
4228 ok(hr == MF_E_STREAMSINKS_FIXED, "Unexpected hr %#lx.\n", hr);
4230 hr = IMFMediaSink_RemoveStreamSink(sink, 0);
4231 ok(hr == MF_E_STREAMSINKS_FIXED, "Unexpected hr %#lx.\n", hr);
4233 hr = IMFMediaSink_GetStreamSinkCount(sink, NULL);
4234 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
4236 hr = IMFMediaSink_GetStreamSinkCount(sink, &count);
4237 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4238 ok(count == 1, "Unexpected count %lu.\n", count);
4240 hr = IMFMediaSink_GetCharacteristics(sink, &flags);
4241 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4242 ok(flags == (MEDIASINK_FIXED_STREAMS | MEDIASINK_CAN_PREROLL), "Unexpected flags %#lx.\n", flags);
4244 check_interface(sink, &IID_IMFMediaSinkPreroll, TRUE);
4245 check_interface(sink, &IID_IMFMediaEventGenerator, TRUE);
4246 check_interface(sink, &IID_IMFClockStateSink, TRUE);
4247 check_interface(sink, &IID_IMFGetService, TRUE);
4248 todo_wine check_interface(sink, &IID_IMFPresentationTimeSource, TRUE);
4249 todo_wine check_service_interface(sink, &MF_RATE_CONTROL_SERVICE, &IID_IMFRateSupport, TRUE);
4250 check_service_interface(sink, &MF_RATE_CONTROL_SERVICE, &IID_IMFRateControl, FALSE);
4251 check_service_interface(sink, &MR_POLICY_VOLUME_SERVICE, &IID_IMFSimpleAudioVolume, TRUE);
4252 check_service_interface(sink, &MR_STREAM_VOLUME_SERVICE, &IID_IMFAudioStreamVolume, TRUE);
4254 /* Clock */
4255 hr = IMFMediaSink_QueryInterface(sink, &IID_IMFClockStateSink, (void **)&state_sink);
4256 ok(hr == S_OK, "Failed to get interface, hr %#lx.\n", hr);
4258 hr = IMFClockStateSink_OnClockStart(state_sink, 0, 0);
4259 ok(hr == MF_E_NOT_INITIALIZED, "Unexpected hr %#lx.\n", hr);
4261 hr = IMFClockStateSink_OnClockPause(state_sink, 0);
4262 ok(hr == MF_E_INVALID_STATE_TRANSITION, "Unexpected hr %#lx.\n", hr);
4264 hr = IMFClockStateSink_OnClockStop(state_sink, 0);
4265 ok(hr == MF_E_NOT_INITIALIZED, "Unexpected hr %#lx.\n", hr);
4267 hr = IMFClockStateSink_OnClockRestart(state_sink, 0);
4268 ok(hr == MF_E_NOT_INITIALIZED, "Unexpected hr %#lx.\n", hr);
4270 IMFClockStateSink_Release(state_sink);
4272 hr = IMFMediaSink_SetPresentationClock(sink, NULL);
4273 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4275 hr = IMFMediaSink_SetPresentationClock(sink, present_clock);
4276 todo_wine
4277 ok(hr == MF_E_CLOCK_NO_TIME_SOURCE, "Unexpected hr %#lx.\n", hr);
4279 hr = MFCreateSystemTimeSource(&time_source);
4280 ok(hr == S_OK, "Failed to create time source, hr %#lx.\n", hr);
4282 hr = IMFPresentationClock_SetTimeSource(present_clock, time_source);
4283 ok(hr == S_OK, "Failed to set time source, hr %#lx.\n", hr);
4284 IMFPresentationTimeSource_Release(time_source);
4286 hr = IMFMediaSink_SetPresentationClock(sink, present_clock);
4287 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4289 hr = IMFMediaSink_GetPresentationClock(sink, NULL);
4290 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
4292 hr = IMFMediaSink_GetPresentationClock(sink, &present_clock2);
4293 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4294 ok(present_clock == present_clock2, "Unexpected instance.\n");
4295 IMFPresentationClock_Release(present_clock2);
4297 /* Stream */
4298 hr = IMFMediaSink_GetStreamSinkByIndex(sink, 0, &stream_sink);
4299 ok(hr == S_OK, "Failed to get a stream, hr %#lx.\n", hr);
4301 check_interface(stream_sink, &IID_IMFMediaEventGenerator, TRUE);
4302 check_interface(stream_sink, &IID_IMFMediaTypeHandler, TRUE);
4303 todo_wine check_interface(stream_sink, &IID_IMFGetService, TRUE);
4305 hr = IMFStreamSink_GetIdentifier(stream_sink, &id);
4306 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4307 ok(!id, "Unexpected id.\n");
4309 hr = IMFStreamSink_GetMediaSink(stream_sink, &sink2);
4310 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4311 ok(sink == sink2, "Unexpected object.\n");
4312 IMFMediaSink_Release(sink2);
4314 hr = IMFStreamSink_GetMediaTypeHandler(stream_sink, &handler);
4315 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4317 hr = IMFStreamSink_QueryInterface(stream_sink, &IID_IMFMediaTypeHandler, (void **)&handler2);
4318 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4319 ok(handler2 == handler, "Unexpected instance.\n");
4320 IMFMediaTypeHandler_Release(handler2);
4322 hr = IMFMediaTypeHandler_GetMajorType(handler, &guid);
4323 ok(hr == S_OK, "Failed to get major type, hr %#lx.\n", hr);
4324 ok(IsEqualGUID(&guid, &MFMediaType_Audio), "Unexpected type %s.\n", wine_dbgstr_guid(&guid));
4326 count = 0;
4327 hr = IMFMediaTypeHandler_GetMediaTypeCount(handler, &count);
4328 ok(hr == S_OK, "Failed to get type count, hr %#lx.\n", hr);
4329 ok(!!count, "Unexpected type count %lu.\n", count);
4331 /* A number of same major/subtype entries are returned, with different degrees of finer format
4332 details. Some incomplete types are not accepted, check that at least one of them is considered supported. */
4334 for (i = 0, found = -1; i < count; ++i)
4336 hr = IMFMediaTypeHandler_GetMediaTypeByIndex(handler, i, &mediatype);
4337 ok(hr == S_OK, "Failed to get media type, hr %#lx.\n", hr);
4339 if (SUCCEEDED(IMFMediaTypeHandler_IsMediaTypeSupported(handler, mediatype, NULL)))
4340 found = i;
4341 IMFMediaType_Release(mediatype);
4343 if (found != -1) break;
4345 ok(found != -1, "Haven't found a supported type.\n");
4347 hr = IMFMediaTypeHandler_GetCurrentMediaType(handler, &mediatype);
4348 ok(hr == MF_E_NOT_INITIALIZED, "Unexpected hr %#lx.\n", hr);
4350 hr = MFCreateMediaType(&mediatype);
4351 ok(hr == S_OK, "Failed to create media type, hr %#lx.\n", hr);
4353 /* Actual return value is MF_E_ATRIBUTENOTFOUND triggered by missing MF_MT_MAJOR_TYPE */
4354 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, mediatype, NULL);
4355 ok(FAILED(hr), "Unexpected hr %#lx.\n", hr);
4357 hr = IMFMediaType_SetGUID(mediatype, &MF_MT_MAJOR_TYPE, &MFMediaType_Video);
4358 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4359 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, mediatype, NULL);
4360 ok(hr == MF_E_INVALIDMEDIATYPE, "Unexpected hr %#lx.\n", hr);
4362 hr = IMFMediaType_SetGUID(mediatype, &MF_MT_MAJOR_TYPE, &MFMediaType_Audio);
4363 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4364 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, mediatype, NULL);
4365 ok(hr == MF_E_INVALIDMEDIATYPE, "Unexpected hr %#lx.\n", hr);
4367 hr = IMFMediaTypeHandler_SetCurrentMediaType(handler, mediatype);
4368 ok(hr == MF_E_INVALIDMEDIATYPE, "Unexpected hr %#lx.\n", hr);
4370 hr = IMFMediaTypeHandler_GetMediaTypeByIndex(handler, found, &mediatype2);
4371 ok(hr == S_OK, "Failed to get media type, hr %#lx.\n", hr);
4373 hr = IMFMediaTypeHandler_GetMediaTypeByIndex(handler, found, &mediatype3);
4374 ok(hr == S_OK, "Failed to get media type, hr %#lx.\n", hr);
4375 ok(mediatype2 == mediatype3, "Unexpected instance.\n");
4376 IMFMediaType_Release(mediatype3);
4378 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, mediatype2, NULL);
4379 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4381 IMFMediaType_Release(mediatype);
4383 check_sar_rate_support(sink);
4385 hr = IMFMediaTypeHandler_SetCurrentMediaType(handler, mediatype2);
4386 ok(hr == S_OK, "Failed to set current type, hr %#lx.\n", hr);
4388 check_sar_rate_support(sink);
4390 hr = IMFMediaTypeHandler_GetCurrentMediaType(handler, &mediatype);
4391 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4392 ok(mediatype == mediatype2, "Unexpected instance.\n");
4393 IMFMediaType_Release(mediatype);
4395 IMFMediaType_Release(mediatype2);
4397 /* Reset back to uninitialized state. */
4398 hr = IMFMediaTypeHandler_SetCurrentMediaType(handler, NULL);
4399 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
4401 IMFMediaTypeHandler_Release(handler);
4403 /* State change with initialized stream. */
4404 hr = IMFMediaSink_QueryInterface(sink, &IID_IMFClockStateSink, (void **)&state_sink);
4405 ok(hr == S_OK, "Failed to get interface, hr %#lx.\n", hr);
4407 hr = IMFClockStateSink_OnClockStart(state_sink, 0, 0);
4408 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4410 hr = IMFClockStateSink_OnClockStart(state_sink, 0, 0);
4411 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4413 hr = IMFClockStateSink_OnClockPause(state_sink, 0);
4414 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4416 hr = IMFClockStateSink_OnClockStop(state_sink, 0);
4417 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4419 hr = IMFClockStateSink_OnClockStop(state_sink, 0);
4420 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4422 hr = IMFClockStateSink_OnClockPause(state_sink, 0);
4423 ok(hr == MF_E_INVALID_STATE_TRANSITION, "Unexpected hr %#lx.\n", hr);
4425 hr = IMFClockStateSink_OnClockRestart(state_sink, 0);
4426 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4428 hr = IMFClockStateSink_OnClockRestart(state_sink, 0);
4429 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4431 hr = IMFClockStateSink_OnClockStop(state_sink, 0);
4432 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4434 IMFClockStateSink_Release(state_sink);
4436 IMFStreamSink_Release(stream_sink);
4438 /* Volume control */
4439 hr = MFGetService((IUnknown *)sink, &MR_POLICY_VOLUME_SERVICE, &IID_IMFSimpleAudioVolume, (void **)&simple_volume);
4440 ok(hr == S_OK, "Failed to get interface, hr %#lx.\n", hr);
4442 hr = IMFSimpleAudioVolume_GetMute(simple_volume, &mute);
4443 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4445 IMFSimpleAudioVolume_Release(simple_volume);
4447 hr = MFGetService((IUnknown *)sink, &MR_STREAM_VOLUME_SERVICE, &IID_IMFAudioStreamVolume, (void **)&stream_volume);
4448 ok(hr == S_OK, "Failed to get interface, hr %#lx.\n", hr);
4450 hr = IMFAudioStreamVolume_GetChannelCount(stream_volume, &channel_count);
4451 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4453 hr = IMFAudioStreamVolume_GetChannelCount(stream_volume, NULL);
4454 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
4456 IMFAudioStreamVolume_Release(stream_volume);
4458 hr = MFGetService((IUnknown *)sink, &MR_AUDIO_POLICY_SERVICE, &IID_IMFAudioPolicy, (void **)&unk);
4459 ok(hr == S_OK, "Failed to get interface, hr %#lx.\n", hr);
4460 IUnknown_Release(unk);
4462 /* Shutdown */
4463 EXPECT_REF(present_clock, 2);
4464 hr = IMFMediaSink_Shutdown(sink);
4465 ok(hr == S_OK, "Failed to shut down, hr %#lx.\n", hr);
4466 EXPECT_REF(present_clock, 1);
4468 hr = IMFMediaSink_Shutdown(sink);
4469 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
4471 hr = IMFMediaSink_AddStreamSink(sink, 123, NULL, &stream_sink);
4472 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
4474 hr = IMFMediaSink_RemoveStreamSink(sink, 0);
4475 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
4477 hr = IMFMediaSink_GetStreamSinkCount(sink, NULL);
4478 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
4480 hr = IMFMediaSink_GetStreamSinkCount(sink, &count);
4481 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
4483 hr = IMFMediaSink_GetCharacteristics(sink, &flags);
4484 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
4486 hr = IMFMediaSink_SetPresentationClock(sink, NULL);
4487 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
4489 hr = IMFMediaSink_SetPresentationClock(sink, present_clock);
4490 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
4492 hr = IMFMediaSink_GetPresentationClock(sink, NULL);
4493 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
4495 hr = IMFMediaSink_GetPresentationClock(sink, &present_clock2);
4496 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
4498 check_sar_rate_support(sink);
4500 IMFMediaSink_Release(sink);
4502 /* Activation */
4503 hr = MFCreateAudioRendererActivate(&activate);
4504 ok(hr == S_OK, "Failed to create activation object, hr %#lx.\n", hr);
4506 hr = IMFActivate_ActivateObject(activate, &IID_IMFMediaSink, (void **)&sink);
4507 ok(hr == S_OK, "Failed to activate, hr %#lx.\n", hr);
4509 hr = IMFActivate_ActivateObject(activate, &IID_IMFMediaSink, (void **)&sink2);
4510 ok(hr == S_OK, "Failed to activate, hr %#lx.\n", hr);
4511 ok(sink == sink2, "Unexpected instance.\n");
4512 IMFMediaSink_Release(sink2);
4514 hr = IMFMediaSink_GetCharacteristics(sink, &flags);
4515 ok(hr == S_OK, "Failed to get sink flags, hr %#lx.\n", hr);
4517 hr = IMFActivate_ShutdownObject(activate);
4518 ok(hr == S_OK, "Failed to shut down, hr %#lx.\n", hr);
4520 hr = IMFMediaSink_GetCharacteristics(sink, &flags);
4521 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
4523 IMFMediaSink_Release(sink);
4525 hr = IMFActivate_ActivateObject(activate, &IID_IMFMediaSink, (void **)&sink);
4526 ok(hr == S_OK, "Failed to activate, hr %#lx.\n", hr);
4528 hr = IMFMediaSink_GetCharacteristics(sink, &flags);
4529 todo_wine
4530 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
4532 IMFMediaSink_Release(sink);
4534 hr = IMFActivate_DetachObject(activate);
4535 ok(hr == E_NOTIMPL, "Unexpected hr %#lx.\n", hr);
4537 IMFActivate_Release(activate);
4539 IMFPresentationClock_Release(present_clock);
4541 hr = MFShutdown();
4542 ok(hr == S_OK, "Shutdown failure, hr %#lx.\n", hr);
4544 /* SAR attributes */
4545 hr = MFCreateAttributes(&attributes, 0);
4546 ok(hr == S_OK, "Failed to create attributes, hr %#lx.\n", hr);
4548 /* Specify role. */
4549 hr = IMFAttributes_SetUINT32(attributes, &MF_AUDIO_RENDERER_ATTRIBUTE_ENDPOINT_ROLE, eMultimedia);
4550 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
4552 hr = MFCreateAudioRenderer(attributes, &sink);
4553 ok(hr == S_OK, "Failed to create a sink, hr %#lx.\n", hr);
4554 IMFMediaSink_Release(sink);
4556 /* Invalid endpoint. */
4557 hr = IMFAttributes_SetString(attributes, &MF_AUDIO_RENDERER_ATTRIBUTE_ENDPOINT_ID, L"endpoint");
4558 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
4560 hr = MFCreateAudioRenderer(attributes, &sink);
4561 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
4563 hr = IMFAttributes_DeleteItem(attributes, &MF_AUDIO_RENDERER_ATTRIBUTE_ENDPOINT_ROLE);
4564 ok(hr == S_OK, "Failed to remove attribute, hr %#lx.\n", hr);
4566 hr = MFCreateAudioRenderer(attributes, &sink);
4567 ok(hr == MF_E_NO_AUDIO_PLAYBACK_DEVICE, "Failed to create a sink, hr %#lx.\n", hr);
4569 IMFAttributes_Release(attributes);
4571 CoUninitialize();
4574 static void test_evr(void)
4576 static const float supported_rates[] =
4578 0.0f, 1.0f, -20.0f, 20.0f, 1000.0f, -1000.0f,
4580 IMFVideoSampleAllocatorCallback *allocator_callback;
4581 IMFStreamSink *stream_sink, *stream_sink2;
4582 IMFVideoDisplayControl *display_control;
4583 IMFMediaType *media_type, *media_type2;
4584 IMFPresentationTimeSource *time_source;
4585 IMFVideoSampleAllocator *allocator;
4586 IMFMediaTypeHandler *type_handler;
4587 IMFVideoRenderer *video_renderer;
4588 IMFPresentationClock *clock;
4589 IMFMediaSink *sink, *sink2;
4590 IMFAttributes *attributes;
4591 UINT32 attr_count, value;
4592 IMFActivate *activate;
4593 HWND window, window2;
4594 IMFRateSupport *rs;
4595 DWORD flags, count;
4596 LONG sample_count;
4597 IMFSample *sample;
4598 unsigned int i;
4599 UINT64 window3;
4600 IUnknown *unk;
4601 float rate;
4602 HRESULT hr;
4603 GUID guid;
4605 hr = MFStartup(MF_VERSION, MFSTARTUP_FULL);
4606 ok(hr == S_OK, "Startup failure, hr %#lx.\n", hr);
4608 hr = MFCreateVideoRenderer(&IID_IMFVideoRenderer, (void **)&video_renderer);
4609 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4611 hr = IMFVideoRenderer_InitializeRenderer(video_renderer, NULL, NULL);
4612 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4614 IMFVideoRenderer_Release(video_renderer);
4616 hr = MFCreateVideoRendererActivate(NULL, NULL);
4617 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
4619 /* Window */
4620 window = create_window();
4621 hr = MFCreateVideoRendererActivate(window, &activate);
4622 ok(hr == S_OK, "Failed to create activate object, hr %#lx.\n", hr);
4624 hr = IMFActivate_GetUINT64(activate, &MF_ACTIVATE_VIDEO_WINDOW, &window3);
4625 ok(hr == S_OK, "Failed to get attribute, hr %#lx.\n", hr);
4626 ok(UlongToHandle(window3) == window, "Unexpected value.\n");
4628 hr = IMFActivate_ActivateObject(activate, &IID_IMFMediaSink, (void **)&sink);
4629 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4631 check_interface(sink, &IID_IMFMediaSinkPreroll, TRUE);
4632 check_interface(sink, &IID_IMFVideoRenderer, TRUE);
4633 check_interface(sink, &IID_IMFMediaEventGenerator, TRUE);
4634 check_interface(sink, &IID_IMFClockStateSink, TRUE);
4635 check_interface(sink, &IID_IMFGetService, TRUE);
4636 check_interface(sink, &IID_IMFQualityAdvise, TRUE);
4637 check_interface(sink, &IID_IMFRateSupport, TRUE);
4638 check_interface(sink, &IID_IMFRateControl, FALSE);
4639 check_service_interface(sink, &MR_VIDEO_MIXER_SERVICE, &IID_IMFVideoProcessor, TRUE);
4640 check_service_interface(sink, &MR_VIDEO_MIXER_SERVICE, &IID_IMFVideoMixerBitmap, TRUE);
4641 check_service_interface(sink, &MR_VIDEO_MIXER_SERVICE, &IID_IMFVideoMixerControl, TRUE);
4642 check_service_interface(sink, &MR_VIDEO_MIXER_SERVICE, &IID_IMFVideoMixerControl2, TRUE);
4643 check_service_interface(sink, &MR_VIDEO_RENDER_SERVICE, &IID_IMFVideoDisplayControl, TRUE);
4644 check_service_interface(sink, &MR_VIDEO_RENDER_SERVICE, &IID_IMFVideoPositionMapper, TRUE);
4645 check_service_interface(sink, &MR_VIDEO_ACCELERATION_SERVICE, &IID_IMFVideoSampleAllocator, FALSE);
4646 check_service_interface(sink, &MR_VIDEO_ACCELERATION_SERVICE, &IID_IDirect3DDeviceManager9, TRUE);
4647 check_service_interface(sink, &MF_RATE_CONTROL_SERVICE, &IID_IMFRateSupport, TRUE);
4649 hr = MFGetService((IUnknown *)sink, &MR_VIDEO_RENDER_SERVICE, &IID_IMFVideoDisplayControl,
4650 (void **)&display_control);
4651 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4653 window2 = NULL;
4654 hr = IMFVideoDisplayControl_GetVideoWindow(display_control, &window2);
4655 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4656 ok(window2 == window, "Unexpected window %p.\n", window2);
4658 IMFVideoDisplayControl_Release(display_control);
4659 IMFMediaSink_Release(sink);
4660 IMFActivate_Release(activate);
4661 DestroyWindow(window);
4663 hr = MFCreateVideoRendererActivate(NULL, &activate);
4664 ok(hr == S_OK, "Failed to create activate object, hr %#lx.\n", hr);
4666 hr = IMFActivate_GetCount(activate, &attr_count);
4667 ok(hr == S_OK, "Failed to get attribute count, hr %#lx.\n", hr);
4668 ok(attr_count == 1, "Unexpected count %u.\n", attr_count);
4670 hr = IMFActivate_GetUINT64(activate, &MF_ACTIVATE_VIDEO_WINDOW, &window3);
4671 ok(hr == S_OK, "Failed to get attribute, hr %#lx.\n", hr);
4672 ok(!window3, "Unexpected value.\n");
4674 hr = IMFActivate_ActivateObject(activate, &IID_IMFMediaSink, (void **)&sink);
4675 ok(hr == S_OK, "Failed to activate, hr %#lx.\n", hr);
4677 hr = IMFMediaSink_QueryInterface(sink, &IID_IMFAttributes, (void **)&attributes);
4678 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4679 hr = IMFAttributes_QueryInterface(attributes, &IID_IMFMediaSink, (void **)&unk);
4680 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4681 IUnknown_Release(unk);
4682 hr = IMFAttributes_GetCount(attributes, &attr_count);
4683 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4684 ok(!!attr_count, "Unexpected count %u.\n", attr_count);
4685 /* Rendering preferences are not immediately propagated to the presenter. */
4686 hr = IMFAttributes_SetUINT32(attributes, &EVRConfig_ForceBob, 1);
4687 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4688 hr = MFGetService((IUnknown *)sink, &MR_VIDEO_RENDER_SERVICE, &IID_IMFVideoDisplayControl, (void **)&display_control);
4689 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4690 hr = IMFVideoDisplayControl_GetRenderingPrefs(display_control, &flags);
4691 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4692 ok(!flags, "Unexpected flags %#lx.\n", flags);
4693 IMFVideoDisplayControl_Release(display_control);
4694 IMFAttributes_Release(attributes);
4696 /* Primary stream type handler. */
4697 hr = IMFMediaSink_GetStreamSinkById(sink, 0, &stream_sink);
4698 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4700 hr = IMFStreamSink_QueryInterface(stream_sink, &IID_IMFAttributes, (void **)&attributes);
4701 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4702 hr = IMFAttributes_GetCount(attributes, &attr_count);
4703 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4704 ok(attr_count == 2, "Unexpected count %u.\n", attr_count);
4705 value = 0;
4706 hr = IMFAttributes_GetUINT32(attributes, &MF_SA_REQUIRED_SAMPLE_COUNT, &value);
4707 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4708 ok(value == 1, "Unexpected attribute value %u.\n", value);
4709 value = 0;
4710 hr = IMFAttributes_GetUINT32(attributes, &MF_SA_D3D_AWARE, &value);
4711 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4712 ok(value == 1, "Unexpected attribute value %u.\n", value);
4714 hr = IMFAttributes_QueryInterface(attributes, &IID_IMFStreamSink, (void **)&unk);
4715 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4716 IUnknown_Release(unk);
4717 IMFAttributes_Release(attributes);
4719 hr = IMFStreamSink_GetMediaTypeHandler(stream_sink, &type_handler);
4720 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4722 hr = IMFMediaTypeHandler_GetMajorType(type_handler, NULL);
4723 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
4725 hr = IMFMediaTypeHandler_GetMajorType(type_handler, &guid);
4726 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4727 ok(IsEqualGUID(&guid, &MFMediaType_Video), "Unexpected type %s.\n", wine_dbgstr_guid(&guid));
4729 /* Supported types are not advertised. */
4730 hr = IMFMediaTypeHandler_GetMediaTypeCount(type_handler, NULL);
4731 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
4733 count = 1;
4734 hr = IMFMediaTypeHandler_GetMediaTypeCount(type_handler, &count);
4735 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4736 ok(!count, "Unexpected count %lu.\n", count);
4738 hr = IMFMediaTypeHandler_GetMediaTypeByIndex(type_handler, 0, NULL);
4739 ok(hr == MF_E_NO_MORE_TYPES, "Unexpected hr %#lx.\n", hr);
4741 hr = IMFMediaTypeHandler_GetMediaTypeByIndex(type_handler, 0, &media_type);
4742 ok(hr == MF_E_NO_MORE_TYPES, "Unexpected hr %#lx.\n", hr);
4744 hr = IMFMediaTypeHandler_GetCurrentMediaType(type_handler, NULL);
4745 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
4747 hr = IMFMediaTypeHandler_GetCurrentMediaType(type_handler, &media_type);
4748 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "Unexpected hr %#lx.\n", hr);
4750 hr = IMFMediaTypeHandler_SetCurrentMediaType(type_handler, NULL);
4751 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
4753 hr = MFCreateMediaType(&media_type);
4754 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4756 hr = IMFMediaType_SetGUID(media_type, &MF_MT_MAJOR_TYPE, &MFMediaType_Video);
4757 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4759 hr = IMFMediaType_SetGUID(media_type, &MF_MT_SUBTYPE, &MFVideoFormat_RGB32);
4760 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4762 hr = IMFMediaType_SetUINT64(media_type, &MF_MT_FRAME_SIZE, (UINT64)640 << 32 | 480);
4763 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4765 hr = IMFMediaTypeHandler_IsMediaTypeSupported(type_handler, NULL, NULL);
4766 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
4768 hr = IMFMediaTypeHandler_IsMediaTypeSupported(type_handler, media_type, &media_type2);
4769 ok(hr == MF_E_INVALIDMEDIATYPE, "Unexpected hr %#lx.\n", hr);
4771 hr = IMFMediaType_SetUINT32(media_type, &MF_MT_ALL_SAMPLES_INDEPENDENT, TRUE);
4772 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4774 media_type2 = (void *)0x1;
4775 hr = IMFMediaTypeHandler_IsMediaTypeSupported(type_handler, media_type, &media_type2);
4776 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4777 ok(!media_type2, "Unexpected media type %p.\n", media_type2);
4779 hr = IMFMediaTypeHandler_SetCurrentMediaType(type_handler, media_type);
4780 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4782 hr = IMFMediaTypeHandler_GetCurrentMediaType(type_handler, &media_type2);
4783 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4784 hr = IMFMediaType_QueryInterface(media_type2, &IID_IMFVideoMediaType, (void **)&unk);
4785 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4786 IUnknown_Release(unk);
4787 IMFMediaType_Release(media_type2);
4789 IMFMediaType_Release(media_type);
4791 IMFMediaTypeHandler_Release(type_handler);
4793 /* Stream uses an allocator. */
4794 check_service_interface(stream_sink, &MR_VIDEO_ACCELERATION_SERVICE, &IID_IMFVideoSampleAllocator, TRUE);
4795 check_service_interface(stream_sink, &MR_VIDEO_ACCELERATION_SERVICE, &IID_IDirect3DDeviceManager9, TRUE);
4796 todo_wine {
4797 check_service_interface(stream_sink, &MR_VIDEO_MIXER_SERVICE, &IID_IMFVideoProcessor, TRUE);
4798 check_service_interface(stream_sink, &MR_VIDEO_MIXER_SERVICE, &IID_IMFVideoMixerBitmap, TRUE);
4799 check_service_interface(stream_sink, &MR_VIDEO_MIXER_SERVICE, &IID_IMFVideoMixerControl, TRUE);
4800 check_service_interface(stream_sink, &MR_VIDEO_MIXER_SERVICE, &IID_IMFVideoMixerControl2, TRUE);
4801 check_service_interface(stream_sink, &MR_VIDEO_RENDER_SERVICE, &IID_IMFVideoDisplayControl, TRUE);
4802 check_service_interface(stream_sink, &MR_VIDEO_RENDER_SERVICE, &IID_IMFVideoPositionMapper, TRUE);
4803 check_service_interface(stream_sink, &MF_RATE_CONTROL_SERVICE, &IID_IMFRateSupport, TRUE);
4805 hr = MFGetService((IUnknown *)stream_sink, &MR_VIDEO_ACCELERATION_SERVICE, &IID_IMFVideoSampleAllocator,
4806 (void **)&allocator);
4807 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4809 hr = IMFVideoSampleAllocator_QueryInterface(allocator, &IID_IMFVideoSampleAllocatorCallback, (void **)&allocator_callback);
4810 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4812 sample_count = 0;
4813 hr = IMFVideoSampleAllocatorCallback_GetFreeSampleCount(allocator_callback, &sample_count);
4814 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4815 ok(!sample_count, "Unexpected sample count %ld.\n", sample_count);
4817 hr = IMFVideoSampleAllocator_AllocateSample(allocator, &sample);
4818 ok(hr == MF_E_NOT_INITIALIZED, "Unexpected hr %#lx.\n", hr);
4820 IMFVideoSampleAllocatorCallback_Release(allocator_callback);
4821 IMFVideoSampleAllocator_Release(allocator);
4823 /* Same test for a substream. */
4824 hr = IMFMediaSink_AddStreamSink(sink, 1, NULL, &stream_sink2);
4825 ok(hr == S_OK || broken(hr == E_INVALIDARG), "Unexpected hr %#lx.\n", hr);
4827 if (SUCCEEDED(hr))
4829 hr = MFGetService((IUnknown *)stream_sink2, &MR_VIDEO_ACCELERATION_SERVICE, &IID_IMFVideoSampleAllocator,
4830 (void **)&allocator);
4831 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4832 IMFVideoSampleAllocator_Release(allocator);
4834 hr = IMFMediaSink_RemoveStreamSink(sink, 1);
4835 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4837 IMFStreamSink_Release(stream_sink2);
4840 hr = IMFMediaSink_GetCharacteristics(sink, &flags);
4841 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4842 ok(flags == (MEDIASINK_CAN_PREROLL | MEDIASINK_CLOCK_REQUIRED), "Unexpected flags %#lx.\n", flags);
4844 hr = IMFActivate_ShutdownObject(activate);
4845 ok(hr == S_OK, "Failed to shut down, hr %#lx.\n", hr);
4847 hr = IMFMediaSink_GetCharacteristics(sink, &flags);
4848 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
4850 /* Activate again. */
4851 hr = IMFActivate_ActivateObject(activate, &IID_IMFMediaSink, (void **)&sink2);
4852 ok(hr == S_OK, "Failed to activate, hr %#lx.\n", hr);
4853 todo_wine
4854 ok(sink == sink2, "Unexpected instance.\n");
4855 IMFMediaSink_Release(sink2);
4857 hr = IMFActivate_DetachObject(activate);
4858 ok(hr == E_NOTIMPL, "Unexpected hr %#lx.\n", hr);
4860 hr = IMFMediaSink_GetCharacteristics(sink, &flags);
4861 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
4863 hr = IMFActivate_ActivateObject(activate, &IID_IMFMediaSink, (void **)&sink2);
4864 ok(hr == S_OK, "Failed to activate, hr %#lx.\n", hr);
4866 hr = IMFActivate_ShutdownObject(activate);
4867 ok(hr == S_OK, "Failed to shut down, hr %#lx.\n", hr);
4869 IMFMediaSink_Release(sink2);
4870 IMFMediaSink_Release(sink);
4872 IMFActivate_Release(activate);
4874 /* Set clock. */
4875 window = create_window();
4877 hr = MFCreateVideoRendererActivate(window, &activate);
4878 ok(hr == S_OK, "Failed to create activate object, hr %#lx.\n", hr);
4880 hr = IMFActivate_ActivateObject(activate, &IID_IMFMediaSink, (void **)&sink);
4881 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4883 hr = MFCreateSystemTimeSource(&time_source);
4884 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4886 hr = MFCreatePresentationClock(&clock);
4887 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4889 hr = IMFPresentationClock_SetTimeSource(clock, time_source);
4890 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4891 IMFPresentationTimeSource_Release(time_source);
4893 hr = IMFMediaSink_SetPresentationClock(sink, clock);
4894 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4896 hr = IMFMediaSink_QueryInterface(sink, &IID_IMFRateSupport, (void **)&rs);
4897 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4899 rate = 1.0f;
4900 hr = IMFRateSupport_GetSlowestRate(rs, MFRATE_FORWARD, FALSE, &rate);
4901 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4902 ok(rate == 0.0f, "Unexpected rate %f.\n", rate);
4904 rate = 1.0f;
4905 hr = IMFRateSupport_GetSlowestRate(rs, MFRATE_REVERSE, FALSE, &rate);
4906 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4907 ok(rate == 0.0f, "Unexpected rate %f.\n", rate);
4909 rate = 1.0f;
4910 hr = IMFRateSupport_GetSlowestRate(rs, MFRATE_FORWARD, TRUE, &rate);
4911 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4912 ok(rate == 0.0f, "Unexpected rate %f.\n", rate);
4914 rate = 1.0f;
4915 hr = IMFRateSupport_GetSlowestRate(rs, MFRATE_REVERSE, TRUE, &rate);
4916 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4917 ok(rate == 0.0f, "Unexpected rate %f.\n", rate);
4919 hr = IMFRateSupport_GetFastestRate(rs, MFRATE_FORWARD, FALSE, &rate);
4920 ok(hr == MF_E_INVALIDREQUEST, "Unexpected hr %#lx.\n", hr);
4922 hr = IMFRateSupport_GetFastestRate(rs, MFRATE_REVERSE, FALSE, &rate);
4923 ok(hr == MF_E_INVALIDREQUEST, "Unexpected hr %#lx.\n", hr);
4925 hr = IMFRateSupport_GetFastestRate(rs, MFRATE_FORWARD, TRUE, &rate);
4926 ok(hr == MF_E_INVALIDREQUEST, "Unexpected hr %#lx.\n", hr);
4928 hr = IMFRateSupport_GetFastestRate(rs, MFRATE_REVERSE, TRUE, &rate);
4929 ok(hr == MF_E_INVALIDREQUEST, "Unexpected hr %#lx.\n", hr);
4931 hr = IMFRateSupport_GetFastestRate(rs, MFRATE_REVERSE, TRUE, NULL);
4932 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
4934 for (i = 0; i < ARRAY_SIZE(supported_rates); ++i)
4936 rate = supported_rates[i] + 1.0f;
4937 hr = IMFRateSupport_IsRateSupported(rs, TRUE, supported_rates[i], &rate);
4938 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4939 ok(rate == supported_rates[i], "Unexpected rate %f.\n", rate);
4941 rate = supported_rates[i] + 1.0f;
4942 hr = IMFRateSupport_IsRateSupported(rs, FALSE, supported_rates[i], &rate);
4943 ok(hr == MF_E_INVALIDREQUEST, "Unexpected hr %#lx.\n", hr);
4944 ok(rate == supported_rates[i], "Unexpected rate %f.\n", rate);
4946 hr = IMFRateSupport_IsRateSupported(rs, TRUE, supported_rates[i], NULL);
4947 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4949 hr = IMFRateSupport_IsRateSupported(rs, FALSE, supported_rates[i], NULL);
4950 ok(hr == MF_E_INVALIDREQUEST, "Unexpected hr %#lx.\n", hr);
4953 /* Configuring stream type make rate support work. */
4954 hr = IMFMediaSink_GetStreamSinkById(sink, 0, &stream_sink);
4955 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4956 hr = IMFStreamSink_GetMediaTypeHandler(stream_sink, &type_handler);
4957 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4958 hr = MFCreateMediaType(&media_type);
4959 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4960 hr = IMFMediaType_SetGUID(media_type, &MF_MT_MAJOR_TYPE, &MFMediaType_Video);
4961 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4962 hr = IMFMediaType_SetGUID(media_type, &MF_MT_SUBTYPE, &MFVideoFormat_RGB32);
4963 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4964 hr = IMFMediaType_SetUINT64(media_type, &MF_MT_FRAME_SIZE, (UINT64)64 << 32 | 64);
4965 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4966 hr = IMFMediaType_SetUINT32(media_type, &MF_MT_ALL_SAMPLES_INDEPENDENT, TRUE);
4967 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4968 hr = IMFMediaTypeHandler_SetCurrentMediaType(type_handler, media_type);
4969 ok(hr == S_OK, "Failed to set current type, hr %#lx.\n", hr);
4971 rate = 1.0f;
4972 hr = IMFRateSupport_GetSlowestRate(rs, MFRATE_FORWARD, TRUE, &rate);
4973 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4974 ok(rate == 0.0f, "Unexpected rate %f.\n", rate);
4976 rate = 1.0f;
4977 hr = IMFRateSupport_GetSlowestRate(rs, MFRATE_REVERSE, TRUE, &rate);
4978 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4979 ok(rate == 0.0f, "Unexpected rate %f.\n", rate);
4981 rate = 0.0f;
4982 hr = IMFRateSupport_GetFastestRate(rs, MFRATE_FORWARD, TRUE, &rate);
4983 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4984 ok(rate == FLT_MAX, "Unexpected rate %f.\n", rate);
4986 rate = 0.0f;
4987 hr = IMFRateSupport_GetFastestRate(rs, MFRATE_REVERSE, TRUE, &rate);
4988 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4989 ok(rate == -FLT_MAX, "Unexpected rate %f.\n", rate);
4991 hr = IMFRateSupport_GetFastestRate(rs, MFRATE_REVERSE, TRUE, NULL);
4992 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
4994 hr = IMFRateSupport_GetSlowestRate(rs, MFRATE_REVERSE, TRUE, NULL);
4995 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
4997 for (i = 0; i < ARRAY_SIZE(supported_rates); ++i)
4999 rate = supported_rates[i] + 1.0f;
5000 hr = IMFRateSupport_IsRateSupported(rs, TRUE, supported_rates[i], &rate);
5001 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5002 ok(rate == supported_rates[i], "Unexpected rate %f.\n", rate);
5004 rate = supported_rates[i] + 1.0f;
5005 hr = IMFRateSupport_IsRateSupported(rs, FALSE, supported_rates[i], &rate);
5006 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5007 ok(rate == supported_rates[i], "Unexpected rate %f.\n", rate);
5009 hr = IMFRateSupport_IsRateSupported(rs, TRUE, supported_rates[i], NULL);
5010 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5012 hr = IMFRateSupport_IsRateSupported(rs, FALSE, supported_rates[i], NULL);
5013 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5016 IMFMediaTypeHandler_Release(type_handler);
5017 IMFMediaType_Release(media_type);
5018 IMFStreamSink_Release(stream_sink);
5020 hr = IMFMediaSink_Shutdown(sink);
5021 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5023 hr = IMFMediaSink_GetStreamSinkCount(sink, NULL);
5024 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
5026 hr = IMFMediaSink_GetStreamSinkCount(sink, &count);
5027 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
5029 hr = IMFRateSupport_GetSlowestRate(rs, MFRATE_FORWARD, FALSE, &rate);
5030 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
5032 hr = IMFRateSupport_GetFastestRate(rs, MFRATE_FORWARD, FALSE, &rate);
5033 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
5035 hr = IMFRateSupport_GetSlowestRate(rs, MFRATE_FORWARD, FALSE, NULL);
5036 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
5038 hr = IMFRateSupport_GetFastestRate(rs, MFRATE_FORWARD, FALSE, NULL);
5039 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
5041 hr = IMFRateSupport_IsRateSupported(rs, TRUE, 1.0f, &rate);
5042 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
5044 IMFPresentationClock_Release(clock);
5046 IMFActivate_Release(activate);
5047 DestroyWindow(window);
5049 hr = MFShutdown();
5050 ok(hr == S_OK, "Shutdown failure, hr %#lx.\n", hr);
5053 static void test_MFCreateSimpleTypeHandler(void)
5055 IMFMediaType *media_type, *media_type2, *media_type3;
5056 IMFMediaTypeHandler *handler;
5057 DWORD count;
5058 HRESULT hr;
5059 GUID guid;
5061 hr = MFCreateSimpleTypeHandler(&handler);
5062 ok(hr == S_OK, "Failed to create object, hr %#lx.\n", hr);
5064 hr = IMFMediaTypeHandler_GetMediaTypeCount(handler, NULL);
5065 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
5067 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, NULL, NULL);
5068 ok(hr == MF_E_UNEXPECTED, "Unexpected hr %#lx.\n", hr);
5070 count = 0;
5071 hr = IMFMediaTypeHandler_GetMediaTypeCount(handler, &count);
5072 ok(hr == S_OK, "Failed to get type count, hr %#lx.\n", hr);
5073 ok(count == 1, "Unexpected count %lu.\n", count);
5075 hr = IMFMediaTypeHandler_GetCurrentMediaType(handler, NULL);
5076 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
5078 media_type = (void *)0xdeadbeef;
5079 hr = IMFMediaTypeHandler_GetCurrentMediaType(handler, &media_type);
5080 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5081 ok(!media_type, "Unexpected pointer.\n");
5083 hr = MFCreateMediaType(&media_type);
5084 ok(hr == S_OK, "Failed to create media type, hr %#lx.\n", hr);
5086 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, media_type, NULL);
5087 ok(hr == MF_E_UNEXPECTED, "Unexpected hr %#lx.\n", hr);
5089 hr = IMFMediaTypeHandler_SetCurrentMediaType(handler, media_type);
5090 ok(hr == S_OK, "Failed to set current type, hr %#lx.\n", hr);
5092 hr = IMFMediaTypeHandler_GetMediaTypeByIndex(handler, 0, &media_type2);
5093 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5094 ok(media_type2 == media_type, "Unexpected type.\n");
5095 IMFMediaType_Release(media_type2);
5097 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, NULL, NULL);
5098 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
5100 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, media_type, NULL);
5101 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
5103 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, media_type, &media_type2);
5104 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
5106 hr = IMFMediaTypeHandler_GetMediaTypeByIndex(handler, 1, &media_type2);
5107 ok(hr == MF_E_NO_MORE_TYPES, "Unexpected hr %#lx.\n", hr);
5109 hr = IMFMediaTypeHandler_GetCurrentMediaType(handler, &media_type2);
5110 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5111 ok(media_type == media_type2, "Unexpected pointer.\n");
5112 IMFMediaType_Release(media_type2);
5114 hr = IMFMediaTypeHandler_GetMajorType(handler, &guid);
5115 ok(hr == MF_E_ATTRIBUTENOTFOUND, "Unexpected hr %#lx.\n", hr);
5117 hr = IMFMediaType_SetGUID(media_type, &MF_MT_MAJOR_TYPE, &MFMediaType_Video);
5118 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
5120 hr = IMFMediaTypeHandler_GetMajorType(handler, &guid);
5121 ok(hr == S_OK, "Failed to get major type, hr %#lx.\n", hr);
5122 ok(IsEqualGUID(&guid, &MFMediaType_Video), "Unexpected major type.\n");
5124 hr = MFCreateMediaType(&media_type3);
5125 ok(hr == S_OK, "Failed to create media type, hr %#lx.\n", hr);
5127 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, media_type3, NULL);
5128 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
5130 hr = IMFMediaType_SetGUID(media_type3, &MF_MT_MAJOR_TYPE, &MFMediaType_Audio);
5131 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
5133 /* Different major types. */
5134 media_type2 = (void *)0xdeadbeef;
5135 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, media_type3, &media_type2);
5136 ok(hr == E_FAIL, "Unexpected hr %#lx.\n", hr);
5137 ok(!media_type2, "Unexpected pointer.\n");
5139 hr = IMFMediaType_SetGUID(media_type3, &MF_MT_MAJOR_TYPE, &MFMediaType_Video);
5140 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
5142 media_type2 = (void *)0xdeadbeef;
5143 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, media_type3, &media_type2);
5144 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5145 ok(!media_type2, "Unexpected pointer.\n");
5147 /* Handler missing subtype. */
5148 hr = IMFMediaType_SetGUID(media_type3, &MF_MT_SUBTYPE, &MFVideoFormat_RGB8);
5149 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
5151 media_type2 = (void *)0xdeadbeef;
5152 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, media_type3, &media_type2);
5153 ok(hr == E_FAIL, "Unexpected hr %#lx.\n", hr);
5154 ok(!media_type2, "Unexpected pointer.\n");
5156 /* Different subtypes. */
5157 hr = IMFMediaType_SetGUID(media_type, &MF_MT_SUBTYPE, &MFVideoFormat_RGB24);
5158 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
5160 media_type2 = (void *)0xdeadbeef;
5161 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, media_type3, &media_type2);
5162 ok(hr == E_FAIL, "Unexpected hr %#lx.\n", hr);
5163 ok(!media_type2, "Unexpected pointer.\n");
5165 /* Same major/subtype. */
5166 hr = IMFMediaType_SetGUID(media_type3, &MF_MT_SUBTYPE, &MFVideoFormat_RGB24);
5167 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
5169 media_type2 = (void *)0xdeadbeef;
5170 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, media_type3, &media_type2);
5171 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5172 ok(!media_type2, "Unexpected pointer.\n");
5174 /* Set one more attribute. */
5175 hr = IMFMediaType_SetUINT64(media_type, &MF_MT_FRAME_SIZE, (UINT64)4 << 32 | 4);
5176 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
5178 media_type2 = (void *)0xdeadbeef;
5179 hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, media_type3, &media_type2);
5180 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5181 ok(!media_type2, "Unexpected pointer.\n");
5183 IMFMediaType_Release(media_type3);
5184 IMFMediaType_Release(media_type);
5186 hr = IMFMediaTypeHandler_SetCurrentMediaType(handler, NULL);
5187 ok(hr == S_OK, "Failed to set current type, hr %#lx.\n", hr);
5189 media_type = (void *)0xdeadbeef;
5190 hr = IMFMediaTypeHandler_GetCurrentMediaType(handler, &media_type);
5191 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5192 ok(!media_type, "Unexpected pointer.\n");
5194 hr = IMFMediaTypeHandler_GetMajorType(handler, &guid);
5195 ok(hr == MF_E_NOT_INITIALIZED, "Unexpected hr %#lx.\n", hr);
5197 IMFMediaTypeHandler_Release(handler);
5200 static void test_MFGetSupportedMimeTypes(void)
5202 PROPVARIANT value;
5203 HRESULT hr;
5205 hr = MFGetSupportedMimeTypes(NULL);
5206 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
5208 value.vt = VT_EMPTY;
5209 hr = MFGetSupportedMimeTypes(&value);
5210 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5211 ok(value.vt == (VT_VECTOR | VT_LPWSTR), "Unexpected value type %#x.\n", value.vt);
5213 PropVariantClear(&value);
5216 static void test_MFGetSupportedSchemes(void)
5218 PROPVARIANT value;
5219 HRESULT hr;
5221 hr = MFGetSupportedSchemes(NULL);
5222 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
5224 value.vt = VT_EMPTY;
5225 hr = MFGetSupportedSchemes(&value);
5226 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5227 ok(value.vt == (VT_VECTOR | VT_LPWSTR), "Unexpected value type %#x.\n", value.vt);
5229 PropVariantClear(&value);
5232 static BOOL is_sample_copier_available_type(IMFMediaType *type)
5234 GUID major = { 0 };
5235 UINT32 count;
5236 HRESULT hr;
5238 hr = IMFMediaType_GetMajorType(type, &major);
5239 ok(hr == S_OK, "Failed to get major type, hr %#lx.\n", hr);
5241 hr = IMFMediaType_GetCount(type, &count);
5242 ok(hr == S_OK, "Failed to get attribute count, hr %#lx.\n", hr);
5243 ok(count == 1, "Unexpected attribute count %u.\n", count);
5245 return IsEqualGUID(&major, &MFMediaType_Video) || IsEqualGUID(&major, &MFMediaType_Audio);
5248 static void test_sample_copier(void)
5250 IMFAttributes *attributes, *attributes2;
5251 DWORD in_min, in_max, out_min, out_max;
5252 IMFMediaType *mediatype, *mediatype2;
5253 MFT_OUTPUT_STREAM_INFO output_info;
5254 IMFSample *sample, *client_sample;
5255 MFT_INPUT_STREAM_INFO input_info;
5256 DWORD input_count, output_count;
5257 MFT_OUTPUT_DATA_BUFFER buffer;
5258 IMFMediaBuffer *media_buffer;
5259 IMFTransform *copier;
5260 DWORD flags, status;
5261 UINT32 value, count;
5262 HRESULT hr;
5264 if (!pMFCreateSampleCopierMFT)
5266 win_skip("MFCreateSampleCopierMFT() is not available.\n");
5267 return;
5270 hr = pMFCreateSampleCopierMFT(&copier);
5271 ok(hr == S_OK, "Failed to create sample copier, hr %#lx.\n", hr);
5273 hr = IMFTransform_GetAttributes(copier, &attributes);
5274 ok(hr == S_OK, "Failed to get transform attributes, hr %#lx.\n", hr);
5275 hr = IMFTransform_GetAttributes(copier, &attributes2);
5276 ok(hr == S_OK, "Failed to get transform attributes, hr %#lx.\n", hr);
5277 ok(attributes == attributes2, "Unexpected instance.\n");
5278 IMFAttributes_Release(attributes2);
5279 hr = IMFAttributes_GetCount(attributes, &count);
5280 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5281 ok(count == 1, "Unexpected attribute count %u.\n", count);
5282 hr = IMFAttributes_GetUINT32(attributes, &MFT_SUPPORT_DYNAMIC_FORMAT_CHANGE, &value);
5283 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5284 ok(!!value, "Unexpected value %u.\n", value);
5285 IMFAttributes_Release(attributes);
5287 hr = IMFTransform_GetInputStreamAttributes(copier, 0, &attributes);
5288 ok(hr == E_NOTIMPL, "Unexpected hr %#lx.\n", hr);
5290 hr = IMFTransform_GetInputStreamAttributes(copier, 1, &attributes);
5291 ok(hr == E_NOTIMPL, "Unexpected hr %#lx.\n", hr);
5293 hr = IMFTransform_GetOutputStreamAttributes(copier, 0, &attributes);
5294 ok(hr == E_NOTIMPL, "Unexpected hr %#lx.\n", hr);
5296 hr = IMFTransform_GetOutputStreamAttributes(copier, 1, &attributes);
5297 ok(hr == E_NOTIMPL, "Unexpected hr %#lx.\n", hr);
5299 hr = IMFTransform_SetOutputBounds(copier, 0, 0);
5300 ok(hr == E_NOTIMPL, "Unexpected hr %#lx.\n", hr);
5302 /* No dynamic streams. */
5303 input_count = output_count = 0;
5304 hr = IMFTransform_GetStreamCount(copier, &input_count, &output_count);
5305 ok(hr == S_OK, "Failed to get stream count, hr %#lx.\n", hr);
5306 ok(input_count == 1 && output_count == 1, "Unexpected streams count.\n");
5308 hr = IMFTransform_GetStreamLimits(copier, &in_min, &in_max, &out_min, &out_max);
5309 ok(hr == S_OK, "Failed to get stream limits, hr %#lx.\n", hr);
5310 ok(in_min == in_max && in_min == 1 && out_min == out_max && out_min == 1, "Unexpected stream limits.\n");
5312 hr = IMFTransform_GetStreamIDs(copier, 1, &input_count, 1, &output_count);
5313 ok(hr == E_NOTIMPL, "Unexpected hr %#lx.\n", hr);
5315 hr = IMFTransform_DeleteInputStream(copier, 0);
5316 ok(hr == E_NOTIMPL, "Unexpected hr %#lx.\n", hr);
5318 /* Available types. */
5319 hr = IMFTransform_GetInputAvailableType(copier, 0, 0, &mediatype);
5320 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5321 ok(is_sample_copier_available_type(mediatype), "Unexpected type.\n");
5322 IMFMediaType_Release(mediatype);
5324 hr = IMFTransform_GetInputAvailableType(copier, 0, 1, &mediatype);
5325 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5326 ok(is_sample_copier_available_type(mediatype), "Unexpected type.\n");
5327 IMFMediaType_Release(mediatype);
5329 hr = IMFTransform_GetInputAvailableType(copier, 0, 2, &mediatype);
5330 ok(hr == MF_E_NO_MORE_TYPES, "Unexpected hr %#lx.\n", hr);
5332 hr = IMFTransform_GetInputAvailableType(copier, 1, 0, &mediatype);
5333 ok(hr == MF_E_INVALIDSTREAMNUMBER, "Unexpected hr %#lx.\n", hr);
5335 hr = IMFTransform_GetOutputAvailableType(copier, 0, 0, &mediatype);
5336 ok(hr == MF_E_NO_MORE_TYPES, "Unexpected hr %#lx.\n", hr);
5338 hr = IMFTransform_GetOutputAvailableType(copier, 1, 0, &mediatype);
5339 ok(hr == MF_E_INVALIDSTREAMNUMBER, "Unexpected hr %#lx.\n", hr);
5341 hr = IMFTransform_GetInputCurrentType(copier, 0, &mediatype);
5342 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "Unexpected hr %#lx.\n", hr);
5344 hr = IMFTransform_GetInputCurrentType(copier, 1, &mediatype);
5345 ok(hr == MF_E_INVALIDSTREAMNUMBER, "Unexpected hr %#lx.\n", hr);
5347 hr = IMFTransform_GetOutputCurrentType(copier, 0, &mediatype);
5348 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "Unexpected hr %#lx.\n", hr);
5350 hr = IMFTransform_GetOutputCurrentType(copier, 1, &mediatype);
5351 ok(hr == MF_E_INVALIDSTREAMNUMBER, "Unexpected hr %#lx.\n", hr);
5353 hr = MFCreateSample(&sample);
5354 ok(hr == S_OK, "Failed to create a sample, hr %#lx.\n", hr);
5356 hr = IMFTransform_ProcessInput(copier, 0, sample, 0);
5357 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "Unexpected hr %#lx.\n", hr);
5359 hr = MFCreateMediaType(&mediatype);
5360 ok(hr == S_OK, "Failed to create media type, hr %#lx.\n", hr);
5362 hr = IMFTransform_SetOutputType(copier, 0, mediatype, 0);
5363 ok(hr == MF_E_ATTRIBUTENOTFOUND, "Unexpected hr %#lx.\n", hr);
5365 hr = IMFMediaType_SetGUID(mediatype, &MF_MT_MAJOR_TYPE, &MFMediaType_Video);
5366 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
5368 hr = IMFMediaType_SetGUID(mediatype, &MF_MT_SUBTYPE, &MFVideoFormat_RGB8);
5369 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
5371 hr = IMFMediaType_SetUINT64(mediatype, &MF_MT_FRAME_SIZE, ((UINT64)16) << 32 | 16);
5372 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
5374 hr = IMFTransform_GetOutputStreamInfo(copier, 0, &output_info);
5375 ok(hr == S_OK, "Failed to get stream info, hr %#lx.\n", hr);
5376 ok(!output_info.dwFlags, "Unexpected flags %#lx.\n", output_info.dwFlags);
5377 ok(!output_info.cbSize, "Unexpected size %lu.\n", output_info.cbSize);
5378 ok(!output_info.cbAlignment, "Unexpected alignment %lu.\n", output_info.cbAlignment);
5380 hr = IMFTransform_GetInputStreamInfo(copier, 0, &input_info);
5381 ok(hr == S_OK, "Failed to get stream info, hr %#lx.\n", hr);
5383 ok(!input_info.hnsMaxLatency, "Unexpected latency %s.\n", wine_dbgstr_longlong(input_info.hnsMaxLatency));
5384 ok(!input_info.dwFlags, "Unexpected flags %#lx.\n", input_info.dwFlags);
5385 ok(!input_info.cbSize, "Unexpected size %lu.\n", input_info.cbSize);
5386 ok(!input_info.cbMaxLookahead, "Unexpected lookahead size %lu.\n", input_info.cbMaxLookahead);
5387 ok(!input_info.cbAlignment, "Unexpected alignment %lu.\n", input_info.cbAlignment);
5389 hr = IMFTransform_SetOutputType(copier, 0, mediatype, 0);
5390 ok(hr == S_OK, "Failed to set input type, hr %#lx.\n", hr);
5392 hr = IMFTransform_GetOutputStreamInfo(copier, 0, &output_info);
5393 ok(hr == S_OK, "Failed to get stream info, hr %#lx.\n", hr);
5394 ok(!output_info.dwFlags, "Unexpected flags %#lx.\n", output_info.dwFlags);
5395 ok(output_info.cbSize == 16 * 16, "Unexpected size %lu.\n", output_info.cbSize);
5396 ok(!output_info.cbAlignment, "Unexpected alignment %lu.\n", output_info.cbAlignment);
5398 hr = IMFTransform_GetOutputCurrentType(copier, 0, &mediatype2);
5399 ok(hr == S_OK, "Failed to get current type, hr %#lx.\n", hr);
5400 IMFMediaType_Release(mediatype2);
5402 hr = IMFTransform_GetInputCurrentType(copier, 0, &mediatype2);
5403 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "Unexpected hr %#lx.\n", hr);
5405 hr = IMFTransform_GetInputStatus(copier, 0, &flags);
5406 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "Unexpected hr %#lx.\n", hr);
5408 /* Setting input type resets output type. */
5409 hr = IMFTransform_GetOutputCurrentType(copier, 0, &mediatype2);
5410 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5411 IMFMediaType_Release(mediatype2);
5413 hr = IMFTransform_SetInputType(copier, 0, mediatype, 0);
5414 ok(hr == S_OK, "Failed to set input type, hr %#lx.\n", hr);
5416 hr = IMFTransform_GetOutputCurrentType(copier, 0, &mediatype2);
5417 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "Unexpected hr %#lx.\n", hr);
5419 hr = IMFTransform_GetInputAvailableType(copier, 0, 1, &mediatype2);
5420 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5421 ok(is_sample_copier_available_type(mediatype2), "Unexpected type.\n");
5422 IMFMediaType_Release(mediatype2);
5424 hr = IMFTransform_GetInputStreamInfo(copier, 0, &input_info);
5425 ok(hr == S_OK, "Failed to get stream info, hr %#lx.\n", hr);
5426 ok(!input_info.hnsMaxLatency, "Unexpected latency %s.\n", wine_dbgstr_longlong(input_info.hnsMaxLatency));
5427 ok(!input_info.dwFlags, "Unexpected flags %#lx.\n", input_info.dwFlags);
5428 ok(input_info.cbSize == 16 * 16, "Unexpected size %lu.\n", input_info.cbSize);
5429 ok(!input_info.cbMaxLookahead, "Unexpected lookahead size %lu.\n", input_info.cbMaxLookahead);
5430 ok(!input_info.cbAlignment, "Unexpected alignment %lu.\n", input_info.cbAlignment);
5432 hr = IMFTransform_GetOutputAvailableType(copier, 0, 0, &mediatype2);
5433 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5434 hr = IMFMediaType_IsEqual(mediatype2, mediatype, &flags);
5435 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5436 IMFMediaType_Release(mediatype2);
5438 hr = IMFTransform_GetInputStatus(copier, 0, &flags);
5439 ok(hr == S_OK, "Failed to get input status, hr %#lx.\n", hr);
5440 ok(flags == MFT_INPUT_STATUS_ACCEPT_DATA, "Unexpected flags %#lx.\n", flags);
5442 hr = IMFTransform_GetInputCurrentType(copier, 0, &mediatype2);
5443 ok(hr == S_OK, "Failed to get current type, hr %#lx.\n", hr);
5444 IMFMediaType_Release(mediatype2);
5446 hr = IMFTransform_GetOutputStatus(copier, &flags);
5447 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "Unexpected hr %#lx.\n", hr);
5449 hr = IMFTransform_SetOutputType(copier, 0, mediatype, 0);
5450 ok(hr == S_OK, "Failed to set output type, hr %#lx.\n", hr);
5452 hr = IMFTransform_GetOutputStatus(copier, &flags);
5453 ok(hr == S_OK, "Failed to get output status, hr %#lx.\n", hr);
5454 ok(!flags, "Unexpected flags %#lx.\n", flags);
5456 /* Pushing samples. */
5457 hr = MFCreateAlignedMemoryBuffer(output_info.cbSize, output_info.cbAlignment, &media_buffer);
5458 ok(hr == S_OK, "Failed to create media buffer, hr %#lx.\n", hr);
5460 hr = IMFSample_AddBuffer(sample, media_buffer);
5461 ok(hr == S_OK, "Failed to add a buffer, hr %#lx.\n", hr);
5462 IMFMediaBuffer_Release(media_buffer);
5464 EXPECT_REF(sample, 1);
5465 hr = IMFTransform_ProcessInput(copier, 0, sample, 0);
5466 ok(hr == S_OK, "Failed to process input, hr %#lx.\n", hr);
5467 EXPECT_REF(sample, 2);
5469 hr = IMFTransform_GetInputStatus(copier, 0, &flags);
5470 ok(hr == S_OK, "Failed to get input status, hr %#lx.\n", hr);
5471 ok(!flags, "Unexpected flags %#lx.\n", flags);
5473 hr = IMFTransform_GetOutputStatus(copier, &flags);
5474 ok(hr == S_OK, "Failed to get output status, hr %#lx.\n", hr);
5475 ok(flags == MFT_OUTPUT_STATUS_SAMPLE_READY, "Unexpected flags %#lx.\n", flags);
5477 hr = IMFTransform_ProcessInput(copier, 0, sample, 0);
5478 ok(hr == MF_E_NOTACCEPTING, "Unexpected hr %#lx.\n", hr);
5480 hr = IMFTransform_GetOutputStreamInfo(copier, 0, &output_info);
5481 ok(hr == S_OK, "Failed to get output info, hr %#lx.\n", hr);
5483 hr = MFCreateAlignedMemoryBuffer(output_info.cbSize, output_info.cbAlignment, &media_buffer);
5484 ok(hr == S_OK, "Failed to create media buffer, hr %#lx.\n", hr);
5486 hr = MFCreateSample(&client_sample);
5487 ok(hr == S_OK, "Failed to create a sample, hr %#lx.\n", hr);
5489 hr = IMFSample_AddBuffer(client_sample, media_buffer);
5490 ok(hr == S_OK, "Failed to add a buffer, hr %#lx.\n", hr);
5491 IMFMediaBuffer_Release(media_buffer);
5493 status = 0;
5494 memset(&buffer, 0, sizeof(buffer));
5495 buffer.pSample = client_sample;
5496 hr = IMFTransform_ProcessOutput(copier, 0, 1, &buffer, &status);
5497 ok(hr == S_OK, "Failed to get output, hr %#lx.\n", hr);
5498 EXPECT_REF(sample, 1);
5500 hr = IMFTransform_ProcessOutput(copier, 0, 1, &buffer, &status);
5501 ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "Failed to get output, hr %#lx.\n", hr);
5503 /* Flushing. */
5504 hr = IMFTransform_ProcessInput(copier, 0, sample, 0);
5505 ok(hr == S_OK, "Failed to process input, hr %#lx.\n", hr);
5506 EXPECT_REF(sample, 2);
5508 hr = IMFTransform_ProcessMessage(copier, MFT_MESSAGE_COMMAND_FLUSH, 0);
5509 ok(hr == S_OK, "Failed to flush, hr %#lx.\n", hr);
5510 EXPECT_REF(sample, 1);
5512 IMFSample_Release(sample);
5513 IMFSample_Release(client_sample);
5515 IMFMediaType_Release(mediatype);
5516 IMFTransform_Release(copier);
5519 struct sample_metadata
5521 unsigned int flags;
5522 LONGLONG duration;
5523 LONGLONG time;
5526 static void sample_copier_process(IMFTransform *copier, IMFMediaBuffer *input_buffer,
5527 IMFMediaBuffer *output_buffer, const struct sample_metadata *md)
5529 static const struct sample_metadata zero_md = { 0, ~0u, ~0u };
5530 IMFSample *input_sample, *output_sample;
5531 MFT_OUTPUT_DATA_BUFFER buffer;
5532 DWORD flags, status;
5533 LONGLONG time;
5534 HRESULT hr;
5536 hr = MFCreateSample(&input_sample);
5537 ok(hr == S_OK, "Failed to create a sample, hr %#lx.\n", hr);
5539 if (md)
5541 hr = IMFSample_SetSampleFlags(input_sample, md->flags);
5542 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5544 hr = IMFSample_SetSampleTime(input_sample, md->time);
5545 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5547 hr = IMFSample_SetSampleDuration(input_sample, md->duration);
5548 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5551 hr = MFCreateSample(&output_sample);
5552 ok(hr == S_OK, "Failed to create a sample, hr %#lx.\n", hr);
5554 hr = IMFSample_SetSampleFlags(output_sample, ~0u);
5555 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5557 hr = IMFSample_SetSampleTime(output_sample, ~0u);
5558 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5560 hr = IMFSample_SetSampleDuration(output_sample, ~0u);
5561 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5563 hr = IMFSample_AddBuffer(input_sample, input_buffer);
5564 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5566 hr = IMFSample_AddBuffer(output_sample, output_buffer);
5567 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5569 hr = IMFTransform_ProcessInput(copier, 0, input_sample, 0);
5570 ok(hr == S_OK, "Failed to process input, hr %#lx.\n", hr);
5572 status = 0;
5573 memset(&buffer, 0, sizeof(buffer));
5574 buffer.pSample = output_sample;
5575 hr = IMFTransform_ProcessOutput(copier, 0, 1, &buffer, &status);
5576 ok(hr == S_OK, "Failed to get output, hr %#lx.\n", hr);
5578 if (!md) md = &zero_md;
5580 hr = IMFSample_GetSampleFlags(output_sample, &flags);
5581 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5582 ok(md->flags == flags, "Unexpected flags.\n");
5583 hr = IMFSample_GetSampleTime(output_sample, &time);
5584 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5585 ok(md->time == time, "Unexpected time.\n");
5586 hr = IMFSample_GetSampleDuration(output_sample, &time);
5587 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5588 ok(md->duration == time, "Unexpected duration.\n");
5590 IMFSample_Release(input_sample);
5591 IMFSample_Release(output_sample);
5594 static void test_sample_copier_output_processing(void)
5596 IMFMediaBuffer *input_buffer, *output_buffer;
5597 MFT_OUTPUT_STREAM_INFO output_info;
5598 struct sample_metadata md;
5599 IMFMediaType *mediatype;
5600 IMFTransform *copier;
5601 DWORD max_length;
5602 HRESULT hr;
5603 BYTE *ptr;
5605 if (!pMFCreateSampleCopierMFT)
5606 return;
5608 hr = pMFCreateSampleCopierMFT(&copier);
5609 ok(hr == S_OK, "Failed to create sample copier, hr %#lx.\n", hr);
5611 /* Configure for 16 x 16 of D3DFMT_X8R8G8B8. */
5612 hr = MFCreateMediaType(&mediatype);
5613 ok(hr == S_OK, "Failed to create media type, hr %#lx.\n", hr);
5615 hr = IMFMediaType_SetGUID(mediatype, &MF_MT_MAJOR_TYPE, &MFMediaType_Video);
5616 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
5618 hr = IMFMediaType_SetGUID(mediatype, &MF_MT_SUBTYPE, &MFVideoFormat_RGB32);
5619 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
5621 hr = IMFMediaType_SetUINT64(mediatype, &MF_MT_FRAME_SIZE, ((UINT64)16) << 32 | 16);
5622 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
5624 hr = IMFTransform_SetInputType(copier, 0, mediatype, 0);
5625 ok(hr == S_OK, "Failed to set input type, hr %#lx.\n", hr);
5627 hr = IMFTransform_SetOutputType(copier, 0, mediatype, 0);
5628 ok(hr == S_OK, "Failed to set input type, hr %#lx.\n", hr);
5630 /* Source and destination are linear buffers, destination is twice as large. */
5631 hr = IMFTransform_GetOutputStreamInfo(copier, 0, &output_info);
5632 ok(hr == S_OK, "Failed to get output info, hr %#lx.\n", hr);
5634 hr = MFCreateAlignedMemoryBuffer(output_info.cbSize, output_info.cbAlignment, &output_buffer);
5635 ok(hr == S_OK, "Failed to create media buffer, hr %#lx.\n", hr);
5637 hr = IMFMediaBuffer_Lock(output_buffer, &ptr, &max_length, NULL);
5638 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5639 memset(ptr, 0xcc, max_length);
5640 hr = IMFMediaBuffer_Unlock(output_buffer);
5641 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5643 hr = MFCreateAlignedMemoryBuffer(output_info.cbSize, output_info.cbAlignment, &input_buffer);
5644 ok(hr == S_OK, "Failed to create media buffer, hr %#lx.\n", hr);
5646 hr = IMFMediaBuffer_Lock(input_buffer, &ptr, &max_length, NULL);
5647 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5648 memset(ptr, 0xaa, max_length);
5649 hr = IMFMediaBuffer_Unlock(input_buffer);
5650 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5651 hr = IMFMediaBuffer_SetCurrentLength(input_buffer, 4);
5652 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5654 sample_copier_process(copier, input_buffer, output_buffer, NULL);
5656 hr = IMFMediaBuffer_Lock(output_buffer, &ptr, &max_length, NULL);
5657 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5658 ok(ptr[0] == 0xaa && ptr[4] == 0xcc, "Unexpected buffer contents.\n");
5660 hr = IMFMediaBuffer_Unlock(output_buffer);
5661 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5663 md.flags = 123;
5664 md.time = 10;
5665 md.duration = 2;
5666 sample_copier_process(copier, input_buffer, output_buffer, &md);
5668 IMFMediaBuffer_Release(input_buffer);
5669 IMFMediaBuffer_Release(output_buffer);
5671 IMFMediaType_Release(mediatype);
5672 IMFTransform_Release(copier);
5675 static void test_MFGetTopoNodeCurrentType(void)
5677 IMFMediaType *media_type, *media_type2;
5678 IMFTopologyNode *node;
5679 HRESULT hr;
5681 if (!pMFGetTopoNodeCurrentType)
5683 win_skip("MFGetTopoNodeCurrentType() is unsupported.\n");
5684 return;
5687 /* Tee node. */
5688 hr = MFCreateTopologyNode(MF_TOPOLOGY_TEE_NODE, &node);
5689 ok(hr == S_OK, "Failed to create a node, hr %#lx.\n", hr);
5691 hr = pMFGetTopoNodeCurrentType(node, 0, TRUE, &media_type);
5692 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
5694 hr = pMFGetTopoNodeCurrentType(node, 0, FALSE, &media_type);
5695 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
5697 hr = MFCreateMediaType(&media_type2);
5698 ok(hr == S_OK, "Failed to create media type, hr %#lx.\n", hr);
5700 hr = IMFMediaType_SetGUID(media_type2, &MF_MT_MAJOR_TYPE, &MFMediaType_Video);
5701 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
5703 /* Input type returned, if set. */
5704 hr = IMFTopologyNode_SetInputPrefType(node, 0, media_type2);
5705 ok(hr == S_OK, "Failed to set media type, hr %#lx.\n", hr);
5707 hr = pMFGetTopoNodeCurrentType(node, 0, FALSE, &media_type);
5708 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5709 ok(media_type == media_type2, "Unexpected pointer.\n");
5710 IMFMediaType_Release(media_type);
5712 hr = IMFTopologyNode_SetInputPrefType(node, 0, NULL);
5713 ok(hr == S_OK, "Failed to set media type, hr %#lx.\n", hr);
5715 hr = pMFGetTopoNodeCurrentType(node, 0, FALSE, &media_type);
5716 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
5718 /* Set second output. */
5719 hr = IMFTopologyNode_SetOutputPrefType(node, 1, media_type2);
5720 ok(hr == S_OK, "Failed to set media type, hr %#lx.\n", hr);
5722 hr = pMFGetTopoNodeCurrentType(node, 0, FALSE, &media_type);
5723 ok(hr == E_FAIL, "Unexpected hr %#lx.\n", hr);
5725 hr = IMFTopologyNode_SetOutputPrefType(node, 1, NULL);
5726 ok(hr == S_OK, "Failed to set media type, hr %#lx.\n", hr);
5728 /* Set first output. */
5729 hr = IMFTopologyNode_SetOutputPrefType(node, 0, media_type2);
5730 ok(hr == S_OK, "Failed to set media type, hr %#lx.\n", hr);
5732 hr = pMFGetTopoNodeCurrentType(node, 0, FALSE, &media_type);
5733 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5734 ok(media_type == media_type2, "Unexpected pointer.\n");
5735 IMFMediaType_Release(media_type);
5737 hr = IMFTopologyNode_SetOutputPrefType(node, 0, NULL);
5738 ok(hr == S_OK, "Failed to set media type, hr %#lx.\n", hr);
5740 /* Set primary output. */
5741 hr = IMFTopologyNode_SetOutputPrefType(node, 1, media_type2);
5742 ok(hr == S_OK, "Failed to set media type, hr %#lx.\n", hr);
5744 hr = IMFTopologyNode_SetUINT32(node, &MF_TOPONODE_PRIMARYOUTPUT, 1);
5745 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
5747 hr = pMFGetTopoNodeCurrentType(node, 0, FALSE, &media_type);
5748 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5749 ok(media_type == media_type2, "Unexpected pointer.\n");
5750 IMFMediaType_Release(media_type);
5752 hr = pMFGetTopoNodeCurrentType(node, 0, TRUE, &media_type);
5753 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5754 ok(media_type == media_type2, "Unexpected pointer.\n");
5755 IMFMediaType_Release(media_type);
5757 IMFTopologyNode_Release(node);
5758 IMFMediaType_Release(media_type2);
5761 static void init_functions(void)
5763 HMODULE mod = GetModuleHandleA("mf.dll");
5765 #define X(f) p##f = (void*)GetProcAddress(mod, #f)
5766 X(MFCreateSampleCopierMFT);
5767 X(MFGetTopoNodeCurrentType);
5768 #undef X
5771 static void test_MFRequireProtectedEnvironment(void)
5773 IMFPresentationDescriptor *pd;
5774 IMFMediaType *mediatype;
5775 IMFStreamDescriptor *sd;
5776 HRESULT hr;
5778 hr = MFCreateMediaType(&mediatype);
5779 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5781 hr = MFCreateStreamDescriptor(0, 1, &mediatype, &sd);
5782 ok(hr == S_OK, "Failed to create stream descriptor, hr %#lx.\n", hr);
5784 hr = MFCreatePresentationDescriptor(1, &sd, &pd);
5785 ok(hr == S_OK, "Failed to create presentation descriptor, hr %#lx.\n", hr);
5787 hr = IMFPresentationDescriptor_SelectStream(pd, 0);
5788 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5790 hr = MFRequireProtectedEnvironment(pd);
5791 ok(hr == S_FALSE, "Unexpected hr %#lx.\n", hr);
5793 hr = IMFStreamDescriptor_SetUINT32(sd, &MF_SD_PROTECTED, 1);
5794 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5796 hr = MFRequireProtectedEnvironment(pd);
5797 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5799 hr = IMFPresentationDescriptor_DeselectStream(pd, 0);
5800 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5802 hr = MFRequireProtectedEnvironment(pd);
5803 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5805 IMFMediaType_Release(mediatype);
5806 IMFStreamDescriptor_Release(sd);
5807 IMFPresentationDescriptor_Release(pd);
5810 static IMFSample *create_sample(const BYTE *data, ULONG size)
5812 IMFMediaBuffer *media_buffer;
5813 IMFSample *sample;
5814 DWORD length;
5815 BYTE *buffer;
5816 HRESULT hr;
5817 ULONG ret;
5819 hr = MFCreateSample(&sample);
5820 ok(hr == S_OK, "MFCreateSample returned %#lx\n", hr);
5821 hr = MFCreateMemoryBuffer(size, &media_buffer);
5822 ok(hr == S_OK, "MFCreateMemoryBuffer returned %#lx\n", hr);
5823 hr = IMFMediaBuffer_Lock(media_buffer, &buffer, NULL, &length);
5824 ok(hr == S_OK, "Lock returned %#lx\n", hr);
5825 ok(length == 0, "got length %lu\n", length);
5826 if (!data) memset(buffer, 0xcd, size);
5827 else memcpy(buffer, data, size);
5828 hr = IMFMediaBuffer_Unlock(media_buffer);
5829 ok(hr == S_OK, "Unlock returned %#lx\n", hr);
5830 hr = IMFMediaBuffer_SetCurrentLength(media_buffer, data ? size : 0);
5831 ok(hr == S_OK, "SetCurrentLength returned %#lx\n", hr);
5832 hr = IMFSample_AddBuffer(sample, media_buffer);
5833 ok(hr == S_OK, "AddBuffer returned %#lx\n", hr);
5834 ret = IMFMediaBuffer_Release(media_buffer);
5835 ok(ret == 1, "Release returned %lu\n", ret);
5837 return sample;
5840 #define check_sample(a, b, c) check_sample_(__LINE__, a, b, c)
5841 static void check_sample_(int line, IMFSample *sample, const BYTE *expect_buf, HANDLE output_file)
5843 IMFMediaBuffer *media_buffer;
5844 DWORD length;
5845 BYTE *buffer;
5846 HRESULT hr;
5847 ULONG ret;
5849 hr = IMFSample_ConvertToContiguousBuffer(sample, &media_buffer);
5850 ok_(__FILE__, line)(hr == S_OK, "ConvertToContiguousBuffer returned %#lx\n", hr);
5851 hr = IMFMediaBuffer_Lock(media_buffer, &buffer, NULL, &length);
5852 ok_(__FILE__, line)(hr == S_OK, "Lock returned %#lx\n", hr);
5853 ok_(__FILE__, line)(!memcmp(expect_buf, buffer, length), "unexpected buffer data\n");
5854 if (output_file) WriteFile(output_file, buffer, length, &length, NULL);
5855 hr = IMFMediaBuffer_Unlock(media_buffer);
5856 ok_(__FILE__, line)(hr == S_OK, "Unlock returned %#lx\n", hr);
5857 ret = IMFMediaBuffer_Release(media_buffer);
5858 ok_(__FILE__, line)(ret == 1, "Release returned %lu\n", ret);
5861 #define check_sample_rgb32(a, b, c) check_sample_rgb32_(__LINE__, a, b, c)
5862 static void check_sample_rgb32_(int line, IMFSample *sample, const BYTE *expect_buf, HANDLE output_file)
5864 DWORD i, length, diff = 0, max_diff;
5865 IMFMediaBuffer *media_buffer;
5866 BYTE *buffer;
5867 HRESULT hr;
5868 ULONG ret;
5870 hr = IMFSample_ConvertToContiguousBuffer(sample, &media_buffer);
5871 ok_(__FILE__, line)(hr == S_OK, "ConvertToContiguousBuffer returned %#lx\n", hr);
5872 hr = IMFMediaBuffer_Lock(media_buffer, &buffer, NULL, &length);
5873 ok_(__FILE__, line)(hr == S_OK, "Lock returned %#lx\n", hr);
5875 /* check that buffer values are "close" enough, there's some pretty big
5876 * differences with the color converter between ffmpeg and native.
5878 for (i = 0; i < length; i++)
5880 if (i % 4 == 3) continue; /* ignore alpha diff */
5881 diff += abs((int)expect_buf[i] - (int)buffer[i]);
5883 max_diff = length * 3 * 256;
5884 ok_(__FILE__, line)(diff * 100 / max_diff == 0, "unexpected buffer data\n");
5886 if (output_file) WriteFile(output_file, buffer, length, &length, NULL);
5887 hr = IMFMediaBuffer_Unlock(media_buffer);
5888 ok_(__FILE__, line)(hr == S_OK, "Unlock returned %#lx\n", hr);
5889 ret = IMFMediaBuffer_Release(media_buffer);
5890 ok_(__FILE__, line)(ret == 1, "Release returned %lu\n", ret);
5893 #define check_sample_pcm16(a, b, c, d) check_sample_pcm16_(__LINE__, a, b, c, d)
5894 static void check_sample_pcm16_(int line, IMFSample *sample, const BYTE *expect_buf, HANDLE output_file, BOOL todo)
5896 IMFMediaBuffer *media_buffer;
5897 DWORD i, length;
5898 BYTE *buffer;
5899 HRESULT hr;
5900 ULONG ret;
5902 hr = IMFSample_ConvertToContiguousBuffer(sample, &media_buffer);
5903 ok_(__FILE__, line)(hr == S_OK, "ConvertToContiguousBuffer returned %#lx\n", hr);
5904 hr = IMFMediaBuffer_Lock(media_buffer, &buffer, NULL, &length);
5905 ok_(__FILE__, line)(hr == S_OK, "Lock returned %#lx\n", hr);
5907 /* check that buffer values are close enough, there's some differences in
5908 * the output of audio DSP between 32bit and 64bit implementation
5910 for (i = 0; i < length; i += 2)
5912 DWORD expect = *(INT16 *)(expect_buf + i), value = *(INT16 *)(buffer + i);
5913 if (expect - value + 512 > 1024) break;
5916 todo_wine_if(todo)
5917 ok_(__FILE__, line)(i == length, "unexpected buffer data\n");
5919 if (output_file) WriteFile(output_file, buffer, length, &length, NULL);
5920 hr = IMFMediaBuffer_Unlock(media_buffer);
5921 ok_(__FILE__, line)(hr == S_OK, "Unlock returned %#lx\n", hr);
5922 ret = IMFMediaBuffer_Release(media_buffer);
5923 ok_(__FILE__, line)(ret == 1, "Release returned %lu\n", ret);
5926 static const BYTE wma_codec_data[10] = {0, 0x44, 0, 0, 0x17, 0, 0, 0, 0, 0};
5927 static const ULONG wmaenc_block_size = 1487;
5928 static const ULONG wmadec_block_size = 0x2000;
5930 static void test_wma_encoder(void)
5932 const GUID transform_inputs[] =
5934 MFAudioFormat_PCM,
5935 MFAudioFormat_Float,
5937 const GUID transform_outputs[] =
5939 MFAudioFormat_WMAudioV8,
5940 MFAudioFormat_WMAudioV9,
5941 MFAudioFormat_WMAudio_Lossless,
5943 const GUID dmo_inputs[] =
5945 MEDIASUBTYPE_PCM,
5947 const GUID dmo_outputs[] =
5949 MEDIASUBTYPE_WMAUDIO2,
5950 MEDIASUBTYPE_WMAUDIO3,
5951 MEDIASUBTYPE_WMAUDIO_LOSSLESS,
5954 static const struct attribute_desc input_type_desc[] =
5956 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
5957 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_Float),
5958 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 32),
5959 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 2),
5960 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 22050),
5961 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 176400),
5962 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 8),
5963 {0},
5965 const struct attribute_desc output_type_desc[] =
5967 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
5968 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_WMAudioV8),
5969 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 2),
5970 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 22050),
5971 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 4003),
5972 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, wmaenc_block_size),
5973 ATTR_BLOB(MF_MT_USER_DATA, wma_codec_data, sizeof(wma_codec_data)),
5974 {0},
5977 MFT_REGISTER_TYPE_INFO output_type = {MFMediaType_Audio, MFAudioFormat_WMAudioV8};
5978 MFT_REGISTER_TYPE_INFO input_type = {MFMediaType_Audio, MFAudioFormat_Float};
5979 ULONG audio_data_len, wmaenc_data_len;
5980 const BYTE *audio_data, *wmaenc_data;
5981 MFT_OUTPUT_STREAM_INFO output_info;
5982 MFT_INPUT_STREAM_INFO input_info;
5983 MFT_OUTPUT_DATA_BUFFER output;
5984 WCHAR output_path[MAX_PATH];
5985 IMFMediaType *media_type;
5986 IMFTransform *transform;
5987 DWORD status, length;
5988 HANDLE output_file;
5989 IMFSample *sample;
5990 HRSRC resource;
5991 GUID class_id;
5992 ULONG i, ret;
5993 HRESULT hr;
5995 hr = CoInitialize(NULL);
5996 ok(hr == S_OK, "Failed to initialize, hr %#lx.\n", hr);
5998 if (!create_transform(MFT_CATEGORY_AUDIO_ENCODER, &input_type, &output_type, L"WMAudio Encoder MFT", &MFMediaType_Audio,
5999 transform_inputs, ARRAY_SIZE(transform_inputs), transform_outputs, ARRAY_SIZE(transform_outputs),
6000 &transform, &CLSID_CWMAEncMediaObject, &class_id))
6001 goto failed;
6003 check_dmo(&class_id, L"WMAudio Encoder DMO", &MEDIATYPE_Audio, dmo_inputs, ARRAY_SIZE(dmo_inputs),
6004 dmo_outputs, ARRAY_SIZE(dmo_outputs));
6006 check_interface(transform, &IID_IMFTransform, TRUE);
6007 check_interface(transform, &IID_IMediaObject, TRUE);
6008 check_interface(transform, &IID_IPropertyStore, TRUE);
6009 check_interface(transform, &IID_IPropertyBag, TRUE);
6011 hr = MFCreateMediaType(&media_type);
6012 ok(hr == S_OK, "MFCreateMediaType returned %#lx\n", hr);
6013 init_media_type(media_type, input_type_desc, -1);
6014 hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
6015 ok(hr == S_OK, "SetInputType returned %#lx.\n", hr);
6016 init_media_type(media_type, output_type_desc, -1);
6017 hr = IMFTransform_SetOutputType(transform, 0, media_type, 0);
6018 ok(hr == S_OK, "SetOutputType returned %#lx.\n", hr);
6019 ret = IMFMediaType_Release(media_type);
6020 ok(ret == 0, "Release returned %lu\n", ret);
6022 memset(&input_info, 0xcd, sizeof(input_info));
6023 hr = IMFTransform_GetInputStreamInfo(transform, 0, &input_info);
6024 ok(hr == S_OK, "GetInputStreamInfo returned %#lx\n", hr);
6025 ok(input_info.hnsMaxLatency == 19969161, "got hnsMaxLatency %s\n",
6026 wine_dbgstr_longlong(input_info.hnsMaxLatency));
6027 ok(input_info.dwFlags == 0, "got dwFlags %#lx\n", input_info.dwFlags);
6028 ok(input_info.cbSize == 8, "got cbSize %lu\n", input_info.cbSize);
6029 ok(input_info.cbMaxLookahead == 0, "got cbMaxLookahead %#lx\n", input_info.cbMaxLookahead);
6030 ok(input_info.cbAlignment == 1, "got cbAlignment %#lx\n", input_info.cbAlignment);
6032 memset(&output_info, 0xcd, sizeof(output_info));
6033 hr = IMFTransform_GetOutputStreamInfo(transform, 0, &output_info);
6034 ok(hr == S_OK, "GetOutputStreamInfo returned %#lx\n", hr);
6035 ok(output_info.dwFlags == 0, "got dwFlags %#lx\n", output_info.dwFlags);
6036 ok(output_info.cbSize == wmaenc_block_size, "got cbSize %#lx\n", output_info.cbSize);
6037 ok(output_info.cbAlignment == 1, "got cbAlignment %#lx\n", output_info.cbAlignment);
6039 resource = FindResourceW(NULL, L"audiodata.bin", (const WCHAR *)RT_RCDATA);
6040 ok(resource != 0, "FindResourceW failed, error %lu\n", GetLastError());
6041 audio_data = LockResource(LoadResource(GetModuleHandleW(NULL), resource));
6042 audio_data_len = SizeofResource(GetModuleHandleW(NULL), resource);
6043 ok(audio_data_len == 179928, "got length %lu\n", audio_data_len);
6045 sample = create_sample(audio_data, audio_data_len);
6046 hr = IMFSample_SetSampleTime(sample, 0);
6047 ok(hr == S_OK, "SetSampleTime returned %#lx\n", hr);
6048 hr = IMFSample_SetSampleDuration(sample, 10000000);
6049 ok(hr == S_OK, "SetSampleDuration returned %#lx\n", hr);
6050 hr = IMFTransform_ProcessInput(transform, 0, sample, 0);
6051 ok(hr == S_OK, "ProcessInput returned %#lx\n", hr);
6052 hr = IMFTransform_ProcessMessage(transform, MFT_MESSAGE_COMMAND_DRAIN, 0);
6053 ok(hr == S_OK, "ProcessMessage returned %#lx\n", hr);
6054 hr = IMFTransform_ProcessInput(transform, 0, sample, 0);
6055 ok(hr == MF_E_NOTACCEPTING, "ProcessInput returned %#lx\n", hr);
6056 IMFSample_Release(sample);
6058 status = 0xdeadbeef;
6059 sample = create_sample(NULL, output_info.cbSize);
6060 memset(&output, 0, sizeof(output));
6061 output.pSample = sample;
6063 resource = FindResourceW(NULL, L"wmaencdata.bin", (const WCHAR *)RT_RCDATA);
6064 ok(resource != 0, "FindResourceW failed, error %lu\n", GetLastError());
6065 wmaenc_data = LockResource(LoadResource(GetModuleHandleW(NULL), resource));
6066 wmaenc_data_len = SizeofResource(GetModuleHandleW(NULL), resource);
6067 ok(wmaenc_data_len % wmaenc_block_size == 0, "got length %lu\n", wmaenc_data_len);
6069 /* and generate a new one as well in a temporary directory */
6070 GetTempPathW(ARRAY_SIZE(output_path), output_path);
6071 lstrcatW(output_path, L"wmaencdata.bin");
6072 output_file = CreateFileW(output_path, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0);
6073 ok(output_file != INVALID_HANDLE_VALUE, "CreateFileW failed, error %lu\n", GetLastError());
6075 i = 0;
6076 while (SUCCEEDED(hr = IMFTransform_ProcessOutput(transform, 0, 1, &output, &status)))
6078 winetest_push_context("%lu", i);
6079 ok(hr == S_OK, "ProcessOutput returned %#lx\n", hr);
6080 ok(output.pSample == sample, "got pSample %p\n", output.pSample);
6081 ok(output.dwStatus == MFT_OUTPUT_DATA_BUFFER_INCOMPLETE ||
6082 broken(output.dwStatus == (MFT_OUTPUT_DATA_BUFFER_INCOMPLETE|7)) /* win7 */,
6083 "got dwStatus %#lx\n", output.dwStatus);
6084 ok(status == 0, "got status %#lx\n", status);
6085 hr = IMFSample_GetTotalLength(sample, &length);
6086 ok(hr == S_OK, "GetTotalLength returned %#lx\n", hr);
6087 ok(length == wmaenc_block_size, "got length %lu\n", length);
6088 ok(wmaenc_data_len > i * wmaenc_block_size, "got %lu blocks\n", i);
6089 check_sample(sample, wmaenc_data + i * wmaenc_block_size, output_file);
6090 winetest_pop_context();
6091 i++;
6094 trace("created %s\n", debugstr_w(output_path));
6095 CloseHandle(output_file);
6097 ret = IMFSample_Release(sample);
6098 ok(ret == 0, "Release returned %lu\n", ret);
6100 status = 0xdeadbeef;
6101 sample = create_sample(NULL, output_info.cbSize);
6102 memset(&output, 0, sizeof(output));
6103 output.pSample = sample;
6104 hr = IMFTransform_ProcessOutput(transform, 0, 1, &output, &status);
6105 ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "ProcessOutput returned %#lx\n", hr);
6106 ok(output.pSample == sample, "got pSample %p\n", output.pSample);
6107 ok(output.dwStatus == 0, "got dwStatus %#lx\n", output.dwStatus);
6108 ok(status == 0, "got status %#lx\n", status);
6109 hr = IMFSample_GetTotalLength(sample, &length);
6110 ok(hr == S_OK, "GetTotalLength returned %#lx\n", hr);
6111 ok(length == 0, "got length %lu\n", length);
6112 ret = IMFSample_Release(sample);
6113 ok(ret == 0, "Release returned %lu\n", ret);
6115 ret = IMFTransform_Release(transform);
6116 ok(ret == 0, "Release returned %lu\n", ret);
6118 failed:
6119 CoUninitialize();
6122 static void test_wma_decoder(void)
6124 const GUID transform_inputs[] =
6126 MEDIASUBTYPE_MSAUDIO1,
6127 MFAudioFormat_WMAudioV8,
6128 MFAudioFormat_WMAudioV9,
6129 MFAudioFormat_WMAudio_Lossless,
6131 const GUID transform_outputs[] =
6133 MFAudioFormat_PCM,
6134 MFAudioFormat_Float,
6136 const GUID dmo_inputs[] =
6138 MEDIASUBTYPE_MSAUDIO1,
6139 MEDIASUBTYPE_WMAUDIO2,
6140 MEDIASUBTYPE_WMAUDIO3,
6141 MEDIASUBTYPE_WMAUDIO_LOSSLESS,
6143 const GUID dmo_outputs[] =
6145 MEDIASUBTYPE_PCM,
6146 MEDIASUBTYPE_IEEE_FLOAT,
6149 static const media_type_desc expect_available_inputs[] =
6152 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
6153 ATTR_GUID(MF_MT_SUBTYPE, MEDIASUBTYPE_MSAUDIO1),
6154 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
6157 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
6158 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_WMAudioV8),
6159 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
6162 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
6163 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_WMAudioV9),
6164 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
6167 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
6168 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_WMAudio_Lossless),
6169 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
6172 static const media_type_desc expect_available_outputs[] =
6175 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
6176 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_Float),
6177 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 32),
6178 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 2),
6179 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 22050),
6180 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 176400),
6181 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 8),
6182 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
6183 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
6184 ATTR_UINT32(MF_MT_AUDIO_PREFER_WAVEFORMATEX, 1),
6187 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
6188 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_PCM),
6189 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 16),
6190 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 2),
6191 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 22050),
6192 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 88200),
6193 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 4),
6194 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
6195 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
6196 ATTR_UINT32(MF_MT_AUDIO_PREFER_WAVEFORMATEX, 1),
6200 const struct attribute_desc input_type_desc[] =
6202 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
6203 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_WMAudioV8),
6204 ATTR_BLOB(MF_MT_USER_DATA, wma_codec_data, sizeof(wma_codec_data)),
6205 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, wmaenc_block_size),
6206 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 22050),
6207 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 2),
6208 {0},
6210 static const struct attribute_desc output_type_desc[] =
6212 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
6213 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_PCM),
6214 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 88200),
6215 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 16),
6216 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 2),
6217 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 22050),
6218 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 4),
6219 {0},
6222 MFT_REGISTER_TYPE_INFO input_type = {MFMediaType_Audio, MFAudioFormat_WMAudioV8};
6223 MFT_REGISTER_TYPE_INFO output_type = {MFMediaType_Audio, MFAudioFormat_Float};
6224 IUnknown *unknown, *tmp_unknown, outer = {&test_unk_vtbl};
6225 ULONG wmadec_data_len, wmaenc_data_len;
6226 const BYTE *wmadec_data, *wmaenc_data;
6227 MFT_OUTPUT_STREAM_INFO output_info;
6228 MFT_OUTPUT_DATA_BUFFER outputs[2];
6229 MFT_INPUT_STREAM_INFO input_info;
6230 MFT_OUTPUT_DATA_BUFFER output;
6231 DWORD status, flags, length;
6232 WCHAR output_path[MAX_PATH];
6233 IMediaObject *media_object;
6234 IPropertyBag *property_bag;
6235 IMFMediaType *media_type;
6236 IMFTransform *transform;
6237 LONGLONG time, duration;
6238 HANDLE output_file;
6239 IMFSample *sample;
6240 ULONG i, ret, ref;
6241 HRSRC resource;
6242 GUID class_id;
6243 UINT32 value;
6244 HRESULT hr;
6246 hr = CoInitialize(NULL);
6247 ok(hr == S_OK, "Failed to initialize, hr %#lx.\n", hr);
6249 if (!create_transform(MFT_CATEGORY_AUDIO_DECODER, &input_type, &output_type, L"WMAudio Decoder MFT", &MFMediaType_Audio,
6250 transform_inputs, ARRAY_SIZE(transform_inputs), transform_outputs, ARRAY_SIZE(transform_outputs),
6251 &transform, &CLSID_CWMADecMediaObject, &class_id))
6252 goto failed;
6254 check_dmo(&class_id, L"WMAudio Decoder DMO", &MEDIATYPE_Audio, dmo_inputs, ARRAY_SIZE(dmo_inputs),
6255 dmo_outputs, ARRAY_SIZE(dmo_outputs));
6257 check_interface(transform, &IID_IMFTransform, TRUE);
6258 check_interface(transform, &IID_IMediaObject, TRUE);
6259 todo_wine
6260 check_interface(transform, &IID_IPropertyStore, TRUE);
6261 check_interface(transform, &IID_IPropertyBag, TRUE);
6263 /* check default media types */
6265 hr = IMFTransform_GetInputStreamInfo(transform, 0, &input_info);
6266 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "GetInputStreamInfo returned %#lx\n", hr);
6267 hr = IMFTransform_GetOutputStreamInfo(transform, 0, &output_info);
6268 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "GetOutputStreamInfo returned %#lx\n", hr);
6269 hr = IMFTransform_GetOutputAvailableType(transform, 0, 0, &media_type);
6270 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "GetOutputAvailableType returned %#lx\n", hr);
6272 i = -1;
6273 while (SUCCEEDED(hr = IMFTransform_GetInputAvailableType(transform, 0, ++i, &media_type)))
6275 winetest_push_context("in %lu", i);
6276 ok(hr == S_OK, "GetInputAvailableType returned %#lx\n", hr);
6277 check_media_type(media_type, expect_available_inputs[i], -1);
6278 hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
6279 ok(hr == MF_E_INVALIDMEDIATYPE, "SetInputType returned %#lx.\n", hr);
6280 ret = IMFMediaType_Release(media_type);
6281 ok(ret == 0, "Release returned %lu\n", ret);
6282 winetest_pop_context();
6284 todo_wine
6285 ok(hr == MF_E_NO_MORE_TYPES, "GetInputAvailableType returned %#lx\n", hr);
6286 todo_wine
6287 ok(i == 4, "%lu input media types\n", i);
6289 /* setting output media type first doesn't work */
6291 hr = MFCreateMediaType(&media_type);
6292 ok(hr == S_OK, "MFCreateMediaType returned %#lx\n", hr);
6293 init_media_type(media_type, output_type_desc, -1);
6294 hr = IMFTransform_SetOutputType(transform, 0, media_type, 0);
6295 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "SetOutputType returned %#lx.\n", hr);
6296 ret = IMFMediaType_Release(media_type);
6297 ok(ret == 0, "Release returned %lu\n", ret);
6299 /* check required input media type attributes */
6301 hr = MFCreateMediaType(&media_type);
6302 ok(hr == S_OK, "MFCreateMediaType returned %#lx\n", hr);
6303 hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
6304 ok(hr == MF_E_ATTRIBUTENOTFOUND, "SetInputType returned %#lx.\n", hr);
6305 init_media_type(media_type, input_type_desc, 1);
6306 hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
6307 ok(hr == MF_E_ATTRIBUTENOTFOUND, "SetInputType returned %#lx.\n", hr);
6308 init_media_type(media_type, input_type_desc, 2);
6309 for (i = 2; i < ARRAY_SIZE(input_type_desc) - 1; ++i)
6311 hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
6312 ok(hr == MF_E_INVALIDMEDIATYPE, "SetInputType returned %#lx.\n", hr);
6313 init_media_type(media_type, input_type_desc, i + 1);
6315 hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
6316 ok(hr == S_OK, "SetInputType returned %#lx.\n", hr);
6317 ret = IMFMediaType_Release(media_type);
6318 ok(ret == 0, "Release returned %lu\n", ret);
6320 hr = IMFTransform_GetInputStreamInfo(transform, 0, &input_info);
6321 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "GetInputStreamInfo returned %#lx\n", hr);
6322 hr = IMFTransform_GetOutputStreamInfo(transform, 0, &output_info);
6323 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "GetOutputStreamInfo returned %#lx\n", hr);
6325 /* check new output media types */
6327 i = -1;
6328 while (SUCCEEDED(hr = IMFTransform_GetOutputAvailableType(transform, 0, ++i, &media_type)))
6330 winetest_push_context("out %lu", i);
6331 ok(hr == S_OK, "GetOutputAvailableType returned %#lx\n", hr);
6332 check_media_type(media_type, expect_available_outputs[i], -1);
6333 ret = IMFMediaType_Release(media_type);
6334 ok(ret == 0, "Release returned %lu\n", ret);
6335 winetest_pop_context();
6337 ok(hr == MF_E_NO_MORE_TYPES, "GetOutputAvailableType returned %#lx\n", hr);
6338 ok(i == 2, "%lu output media types\n", i);
6340 /* check required output media type attributes */
6342 hr = MFCreateMediaType(&media_type);
6343 ok(hr == S_OK, "MFCreateMediaType returned %#lx\n", hr);
6344 hr = IMFTransform_SetOutputType(transform, 0, media_type, 0);
6345 ok(hr == MF_E_ATTRIBUTENOTFOUND, "SetOutputType returned %#lx.\n", hr);
6346 init_media_type(media_type, output_type_desc, 1);
6347 hr = IMFTransform_SetOutputType(transform, 0, media_type, 0);
6348 ok(hr == MF_E_ATTRIBUTENOTFOUND, "SetOutputType returned %#lx.\n", hr);
6349 init_media_type(media_type, output_type_desc, 2);
6350 for (i = 2; i < ARRAY_SIZE(output_type_desc) - 1; ++i)
6352 hr = IMFTransform_SetOutputType(transform, 0, media_type, 0);
6353 ok(hr == MF_E_INVALIDMEDIATYPE, "SetOutputType returned %#lx.\n", hr);
6354 init_media_type(media_type, output_type_desc, i + 1);
6356 hr = IMFTransform_SetOutputType(transform, 0, media_type, 0);
6357 ok(hr == S_OK, "SetOutputType returned %#lx.\n", hr);
6358 ret = IMFMediaType_Release(media_type);
6359 ok(ret == 0, "Release returned %lu\n", ret);
6361 memset(&input_info, 0xcd, sizeof(input_info));
6362 hr = IMFTransform_GetInputStreamInfo(transform, 0, &input_info);
6363 ok(hr == S_OK, "GetInputStreamInfo returned %#lx\n", hr);
6364 ok(input_info.hnsMaxLatency == 0, "got hnsMaxLatency %s\n", wine_dbgstr_longlong(input_info.hnsMaxLatency));
6365 ok(input_info.dwFlags == 0, "got dwFlags %#lx\n", input_info.dwFlags);
6366 ok(input_info.cbSize == wmaenc_block_size, "got cbSize %lu\n", input_info.cbSize);
6367 ok(input_info.cbMaxLookahead == 0, "got cbMaxLookahead %#lx\n", input_info.cbMaxLookahead);
6368 ok(input_info.cbAlignment == 1, "got cbAlignment %#lx\n", input_info.cbAlignment);
6370 memset(&output_info, 0xcd, sizeof(output_info));
6371 hr = IMFTransform_GetOutputStreamInfo(transform, 0, &output_info);
6372 ok(hr == S_OK, "GetOutputStreamInfo returned %#lx\n", hr);
6373 ok(output_info.dwFlags == 0, "got dwFlags %#lx\n", output_info.dwFlags);
6374 todo_wine
6375 ok(output_info.cbSize == 0, "got cbSize %#lx\n", output_info.cbSize);
6376 ok(output_info.cbAlignment == 1, "got cbAlignment %#lx\n", output_info.cbAlignment);
6378 /* MF_MT_AUDIO_AVG_BYTES_PER_SECOND isn't required by SetInputType, but is needed for the transform to work */
6380 hr = MFCreateMediaType(&media_type);
6381 ok(hr == S_OK, "MFCreateMediaType returned %#lx\n", hr);
6382 init_media_type(media_type, input_type_desc, -1);
6383 hr = IMFMediaType_SetUINT32(media_type, &MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 4003);
6384 ok(hr == S_OK, "SetUINT32 returned %#lx\n", hr);
6385 hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
6386 ok(hr == S_OK, "SetInputType returned %#lx.\n", hr);
6388 hr = IMFTransform_GetOutputStreamInfo(transform, 0, &output_info);
6389 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "GetOutputStreamInfo returned %#lx\n", hr);
6391 init_media_type(media_type, output_type_desc, -1);
6392 hr = IMFTransform_SetOutputType(transform, 0, media_type, 0);
6393 ok(hr == S_OK, "SetInputType returned %#lx.\n", hr);
6394 ret = IMFMediaType_Release(media_type);
6395 ok(ret == 0, "Release returned %lu\n", ret);
6397 memset(&output_info, 0xcd, sizeof(output_info));
6398 hr = IMFTransform_GetOutputStreamInfo(transform, 0, &output_info);
6399 ok(hr == S_OK, "GetOutputStreamInfo returned %#lx\n", hr);
6400 ok(output_info.dwFlags == 0, "got dwFlags %#lx\n", output_info.dwFlags);
6401 ok(output_info.cbSize == wmadec_block_size, "got cbSize %#lx\n", output_info.cbSize);
6402 ok(output_info.cbAlignment == 1, "got cbAlignment %#lx\n", output_info.cbAlignment);
6404 resource = FindResourceW(NULL, L"wmaencdata.bin", (const WCHAR *)RT_RCDATA);
6405 ok(resource != 0, "FindResourceW failed, error %lu\n", GetLastError());
6406 wmaenc_data = LockResource(LoadResource(GetModuleHandleW(NULL), resource));
6407 wmaenc_data_len = SizeofResource(GetModuleHandleW(NULL), resource);
6408 ok(wmaenc_data_len % wmaenc_block_size == 0, "got length %lu\n", wmaenc_data_len);
6410 sample = create_sample(wmaenc_data, wmaenc_block_size / 2);
6411 hr = IMFTransform_ProcessInput(transform, 0, sample, 0);
6412 ok(hr == S_OK, "ProcessInput returned %#lx\n", hr);
6413 ret = IMFSample_Release(sample);
6414 ok(ret == 0, "Release returned %lu\n", ret);
6415 sample = create_sample(wmaenc_data, wmaenc_block_size + 1);
6416 hr = IMFTransform_ProcessInput(transform, 0, sample, 0);
6417 ok(hr == S_OK, "ProcessInput returned %#lx\n", hr);
6418 ret = IMFSample_Release(sample);
6419 ok(ret == 0, "Release returned %lu\n", ret);
6420 sample = create_sample(wmaenc_data, wmaenc_block_size);
6421 hr = IMFTransform_ProcessInput(transform, 0, sample, 0);
6422 ok(hr == S_OK, "ProcessInput returned %#lx\n", hr);
6423 hr = IMFTransform_ProcessInput(transform, 0, sample, 0);
6424 ok(hr == MF_E_NOTACCEPTING, "ProcessInput returned %#lx\n", hr);
6425 ret = IMFSample_Release(sample);
6426 ok(ret == 1, "Release returned %lu\n", ret);
6428 /* As output_info.dwFlags doesn't have MFT_OUTPUT_STREAM_CAN_PROVIDE_SAMPLES
6429 * IMFTransform_ProcessOutput needs a sample or returns MF_E_TRANSFORM_NEED_MORE_INPUT */
6431 status = 0xdeadbeef;
6432 memset(&output, 0, sizeof(output));
6433 hr = IMFTransform_ProcessOutput(transform, 0, 1, &output, &status);
6434 ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "ProcessOutput returned %#lx\n", hr);
6435 ok(output.dwStreamID == 0, "got dwStreamID %lu\n", output.dwStreamID);
6436 ok(!output.pSample, "got pSample %p\n", output.pSample);
6437 ok(output.dwStatus == MFT_OUTPUT_DATA_BUFFER_NO_SAMPLE ||
6438 broken(output.dwStatus == (MFT_OUTPUT_DATA_BUFFER_INCOMPLETE|MFT_OUTPUT_DATA_BUFFER_NO_SAMPLE)) /* Win7 */,
6439 "got dwStatus %#lx\n", output.dwStatus);
6440 ok(!output.pEvents, "got pEvents %p\n", output.pEvents);
6441 ok(status == 0, "got status %#lx\n", status);
6443 sample = create_sample(wmaenc_data, wmaenc_block_size);
6444 hr = IMFTransform_ProcessInput(transform, 0, sample, 0);
6445 ok(hr == MF_E_NOTACCEPTING, "ProcessInput returned %#lx\n", hr);
6446 ret = IMFSample_Release(sample);
6447 ok(ret == 0, "Release returned %lu\n", ret);
6449 status = 0xdeadbeef;
6450 memset(&output, 0, sizeof(output));
6451 hr = IMFTransform_ProcessOutput(transform, 0, 1, &output, &status);
6452 ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "ProcessOutput returned %#lx\n", hr);
6453 ok(!output.pSample, "got pSample %p\n", output.pSample);
6454 ok(output.dwStatus == MFT_OUTPUT_DATA_BUFFER_NO_SAMPLE ||
6455 broken(output.dwStatus == (MFT_OUTPUT_DATA_BUFFER_INCOMPLETE|MFT_OUTPUT_DATA_BUFFER_NO_SAMPLE)) /* Win7 */,
6456 "got dwStatus %#lx\n", output.dwStatus);
6457 ok(status == 0, "got status %#lx\n", status);
6459 status = 0xdeadbeef;
6460 memset(&output, 0, sizeof(output));
6461 output_info.cbSize = wmadec_block_size;
6462 sample = create_sample(NULL, output_info.cbSize);
6463 outputs[0].pSample = sample;
6464 sample = create_sample(NULL, output_info.cbSize);
6465 outputs[1].pSample = sample;
6466 hr = IMFTransform_ProcessOutput(transform, 0, 2, outputs, &status);
6467 ok(hr == E_INVALIDARG, "ProcessOutput returned %#lx\n", hr);
6468 IMFSample_Release(outputs[0].pSample);
6469 IMFSample_Release(outputs[1].pSample);
6471 resource = FindResourceW(NULL, L"wmadecdata.bin", (const WCHAR *)RT_RCDATA);
6472 ok(resource != 0, "FindResourceW failed, error %lu\n", GetLastError());
6473 wmadec_data = LockResource(LoadResource(GetModuleHandleW(NULL), resource));
6474 wmadec_data_len = SizeofResource(GetModuleHandleW(NULL), resource);
6475 ok(wmadec_data_len == wmadec_block_size * 7 / 2, "got length %lu\n", wmadec_data_len);
6477 /* and generate a new one as well in a temporary directory */
6478 GetTempPathW(ARRAY_SIZE(output_path), output_path);
6479 lstrcatW(output_path, L"wmadecdata.bin");
6480 output_file = CreateFileW(output_path, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0);
6481 ok(output_file != INVALID_HANDLE_VALUE, "CreateFileW failed, error %lu\n", GetLastError());
6483 status = 0xdeadbeef;
6484 output_info.cbSize = wmadec_block_size;
6485 sample = create_sample(NULL, output_info.cbSize);
6486 memset(&output, 0, sizeof(output));
6487 output.pSample = sample;
6488 hr = IMFTransform_ProcessOutput(transform, 0, 1, &output, &status);
6490 for (i = 0; i < 4; ++i)
6492 winetest_push_context("%lu", i);
6494 ok(hr == S_OK, "ProcessOutput returned %#lx\n", hr);
6495 ok(output.pSample == sample, "got pSample %p\n", output.pSample);
6496 ok(output.dwStatus == MFT_OUTPUT_DATA_BUFFER_INCOMPLETE || output.dwStatus == 0 ||
6497 broken(output.dwStatus == (MFT_OUTPUT_DATA_BUFFER_INCOMPLETE|7) || output.dwStatus == 7) /* Win7 */,
6498 "got dwStatus %#lx\n", output.dwStatus);
6499 ok(status == 0, "got status %#lx\n", status);
6500 value = 0xdeadbeef;
6501 hr = IMFSample_GetUINT32(sample, &MFSampleExtension_CleanPoint, &value);
6502 ok(hr == S_OK, "GetUINT32 MFSampleExtension_CleanPoint returned %#lx\n", hr);
6503 ok(value == 1, "got MFSampleExtension_CleanPoint %u\n", value);
6504 hr = IMFSample_GetTotalLength(sample, &length);
6505 ok(hr == S_OK, "GetTotalLength returned %#lx\n", hr);
6506 flags = 0xdeadbeef;
6507 hr = IMFSample_GetSampleFlags(sample, &flags);
6508 ok(hr == S_OK, "GetSampleFlags returned %#lx\n", hr);
6509 ok(flags == 0, "got flags %#lx\n", flags);
6510 time = 0xdeadbeef;
6511 hr = IMFSample_GetSampleTime(sample, &time);
6512 ok(hr == S_OK, "GetSampleTime returned %#lx\n", hr);
6513 ok(time == i * 928798, "got time %I64d\n", time);
6514 duration = 0xdeadbeef;
6515 hr = IMFSample_GetSampleDuration(sample, &duration);
6516 ok(hr == S_OK, "GetSampleDuration returned %#lx\n", hr);
6517 if (output.dwStatus == MFT_OUTPUT_DATA_BUFFER_INCOMPLETE ||
6518 broken(output.dwStatus == (MFT_OUTPUT_DATA_BUFFER_INCOMPLETE|7)))
6520 ok(length == wmadec_block_size, "got length %lu\n", length);
6521 ok(duration == 928798, "got duration %I64d\n", duration);
6522 check_sample_pcm16(sample, wmadec_data, output_file, TRUE);
6523 wmadec_data += wmadec_block_size;
6524 wmadec_data_len -= wmadec_block_size;
6526 else
6528 /* FFmpeg doesn't seem to decode WMA buffers in the same way as native */
6529 todo_wine
6530 ok(length == wmadec_block_size / 2, "got length %lu\n", length);
6531 todo_wine
6532 ok(duration == 464399, "got duration %I64d\n", duration);
6534 if (length == wmadec_block_size / 2)
6535 check_sample_pcm16(sample, wmadec_data, output_file, FALSE);
6536 wmadec_data += length;
6537 wmadec_data_len -= length;
6539 ret = IMFSample_Release(sample);
6540 ok(ret == 0, "Release returned %lu\n", ret);
6542 status = 0xdeadbeef;
6543 sample = create_sample(NULL, output_info.cbSize);
6544 memset(&output, 0, sizeof(output));
6545 output.pSample = sample;
6546 hr = IMFTransform_ProcessOutput(transform, 0, 1, &output, &status);
6548 winetest_pop_context();
6550 todo_wine
6551 ok(wmadec_data_len == 0, "missing %#lx bytes\n", wmadec_data_len);
6553 trace("created %s\n", debugstr_w(output_path));
6554 CloseHandle(output_file);
6556 ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "ProcessOutput returned %#lx\n", hr);
6557 ok(output.pSample == sample, "got pSample %p\n", output.pSample);
6558 ok(output.dwStatus == 0, "got dwStatus %#lx\n", output.dwStatus);
6559 ok(status == 0, "got status %#lx\n", status);
6560 ret = IMFSample_Release(sample);
6561 ok(ret == 0, "Release returned %lu\n", ret);
6563 status = 0xdeadbeef;
6564 sample = create_sample(NULL, output_info.cbSize);
6565 memset(&output, 0, sizeof(output));
6566 output.pSample = sample;
6567 hr = IMFTransform_ProcessOutput(transform, 0, 1, &output, &status);
6568 ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "ProcessOutput returned %#lx\n", hr);
6569 ok(output.pSample == sample, "got pSample %p\n", output.pSample);
6570 ok(output.dwStatus == 0 ||
6571 broken(output.dwStatus == (MFT_OUTPUT_DATA_BUFFER_INCOMPLETE|7)) /* Win7 */,
6572 "got dwStatus %#lx\n", output.dwStatus);
6573 ok(status == 0, "got status %#lx\n", status);
6574 hr = IMFSample_GetTotalLength(sample, &length);
6575 ok(hr == S_OK, "GetTotalLength returned %#lx\n", hr);
6576 ok(length == 0, "got length %lu\n", length);
6577 ret = IMFSample_Release(sample);
6578 ok(ret == 0, "Release returned %lu\n", ret);
6580 sample = create_sample(wmaenc_data, wmaenc_block_size);
6581 hr = IMFTransform_ProcessInput(transform, 0, sample, 0);
6582 ok(hr == S_OK, "ProcessInput returned %#lx\n", hr);
6584 ret = IMFTransform_Release(transform);
6585 ok(ret == 0, "Release returned %lu\n", ret);
6586 ret = IMFSample_Release(sample);
6587 ok(ret == 0, "Release returned %lu\n", ret);
6589 hr = CoCreateInstance( &CLSID_CWMADecMediaObject, &outer, CLSCTX_INPROC_SERVER, &IID_IUnknown,
6590 (void **)&unknown );
6591 ok( hr == S_OK, "CoCreateInstance returned %#lx\n", hr );
6592 hr = IUnknown_QueryInterface( unknown, &IID_IMFTransform, (void **)&transform );
6593 ok( hr == S_OK, "QueryInterface returned %#lx\n", hr );
6594 hr = IUnknown_QueryInterface( unknown, &IID_IMediaObject, (void **)&media_object );
6595 ok( hr == S_OK, "QueryInterface returned %#lx\n", hr );
6596 hr = IUnknown_QueryInterface( unknown, &IID_IPropertyBag, (void **)&property_bag );
6597 ok( hr == S_OK, "QueryInterface returned %#lx\n", hr );
6598 hr = IUnknown_QueryInterface( media_object, &IID_IUnknown, (void **)&tmp_unknown );
6599 ok( hr == S_OK, "QueryInterface returned %#lx\n", hr );
6601 ok( unknown != &outer, "got outer IUnknown\n" );
6602 ok( transform != (void *)unknown, "got IUnknown == IMFTransform\n" );
6603 ok( media_object != (void *)unknown, "got IUnknown == IMediaObject\n" );
6604 ok( property_bag != (void *)unknown, "got IUnknown == IPropertyBag\n" );
6605 ok( tmp_unknown != unknown, "got inner IUnknown\n" );
6607 check_interface( unknown, &IID_IPersistPropertyBag, FALSE );
6608 check_interface( unknown, &IID_IAMFilterMiscFlags, FALSE );
6609 check_interface( unknown, &IID_IMediaSeeking, FALSE );
6610 check_interface( unknown, &IID_IMediaPosition, FALSE );
6611 check_interface( unknown, &IID_IReferenceClock, FALSE );
6612 check_interface( unknown, &IID_IBasicAudio, FALSE );
6614 ref = IUnknown_Release( tmp_unknown );
6615 ok( ref == 1, "Release returned %lu\n", ref );
6616 ref = IPropertyBag_Release( property_bag );
6617 ok( ref == 1, "Release returned %lu\n", ref );
6618 ref = IMediaObject_Release( media_object );
6619 ok( ref == 1, "Release returned %lu\n", ref );
6620 ref = IMFTransform_Release( transform );
6621 ok( ref == 1, "Release returned %lu\n", ref );
6622 ref = IUnknown_Release( unknown );
6623 ok( ref == 0, "Release returned %lu\n", ref );
6625 failed:
6626 CoUninitialize();
6629 #define next_h264_sample(a, b) next_h264_sample_(__LINE__, a, b)
6630 static IMFSample *next_h264_sample_(int line, const BYTE **h264_buf, ULONG *h264_len)
6632 const BYTE *sample_data;
6634 ok_(__FILE__, line)(*h264_len > 4, "invalid h264 length\n");
6635 ok_(__FILE__, line)(*(UINT32 *)*h264_buf == 0x01000000, "invalid h264 buffer\n");
6636 sample_data = *h264_buf;
6638 (*h264_len) -= 4;
6639 (*h264_buf) += 4;
6641 while (*h264_len >= 4 && *(UINT32 *)*h264_buf != 0x01000000)
6643 (*h264_len)--;
6644 (*h264_buf)++;
6647 return create_sample(sample_data, *h264_buf - sample_data);
6650 static void test_h264_decoder(void)
6652 const GUID transform_inputs[] =
6654 MFVideoFormat_H264,
6655 MFVideoFormat_H264_ES,
6657 const GUID transform_outputs[] =
6659 MFVideoFormat_NV12,
6660 MFVideoFormat_YV12,
6661 MFVideoFormat_IYUV,
6662 MFVideoFormat_I420,
6663 MFVideoFormat_YUY2,
6665 static const media_type_desc default_inputs[] =
6668 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
6669 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_H264),
6672 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
6673 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_H264_ES),
6676 static const media_type_desc default_outputs[] =
6679 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
6680 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_NV12),
6681 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
6682 ATTR_RATIO(MF_MT_FRAME_RATE, 30000, 1001),
6683 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, 1920),
6684 ATTR_UINT32(MF_MT_INTERLACE_MODE, 7),
6685 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
6686 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
6689 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
6690 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_YV12),
6691 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
6692 ATTR_RATIO(MF_MT_FRAME_RATE, 30000, 1001),
6693 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, 1920),
6694 ATTR_UINT32(MF_MT_INTERLACE_MODE, 7),
6695 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
6696 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
6699 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
6700 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_IYUV),
6701 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
6702 ATTR_RATIO(MF_MT_FRAME_RATE, 30000, 1001),
6703 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, 1920),
6704 ATTR_UINT32(MF_MT_INTERLACE_MODE, 7),
6705 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
6706 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
6709 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
6710 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_I420),
6711 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
6712 ATTR_RATIO(MF_MT_FRAME_RATE, 30000, 1001),
6713 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, 1920),
6714 ATTR_UINT32(MF_MT_INTERLACE_MODE, 7),
6715 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
6716 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
6719 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
6720 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_YUY2),
6721 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
6722 ATTR_RATIO(MF_MT_FRAME_RATE, 30000, 1001),
6723 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, 3840),
6724 ATTR_UINT32(MF_MT_INTERLACE_MODE, 7),
6725 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
6726 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
6729 static const media_type_desc default_outputs_extra[] =
6732 ATTR_RATIO(MF_MT_FRAME_SIZE, 1920, 1080),
6733 ATTR_UINT32(MF_MT_SAMPLE_SIZE, 3110400),
6734 ATTR_UINT32(MF_MT_VIDEO_ROTATION, 0),
6737 ATTR_RATIO(MF_MT_FRAME_SIZE, 1920, 1080),
6738 ATTR_UINT32(MF_MT_SAMPLE_SIZE, 3110400),
6739 ATTR_UINT32(MF_MT_VIDEO_ROTATION, 0),
6742 ATTR_RATIO(MF_MT_FRAME_SIZE, 1920, 1080),
6743 ATTR_UINT32(MF_MT_SAMPLE_SIZE, 3110400),
6744 ATTR_UINT32(MF_MT_VIDEO_ROTATION, 0),
6747 ATTR_RATIO(MF_MT_FRAME_SIZE, 1920, 1080),
6748 ATTR_UINT32(MF_MT_SAMPLE_SIZE, 3110400),
6749 ATTR_UINT32(MF_MT_VIDEO_ROTATION, 0),
6752 ATTR_RATIO(MF_MT_FRAME_SIZE, 1920, 1080),
6753 ATTR_UINT32(MF_MT_SAMPLE_SIZE, 4147200),
6754 ATTR_UINT32(MF_MT_VIDEO_ROTATION, 0),
6757 static const media_type_desc default_outputs_win7[] =
6760 ATTR_RATIO(MF_MT_FRAME_SIZE, 1920, 1088),
6761 ATTR_UINT32(MF_MT_SAMPLE_SIZE, 3133440),
6764 ATTR_RATIO(MF_MT_FRAME_SIZE, 1920, 1088),
6765 ATTR_UINT32(MF_MT_SAMPLE_SIZE, 3133440),
6768 ATTR_RATIO(MF_MT_FRAME_SIZE, 1920, 1088),
6769 ATTR_UINT32(MF_MT_SAMPLE_SIZE, 3133440),
6772 ATTR_RATIO(MF_MT_FRAME_SIZE, 1920, 1088),
6773 ATTR_UINT32(MF_MT_SAMPLE_SIZE, 3133440),
6776 ATTR_RATIO(MF_MT_FRAME_SIZE, 1920, 1088),
6777 ATTR_UINT32(MF_MT_SAMPLE_SIZE, 4177920),
6780 static const struct attribute_desc input_type_desc[] =
6782 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
6783 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_H264),
6784 {0},
6786 static const struct attribute_desc minimal_output_type_desc[] =
6788 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
6789 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_NV12),
6790 ATTR_RATIO(MF_MT_FRAME_SIZE, 1920, 1080),
6791 {0},
6793 static const struct attribute_desc output_type_desc[] =
6795 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
6796 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_NV12),
6797 ATTR_RATIO(MF_MT_FRAME_SIZE, 1920, 1080),
6798 ATTR_RATIO(MF_MT_FRAME_RATE, 60000, 1000),
6799 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 2, 1),
6800 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, 3840),
6801 ATTR_UINT32(MF_MT_SAMPLE_SIZE, 3840 * 1080 * 3 / 2),
6802 ATTR_UINT32(MF_MT_VIDEO_ROTATION, 0),
6803 {0},
6805 static const struct attribute_desc output_type_desc_win7[] =
6807 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
6808 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_NV12),
6809 ATTR_RATIO(MF_MT_FRAME_SIZE, 1920, 1088),
6810 ATTR_RATIO(MF_MT_FRAME_RATE, 60000, 1000),
6811 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 2, 1),
6812 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, 3840),
6813 ATTR_UINT32(MF_MT_SAMPLE_SIZE, 3840 * 1088 * 3 / 2),
6814 ATTR_UINT32(MF_MT_VIDEO_ROTATION, 0),
6815 {0},
6817 static const struct attribute_desc new_output_type_desc[] =
6819 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
6820 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_I420),
6821 ATTR_RATIO(MF_MT_FRAME_SIZE, 96, 96),
6822 ATTR_RATIO(MF_MT_FRAME_RATE, 1, 1),
6823 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 2),
6824 {0},
6826 static const struct attribute_desc new_output_type_desc_win7[] =
6828 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
6829 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_I420),
6830 ATTR_RATIO(MF_MT_FRAME_SIZE, 96, 96),
6831 ATTR_RATIO(MF_MT_FRAME_RATE, 1, 1),
6832 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 2),
6833 {0},
6835 static const MFVideoArea actual_aperture = {.Area={82,84}};
6836 static const DWORD actual_width = 96, actual_height = 96;
6837 const media_type_desc actual_outputs[] =
6840 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
6841 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_NV12),
6842 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
6843 ATTR_RATIO(MF_MT_FRAME_RATE, 60000, 1000),
6844 ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height),
6845 ATTR_UINT32(MF_MT_SAMPLE_SIZE, actual_width * actual_height * 3 / 2),
6846 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, actual_width),
6847 /* ATTR_UINT32(MF_MT_VIDEO_ROTATION, 0), missing on Win7 */
6848 ATTR_UINT32(MF_MT_INTERLACE_MODE, 7),
6849 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
6850 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
6851 ATTR_BLOB(MF_MT_MINIMUM_DISPLAY_APERTURE, &actual_aperture, 16),
6854 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
6855 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_YV12),
6856 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
6857 ATTR_RATIO(MF_MT_FRAME_RATE, 60000, 1000),
6858 ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height),
6859 ATTR_UINT32(MF_MT_SAMPLE_SIZE, actual_width * actual_height * 3 / 2),
6860 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, actual_width),
6861 /* ATTR_UINT32(MF_MT_VIDEO_ROTATION, 0), missing on Win7 */
6862 ATTR_UINT32(MF_MT_INTERLACE_MODE, 7),
6863 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
6864 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
6865 ATTR_BLOB(MF_MT_MINIMUM_DISPLAY_APERTURE, &actual_aperture, 16),
6868 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
6869 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_IYUV),
6870 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
6871 ATTR_RATIO(MF_MT_FRAME_RATE, 60000, 1000),
6872 ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height),
6873 ATTR_UINT32(MF_MT_SAMPLE_SIZE, actual_width * actual_height * 3 / 2),
6874 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, actual_width),
6875 /* ATTR_UINT32(MF_MT_VIDEO_ROTATION, 0), missing on Win7 */
6876 ATTR_UINT32(MF_MT_INTERLACE_MODE, 7),
6877 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
6878 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
6879 ATTR_BLOB(MF_MT_MINIMUM_DISPLAY_APERTURE, &actual_aperture, 16),
6882 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
6883 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_I420),
6884 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
6885 ATTR_RATIO(MF_MT_FRAME_RATE, 60000, 1000),
6886 ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height),
6887 ATTR_UINT32(MF_MT_SAMPLE_SIZE, actual_width * actual_height * 3 / 2),
6888 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, actual_width),
6889 /* ATTR_UINT32(MF_MT_VIDEO_ROTATION, 0), missing on Win7 */
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),
6893 ATTR_BLOB(MF_MT_MINIMUM_DISPLAY_APERTURE, &actual_aperture, 16),
6896 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
6897 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_YUY2),
6898 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
6899 ATTR_RATIO(MF_MT_FRAME_RATE, 60000, 1000),
6900 ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height),
6901 ATTR_UINT32(MF_MT_SAMPLE_SIZE, actual_width * actual_height * 2),
6902 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, actual_width * 2),
6903 /* ATTR_UINT32(MF_MT_VIDEO_ROTATION, 0), missing on Win7 */
6904 ATTR_UINT32(MF_MT_INTERLACE_MODE, 7),
6905 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
6906 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
6907 ATTR_BLOB(MF_MT_MINIMUM_DISPLAY_APERTURE, &actual_aperture, 16),
6911 MFT_REGISTER_TYPE_INFO input_type = {MFMediaType_Video, MFVideoFormat_H264};
6912 MFT_REGISTER_TYPE_INFO output_type = {MFMediaType_Video, MFVideoFormat_NV12};
6913 const BYTE *h264_encoded_data, *nv12_frame_data, *i420_frame_data;
6914 ULONG h264_encoded_data_len, nv12_frame_len, i420_frame_len;
6915 DWORD input_id, output_id, input_count, output_count;
6916 MFT_OUTPUT_STREAM_INFO output_info;
6917 MFT_INPUT_STREAM_INFO input_info;
6918 MFT_OUTPUT_DATA_BUFFER output;
6919 IMFMediaBuffer *media_buffer;
6920 DWORD status, length, count;
6921 WCHAR output_path[MAX_PATH];
6922 IMFAttributes *attributes;
6923 IMFMediaType *media_type;
6924 LONGLONG time, duration;
6925 IMFTransform *transform;
6926 BOOL is_win7 = FALSE;
6927 ULONG i, ret, flags;
6928 HANDLE output_file;
6929 IMFSample *sample;
6930 HRSRC resource;
6931 GUID class_id;
6932 UINT32 value;
6933 BYTE *data;
6934 HRESULT hr;
6936 hr = CoInitialize(NULL);
6937 ok(hr == S_OK, "Failed to initialize, hr %#lx.\n", hr);
6939 if (!create_transform(MFT_CATEGORY_VIDEO_DECODER, &input_type, &output_type, L"Microsoft H264 Video Decoder MFT", &MFMediaType_Video,
6940 transform_inputs, ARRAY_SIZE(transform_inputs), transform_outputs, ARRAY_SIZE(transform_outputs),
6941 &transform, &CLSID_MSH264DecoderMFT, &class_id))
6942 goto failed;
6944 hr = IMFTransform_GetAttributes(transform, &attributes);
6945 ok(hr == S_OK, "GetAttributes returned %#lx\n", hr);
6946 hr = IMFAttributes_SetUINT32(attributes, &MF_LOW_LATENCY, 1);
6947 ok(hr == S_OK, "SetUINT32 returned %#lx\n", hr);
6948 IMFAttributes_Release(attributes);
6950 /* no output type is available before an input type is set */
6952 hr = IMFTransform_GetOutputAvailableType(transform, 0, 0, &media_type);
6953 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "GetOutputAvailableType returned %#lx\n", hr);
6954 hr = IMFTransform_GetOutputCurrentType(transform, 0, &media_type);
6955 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "GetOutputCurrentType returned %#lx\n", hr);
6957 /* setting output media type first doesn't work */
6959 hr = MFCreateMediaType(&media_type);
6960 ok(hr == S_OK, "MFCreateMediaType returned %#lx\n", hr);
6961 init_media_type(media_type, default_outputs[0], -1);
6962 hr = IMFTransform_SetOutputType(transform, 0, media_type, 0);
6963 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "SetOutputType returned %#lx.\n", hr);
6964 ret = IMFMediaType_Release(media_type);
6965 ok(ret == 0, "Release returned %lu\n", ret);
6967 /* check available input types */
6969 flags = MFT_INPUT_STREAM_WHOLE_SAMPLES | MFT_INPUT_STREAM_SINGLE_SAMPLE_PER_BUFFER | MFT_INPUT_STREAM_FIXED_SAMPLE_SIZE;
6970 memset(&input_info, 0xcd, sizeof(input_info));
6971 hr = IMFTransform_GetInputStreamInfo(transform, 0, &input_info);
6972 todo_wine
6973 ok(hr == S_OK, "GetInputStreamInfo returned %#lx\n", hr);
6974 todo_wine
6975 ok(input_info.hnsMaxLatency == 0, "got hnsMaxLatency %s\n", wine_dbgstr_longlong(input_info.hnsMaxLatency));
6976 todo_wine
6977 ok(input_info.dwFlags == flags, "got dwFlags %#lx\n", input_info.dwFlags);
6978 todo_wine
6979 ok(input_info.cbSize == 0x1000, "got cbSize %lu\n", input_info.cbSize);
6980 todo_wine
6981 ok(input_info.cbMaxLookahead == 0, "got cbMaxLookahead %#lx\n", input_info.cbMaxLookahead);
6982 todo_wine
6983 ok(input_info.cbAlignment == 0, "got cbAlignment %#lx\n", input_info.cbAlignment);
6985 flags = MFT_OUTPUT_STREAM_WHOLE_SAMPLES | MFT_OUTPUT_STREAM_SINGLE_SAMPLE_PER_BUFFER | MFT_OUTPUT_STREAM_FIXED_SAMPLE_SIZE;
6986 memset(&output_info, 0xcd, sizeof(output_info));
6987 hr = IMFTransform_GetOutputStreamInfo(transform, 0, &output_info);
6988 ok(hr == S_OK, "GetOutputStreamInfo returned %#lx\n", hr);
6989 ok(output_info.dwFlags == flags, "got dwFlags %#lx\n", output_info.dwFlags);
6990 ok(output_info.cbSize == 1920 * 1088 * 2, "got cbSize %#lx\n", output_info.cbSize);
6991 ok(output_info.cbAlignment == 0, "got cbAlignment %#lx\n", output_info.cbAlignment);
6993 i = -1;
6994 while (SUCCEEDED(hr = IMFTransform_GetInputAvailableType(transform, 0, ++i, &media_type)))
6996 winetest_push_context("in %lu", i);
6997 ok(hr == S_OK, "GetInputAvailableType returned %#lx\n", hr);
6998 check_media_type(media_type, default_inputs[i], -1);
6999 ret = IMFMediaType_Release(media_type);
7000 ok(ret == 0, "Release returned %lu\n", ret);
7001 winetest_pop_context();
7003 ok(hr == MF_E_NO_MORE_TYPES, "GetInputAvailableType returned %#lx\n", hr);
7004 ok(i == 2 || broken(i == 1) /* Win7 */, "%lu input media types\n", i);
7006 /* check required input media type attributes */
7008 hr = MFCreateMediaType(&media_type);
7009 ok(hr == S_OK, "MFCreateMediaType returned %#lx\n", hr);
7010 hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
7011 ok(hr == E_INVALIDARG, "SetInputType returned %#lx.\n", hr);
7012 init_media_type(media_type, input_type_desc, 1);
7013 hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
7014 todo_wine
7015 ok(hr == MF_E_INVALIDMEDIATYPE, "SetInputType returned %#lx.\n", hr);
7016 init_media_type(media_type, input_type_desc, 2);
7017 hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
7018 ok(hr == S_OK, "SetInputType returned %#lx.\n", hr);
7019 ret = IMFMediaType_Release(media_type);
7020 ok(ret == 1, "Release returned %lu\n", ret);
7022 flags = MFT_OUTPUT_STREAM_WHOLE_SAMPLES | MFT_OUTPUT_STREAM_SINGLE_SAMPLE_PER_BUFFER | MFT_OUTPUT_STREAM_FIXED_SAMPLE_SIZE;
7023 memset(&output_info, 0xcd, sizeof(output_info));
7024 hr = IMFTransform_GetOutputStreamInfo(transform, 0, &output_info);
7025 ok(hr == S_OK, "GetOutputStreamInfo returned %#lx\n", hr);
7026 ok(output_info.dwFlags == flags, "got dwFlags %#lx\n", output_info.dwFlags);
7027 todo_wine
7028 ok(output_info.cbSize == 1920 * 1080 * 2 || broken(output_info.cbSize == 1920 * 1088 * 2) /* Win7 */,
7029 "got cbSize %#lx\n", output_info.cbSize);
7030 ok(output_info.cbAlignment == 0, "got cbAlignment %#lx\n", output_info.cbAlignment);
7032 /* output types can now be enumerated (though they are actually the same for all input types) */
7034 i = -1;
7035 while (SUCCEEDED(hr = IMFTransform_GetOutputAvailableType(transform, 0, ++i, &media_type)))
7037 winetest_push_context("out %lu", i);
7038 ok(hr == S_OK, "GetOutputAvailableType returned %#lx\n", hr);
7039 check_media_type(media_type, default_outputs[i], -1);
7040 hr = IMFMediaType_GetItem(media_type, &MF_MT_VIDEO_ROTATION, NULL);
7041 is_win7 = broken(FAILED(hr));
7042 check_media_type(media_type, is_win7 ? default_outputs_win7[i] : default_outputs_extra[i], -1);
7043 ret = IMFMediaType_Release(media_type);
7044 ok(ret == 0, "Release returned %lu\n", ret);
7045 winetest_pop_context();
7047 ok(hr == MF_E_NO_MORE_TYPES, "GetOutputAvailableType returned %#lx\n", hr);
7048 ok(i == 5, "%lu output media types\n", i);
7050 /* check required output media type attributes */
7052 hr = MFCreateMediaType(&media_type);
7053 ok(hr == S_OK, "MFCreateMediaType returned %#lx\n", hr);
7054 hr = IMFTransform_SetOutputType(transform, 0, media_type, 0);
7055 todo_wine
7056 ok(hr == E_INVALIDARG, "SetOutputType returned %#lx.\n", hr);
7057 init_media_type(media_type, minimal_output_type_desc, 1);
7058 hr = IMFTransform_SetOutputType(transform, 0, media_type, 0);
7059 todo_wine
7060 ok(hr == MF_E_INVALIDMEDIATYPE, "SetOutputType returned %#lx.\n", hr);
7061 init_media_type(media_type, minimal_output_type_desc, 2);
7062 for (i = 2; i < ARRAY_SIZE(minimal_output_type_desc) - 1; ++i)
7064 hr = IMFTransform_SetOutputType(transform, 0, media_type, 0);
7065 todo_wine
7066 ok(hr == MF_E_ATTRIBUTENOTFOUND, "SetOutputType returned %#lx.\n", hr);
7067 init_media_type(media_type, minimal_output_type_desc, i + 1);
7069 hr = IMFTransform_SetOutputType(transform, 0, media_type, 0);
7070 ok(hr == (is_win7 ? MF_E_INVALIDMEDIATYPE : S_OK), "SetOutputType returned %#lx.\n", hr);
7071 init_media_type(media_type, is_win7 ? output_type_desc_win7 : output_type_desc, -1);
7072 hr = IMFTransform_SetOutputType(transform, 0, media_type, 0);
7073 ok(hr == S_OK, "SetOutputType returned %#lx.\n", hr);
7074 ret = IMFMediaType_Release(media_type);
7075 ok(ret == 1, "Release returned %lu\n", ret);
7077 hr = IMFTransform_GetOutputCurrentType(transform, 0, &media_type);
7078 ok(hr == S_OK, "GetOutputCurrentType returned %#lx\n", hr);
7079 check_media_type(media_type, is_win7 ? output_type_desc_win7 : output_type_desc, -1);
7080 ret = IMFMediaType_Release(media_type);
7081 ok(ret == 0, "Release returned %lu\n", ret);
7083 /* check that the output media type we've selected don't change the enumeration */
7085 i = -1;
7086 while (SUCCEEDED(hr = IMFTransform_GetOutputAvailableType(transform, 0, ++i, &media_type)))
7088 winetest_push_context("out %lu", i);
7089 ok(hr == S_OK, "GetOutputAvailableType returned %#lx\n", hr);
7090 check_media_type(media_type, default_outputs[i], -1);
7091 check_media_type(media_type, is_win7 ? default_outputs_win7[i] : default_outputs_extra[i], -1);
7092 ret = IMFMediaType_Release(media_type);
7093 ok(ret == 0, "Release returned %lu\n", ret);
7094 winetest_pop_context();
7096 ok(hr == MF_E_NO_MORE_TYPES, "GetOutputAvailableType returned %#lx\n", hr);
7097 ok(i == 5, "%lu output media types\n", i);
7099 flags = MFT_INPUT_STREAM_WHOLE_SAMPLES | MFT_INPUT_STREAM_SINGLE_SAMPLE_PER_BUFFER | MFT_INPUT_STREAM_FIXED_SAMPLE_SIZE;
7100 memset(&input_info, 0xcd, sizeof(input_info));
7101 hr = IMFTransform_GetInputStreamInfo(transform, 0, &input_info);
7102 ok(hr == S_OK, "GetInputStreamInfo returned %#lx\n", hr);
7103 ok(input_info.hnsMaxLatency == 0, "got hnsMaxLatency %s\n", wine_dbgstr_longlong(input_info.hnsMaxLatency));
7104 ok(input_info.dwFlags == flags, "got dwFlags %#lx\n", input_info.dwFlags);
7105 ok(input_info.cbSize == 0x1000, "got cbSize %lu\n", input_info.cbSize);
7106 ok(input_info.cbMaxLookahead == 0, "got cbMaxLookahead %#lx\n", input_info.cbMaxLookahead);
7107 ok(input_info.cbAlignment == 0, "got cbAlignment %#lx\n", input_info.cbAlignment);
7109 flags = MFT_OUTPUT_STREAM_WHOLE_SAMPLES | MFT_OUTPUT_STREAM_SINGLE_SAMPLE_PER_BUFFER | MFT_OUTPUT_STREAM_FIXED_SAMPLE_SIZE;
7110 memset(&output_info, 0xcd, sizeof(output_info));
7111 hr = IMFTransform_GetOutputStreamInfo(transform, 0, &output_info);
7112 ok(hr == S_OK, "GetOutputStreamInfo returned %#lx\n", hr);
7113 ok(output_info.dwFlags == flags, "got dwFlags %#lx\n", output_info.dwFlags);
7114 todo_wine
7115 ok(output_info.cbSize == 1920 * 1080 * 2 || broken(output_info.cbSize == 1920 * 1088 * 2) /* Win7 */,
7116 "got cbSize %#lx\n", output_info.cbSize);
7117 ok(output_info.cbAlignment == 0, "got cbAlignment %#lx\n", output_info.cbAlignment);
7119 input_count = output_count = 0xdeadbeef;
7120 hr = IMFTransform_GetStreamCount(transform, &input_count, &output_count);
7121 todo_wine
7122 ok(hr == S_OK, "GetStreamCount returned %#lx\n", hr);
7123 todo_wine
7124 ok(input_count == 1, "got input_count %lu\n", input_count);
7125 todo_wine
7126 ok(output_count == 1, "got output_count %lu\n", output_count);
7127 hr = IMFTransform_GetStreamIDs(transform, 1, &input_id, 1, &output_id);
7128 ok(hr == E_NOTIMPL, "GetStreamIDs returned %#lx\n", hr);
7130 resource = FindResourceW(NULL, L"h264data.bin", (const WCHAR *)RT_RCDATA);
7131 ok(resource != 0, "FindResourceW failed, error %lu\n", GetLastError());
7132 h264_encoded_data = LockResource(LoadResource(GetModuleHandleW(NULL), resource));
7133 h264_encoded_data_len = SizeofResource(GetModuleHandleW(NULL), resource);
7135 /* As output_info.dwFlags doesn't have MFT_OUTPUT_STREAM_CAN_PROVIDE_SAMPLES
7136 * IMFTransform_ProcessOutput needs a sample or returns an error */
7138 status = 0;
7139 memset(&output, 0, sizeof(output));
7140 hr = IMFTransform_ProcessOutput(transform, 0, 1, &output, &status);
7141 ok(hr == E_INVALIDARG || hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "ProcessOutput returned %#lx\n", hr);
7142 ok(output.dwStreamID == 0, "got dwStreamID %lu\n", output.dwStreamID);
7143 ok(!output.pSample, "got pSample %p\n", output.pSample);
7144 ok(output.dwStatus == 0, "got dwStatus %#lx\n", output.dwStatus);
7145 ok(!output.pEvents, "got pEvents %p\n", output.pEvents);
7146 ok(status == 0, "got status %#lx\n", status);
7148 i = 0;
7149 sample = next_h264_sample(&h264_encoded_data, &h264_encoded_data_len);
7150 while (1)
7152 status = 0;
7153 memset(&output, 0, sizeof(output));
7154 output.pSample = create_sample(NULL, output_info.cbSize);
7155 hr = IMFTransform_ProcessOutput(transform, 0, 1, &output, &status);
7156 if (hr != MF_E_TRANSFORM_NEED_MORE_INPUT) break;
7157 ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "ProcessOutput returned %#lx\n", hr);
7158 ok(output.dwStreamID == 0, "got dwStreamID %lu\n", output.dwStreamID);
7159 ok(!!output.pSample, "got pSample %p\n", output.pSample);
7160 ok(output.dwStatus == 0, "got dwStatus %#lx\n", output.dwStatus);
7161 ok(!output.pEvents, "got pEvents %p\n", output.pEvents);
7162 ok(status == 0, "got status %#lx\n", status);
7163 hr = IMFSample_GetTotalLength(output.pSample, &length);
7164 ok(hr == S_OK, "GetTotalLength returned %#lx\n", hr);
7165 ok(length == 0, "got length %lu\n", length);
7166 ret = IMFSample_Release(output.pSample);
7167 ok(ret == 0, "Release returned %lu\n", ret);
7169 hr = IMFTransform_ProcessInput(transform, 0, sample, 0);
7170 ok(hr == S_OK, "ProcessInput returned %#lx\n", hr);
7171 ret = IMFSample_Release(sample);
7172 ok(ret <= 1, "Release returned %lu\n", ret);
7173 sample = next_h264_sample(&h264_encoded_data, &h264_encoded_data_len);
7175 hr = IMFTransform_ProcessInput(transform, 0, sample, 0);
7176 ok(hr == S_OK, "ProcessInput returned %#lx\n", hr);
7177 ret = IMFSample_Release(sample);
7178 ok(ret <= 1, "Release returned %lu\n", ret);
7179 sample = next_h264_sample(&h264_encoded_data, &h264_encoded_data_len);
7180 i++;
7182 hr = IMFTransform_ProcessMessage(transform, MFT_MESSAGE_COMMAND_DRAIN, 0);
7183 ok(hr == S_OK, "ProcessMessage returned %#lx\n", hr);
7185 todo_wine
7186 ok(i == 2, "got %lu iterations\n", i);
7187 todo_wine
7188 ok(h264_encoded_data_len == 1180, "got h264_encoded_data_len %lu\n", h264_encoded_data_len);
7189 ok(hr == MF_E_TRANSFORM_STREAM_CHANGE, "ProcessOutput returned %#lx\n", hr);
7190 ok(output.dwStreamID == 0, "got dwStreamID %lu\n", output.dwStreamID);
7191 ok(!!output.pSample, "got pSample %p\n", output.pSample);
7192 ok(output.dwStatus == MFT_OUTPUT_DATA_BUFFER_FORMAT_CHANGE,
7193 "got dwStatus %#lx\n", output.dwStatus);
7194 ok(!output.pEvents, "got pEvents %p\n", output.pEvents);
7195 ok(status == MFT_PROCESS_OUTPUT_STATUS_NEW_STREAMS,
7196 "got status %#lx\n", status);
7197 hr = IMFSample_GetTotalLength(output.pSample, &length);
7198 ok(hr == S_OK, "GetTotalLength returned %#lx\n", hr);
7199 ok(length == 0, "got length %lu\n", length);
7200 ret = IMFSample_Release(output.pSample);
7201 ok(ret == 0, "Release returned %lu\n", ret);
7203 flags = MFT_OUTPUT_STREAM_WHOLE_SAMPLES | MFT_OUTPUT_STREAM_SINGLE_SAMPLE_PER_BUFFER | MFT_OUTPUT_STREAM_FIXED_SAMPLE_SIZE;
7204 memset(&output_info, 0xcd, sizeof(output_info));
7205 hr = IMFTransform_GetOutputStreamInfo(transform, 0, &output_info);
7206 ok(hr == S_OK, "GetOutputStreamInfo returned %#lx\n", hr);
7207 ok(output_info.dwFlags == flags, "got dwFlags %#lx\n", output_info.dwFlags);
7208 ok(output_info.cbSize == actual_width * actual_height * 2, "got cbSize %#lx\n", output_info.cbSize);
7209 ok(output_info.cbAlignment == 0, "got cbAlignment %#lx\n", output_info.cbAlignment);
7211 i = -1;
7212 while (SUCCEEDED(hr = IMFTransform_GetOutputAvailableType(transform, 0, ++i, &media_type)))
7214 winetest_push_context("out %lu", i);
7215 ok(hr == S_OK, "GetOutputAvailableType returned %#lx\n", hr);
7216 check_media_type(media_type, actual_outputs[i], -1);
7217 ret = IMFMediaType_Release(media_type);
7218 ok(ret == 0, "Release returned %lu\n", ret);
7219 winetest_pop_context();
7221 ok(hr == MF_E_NO_MORE_TYPES, "GetOutputAvailableType returned %#lx\n", hr);
7222 ok(i == 5, "%lu output media types\n", i);
7224 /* current output type is still the one we selected */
7225 hr = IMFTransform_GetOutputCurrentType(transform, 0, &media_type);
7226 ok(hr == S_OK, "GetOutputCurrentType returned %#lx\n", hr);
7227 check_media_type(media_type, is_win7 ? output_type_desc_win7 : output_type_desc, -1);
7228 hr = IMFMediaType_GetItemType(media_type, &MF_MT_MINIMUM_DISPLAY_APERTURE, NULL);
7229 ok(hr == MF_E_ATTRIBUTENOTFOUND, "GetItemType returned %#lx\n", hr);
7230 ret = IMFMediaType_Release(media_type);
7231 ok(ret == 0, "Release returned %lu\n", ret);
7233 /* and generate a new one as well in a temporary directory */
7234 GetTempPathW(ARRAY_SIZE(output_path), output_path);
7235 lstrcatW(output_path, L"nv12frame.bin");
7236 output_file = CreateFileW(output_path, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0);
7237 ok(output_file != INVALID_HANDLE_VALUE, "CreateFileW failed, error %lu\n", GetLastError());
7239 resource = FindResourceW(NULL, L"nv12frame.bin", (const WCHAR *)RT_RCDATA);
7240 ok(resource != 0, "FindResourceW failed, error %lu\n", GetLastError());
7241 nv12_frame_data = LockResource(LoadResource(GetModuleHandleW(NULL), resource));
7242 nv12_frame_len = SizeofResource(GetModuleHandleW(NULL), resource);
7243 ok(nv12_frame_len == actual_width * actual_height * 3 / 2, "got frame length %lu\n", nv12_frame_len);
7245 status = 0;
7246 memset(&output, 0, sizeof(output));
7247 output.pSample = create_sample(NULL, actual_width * actual_height * 2);
7248 hr = IMFTransform_ProcessOutput(transform, 0, 1, &output, &status);
7249 ok(hr == S_OK, "ProcessOutput returned %#lx\n", hr);
7250 ok(output.dwStreamID == 0, "got dwStreamID %lu\n", output.dwStreamID);
7251 ok(!!output.pSample, "got pSample %p\n", output.pSample);
7252 ok(output.dwStatus == 0, "got dwStatus %#lx\n", output.dwStatus);
7253 ok(!output.pEvents, "got pEvents %p\n", output.pEvents);
7254 ok(status == 0, "got status %#lx\n", status);
7256 hr = IMFSample_GetUINT32(sample, &MFSampleExtension_CleanPoint, &value);
7257 ok(hr == MF_E_ATTRIBUTENOTFOUND, "GetUINT32 MFSampleExtension_CleanPoint returned %#lx\n", hr);
7259 count = 0xdeadbeef;
7260 hr = IMFSample_GetBufferCount(output.pSample, &count);
7261 ok(hr == S_OK, "GetBufferCount returned %#lx\n", hr);
7262 ok(count == 1, "got count %#lx\n", count);
7264 flags = 0xdeadbeef;
7265 hr = IMFSample_GetSampleFlags(output.pSample, &flags);
7266 ok(hr == S_OK, "GetSampleFlags returned %#lx\n", hr);
7267 ok(flags == 0, "got flags %#lx\n", flags);
7269 time = 0xdeadbeef;
7270 hr = IMFSample_GetSampleTime(output.pSample, &time);
7271 ok(hr == S_OK, "GetSampleTime returned %#lx\n", hr);
7272 ok(time == 0, "got time %I64d\n", time);
7274 /* doesn't matter what frame rate we've selected, duration is defined by the stream */
7275 duration = 0xdeadbeef;
7276 hr = IMFSample_GetSampleDuration(output.pSample, &duration);
7277 ok(hr == S_OK, "GetSampleDuration returned %#lx\n", hr);
7278 ok(duration - 333666 <= 2, "got duration %I64d\n", duration);
7280 /* Win8 and before pad the data with garbage instead of original
7281 * buffer data, make sure it's consistent. */
7282 hr = IMFSample_ConvertToContiguousBuffer(output.pSample, &media_buffer);
7283 ok(hr == S_OK, "ConvertToContiguousBuffer returned %#lx\n", hr);
7284 hr = IMFMediaBuffer_Lock(media_buffer, &data, NULL, &length);
7285 ok(hr == S_OK, "Lock returned %#lx\n", hr);
7286 ok(length == nv12_frame_len, "got length %lu\n", length);
7288 for (i = 0; i < actual_aperture.Area.cy; ++i)
7290 memset(data + actual_width * i + actual_aperture.Area.cx, 0xcd, actual_width - actual_aperture.Area.cx);
7291 memset(data + actual_width * (actual_height + i) + actual_aperture.Area.cx, 0xcd, actual_width - actual_aperture.Area.cx);
7293 memset(data + actual_width * actual_aperture.Area.cy, 0xcd, (actual_height - actual_aperture.Area.cy) * actual_width);
7294 memset(data + actual_width * (actual_height + actual_aperture.Area.cy / 2), 0xcd, (actual_height - actual_aperture.Area.cy) / 2 * actual_width);
7296 hr = IMFMediaBuffer_Unlock(media_buffer);
7297 ok(hr == S_OK, "Unlock returned %#lx\n", hr);
7298 IMFMediaBuffer_Release(media_buffer);
7300 check_sample(output.pSample, nv12_frame_data, output_file);
7302 ret = IMFSample_Release(output.pSample);
7303 ok(ret == 0, "Release returned %lu\n", ret);
7305 trace("created %s\n", debugstr_w(output_path));
7306 CloseHandle(output_file);
7308 /* we can change it, but only with the correct frame size */
7309 hr = MFCreateMediaType(&media_type);
7310 ok(hr == S_OK, "MFCreateMediaType returned %#lx\n", hr);
7311 init_media_type(media_type, is_win7 ? output_type_desc_win7 : output_type_desc, -1);
7312 hr = IMFTransform_SetOutputType(transform, 0, media_type, 0);
7313 ok(hr == MF_E_INVALIDMEDIATYPE, "SetOutputType returned %#lx.\n", hr);
7314 init_media_type(media_type, is_win7 ? new_output_type_desc_win7 : new_output_type_desc, -1);
7315 hr = IMFTransform_SetOutputType(transform, 0, media_type, 0);
7316 ok(hr == S_OK, "SetOutputType returned %#lx.\n", hr);
7317 ret = IMFMediaType_Release(media_type);
7318 ok(ret == 1, "Release returned %lu\n", ret);
7320 hr = IMFTransform_GetOutputCurrentType(transform, 0, &media_type);
7321 ok(hr == S_OK, "GetOutputCurrentType returned %#lx\n", hr);
7322 check_media_type(media_type, is_win7 ? new_output_type_desc_win7 : new_output_type_desc, -1);
7323 hr = IMFMediaType_GetItemType(media_type, &MF_MT_MINIMUM_DISPLAY_APERTURE, NULL);
7324 ok(hr == MF_E_ATTRIBUTENOTFOUND, "GetItemType returned %#lx\n", hr);
7325 ret = IMFMediaType_Release(media_type);
7326 ok(ret == 0, "Release returned %lu\n", ret);
7328 status = 0;
7329 memset(&output, 0, sizeof(output));
7330 output.pSample = create_sample(NULL, actual_width * actual_height * 2);
7331 hr = IMFTransform_ProcessOutput(transform, 0, 1, &output, &status);
7332 todo_wine
7333 ok(hr == MF_E_TRANSFORM_STREAM_CHANGE, "ProcessOutput returned %#lx\n", hr);
7335 if (hr == MF_E_TRANSFORM_NEED_MORE_INPUT)
7337 hr = IMFTransform_ProcessInput(transform, 0, sample, 0);
7338 ok(hr == S_OK, "ProcessInput returned %#lx\n", hr);
7339 ret = IMFSample_Release(sample);
7340 ok(ret <= 1, "Release returned %lu\n", ret);
7341 sample = next_h264_sample(&h264_encoded_data, &h264_encoded_data_len);
7342 hr = IMFTransform_ProcessOutput(transform, 0, 1, &output, &status);
7343 todo_wine
7344 ok(hr == MF_E_TRANSFORM_STREAM_CHANGE, "ProcessOutput returned %#lx\n", hr);
7347 ok(output.dwStreamID == 0, "got dwStreamID %lu\n", output.dwStreamID);
7348 ok(!!output.pSample, "got pSample %p\n", output.pSample);
7349 todo_wine
7350 ok(output.dwStatus == MFT_OUTPUT_DATA_BUFFER_FORMAT_CHANGE, "got dwStatus %#lx\n", output.dwStatus);
7351 ok(!output.pEvents, "got pEvents %p\n", output.pEvents);
7352 todo_wine
7353 ok(status == MFT_PROCESS_OUTPUT_STATUS_NEW_STREAMS, "got status %#lx\n", status);
7354 hr = IMFSample_GetTotalLength(output.pSample, &length);
7355 ok(hr == S_OK, "GetTotalLength returned %#lx\n", hr);
7356 ok(length == 0, "got length %lu\n", length);
7357 ret = IMFSample_Release(output.pSample);
7358 ok(ret == 0, "Release returned %lu\n", ret);
7360 GetTempPathW(ARRAY_SIZE(output_path), output_path);
7361 lstrcatW(output_path, L"i420frame.bin");
7362 output_file = CreateFileW(output_path, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0);
7363 ok(output_file != INVALID_HANDLE_VALUE, "CreateFileW failed, error %lu\n", GetLastError());
7365 resource = FindResourceW(NULL, L"i420frame.bin", (const WCHAR *)RT_RCDATA);
7366 ok(resource != 0, "FindResourceW failed, error %lu\n", GetLastError());
7367 i420_frame_data = LockResource(LoadResource(GetModuleHandleW(NULL), resource));
7368 i420_frame_len = SizeofResource(GetModuleHandleW(NULL), resource);
7369 ok(i420_frame_len == actual_width * actual_height * 3 / 2, "got frame length %lu\n", i420_frame_len);
7371 status = 0;
7372 memset(&output, 0, sizeof(output));
7373 output.pSample = create_sample(NULL, actual_width * actual_height * 2);
7374 hr = IMFTransform_ProcessOutput(transform, 0, 1, &output, &status);
7375 todo_wine
7376 ok(hr == S_OK, "ProcessOutput returned %#lx\n", hr);
7377 ok(output.dwStreamID == 0, "got dwStreamID %lu\n", output.dwStreamID);
7378 ok(!!output.pSample, "got pSample %p\n", output.pSample);
7379 ok(output.dwStatus == 0, "got dwStatus %#lx\n", output.dwStatus);
7380 ok(!output.pEvents, "got pEvents %p\n", output.pEvents);
7381 ok(status == 0, "got status %#lx\n", status);
7382 if (hr != S_OK) goto skip_i420_tests;
7384 hr = IMFSample_GetSampleTime(output.pSample, &time);
7385 ok(hr == S_OK, "GetSampleTime returned %#lx\n", hr);
7386 ok(time - 333666 <= 2, "got time %I64d\n", time);
7388 duration = 0xdeadbeef;
7389 hr = IMFSample_GetSampleDuration(output.pSample, &duration);
7390 ok(hr == S_OK, "GetSampleDuration returned %#lx\n", hr);
7391 ok(duration - 333666 <= 2, "got duration %I64d\n", duration);
7393 /* Win8 and before pad the data with garbage instead of original
7394 * buffer data, make sure it's consistent. */
7395 hr = IMFSample_ConvertToContiguousBuffer(output.pSample, &media_buffer);
7396 ok(hr == S_OK, "ConvertToContiguousBuffer returned %#lx\n", hr);
7397 hr = IMFMediaBuffer_Lock(media_buffer, &data, NULL, &length);
7398 ok(hr == S_OK, "Lock returned %#lx\n", hr);
7399 ok(length == i420_frame_len, "got length %lu\n", length);
7401 for (i = 0; i < actual_aperture.Area.cy; ++i)
7403 memset(data + actual_width * i + actual_aperture.Area.cx, 0xcd, actual_width - actual_aperture.Area.cx);
7404 memset(data + actual_width * actual_height + actual_width / 2 * i + actual_aperture.Area.cx / 2, 0xcd,
7405 actual_width / 2 - actual_aperture.Area.cx / 2);
7406 memset(data + actual_width * actual_height + actual_width / 2 * (actual_height / 2 + i) + actual_aperture.Area.cx / 2, 0xcd,
7407 actual_width / 2 - actual_aperture.Area.cx / 2);
7409 memset(data + actual_width * actual_aperture.Area.cy, 0xcd, (actual_height - actual_aperture.Area.cy) * actual_width);
7410 memset(data + actual_width * actual_height + actual_width / 2 * actual_aperture.Area.cy / 2, 0xcd,
7411 (actual_height - actual_aperture.Area.cy) / 2 * actual_width / 2);
7412 memset(data + actual_width * actual_height + actual_width / 2 * (actual_height / 2 + actual_aperture.Area.cy / 2), 0xcd,
7413 (actual_height - actual_aperture.Area.cy) / 2 * actual_width / 2);
7415 hr = IMFMediaBuffer_Unlock(media_buffer);
7416 ok(hr == S_OK, "Unlock returned %#lx\n", hr);
7417 IMFMediaBuffer_Release(media_buffer);
7419 check_sample(output.pSample, i420_frame_data, output_file);
7421 skip_i420_tests:
7422 ret = IMFSample_Release(output.pSample);
7423 ok(ret == 0, "Release returned %lu\n", ret);
7425 trace("created %s\n", debugstr_w(output_path));
7426 CloseHandle(output_file);
7428 status = 0;
7429 memset(&output, 0, sizeof(output));
7430 output.pSample = create_sample(NULL, actual_width * actual_height * 2);
7431 hr = IMFTransform_ProcessOutput(transform, 0, 1, &output, &status);
7432 ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "ProcessOutput returned %#lx\n", hr);
7433 ok(output.dwStreamID == 0, "got dwStreamID %lu\n", output.dwStreamID);
7434 ok(!!output.pSample, "got pSample %p\n", output.pSample);
7435 ok(output.dwStatus == 0, "got dwStatus %#lx\n", output.dwStatus);
7436 ok(!output.pEvents, "got pEvents %p\n", output.pEvents);
7437 ok(status == 0, "got status %#lx\n", status);
7438 ret = IMFSample_Release(output.pSample);
7439 ok(ret == 0, "Release returned %lu\n", ret);
7441 ret = IMFTransform_Release(transform);
7442 ok(ret == 0, "Release returned %lu\n", ret);
7443 ret = IMFSample_Release(sample);
7444 ok(ret == 0, "Release returned %lu\n", ret);
7446 failed:
7447 CoUninitialize();
7450 static void test_audio_convert(void)
7452 const GUID transform_inputs[2] =
7454 MFAudioFormat_PCM,
7455 MFAudioFormat_Float,
7457 const GUID transform_outputs[2] =
7459 MFAudioFormat_PCM,
7460 MFAudioFormat_Float,
7463 static const media_type_desc expect_available_inputs[] =
7466 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
7467 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_Float),
7468 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
7471 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
7472 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_PCM),
7473 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
7476 static const media_type_desc expect_available_outputs[] =
7479 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
7480 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_Float),
7481 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
7484 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
7485 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_PCM),
7486 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
7489 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
7490 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_Float),
7491 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 32),
7492 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 2),
7493 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 48000),
7494 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 384000),
7495 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 8),
7496 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
7497 ATTR_UINT32(MF_MT_AUDIO_PREFER_WAVEFORMATEX, 1),
7500 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
7501 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_PCM),
7502 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 16),
7503 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 2),
7504 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 48000),
7505 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 192000),
7506 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 4),
7507 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
7508 ATTR_UINT32(MF_MT_AUDIO_PREFER_WAVEFORMATEX, 1),
7512 static const struct attribute_desc input_type_desc[] =
7514 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
7515 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_Float),
7516 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 32),
7517 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 2),
7518 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 22050),
7519 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 176400),
7520 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 8),
7521 {0},
7523 const struct attribute_desc output_type_desc[] =
7525 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
7526 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_PCM),
7527 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 16),
7528 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 2),
7529 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 44100),
7530 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 176400),
7531 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 4),
7532 {0},
7535 MFT_REGISTER_TYPE_INFO output_type = {MFMediaType_Audio, MFAudioFormat_PCM};
7536 MFT_REGISTER_TYPE_INFO input_type = {MFMediaType_Audio, MFAudioFormat_Float};
7537 static const ULONG audioconv_block_size = 0x4000;
7538 ULONG audio_data_len, audioconv_data_len;
7539 const BYTE *audio_data, *audioconv_data;
7540 MFT_OUTPUT_STREAM_INFO output_info;
7541 MFT_INPUT_STREAM_INFO input_info;
7542 MFT_OUTPUT_DATA_BUFFER output;
7543 WCHAR output_path[MAX_PATH];
7544 IMFMediaType *media_type;
7545 LONGLONG time, duration;
7546 IMFTransform *transform;
7547 DWORD length, status;
7548 HANDLE output_file;
7549 IMFSample *sample;
7550 HRSRC resource;
7551 GUID class_id;
7552 ULONG i, ret;
7553 HRESULT hr;
7555 hr = CoInitialize(NULL);
7556 ok(hr == S_OK, "Failed to initialize, hr %#lx.\n", hr);
7558 if (!create_transform(MFT_CATEGORY_AUDIO_EFFECT, &input_type, &output_type, L"Resampler MFT", &MFMediaType_Audio,
7559 transform_inputs, ARRAY_SIZE(transform_inputs), transform_outputs, ARRAY_SIZE(transform_outputs),
7560 &transform, &CLSID_CResamplerMediaObject, &class_id))
7561 goto failed;
7563 check_dmo(&class_id, L"Resampler DMO", &MEDIATYPE_Audio, transform_inputs, ARRAY_SIZE(transform_inputs),
7564 transform_outputs, ARRAY_SIZE(transform_outputs));
7566 check_interface(transform, &IID_IMFTransform, TRUE);
7567 check_interface(transform, &IID_IMediaObject, TRUE);
7568 check_interface(transform, &IID_IPropertyStore, TRUE);
7569 todo_wine
7570 check_interface(transform, &IID_IPropertyBag, TRUE);
7571 /* check_interface(transform, &IID_IWMResamplerProps, TRUE); */
7573 /* check default media types */
7575 hr = IMFTransform_GetInputStreamInfo(transform, 0, &input_info);
7576 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "GetInputStreamInfo returned %#lx\n", hr);
7577 hr = IMFTransform_GetOutputStreamInfo(transform, 0, &output_info);
7578 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "GetOutputStreamInfo returned %#lx\n", hr);
7580 i = -1;
7581 while (SUCCEEDED(hr = IMFTransform_GetOutputAvailableType(transform, 0, ++i, &media_type)))
7583 winetest_push_context("out %lu", i);
7584 ok(hr == S_OK, "GetOutputAvailableType returned %#lx\n", hr);
7585 check_media_type(media_type, expect_available_outputs[i], -1);
7586 ret = IMFMediaType_Release(media_type);
7587 ok(ret == 0, "Release returned %lu\n", ret);
7588 winetest_pop_context();
7590 ok(hr == MF_E_NO_MORE_TYPES, "GetOutputAvailableType returned %#lx\n", hr);
7591 ok(i == 4, "%lu output media types\n", i);
7593 i = -1;
7594 while (SUCCEEDED(hr = IMFTransform_GetInputAvailableType(transform, 0, ++i, &media_type)))
7596 winetest_push_context("in %lu", i);
7597 ok(hr == S_OK, "GetInputAvailableType returned %#lx\n", hr);
7598 check_media_type(media_type, expect_available_inputs[i], -1);
7599 hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
7600 ok(hr == MF_E_INVALIDMEDIATYPE, "SetInputType returned %#lx.\n", hr);
7601 ret = IMFMediaType_Release(media_type);
7602 ok(ret == 0, "Release returned %lu\n", ret);
7603 winetest_pop_context();
7605 ok(hr == MF_E_NO_MORE_TYPES, "GetInputAvailableType returned %#lx\n", hr);
7606 ok(i == 2, "%lu input media types\n", i);
7608 /* setting output media type first doesn't work */
7610 hr = MFCreateMediaType(&media_type);
7611 ok(hr == S_OK, "MFCreateMediaType returned %#lx\n", hr);
7612 init_media_type(media_type, output_type_desc, -1);
7613 hr = IMFTransform_SetOutputType(transform, 0, media_type, 0);
7614 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "SetOutputType returned %#lx.\n", hr);
7615 ret = IMFMediaType_Release(media_type);
7616 ok(ret == 0, "Release returned %lu\n", ret);
7618 /* check required input media type attributes */
7620 hr = MFCreateMediaType(&media_type);
7621 ok(hr == S_OK, "MFCreateMediaType returned %#lx\n", hr);
7622 hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
7623 ok(hr == MF_E_ATTRIBUTENOTFOUND, "SetInputType returned %#lx.\n", hr);
7624 init_media_type(media_type, input_type_desc, 1);
7625 hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
7626 ok(hr == MF_E_ATTRIBUTENOTFOUND, "SetInputType returned %#lx.\n", hr);
7627 init_media_type(media_type, input_type_desc, 2);
7628 for (i = 2; i < ARRAY_SIZE(input_type_desc) - 1; ++i)
7630 hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
7631 ok(hr == MF_E_INVALIDMEDIATYPE, "SetInputType returned %#lx.\n", hr);
7632 init_media_type(media_type, input_type_desc, i + 1);
7634 hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
7635 ok(hr == S_OK, "SetInputType returned %#lx.\n", hr);
7636 ret = IMFMediaType_Release(media_type);
7637 ok(ret == 0, "Release returned %lu\n", ret);
7639 hr = IMFTransform_GetInputStreamInfo(transform, 0, &input_info);
7640 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "GetInputStreamInfo returned %#lx\n", hr);
7641 hr = IMFTransform_GetOutputStreamInfo(transform, 0, &output_info);
7642 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "GetOutputStreamInfo returned %#lx\n", hr);
7644 /* check new output media types */
7646 i = -1;
7647 while (SUCCEEDED(hr = IMFTransform_GetOutputAvailableType(transform, 0, ++i, &media_type)))
7649 winetest_push_context("out %lu", i);
7650 ok(hr == S_OK, "GetOutputAvailableType returned %#lx\n", hr);
7651 check_media_type(media_type, expect_available_outputs[i], -1);
7652 ret = IMFMediaType_Release(media_type);
7653 ok(ret == 0, "Release returned %lu\n", ret);
7654 winetest_pop_context();
7656 ok(hr == MF_E_NO_MORE_TYPES, "GetOutputAvailableType returned %#lx\n", hr);
7657 ok(i == 4, "%lu output media types\n", i);
7659 /* check required output media type attributes */
7661 hr = MFCreateMediaType(&media_type);
7662 ok(hr == S_OK, "MFCreateMediaType returned %#lx\n", hr);
7663 hr = IMFTransform_SetOutputType(transform, 0, media_type, 0);
7664 ok(hr == MF_E_ATTRIBUTENOTFOUND, "SetOutputType returned %#lx.\n", hr);
7665 init_media_type(media_type, output_type_desc, 1);
7666 hr = IMFTransform_SetOutputType(transform, 0, media_type, 0);
7667 ok(hr == MF_E_ATTRIBUTENOTFOUND, "SetOutputType returned %#lx.\n", hr);
7668 init_media_type(media_type, output_type_desc, 2);
7669 for (i = 2; i < ARRAY_SIZE(output_type_desc) - 1; ++i)
7671 hr = IMFTransform_SetOutputType(transform, 0, media_type, 0);
7672 ok(hr == MF_E_INVALIDMEDIATYPE, "SetOutputType returned %#lx.\n", hr);
7673 init_media_type(media_type, output_type_desc, i + 1);
7675 hr = IMFTransform_SetOutputType(transform, 0, media_type, 0);
7676 ok(hr == S_OK, "SetOutputType returned %#lx.\n", hr);
7677 ret = IMFMediaType_Release(media_type);
7678 ok(ret == 0, "Release returned %lu\n", ret);
7680 memset(&input_info, 0xcd, sizeof(input_info));
7681 hr = IMFTransform_GetInputStreamInfo(transform, 0, &input_info);
7682 ok(hr == S_OK, "GetInputStreamInfo returned %#lx\n", hr);
7683 ok(input_info.hnsMaxLatency == 0, "got hnsMaxLatency %s\n", wine_dbgstr_longlong(input_info.hnsMaxLatency));
7684 ok(input_info.dwFlags == 0, "got dwFlags %#lx\n", input_info.dwFlags);
7685 ok(input_info.cbSize == 8, "got cbSize %lu\n", input_info.cbSize);
7686 ok(input_info.cbMaxLookahead == 0, "got cbMaxLookahead %#lx\n", input_info.cbMaxLookahead);
7687 ok(input_info.cbAlignment == 1, "got cbAlignment %#lx\n", input_info.cbAlignment);
7689 memset(&output_info, 0xcd, sizeof(output_info));
7690 hr = IMFTransform_GetOutputStreamInfo(transform, 0, &output_info);
7691 ok(hr == S_OK, "GetOutputStreamInfo returned %#lx\n", hr);
7692 ok(output_info.dwFlags == 0, "got dwFlags %#lx\n", output_info.dwFlags);
7693 ok(output_info.cbSize == 4, "got cbSize %#lx\n", output_info.cbSize);
7694 ok(output_info.cbAlignment == 1, "got cbAlignment %#lx\n", output_info.cbAlignment);
7696 resource = FindResourceW(NULL, L"audiodata.bin", (const WCHAR *)RT_RCDATA);
7697 ok(resource != 0, "FindResourceW failed, error %lu\n", GetLastError());
7698 audio_data = LockResource(LoadResource(GetModuleHandleW(NULL), resource));
7699 audio_data_len = SizeofResource(GetModuleHandleW(NULL), resource);
7700 ok(audio_data_len == 179928, "got length %lu\n", audio_data_len);
7702 sample = create_sample(audio_data, audio_data_len);
7703 hr = IMFSample_SetSampleTime(sample, 0);
7704 ok(hr == S_OK, "SetSampleTime returned %#lx\n", hr);
7705 hr = IMFSample_SetSampleDuration(sample, 10000000);
7706 ok(hr == S_OK, "SetSampleDuration returned %#lx\n", hr);
7707 hr = IMFTransform_ProcessInput(transform, 0, sample, 0);
7708 ok(hr == S_OK, "ProcessInput returned %#lx\n", hr);
7709 hr = IMFTransform_ProcessMessage(transform, MFT_MESSAGE_COMMAND_DRAIN, 0);
7710 ok(hr == S_OK, "ProcessMessage returned %#lx\n", hr);
7711 hr = IMFTransform_ProcessInput(transform, 0, sample, 0);
7712 ok(hr == MF_E_NOTACCEPTING, "ProcessInput returned %#lx\n", hr);
7713 IMFSample_Release(sample);
7715 status = 0xdeadbeef;
7716 sample = create_sample(NULL, audioconv_block_size);
7717 memset(&output, 0, sizeof(output));
7718 output.pSample = sample;
7720 resource = FindResourceW(NULL, L"audioconvdata.bin", (const WCHAR *)RT_RCDATA);
7721 ok(resource != 0, "FindResourceW failed, error %lu\n", GetLastError());
7722 audioconv_data = LockResource(LoadResource(GetModuleHandleW(NULL), resource));
7723 audioconv_data_len = SizeofResource(GetModuleHandleW(NULL), resource);
7724 ok(audioconv_data_len == 179924, "got length %lu\n", audioconv_data_len);
7726 /* and generate a new one as well in a temporary directory */
7727 GetTempPathW(ARRAY_SIZE(output_path), output_path);
7728 lstrcatW(output_path, L"audioconvdata.bin");
7729 output_file = CreateFileW(output_path, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0);
7730 ok(output_file != INVALID_HANDLE_VALUE, "CreateFileW failed, error %lu\n", GetLastError());
7732 i = 0;
7733 while (SUCCEEDED(hr = IMFTransform_ProcessOutput(transform, 0, 1, &output, &status)))
7735 winetest_push_context("%lu", i);
7736 ok(hr == S_OK, "ProcessOutput returned %#lx\n", hr);
7737 ok(output.pSample == sample, "got pSample %p\n", output.pSample);
7738 ok(output.dwStatus == MFT_OUTPUT_DATA_BUFFER_INCOMPLETE || output.dwStatus == 0 ||
7739 broken(output.dwStatus == (MFT_OUTPUT_DATA_BUFFER_INCOMPLETE|6) || output.dwStatus == 6) /* win7 */,
7740 "got dwStatus %#lx\n", output.dwStatus);
7741 ok(status == 0, "got status %#lx\n", status);
7742 if (!(output.dwStatus & MFT_OUTPUT_DATA_BUFFER_INCOMPLETE))
7744 winetest_pop_context();
7745 break;
7748 hr = IMFSample_GetSampleTime(sample, &time);
7749 ok(hr == S_OK, "GetSampleTime returned %#lx\n", hr);
7750 ok(time == i * 928798, "got time %I64d\n", time);
7751 hr = IMFSample_GetSampleDuration(sample, &duration);
7752 ok(hr == S_OK, "GetSampleDuration returned %#lx\n", hr);
7753 ok(duration == 928798, "got duration %I64d\n", duration);
7754 hr = IMFSample_GetTotalLength(sample, &length);
7755 ok(hr == S_OK, "GetTotalLength returned %#lx\n", hr);
7756 ok(length == audioconv_block_size, "got length %lu\n", length);
7757 ok(audioconv_data_len > audioconv_block_size, "got remaining length %lu\n", audioconv_data_len);
7758 check_sample_pcm16(sample, audioconv_data, output_file, FALSE);
7759 audioconv_data_len -= audioconv_block_size;
7760 audioconv_data += audioconv_block_size;
7762 winetest_pop_context();
7763 i++;
7766 hr = IMFSample_GetSampleTime(sample, &time);
7767 ok(hr == S_OK, "GetSampleTime returned %#lx\n", hr);
7768 ok(time == i * 928798, "got time %I64d\n", time);
7769 hr = IMFSample_GetSampleDuration(sample, &duration);
7770 ok(hr == S_OK, "GetSampleDuration returned %#lx\n", hr);
7771 todo_wine
7772 ok(duration == 897506, "got duration %I64d\n", duration);
7773 hr = IMFSample_GetTotalLength(sample, &length);
7774 ok(hr == S_OK, "GetTotalLength returned %#lx\n", hr);
7775 todo_wine
7776 ok(length == 15832, "got length %lu\n", length);
7777 ok(audioconv_data_len == 16084, "got remaining length %lu\n", audioconv_data_len);
7778 check_sample_pcm16(sample, audioconv_data, output_file, FALSE);
7779 audioconv_data_len -= length;
7780 audioconv_data += length;
7782 memset(&output, 0, sizeof(output));
7783 output.pSample = sample;
7784 hr = IMFTransform_ProcessOutput(transform, 0, 1, &output, &status);
7785 todo_wine
7786 ok(hr == S_OK || broken(hr == MF_E_TRANSFORM_NEED_MORE_INPUT) /* win7 */, "ProcessOutput returned %#lx\n", hr);
7787 ok(output.pSample == sample, "got pSample %p\n", output.pSample);
7788 todo_wine
7789 ok(output.dwStatus == MFT_OUTPUT_DATA_BUFFER_INCOMPLETE || broken(output.dwStatus == 0) /* win7 */,
7790 "got dwStatus %#lx\n", output.dwStatus);
7791 ok(status == 0, "got status %#lx\n", status);
7793 if (hr == S_OK)
7795 hr = IMFSample_GetSampleTime(sample, &time);
7796 ok(hr == S_OK, "GetSampleTime returned %#lx\n", hr);
7797 todo_wine
7798 ok(time == 10185486, "got time %I64d\n", time);
7799 hr = IMFSample_GetSampleDuration(sample, &duration);
7800 ok(hr == S_OK, "GetSampleDuration returned %#lx\n", hr);
7801 todo_wine
7802 ok(duration == 14286, "got duration %I64d\n", duration);
7803 hr = IMFSample_GetTotalLength(sample, &length);
7804 ok(hr == S_OK, "GetTotalLength returned %#lx\n", hr);
7805 todo_wine
7806 ok(length == audioconv_data_len, "got length %lu\n", length);
7807 if (length == audioconv_data_len)
7808 check_sample_pcm16(sample, audioconv_data, output_file, FALSE);
7811 trace("created %s\n", debugstr_w(output_path));
7812 CloseHandle(output_file);
7814 ret = IMFSample_Release(sample);
7815 ok(ret == 0, "Release returned %lu\n", ret);
7817 status = 0xdeadbeef;
7818 sample = create_sample(NULL, audioconv_block_size);
7819 memset(&output, 0, sizeof(output));
7820 output.pSample = sample;
7821 hr = IMFTransform_ProcessOutput(transform, 0, 1, &output, &status);
7822 ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "ProcessOutput returned %#lx\n", hr);
7823 ok(output.pSample == sample, "got pSample %p\n", output.pSample);
7824 ok(output.dwStatus == 0, "got dwStatus %#lx\n", output.dwStatus);
7825 ok(status == 0, "got status %#lx\n", status);
7826 hr = IMFSample_GetTotalLength(sample, &length);
7827 ok(hr == S_OK, "GetTotalLength returned %#lx\n", hr);
7828 ok(length == 0, "got length %lu\n", length);
7829 ret = IMFSample_Release(sample);
7830 ok(ret == 0, "Release returned %lu\n", ret);
7832 ret = IMFTransform_Release(transform);
7833 ok(ret == 0, "Release returned %lu\n", ret);
7835 failed:
7836 CoUninitialize();
7839 static void test_color_convert(void)
7841 const GUID transform_inputs[20] =
7843 MFVideoFormat_YV12,
7844 MFVideoFormat_YUY2,
7845 MFVideoFormat_UYVY,
7846 MFVideoFormat_AYUV,
7847 MFVideoFormat_NV12,
7848 DMOVideoFormat_RGB32,
7849 DMOVideoFormat_RGB565,
7850 MFVideoFormat_I420,
7851 MFVideoFormat_IYUV,
7852 MFVideoFormat_YVYU,
7853 DMOVideoFormat_RGB24,
7854 DMOVideoFormat_RGB555,
7855 DMOVideoFormat_RGB8,
7856 MEDIASUBTYPE_V216,
7857 MEDIASUBTYPE_V410,
7858 MFVideoFormat_NV11,
7859 MFVideoFormat_Y41P,
7860 MFVideoFormat_Y41T,
7861 MFVideoFormat_Y42T,
7862 MFVideoFormat_YVU9,
7864 const GUID transform_outputs[16] =
7866 MFVideoFormat_YV12,
7867 MFVideoFormat_YUY2,
7868 MFVideoFormat_UYVY,
7869 MFVideoFormat_AYUV,
7870 MFVideoFormat_NV12,
7871 DMOVideoFormat_RGB32,
7872 DMOVideoFormat_RGB565,
7873 MFVideoFormat_I420,
7874 MFVideoFormat_IYUV,
7875 MFVideoFormat_YVYU,
7876 DMOVideoFormat_RGB24,
7877 DMOVideoFormat_RGB555,
7878 DMOVideoFormat_RGB8,
7879 MEDIASUBTYPE_V216,
7880 MEDIASUBTYPE_V410,
7881 MFVideoFormat_NV11,
7883 const GUID dmo_inputs[20] =
7885 MEDIASUBTYPE_YV12,
7886 MEDIASUBTYPE_YUY2,
7887 MEDIASUBTYPE_UYVY,
7888 MEDIASUBTYPE_AYUV,
7889 MEDIASUBTYPE_NV12,
7890 MEDIASUBTYPE_RGB32,
7891 MEDIASUBTYPE_RGB565,
7892 MEDIASUBTYPE_I420,
7893 MEDIASUBTYPE_IYUV,
7894 MEDIASUBTYPE_YVYU,
7895 MEDIASUBTYPE_RGB24,
7896 MEDIASUBTYPE_RGB555,
7897 MEDIASUBTYPE_RGB8,
7898 MEDIASUBTYPE_V216,
7899 MEDIASUBTYPE_V410,
7900 MEDIASUBTYPE_NV11,
7901 MEDIASUBTYPE_Y41P,
7902 MEDIASUBTYPE_Y41T,
7903 MEDIASUBTYPE_Y42T,
7904 MEDIASUBTYPE_YVU9,
7906 const GUID dmo_outputs[16] =
7908 MEDIASUBTYPE_YV12,
7909 MEDIASUBTYPE_YUY2,
7910 MEDIASUBTYPE_UYVY,
7911 MEDIASUBTYPE_AYUV,
7912 MEDIASUBTYPE_NV12,
7913 MEDIASUBTYPE_RGB32,
7914 MEDIASUBTYPE_RGB565,
7915 MEDIASUBTYPE_I420,
7916 MEDIASUBTYPE_IYUV,
7917 MEDIASUBTYPE_YVYU,
7918 MEDIASUBTYPE_RGB24,
7919 MEDIASUBTYPE_RGB555,
7920 MEDIASUBTYPE_RGB8,
7921 MEDIASUBTYPE_V216,
7922 MEDIASUBTYPE_V410,
7923 MEDIASUBTYPE_NV11,
7926 static const media_type_desc expect_available_inputs[20] =
7928 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_YV12), },
7929 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_YUY2), },
7930 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_UYVY), },
7931 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_AYUV), },
7932 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_NV12), },
7933 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_RGB32), },
7934 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_RGB565), },
7935 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_I420), },
7936 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_IYUV), },
7937 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_YVYU), },
7938 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_RGB24), },
7939 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_RGB555), },
7940 { ATTR_GUID(MF_MT_SUBTYPE, MEDIASUBTYPE_RGB8), },
7941 { ATTR_GUID(MF_MT_SUBTYPE, MEDIASUBTYPE_V216), },
7942 { ATTR_GUID(MF_MT_SUBTYPE, MEDIASUBTYPE_V410), },
7943 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_NV11), },
7944 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_Y41P), },
7945 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_Y41T), },
7946 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_Y42T), },
7947 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_YVU9), },
7949 static const media_type_desc expect_available_outputs[16] =
7951 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_YV12), },
7952 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_YUY2), },
7953 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_UYVY), },
7954 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_AYUV), },
7955 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_NV12), },
7956 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_RGB32), },
7957 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_RGB565), },
7958 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_I420), },
7959 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_IYUV), },
7960 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_YVYU), },
7961 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_RGB24), },
7962 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_RGB555), },
7963 { ATTR_GUID(MF_MT_SUBTYPE, MEDIASUBTYPE_RGB8), },
7964 { ATTR_GUID(MF_MT_SUBTYPE, MEDIASUBTYPE_V216), },
7965 { ATTR_GUID(MF_MT_SUBTYPE, MEDIASUBTYPE_V410), },
7966 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_NV11), },
7968 static const media_type_desc expect_available_common =
7970 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
7971 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
7972 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
7975 static const MFVideoArea actual_aperture = {.Area={82,84}};
7976 static const DWORD actual_width = 96, actual_height = 96;
7977 const struct attribute_desc input_type_desc[] =
7979 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
7980 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_NV12),
7981 ATTR_BLOB(MF_MT_MINIMUM_DISPLAY_APERTURE, &actual_aperture, 16),
7982 ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height),
7983 {0},
7985 const struct attribute_desc output_type_desc[] =
7987 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
7988 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_RGB32),
7989 ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height),
7990 {0},
7993 MFT_REGISTER_TYPE_INFO output_type = {MFMediaType_Video, MFVideoFormat_NV12};
7994 MFT_REGISTER_TYPE_INFO input_type = {MFMediaType_Video, MFVideoFormat_I420};
7995 ULONG nv12frame_data_len, rgb32_data_len;
7996 const BYTE *nv12frame_data, *rgb32_data;
7997 MFT_OUTPUT_STREAM_INFO output_info;
7998 MFT_INPUT_STREAM_INFO input_info;
7999 MFT_OUTPUT_DATA_BUFFER output;
8000 WCHAR output_path[MAX_PATH];
8001 IMFMediaType *media_type;
8002 LONGLONG time, duration;
8003 IMFTransform *transform;
8004 DWORD length, status;
8005 HANDLE output_file;
8006 IMFSample *sample;
8007 HRSRC resource;
8008 GUID class_id;
8009 ULONG i, ret;
8010 HRESULT hr;
8012 hr = CoInitialize(NULL);
8013 ok(hr == S_OK, "Failed to initialize, hr %#lx.\n", hr);
8015 if (!create_transform(MFT_CATEGORY_VIDEO_EFFECT, &input_type, &output_type, L"Color Converter MFT", &MFMediaType_Video,
8016 transform_inputs, ARRAY_SIZE(transform_inputs), transform_outputs, ARRAY_SIZE(transform_outputs),
8017 &transform, &CLSID_CColorConvertDMO, &class_id))
8018 goto failed;
8020 check_dmo(&CLSID_CColorConvertDMO, L"Color Converter DMO", &MEDIATYPE_Video, dmo_inputs, ARRAY_SIZE(dmo_inputs),
8021 dmo_outputs, ARRAY_SIZE(dmo_outputs));
8023 check_interface(transform, &IID_IMFTransform, TRUE);
8024 check_interface(transform, &IID_IMediaObject, TRUE);
8025 check_interface(transform, &IID_IPropertyStore, TRUE);
8026 check_interface(transform, &IID_IMFRealTimeClient, TRUE);
8027 /* check_interface(transform, &IID_IWMColorConvProps, TRUE); */
8029 /* check default media types */
8031 hr = IMFTransform_GetInputStreamInfo(transform, 0, &input_info);
8032 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "GetInputStreamInfo returned %#lx\n", hr);
8033 hr = IMFTransform_GetOutputStreamInfo(transform, 0, &output_info);
8034 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "GetOutputStreamInfo returned %#lx\n", hr);
8036 i = -1;
8037 while (SUCCEEDED(hr = IMFTransform_GetOutputAvailableType(transform, 0, ++i, &media_type)))
8039 winetest_push_context("out %lu", i);
8040 ok(hr == S_OK, "GetOutputAvailableType returned %#lx\n", hr);
8041 check_media_type(media_type, expect_available_common, -1);
8042 check_media_type(media_type, expect_available_outputs[i], -1);
8043 ret = IMFMediaType_Release(media_type);
8044 ok(ret == 0, "Release returned %lu\n", ret);
8045 winetest_pop_context();
8047 ok(hr == MF_E_NO_MORE_TYPES, "GetOutputAvailableType returned %#lx\n", hr);
8048 ok(i == 16, "%lu output media types\n", i);
8050 i = -1;
8051 while (SUCCEEDED(hr = IMFTransform_GetInputAvailableType(transform, 0, ++i, &media_type)))
8053 winetest_push_context("in %lu", i);
8054 ok(hr == S_OK, "GetInputAvailableType returned %#lx\n", hr);
8055 check_media_type(media_type, expect_available_common, -1);
8056 check_media_type(media_type, expect_available_inputs[i], -1);
8057 hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
8058 if (i == 12)
8060 todo_wine
8061 ok(hr == MF_E_INVALIDMEDIATYPE, "SetInputType returned %#lx.\n", hr);
8063 else
8064 ok(hr == E_INVALIDARG, "SetInputType returned %#lx.\n", hr);
8065 ret = IMFMediaType_Release(media_type);
8066 ok(ret == 0, "Release returned %lu\n", ret);
8067 winetest_pop_context();
8069 ok(hr == MF_E_NO_MORE_TYPES, "GetInputAvailableType returned %#lx\n", hr);
8070 ok(i == 20, "%lu input media types\n", i);
8072 /* check required output media type attributes */
8074 hr = MFCreateMediaType(&media_type);
8075 ok(hr == S_OK, "MFCreateMediaType returned %#lx\n", hr);
8076 hr = IMFTransform_SetOutputType(transform, 0, media_type, 0);
8077 ok(hr == MF_E_ATTRIBUTENOTFOUND, "SetOutputType returned %#lx.\n", hr);
8078 init_media_type(media_type, output_type_desc, 1);
8079 hr = IMFTransform_SetOutputType(transform, 0, media_type, 0);
8080 ok(hr == MF_E_ATTRIBUTENOTFOUND, "SetOutputType returned %#lx.\n", hr);
8081 init_media_type(media_type, output_type_desc, 2);
8082 for (i = 2; i < ARRAY_SIZE(output_type_desc) - 1; ++i)
8084 hr = IMFTransform_SetOutputType(transform, 0, media_type, 0);
8085 ok(hr == E_INVALIDARG, "SetOutputType returned %#lx.\n", hr);
8086 init_media_type(media_type, output_type_desc, i + 1);
8088 hr = IMFTransform_SetOutputType(transform, 0, media_type, 0);
8089 ok(hr == S_OK, "SetOutputType returned %#lx.\n", hr);
8090 ret = IMFMediaType_Release(media_type);
8091 ok(ret == 0, "Release returned %lu\n", ret);
8093 /* check required input media type attributes */
8095 hr = MFCreateMediaType(&media_type);
8096 ok(hr == S_OK, "MFCreateMediaType returned %#lx\n", hr);
8097 hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
8098 ok(hr == MF_E_ATTRIBUTENOTFOUND, "SetInputType returned %#lx.\n", hr);
8099 init_media_type(media_type, input_type_desc, 1);
8100 hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
8101 ok(hr == MF_E_ATTRIBUTENOTFOUND, "SetInputType returned %#lx.\n", hr);
8102 init_media_type(media_type, input_type_desc, 2);
8103 for (i = 2; i < ARRAY_SIZE(input_type_desc) - 1; ++i)
8105 hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
8106 ok(hr == E_INVALIDARG, "SetInputType returned %#lx.\n", hr);
8107 init_media_type(media_type, input_type_desc, i + 1);
8109 hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
8110 ok(hr == S_OK, "SetInputType returned %#lx.\n", hr);
8111 ret = IMFMediaType_Release(media_type);
8112 ok(ret == 0, "Release returned %lu\n", ret);
8114 memset(&input_info, 0xcd, sizeof(input_info));
8115 hr = IMFTransform_GetInputStreamInfo(transform, 0, &input_info);
8116 ok(hr == S_OK, "GetInputStreamInfo returned %#lx\n", hr);
8117 ok(input_info.hnsMaxLatency == 0, "got hnsMaxLatency %s\n", wine_dbgstr_longlong(input_info.hnsMaxLatency));
8118 ok(input_info.dwFlags == 0, "got dwFlags %#lx\n", input_info.dwFlags);
8119 ok(input_info.cbSize == actual_width * actual_height * 3 / 2, "got cbSize %#lx\n", input_info.cbSize);
8120 ok(input_info.cbMaxLookahead == 0, "got cbMaxLookahead %#lx\n", input_info.cbMaxLookahead);
8121 ok(input_info.cbAlignment == 1, "got cbAlignment %#lx\n", input_info.cbAlignment);
8123 memset(&output_info, 0xcd, sizeof(output_info));
8124 hr = IMFTransform_GetOutputStreamInfo(transform, 0, &output_info);
8125 ok(hr == S_OK, "GetOutputStreamInfo returned %#lx\n", hr);
8126 ok(output_info.dwFlags == 0, "got dwFlags %#lx\n", output_info.dwFlags);
8127 ok(output_info.cbSize == actual_width * actual_height * 4, "got cbSize %#lx\n", output_info.cbSize);
8128 ok(output_info.cbAlignment == 1, "got cbAlignment %#lx\n", output_info.cbAlignment);
8130 resource = FindResourceW(NULL, L"nv12frame.bin", (const WCHAR *)RT_RCDATA);
8131 ok(resource != 0, "FindResourceW failed, error %lu\n", GetLastError());
8132 nv12frame_data = LockResource(LoadResource(GetModuleHandleW(NULL), resource));
8133 nv12frame_data_len = SizeofResource(GetModuleHandleW(NULL), resource);
8134 ok(nv12frame_data_len == 13824, "got length %lu\n", nv12frame_data_len);
8136 sample = create_sample(nv12frame_data, nv12frame_data_len);
8137 hr = IMFSample_SetSampleTime(sample, 0);
8138 ok(hr == S_OK, "SetSampleTime returned %#lx\n", hr);
8139 hr = IMFSample_SetSampleDuration(sample, 10000000);
8140 ok(hr == S_OK, "SetSampleDuration returned %#lx\n", hr);
8141 hr = IMFTransform_ProcessInput(transform, 0, sample, 0);
8142 ok(hr == S_OK, "ProcessInput returned %#lx\n", hr);
8143 hr = IMFTransform_ProcessInput(transform, 0, sample, 0);
8144 ok(hr == MF_E_NOTACCEPTING, "ProcessInput returned %#lx\n", hr);
8145 hr = IMFTransform_ProcessMessage(transform, MFT_MESSAGE_COMMAND_DRAIN, 0);
8146 ok(hr == S_OK, "ProcessMessage returned %#lx\n", hr);
8147 IMFSample_Release(sample);
8149 resource = FindResourceW(NULL, L"rgb32frame.bin", (const WCHAR *)RT_RCDATA);
8150 ok(resource != 0, "FindResourceW failed, error %lu\n", GetLastError());
8151 rgb32_data = LockResource(LoadResource(GetModuleHandleW(NULL), resource));
8152 rgb32_data_len = SizeofResource(GetModuleHandleW(NULL), resource);
8153 ok(rgb32_data_len == output_info.cbSize, "got length %lu\n", rgb32_data_len);
8155 /* and generate a new one as well in a temporary directory */
8156 GetTempPathW(ARRAY_SIZE(output_path), output_path);
8157 lstrcatW(output_path, L"rgb32frame.bin");
8158 output_file = CreateFileW(output_path, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0);
8159 ok(output_file != INVALID_HANDLE_VALUE, "CreateFileW failed, error %lu\n", GetLastError());
8161 status = 0xdeadbeef;
8162 sample = create_sample(NULL, output_info.cbSize);
8163 memset(&output, 0, sizeof(output));
8164 output.pSample = sample;
8165 hr = IMFTransform_ProcessOutput(transform, 0, 1, &output, &status);
8166 ok(hr == S_OK, "ProcessOutput returned %#lx\n", hr);
8167 ok(output.pSample == sample, "got pSample %p\n", output.pSample);
8168 ok(output.dwStatus == 0 || broken(output.dwStatus == 6) /* win7 */, "got dwStatus %#lx\n", output.dwStatus);
8169 ok(status == 0, "got status %#lx\n", status);
8171 hr = IMFSample_GetSampleTime(sample, &time);
8172 ok(hr == S_OK, "GetSampleTime returned %#lx\n", hr);
8173 ok(time == 0, "got time %I64d\n", time);
8174 hr = IMFSample_GetSampleDuration(sample, &duration);
8175 ok(hr == S_OK, "GetSampleDuration returned %#lx\n", hr);
8176 ok(duration == 10000000, "got duration %I64d\n", duration);
8177 hr = IMFSample_GetTotalLength(sample, &length);
8178 ok(hr == S_OK, "GetTotalLength returned %#lx\n", hr);
8179 ok(length == output_info.cbSize, "got length %lu\n", length);
8180 check_sample_rgb32(sample, rgb32_data, output_file);
8181 rgb32_data_len -= output_info.cbSize;
8182 rgb32_data += output_info.cbSize;
8184 trace("created %s\n", debugstr_w(output_path));
8185 CloseHandle(output_file);
8187 ret = IMFSample_Release(sample);
8188 ok(ret == 0, "Release returned %lu\n", ret);
8190 status = 0xdeadbeef;
8191 sample = create_sample(NULL, output_info.cbSize);
8192 memset(&output, 0, sizeof(output));
8193 output.pSample = sample;
8194 hr = IMFTransform_ProcessOutput(transform, 0, 1, &output, &status);
8195 ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "ProcessOutput returned %#lx\n", hr);
8196 ok(output.pSample == sample, "got pSample %p\n", output.pSample);
8197 ok(output.dwStatus == 0, "got dwStatus %#lx\n", output.dwStatus);
8198 ok(status == 0, "got status %#lx\n", status);
8199 hr = IMFSample_GetTotalLength(sample, &length);
8200 ok(hr == S_OK, "GetTotalLength returned %#lx\n", hr);
8201 ok(length == 0, "got length %lu\n", length);
8202 ret = IMFSample_Release(sample);
8203 ok(ret == 0, "Release returned %lu\n", ret);
8205 IMFTransform_Release(transform);
8207 failed:
8208 CoUninitialize();
8212 START_TEST(mf)
8214 init_functions();
8216 if (is_vista())
8218 win_skip("Skipping tests on Vista.\n");
8219 return;
8222 test_video_processor();
8223 test_topology();
8224 test_topology_tee_node();
8225 test_topology_loader();
8226 test_topology_loader_evr();
8227 test_MFGetService();
8228 test_sequencer_source();
8229 test_media_session();
8230 test_media_session_rate_control();
8231 test_MFShutdownObject();
8232 test_presentation_clock();
8233 test_sample_grabber();
8234 test_sample_grabber_is_mediatype_supported();
8235 test_quality_manager();
8236 test_sar();
8237 test_evr();
8238 test_MFCreateSimpleTypeHandler();
8239 test_MFGetSupportedMimeTypes();
8240 test_MFGetSupportedSchemes();
8241 test_sample_copier();
8242 test_sample_copier_output_processing();
8243 test_MFGetTopoNodeCurrentType();
8244 test_MFRequireProtectedEnvironment();
8245 test_wma_encoder();
8246 test_wma_decoder();
8247 test_h264_decoder();
8248 test_audio_convert();
8249 test_color_convert();