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