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