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
33 #include "mmdeviceapi.h"
35 #include "wmcodecdsp.h"
40 #include "wine/test.h"
45 #define DEFINE_EXPECT(func) \
46 static BOOL expect_ ## func = FALSE, called_ ## func = FALSE
48 #define SET_EXPECT(func) \
49 expect_ ## func = TRUE
51 #define CHECK_EXPECT2(func) \
53 ok(expect_ ##func, "unexpected call " #func "\n"); \
54 called_ ## func = TRUE; \
57 #define CHECK_EXPECT(func) \
59 CHECK_EXPECT2(func); \
60 expect_ ## func = FALSE; \
63 #define CHECK_CALLED(func) \
65 ok(called_ ## func, "expected " #func "\n"); \
66 expect_ ## func = called_ ## func = FALSE; \
69 #define CHECK_NOT_CALLED(func) \
71 ok(!called_ ## func, "unexpected " #func "\n"); \
72 expect_ ## func = called_ ## func = FALSE; \
75 #define CLEAR_CALLED(func) \
76 expect_ ## func = called_ ## func = FALSE
78 extern GUID DMOVideoFormat_RGB32
;
80 HRESULT (WINAPI
*pMFCreateSampleCopierMFT
)(IMFTransform
**copier
);
81 HRESULT (WINAPI
*pMFGetTopoNodeCurrentType
)(IMFTopologyNode
*node
, DWORD stream
, BOOL output
, IMFMediaType
**type
);
82 HRESULT (WINAPI
*pMFCreateDXGIDeviceManager
)(UINT
*token
, IMFDXGIDeviceManager
**manager
);
83 BOOL has_video_processor
;
85 static BOOL
is_vista(void)
87 return !pMFGetTopoNodeCurrentType
;
90 #define EXPECT_REF(obj,ref) _expect_ref((IUnknown*)obj, ref, __LINE__)
91 static void _expect_ref(IUnknown
* obj
, ULONG expected_refcount
, int line
)
95 refcount
= IUnknown_Release(obj
);
96 ok_(__FILE__
, line
)(refcount
== expected_refcount
, "Unexpected refcount %ld, expected %ld.\n", refcount
,
100 #define check_interface(a, b, c) check_interface_(__LINE__, a, b, c)
101 static void check_interface_(unsigned int line
, void *iface_ptr
, REFIID iid
, BOOL supported
)
103 IUnknown
*iface
= iface_ptr
;
104 HRESULT hr
, expected_hr
;
107 expected_hr
= supported
? S_OK
: E_NOINTERFACE
;
109 hr
= IUnknown_QueryInterface(iface
, iid
, (void **)&unk
);
110 ok_(__FILE__
, line
)(hr
== expected_hr
, "Got hr %#lx, expected %#lx.\n", hr
, expected_hr
);
112 IUnknown_Release(unk
);
115 #define check_service_interface(a, b, c, d) check_service_interface_(__LINE__, a, b, c, d)
116 static void check_service_interface_(unsigned int line
, void *iface_ptr
, REFGUID service
, REFIID iid
, BOOL supported
)
118 IUnknown
*iface
= iface_ptr
;
119 HRESULT hr
, expected_hr
;
122 expected_hr
= supported
? S_OK
: E_NOINTERFACE
;
124 hr
= MFGetService(iface
, service
, iid
, (void **)&unk
);
125 ok_(__FILE__
, line
)(hr
== expected_hr
, "Got hr %#lx, expected %#lx.\n", hr
, expected_hr
);
127 IUnknown_Release(unk
);
130 static HWND
create_window(void)
132 RECT r
= {0, 0, 640, 480};
134 AdjustWindowRect(&r
, WS_OVERLAPPEDWINDOW
| WS_VISIBLE
, FALSE
);
136 return CreateWindowA("static", "mf_test", WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
137 0, 0, r
.right
- r
.left
, r
.bottom
- r
.top
, NULL
, NULL
, NULL
, NULL
);
140 static IMFSample
*create_sample(const BYTE
*data
, ULONG size
)
142 IMFMediaBuffer
*media_buffer
;
149 hr
= MFCreateSample(&sample
);
150 ok(hr
== S_OK
, "MFCreateSample returned %#lx\n", hr
);
151 hr
= MFCreateMemoryBuffer(size
, &media_buffer
);
152 ok(hr
== S_OK
, "MFCreateMemoryBuffer returned %#lx\n", hr
);
153 hr
= IMFMediaBuffer_Lock(media_buffer
, &buffer
, NULL
, &length
);
154 ok(hr
== S_OK
, "Lock returned %#lx\n", hr
);
155 ok(length
== 0, "got length %lu\n", length
);
156 if (!data
) memset(buffer
, 0xcd, size
);
157 else memcpy(buffer
, data
, size
);
158 hr
= IMFMediaBuffer_Unlock(media_buffer
);
159 ok(hr
== S_OK
, "Unlock returned %#lx\n", hr
);
160 hr
= IMFMediaBuffer_SetCurrentLength(media_buffer
, data
? size
: 0);
161 ok(hr
== S_OK
, "SetCurrentLength returned %#lx\n", hr
);
162 hr
= IMFSample_AddBuffer(sample
, media_buffer
);
163 ok(hr
== S_OK
, "AddBuffer returned %#lx\n", hr
);
164 ret
= IMFMediaBuffer_Release(media_buffer
);
165 ok(ret
== 1, "Release returned %lu\n", ret
);
170 #define check_handler_required_attributes(a, b) check_handler_required_attributes_(__LINE__, a, b)
171 static void check_handler_required_attributes_(int line
, IMFMediaTypeHandler
*handler
, const struct attribute_desc
*attributes
)
173 const struct attribute_desc
*attr
;
174 IMFMediaType
*media_type
;
178 hr
= MFCreateMediaType(&media_type
);
179 ok_(__FILE__
, line
)(hr
== S_OK
, "MFCreateMediaType returned hr %#lx.\n", hr
);
180 init_media_type(media_type
, attributes
, -1);
182 for (attr
= attributes
; attr
&& attr
->key
; attr
++)
184 winetest_push_context("%s", debugstr_a(attr
->name
));
185 hr
= IMFMediaType_DeleteItem(media_type
, attr
->key
);
186 ok_(__FILE__
, line
)(hr
== S_OK
, "DeleteItem returned %#lx\n", hr
);
187 hr
= IMFMediaTypeHandler_IsMediaTypeSupported(handler
, media_type
, NULL
);
188 todo_wine_if(attr
->todo
)
189 ok_(__FILE__
, line
)(FAILED(hr
) == attr
->required
, "IsMediaTypeSupported returned %#lx.\n", hr
);
190 hr
= IMFMediaType_SetItem(media_type
, attr
->key
, &attr
->value
);
191 ok_(__FILE__
, line
)(hr
== S_OK
, "SetItem returned %#lx\n", hr
);
192 winetest_pop_context();
195 hr
= IMFMediaTypeHandler_IsMediaTypeSupported(handler
, media_type
, NULL
);
196 ok_(__FILE__
, line
)(hr
== S_OK
, "IsMediaTypeSupported returned %#lx.\n", hr
);
197 ref
= IMFMediaType_Release(media_type
);
198 ok_(__FILE__
, line
)(!ref
, "Release returned %lu\n", ref
);
201 static void create_descriptors(UINT enum_types_count
, IMFMediaType
**enum_types
, const media_type_desc
*current_desc
,
202 IMFPresentationDescriptor
**pd
, IMFStreamDescriptor
**sd
)
206 hr
= MFCreateStreamDescriptor(0, enum_types_count
, enum_types
, sd
);
207 ok(hr
== S_OK
, "Failed to create stream descriptor, hr %#lx.\n", hr
);
209 hr
= MFCreatePresentationDescriptor(1, sd
, pd
);
210 ok(hr
== S_OK
, "Failed to create presentation descriptor, hr %#lx.\n", hr
);
214 IMFMediaTypeHandler
*handler
;
217 hr
= MFCreateMediaType(&type
);
218 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
219 init_media_type(type
, *current_desc
, -1);
221 hr
= IMFStreamDescriptor_GetMediaTypeHandler(*sd
, &handler
);
222 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
223 hr
= IMFMediaTypeHandler_SetCurrentMediaType(handler
, type
);
224 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
226 IMFMediaTypeHandler_Release(handler
);
227 IMFMediaType_Release(type
);
231 static void init_source_node(IMFMediaSource
*source
, MF_CONNECT_METHOD method
, IMFTopologyNode
*node
,
232 IMFPresentationDescriptor
*pd
, IMFStreamDescriptor
*sd
)
236 hr
= IMFTopologyNode_DeleteAllItems(node
);
237 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
239 hr
= IMFTopologyNode_SetUnknown(node
, &MF_TOPONODE_PRESENTATION_DESCRIPTOR
, (IUnknown
*)pd
);
240 ok(hr
== S_OK
, "Failed to set node pd, hr %#lx.\n", hr
);
241 hr
= IMFTopologyNode_SetUnknown(node
, &MF_TOPONODE_STREAM_DESCRIPTOR
, (IUnknown
*)sd
);
242 ok(hr
== S_OK
, "Failed to set node sd, hr %#lx.\n", hr
);
246 hr
= IMFTopologyNode_SetUINT32(node
, &MF_TOPONODE_CONNECT_METHOD
, method
);
247 ok(hr
== S_OK
, "Failed to set connect method, hr %#lx.\n", hr
);
252 hr
= IMFTopologyNode_SetUnknown(node
, &MF_TOPONODE_SOURCE
, (IUnknown
*)source
);
253 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
257 static void init_sink_node(IMFStreamSink
*stream_sink
, MF_CONNECT_METHOD method
, IMFTopologyNode
*node
)
261 hr
= IMFTopologyNode_DeleteAllItems(node
);
262 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
264 hr
= IMFTopologyNode_SetObject(node
, (IUnknown
*)stream_sink
);
265 ok(hr
== S_OK
, "Failed to set object, hr %#lx.\n", hr
);
269 hr
= IMFTopologyNode_SetUINT32(node
, &MF_TOPONODE_CONNECT_METHOD
, method
);
270 ok(hr
== S_OK
, "Failed to set connect method, hr %#lx.\n", hr
);
274 DEFINE_EXPECT(test_source_BeginGetEvent
);
275 DEFINE_EXPECT(test_source_QueueEvent
);
276 DEFINE_EXPECT(test_source_Start
);
280 IMFMediaSource IMFMediaSource_iface
;
282 HRESULT begin_get_event_res
;
283 IMFPresentationDescriptor
*pd
;
286 static struct test_source
*impl_from_IMFMediaSource(IMFMediaSource
*iface
)
288 return CONTAINING_RECORD(iface
, struct test_source
, IMFMediaSource_iface
);
291 static HRESULT WINAPI
test_source_QueryInterface(IMFMediaSource
*iface
, REFIID riid
, void **out
)
293 if (IsEqualIID(riid
, &IID_IMFMediaSource
)
294 || IsEqualIID(riid
, &IID_IMFMediaEventGenerator
)
295 || IsEqualIID(riid
, &IID_IUnknown
))
302 return E_NOINTERFACE
;
305 IMFMediaSource_AddRef(iface
);
309 static ULONG WINAPI
test_source_AddRef(IMFMediaSource
*iface
)
311 struct test_source
*source
= impl_from_IMFMediaSource(iface
);
312 return InterlockedIncrement(&source
->refcount
);
315 static ULONG WINAPI
test_source_Release(IMFMediaSource
*iface
)
317 struct test_source
*source
= impl_from_IMFMediaSource(iface
);
318 ULONG refcount
= InterlockedDecrement(&source
->refcount
);
322 IMFPresentationDescriptor_Release(source
->pd
);
329 static HRESULT WINAPI
test_source_GetEvent(IMFMediaSource
*iface
, DWORD flags
, IMFMediaEvent
**event
)
331 ok(0, "Unexpected call.\n");
335 static HRESULT WINAPI
test_source_BeginGetEvent(IMFMediaSource
*iface
, IMFAsyncCallback
*callback
, IUnknown
*state
)
337 struct test_source
*source
= impl_from_IMFMediaSource(iface
);
338 CHECK_EXPECT(test_source_BeginGetEvent
);
339 return source
->begin_get_event_res
;
342 static HRESULT WINAPI
test_source_EndGetEvent(IMFMediaSource
*iface
, IMFAsyncResult
*result
, IMFMediaEvent
**event
)
344 ok(0, "Unexpected call.\n");
348 static HRESULT WINAPI
test_source_QueueEvent(IMFMediaSource
*iface
, MediaEventType event_type
, REFGUID ext_type
,
349 HRESULT hr
, const PROPVARIANT
*value
)
351 CHECK_EXPECT(test_source_QueueEvent
);
355 static HRESULT WINAPI
test_source_GetCharacteristics(IMFMediaSource
*iface
, DWORD
*flags
)
361 static HRESULT WINAPI
test_source_CreatePresentationDescriptor(IMFMediaSource
*iface
, IMFPresentationDescriptor
**pd
)
363 struct test_source
*source
= impl_from_IMFMediaSource(iface
);
364 return IMFPresentationDescriptor_Clone(source
->pd
, pd
);
367 static HRESULT WINAPI
test_source_Start(IMFMediaSource
*iface
, IMFPresentationDescriptor
*pd
, const GUID
*time_format
,
368 const PROPVARIANT
*start_position
)
370 CHECK_EXPECT(test_source_Start
);
374 static HRESULT WINAPI
test_source_Stop(IMFMediaSource
*iface
)
376 ok(0, "Unexpected call.\n");
380 static HRESULT WINAPI
test_source_Pause(IMFMediaSource
*iface
)
382 ok(0, "Unexpected call.\n");
386 static HRESULT WINAPI
test_source_Shutdown(IMFMediaSource
*iface
)
388 ok(0, "Unexpected call.\n");
392 static const IMFMediaSourceVtbl test_source_vtbl
=
394 test_source_QueryInterface
,
397 test_source_GetEvent
,
398 test_source_BeginGetEvent
,
399 test_source_EndGetEvent
,
400 test_source_QueueEvent
,
401 test_source_GetCharacteristics
,
402 test_source_CreatePresentationDescriptor
,
406 test_source_Shutdown
,
409 static IMFMediaSource
*create_test_source(IMFPresentationDescriptor
*pd
)
411 struct test_source
*source
;
413 source
= calloc(1, sizeof(*source
));
414 source
->IMFMediaSource_iface
.lpVtbl
= &test_source_vtbl
;
415 source
->refcount
= 1;
416 source
->begin_get_event_res
= E_NOTIMPL
;
417 IMFPresentationDescriptor_AddRef((source
->pd
= pd
));
419 return &source
->IMFMediaSource_iface
;
422 static HRESULT WINAPI
test_unk_QueryInterface(IUnknown
*iface
, REFIID riid
, void **obj
)
424 if (IsEqualIID(riid
, &IID_IUnknown
))
427 IUnknown_AddRef(iface
);
432 return E_NOINTERFACE
;
435 static ULONG WINAPI
test_unk_AddRef(IUnknown
*iface
)
440 static ULONG WINAPI
test_unk_Release(IUnknown
*iface
)
445 static const IUnknownVtbl test_unk_vtbl
=
447 test_unk_QueryInterface
,
452 static void test_topology(void)
454 IMFMediaType
*mediatype
, *mediatype2
, *mediatype3
;
455 IMFCollection
*collection
, *collection2
;
456 IUnknown test_unk2
= { &test_unk_vtbl
};
457 IUnknown test_unk
= { &test_unk_vtbl
};
458 IMFTopologyNode
*node
, *node2
, *node3
;
459 IMFTopology
*topology
, *topology2
;
460 DWORD size
, io_count
, index
;
461 MF_TOPOLOGY_TYPE node_type
;
469 hr
= MFCreateTopology(NULL
);
470 ok(hr
== E_POINTER
, "got %#lx\n", hr
);
472 hr
= MFCreateTopology(&topology
);
473 ok(hr
== S_OK
, "Failed to create topology, hr %#lx.\n", hr
);
474 hr
= IMFTopology_GetTopologyID(topology
, &id
);
475 ok(hr
== S_OK
, "Failed to get id, hr %#lx.\n", hr
);
476 ok(id
== 1, "Unexpected id.\n");
478 hr
= MFCreateTopology(&topology2
);
479 ok(hr
== S_OK
, "Failed to create topology, hr %#lx.\n", hr
);
480 hr
= IMFTopology_GetTopologyID(topology2
, &id
);
481 ok(hr
== S_OK
, "Failed to get id, hr %#lx.\n", hr
);
482 ok(id
== 2, "Unexpected id.\n");
484 ref
= IMFTopology_Release(topology
);
485 ok(ref
== 0, "Release returned %ld\n", ref
);
487 hr
= MFCreateTopology(&topology
);
488 ok(hr
== S_OK
, "Failed to create topology, hr %#lx.\n", hr
);
489 hr
= IMFTopology_GetTopologyID(topology
, &id
);
490 ok(hr
== S_OK
, "Failed to get id, hr %#lx.\n", hr
);
491 ok(id
== 3, "Unexpected id.\n");
493 ref
= IMFTopology_Release(topology2
);
494 ok(ref
== 0, "Release returned %ld\n", ref
);
496 /* No attributes by default. */
497 for (node_type
= MF_TOPOLOGY_OUTPUT_NODE
; node_type
< MF_TOPOLOGY_TEE_NODE
; ++node_type
)
499 hr
= MFCreateTopologyNode(node_type
, &node
);
500 ok(hr
== S_OK
, "Failed to create a node for type %d, hr %#lx.\n", node_type
, hr
);
501 hr
= IMFTopologyNode_GetCount(node
, &count
);
502 ok(hr
== S_OK
, "Failed to get attribute count, hr %#lx.\n", hr
);
503 ok(!count
, "Unexpected attribute count %u.\n", count
);
504 ref
= IMFTopologyNode_Release(node
);
505 ok(ref
== 0, "Release returned %ld\n", ref
);
508 hr
= MFCreateTopologyNode(MF_TOPOLOGY_OUTPUT_NODE
, NULL
);
509 ok(hr
== E_POINTER
, "Unexpected hr %#lx.\n", hr
);
511 hr
= MFCreateTopologyNode(MF_TOPOLOGY_OUTPUT_NODE
, &node
);
512 ok(hr
== S_OK
, "Failed to create topology node, hr %#lx.\n", hr
);
514 hr
= MFCreateTopologyNode(MF_TOPOLOGY_TEE_NODE
, &node2
);
515 ok(hr
== S_OK
, "Failed to create topology node, hr %#lx.\n", hr
);
517 hr
= IMFTopologyNode_GetTopoNodeID(node
, &id
);
518 ok(hr
== S_OK
, "Failed to get node id, hr %#lx.\n", hr
);
519 ok(((id
>> 32) == GetCurrentProcessId()) && !!(id
& 0xffff), "Unexpected node id %s.\n", wine_dbgstr_longlong(id
));
521 hr
= IMFTopologyNode_SetTopoNodeID(node2
, id
);
522 ok(hr
== S_OK
, "Failed to set node id, hr %#lx.\n", hr
);
524 hr
= IMFTopology_GetNodeCount(topology
, NULL
);
525 ok(hr
== E_POINTER
, "Unexpected hr %#lx.\n", hr
);
527 hr
= IMFTopology_AddNode(topology
, NULL
);
528 ok(hr
== E_POINTER
, "Unexpected hr %#lx.\n", hr
);
531 hr
= IMFTopology_GetNodeCount(topology
, &node_count
);
532 ok(hr
== S_OK
, "Failed to get node count, hr %#lx.\n", hr
);
533 ok(node_count
== 0, "Unexpected node count %u.\n", node_count
);
535 /* Same id, different nodes. */
536 hr
= IMFTopology_AddNode(topology
, node
);
537 ok(hr
== S_OK
, "Failed to add a node, hr %#lx.\n", hr
);
540 hr
= IMFTopology_GetNodeCount(topology
, &node_count
);
541 ok(hr
== S_OK
, "Failed to get node count, hr %#lx.\n", hr
);
542 ok(node_count
== 1, "Unexpected node count %u.\n", node_count
);
544 hr
= IMFTopology_AddNode(topology
, node2
);
545 ok(hr
== E_INVALIDARG
, "Unexpected hr %#lx.\n", hr
);
546 ref
= IMFTopologyNode_Release(node2
);
547 ok(ref
== 0, "Release returned %ld\n", ref
);
549 hr
= IMFTopology_GetNodeByID(topology
, id
, &node2
);
550 ok(hr
== S_OK
, "Failed to get a node, hr %#lx.\n", hr
);
551 ok(node2
== node
, "Unexpected node.\n");
552 IMFTopologyNode_Release(node2
);
554 /* Change node id, add it again. */
555 hr
= IMFTopologyNode_SetTopoNodeID(node
, ++id
);
556 ok(hr
== S_OK
, "Failed to set node id, hr %#lx.\n", hr
);
558 hr
= IMFTopology_GetNodeByID(topology
, id
, &node2
);
559 ok(hr
== S_OK
, "Failed to get a node, hr %#lx.\n", hr
);
560 ok(node2
== node
, "Unexpected node.\n");
561 IMFTopologyNode_Release(node2
);
563 hr
= IMFTopology_GetNodeByID(topology
, id
+ 1, &node2
);
564 ok(hr
== MF_E_NOT_FOUND
, "Unexpected hr %#lx.\n", hr
);
566 hr
= IMFTopology_AddNode(topology
, node
);
567 ok(hr
== E_INVALIDARG
, "Failed to add a node, hr %#lx.\n", hr
);
569 hr
= IMFTopology_GetNode(topology
, 0, &node2
);
570 ok(hr
== S_OK
, "Failed to get a node, hr %#lx.\n", hr
);
571 ok(node2
== node
, "Unexpected node.\n");
572 IMFTopologyNode_Release(node2
);
574 hr
= IMFTopology_GetNode(topology
, 1, NULL
);
575 ok(hr
== E_POINTER
, "Unexpected hr %#lx.\n", hr
);
577 hr
= IMFTopology_GetNode(topology
, 1, &node2
);
578 ok(hr
== MF_E_INVALIDINDEX
, "Failed to get a node, hr %#lx.\n", hr
);
580 hr
= IMFTopology_GetNode(topology
, -2, &node2
);
581 ok(hr
== MF_E_INVALIDINDEX
, "Failed to get a node, hr %#lx.\n", hr
);
583 hr
= MFCreateTopologyNode(MF_TOPOLOGY_TEE_NODE
, &node2
);
584 ok(hr
== S_OK
, "Failed to create topology node, hr %#lx.\n", hr
);
585 hr
= IMFTopology_AddNode(topology
, node2
);
586 ok(hr
== S_OK
, "Failed to add a node, hr %#lx.\n", hr
);
587 ref
= IMFTopologyNode_Release(node2
);
588 ok(ref
== 1, "Release returned %ld\n", ref
);
591 hr
= IMFTopology_GetNodeCount(topology
, &node_count
);
592 ok(hr
== S_OK
, "Failed to get node count, hr %#lx.\n", hr
);
593 ok(node_count
== 2, "Unexpected node count %u.\n", node_count
);
595 /* Remove with detached node, existing id. */
596 hr
= MFCreateTopologyNode(MF_TOPOLOGY_TEE_NODE
, &node2
);
597 ok(hr
== S_OK
, "Failed to create topology node, hr %#lx.\n", hr
);
598 hr
= IMFTopologyNode_SetTopoNodeID(node2
, id
);
599 ok(hr
== S_OK
, "Failed to set node id, hr %#lx.\n", hr
);
600 hr
= IMFTopology_RemoveNode(topology
, node2
);
601 ok(hr
== E_INVALIDARG
, "Unexpected hr %#lx.\n", hr
);
602 ref
= IMFTopologyNode_Release(node2
);
603 ok(ref
== 0, "Release returned %ld\n", ref
);
605 hr
= IMFTopology_RemoveNode(topology
, node
);
606 ok(hr
== S_OK
, "Failed to remove a node, hr %#lx.\n", hr
);
609 hr
= IMFTopology_GetNodeCount(topology
, &node_count
);
610 ok(hr
== S_OK
, "Failed to get node count, hr %#lx.\n", hr
);
611 ok(node_count
== 1, "Unexpected node count %u.\n", node_count
);
613 hr
= IMFTopology_Clear(topology
);
614 ok(hr
== S_OK
, "Failed to clear topology, hr %#lx.\n", hr
);
617 hr
= IMFTopology_GetNodeCount(topology
, &node_count
);
618 ok(hr
== S_OK
, "Failed to get node count, hr %#lx.\n", hr
);
619 ok(node_count
== 0, "Unexpected node count %u.\n", node_count
);
621 hr
= IMFTopology_Clear(topology
);
622 ok(hr
== S_OK
, "Failed to clear topology, hr %#lx.\n", hr
);
624 hr
= IMFTopologyNode_SetTopoNodeID(node
, 123);
625 ok(hr
== S_OK
, "Failed to set node id, hr %#lx.\n", hr
);
627 ref
= IMFTopologyNode_Release(node
);
628 ok(ref
== 0, "Release returned %ld\n", ref
);
630 /* Change id for attached node. */
631 hr
= MFCreateTopologyNode(MF_TOPOLOGY_OUTPUT_NODE
, &node
);
632 ok(hr
== S_OK
, "Failed to create topology node, hr %#lx.\n", hr
);
634 hr
= MFCreateTopologyNode(MF_TOPOLOGY_TEE_NODE
, &node2
);
635 ok(hr
== S_OK
, "Failed to create topology 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 hr
= IMFTopology_AddNode(topology
, node2
);
641 ok(hr
== S_OK
, "Failed to add a node, hr %#lx.\n", hr
);
643 hr
= IMFTopologyNode_GetTopoNodeID(node
, &id
);
644 ok(hr
== S_OK
, "Failed to get node id, hr %#lx.\n", hr
);
646 hr
= IMFTopologyNode_SetTopoNodeID(node2
, id
);
647 ok(hr
== S_OK
, "Failed to get node id, hr %#lx.\n", hr
);
649 hr
= IMFTopology_GetNodeByID(topology
, id
, &node3
);
650 ok(hr
== S_OK
, "Failed to get a node, hr %#lx.\n", hr
);
651 ok(node3
== node
, "Unexpected node.\n");
652 IMFTopologyNode_Release(node3
);
654 /* Source/output collections. */
655 hr
= IMFTopology_Clear(topology
);
656 ok(hr
== S_OK
, "Failed to clear topology, hr %#lx.\n", hr
);
658 ref
= IMFTopologyNode_Release(node
);
659 ok(ref
== 0, "Release returned %ld\n", ref
);
660 ref
= IMFTopologyNode_Release(node2
);
661 ok(ref
== 0, "Release returned %ld\n", ref
);
663 hr
= IMFTopology_GetSourceNodeCollection(topology
, NULL
);
664 ok(hr
== E_POINTER
, "Unexpected hr %#lx.\n", hr
);
666 hr
= IMFTopology_GetSourceNodeCollection(topology
, &collection
);
667 ok(hr
== S_OK
, "Failed to get source node collection, hr %#lx.\n", hr
);
668 ok(!!collection
, "Unexpected object pointer.\n");
670 hr
= IMFTopology_GetSourceNodeCollection(topology
, &collection2
);
671 ok(hr
== S_OK
, "Failed to get source node collection, hr %#lx.\n", hr
);
672 ok(!!collection2
, "Unexpected object pointer.\n");
673 ok(collection2
!= collection
, "Expected cloned collection.\n");
675 hr
= IMFCollection_GetElementCount(collection
, &size
);
676 ok(hr
== S_OK
, "Failed to get item count, hr %#lx.\n", hr
);
677 ok(!size
, "Unexpected item count.\n");
679 EXPECT_REF(collection
, 1);
680 hr
= IMFCollection_AddElement(collection
, (IUnknown
*)collection
);
681 ok(hr
== S_OK
, "Failed to add element, hr %#lx.\n", hr
);
682 EXPECT_REF(collection
, 2);
684 hr
= IMFCollection_GetElementCount(collection
, &size
);
685 ok(hr
== S_OK
, "Failed to get item count, hr %#lx.\n", hr
);
686 ok(size
== 1, "Unexpected item count.\n");
688 /* Empty collection to stop referencing itself */
689 hr
= IMFCollection_RemoveAllElements(collection
);
690 ok(hr
== S_OK
, "Failed to get item count, hr %#lx.\n", hr
);
692 hr
= IMFCollection_GetElementCount(collection2
, &size
);
693 ok(hr
== S_OK
, "Failed to get item count, hr %#lx.\n", hr
);
694 ok(!size
, "Unexpected item count.\n");
696 ref
= IMFCollection_Release(collection2
);
697 ok(ref
== 0, "Release returned %ld\n", ref
);
698 ref
= IMFCollection_Release(collection
);
699 ok(ref
== 0, "Release returned %ld\n", ref
);
701 /* Add some nodes. */
702 hr
= IMFTopology_GetSourceNodeCollection(topology
, NULL
);
703 ok(hr
== E_POINTER
, "Unexpected hr %#lx.\n", hr
);
705 hr
= IMFTopology_GetOutputNodeCollection(topology
, NULL
);
706 ok(hr
== E_POINTER
, "Unexpected hr %#lx.\n", hr
);
708 hr
= MFCreateTopologyNode(MF_TOPOLOGY_SOURCESTREAM_NODE
, &node
);
709 ok(hr
== S_OK
, "Failed to create a node, hr %#lx.\n", hr
);
710 hr
= IMFTopology_AddNode(topology
, node
);
711 ok(hr
== S_OK
, "Failed to add a node, hr %#lx.\n", hr
);
712 IMFTopologyNode_Release(node
);
714 hr
= IMFTopology_GetSourceNodeCollection(topology
, &collection
);
715 ok(hr
== S_OK
, "Failed to get source node collection, hr %#lx.\n", hr
);
716 ok(!!collection
, "Unexpected object pointer.\n");
717 hr
= IMFCollection_GetElementCount(collection
, &size
);
718 ok(hr
== S_OK
, "Failed to get item count, hr %#lx.\n", hr
);
719 ok(size
== 1, "Unexpected item count.\n");
720 ref
= IMFCollection_Release(collection
);
721 ok(ref
== 0, "Release returned %ld\n", ref
);
723 hr
= MFCreateTopologyNode(MF_TOPOLOGY_TEE_NODE
, &node
);
724 ok(hr
== S_OK
, "Failed to create a node, hr %#lx.\n", hr
);
725 hr
= IMFTopology_AddNode(topology
, node
);
726 ok(hr
== S_OK
, "Failed to add a node, hr %#lx.\n", hr
);
727 IMFTopologyNode_Release(node
);
729 hr
= IMFTopology_GetSourceNodeCollection(topology
, &collection
);
730 ok(hr
== S_OK
, "Failed to get source node collection, hr %#lx.\n", hr
);
731 ok(!!collection
, "Unexpected object pointer.\n");
732 hr
= IMFCollection_GetElementCount(collection
, &size
);
733 ok(hr
== S_OK
, "Failed to get item count, hr %#lx.\n", hr
);
734 ok(size
== 1, "Unexpected item count.\n");
735 ref
= IMFCollection_Release(collection
);
736 ok(ref
== 0, "Release returned %ld\n", ref
);
738 hr
= MFCreateTopologyNode(MF_TOPOLOGY_TRANSFORM_NODE
, &node
);
739 ok(hr
== S_OK
, "Failed to create a node, hr %#lx.\n", hr
);
740 hr
= IMFTopology_AddNode(topology
, node
);
741 ok(hr
== S_OK
, "Failed to add a node, hr %#lx.\n", hr
);
742 IMFTopologyNode_Release(node
);
744 hr
= IMFTopology_GetSourceNodeCollection(topology
, &collection
);
745 ok(hr
== S_OK
, "Failed to get source node collection, hr %#lx.\n", hr
);
746 ok(!!collection
, "Unexpected object pointer.\n");
747 hr
= IMFCollection_GetElementCount(collection
, &size
);
748 ok(hr
== S_OK
, "Failed to get item count, hr %#lx.\n", hr
);
749 ok(size
== 1, "Unexpected item count.\n");
750 ref
= IMFCollection_Release(collection
);
751 ok(ref
== 0, "Release returned %ld\n", ref
);
753 hr
= MFCreateTopologyNode(MF_TOPOLOGY_OUTPUT_NODE
, &node
);
754 ok(hr
== S_OK
, "Failed to create a node, hr %#lx.\n", hr
);
755 hr
= IMFTopology_AddNode(topology
, node
);
756 ok(hr
== S_OK
, "Failed to add a node, hr %#lx.\n", hr
);
758 /* Associated object. */
759 hr
= IMFTopologyNode_SetObject(node
, NULL
);
760 ok(hr
== S_OK
, "Failed to set object, hr %#lx.\n", hr
);
762 hr
= IMFTopologyNode_GetObject(node
, NULL
);
763 ok(hr
== E_POINTER
, "Unexpected hr %#lx.\n", hr
);
765 object
= (void *)0xdeadbeef;
766 hr
= IMFTopologyNode_GetObject(node
, &object
);
767 ok(hr
== E_FAIL
, "Unexpected hr %#lx.\n", hr
);
768 ok(!object
, "Unexpected object %p.\n", object
);
770 hr
= IMFTopologyNode_SetObject(node
, &test_unk
);
771 ok(hr
== S_OK
, "Failed to set object, hr %#lx.\n", hr
);
773 hr
= IMFTopologyNode_GetObject(node
, &object
);
774 ok(hr
== S_OK
, "Failed to get object, hr %#lx.\n", hr
);
775 ok(object
== &test_unk
, "Unexpected object %p.\n", object
);
776 IUnknown_Release(object
);
778 hr
= IMFTopologyNode_SetObject(node
, &test_unk2
);
779 ok(hr
== S_OK
, "Failed to set object, hr %#lx.\n", hr
);
781 hr
= IMFTopologyNode_GetCount(node
, &count
);
782 ok(hr
== S_OK
, "Failed to get attribute count, hr %#lx.\n", hr
);
783 ok(count
== 0, "Unexpected attribute count %u.\n", count
);
785 hr
= IMFTopologyNode_SetGUID(node
, &MF_TOPONODE_TRANSFORM_OBJECTID
, &MF_TOPONODE_TRANSFORM_OBJECTID
);
786 ok(hr
== S_OK
, "Failed to set attribute, hr %#lx.\n", hr
);
788 hr
= IMFTopologyNode_SetObject(node
, NULL
);
789 ok(hr
== S_OK
, "Failed to set object, hr %#lx.\n", hr
);
791 object
= (void *)0xdeadbeef;
792 hr
= IMFTopologyNode_GetObject(node
, &object
);
793 ok(hr
== E_FAIL
, "Unexpected hr %#lx.\n", hr
);
794 ok(!object
, "Unexpected object %p.\n", object
);
796 hr
= IMFTopologyNode_GetCount(node
, &count
);
797 ok(hr
== S_OK
, "Failed to get attribute count, hr %#lx.\n", hr
);
798 ok(count
== 1, "Unexpected attribute count %u.\n", count
);
800 /* Preferred stream types. */
801 hr
= IMFTopologyNode_GetInputCount(node
, &io_count
);
802 ok(hr
== S_OK
, "Failed to get input count, hr %#lx.\n", hr
);
803 ok(io_count
== 0, "Unexpected count %lu.\n", io_count
);
805 hr
= IMFTopologyNode_GetInputPrefType(node
, 0, &mediatype
);
806 ok(hr
== E_INVALIDARG
, "Unexpected hr %#lx.\n", hr
);
808 hr
= MFCreateMediaType(&mediatype
);
809 ok(hr
== S_OK
, "Failed to create media type, hr %#lx.\n", hr
);
811 hr
= IMFTopologyNode_SetInputPrefType(node
, 0, mediatype
);
812 ok(hr
== S_OK
, "Failed to set preferred type, hr %#lx.\n", hr
);
814 hr
= IMFTopologyNode_GetInputPrefType(node
, 0, &mediatype2
);
815 ok(hr
== S_OK
, "Failed to get preferred type, hr %#lx.\n", hr
);
816 ok(mediatype2
== mediatype
, "Unexpected mediatype instance.\n");
817 IMFMediaType_Release(mediatype2
);
819 hr
= IMFTopologyNode_SetInputPrefType(node
, 0, NULL
);
820 ok(hr
== S_OK
, "Failed to set preferred type, hr %#lx.\n", hr
);
822 hr
= IMFTopologyNode_GetInputPrefType(node
, 0, &mediatype2
);
823 ok(hr
== E_FAIL
, "Unexpected hr %#lx.\n", hr
);
824 ok(!mediatype2
, "Unexpected mediatype instance.\n");
826 hr
= IMFTopologyNode_SetInputPrefType(node
, 1, mediatype
);
827 ok(hr
== S_OK
, "Failed to set preferred type, hr %#lx.\n", hr
);
829 hr
= IMFTopologyNode_SetInputPrefType(node
, 1, mediatype
);
830 ok(hr
== S_OK
, "Failed to set preferred type, hr %#lx.\n", hr
);
832 hr
= IMFTopologyNode_GetInputCount(node
, &io_count
);
833 ok(hr
== S_OK
, "Failed to get input count, hr %#lx.\n", hr
);
834 ok(io_count
== 2, "Unexpected count %lu.\n", io_count
);
836 hr
= IMFTopologyNode_GetOutputCount(node
, &io_count
);
837 ok(hr
== S_OK
, "Failed to get input count, hr %#lx.\n", hr
);
838 ok(io_count
== 0, "Unexpected count %lu.\n", io_count
);
840 hr
= IMFTopologyNode_SetOutputPrefType(node
, 0, mediatype
);
841 ok(hr
== E_NOTIMPL
, "Unexpected hr %#lx.\n", hr
);
843 ref
= IMFTopologyNode_Release(node
);
844 ok(ref
== 1, "Release returned %ld\n", ref
);
847 hr
= MFCreateTopologyNode(MF_TOPOLOGY_SOURCESTREAM_NODE
, &node
);
848 ok(hr
== S_OK
, "Failed to create a node, hr %#lx.\n", hr
);
850 hr
= IMFTopologyNode_SetInputPrefType(node
, 0, mediatype
);
851 ok(hr
== E_NOTIMPL
, "Unexpected hr %#lx.\n", hr
);
853 hr
= IMFTopologyNode_SetOutputPrefType(node
, 2, mediatype
);
854 ok(hr
== S_OK
, "Failed to set preferred type, hr %#lx.\n", hr
);
856 hr
= IMFTopologyNode_GetOutputPrefType(node
, 0, &mediatype2
);
857 ok(hr
== E_FAIL
, "Failed to get preferred type, hr %#lx.\n", hr
);
858 ok(!mediatype2
, "Unexpected mediatype instance.\n");
860 hr
= IMFTopologyNode_GetOutputCount(node
, &io_count
);
861 ok(hr
== S_OK
, "Failed to get output count, hr %#lx.\n", hr
);
862 ok(io_count
== 3, "Unexpected count %lu.\n", io_count
);
864 ref
= IMFTopologyNode_Release(node
);
865 ok(ref
== 0, "Release returned %ld\n", ref
);
868 hr
= MFCreateTopologyNode(MF_TOPOLOGY_TEE_NODE
, &node
);
869 ok(hr
== S_OK
, "Failed to create a node, hr %#lx.\n", hr
);
871 hr
= IMFTopologyNode_SetInputPrefType(node
, 0, mediatype
);
872 ok(hr
== S_OK
, "Failed to set preferred type, hr %#lx.\n", hr
);
874 hr
= IMFTopologyNode_GetInputPrefType(node
, 0, &mediatype2
);
875 ok(hr
== S_OK
, "Failed to get preferred type, hr %#lx.\n", hr
);
876 ok(mediatype2
== mediatype
, "Unexpected mediatype instance.\n");
877 IMFMediaType_Release(mediatype2
);
879 hr
= IMFTopologyNode_GetOutputPrefType(node
, 0, &mediatype2
);
880 ok(hr
== E_INVALIDARG
, "Unexpected hr %#lx.\n", hr
);
882 hr
= IMFTopologyNode_GetInputCount(node
, &io_count
);
883 ok(hr
== S_OK
, "Failed to get output count, hr %#lx.\n", hr
);
884 ok(io_count
== 0, "Unexpected count %lu.\n", io_count
);
886 hr
= IMFTopologyNode_SetInputPrefType(node
, 1, mediatype
);
887 ok(hr
== MF_E_INVALIDTYPE
, "Unexpected hr %#lx.\n", hr
);
889 hr
= IMFTopologyNode_SetInputPrefType(node
, 3, mediatype
);
890 ok(hr
== MF_E_INVALIDTYPE
, "Unexpected hr %#lx.\n", hr
);
892 hr
= IMFTopologyNode_SetOutputPrefType(node
, 4, mediatype
);
893 ok(hr
== S_OK
, "Failed to set preferred type, hr %#lx.\n", hr
);
895 hr
= IMFTopologyNode_GetOutputPrefType(node
, 0, &mediatype2
);
896 ok(hr
== E_FAIL
, "Unexpected hr %#lx.\n", hr
);
898 hr
= MFCreateMediaType(&mediatype2
);
899 ok(hr
== S_OK
, "Failed to create media type, hr %#lx.\n", hr
);
901 /* Changing output type does not change input type. */
902 hr
= IMFTopologyNode_SetOutputPrefType(node
, 4, mediatype2
);
903 ok(hr
== S_OK
, "Failed to set preferred type, hr %#lx.\n", hr
);
905 hr
= IMFTopologyNode_GetInputPrefType(node
, 0, &mediatype3
);
906 ok(hr
== S_OK
, "Failed to get preferred type, hr %#lx.\n", hr
);
907 ok(mediatype3
== mediatype
, "Unexpected mediatype instance.\n");
908 IMFMediaType_Release(mediatype3
);
910 IMFMediaType_Release(mediatype2
);
912 hr
= IMFTopologyNode_GetInputCount(node
, &io_count
);
913 ok(hr
== S_OK
, "Failed to get output count, hr %#lx.\n", hr
);
914 ok(io_count
== 0, "Unexpected count %lu.\n", io_count
);
916 hr
= IMFTopologyNode_GetOutputCount(node
, &io_count
);
917 ok(hr
== S_OK
, "Failed to get output count, hr %#lx.\n", hr
);
918 ok(io_count
== 5, "Unexpected count %lu.\n", io_count
);
920 ref
= IMFTopologyNode_Release(node
);
921 ok(ref
== 0, "Release returned %ld\n", ref
);
923 /* Transform node. */
924 hr
= MFCreateTopologyNode(MF_TOPOLOGY_TRANSFORM_NODE
, &node
);
925 ok(hr
== S_OK
, "Failed to create a node, hr %#lx.\n", hr
);
927 hr
= IMFTopologyNode_SetInputPrefType(node
, 3, mediatype
);
928 ok(hr
== S_OK
, "Failed to set preferred type, hr %#lx.\n", hr
);
930 hr
= IMFTopologyNode_GetInputCount(node
, &io_count
);
931 ok(hr
== S_OK
, "Failed to get input count, hr %#lx.\n", hr
);
932 ok(io_count
== 4, "Unexpected count %lu.\n", io_count
);
934 hr
= IMFTopologyNode_SetOutputPrefType(node
, 4, mediatype
);
935 ok(hr
== S_OK
, "Failed to set preferred type, hr %#lx.\n", hr
);
937 hr
= IMFTopologyNode_GetInputCount(node
, &io_count
);
938 ok(hr
== S_OK
, "Failed to get output count, hr %#lx.\n", hr
);
939 ok(io_count
== 4, "Unexpected count %lu.\n", io_count
);
941 hr
= IMFTopologyNode_GetOutputCount(node
, &io_count
);
942 ok(hr
== S_OK
, "Failed to get output count, hr %#lx.\n", hr
);
943 ok(io_count
== 5, "Unexpected count %lu.\n", io_count
);
945 ref
= IMFTopologyNode_Release(node
);
946 ok(ref
== 0, "Release returned %ld\n", ref
);
948 IMFMediaType_Release(mediatype
);
950 hr
= IMFTopology_GetOutputNodeCollection(topology
, &collection
);
951 ok(hr
== S_OK
|| broken(hr
== E_FAIL
) /* before Win8 */, "Failed to get output node collection, hr %#lx.\n", hr
);
954 ok(!!collection
, "Unexpected object pointer.\n");
955 hr
= IMFCollection_GetElementCount(collection
, &size
);
956 ok(hr
== S_OK
, "Failed to get item count, hr %#lx.\n", hr
);
957 ok(size
== 1, "Unexpected item count.\n");
958 ref
= IMFCollection_Release(collection
);
959 ok(ref
== 0, "Release returned %ld\n", ref
);
962 ref
= IMFTopology_Release(topology
);
963 ok(ref
== 0, "Release returned %ld\n", ref
);
966 hr
= MFCreateTopologyNode(MF_TOPOLOGY_SOURCESTREAM_NODE
, &node
);
967 ok(hr
== S_OK
, "Failed to create topology node, hr %#lx.\n", hr
);
969 hr
= MFCreateTopologyNode(MF_TOPOLOGY_OUTPUT_NODE
, &node2
);
970 ok(hr
== S_OK
, "Failed to create topology node, hr %#lx.\n", hr
);
973 EXPECT_REF(node2
, 1);
975 hr
= IMFTopologyNode_ConnectOutput(node
, 0, node2
, 1);
976 ok(hr
== S_OK
, "Failed to connect nodes, hr %#lx.\n", hr
);
979 EXPECT_REF(node2
, 2);
981 IMFTopologyNode_Release(node
);
984 EXPECT_REF(node2
, 2);
986 IMFTopologyNode_Release(node2
);
989 EXPECT_REF(node2
, 1);
991 hr
= IMFTopologyNode_GetNodeType(node2
, &node_type
);
992 ok(hr
== S_OK
, "Failed to get node type, hr %#lx.\n", hr
);
994 IMFTopologyNode_Release(node
);
996 /* Connect within topology. */
997 hr
= MFCreateTopologyNode(MF_TOPOLOGY_SOURCESTREAM_NODE
, &node
);
998 ok(hr
== S_OK
, "Failed to create topology node, hr %#lx.\n", hr
);
1000 hr
= MFCreateTopologyNode(MF_TOPOLOGY_OUTPUT_NODE
, &node2
);
1001 ok(hr
== S_OK
, "Failed to create topology node, hr %#lx.\n", hr
);
1003 hr
= MFCreateTopology(&topology
);
1004 ok(hr
== S_OK
, "Failed to create topology, hr %#lx.\n", hr
);
1006 hr
= IMFTopology_AddNode(topology
, node
);
1007 ok(hr
== S_OK
, "Failed to add a node, hr %#lx.\n", hr
);
1009 hr
= IMFTopology_AddNode(topology
, node2
);
1010 ok(hr
== S_OK
, "Failed to add a node, hr %#lx.\n", hr
);
1012 EXPECT_REF(node
, 2);
1013 EXPECT_REF(node2
, 2);
1015 hr
= IMFTopologyNode_ConnectOutput(node
, 0, node2
, 1);
1016 ok(hr
== S_OK
, "Failed to connect nodes, hr %#lx.\n", hr
);
1018 EXPECT_REF(node
, 3);
1019 EXPECT_REF(node2
, 3);
1021 hr
= IMFTopology_Clear(topology
);
1022 ok(hr
== S_OK
, "Failed to clear topology, hr %#lx.\n", hr
);
1024 EXPECT_REF(node
, 1);
1025 EXPECT_REF(node2
, 1);
1027 /* Removing connected node breaks connection. */
1028 hr
= IMFTopology_AddNode(topology
, node
);
1029 ok(hr
== S_OK
, "Failed to add a node, hr %#lx.\n", hr
);
1031 hr
= IMFTopology_AddNode(topology
, node2
);
1032 ok(hr
== S_OK
, "Failed to add a node, hr %#lx.\n", hr
);
1034 hr
= IMFTopologyNode_ConnectOutput(node
, 0, node2
, 1);
1035 ok(hr
== S_OK
, "Failed to connect nodes, hr %#lx.\n", hr
);
1037 hr
= IMFTopology_RemoveNode(topology
, node
);
1038 ok(hr
== S_OK
, "Failed to remove a node, hr %#lx.\n", hr
);
1040 EXPECT_REF(node
, 1);
1041 EXPECT_REF(node2
, 2);
1043 hr
= IMFTopologyNode_GetOutput(node
, 0, &node3
, &index
);
1044 ok(hr
== MF_E_NOT_FOUND
, "Unexpected hr %#lx.\n", hr
);
1046 hr
= IMFTopology_AddNode(topology
, node
);
1047 ok(hr
== S_OK
, "Failed to add a node, hr %#lx.\n", hr
);
1049 hr
= IMFTopologyNode_ConnectOutput(node
, 0, node2
, 1);
1050 ok(hr
== S_OK
, "Failed to connect nodes, hr %#lx.\n", hr
);
1052 hr
= IMFTopology_RemoveNode(topology
, node2
);
1053 ok(hr
== S_OK
, "Failed to remove a node, hr %#lx.\n", hr
);
1055 EXPECT_REF(node
, 2);
1056 EXPECT_REF(node2
, 1);
1058 IMFTopologyNode_Release(node
);
1059 IMFTopologyNode_Release(node2
);
1061 /* Cloning nodes of different types. */
1062 hr
= MFCreateTopologyNode(MF_TOPOLOGY_SOURCESTREAM_NODE
, &node
);
1063 ok(hr
== S_OK
, "Failed to create topology node, hr %#lx.\n", hr
);
1065 hr
= MFCreateTopologyNode(MF_TOPOLOGY_OUTPUT_NODE
, &node2
);
1066 ok(hr
== S_OK
, "Failed to create topology node, hr %#lx.\n", hr
);
1068 hr
= IMFTopologyNode_CloneFrom(node
, node2
);
1069 ok(hr
== MF_E_INVALIDREQUEST
, "Unexpected hr %#lx.\n", hr
);
1071 ref
= IMFTopologyNode_Release(node2
);
1072 ok(ref
== 0, "Release returned %ld\n", ref
);
1074 /* Cloning preferred types. */
1075 hr
= MFCreateTopologyNode(MF_TOPOLOGY_SOURCESTREAM_NODE
, &node2
);
1076 ok(hr
== S_OK
, "Failed to create topology node, hr %#lx.\n", hr
);
1078 hr
= MFCreateMediaType(&mediatype
);
1079 ok(hr
== S_OK
, "Failed to create media type, hr %#lx.\n", hr
);
1081 hr
= IMFTopologyNode_SetOutputPrefType(node2
, 0, mediatype
);
1082 ok(hr
== S_OK
, "Failed to set preferred type, hr %#lx.\n", hr
);
1084 /* Vista checks for additional attributes. */
1085 hr
= IMFTopologyNode_CloneFrom(node
, node2
);
1086 ok(hr
== S_OK
|| broken(hr
== MF_E_ATTRIBUTENOTFOUND
) /* Vista */, "Failed to clone a node, hr %#lx.\n", hr
);
1088 hr
= IMFTopologyNode_GetOutputPrefType(node
, 0, &mediatype2
);
1089 ok(hr
== S_OK
, "Failed to get preferred type, hr %#lx.\n", hr
);
1090 ok(mediatype
== mediatype2
, "Unexpected media type.\n");
1092 IMFMediaType_Release(mediatype2
);
1094 ref
= IMFTopologyNode_Release(node2
);
1095 ok(ref
== 0, "Release returned %ld\n", ref
);
1097 IMFMediaType_Release(mediatype
);
1099 /* Existing preferred types are not cleared. */
1100 hr
= MFCreateTopologyNode(MF_TOPOLOGY_SOURCESTREAM_NODE
, &node2
);
1101 ok(hr
== S_OK
, "Failed to create topology node, hr %#lx.\n", hr
);
1103 hr
= IMFTopologyNode_GetOutputCount(node
, &io_count
);
1104 ok(hr
== S_OK
, "Failed to get output count, hr %#lx.\n", hr
);
1105 ok(io_count
== 1, "Unexpected output count.\n");
1107 hr
= IMFTopologyNode_CloneFrom(node
, node2
);
1108 ok(hr
== S_OK
|| broken(hr
== MF_E_ATTRIBUTENOTFOUND
) /* Vista */, "Failed to clone a node, hr %#lx.\n", hr
);
1110 hr
= IMFTopologyNode_GetOutputCount(node
, &io_count
);
1111 ok(hr
== S_OK
, "Failed to get output count, hr %#lx.\n", hr
);
1112 ok(io_count
== 1, "Unexpected output count.\n");
1114 hr
= IMFTopologyNode_GetOutputPrefType(node
, 0, &mediatype2
);
1115 ok(hr
== S_OK
, "Failed to get preferred type, hr %#lx.\n", hr
);
1116 ok(!!mediatype2
, "Unexpected media type.\n");
1117 IMFMediaType_Release(mediatype2
);
1119 hr
= IMFTopologyNode_CloneFrom(node2
, node
);
1120 ok(hr
== S_OK
|| broken(hr
== MF_E_ATTRIBUTENOTFOUND
) /* Vista */, "Failed to clone a node, hr %#lx.\n", hr
);
1122 hr
= IMFTopologyNode_GetOutputCount(node2
, &io_count
);
1123 ok(hr
== S_OK
, "Failed to get output count, hr %#lx.\n", hr
);
1124 ok(io_count
== 1, "Unexpected output count.\n");
1126 ref
= IMFTopologyNode_Release(node2
);
1127 ok(ref
== 0, "Release returned %ld\n", ref
);
1128 ref
= IMFTopologyNode_Release(node
);
1129 ok(ref
== 0, "Release returned %ld\n", ref
);
1131 /* Add one node, connect to another that hasn't been added. */
1132 hr
= IMFTopology_Clear(topology
);
1133 ok(hr
== S_OK
, "Failed to clear topology, hr %#lx.\n", hr
);
1135 hr
= MFCreateTopologyNode(MF_TOPOLOGY_SOURCESTREAM_NODE
, &node
);
1136 ok(hr
== S_OK
, "Failed to create topology node, hr %#lx.\n", hr
);
1138 hr
= MFCreateTopologyNode(MF_TOPOLOGY_OUTPUT_NODE
, &node2
);
1139 ok(hr
== S_OK
, "Failed to create topology node, hr %#lx.\n", hr
);
1141 hr
= IMFTopology_AddNode(topology
, node
);
1142 ok(hr
== S_OK
, "Failed to add a node, hr %#lx.\n", hr
);
1144 hr
= IMFTopology_GetNodeCount(topology
, &node_count
);
1145 ok(hr
== S_OK
, "Failed to get node count, hr %#lx.\n", hr
);
1146 ok(node_count
== 1, "Unexpected node count.\n");
1148 hr
= IMFTopologyNode_ConnectOutput(node
, 0, node2
, 0);
1149 ok(hr
== S_OK
, "Failed to connect nodes, hr %#lx.\n", hr
);
1151 hr
= IMFTopology_GetNodeCount(topology
, &node_count
);
1152 ok(hr
== S_OK
, "Failed to get node count, hr %#lx.\n", hr
);
1153 ok(node_count
== 1, "Unexpected node count.\n");
1155 /* Add same node to different topologies. */
1156 hr
= IMFTopology_Clear(topology
);
1157 ok(hr
== S_OK
, "Failed to clear topology, hr %#lx.\n", hr
);
1159 hr
= MFCreateTopology(&topology2
);
1160 ok(hr
== S_OK
, "Failed to create topology, hr %#lx.\n", hr
);
1162 hr
= MFCreateTopologyNode(MF_TOPOLOGY_SOURCESTREAM_NODE
, &node
);
1163 ok(hr
== S_OK
, "Failed to create topology node, hr %#lx.\n", hr
);
1165 hr
= IMFTopology_AddNode(topology
, node
);
1166 ok(hr
== S_OK
, "Failed to add a node, hr %#lx.\n", hr
);
1167 EXPECT_REF(node
, 2);
1169 hr
= IMFTopology_GetNodeCount(topology
, &node_count
);
1170 ok(hr
== S_OK
, "Failed to get node count, hr %#lx.\n", hr
);
1171 ok(node_count
== 1, "Unexpected node count.\n");
1173 hr
= IMFTopology_GetNodeCount(topology2
, &node_count
);
1174 ok(hr
== S_OK
, "Failed to get node count, hr %#lx.\n", hr
);
1175 ok(node_count
== 0, "Unexpected node count.\n");
1177 hr
= IMFTopology_AddNode(topology2
, node
);
1178 ok(hr
== S_OK
, "Failed to add a node, hr %#lx.\n", hr
);
1179 EXPECT_REF(node
, 3);
1181 hr
= IMFTopology_GetNodeCount(topology
, &node_count
);
1182 ok(hr
== S_OK
, "Failed to get node count, hr %#lx.\n", hr
);
1183 ok(node_count
== 1, "Unexpected node count.\n");
1185 hr
= IMFTopology_GetNodeCount(topology2
, &node_count
);
1186 ok(hr
== S_OK
, "Failed to get node count, hr %#lx.\n", hr
);
1187 ok(node_count
== 1, "Unexpected node count.\n");
1189 ref
= IMFTopology_Release(topology2
);
1190 ok(ref
== 0, "Release returned %ld\n", ref
);
1191 ref
= IMFTopology_Release(topology
);
1192 ok(ref
== 0, "Release returned %ld\n", ref
);
1194 ref
= IMFTopologyNode_Release(node
);
1195 ok(ref
== 0, "Release returned %ld\n", ref
);
1196 ref
= IMFTopologyNode_Release(node2
);
1197 ok(ref
== 0, "Release returned %ld\n", ref
);
1199 /* Try cloning a topology without all outputs connected */
1200 hr
= MFCreateTopology(&topology
);
1201 ok(hr
== S_OK
, "Failed to create topology, hr %#lx.\n", hr
);
1203 hr
= MFCreateTopology(&topology2
);
1204 ok(hr
== S_OK
, "Failed to create topology, hr %#lx.\n", hr
);
1206 hr
= MFCreateTopologyNode(MF_TOPOLOGY_TRANSFORM_NODE
, &node
);
1207 ok(hr
== S_OK
, "Failed to create topology node, hr %#lx.\n", hr
);
1209 hr
= IMFTopology_AddNode(topology
, node
);
1210 ok(hr
== S_OK
, "Failed to add a node, hr %#lx.\n", hr
);
1211 EXPECT_REF(node
, 2);
1213 hr
= MFCreateTopologyNode(MF_TOPOLOGY_OUTPUT_NODE
, &node2
);
1214 ok(hr
== S_OK
, "Failed to create topology node, hr %#lx.\n", hr
);
1216 hr
= IMFTopology_AddNode(topology
, node2
);
1217 ok(hr
== S_OK
, "Failed to add a node, hr %#lx.\n", hr
);
1218 EXPECT_REF(node
, 2);
1220 hr
= IMFTopologyNode_ConnectOutput(node
, 1, node2
, 0);
1221 ok(hr
== S_OK
, "Failed to connect output, hr %#lx.\n", hr
);
1223 hr
= IMFTopology_CloneFrom(topology2
, topology
);
1224 ok(hr
== S_OK
, "Failed to clone from topology, hr %#lx.\n", hr
);
1226 hr
= IMFTopology_GetNodeCount(topology2
, &node_count
);
1227 ok(hr
== S_OK
, "Failed to get node count, hr %#lx.\n", hr
);
1228 ok(node_count
== 2, "Unexpected node count %u.\n", node_count
);
1230 hr
= IMFTopology_GetNode(topology2
, 0, &node3
);
1231 ok(hr
== S_OK
, "Failed to get node, hr %#lx.\n", hr
);
1233 hr
= IMFTopologyNode_GetOutputCount(node3
, &size
);
1234 ok(hr
== S_OK
, "Failed to get output count, hr %#lx.\n", hr
);
1235 ok(size
== 2, "Unexpected output count %lu.\n", size
);
1237 IMFTopologyNode_Release(node3
);
1239 ref
= IMFTopology_Release(topology2
);
1240 ok(ref
== 0, "Release returned %ld\n", ref
);
1241 ref
= IMFTopology_Release(topology
);
1242 ok(ref
== 0, "Release returned %ld\n", ref
);
1244 ref
= IMFTopologyNode_Release(node2
);
1245 ok(ref
== 0, "Release returned %ld\n", ref
);
1246 ref
= IMFTopologyNode_Release(node
);
1247 ok(ref
== 0, "Release returned %ld\n", ref
);
1250 static void test_topology_tee_node(void)
1252 IMFTopologyNode
*src_node
, *tee_node
;
1253 IMFMediaType
*mediatype
, *mediatype2
;
1254 IMFTopology
*topology
;
1259 hr
= MFCreateTopology(&topology
);
1260 ok(hr
== S_OK
, "Failed to create topology, hr %#lx.\n", hr
);
1262 hr
= MFCreateMediaType(&mediatype
);
1263 ok(hr
== S_OK
, "Failed to create media type, hr %#lx.\n", hr
);
1265 hr
= MFCreateTopologyNode(MF_TOPOLOGY_TEE_NODE
, &tee_node
);
1266 ok(hr
== S_OK
, "Failed to create topology node, hr %#lx.\n", hr
);
1268 hr
= MFCreateTopologyNode(MF_TOPOLOGY_SOURCESTREAM_NODE
, &src_node
);
1269 ok(hr
== S_OK
, "Failed to create topology node, hr %#lx.\n", hr
);
1271 hr
= IMFTopologyNode_SetInputPrefType(tee_node
, 0, mediatype
);
1272 ok(hr
== S_OK
, "Failed to set type, hr %#lx.\n", hr
);
1274 /* Even though tee node has only one input and source has only one output,
1275 it's possible to connect to higher inputs/outputs. */
1277 /* SRC(0) -> TEE(0) */
1278 hr
= IMFTopologyNode_ConnectOutput(src_node
, 0, tee_node
, 0);
1279 ok(hr
== S_OK
, "Failed to connect nodes, hr %#lx.\n", hr
);
1281 hr
= IMFTopologyNode_GetInputCount(tee_node
, &count
);
1282 ok(hr
== S_OK
, "Failed to get count, hr %#lx.\n", hr
);
1283 ok(count
== 1, "Unexpected count %lu.\n", count
);
1285 hr
= IMFTopologyNode_GetInputPrefType(tee_node
, 0, &mediatype2
);
1286 ok(hr
== S_OK
, "Failed to get type, hr %#lx.\n", hr
);
1287 ok(mediatype2
== mediatype
, "Unexpected type.\n");
1288 IMFMediaType_Release(mediatype2
);
1290 /* SRC(0) -> TEE(1) */
1291 hr
= IMFTopologyNode_ConnectOutput(src_node
, 0, tee_node
, 1);
1292 ok(hr
== S_OK
, "Failed to connect nodes, hr %#lx.\n", hr
);
1294 hr
= IMFTopologyNode_GetInputCount(tee_node
, &count
);
1295 ok(hr
== S_OK
, "Failed to get count, hr %#lx.\n", hr
);
1296 ok(count
== 2, "Unexpected count %lu.\n", count
);
1298 hr
= IMFTopologyNode_SetInputPrefType(tee_node
, 1, mediatype
);
1299 ok(hr
== MF_E_INVALIDTYPE
, "Unexpected hr %#lx.\n", hr
);
1301 /* SRC(1) -> TEE(1) */
1302 hr
= IMFTopologyNode_ConnectOutput(src_node
, 1, tee_node
, 1);
1303 ok(hr
== S_OK
, "Failed to connect nodes, hr %#lx.\n", hr
);
1305 hr
= IMFTopologyNode_GetOutputCount(src_node
, &count
);
1306 ok(hr
== S_OK
, "Failed to get count, hr %#lx.\n", hr
);
1307 ok(count
== 2, "Unexpected count %lu.\n", count
);
1309 EXPECT_REF(src_node
, 2);
1310 EXPECT_REF(tee_node
, 2);
1311 hr
= IMFTopologyNode_DisconnectOutput(src_node
, 1);
1312 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
1314 ref
= IMFTopologyNode_Release(src_node
);
1315 ok(ref
== 0, "Release returned %ld\n", ref
);
1316 ref
= IMFTopologyNode_Release(tee_node
);
1317 ok(ref
== 0, "Release returned %ld\n", ref
);
1319 ref
= IMFMediaType_Release(mediatype
);
1320 ok(ref
== 0, "Release returned %ld\n", ref
);
1321 ref
= IMFTopology_Release(topology
);
1322 ok(ref
== 0, "Release returned %ld\n", ref
);
1325 static HRESULT WINAPI
test_getservice_QI(IMFGetService
*iface
, REFIID riid
, void **obj
)
1327 if (IsEqualIID(riid
, &IID_IMFGetService
) || IsEqualIID(riid
, &IID_IUnknown
))
1334 return E_NOINTERFACE
;
1337 static ULONG WINAPI
test_getservice_AddRef(IMFGetService
*iface
)
1342 static ULONG WINAPI
test_getservice_Release(IMFGetService
*iface
)
1347 static HRESULT WINAPI
test_getservice_GetService(IMFGetService
*iface
, REFGUID service
, REFIID riid
, void **obj
)
1349 *obj
= (void *)0xdeadbeef;
1353 static const IMFGetServiceVtbl testmfgetservicevtbl
=
1356 test_getservice_AddRef
,
1357 test_getservice_Release
,
1358 test_getservice_GetService
,
1361 static IMFGetService test_getservice
= { &testmfgetservicevtbl
};
1363 static HRESULT WINAPI
testservice_QI(IUnknown
*iface
, REFIID riid
, void **obj
)
1365 if (IsEqualIID(riid
, &IID_IUnknown
))
1373 if (IsEqualIID(riid
, &IID_IMFGetService
))
1376 return E_NOINTERFACE
;
1379 static HRESULT WINAPI
testservice2_QI(IUnknown
*iface
, REFIID riid
, void **obj
)
1381 if (IsEqualIID(riid
, &IID_IUnknown
))
1387 if (IsEqualIID(riid
, &IID_IMFGetService
))
1389 *obj
= &test_getservice
;
1394 return E_NOINTERFACE
;
1397 static ULONG WINAPI
testservice_AddRef(IUnknown
*iface
)
1402 static ULONG WINAPI
testservice_Release(IUnknown
*iface
)
1407 static const IUnknownVtbl testservicevtbl
=
1411 testservice_Release
,
1414 static const IUnknownVtbl testservice2vtbl
=
1418 testservice_Release
,
1421 static IUnknown testservice
= { &testservicevtbl
};
1422 static IUnknown testservice2
= { &testservice2vtbl
};
1424 static void test_MFGetService(void)
1429 hr
= MFGetService(NULL
, NULL
, NULL
, NULL
);
1430 ok(hr
== E_POINTER
, "Unexpected return value %#lx.\n", hr
);
1432 unk
= (void *)0xdeadbeef;
1433 hr
= MFGetService(NULL
, NULL
, NULL
, (void **)&unk
);
1434 ok(hr
== E_POINTER
, "Unexpected return value %#lx.\n", hr
);
1435 ok(unk
== (void *)0xdeadbeef, "Unexpected out object.\n");
1437 hr
= MFGetService(&testservice
, NULL
, NULL
, NULL
);
1438 ok(hr
== 0x82eddead, "Unexpected return value %#lx.\n", hr
);
1440 unk
= (void *)0xdeadbeef;
1441 hr
= MFGetService(&testservice
, NULL
, NULL
, (void **)&unk
);
1442 ok(hr
== 0x82eddead, "Unexpected return value %#lx.\n", hr
);
1443 ok(unk
== (void *)0xdeadbeef, "Unexpected out object.\n");
1446 hr
= MFGetService(&testservice2
, NULL
, NULL
, (void **)&unk
);
1447 ok(hr
== 0x83eddead, "Unexpected return value %#lx.\n", hr
);
1448 ok(unk
== (void *)0xdeadbeef, "Unexpected out object.\n");
1451 static void test_sequencer_source(void)
1453 IMFSequencerSource
*seq_source
;
1457 hr
= MFStartup(MF_VERSION
, MFSTARTUP_FULL
);
1458 ok(hr
== S_OK
, "Startup failure, hr %#lx.\n", hr
);
1460 hr
= MFCreateSequencerSource(NULL
, &seq_source
);
1461 ok(hr
== S_OK
, "Failed to create sequencer source, hr %#lx.\n", hr
);
1463 check_interface(seq_source
, &IID_IMFMediaSourceTopologyProvider
, TRUE
);
1465 ref
= IMFSequencerSource_Release(seq_source
);
1466 ok(ref
== 0, "Release returned %ld\n", ref
);
1469 ok(hr
== S_OK
, "Shutdown failure, hr %#lx.\n", hr
);
1474 IMFMediaTypeHandler IMFMediaTypeHandler_iface
;
1476 ULONG set_current_count
;
1477 IMFMediaType
*current_type
;
1478 IMFMediaType
*invalid_type
;
1481 ULONG media_types_count
;
1482 IMFMediaType
**media_types
;
1485 static struct test_handler
*impl_from_IMFMediaTypeHandler(IMFMediaTypeHandler
*iface
)
1487 return CONTAINING_RECORD(iface
, struct test_handler
, IMFMediaTypeHandler_iface
);
1490 static HRESULT WINAPI
test_handler_QueryInterface(IMFMediaTypeHandler
*iface
, REFIID riid
, void **obj
)
1492 if (IsEqualIID(riid
, &IID_IMFMediaTypeHandler
)
1493 || IsEqualIID(riid
, &IID_IUnknown
))
1495 IMFMediaTypeHandler_AddRef((*obj
= iface
));
1500 return E_NOINTERFACE
;
1503 static ULONG WINAPI
test_handler_AddRef(IMFMediaTypeHandler
*iface
)
1508 static ULONG WINAPI
test_handler_Release(IMFMediaTypeHandler
*iface
)
1513 static HRESULT WINAPI
test_handler_IsMediaTypeSupported(IMFMediaTypeHandler
*iface
, IMFMediaType
*in_type
,
1514 IMFMediaType
**out_type
)
1516 struct test_handler
*impl
= impl_from_IMFMediaTypeHandler(iface
);
1522 if (impl
->invalid_type
&& IMFMediaType_Compare(impl
->invalid_type
, (IMFAttributes
*)in_type
,
1523 MF_ATTRIBUTES_MATCH_OUR_ITEMS
, &result
) == S_OK
&& result
)
1524 return MF_E_INVALIDMEDIATYPE
;
1526 if (!impl
->current_type
)
1529 if (IMFMediaType_Compare(impl
->current_type
, (IMFAttributes
*)in_type
,
1530 MF_ATTRIBUTES_MATCH_OUR_ITEMS
, &result
) == S_OK
&& result
)
1533 return MF_E_INVALIDMEDIATYPE
;
1536 static HRESULT WINAPI
test_handler_GetMediaTypeCount(IMFMediaTypeHandler
*iface
, DWORD
*count
)
1538 ok(0, "Unexpected call.\n");
1542 static HRESULT WINAPI
test_handler_GetMediaTypeByIndex(IMFMediaTypeHandler
*iface
, DWORD index
,
1543 IMFMediaType
**type
)
1545 struct test_handler
*impl
= impl_from_IMFMediaTypeHandler(iface
);
1547 if (impl
->media_types
)
1551 if (index
>= impl
->media_types_count
)
1552 return MF_E_NO_MORE_TYPES
;
1554 IMFMediaType_AddRef((*type
= impl
->media_types
[index
]));
1558 ok(0, "Unexpected call.\n");
1562 static HRESULT WINAPI
test_handler_SetCurrentMediaType(IMFMediaTypeHandler
*iface
, IMFMediaType
*media_type
)
1564 struct test_handler
*impl
= impl_from_IMFMediaTypeHandler(iface
);
1566 if (impl
->current_type
)
1567 IMFMediaType_Release(impl
->current_type
);
1568 IMFMediaType_AddRef((impl
->current_type
= media_type
));
1569 impl
->set_current_count
++;
1574 static HRESULT WINAPI
test_handler_GetCurrentMediaType(IMFMediaTypeHandler
*iface
, IMFMediaType
**media_type
)
1576 struct test_handler
*impl
= impl_from_IMFMediaTypeHandler(iface
);
1579 if (!impl
->current_type
)
1581 if (!impl
->media_types
)
1583 if (!impl
->media_types_count
)
1584 return MF_E_TRANSFORM_TYPE_NOT_SET
;
1585 return MF_E_NOT_INITIALIZED
;
1588 if (FAILED(hr
= MFCreateMediaType(media_type
)))
1591 hr
= IMFMediaType_CopyAllItems(impl
->current_type
, (IMFAttributes
*)*media_type
);
1593 IMFMediaType_Release(*media_type
);
1598 static HRESULT WINAPI
test_handler_GetMajorType(IMFMediaTypeHandler
*iface
, GUID
*type
)
1600 ok(0, "Unexpected call.\n");
1604 static const IMFMediaTypeHandlerVtbl test_handler_vtbl
=
1606 test_handler_QueryInterface
,
1607 test_handler_AddRef
,
1608 test_handler_Release
,
1609 test_handler_IsMediaTypeSupported
,
1610 test_handler_GetMediaTypeCount
,
1611 test_handler_GetMediaTypeByIndex
,
1612 test_handler_SetCurrentMediaType
,
1613 test_handler_GetCurrentMediaType
,
1614 test_handler_GetMajorType
,
1617 static const struct test_handler test_handler
= {.IMFMediaTypeHandler_iface
.lpVtbl
= &test_handler_vtbl
};
1619 struct test_media_sink
1621 IMFMediaSink IMFMediaSink_iface
;
1625 static struct test_media_sink
*impl_from_IMFMediaSink(IMFMediaSink
*iface
)
1627 return CONTAINING_RECORD(iface
, struct test_media_sink
, IMFMediaSink_iface
);
1630 static HRESULT WINAPI
test_media_sink_QueryInterface(IMFMediaSink
*iface
, REFIID riid
, void **obj
)
1632 if (IsEqualIID(riid
, &IID_IMFMediaSink
)
1633 || IsEqualIID(riid
, &IID_IUnknown
))
1635 IMFMediaSink_AddRef((*obj
= iface
));
1640 return E_NOINTERFACE
;
1643 static ULONG WINAPI
test_media_sink_AddRef(IMFMediaSink
*iface
)
1648 static ULONG WINAPI
test_media_sink_Release(IMFMediaSink
*iface
)
1653 static HRESULT WINAPI
test_media_sink_GetCharacteristics(IMFMediaSink
*iface
, DWORD
*characteristics
)
1655 *characteristics
= 0;
1659 static HRESULT WINAPI
test_media_sink_AddStreamSink(IMFMediaSink
*iface
,
1660 DWORD stream_sink_id
, IMFMediaType
*media_type
, IMFStreamSink
**stream_sink
)
1662 ok(0, "Unexpected call.\n");
1666 static HRESULT WINAPI
test_media_sink_RemoveStreamSink(IMFMediaSink
*iface
, DWORD stream_sink_id
)
1668 ok(0, "Unexpected call.\n");
1672 static HRESULT WINAPI
test_media_sink_GetStreamSinkCount(IMFMediaSink
*iface
, DWORD
*count
)
1674 ok(0, "Unexpected call.\n");
1678 static HRESULT WINAPI
test_media_sink_GetStreamSinkByIndex(IMFMediaSink
*iface
, DWORD index
, IMFStreamSink
**sink
)
1680 ok(0, "Unexpected call.\n");
1684 static HRESULT WINAPI
test_media_sink_GetStreamSinkById(IMFMediaSink
*iface
, DWORD stream_sink_id
, IMFStreamSink
**sink
)
1686 ok(0, "Unexpected call.\n");
1690 static HRESULT WINAPI
test_media_sink_SetPresentationClock(IMFMediaSink
*iface
, IMFPresentationClock
*clock
)
1692 ok(0, "Unexpected call.\n");
1696 static HRESULT WINAPI
test_media_sink_GetPresentationClock(IMFMediaSink
*iface
, IMFPresentationClock
**clock
)
1698 ok(0, "Unexpected call.\n");
1702 static HRESULT WINAPI
test_media_sink_Shutdown(IMFMediaSink
*iface
)
1704 struct test_media_sink
*sink
= impl_from_IMFMediaSink(iface
);
1705 ok(!sink
->shutdown
, "Unexpected call.\n");
1706 sink
->shutdown
= TRUE
;
1710 static const IMFMediaSinkVtbl test_media_sink_vtbl
=
1712 test_media_sink_QueryInterface
,
1713 test_media_sink_AddRef
,
1714 test_media_sink_Release
,
1715 test_media_sink_GetCharacteristics
,
1716 test_media_sink_AddStreamSink
,
1717 test_media_sink_RemoveStreamSink
,
1718 test_media_sink_GetStreamSinkCount
,
1719 test_media_sink_GetStreamSinkByIndex
,
1720 test_media_sink_GetStreamSinkById
,
1721 test_media_sink_SetPresentationClock
,
1722 test_media_sink_GetPresentationClock
,
1723 test_media_sink_Shutdown
,
1726 static const struct test_media_sink test_media_sink
= {.IMFMediaSink_iface
.lpVtbl
= &test_media_sink_vtbl
};
1728 struct test_stream_sink
1730 IMFStreamSink IMFStreamSink_iface
;
1731 IMFMediaTypeHandler
*handler
;
1732 IMFMediaSink
*media_sink
;
1735 static struct test_stream_sink
*impl_from_IMFStreamSink(IMFStreamSink
*iface
)
1737 return CONTAINING_RECORD(iface
, struct test_stream_sink
, IMFStreamSink_iface
);
1740 static HRESULT WINAPI
test_stream_sink_QueryInterface(IMFStreamSink
*iface
, REFIID riid
, void **obj
)
1742 if (IsEqualIID(riid
, &IID_IMFStreamSink
)
1743 || IsEqualIID(riid
, &IID_IMFMediaEventGenerator
)
1744 || IsEqualIID(riid
, &IID_IUnknown
))
1746 IMFStreamSink_AddRef((*obj
= iface
));
1751 return E_NOINTERFACE
;
1754 static ULONG WINAPI
test_stream_sink_AddRef(IMFStreamSink
*iface
)
1759 static ULONG WINAPI
test_stream_sink_Release(IMFStreamSink
*iface
)
1764 static HRESULT WINAPI
test_stream_sink_GetEvent(IMFStreamSink
*iface
, DWORD flags
, IMFMediaEvent
**event
)
1766 ok(0, "Unexpected call.\n");
1770 static HRESULT WINAPI
test_stream_sink_BeginGetEvent(IMFStreamSink
*iface
, IMFAsyncCallback
*callback
, IUnknown
*state
)
1772 ok(0, "Unexpected call.\n");
1776 static HRESULT WINAPI
test_stream_sink_EndGetEvent(IMFStreamSink
*iface
, IMFAsyncResult
*result
,
1777 IMFMediaEvent
**event
)
1779 ok(0, "Unexpected call.\n");
1783 static HRESULT WINAPI
test_stream_sink_QueueEvent(IMFStreamSink
*iface
, MediaEventType event_type
,
1784 REFGUID ext_type
, HRESULT hr
, const PROPVARIANT
*value
)
1786 ok(0, "Unexpected call.\n");
1790 static HRESULT WINAPI
test_stream_sink_GetMediaSink(IMFStreamSink
*iface
, IMFMediaSink
**sink
)
1792 struct test_stream_sink
*impl
= impl_from_IMFStreamSink(iface
);
1794 if (impl
->media_sink
)
1796 IMFMediaSink_AddRef((*sink
= impl
->media_sink
));
1801 ok(0, "Unexpected call.\n");
1805 static HRESULT WINAPI
test_stream_sink_GetIdentifier(IMFStreamSink
*iface
, DWORD
*id
)
1807 ok(0, "Unexpected call.\n");
1811 static HRESULT WINAPI
test_stream_sink_GetMediaTypeHandler(IMFStreamSink
*iface
, IMFMediaTypeHandler
**handler
)
1813 struct test_stream_sink
*impl
= impl_from_IMFStreamSink(iface
);
1817 IMFMediaTypeHandler_AddRef((*handler
= impl
->handler
));
1821 ok(0, "Unexpected call.\n");
1825 static HRESULT WINAPI
test_stream_sink_ProcessSample(IMFStreamSink
*iface
, IMFSample
*sample
)
1827 ok(0, "Unexpected call.\n");
1831 static HRESULT WINAPI
test_stream_sink_PlaceMarker(IMFStreamSink
*iface
, MFSTREAMSINK_MARKER_TYPE marker_type
,
1832 const PROPVARIANT
*marker_value
, const PROPVARIANT
*context
)
1834 ok(0, "Unexpected call.\n");
1838 static HRESULT WINAPI
test_stream_sink_Flush(IMFStreamSink
*iface
)
1840 ok(0, "Unexpected call.\n");
1844 static const IMFStreamSinkVtbl test_stream_sink_vtbl
=
1846 test_stream_sink_QueryInterface
,
1847 test_stream_sink_AddRef
,
1848 test_stream_sink_Release
,
1849 test_stream_sink_GetEvent
,
1850 test_stream_sink_BeginGetEvent
,
1851 test_stream_sink_EndGetEvent
,
1852 test_stream_sink_QueueEvent
,
1853 test_stream_sink_GetMediaSink
,
1854 test_stream_sink_GetIdentifier
,
1855 test_stream_sink_GetMediaTypeHandler
,
1856 test_stream_sink_ProcessSample
,
1857 test_stream_sink_PlaceMarker
,
1858 test_stream_sink_Flush
,
1861 static const struct test_stream_sink test_stream_sink
= {.IMFStreamSink_iface
.lpVtbl
= &test_stream_sink_vtbl
};
1863 struct test_callback
1865 IMFAsyncCallback IMFAsyncCallback_iface
;
1869 IMFMediaEvent
*media_event
;
1870 BOOL check_media_event
;
1873 static struct test_callback
*impl_from_IMFAsyncCallback(IMFAsyncCallback
*iface
)
1875 return CONTAINING_RECORD(iface
, struct test_callback
, IMFAsyncCallback_iface
);
1878 static HRESULT WINAPI
testcallback_QueryInterface(IMFAsyncCallback
*iface
, REFIID riid
, void **obj
)
1880 if (IsEqualIID(riid
, &IID_IMFAsyncCallback
) ||
1881 IsEqualIID(riid
, &IID_IUnknown
))
1884 IMFAsyncCallback_AddRef(iface
);
1889 return E_NOINTERFACE
;
1892 static ULONG WINAPI
testcallback_AddRef(IMFAsyncCallback
*iface
)
1894 struct test_callback
*callback
= impl_from_IMFAsyncCallback(iface
);
1895 return InterlockedIncrement(&callback
->refcount
);
1898 static ULONG WINAPI
testcallback_Release(IMFAsyncCallback
*iface
)
1900 struct test_callback
*callback
= impl_from_IMFAsyncCallback(iface
);
1901 ULONG refcount
= InterlockedDecrement(&callback
->refcount
);
1905 if (callback
->media_event
)
1906 IMFMediaEvent_Release(callback
->media_event
);
1907 CloseHandle(callback
->event
);
1914 static HRESULT WINAPI
testcallback_GetParameters(IMFAsyncCallback
*iface
, DWORD
*flags
, DWORD
*queue
)
1916 ok(flags
!= NULL
&& queue
!= NULL
, "Unexpected arguments.\n");
1920 static HRESULT WINAPI
testcallback_Invoke(IMFAsyncCallback
*iface
, IMFAsyncResult
*result
)
1922 struct test_callback
*callback
= CONTAINING_RECORD(iface
, struct test_callback
, IMFAsyncCallback_iface
);
1926 ok(result
!= NULL
, "Unexpected result object.\n");
1928 if (callback
->media_event
)
1929 IMFMediaEvent_Release(callback
->media_event
);
1931 if (callback
->check_media_event
)
1933 hr
= IMFAsyncResult_GetObject(result
, &object
);
1934 ok(hr
== E_POINTER
, "Unexpected hr %#lx.\n", hr
);
1936 hr
= IMFAsyncResult_GetState(result
, &object
);
1937 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
1938 hr
= IMFMediaEventGenerator_EndGetEvent((IMFMediaEventGenerator
*)object
,
1939 result
, &callback
->media_event
);
1940 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
1941 IUnknown_Release(object
);
1944 SetEvent(callback
->event
);
1949 static const IMFAsyncCallbackVtbl testcallbackvtbl
=
1951 testcallback_QueryInterface
,
1952 testcallback_AddRef
,
1953 testcallback_Release
,
1954 testcallback_GetParameters
,
1955 testcallback_Invoke
,
1958 static IMFAsyncCallback
*create_test_callback(BOOL check_media_event
)
1960 struct test_callback
*callback
;
1962 if (!(callback
= calloc(1, sizeof(*callback
))))
1965 callback
->refcount
= 1;
1966 callback
->check_media_event
= check_media_event
;
1967 callback
->IMFAsyncCallback_iface
.lpVtbl
= &testcallbackvtbl
;
1968 callback
->event
= CreateEventW(NULL
, FALSE
, FALSE
, NULL
);
1969 ok(!!callback
->event
, "CreateEventW failed, error %lu\n", GetLastError());
1971 return &callback
->IMFAsyncCallback_iface
;
1974 #define wait_media_event(a, b, c, d, e) wait_media_event_(__LINE__, a, b, c, d, e)
1975 static HRESULT
wait_media_event_(int line
, IMFMediaSession
*session
, IMFAsyncCallback
*callback
,
1976 MediaEventType expect_type
, DWORD timeout
, PROPVARIANT
*value
)
1978 struct test_callback
*impl
= impl_from_IMFAsyncCallback(callback
);
1979 MediaEventType type
;
1986 hr
= IMFMediaSession_BeginGetEvent(session
, &impl
->IMFAsyncCallback_iface
, (IUnknown
*)session
);
1987 ok_(__FILE__
, line
)(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
1988 ret
= WaitForSingleObject(impl
->event
, timeout
);
1989 ok_(__FILE__
, line
)(ret
== WAIT_OBJECT_0
, "WaitForSingleObject returned %lu\n", ret
);
1990 hr
= IMFMediaEvent_GetType(impl
->media_event
, &type
);
1991 ok_(__FILE__
, line
)(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
1992 } while (type
!= expect_type
);
1994 ok_(__FILE__
, line
)(type
== expect_type
, "got type %lu\n", type
);
1996 hr
= IMFMediaEvent_GetExtendedType(impl
->media_event
, &guid
);
1997 ok_(__FILE__
, line
)(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
1998 ok_(__FILE__
, line
)(IsEqualGUID(&guid
, &GUID_NULL
), "got extended type %s\n", debugstr_guid(&guid
));
2000 hr
= IMFMediaEvent_GetValue(impl
->media_event
, value
);
2001 ok_(__FILE__
, line
)(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
2003 hr
= IMFMediaEvent_GetStatus(impl
->media_event
, &status
);
2004 ok_(__FILE__
, line
)(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
2009 #define wait_media_event_until_blocking(a, b, c, d, e) wait_media_event_until_blocking_(__LINE__, a, b, c, d, e)
2010 static HRESULT
wait_media_event_until_blocking_(int line
, IMFMediaSession
*session
, IMFAsyncCallback
*callback
,
2011 MediaEventType expect_type
, DWORD timeout
, PROPVARIANT
*value
)
2013 struct test_callback
*impl
= impl_from_IMFAsyncCallback(callback
);
2014 MediaEventType type
;
2021 hr
= IMFMediaSession_BeginGetEvent(session
, &impl
->IMFAsyncCallback_iface
, (IUnknown
*)session
);
2022 ok_(__FILE__
, line
)(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
2023 ret
= WaitForSingleObject(impl
->event
, timeout
);
2024 if (ret
== WAIT_TIMEOUT
) return WAIT_TIMEOUT
;
2025 hr
= IMFMediaEvent_GetType(impl
->media_event
, &type
);
2026 ok_(__FILE__
, line
)(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
2027 } while (type
!= expect_type
);
2029 ok_(__FILE__
, line
)(type
== expect_type
, "got type %lu\n", type
);
2031 hr
= IMFMediaEvent_GetExtendedType(impl
->media_event
, &guid
);
2032 ok_(__FILE__
, line
)(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
2033 ok_(__FILE__
, line
)(IsEqualGUID(&guid
, &GUID_NULL
), "got extended type %s\n", debugstr_guid(&guid
));
2035 hr
= IMFMediaEvent_GetValue(impl
->media_event
, value
);
2036 ok_(__FILE__
, line
)(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
2038 hr
= IMFMediaEvent_GetStatus(impl
->media_event
, &status
);
2039 ok_(__FILE__
, line
)(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
2044 static IMFMediaSource
*create_media_source(const WCHAR
*name
, const WCHAR
*mime
)
2046 IMFSourceResolver
*resolver
;
2047 IMFAttributes
*attributes
;
2048 const BYTE
*resource_data
;
2049 MF_OBJECT_TYPE obj_type
;
2050 IMFMediaSource
*source
;
2051 IMFByteStream
*stream
;
2056 resource
= FindResourceW(NULL
, name
, (const WCHAR
*)RT_RCDATA
);
2057 ok(resource
!= 0, "FindResourceW %s failed, error %lu\n", debugstr_w(name
), GetLastError());
2058 resource_data
= LockResource(LoadResource(GetModuleHandleW(NULL
), resource
));
2059 resource_len
= SizeofResource(GetModuleHandleW(NULL
), resource
);
2061 hr
= MFCreateTempFile(MF_ACCESSMODE_READWRITE
, MF_OPENMODE_DELETE_IF_EXIST
, MF_FILEFLAGS_NONE
, &stream
);
2062 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
2063 hr
= IMFByteStream_Write(stream
, resource_data
, resource_len
, &resource_len
);
2064 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
2065 hr
= IMFByteStream_SetCurrentPosition(stream
, 0);
2066 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
2068 hr
= IMFByteStream_QueryInterface(stream
, &IID_IMFAttributes
, (void **)&attributes
);
2069 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
2070 hr
= IMFAttributes_SetString(attributes
, &MF_BYTESTREAM_CONTENT_TYPE
, mime
);
2071 ok(hr
== S_OK
, "Failed to set string value, hr %#lx.\n", hr
);
2072 IMFAttributes_Release(attributes
);
2074 hr
= MFCreateSourceResolver(&resolver
);
2075 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
2076 hr
= IMFSourceResolver_CreateObjectFromByteStream(resolver
, stream
, NULL
, MF_RESOLUTION_MEDIASOURCE
, NULL
,
2077 &obj_type
, (IUnknown
**)&source
);
2078 todo_wine_if(hr
== MF_E_UNEXPECTED
) /* Gitlab CI Debian runner */
2079 ok(hr
== S_OK
|| broken(hr
== MF_E_UNSUPPORTED_BYTESTREAM_TYPE
), "Unexpected hr %#lx.\n", hr
);
2080 IMFSourceResolver_Release(resolver
);
2081 IMFByteStream_Release(stream
);
2086 ok(obj_type
== MF_OBJECT_MEDIASOURCE
, "got %d\n", obj_type
);
2096 SINK_ON_CLOCK_START
,
2097 SINK_ON_CLOCK_PAUSE
,
2099 SINK_ON_CLOCK_RESTART
,
2100 SINK_ON_CLOCK_SETRATE
,
2103 #define MAX_OBJECT_STATE 1024
2105 struct object_state_record
2107 enum object_state states
[MAX_OBJECT_STATE
];
2108 unsigned int state_count
;
2110 static struct object_state_record actual_object_state_record
;
2112 #define add_object_state(a, b) _add_object_state(__LINE__, a, b)
2113 static void _add_object_state(int line
, struct object_state_record
*record
, enum object_state state
)
2115 ok_(__FILE__
, line
)(record
->state_count
< MAX_OBJECT_STATE
, "exceeded state_count maximum %d.\n", MAX_OBJECT_STATE
);
2116 if (record
->state_count
< MAX_OBJECT_STATE
)
2117 record
->states
[record
->state_count
++] = state
;
2120 #define compare_object_states(a, b) _compare_object_states(__LINE__, a, b)
2121 static void _compare_object_states(int line
, const struct object_state_record
*r1
,
2122 const struct object_state_record
*r2
)
2124 ok_(__FILE__
, line
)(r1
->state_count
== r2
->state_count
, "State count not equal.\n");
2125 if (r1
->state_count
== r2
->state_count
)
2126 ok_(__FILE__
, line
)(!memcmp(r1
->states
, r2
->states
, sizeof(enum object_state
) * r1
->state_count
), "Got different states.\n");
2136 struct test_media_stream
2138 IMFMediaStream IMFMediaStream_iface
;
2139 IMFMediaEventQueue
*event_queue
;
2140 IMFStreamDescriptor
*sd
;
2141 IMFMediaSource
*source
;
2142 LONGLONG sample_duration
;
2143 LONGLONG sample_time
;
2148 static struct test_media_stream
*impl_from_IMFMediaStream(IMFMediaStream
*iface
)
2150 return CONTAINING_RECORD(iface
, struct test_media_stream
, IMFMediaStream_iface
);
2153 static HRESULT WINAPI
test_media_stream_QueryInterface(IMFMediaStream
*iface
, REFIID riid
, void **out
)
2155 if (IsEqualIID(riid
, &IID_IMFMediaStream
)
2156 || IsEqualIID(riid
, &IID_IMFMediaEventGenerator
)
2157 || IsEqualIID(riid
, &IID_IUnknown
))
2164 return E_NOINTERFACE
;
2167 IMFMediaStream_AddRef(iface
);
2171 static ULONG WINAPI
test_media_stream_AddRef(IMFMediaStream
*iface
)
2173 struct test_media_stream
*stream
= impl_from_IMFMediaStream(iface
);
2174 return InterlockedIncrement(&stream
->refcount
);
2177 static ULONG WINAPI
test_media_stream_Release(IMFMediaStream
*iface
)
2179 struct test_media_stream
*stream
= impl_from_IMFMediaStream(iface
);
2180 ULONG refcount
= InterlockedDecrement(&stream
->refcount
);
2184 IMFMediaEventQueue_Release(stream
->event_queue
);
2191 static HRESULT WINAPI
test_media_stream_GetEvent(IMFMediaStream
*iface
, DWORD flags
, IMFMediaEvent
**event
)
2193 struct test_media_stream
*stream
= impl_from_IMFMediaStream(iface
);
2194 return IMFMediaEventQueue_GetEvent(stream
->event_queue
, flags
, event
);
2197 static HRESULT WINAPI
test_media_stream_BeginGetEvent(IMFMediaStream
*iface
, IMFAsyncCallback
*callback
, IUnknown
*state
)
2199 struct test_media_stream
*stream
= impl_from_IMFMediaStream(iface
);
2200 return IMFMediaEventQueue_BeginGetEvent(stream
->event_queue
, callback
, state
);
2203 static HRESULT WINAPI
test_media_stream_EndGetEvent(IMFMediaStream
*iface
, IMFAsyncResult
*result
, IMFMediaEvent
**event
)
2205 struct test_media_stream
*stream
= impl_from_IMFMediaStream(iface
);
2206 return IMFMediaEventQueue_EndGetEvent(stream
->event_queue
, result
, event
);
2209 static HRESULT WINAPI
test_media_stream_QueueEvent(IMFMediaStream
*iface
, MediaEventType event_type
, REFGUID ext_type
,
2210 HRESULT hr
, const PROPVARIANT
*value
)
2212 struct test_media_stream
*stream
= impl_from_IMFMediaStream(iface
);
2213 return IMFMediaEventQueue_QueueEventParamVar(stream
->event_queue
, event_type
, ext_type
, hr
, value
);
2216 static HRESULT WINAPI
test_media_stream_GetMediaSource(IMFMediaStream
*iface
, IMFMediaSource
**source
)
2218 struct test_media_stream
*stream
= impl_from_IMFMediaStream(iface
);
2220 *source
= stream
->source
;
2221 IMFMediaSource_AddRef(*source
);
2226 static HRESULT WINAPI
test_media_stream_GetStreamDescriptor(IMFMediaStream
*iface
, IMFStreamDescriptor
**sd
)
2228 struct test_media_stream
*stream
= impl_from_IMFMediaStream(iface
);
2231 IMFStreamDescriptor_AddRef(*sd
);
2236 static HRESULT WINAPI
test_media_stream_RequestSample(IMFMediaStream
*iface
, IUnknown
*token
)
2238 struct test_media_stream
*stream
= impl_from_IMFMediaStream(iface
);
2239 IMFMediaBuffer
*buffer
;
2243 hr
= MFCreateSample(&sample
);
2244 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
2245 if (stream
->sample_duration
)
2247 hr
= IMFSample_SetSampleDuration(sample
, stream
->sample_duration
);
2248 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
2250 hr
= IMFSample_SetSampleTime(sample
, stream
->sample_time
);
2251 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
2253 stream
->sample_time
+= stream
->sample_duration
;
2257 hr
= IMFSample_SetSampleTime(sample
, 123);
2258 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
2260 hr
= IMFSample_SetSampleDuration(sample
, 1);
2261 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
2265 IMFSample_SetUnknown(sample
, &MFSampleExtension_Token
, token
);
2267 /* Reader expects buffers, empty samples are considered an error. */
2268 hr
= MFCreateMemoryBuffer(8, &buffer
);
2269 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
2270 hr
= IMFSample_AddBuffer(sample
, buffer
);
2271 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
2272 IMFMediaBuffer_Release(buffer
);
2274 hr
= IMFMediaEventQueue_QueueEventParamUnk(stream
->event_queue
, MEMediaSample
, &GUID_NULL
, S_OK
,
2275 (IUnknown
*)sample
);
2276 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
2277 IMFSample_Release(sample
);
2282 static const IMFMediaStreamVtbl test_media_stream_vtbl
=
2284 test_media_stream_QueryInterface
,
2285 test_media_stream_AddRef
,
2286 test_media_stream_Release
,
2287 test_media_stream_GetEvent
,
2288 test_media_stream_BeginGetEvent
,
2289 test_media_stream_EndGetEvent
,
2290 test_media_stream_QueueEvent
,
2291 test_media_stream_GetMediaSource
,
2292 test_media_stream_GetStreamDescriptor
,
2293 test_media_stream_RequestSample
,
2296 #define TEST_SOURCE_NUM_STREAMS 3
2298 struct test_seek_source
2300 IMFMediaSource IMFMediaSource_iface
;
2301 IMFMediaEventQueue
*event_queue
;
2302 IMFPresentationDescriptor
*pd
;
2303 struct test_media_stream
*streams
[TEST_SOURCE_NUM_STREAMS
];
2304 enum source_state state
;
2305 unsigned stream_count
;
2306 CRITICAL_SECTION cs
;
2311 static struct test_seek_source
*impl_test_seek_source_from_IMFMediaSource(IMFMediaSource
*iface
)
2313 return CONTAINING_RECORD(iface
, struct test_seek_source
, IMFMediaSource_iface
);
2316 static HRESULT WINAPI
test_seek_source_QueryInterface(IMFMediaSource
*iface
, REFIID riid
, void **out
)
2318 if (IsEqualIID(riid
, &IID_IMFMediaSource
)
2319 || IsEqualIID(riid
, &IID_IMFMediaEventGenerator
)
2320 || IsEqualIID(riid
, &IID_IUnknown
))
2327 return E_NOINTERFACE
;
2330 IMFMediaSource_AddRef(iface
);
2334 static ULONG WINAPI
test_seek_source_AddRef(IMFMediaSource
*iface
)
2336 struct test_seek_source
*source
= impl_test_seek_source_from_IMFMediaSource(iface
);
2337 return InterlockedIncrement(&source
->refcount
);
2340 static ULONG WINAPI
test_seek_source_Release(IMFMediaSource
*iface
)
2342 struct test_seek_source
*source
= impl_test_seek_source_from_IMFMediaSource(iface
);
2343 ULONG refcount
= InterlockedDecrement(&source
->refcount
);
2347 IMFMediaEventQueue_Release(source
->event_queue
);
2354 static HRESULT WINAPI
test_seek_source_GetEvent(IMFMediaSource
*iface
, DWORD flags
, IMFMediaEvent
**event
)
2356 struct test_seek_source
*source
= impl_test_seek_source_from_IMFMediaSource(iface
);
2357 return IMFMediaEventQueue_GetEvent(source
->event_queue
, flags
, event
);
2360 static HRESULT WINAPI
test_seek_source_BeginGetEvent(IMFMediaSource
*iface
, IMFAsyncCallback
*callback
, IUnknown
*state
)
2362 struct test_seek_source
*source
= impl_test_seek_source_from_IMFMediaSource(iface
);
2363 return IMFMediaEventQueue_BeginGetEvent(source
->event_queue
, callback
, state
);
2366 static HRESULT WINAPI
test_seek_source_EndGetEvent(IMFMediaSource
*iface
, IMFAsyncResult
*result
, IMFMediaEvent
**event
)
2368 struct test_seek_source
*source
= impl_test_seek_source_from_IMFMediaSource(iface
);
2369 return IMFMediaEventQueue_EndGetEvent(source
->event_queue
, result
, event
);
2372 static HRESULT WINAPI
test_seek_source_QueueEvent(IMFMediaSource
*iface
, MediaEventType event_type
, REFGUID ext_type
,
2373 HRESULT hr
, const PROPVARIANT
*value
)
2375 struct test_seek_source
*source
= impl_test_seek_source_from_IMFMediaSource(iface
);
2376 return IMFMediaEventQueue_QueueEventParamVar(source
->event_queue
, event_type
, ext_type
, hr
, value
);
2379 static HRESULT WINAPI
test_seek_source_GetCharacteristics(IMFMediaSource
*iface
, DWORD
*flags
)
2381 struct test_seek_source
*source
= impl_test_seek_source_from_IMFMediaSource(iface
);
2383 if (source
->seekable
)
2384 *flags
= MFMEDIASOURCE_CAN_PAUSE
| MFMEDIASOURCE_CAN_SEEK
;
2386 *flags
= MFMEDIASOURCE_CAN_PAUSE
;
2390 static HRESULT WINAPI
test_seek_source_CreatePresentationDescriptor(IMFMediaSource
*iface
, IMFPresentationDescriptor
**pd
)
2392 struct test_seek_source
*source
= impl_test_seek_source_from_IMFMediaSource(iface
);
2393 IMFStreamDescriptor
*sds
[ARRAY_SIZE(source
->streams
)];
2394 IMFMediaType
*media_type
;
2398 EnterCriticalSection(&source
->cs
);
2403 IMFPresentationDescriptor_AddRef(*pd
);
2407 for (i
= 0; i
< source
->stream_count
; ++i
)
2409 hr
= MFCreateMediaType(&media_type
);
2410 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
2412 hr
= IMFMediaType_SetGUID(media_type
, &MF_MT_MAJOR_TYPE
, &MFMediaType_Video
);
2413 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
2414 hr
= IMFMediaType_SetGUID(media_type
, &MF_MT_SUBTYPE
, &MFVideoFormat_RGB32
);
2415 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
2416 hr
= IMFMediaType_SetUINT64(media_type
, &MF_MT_FRAME_SIZE
, (UINT64
)640 << 32 | 480);
2417 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
2419 hr
= MFCreateStreamDescriptor(i
, 1, &media_type
, &sds
[i
]);
2420 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
2422 IMFMediaType_Release(media_type
);
2425 hr
= MFCreatePresentationDescriptor(source
->stream_count
, sds
, &source
->pd
);
2426 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
2427 hr
= IMFPresentationDescriptor_SetUINT64(source
->pd
, &MF_PD_DURATION
, 10 * 10000000);
2428 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
2429 hr
= IMFPresentationDescriptor_SelectStream(source
->pd
, 0);
2430 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
2431 for (i
= 0; i
< source
->stream_count
; ++i
)
2432 IMFStreamDescriptor_Release(sds
[i
]);
2435 IMFPresentationDescriptor_AddRef(*pd
);
2438 LeaveCriticalSection(&source
->cs
);
2443 static BOOL
is_stream_selected(IMFPresentationDescriptor
*pd
, DWORD index
)
2445 IMFStreamDescriptor
*sd
;
2446 BOOL selected
= FALSE
;
2448 if (SUCCEEDED(IMFPresentationDescriptor_GetStreamDescriptorByIndex(pd
, index
, &selected
, &sd
)))
2449 IMFStreamDescriptor_Release(sd
);
2454 static HRESULT WINAPI
test_seek_source_Start(IMFMediaSource
*iface
, IMFPresentationDescriptor
*pd
, const GUID
*time_format
,
2455 const PROPVARIANT
*start_position
)
2457 struct test_seek_source
*source
= impl_test_seek_source_from_IMFMediaSource(iface
);
2458 MediaEventType event_type
;
2463 add_object_state(&actual_object_state_record
, SOURCE_START
);
2465 ok(time_format
&& IsEqualGUID(time_format
, &GUID_NULL
), "Unexpected time format %s.\n",
2466 wine_dbgstr_guid(time_format
));
2467 ok(start_position
&& (start_position
->vt
== VT_I8
|| start_position
->vt
== VT_EMPTY
),
2468 "Unexpected position type.\n");
2470 /* This is what makes IMFMediaSession::Start() seeking fail, not the lacking of MFMEDIASOURCE_CAN_SEEK.
2471 * Without this, IMFMediaSession::Start() seeking succeeds even with the missing MFMEDIASOURCE_CAN_SEEK.
2472 * If this is check is not here, the first IMFMediaSession::Start() call to a non-zero position
2473 * succeeds somehow on Windows 10, then all following seeks fails and no MESessionStarted events */
2474 if (!source
->seekable
&& start_position
&& start_position
->vt
== VT_I8
&& start_position
->hVal
.QuadPart
)
2477 EnterCriticalSection(&source
->cs
);
2479 event_type
= source
->state
!= SOURCE_STOPPED
? MESourceSeeked
: MESourceStarted
;
2480 hr
= IMFMediaEventQueue_QueueEventParamVar(source
->event_queue
, event_type
, &GUID_NULL
, S_OK
, NULL
);
2481 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
2483 for (i
= 0; i
< source
->stream_count
; ++i
)
2485 if (!is_stream_selected(pd
, i
))
2488 var
.vt
= VT_UNKNOWN
;
2489 var
.punkVal
= (IUnknown
*)&source
->streams
[i
]->IMFMediaStream_iface
;
2490 event_type
= source
->streams
[i
]->is_new
? MENewStream
: MEUpdatedStream
;
2491 source
->streams
[i
]->is_new
= FALSE
;
2492 hr
= IMFMediaEventQueue_QueueEventParamVar(source
->event_queue
, event_type
, &GUID_NULL
, S_OK
, &var
);
2493 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
2495 event_type
= source
->state
!= SOURCE_STOPPED
? MEStreamSeeked
: MEStreamStarted
;
2496 hr
= IMFMediaEventQueue_QueueEventParamVar(source
->streams
[i
]->event_queue
, event_type
, &GUID_NULL
,
2498 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
2501 source
->state
= SOURCE_RUNNING
;
2503 LeaveCriticalSection(&source
->cs
);
2508 static HRESULT WINAPI
test_seek_source_Stop(IMFMediaSource
*iface
)
2510 struct test_seek_source
*source
= impl_test_seek_source_from_IMFMediaSource(iface
);
2511 MediaEventType event_type
;
2515 add_object_state(&actual_object_state_record
, SOURCE_STOP
);
2517 EnterCriticalSection(&source
->cs
);
2519 event_type
= MESourceStopped
;
2520 hr
= IMFMediaEventQueue_QueueEventParamVar(source
->event_queue
, event_type
, &GUID_NULL
, S_OK
, NULL
);
2521 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
2523 for (i
= 0; i
< source
->stream_count
; ++i
)
2525 if (!is_stream_selected(source
->pd
, i
))
2528 event_type
= MEStreamStopped
;
2529 hr
= IMFMediaEventQueue_QueueEventParamVar(source
->streams
[i
]->event_queue
, event_type
, &GUID_NULL
,
2531 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
2534 source
->state
= SOURCE_STOPPED
;
2536 LeaveCriticalSection(&source
->cs
);
2541 static HRESULT WINAPI
test_seek_source_Pause(IMFMediaSource
*iface
)
2543 struct test_seek_source
*source
= impl_test_seek_source_from_IMFMediaSource(iface
);
2544 MediaEventType event_type
;
2548 add_object_state(&actual_object_state_record
, SOURCE_PAUSE
);
2550 EnterCriticalSection(&source
->cs
);
2552 event_type
= MESourcePaused
;
2553 hr
= IMFMediaEventQueue_QueueEventParamVar(source
->event_queue
, event_type
, &GUID_NULL
, S_OK
, NULL
);
2554 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
2556 for (i
= 0; i
< source
->stream_count
; ++i
)
2558 if (!is_stream_selected(source
->pd
, i
))
2561 event_type
= MEStreamPaused
;
2562 hr
= IMFMediaEventQueue_QueueEventParamVar(source
->streams
[i
]->event_queue
, event_type
, &GUID_NULL
,
2564 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
2567 source
->state
= SOURCE_PAUSED
;
2568 LeaveCriticalSection(&source
->cs
);
2573 static HRESULT WINAPI
test_seek_source_Shutdown(IMFMediaSource
*iface
)
2575 struct test_seek_source
*source
= impl_test_seek_source_from_IMFMediaSource(iface
);
2578 add_object_state(&actual_object_state_record
, SOURCE_SHUTDOWN
);
2580 hr
= IMFMediaEventQueue_Shutdown(source
->event_queue
);
2581 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
2586 static const IMFMediaSourceVtbl test_seek_source_vtbl
=
2588 test_seek_source_QueryInterface
,
2589 test_seek_source_AddRef
,
2590 test_seek_source_Release
,
2591 test_seek_source_GetEvent
,
2592 test_seek_source_BeginGetEvent
,
2593 test_seek_source_EndGetEvent
,
2594 test_seek_source_QueueEvent
,
2595 test_seek_source_GetCharacteristics
,
2596 test_seek_source_CreatePresentationDescriptor
,
2597 test_seek_source_Start
,
2598 test_seek_source_Stop
,
2599 test_seek_source_Pause
,
2600 test_seek_source_Shutdown
,
2603 static HRESULT WINAPI
test_seek_clock_sink_QueryInterface(IMFClockStateSink
*iface
, REFIID riid
, void **obj
)
2605 if (IsEqualIID(riid
, &IID_IMFClockStateSink
) ||
2606 IsEqualIID(riid
, &IID_IUnknown
))
2609 IMFClockStateSink_AddRef(iface
);
2614 return E_NOINTERFACE
;
2617 static ULONG WINAPI
test_seek_clock_sink_AddRef(IMFClockStateSink
*iface
)
2622 static ULONG WINAPI
test_seek_clock_sink_Release(IMFClockStateSink
*iface
)
2627 static HRESULT WINAPI
test_seek_clock_sink_OnClockStart(IMFClockStateSink
*iface
, MFTIME system_time
, LONGLONG offset
)
2629 add_object_state(&actual_object_state_record
, SINK_ON_CLOCK_START
);
2633 static HRESULT WINAPI
test_seek_clock_sink_OnClockStop(IMFClockStateSink
*iface
, MFTIME system_time
)
2635 add_object_state(&actual_object_state_record
, SINK_ON_CLOCK_STOP
);
2639 static HRESULT WINAPI
test_seek_clock_sink_OnClockPause(IMFClockStateSink
*iface
, MFTIME system_time
)
2641 add_object_state(&actual_object_state_record
, SINK_ON_CLOCK_PAUSE
);
2645 static HRESULT WINAPI
test_seek_clock_sink_OnClockRestart(IMFClockStateSink
*iface
, MFTIME system_time
)
2647 add_object_state(&actual_object_state_record
, SINK_ON_CLOCK_RESTART
);
2651 static HRESULT WINAPI
test_seek_clock_sink_OnClockSetRate(IMFClockStateSink
*iface
, MFTIME system_time
, float rate
)
2653 add_object_state(&actual_object_state_record
, SINK_ON_CLOCK_SETRATE
);
2657 static const IMFClockStateSinkVtbl test_seek_clock_sink_vtbl
=
2659 test_seek_clock_sink_QueryInterface
,
2660 test_seek_clock_sink_AddRef
,
2661 test_seek_clock_sink_Release
,
2662 test_seek_clock_sink_OnClockStart
,
2663 test_seek_clock_sink_OnClockStop
,
2664 test_seek_clock_sink_OnClockPause
,
2665 test_seek_clock_sink_OnClockRestart
,
2666 test_seek_clock_sink_OnClockSetRate
,
2669 static struct test_media_stream
*create_test_stream(DWORD stream_index
, IMFMediaSource
*source
)
2671 struct test_media_stream
*stream
;
2672 IMFPresentationDescriptor
*pd
;
2676 stream
= calloc(1, sizeof(*stream
));
2677 stream
->IMFMediaStream_iface
.lpVtbl
= &test_media_stream_vtbl
;
2678 stream
->refcount
= 1;
2679 hr
= MFCreateEventQueue(&stream
->event_queue
);
2680 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
2681 stream
->source
= source
;
2682 IMFMediaSource_AddRef(stream
->source
);
2683 stream
->is_new
= TRUE
;
2685 IMFMediaSource_CreatePresentationDescriptor(source
, &pd
);
2686 IMFPresentationDescriptor_GetStreamDescriptorByIndex(pd
, stream_index
, &selected
, &stream
->sd
);
2687 IMFPresentationDescriptor_Release(pd
);
2692 static IMFMediaSource
*create_test_seek_source(BOOL seekable
)
2694 struct test_seek_source
*source
;
2697 source
= calloc(1, sizeof(*source
));
2698 source
->IMFMediaSource_iface
.lpVtbl
= &test_seek_source_vtbl
;
2699 source
->refcount
= 1;
2700 source
->stream_count
= 1;
2701 source
->seekable
= seekable
;
2702 MFCreateEventQueue(&source
->event_queue
);
2703 InitializeCriticalSection(&source
->cs
);
2704 for (i
= 0; i
< source
->stream_count
; ++i
)
2705 source
->streams
[i
] = create_test_stream(i
, &source
->IMFMediaSource_iface
);
2707 return &source
->IMFMediaSource_iface
;
2710 static void test_media_session_events(void)
2712 static const media_type_desc audio_float_44100
=
2714 ATTR_GUID(MF_MT_MAJOR_TYPE
, MFMediaType_Audio
),
2715 ATTR_GUID(MF_MT_SUBTYPE
, MFAudioFormat_Float
),
2716 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS
, 1),
2717 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT
, 4),
2718 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND
, 44100),
2719 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND
, 4 * 44100),
2720 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE
, 4 * 8),
2722 static const media_type_desc audio_pcm_48000
=
2724 ATTR_GUID(MF_MT_MAJOR_TYPE
, MFMediaType_Audio
),
2725 ATTR_GUID(MF_MT_SUBTYPE
, MFAudioFormat_PCM
),
2726 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS
, 1),
2727 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT
, 2),
2728 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND
, 48000),
2729 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND
, 2 * 48000),
2730 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE
, 2 * 8),
2733 struct test_stream_sink stream_sink
= test_stream_sink
;
2734 struct test_media_sink media_sink
= test_media_sink
;
2735 struct test_handler handler
= test_handler
;
2736 struct test_source
*source_impl
;
2737 IMFAsyncCallback
*callback
, *callback2
;
2738 IMFMediaType
*input_type
, *output_type
;
2739 IMFTopologyNode
*src_node
, *sink_node
;
2740 IMFPresentationDescriptor
*pd
;
2741 IMFMediaSession
*session
;
2742 IMFStreamDescriptor
*sd
;
2743 IMFAsyncResult
*result
;
2744 IMFMediaSource
*source
;
2745 IMFTopology
*topology
;
2746 IMFMediaEvent
*event
;
2747 PROPVARIANT propvar
;
2751 stream_sink
.handler
= &handler
.IMFMediaTypeHandler_iface
;
2752 stream_sink
.media_sink
= &media_sink
.IMFMediaSink_iface
;
2754 hr
= MFStartup(MF_VERSION
, MFSTARTUP_FULL
);
2755 ok(hr
== S_OK
, "Startup failure, hr %#lx.\n", hr
);
2757 callback
= create_test_callback(TRUE
);
2758 callback2
= create_test_callback(TRUE
);
2760 hr
= MFCreateMediaSession(NULL
, &session
);
2761 ok(hr
== S_OK
, "Failed to create media session, hr %#lx.\n", hr
);
2763 hr
= IMFMediaSession_GetEvent(session
, MF_EVENT_FLAG_NO_WAIT
, &event
);
2764 ok(hr
== MF_E_NO_EVENTS_AVAILABLE
, "Unexpected hr %#lx.\n", hr
);
2767 hr
= IMFMediaSession_BeginGetEvent(session
, NULL
, NULL
);
2768 ok(hr
== E_INVALIDARG
, "Unexpected hr %#lx.\n", hr
);
2770 hr
= IMFMediaSession_BeginGetEvent(session
, callback
, (IUnknown
*)session
);
2771 ok(hr
== S_OK
, "Failed to Begin*, hr %#lx.\n", hr
);
2772 EXPECT_REF(callback
, 2);
2774 /* Same callback, same state. */
2775 hr
= IMFMediaSession_BeginGetEvent(session
, callback
, (IUnknown
*)session
);
2776 ok(hr
== MF_S_MULTIPLE_BEGIN
, "Unexpected hr %#lx.\n", hr
);
2777 EXPECT_REF(callback
, 2);
2779 /* Same callback, different state. */
2780 hr
= IMFMediaSession_BeginGetEvent(session
, callback
, (IUnknown
*)callback
);
2781 ok(hr
== MF_E_MULTIPLE_BEGIN
, "Unexpected hr %#lx.\n", hr
);
2782 EXPECT_REF(callback
, 2);
2784 /* Different callback, same state. */
2785 hr
= IMFMediaSession_BeginGetEvent(session
, callback2
, (IUnknown
*)session
);
2786 ok(hr
== MF_E_MULTIPLE_SUBSCRIBERS
, "Unexpected hr %#lx.\n", hr
);
2787 EXPECT_REF(callback2
, 1);
2789 /* Different callback, different state. */
2790 hr
= IMFMediaSession_BeginGetEvent(session
, callback2
, (IUnknown
*)callback
);
2791 ok(hr
== MF_E_MULTIPLE_SUBSCRIBERS
, "Unexpected hr %#lx.\n", hr
);
2792 EXPECT_REF(callback
, 2);
2794 hr
= MFCreateAsyncResult(NULL
, callback
, NULL
, &result
);
2795 ok(hr
== S_OK
, "Failed to create result, hr %#lx.\n", hr
);
2797 hr
= IMFMediaSession_EndGetEvent(session
, result
, &event
);
2798 ok(hr
== E_FAIL
, "Unexpected hr %#lx.\n", hr
);
2800 /* Shutdown behavior. */
2801 hr
= IMFMediaSession_Shutdown(session
);
2802 ok(hr
== S_OK
, "Failed to shut down, hr %#lx.\n", hr
);
2803 IMFMediaSession_Release(session
);
2805 /* Shutdown leaks callback */
2806 EXPECT_REF(callback
, 2);
2807 EXPECT_REF(callback2
, 1);
2809 IMFAsyncCallback_Release(callback
);
2810 IMFAsyncCallback_Release(callback2
);
2813 callback
= create_test_callback(TRUE
);
2815 hr
= MFCreateMediaSession(NULL
, &session
);
2816 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
2818 propvar
.vt
= VT_EMPTY
;
2819 hr
= IMFMediaSession_Start(session
, &GUID_NULL
, &propvar
);
2820 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
2821 hr
= wait_media_event(session
, callback
, MESessionStarted
, 1000, &propvar
);
2822 ok(hr
== MF_E_INVALIDREQUEST
, "Unexpected hr %#lx.\n", hr
);
2823 ok(propvar
.vt
== VT_EMPTY
, "got vt %u\n", propvar
.vt
);
2825 hr
= IMFMediaSession_Stop(session
);
2826 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
2827 hr
= wait_media_event(session
, callback
, MESessionStopped
, 1000, &propvar
);
2829 ok(hr
== MF_E_INVALIDREQUEST
, "Unexpected hr %#lx.\n", hr
);
2830 ok(propvar
.vt
== VT_EMPTY
, "got vt %u\n", propvar
.vt
);
2832 hr
= IMFMediaSession_Pause(session
);
2833 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
2834 hr
= wait_media_event(session
, callback
, MESessionPaused
, 1000, &propvar
);
2836 ok(hr
== MF_E_INVALIDREQUEST
, "Unexpected hr %#lx.\n", hr
);
2837 ok(propvar
.vt
== VT_EMPTY
, "got vt %u\n", propvar
.vt
);
2839 hr
= IMFMediaSession_ClearTopologies(session
);
2840 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
2841 hr
= wait_media_event(session
, callback
, MESessionTopologiesCleared
, 1000, &propvar
);
2842 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
2843 ok(propvar
.vt
== VT_EMPTY
, "got vt %u\n", propvar
.vt
);
2845 hr
= IMFMediaSession_ClearTopologies(session
);
2846 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
2847 hr
= wait_media_event(session
, callback
, MESessionTopologiesCleared
, 1000, &propvar
);
2848 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
2849 ok(propvar
.vt
== VT_EMPTY
, "got vt %u\n", propvar
.vt
);
2851 hr
= IMFMediaSession_Close(session
);
2852 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
2853 hr
= wait_media_event(session
, callback
, MESessionClosed
, 1000, &propvar
);
2854 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
2855 ok(propvar
.vt
== VT_EMPTY
, "got vt %u\n", propvar
.vt
);
2857 hr
= IMFMediaSession_ClearTopologies(session
);
2858 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
2859 hr
= wait_media_event(session
, callback
, MESessionTopologiesCleared
, 1000, &propvar
);
2860 ok(hr
== MF_E_INVALIDREQUEST
, "Unexpected hr %#lx.\n", hr
);
2861 ok(propvar
.vt
== VT_EMPTY
, "got vt %u\n", propvar
.vt
);
2863 hr
= IMFMediaSession_Shutdown(session
);
2864 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
2866 /* sometimes briefly leaking */
2867 IMFMediaSession_Release(session
);
2870 hr
= MFCreateMediaSession(NULL
, &session
);
2871 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
2873 hr
= MFCreateMediaType(&input_type
);
2874 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
2875 init_media_type(input_type
, audio_float_44100
, -1);
2876 create_descriptors(1, &input_type
, NULL
, &pd
, &sd
);
2878 hr
= MFCreateTopologyNode(MF_TOPOLOGY_OUTPUT_NODE
, &sink_node
);
2879 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
2880 init_sink_node(&stream_sink
.IMFStreamSink_iface
, -1, sink_node
);
2882 hr
= MFCreateMediaType(&output_type
);
2883 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
2884 init_media_type(output_type
, audio_pcm_48000
, -1);
2885 handler
.media_types_count
= 1;
2886 handler
.media_types
= &output_type
;
2888 hr
= MFCreateTopologyNode(MF_TOPOLOGY_SOURCESTREAM_NODE
, &src_node
);
2889 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
2890 init_source_node(NULL
, -1, src_node
, pd
, sd
);
2892 hr
= MFCreateTopology(&topology
);
2893 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
2894 hr
= IMFTopology_AddNode(topology
, sink_node
);
2895 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
2896 hr
= IMFTopology_AddNode(topology
, src_node
);
2897 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
2898 hr
= IMFTopologyNode_ConnectOutput(src_node
, 0, sink_node
, 0);
2899 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
2901 hr
= IMFMediaSession_SetTopology(session
, 0, topology
);
2902 ok(hr
== MF_E_TOPO_MISSING_SOURCE
, "Unexpected hr %#lx.\n", hr
);
2904 source
= create_test_source(pd
);
2905 init_source_node(source
, -1, src_node
, pd
, sd
);
2907 hr
= IMFMediaSession_SetTopology(session
, 0, topology
);
2908 ok(hr
== MF_E_TOPO_STREAM_DESCRIPTOR_NOT_SELECTED
, "Unexpected hr %#lx.\n", hr
);
2910 hr
= IMFMediaSession_ClearTopologies(session
);
2911 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
2912 hr
= wait_media_event(session
, callback
, MESessionTopologiesCleared
, 1000, &propvar
);
2913 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
2914 ok(propvar
.vt
== VT_EMPTY
, "got vt %u\n", propvar
.vt
);
2916 hr
= IMFMediaSession_Shutdown(session
);
2917 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
2918 ok(!media_sink
.shutdown
, "media sink is shutdown.\n");
2919 media_sink
.shutdown
= FALSE
;
2921 /* sometimes briefly leaking */
2922 IMFMediaSession_Release(session
);
2924 if (handler
.current_type
)
2925 IMFMediaType_Release(handler
.current_type
);
2926 handler
.current_type
= NULL
;
2929 /* SetTopology without a current output type */
2931 hr
= MFCreateMediaSession(NULL
, &session
);
2932 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
2934 IMFPresentationDescriptor_SelectStream(pd
, 0);
2936 hr
= IMFMediaSession_SetTopology(session
, MFSESSION_SETTOPOLOGY_NORESOLUTION
, topology
);
2937 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
2938 hr
= wait_media_event(session
, callback
, MESessionTopologySet
, 1000, &propvar
);
2939 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
2940 ok(propvar
.vt
== VT_UNKNOWN
, "got vt %u\n", propvar
.vt
);
2941 ok(propvar
.punkVal
== (IUnknown
*)topology
, "got punkVal %p\n", propvar
.punkVal
);
2942 PropVariantClear(&propvar
);
2944 ok(!handler
.enum_count
, "got %lu GetMediaTypeByIndex\n", handler
.enum_count
);
2945 ok(!handler
.set_current_count
, "got %lu SetCurrentMediaType\n", handler
.set_current_count
);
2946 handler
.enum_count
= handler
.set_current_count
= 0;
2948 hr
= IMFMediaSession_ClearTopologies(session
);
2949 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
2950 hr
= wait_media_event(session
, callback
, MESessionTopologiesCleared
, 1000, &propvar
);
2951 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
2952 ok(propvar
.vt
== VT_EMPTY
, "got vt %u\n", propvar
.vt
);
2954 hr
= IMFMediaSession_Shutdown(session
);
2955 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
2956 ok(media_sink
.shutdown
, "media sink didn't shutdown.\n");
2957 media_sink
.shutdown
= FALSE
;
2959 /* sometimes briefly leaking */
2960 IMFMediaSession_Release(session
);
2962 if (handler
.current_type
)
2963 IMFMediaType_Release(handler
.current_type
);
2964 handler
.current_type
= NULL
;
2967 /* SetTopology without a current output type */
2969 hr
= MFCreateMediaSession(NULL
, &session
);
2970 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
2972 hr
= IMFMediaSession_SetTopology(session
, 0, topology
);
2973 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
2974 hr
= wait_media_event(session
, callback
, MESessionTopologySet
, 1000, &propvar
);
2975 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
2976 ok(propvar
.vt
== VT_UNKNOWN
, "got vt %u\n", propvar
.vt
);
2977 ok(propvar
.punkVal
!= (IUnknown
*)topology
, "got punkVal %p\n", propvar
.punkVal
);
2978 PropVariantClear(&propvar
);
2981 ok(!handler
.enum_count
, "got %lu GetMediaTypeByIndex\n", handler
.enum_count
);
2982 ok(handler
.set_current_count
, "got %lu SetCurrentMediaType\n", handler
.set_current_count
);
2983 handler
.enum_count
= handler
.set_current_count
= 0;
2985 hr
= IMFMediaSession_ClearTopologies(session
);
2986 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
2987 hr
= wait_media_event(session
, callback
, MESessionTopologiesCleared
, 1000, &propvar
);
2988 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
2989 ok(propvar
.vt
== VT_EMPTY
, "got vt %u\n", propvar
.vt
);
2991 hr
= IMFMediaSession_Shutdown(session
);
2992 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
2993 ok(media_sink
.shutdown
, "media sink didn't shutdown.\n");
2994 media_sink
.shutdown
= FALSE
;
2996 /* sometimes briefly leaking */
2997 IMFMediaSession_Release(session
);
2999 if (handler
.current_type
)
3000 IMFMediaType_Release(handler
.current_type
);
3001 handler
.current_type
= NULL
;
3004 /* SetTopology without a current output type, refusing input type */
3006 handler
.invalid_type
= input_type
;
3008 hr
= MFCreateMediaSession(NULL
, &session
);
3009 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3011 hr
= IMFMediaSession_SetTopology(session
, 0, topology
);
3012 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3013 hr
= wait_media_event(session
, callback
, MESessionTopologySet
, 1000, &propvar
);
3014 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3015 ok(propvar
.vt
== VT_UNKNOWN
, "got vt %u\n", propvar
.vt
);
3016 ok(propvar
.punkVal
!= (IUnknown
*)topology
, "got punkVal %p\n", propvar
.punkVal
);
3017 PropVariantClear(&propvar
);
3019 ok(handler
.enum_count
, "got %lu GetMediaTypeByIndex\n", handler
.enum_count
);
3020 ok(handler
.set_current_count
, "got %lu SetCurrentMediaType\n", handler
.set_current_count
);
3021 handler
.enum_count
= handler
.set_current_count
= 0;
3023 hr
= IMFMediaSession_ClearTopologies(session
);
3024 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3025 hr
= wait_media_event(session
, callback
, MESessionTopologiesCleared
, 1000, &propvar
);
3026 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3027 ok(propvar
.vt
== VT_EMPTY
, "got vt %u\n", propvar
.vt
);
3029 hr
= IMFMediaSession_Shutdown(session
);
3030 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3031 ok(media_sink
.shutdown
, "media sink didn't shutdown.\n");
3032 media_sink
.shutdown
= FALSE
;
3034 /* sometimes briefly leaking */
3035 IMFMediaSession_Release(session
);
3037 if (handler
.current_type
)
3038 IMFMediaType_Release(handler
.current_type
);
3039 handler
.current_type
= NULL
;
3042 /* SetTopology without a current output type, refusing input type, requiring a converter */
3044 handler
.media_types_count
= 0;
3045 handler
.invalid_type
= input_type
;
3047 hr
= MFCreateMediaSession(NULL
, &session
);
3048 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3050 hr
= IMFMediaSession_SetTopology(session
, 0, topology
);
3051 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3052 hr
= wait_media_event(session
, callback
, MESessionTopologySet
, 1000, &propvar
);
3053 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3054 ok(propvar
.vt
== VT_UNKNOWN
, "got vt %u\n", propvar
.vt
);
3055 ok(propvar
.punkVal
!= (IUnknown
*)topology
, "got punkVal %p\n", propvar
.punkVal
);
3056 PropVariantClear(&propvar
);
3058 ok(!handler
.enum_count
, "got %lu GetMediaTypeByIndex\n", handler
.enum_count
);
3059 ok(handler
.set_current_count
, "got %lu SetCurrentMediaType\n", handler
.set_current_count
);
3060 handler
.enum_count
= handler
.set_current_count
= 0;
3062 hr
= IMFMediaSession_ClearTopologies(session
);
3063 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3064 hr
= wait_media_event(session
, callback
, MESessionTopologiesCleared
, 1000, &propvar
);
3065 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3066 ok(propvar
.vt
== VT_EMPTY
, "got vt %u\n", propvar
.vt
);
3068 hr
= IMFMediaSession_Shutdown(session
);
3069 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3070 ok(media_sink
.shutdown
, "media sink didn't shutdown.\n");
3071 media_sink
.shutdown
= FALSE
;
3073 /* sometimes briefly leaking */
3074 IMFMediaSession_Release(session
);
3076 if (handler
.current_type
)
3077 IMFMediaType_Release(handler
.current_type
);
3078 handler
.current_type
= NULL
;
3081 /* SetTopology with a current output type */
3083 handler
.media_types_count
= 1;
3084 IMFMediaType_AddRef((handler
.current_type
= output_type
));
3086 hr
= MFCreateMediaSession(NULL
, &session
);
3087 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3089 hr
= IMFMediaSession_SetTopology(session
, 0, topology
);
3090 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3091 hr
= wait_media_event(session
, callback
, MESessionTopologySet
, 1000, &propvar
);
3092 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3093 ok(propvar
.vt
== VT_UNKNOWN
, "got vt %u\n", propvar
.vt
);
3094 ok(propvar
.punkVal
!= (IUnknown
*)topology
, "got punkVal %p\n", propvar
.punkVal
);
3095 PropVariantClear(&propvar
);
3097 ok(!handler
.enum_count
, "got %lu GetMediaTypeByIndex\n", handler
.enum_count
);
3098 ok(handler
.set_current_count
, "got %lu SetCurrentMediaType\n", handler
.set_current_count
);
3099 handler
.enum_count
= handler
.set_current_count
= 0;
3101 hr
= IMFMediaSession_ClearTopologies(session
);
3102 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3103 hr
= wait_media_event(session
, callback
, MESessionTopologiesCleared
, 1000, &propvar
);
3104 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3105 ok(propvar
.vt
== VT_EMPTY
, "got vt %u\n", propvar
.vt
);
3107 hr
= IMFMediaSession_Shutdown(session
);
3108 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3109 ok(media_sink
.shutdown
, "media sink didn't shutdown.\n");
3110 media_sink
.shutdown
= FALSE
;
3112 /* sometimes briefly leaking */
3113 IMFMediaSession_Release(session
);
3116 /* test IMFMediaSession_Start with source returning an error in BeginGetEvent */
3117 source_impl
= impl_from_IMFMediaSource(source
);
3119 hr
= MFCreateMediaSession(NULL
, &session
);
3120 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3122 hr
= IMFMediaSession_SetTopology(session
, 0, topology
);
3123 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3124 hr
= wait_media_event(session
, callback
, MESessionTopologySet
, 1000, &propvar
);
3125 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3126 ok(propvar
.vt
== VT_UNKNOWN
, "got vt %u\n", propvar
.vt
);
3127 ok(propvar
.punkVal
!= (IUnknown
*)topology
, "got punkVal %p\n", propvar
.punkVal
);
3128 PropVariantClear(&propvar
);
3130 source_impl
->begin_get_event_res
= 0x80001234;
3132 SET_EXPECT(test_source_BeginGetEvent
);
3133 SET_EXPECT(test_source_QueueEvent
);
3134 SET_EXPECT(test_source_Start
);
3136 propvar
.vt
= VT_EMPTY
;
3137 hr
= IMFMediaSession_Start(session
, &GUID_NULL
, &propvar
);
3138 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3139 hr
= wait_media_event_until_blocking(session
, callback
, MESessionStarted
, 1000, &propvar
);
3140 ok(hr
== 0x80001234, "Unexpected hr %#lx.\n", hr
);
3141 ok(propvar
.vt
== VT_EMPTY
, "got vt %u\n", propvar
.vt
);
3142 ok(propvar
.punkVal
!= (IUnknown
*)topology
, "got punkVal %p\n", propvar
.punkVal
);
3143 PropVariantClear(&propvar
);
3145 CHECK_CALLED(test_source_BeginGetEvent
);
3146 CHECK_NOT_CALLED(test_source_Start
);
3148 hr
= IMFMediaSession_ClearTopologies(session
);
3149 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3151 hr
= IMFMediaSession_Shutdown(session
);
3152 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3153 ok(media_sink
.shutdown
, "media sink didn't shutdown.\n");
3154 media_sink
.shutdown
= FALSE
;
3156 source_impl
->begin_get_event_res
= E_NOTIMPL
;
3158 CLEAR_CALLED(test_source_BeginGetEvent
);
3159 CLEAR_CALLED(test_source_QueueEvent
);
3160 CLEAR_CALLED(test_source_Start
);
3162 /* sometimes briefly leaking */
3163 IMFMediaSession_Release(session
);
3166 /* test IMFMediaSession_Start when test source BeginGetEvent returns S_OK */
3167 hr
= MFCreateMediaSession(NULL
, &session
);
3168 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3170 hr
= IMFMediaSession_SetTopology(session
, 0, topology
);
3171 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3172 hr
= wait_media_event(session
, callback
, MESessionTopologySet
, 1000, &propvar
);
3173 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3174 ok(propvar
.vt
== VT_UNKNOWN
, "got vt %u\n", propvar
.vt
);
3175 ok(propvar
.punkVal
!= (IUnknown
*)topology
, "got punkVal %p\n", propvar
.punkVal
);
3176 PropVariantClear(&propvar
);
3178 source_impl
= impl_from_IMFMediaSource(source
);
3179 source_impl
->begin_get_event_res
= S_OK
;
3181 SET_EXPECT(test_source_BeginGetEvent
);
3182 SET_EXPECT(test_source_QueueEvent
);
3183 SET_EXPECT(test_source_Start
);
3185 propvar
.vt
= VT_EMPTY
;
3186 hr
= IMFMediaSession_Start(session
, &GUID_NULL
, &propvar
);
3187 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3188 hr
= wait_media_event_until_blocking(session
, callback
, MESessionStarted
, 1000, &propvar
);
3189 ok(hr
== E_NOTIMPL
, "Unexpected hr %#lx.\n", hr
);
3190 ok(propvar
.vt
== VT_EMPTY
, "got vt %u\n", propvar
.vt
);
3191 ok(propvar
.punkVal
!= (IUnknown
*)topology
, "got punkVal %p\n", propvar
.punkVal
);
3192 PropVariantClear(&propvar
);
3194 CHECK_CALLED(test_source_BeginGetEvent
);
3195 CHECK_CALLED(test_source_Start
);
3197 hr
= IMFMediaSession_ClearTopologies(session
);
3198 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3200 hr
= IMFMediaSession_Shutdown(session
);
3201 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3202 ok(media_sink
.shutdown
, "media sink didn't shutdown.\n");
3203 media_sink
.shutdown
= FALSE
;
3205 source_impl
->begin_get_event_res
= E_NOTIMPL
;
3207 CLEAR_CALLED(test_source_BeginGetEvent
);
3208 CLEAR_CALLED(test_source_QueueEvent
);
3209 CLEAR_CALLED(test_source_Start
);
3211 /* sometimes briefly leaking */
3212 IMFMediaSession_Release(session
);
3214 IMFAsyncCallback_Release(callback
);
3216 if (handler
.current_type
)
3217 IMFMediaType_Release(handler
.current_type
);
3218 handler
.current_type
= NULL
;
3220 hr
= IMFTopology_Clear(topology
);
3221 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3222 ref
= IMFTopologyNode_Release(src_node
);
3223 ok(ref
== 0, "Release returned %ld\n", ref
);
3224 ref
= IMFTopologyNode_Release(sink_node
);
3225 ok(ref
== 0, "Release returned %ld\n", ref
);
3226 ref
= IMFTopology_Release(topology
);
3227 ok(ref
== 0, "Release returned %ld\n", ref
);
3229 ref
= IMFMediaSource_Release(source
);
3230 ok(ref
== 0, "Release returned %ld\n", ref
);
3231 ref
= IMFPresentationDescriptor_Release(pd
);
3232 ok(ref
== 0, "Release returned %ld\n", ref
);
3233 ref
= IMFStreamDescriptor_Release(sd
);
3234 ok(ref
== 0, "Release returned %ld\n", ref
);
3235 ref
= IMFMediaType_Release(input_type
);
3236 ok(ref
== 0, "Release returned %ld\n", ref
);
3240 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3243 static void test_media_session(void)
3245 IMFRateSupport
*rate_support
;
3246 IMFAttributes
*attributes
;
3247 IMFMediaSession
*session
;
3248 MFSHUTDOWN_STATUS status
;
3249 IMFTopology
*topology
;
3250 IMFShutdown
*shutdown
;
3251 PROPVARIANT propvar
;
3257 hr
= MFStartup(MF_VERSION
, MFSTARTUP_FULL
);
3258 ok(hr
== S_OK
, "Startup failure, hr %#lx.\n", hr
);
3260 hr
= MFCreateMediaSession(NULL
, &session
);
3261 ok(hr
== S_OK
, "Failed to create media session, hr %#lx.\n", hr
);
3263 check_interface(session
, &IID_IMFGetService
, TRUE
);
3264 check_interface(session
, &IID_IMFRateSupport
, TRUE
);
3265 check_interface(session
, &IID_IMFRateControl
, TRUE
);
3266 check_interface(session
, &IID_IMFAttributes
, FALSE
);
3267 check_interface(session
, &IID_IMFTopologyNodeAttributeEditor
, FALSE
);
3268 check_interface(session
, &IID_IMFLocalMFTRegistration
, FALSE
);
3269 check_service_interface(session
, &MF_RATE_CONTROL_SERVICE
, &IID_IMFRateSupport
, TRUE
);
3270 check_service_interface(session
, &MF_RATE_CONTROL_SERVICE
, &IID_IMFRateControl
, TRUE
);
3271 check_service_interface(session
, &MF_TOPONODE_ATTRIBUTE_EDITOR_SERVICE
, &IID_IMFTopologyNodeAttributeEditor
, TRUE
);
3272 check_service_interface(session
, &MF_LOCAL_MFT_REGISTRATION_SERVICE
, &IID_IMFLocalMFTRegistration
, TRUE
);
3274 hr
= IMFMediaSession_GetClock(session
, &clock
);
3275 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3277 hr
= IMFClock_QueryInterface(clock
, &IID_IMFShutdown
, (void **)&shutdown
);
3278 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3280 hr
= IMFShutdown_GetShutdownStatus(shutdown
, &status
);
3281 ok(hr
== MF_E_INVALIDREQUEST
, "Unexpected hr %#lx.\n", hr
);
3283 hr
= IMFMediaSession_Shutdown(session
);
3284 ok(hr
== S_OK
, "Failed to shut down, hr %#lx.\n", hr
);
3286 check_interface(session
, &IID_IMFGetService
, TRUE
);
3288 hr
= IMFMediaSession_QueryInterface(session
, &IID_IMFGetService
, (void **)&gs
);
3289 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3291 hr
= IMFGetService_GetService(gs
, &MF_RATE_CONTROL_SERVICE
, &IID_IMFRateSupport
, (void **)&rate_support
);
3292 ok(hr
== MF_E_SHUTDOWN
, "Unexpected hr %#lx.\n", hr
);
3294 IMFGetService_Release(gs
);
3296 hr
= IMFShutdown_GetShutdownStatus(shutdown
, &status
);
3297 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3298 ok(status
== MFSHUTDOWN_COMPLETED
, "Unexpected shutdown status %u.\n", status
);
3300 IMFShutdown_Release(shutdown
);
3302 hr
= IMFMediaSession_ClearTopologies(session
);
3303 ok(hr
== MF_E_SHUTDOWN
, "Unexpected hr %#lx.\n", hr
);
3305 hr
= IMFMediaSession_Start(session
, &GUID_NULL
, NULL
);
3306 ok(hr
== E_POINTER
, "Unexpected hr %#lx.\n", hr
);
3308 propvar
.vt
= VT_EMPTY
;
3309 hr
= IMFMediaSession_Start(session
, &GUID_NULL
, &propvar
);
3310 ok(hr
== MF_E_SHUTDOWN
, "Unexpected hr %#lx.\n", hr
);
3312 hr
= IMFMediaSession_Pause(session
);
3313 ok(hr
== MF_E_SHUTDOWN
, "Unexpected hr %#lx.\n", hr
);
3315 hr
= IMFMediaSession_Stop(session
);
3316 ok(hr
== MF_E_SHUTDOWN
, "Unexpected hr %#lx.\n", hr
);
3318 hr
= IMFMediaSession_Close(session
);
3319 ok(hr
== MF_E_SHUTDOWN
, "Unexpected hr %#lx.\n", hr
);
3321 hr
= IMFMediaSession_GetClock(session
, &clock
);
3322 ok(hr
== MF_E_SHUTDOWN
|| broken(hr
== E_UNEXPECTED
) /* Win7 */, "Unexpected hr %#lx.\n", hr
);
3324 hr
= IMFMediaSession_GetSessionCapabilities(session
, &caps
);
3325 ok(hr
== MF_E_SHUTDOWN
, "Unexpected hr %#lx.\n", hr
);
3327 hr
= IMFMediaSession_GetSessionCapabilities(session
, NULL
);
3328 ok(hr
== E_POINTER
, "Unexpected hr %#lx.\n", hr
);
3330 hr
= IMFMediaSession_GetFullTopology(session
, MFSESSION_GETFULLTOPOLOGY_CURRENT
, 0, &topology
);
3331 ok(hr
== MF_E_SHUTDOWN
, "Unexpected hr %#lx.\n", hr
);
3333 hr
= IMFMediaSession_Shutdown(session
);
3334 ok(hr
== MF_E_SHUTDOWN
, "Unexpected hr %#lx.\n", hr
);
3336 IMFMediaSession_Release(session
);
3338 /* Custom topology loader, GUID is not registered. */
3339 hr
= MFCreateAttributes(&attributes
, 1);
3340 ok(hr
== S_OK
, "Failed to create attributes, hr %#lx.\n", hr
);
3342 hr
= IMFAttributes_SetGUID(attributes
, &MF_SESSION_TOPOLOADER
, &MF_SESSION_TOPOLOADER
);
3343 ok(hr
== S_OK
, "Failed to set attribute, hr %#lx.\n", hr
);
3345 hr
= MFCreateMediaSession(attributes
, &session
);
3346 ok(hr
== S_OK
, "Failed to create media session, hr %#lx.\n", hr
);
3347 IMFMediaSession_Release(session
);
3349 /* Disabled quality manager. */
3350 hr
= IMFAttributes_SetGUID(attributes
, &MF_SESSION_QUALITY_MANAGER
, &GUID_NULL
);
3351 ok(hr
== S_OK
, "Failed to set attribute, hr %#lx.\n", hr
);
3353 hr
= MFCreateMediaSession(attributes
, &session
);
3354 ok(hr
== S_OK
, "Failed to create media session, hr %#lx.\n", hr
);
3355 IMFMediaSession_Release(session
);
3357 IMFAttributes_Release(attributes
);
3360 static void test_media_session_rate_control(void)
3362 IMFRateControl
*rate_control
, *clock_rate_control
;
3363 IMFPresentationClock
*presentation_clock
;
3364 IMFPresentationTimeSource
*time_source
;
3365 MFCLOCK_PROPERTIES clock_props
;
3366 IMFRateSupport
*rate_support
;
3367 IMFMediaSession
*session
;
3373 hr
= MFStartup(MF_VERSION
, MFSTARTUP_FULL
);
3374 ok(hr
== S_OK
, "Startup failure, hr %#lx.\n", hr
);
3376 hr
= MFCreateMediaSession(NULL
, &session
);
3377 ok(hr
== S_OK
, "Failed to create media session, hr %#lx.\n", hr
);
3379 hr
= MFGetService((IUnknown
*)session
, &MF_RATE_CONTROL_SERVICE
, &IID_IMFRateSupport
, (void **)&rate_support
);
3380 ok(hr
== S_OK
, "Failed to get rate support interface, hr %#lx.\n", hr
);
3382 hr
= MFGetService((IUnknown
*)session
, &MF_RATE_CONTROL_SERVICE
, &IID_IMFRateControl
, (void **)&rate_control
);
3383 ok(hr
== S_OK
, "Failed to get rate control interface, hr %#lx.\n", hr
);
3385 hr
= IMFRateControl_GetRate(rate_control
, NULL
, NULL
);
3386 ok(FAILED(hr
), "Unexpected hr %#lx.\n", hr
);
3389 hr
= IMFRateControl_GetRate(rate_control
, NULL
, &rate
);
3390 ok(hr
== S_OK
, "Failed to get playback rate, hr %#lx.\n", hr
);
3391 ok(rate
== 1.0f
, "Unexpected rate %f.\n", rate
);
3393 hr
= IMFRateControl_GetRate(rate_control
, &thin
, NULL
);
3394 ok(FAILED(hr
), "Unexpected hr %#lx.\n", hr
);
3398 hr
= IMFRateControl_GetRate(rate_control
, &thin
, &rate
);
3399 ok(hr
== S_OK
, "Failed to get playback rate, hr %#lx.\n", hr
);
3400 ok(!thin
, "Unexpected thinning.\n");
3401 ok(rate
== 1.0f
, "Unexpected rate %f.\n", rate
);
3403 hr
= IMFMediaSession_GetClock(session
, &clock
);
3404 ok(hr
== S_OK
, "Failed to get clock, hr %#lx.\n", hr
);
3406 hr
= IMFClock_QueryInterface(clock
, &IID_IMFPresentationClock
, (void **)&presentation_clock
);
3407 ok(hr
== S_OK
, "Failed to get rate control, hr %#lx.\n", hr
);
3409 hr
= IMFClock_QueryInterface(clock
, &IID_IMFRateControl
, (void **)&clock_rate_control
);
3410 ok(hr
== S_OK
, "Failed to get rate control, hr %#lx.\n", hr
);
3413 hr
= IMFRateControl_GetRate(clock_rate_control
, NULL
, &rate
);
3414 ok(hr
== S_OK
, "Failed to get clock rate, hr %#lx.\n", hr
);
3415 ok(rate
== 1.0f
, "Unexpected rate %f.\n", rate
);
3417 hr
= IMFRateControl_SetRate(clock_rate_control
, FALSE
, 1.5f
);
3418 ok(hr
== MF_E_CLOCK_NO_TIME_SOURCE
, "Unexpected hr %#lx.\n", hr
);
3420 hr
= IMFRateControl_SetRate(rate_control
, FALSE
, 1.5f
);
3421 ok(hr
== S_OK
, "Failed to set rate, hr %#lx.\n", hr
);
3423 hr
= IMFClock_GetProperties(clock
, &clock_props
);
3424 ok(hr
== MF_E_CLOCK_NO_TIME_SOURCE
, "Unexpected hr %#lx.\n", hr
);
3426 hr
= MFCreateSystemTimeSource(&time_source
);
3427 ok(hr
== S_OK
, "Failed to create time source, hr %#lx.\n", hr
);
3429 hr
= IMFPresentationClock_SetTimeSource(presentation_clock
, time_source
);
3430 ok(hr
== S_OK
, "Failed to set time source, hr %#lx.\n", hr
);
3432 hr
= IMFRateControl_SetRate(rate_control
, FALSE
, 1.5f
);
3433 ok(hr
== S_OK
, "Failed to set rate, hr %#lx.\n", hr
);
3436 hr
= IMFRateControl_GetRate(clock_rate_control
, NULL
, &rate
);
3437 ok(hr
== S_OK
, "Failed to get clock rate, hr %#lx.\n", hr
);
3438 ok(rate
== 1.0f
, "Unexpected rate %f.\n", rate
);
3440 IMFPresentationTimeSource_Release(time_source
);
3442 IMFRateControl_Release(clock_rate_control
);
3443 IMFPresentationClock_Release(presentation_clock
);
3444 IMFClock_Release(clock
);
3446 IMFRateControl_Release(rate_control
);
3447 IMFRateSupport_Release(rate_support
);
3449 IMFMediaSession_Release(session
);
3452 ok(hr
== S_OK
, "Shutdown failure, hr %#lx.\n", hr
);
3455 struct test_grabber_callback
3457 IMFSampleGrabberSinkCallback IMFSampleGrabberSinkCallback_iface
;
3460 IMFCollection
*samples
;
3465 static struct test_grabber_callback
*impl_from_IMFSampleGrabberSinkCallback(IMFSampleGrabberSinkCallback
*iface
)
3467 return CONTAINING_RECORD(iface
, struct test_grabber_callback
, IMFSampleGrabberSinkCallback_iface
);
3470 static HRESULT WINAPI
test_grabber_callback_QueryInterface(IMFSampleGrabberSinkCallback
*iface
, REFIID riid
, void **obj
)
3472 if (IsEqualIID(riid
, &IID_IMFSampleGrabberSinkCallback
) ||
3473 IsEqualIID(riid
, &IID_IMFClockStateSink
) ||
3474 IsEqualIID(riid
, &IID_IUnknown
))
3477 IMFSampleGrabberSinkCallback_AddRef(iface
);
3482 return E_NOINTERFACE
;
3485 static ULONG WINAPI
test_grabber_callback_AddRef(IMFSampleGrabberSinkCallback
*iface
)
3487 struct test_grabber_callback
*grabber
= impl_from_IMFSampleGrabberSinkCallback(iface
);
3488 return InterlockedIncrement(&grabber
->refcount
);
3491 static ULONG WINAPI
test_grabber_callback_Release(IMFSampleGrabberSinkCallback
*iface
)
3493 struct test_grabber_callback
*grabber
= impl_from_IMFSampleGrabberSinkCallback(iface
);
3494 ULONG refcount
= InterlockedDecrement(&grabber
->refcount
);
3498 IMFCollection_Release(grabber
->samples
);
3499 if (grabber
->ready_event
)
3500 CloseHandle(grabber
->ready_event
);
3501 if (grabber
->done_event
)
3502 CloseHandle(grabber
->done_event
);
3509 static HRESULT WINAPI
test_grabber_callback_OnClockStart(IMFSampleGrabberSinkCallback
*iface
, MFTIME time
, LONGLONG offset
)
3514 static HRESULT WINAPI
test_grabber_callback_OnClockStop(IMFSampleGrabberSinkCallback
*iface
, MFTIME time
)
3519 static HRESULT WINAPI
test_grabber_callback_OnClockPause(IMFSampleGrabberSinkCallback
*iface
, MFTIME time
)
3524 static HRESULT WINAPI
test_grabber_callback_OnClockRestart(IMFSampleGrabberSinkCallback
*iface
, MFTIME time
)
3529 static HRESULT WINAPI
test_grabber_callback_OnClockSetRate(IMFSampleGrabberSinkCallback
*iface
, MFTIME time
, float rate
)
3534 static HRESULT WINAPI
test_grabber_callback_OnSetPresentationClock(IMFSampleGrabberSinkCallback
*iface
,
3535 IMFPresentationClock
*clock
)
3540 static HRESULT WINAPI
test_grabber_callback_OnProcessSample(IMFSampleGrabberSinkCallback
*iface
, REFGUID major_type
,
3541 DWORD sample_flags
, LONGLONG sample_time
, LONGLONG sample_duration
, const BYTE
*buffer
, DWORD sample_size
)
3543 struct test_grabber_callback
*grabber
= CONTAINING_RECORD(iface
, struct test_grabber_callback
, IMFSampleGrabberSinkCallback_iface
);
3548 if (!grabber
->ready_event
)
3551 sample
= create_sample(buffer
, sample_size
);
3552 hr
= IMFSample_SetSampleFlags(sample
, sample_flags
);
3553 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3554 /* FIXME: sample time is inconsistent across windows versions, ignore it */
3555 hr
= IMFSample_SetSampleTime(sample
, 0);
3556 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3557 hr
= IMFSample_SetSampleDuration(sample
, sample_duration
);
3558 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3559 IMFCollection_AddElement(grabber
->samples
, (IUnknown
*)sample
);
3560 IMFSample_Release(sample
);
3562 SetEvent(grabber
->ready_event
);
3563 res
= WaitForSingleObject(grabber
->done_event
, 1000);
3564 ok(!res
, "WaitForSingleObject returned %#lx\n", res
);
3569 static HRESULT WINAPI
test_grabber_callback_OnShutdown(IMFSampleGrabberSinkCallback
*iface
)
3574 static const IMFSampleGrabberSinkCallbackVtbl test_grabber_callback_vtbl
=
3576 test_grabber_callback_QueryInterface
,
3577 test_grabber_callback_AddRef
,
3578 test_grabber_callback_Release
,
3579 test_grabber_callback_OnClockStart
,
3580 test_grabber_callback_OnClockStop
,
3581 test_grabber_callback_OnClockPause
,
3582 test_grabber_callback_OnClockRestart
,
3583 test_grabber_callback_OnClockSetRate
,
3584 test_grabber_callback_OnSetPresentationClock
,
3585 test_grabber_callback_OnProcessSample
,
3586 test_grabber_callback_OnShutdown
,
3589 static IMFSampleGrabberSinkCallback
*create_test_grabber_callback(void)
3591 struct test_grabber_callback
*grabber
;
3594 if (!(grabber
= calloc(1, sizeof(*grabber
))))
3597 grabber
->IMFSampleGrabberSinkCallback_iface
.lpVtbl
= &test_grabber_callback_vtbl
;
3598 grabber
->refcount
= 1;
3599 hr
= MFCreateCollection(&grabber
->samples
);
3600 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3602 return &grabber
->IMFSampleGrabberSinkCallback_iface
;
3605 enum loader_test_flags
3608 LOADER_NEEDS_VIDEO_PROCESSOR
= 0x8,
3609 LOADER_SET_ENUMERATE_SOURCE_TYPES
= 0x10,
3610 LOADER_NO_CURRENT_OUTPUT
= 0x20,
3611 LOADER_SET_INVALID_INPUT
= 0x40,
3612 LOADER_SET_MEDIA_TYPES
= 0x80,
3613 LOADER_ADD_RESAMPLER_MFT
= 0x100,
3616 static void test_topology_loader(void)
3618 static const media_type_desc audio_float_44100
=
3620 ATTR_GUID(MF_MT_MAJOR_TYPE
, MFMediaType_Audio
),
3621 ATTR_GUID(MF_MT_SUBTYPE
, MFAudioFormat_Float
),
3622 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS
, 1),
3623 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT
, 4),
3624 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND
, 44100),
3625 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND
, 4 * 44100),
3626 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE
, 4 * 8),
3628 static const media_type_desc audio_pcm_44100
=
3630 ATTR_GUID(MF_MT_MAJOR_TYPE
, MFMediaType_Audio
),
3631 ATTR_GUID(MF_MT_SUBTYPE
, MFAudioFormat_PCM
),
3632 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS
, 1),
3633 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND
, 44100),
3634 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND
, 44100),
3635 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT
, 1),
3636 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE
, 8),
3638 static const media_type_desc audio_pcm_48000
=
3640 ATTR_GUID(MF_MT_MAJOR_TYPE
, MFMediaType_Audio
),
3641 ATTR_GUID(MF_MT_SUBTYPE
, MFAudioFormat_PCM
),
3642 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS
, 1),
3643 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND
, 48000),
3644 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND
, 48000),
3645 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT
, 1),
3646 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE
, 8),
3648 static const media_type_desc audio_pcm_48000_resampler
=
3650 ATTR_GUID(MF_MT_MAJOR_TYPE
, MFMediaType_Audio
),
3651 ATTR_GUID(MF_MT_SUBTYPE
, MFAudioFormat_PCM
),
3652 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE
, 16),
3653 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS
, 2),
3654 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND
, 48000),
3655 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND
, 192000),
3656 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT
, 4),
3657 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT
, 1),
3658 ATTR_UINT32(MF_MT_AUDIO_PREFER_WAVEFORMATEX
, 1),
3660 static const media_type_desc audio_float_48000
=
3662 ATTR_GUID(MF_MT_MAJOR_TYPE
, MFMediaType_Audio
),
3663 ATTR_GUID(MF_MT_SUBTYPE
, MFAudioFormat_Float
),
3664 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS
, 2),
3665 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND
, 48000),
3666 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND
, 8 * 48000),
3667 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT
, 8),
3668 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE
, 32),
3670 static const media_type_desc audio_mp3_44100
=
3672 ATTR_GUID(MF_MT_MAJOR_TYPE
, MFMediaType_Audio
),
3673 ATTR_GUID(MF_MT_SUBTYPE
, MFAudioFormat_MP3
),
3674 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS
, 2),
3675 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND
, 44100),
3676 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND
, 16000),
3677 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT
, 1),
3679 static const media_type_desc audio_pcm_44100_incomplete
=
3681 ATTR_GUID(MF_MT_MAJOR_TYPE
, MFMediaType_Audio
),
3682 ATTR_GUID(MF_MT_SUBTYPE
, MFAudioFormat_PCM
),
3683 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS
, 1),
3684 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND
, 44100),
3685 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT
, 1),
3686 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE
, 8),
3688 static const media_type_desc audio_float_44100_stereo
=
3690 ATTR_GUID(MF_MT_MAJOR_TYPE
, MFMediaType_Audio
),
3691 ATTR_GUID(MF_MT_SUBTYPE
, MFAudioFormat_Float
),
3692 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS
, 2),
3693 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT
, 2 * 4),
3694 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND
, 44100),
3695 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND
, 2 * 4 * 44100),
3696 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE
, 4 * 8),
3697 ATTR_UINT32(MF_MT_AUDIO_CHANNEL_MASK
, 3),
3698 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT
, 1),
3700 static const media_type_desc video_i420_1280
=
3702 ATTR_GUID(MF_MT_MAJOR_TYPE
, MFMediaType_Video
),
3703 ATTR_GUID(MF_MT_SUBTYPE
, MFVideoFormat_I420
),
3704 ATTR_RATIO(MF_MT_FRAME_SIZE
, 1280, 720),
3706 static const media_type_desc video_color_convert_1280_rgb32
=
3708 ATTR_GUID(MF_MT_MAJOR_TYPE
, MFMediaType_Video
),
3709 ATTR_GUID(MF_MT_SUBTYPE
, DMOVideoFormat_RGB32
),
3710 ATTR_RATIO(MF_MT_FRAME_SIZE
, 1280, 720),
3712 static const media_type_desc video_video_processor_1280_rgb32
=
3714 ATTR_GUID(MF_MT_MAJOR_TYPE
, MFMediaType_Video
),
3715 ATTR_GUID(MF_MT_SUBTYPE
, MFVideoFormat_RGB32
),
3716 ATTR_RATIO(MF_MT_FRAME_SIZE
, 1280, 720),
3718 static const media_type_desc video_video_processor_rgb32
=
3720 ATTR_GUID(MF_MT_MAJOR_TYPE
, MFMediaType_Video
),
3721 ATTR_GUID(MF_MT_SUBTYPE
, MFVideoFormat_RGB32
),
3723 static const media_type_desc video_h264_1280
=
3725 ATTR_GUID(MF_MT_MAJOR_TYPE
, MFMediaType_Video
),
3726 ATTR_GUID(MF_MT_SUBTYPE
, MFVideoFormat_H264
),
3727 ATTR_RATIO(MF_MT_FRAME_SIZE
, 1280, 720),
3729 static const media_type_desc video_nv12_1280
=
3731 ATTR_GUID(MF_MT_MAJOR_TYPE
, MFMediaType_Video
),
3732 ATTR_GUID(MF_MT_SUBTYPE
, MFVideoFormat_NV12
),
3733 ATTR_RATIO(MF_MT_FRAME_RATE
, 30000, 1001),
3734 ATTR_RATIO(MF_MT_FRAME_SIZE
, 1280, 720),
3735 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO
, 1, 1),
3736 ATTR_UINT32(MF_MT_SAMPLE_SIZE
, 1280 * 720 * 3 / 2),
3737 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT
, 1),
3738 ATTR_UINT32(MF_MT_DEFAULT_STRIDE
, 1280),
3739 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES
, 1),
3740 ATTR_UINT32(MF_MT_INTERLACE_MODE
, 7),
3742 static const media_type_desc video_dummy
=
3744 ATTR_GUID(MF_MT_MAJOR_TYPE
, MFMediaType_Video
),
3747 const struct loader_test
3749 const media_type_desc
*input_type
;
3750 const media_type_desc
*output_type
;
3751 const media_type_desc
*current_input
;
3752 const media_type_desc
*decoded_type
;
3753 MF_CONNECT_METHOD source_method
;
3754 MF_CONNECT_METHOD sink_method
;
3755 HRESULT expected_result
;
3758 GUID converter_class
;
3763 /* PCM -> PCM, same enumerated type, no current type */
3764 .input_type
= &audio_pcm_44100
, .output_type
= &audio_pcm_44100
, .sink_method
= MF_CONNECT_DIRECT
, .source_method
= -1,
3765 .expected_result
= S_OK
,
3768 /* PCM -> PCM, same enumerated type, incomplete current type */
3769 .input_type
= &audio_pcm_44100
, .output_type
= &audio_pcm_44100
, .sink_method
= MF_CONNECT_DIRECT
, .source_method
= -1,
3770 .current_input
= &audio_pcm_44100_incomplete
,
3771 .expected_result
= MF_E_INVALIDMEDIATYPE
,
3772 .flags
= LOADER_TODO
,
3775 /* PCM -> PCM, same enumerated bps, different current bps */
3776 .input_type
= &audio_pcm_48000
, .output_type
= &audio_pcm_48000
, .sink_method
= MF_CONNECT_DIRECT
, .source_method
= -1,
3777 .current_input
= &audio_pcm_44100
,
3778 .expected_result
= MF_E_INVALIDMEDIATYPE
,
3781 /* PCM -> PCM, same enumerated bps, different current bps, force enumerate */
3782 .input_type
= &audio_pcm_48000
, .output_type
= &audio_pcm_48000
, .sink_method
= MF_CONNECT_DIRECT
, .source_method
= -1,
3783 .current_input
= &audio_pcm_44100
,
3784 .expected_result
= S_OK
,
3785 .flags
= LOADER_SET_ENUMERATE_SOURCE_TYPES
,
3789 /* PCM -> PCM, incomplete enumerated type, same current type */
3790 .input_type
= &audio_pcm_44100_incomplete
, .output_type
= &audio_pcm_44100
, .sink_method
= MF_CONNECT_DIRECT
, .source_method
= -1,
3791 .current_input
= &audio_pcm_44100
,
3792 .expected_result
= S_OK
,
3795 /* PCM -> PCM, incomplete enumerated type, same current type, force enumerate */
3796 .input_type
= &audio_pcm_44100_incomplete
, .output_type
= &audio_pcm_44100
, .sink_method
= MF_CONNECT_DIRECT
, .source_method
= -1,
3797 .current_input
= &audio_pcm_44100
,
3798 .expected_result
= MF_E_NO_MORE_TYPES
,
3799 .flags
= LOADER_SET_ENUMERATE_SOURCE_TYPES
| LOADER_TODO
,
3803 /* PCM -> PCM, different enumerated bps, no current type */
3804 .input_type
= &audio_pcm_44100
, .output_type
= &audio_pcm_48000
, .sink_method
= MF_CONNECT_DIRECT
, .source_method
= -1,
3805 .expected_result
= MF_E_INVALIDMEDIATYPE
,
3808 /* PCM -> PCM, different enumerated bps, same current bps */
3809 .input_type
= &audio_pcm_44100
, .output_type
= &audio_pcm_48000
, .sink_method
= MF_CONNECT_DIRECT
, .source_method
= -1,
3810 .current_input
= &audio_pcm_48000
,
3811 .expected_result
= S_OK
,
3814 /* PCM -> PCM, different enumerated bps, same current bps, force enumerate */
3815 .input_type
= &audio_pcm_44100
, .output_type
= &audio_pcm_48000
, .sink_method
= MF_CONNECT_DIRECT
, .source_method
= -1,
3816 .current_input
= &audio_pcm_48000
,
3817 .expected_result
= MF_E_NO_MORE_TYPES
,
3818 .flags
= LOADER_SET_ENUMERATE_SOURCE_TYPES
,
3821 /* PCM -> PCM, different enumerated bps, no current type, sink allow converter */
3822 .input_type
= &audio_pcm_44100
, .output_type
= &audio_pcm_48000
, .sink_method
= MF_CONNECT_ALLOW_CONVERTER
, .source_method
= MF_CONNECT_DIRECT
,
3823 .expected_result
= S_OK
, .converter_class
= CLSID_CResamplerMediaObject
,
3826 /* PCM -> PCM, different enumerated bps, same current type, sink allow converter, force enumerate */
3827 .input_type
= &audio_pcm_44100
, .output_type
= &audio_pcm_48000
, .sink_method
= MF_CONNECT_ALLOW_CONVERTER
, .source_method
= -1,
3828 .current_input
= &audio_pcm_48000
,
3829 .expected_result
= S_OK
, .converter_class
= CLSID_CResamplerMediaObject
,
3830 .flags
= LOADER_SET_ENUMERATE_SOURCE_TYPES
,
3833 /* PCM -> PCM, different enumerated bps, no current type, sink allow decoder */
3834 .input_type
= &audio_pcm_44100
, .output_type
= &audio_pcm_48000
, .sink_method
= MF_CONNECT_ALLOW_DECODER
, .source_method
= MF_CONNECT_DIRECT
,
3835 .expected_result
= S_OK
, .converter_class
= CLSID_CResamplerMediaObject
,
3838 /* PCM -> PCM, different enumerated bps, no current type, default methods */
3839 .input_type
= &audio_pcm_44100
, .output_type
= &audio_pcm_48000
, .sink_method
= -1, .source_method
= -1,
3840 .expected_result
= S_OK
, .converter_class
= CLSID_CResamplerMediaObject
,
3843 /* PCM -> PCM, different enumerated bps, no current type, source allow converter */
3844 .input_type
= &audio_pcm_44100
, .output_type
= &audio_pcm_48000
, .sink_method
= MF_CONNECT_DIRECT
, .source_method
= MF_CONNECT_ALLOW_CONVERTER
,
3845 .expected_result
= MF_E_INVALIDMEDIATYPE
,
3849 /* Float -> PCM, refuse input type, add converter */
3850 .input_type
= &audio_float_44100
, .output_type
= &audio_pcm_48000
, .sink_method
= MF_CONNECT_DIRECT
, .source_method
= -1,
3851 .expected_result
= MF_E_NO_MORE_TYPES
, .converter_class
= CLSID_CResamplerMediaObject
,
3852 .flags
= LOADER_SET_INVALID_INPUT
| LOADER_ADD_RESAMPLER_MFT
,
3855 /* Float -> PCM, refuse input type, add converter, allow resampler output type */
3856 .input_type
= &audio_float_44100
, .output_type
= &audio_pcm_48000_resampler
, .sink_method
= MF_CONNECT_DIRECT
, .source_method
= -1,
3857 .expected_result
= S_OK
, .converter_class
= CLSID_CResamplerMediaObject
,
3858 .flags
= LOADER_SET_INVALID_INPUT
| LOADER_ADD_RESAMPLER_MFT
,
3863 .input_type
= &audio_mp3_44100
, .output_type
= &audio_pcm_44100
, .sink_method
= MF_CONNECT_DIRECT
, .source_method
= -1,
3864 .current_input
= &audio_mp3_44100
,
3865 .expected_result
= MF_E_INVALIDMEDIATYPE
,
3868 /* MP3 -> PCM, force enumerate */
3869 .input_type
= &audio_mp3_44100
, .output_type
= &audio_pcm_44100
, .sink_method
= MF_CONNECT_DIRECT
, .source_method
= -1,
3870 .current_input
= &audio_mp3_44100
,
3871 .expected_result
= MF_E_NO_MORE_TYPES
,
3872 .flags
= LOADER_SET_ENUMERATE_SOURCE_TYPES
,
3876 .input_type
= &audio_mp3_44100
, .output_type
= &audio_pcm_44100
, .sink_method
= MF_CONNECT_ALLOW_CONVERTER
, .source_method
= -1,
3877 .current_input
= &audio_mp3_44100
,
3878 .expected_result
= MF_E_TRANSFORM_NOT_POSSIBLE_FOR_CURRENT_MEDIATYPE_COMBINATION
,
3879 .flags
= LOADER_TODO
,
3883 .input_type
= &audio_mp3_44100
, .output_type
= &audio_pcm_44100
, .sink_method
= MF_CONNECT_ALLOW_DECODER
, .source_method
= -1,
3884 .current_input
= &audio_mp3_44100
,
3885 .expected_result
= S_OK
, .decoder_class
= CLSID_CMP3DecMediaObject
,
3886 .flags
= LOADER_TODO
,
3889 /* MP3 -> PCM, need both decoder and converter */
3890 .input_type
= &audio_mp3_44100
, .output_type
= &audio_float_48000
, .sink_method
= MF_CONNECT_ALLOW_DECODER
, .source_method
= -1,
3891 .current_input
= &audio_mp3_44100
, .decoded_type
= &audio_float_44100_stereo
,
3892 .expected_result
= S_OK
, .decoder_class
= CLSID_CMP3DecMediaObject
, .converter_class
= CLSID_CResamplerMediaObject
,
3893 .flags
= LOADER_TODO
,
3897 /* I420 -> RGB32, Color Convert media type */
3898 .input_type
= &video_i420_1280
, .output_type
= &video_color_convert_1280_rgb32
, .sink_method
= -1, .source_method
= -1,
3899 .expected_result
= MF_E_TOPO_CODEC_NOT_FOUND
, .converter_class
= CLSID_CColorConvertDMO
,
3900 .flags
= LOADER_NEEDS_VIDEO_PROCESSOR
,
3903 /* I420 -> RGB32, Video Processor media type */
3904 .input_type
= &video_i420_1280
, .output_type
= &video_video_processor_1280_rgb32
, .sink_method
= -1, .source_method
= -1,
3905 .expected_result
= S_OK
, .converter_class
= CLSID_CColorConvertDMO
,
3908 /* I420 -> RGB32, Video Processor media type without frame size */
3909 .input_type
= &video_i420_1280
, .output_type
= &video_video_processor_rgb32
, .sink_method
= -1, .source_method
= -1,
3910 .expected_result
= S_OK
, .converter_class
= CLSID_CColorConvertDMO
,
3913 /* H264 -> RGB32, Video Processor media type */
3914 .input_type
= &video_h264_1280
, .output_type
= &video_video_processor_1280_rgb32
, .sink_method
= -1, .source_method
= -1,
3915 .decoded_type
= &video_nv12_1280
,
3916 .expected_result
= S_OK
, .decoder_class
= CLSID_CMSH264DecoderMFT
, .converter_class
= CLSID_CColorConvertDMO
,
3919 /* RGB32 -> Any Video, no current output type */
3920 .input_type
= &video_i420_1280
, .output_type
= &video_dummy
, .sink_method
= -1, .source_method
= -1,
3921 .expected_result
= S_OK
,
3922 .flags
= LOADER_NO_CURRENT_OUTPUT
,
3925 /* RGB32 -> Any Video, no current output type, refuse input type */
3926 .input_type
= &video_i420_1280
, .output_type
= &video_dummy
, .sink_method
= -1, .source_method
= -1,
3927 .expected_result
= S_OK
, .converter_class
= CLSID_CColorConvertDMO
,
3928 .flags
= LOADER_NO_CURRENT_OUTPUT
| LOADER_SET_INVALID_INPUT
,
3931 /* RGB32 -> Any Video, no current output type, refuse input type */
3932 .input_type
= &video_i420_1280
, .output_type
= &video_video_processor_rgb32
, .sink_method
= -1, .source_method
= -1,
3933 .expected_result
= S_OK
, .converter_class
= CLSID_CColorConvertDMO
,
3934 .flags
= LOADER_NO_CURRENT_OUTPUT
| LOADER_SET_INVALID_INPUT
| LOADER_SET_MEDIA_TYPES
,
3938 IMFTopologyNode
*src_node
, *sink_node
, *src_node2
, *sink_node2
, *mft_node
;
3939 IMFSampleGrabberSinkCallback
*grabber_callback
= create_test_grabber_callback();
3940 struct test_stream_sink stream_sink
= test_stream_sink
;
3941 IMFMediaType
*media_type
, *input_type
, *output_type
;
3942 IMFTopology
*topology
, *topology2
, *full_topology
;
3943 struct test_handler handler
= test_handler
;
3944 IMFPresentationDescriptor
*pd
;
3945 unsigned int i
, count
, value
;
3946 IMFActivate
*sink_activate
;
3947 MF_TOPOLOGY_TYPE node_type
;
3948 IMFStreamDescriptor
*sd
;
3949 IMFTransform
*transform
;
3950 IMFMediaSource
*source
;
3951 IMFTopoLoader
*loader
;
3952 IUnknown
*node_object
;
3954 TOPOID node_id
, oldtopoid
, newtopoid
;
3960 stream_sink
.handler
= &handler
.IMFMediaTypeHandler_iface
;
3962 hr
= MFStartup(MF_VERSION
, MFSTARTUP_FULL
);
3963 ok(hr
== S_OK
, "Startup failure, hr %#lx.\n", hr
);
3965 hr
= MFCreateTopoLoader(NULL
);
3966 ok(hr
== E_POINTER
, "Unexpected hr %#lx.\n", hr
);
3968 hr
= MFCreateTopoLoader(&loader
);
3969 ok(hr
== S_OK
, "Failed to create topology loader, hr %#lx.\n", hr
);
3971 hr
= MFCreateTopology(&topology
);
3972 ok(hr
== S_OK
, "Failed to create topology, hr %#lx.\n", hr
);
3974 /* Empty topology */
3975 hr
= IMFTopoLoader_Load(loader
, topology
, &full_topology
, NULL
);
3976 todo_wine_if(hr
== S_OK
)
3977 ok(hr
== MF_E_TOPO_UNSUPPORTED
, "Unexpected hr %#lx.\n", hr
);
3978 if (hr
== S_OK
) IMFTopology_Release(full_topology
);
3980 /* Add source node. */
3981 hr
= MFCreateTopologyNode(MF_TOPOLOGY_SOURCESTREAM_NODE
, &src_node
);
3982 ok(hr
== S_OK
, "Failed to create topology node, hr %#lx.\n", hr
);
3984 hr
= MFCreateMediaType(&media_type
);
3985 ok(hr
== S_OK
, "Failed to create media type, hr %#lx.\n", hr
);
3986 hr
= IMFMediaType_SetGUID(media_type
, &MF_MT_MAJOR_TYPE
, &MFMediaType_Audio
);
3987 ok(hr
== S_OK
, "Failed to set attribute, hr %#lx.\n", hr
);
3988 hr
= IMFMediaType_SetGUID(media_type
, &MF_MT_SUBTYPE
, &MFAudioFormat_PCM
);
3989 ok(hr
== S_OK
, "Failed to set attribute, hr %#lx.\n", hr
);
3991 /* When a decoder is involved, windows requires this attribute to be present */
3992 create_descriptors(1, &media_type
, NULL
, &pd
, &sd
);
3993 IMFMediaType_Release(media_type
);
3995 source
= create_test_source(pd
);
3997 hr
= IMFTopologyNode_SetUnknown(src_node
, &MF_TOPONODE_SOURCE
, (IUnknown
*)source
);
3998 ok(hr
== S_OK
, "Failed to set node source, hr %#lx.\n", hr
);
4000 hr
= IMFTopologyNode_SetUnknown(src_node
, &MF_TOPONODE_STREAM_DESCRIPTOR
, (IUnknown
*)sd
);
4001 ok(hr
== S_OK
, "Failed to set node sd, hr %#lx.\n", hr
);
4003 hr
= IMFTopologyNode_SetUnknown(src_node
, &MF_TOPONODE_PRESENTATION_DESCRIPTOR
, (IUnknown
*)pd
);
4004 ok(hr
== S_OK
, "Failed to set node pd, hr %#lx.\n", hr
);
4006 hr
= IMFTopology_AddNode(topology
, src_node
);
4007 ok(hr
== S_OK
, "Failed to add a node, hr %#lx.\n", hr
);
4009 /* Source node only. */
4010 hr
= IMFTopoLoader_Load(loader
, topology
, &full_topology
, NULL
);
4011 ok(hr
== MF_E_TOPO_UNSUPPORTED
, "Unexpected hr %#lx.\n", hr
);
4013 hr
= MFCreateTopologyNode(MF_TOPOLOGY_OUTPUT_NODE
, &sink_node
);
4014 ok(hr
== S_OK
, "Failed to create output node, hr %#lx.\n", hr
);
4016 hr
= MFCreateMediaType(&media_type
);
4017 ok(hr
== S_OK
, "Failed to create media type, hr %#lx.\n", hr
);
4019 hr
= IMFMediaType_SetGUID(media_type
, &MF_MT_MAJOR_TYPE
, &MFMediaType_Audio
);
4020 ok(hr
== S_OK
, "Failed to set attribute, hr %#lx.\n", hr
);
4021 hr
= IMFMediaType_SetGUID(media_type
, &MF_MT_SUBTYPE
, &MFAudioFormat_PCM
);
4022 ok(hr
== S_OK
, "Failed to set attribute, hr %#lx.\n", hr
);
4024 hr
= MFCreateSampleGrabberSinkActivate(media_type
, grabber_callback
, &sink_activate
);
4025 ok(hr
== S_OK
, "Failed to create grabber sink, hr %#lx.\n", hr
);
4027 hr
= IMFTopologyNode_SetObject(sink_node
, (IUnknown
*)sink_activate
);
4028 ok(hr
== S_OK
, "Failed to set object, hr %#lx.\n", hr
);
4030 IMFMediaType_Release(media_type
);
4032 hr
= IMFTopology_AddNode(topology
, sink_node
);
4033 ok(hr
== S_OK
, "Failed to add sink node, hr %#lx.\n", hr
);
4035 hr
= IMFTopoLoader_Load(loader
, topology
, &full_topology
, NULL
);
4036 todo_wine_if(hr
== MF_E_TOPO_SINK_ACTIVATES_UNSUPPORTED
)
4037 ok(hr
== MF_E_TOPO_UNSUPPORTED
, "Unexpected hr %#lx.\n", hr
);
4039 hr
= IMFTopologyNode_ConnectOutput(src_node
, 0, sink_node
, 0);
4040 ok(hr
== S_OK
, "Failed to connect nodes, hr %#lx.\n", hr
);
4042 /* Sink was not resolved. */
4043 hr
= IMFTopoLoader_Load(loader
, topology
, &full_topology
, NULL
);
4044 ok(hr
== MF_E_TOPO_SINK_ACTIVATES_UNSUPPORTED
, "Unexpected hr %#lx.\n", hr
);
4046 hr
= IMFTopologyNode_SetObject(sink_node
, NULL
);
4047 ok(hr
== S_OK
, "Failed to set object, hr %#lx.\n", hr
);
4049 hr
= IMFActivate_ShutdownObject(sink_activate
);
4050 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
4051 ref
= IMFActivate_Release(sink_activate
);
4052 ok(ref
== 0, "Release returned %ld\n", ref
);
4054 hr
= IMFTopologyNode_SetUnknown(src_node
, &MF_TOPONODE_SOURCE
, NULL
);
4055 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
4056 hr
= IMFTopologyNode_SetUnknown(src_node
, &MF_TOPONODE_STREAM_DESCRIPTOR
, NULL
);
4057 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
4058 hr
= IMFTopologyNode_SetUnknown(src_node
, &MF_TOPONODE_PRESENTATION_DESCRIPTOR
, NULL
);
4059 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
4060 ref
= IMFMediaSource_Release(source
);
4061 ok(ref
== 0, "Release returned %ld\n", ref
);
4062 ref
= IMFPresentationDescriptor_Release(pd
);
4063 ok(ref
== 0, "Release returned %ld\n", ref
);
4064 ref
= IMFStreamDescriptor_Release(sd
);
4065 ok(ref
== 0, "Release returned %ld\n", ref
);
4068 hr
= MFCreateMediaType(&input_type
);
4069 ok(hr
== S_OK
, "Failed to create media type, hr %#lx.\n", hr
);
4071 hr
= MFCreateMediaType(&output_type
);
4072 ok(hr
== S_OK
, "Failed to create media type, hr %#lx.\n", hr
);
4074 for (i
= 0; i
< ARRAY_SIZE(loader_tests
); ++i
)
4076 const struct loader_test
*test
= &loader_tests
[i
];
4078 winetest_push_context("%u", i
);
4080 init_media_type(input_type
, *test
->input_type
, -1);
4081 init_media_type(output_type
, *test
->output_type
, -1);
4083 handler
.set_current_count
= 0;
4084 if (test
->flags
& LOADER_NO_CURRENT_OUTPUT
)
4085 handler
.current_type
= NULL
;
4087 IMFMediaType_AddRef((handler
.current_type
= output_type
));
4089 if (test
->flags
& LOADER_SET_INVALID_INPUT
)
4090 handler
.invalid_type
= input_type
;
4092 handler
.invalid_type
= NULL
;
4094 handler
.enum_count
= 0;
4095 if (test
->flags
& LOADER_SET_MEDIA_TYPES
)
4097 handler
.media_types_count
= 1;
4098 handler
.media_types
= &output_type
;
4102 handler
.media_types_count
= 0;
4103 handler
.media_types
= NULL
;
4106 if (test
->flags
& LOADER_ADD_RESAMPLER_MFT
)
4108 hr
= IMFTopology_Clear(topology
);
4109 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
4110 hr
= IMFTopology_AddNode(topology
, src_node
);
4111 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
4112 hr
= IMFTopology_AddNode(topology
, sink_node
);
4113 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
4115 hr
= MFCreateTopologyNode(MF_TOPOLOGY_TRANSFORM_NODE
, &mft_node
);
4116 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
4118 hr
= CoCreateInstance(&CLSID_CResamplerMediaObject
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IMFTransform
, (void **)&transform
);
4119 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
4120 hr
= IMFTopologyNode_SetGUID(mft_node
, &MF_TOPONODE_TRANSFORM_OBJECTID
, &CLSID_CResamplerMediaObject
);
4121 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
4122 hr
= IMFTopologyNode_SetObject(mft_node
, (IUnknown
*)transform
);
4123 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
4124 IMFTransform_Release(transform
);
4126 hr
= IMFTopology_AddNode(topology
, mft_node
);
4127 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
4128 hr
= IMFTopologyNode_ConnectOutput(src_node
, 0, mft_node
, 0);
4129 ok(hr
== S_OK
, "Failed to connect nodes, hr %#lx.\n", hr
);
4130 hr
= IMFTopologyNode_ConnectOutput(mft_node
, 0, sink_node
, 0);
4131 ok(hr
== S_OK
, "Failed to connect nodes, hr %#lx.\n", hr
);
4132 IMFTopologyNode_Release(mft_node
);
4136 hr
= IMFTopology_Clear(topology
);
4137 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
4138 hr
= IMFTopology_AddNode(topology
, src_node
);
4139 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
4140 hr
= IMFTopology_AddNode(topology
, sink_node
);
4141 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
4142 hr
= IMFTopologyNode_ConnectOutput(src_node
, 0, sink_node
, 0);
4143 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
4146 create_descriptors(1, &input_type
, test
->current_input
, &pd
, &sd
);
4148 source
= create_test_source(pd
);
4150 init_source_node(source
, test
->source_method
, src_node
, pd
, sd
);
4151 init_sink_node(&stream_sink
.IMFStreamSink_iface
, test
->sink_method
, sink_node
);
4153 hr
= IMFTopology_GetCount(topology
, &count
);
4154 ok(hr
== S_OK
, "Failed to get attribute count, hr %#lx.\n", hr
);
4155 ok(!count
, "Unexpected count %u.\n", count
);
4157 if (test
->flags
& LOADER_SET_ENUMERATE_SOURCE_TYPES
)
4158 IMFTopology_SetUINT32(topology
, &MF_TOPOLOGY_ENUMERATE_SOURCE_TYPES
, 1);
4159 hr
= IMFTopoLoader_Load(loader
, topology
, &full_topology
, NULL
);
4160 IMFTopology_DeleteItem(topology
, &MF_TOPOLOGY_ENUMERATE_SOURCE_TYPES
);
4162 if (test
->flags
& LOADER_NEEDS_VIDEO_PROCESSOR
&& !has_video_processor
)
4163 ok(hr
== MF_E_INVALIDMEDIATYPE
|| hr
== MF_E_TOPO_CODEC_NOT_FOUND
,
4164 "Unexpected hr %#lx\n", hr
);
4167 todo_wine_if(test
->flags
& LOADER_TODO
)
4168 ok(hr
== test
->expected_result
, "Unexpected hr %#lx\n", hr
);
4169 ok(full_topology
!= topology
, "Unexpected instance.\n");
4172 if (test
->expected_result
!= hr
)
4174 if (hr
!= S_OK
) ref
= 0;
4175 else ref
= IMFTopology_Release(full_topology
);
4176 ok(ref
== 0, "Release returned %ld\n", ref
);
4178 else if (test
->expected_result
== S_OK
)
4180 IMFTopology_GetTopologyID(topology
, &oldtopoid
);
4181 IMFTopology_GetTopologyID(full_topology
, &newtopoid
);
4182 todo_wine
ok(oldtopoid
== newtopoid
, "Expected the same topology id. %llu == %llu\n", oldtopoid
, newtopoid
);
4183 ok(topology
!= full_topology
, "Expected a different object for the resolved topology.\n");
4185 hr
= IMFTopology_GetCount(full_topology
, &count
);
4186 ok(hr
== S_OK
, "Failed to get attribute count, hr %#lx.\n", hr
);
4188 ok(count
== (test
->flags
& LOADER_SET_ENUMERATE_SOURCE_TYPES
? 2 : 1),
4189 "Unexpected count %u.\n", count
);
4192 hr
= IMFTopology_GetUINT32(full_topology
, &MF_TOPOLOGY_RESOLUTION_STATUS
, &value
);
4194 ok(hr
== S_OK
, "Failed to get attribute, hr %#lx.\n", hr
);
4195 ok(value
== MF_TOPOLOGY_RESOLUTION_SUCCEEDED
, "Unexpected value %#x.\n", value
);
4198 if (!IsEqualGUID(&test
->decoder_class
, &GUID_NULL
))
4200 if (!IsEqualGUID(&test
->converter_class
, &GUID_NULL
))
4203 hr
= IMFTopology_GetNodeCount(full_topology
, &node_count
);
4204 ok(hr
== S_OK
, "Failed to get node count, hr %#lx.\n", hr
);
4205 todo_wine_if(IsEqualGUID(&test
->decoder_class
, &CLSID_CMP3DecMediaObject
))
4206 ok(node_count
== count
, "Unexpected node count %u.\n", node_count
);
4208 hr
= IMFTopologyNode_GetTopoNodeID(src_node
, &node_id
);
4209 ok(hr
== S_OK
, "Failed to get source node id, hr %#lx.\n", hr
);
4211 hr
= IMFTopology_GetNodeByID(full_topology
, node_id
, &src_node2
);
4212 ok(hr
== S_OK
, "Failed to get source in resolved topology, hr %#lx.\n", hr
);
4214 hr
= IMFTopologyNode_GetTopoNodeID(sink_node
, &node_id
);
4215 ok(hr
== S_OK
, "Failed to get sink node id, hr %#lx.\n", hr
);
4217 hr
= IMFTopology_GetNodeByID(full_topology
, node_id
, &sink_node2
);
4218 ok(hr
== S_OK
, "Failed to get sink in resolved topology, hr %#lx.\n", hr
);
4220 if (!IsEqualGUID(&test
->decoder_class
, &GUID_NULL
))
4224 hr
= IMFTopologyNode_GetOutput(src_node2
, 0, &mft_node
, &index
);
4225 ok(hr
== S_OK
, "Failed to get decoder in resolved topology, hr %#lx.\n", hr
);
4226 ok(!index
, "Unexpected stream index %lu.\n", index
);
4228 hr
= IMFTopologyNode_GetNodeType(mft_node
, &node_type
);
4229 ok(hr
== S_OK
, "Failed to get transform node type in resolved topology, hr %#lx.\n", hr
);
4230 ok(node_type
== MF_TOPOLOGY_TRANSFORM_NODE
, "Unexpected node type %u.\n", node_type
);
4233 hr
= IMFTopologyNode_GetUINT32(mft_node
, &MF_TOPONODE_DECODER
, &value
);
4234 ok(hr
== S_OK
, "Failed to get attribute, hr %#lx.\n", hr
);
4235 ok(value
== 1, "Unexpected value.\n");
4237 class_id
= GUID_NULL
;
4238 hr
= IMFTopologyNode_GetGUID(mft_node
, &MF_TOPONODE_TRANSFORM_OBJECTID
, &class_id
);
4239 ok(hr
== S_OK
, "Failed to get attribute, hr %#lx.\n", hr
);
4240 ok(IsEqualGUID(&class_id
, &test
->decoder_class
), "got MF_TOPONODE_TRANSFORM_OBJECTID %s.\n", debugstr_guid(&class_id
));
4242 hr
= IMFTopologyNode_GetObject(mft_node
, &node_object
);
4243 ok(hr
== S_OK
, "Failed to get object of transform node, hr %#lx.\n", hr
);
4244 IMFTopologyNode_Release(mft_node
);
4246 hr
= IUnknown_QueryInterface(node_object
, &IID_IMFTransform
, (void **)&transform
);
4247 ok(hr
== S_OK
, "Failed to get IMFTransform from transform node's object, hr %#lx.\n", hr
);
4248 IUnknown_Release(node_object
);
4250 hr
= IMFTransform_GetInputCurrentType(transform
, 0, &media_type
);
4251 ok(hr
== S_OK
, "Failed to get transform input type, hr %#lx.\n", hr
);
4252 hr
= IMFMediaType_Compare(input_type
, (IMFAttributes
*)media_type
, MF_ATTRIBUTES_MATCH_OUR_ITEMS
, &ret
);
4253 ok(hr
== S_OK
, "Failed to compare media types, hr %#lx.\n", hr
);
4254 ok(ret
, "Input type of first transform doesn't match source node type.\n");
4255 IMFMediaType_Release(media_type
);
4257 hr
= IMFTransform_GetOutputCurrentType(transform
, 0, &media_type
);
4258 ok(hr
== S_OK
, "Failed to get transform input type, hr %#lx.\n", hr
);
4259 if (IsEqualGUID(&test
->converter_class
, &GUID_NULL
))
4261 hr
= IMFMediaType_Compare(output_type
, (IMFAttributes
*)media_type
, MF_ATTRIBUTES_MATCH_OUR_ITEMS
, &ret
);
4262 ok(hr
== S_OK
, "Failed to compare media types, hr %#lx.\n", hr
);
4263 ok(ret
, "Output type of first transform doesn't match sink node type.\n");
4265 else if (test
->decoded_type
)
4267 check_media_type(media_type
, *test
->decoded_type
, -1);
4269 IMFMediaType_Release(media_type
);
4271 IMFTransform_Release(transform
);
4274 if (!IsEqualGUID(&test
->converter_class
, &GUID_NULL
))
4278 hr
= IMFTopologyNode_GetInput(sink_node2
, 0, &mft_node
, &index
);
4279 ok(hr
== S_OK
, "Failed to get decoder in resolved topology, hr %#lx.\n", hr
);
4280 ok(!index
, "Unexpected stream index %lu.\n", index
);
4282 hr
= IMFTopologyNode_GetNodeType(mft_node
, &node_type
);
4283 ok(hr
== S_OK
, "Failed to get transform node type in resolved topology, hr %#lx.\n", hr
);
4284 ok(node_type
== MF_TOPOLOGY_TRANSFORM_NODE
, "Unexpected node type %u.\n", node_type
);
4286 class_id
= GUID_NULL
;
4287 hr
= IMFTopologyNode_GetGUID(mft_node
, &MF_TOPONODE_TRANSFORM_OBJECTID
, &class_id
);
4288 ok(hr
== S_OK
, "Failed to get attribute, hr %#lx.\n", hr
);
4289 todo_wine_if(IsEqualGUID(&test
->converter_class
, &CLSID_CColorConvertDMO
))
4290 ok(IsEqualGUID(&class_id
, &test
->converter_class
), "got MF_TOPONODE_TRANSFORM_OBJECTID %s.\n", debugstr_guid(&class_id
));
4292 hr
= IMFTopologyNode_GetObject(mft_node
, &node_object
);
4293 ok(hr
== S_OK
, "Failed to get object of transform node, hr %#lx.\n", hr
);
4294 IMFTopologyNode_Release(mft_node
);
4296 hr
= IUnknown_QueryInterface(node_object
, &IID_IMFTransform
, (void **)&transform
);
4297 ok(hr
== S_OK
, "Failed to get IMFTransform from transform node's object, hr %#lx.\n", hr
);
4298 IUnknown_Release(node_object
);
4300 hr
= IMFTransform_GetInputCurrentType(transform
, 0, &media_type
);
4301 ok(hr
== S_OK
, "Failed to get transform input type, hr %#lx.\n", hr
);
4302 if (IsEqualGUID(&test
->decoder_class
, &GUID_NULL
))
4304 hr
= IMFMediaType_Compare(input_type
, (IMFAttributes
*)media_type
, MF_ATTRIBUTES_MATCH_OUR_ITEMS
, &ret
);
4305 ok(hr
== S_OK
, "Failed to compare media types, hr %#lx.\n", hr
);
4306 ok(ret
, "Input type of last transform doesn't match source node type.\n");
4308 else if (test
->decoded_type
)
4310 check_media_type(media_type
, *test
->decoded_type
, -1);
4312 IMFMediaType_Release(media_type
);
4314 hr
= IMFTransform_GetOutputCurrentType(transform
, 0, &media_type
);
4315 ok(hr
== S_OK
, "Failed to get transform input type, hr %#lx.\n", hr
);
4316 hr
= IMFMediaType_Compare(output_type
, (IMFAttributes
*)media_type
, MF_ATTRIBUTES_MATCH_OUR_ITEMS
, &ret
);
4317 ok(hr
== S_OK
, "Failed to compare media types, hr %#lx.\n", hr
);
4318 ok(ret
, "Output type of last transform doesn't match sink node type.\n");
4319 IMFMediaType_Release(media_type
);
4321 IMFTransform_Release(transform
);
4324 IMFTopologyNode_Release(src_node2
);
4325 IMFTopologyNode_Release(sink_node2
);
4327 hr
= IMFTopology_SetUINT32(full_topology
, &IID_IMFTopology
, 123);
4328 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
4329 hr
= IMFTopoLoader_Load(loader
, full_topology
, &topology2
, NULL
);
4330 ok(hr
== S_OK
, "Failed to resolve topology, hr %#lx.\n", hr
);
4331 ok(full_topology
!= topology2
, "Unexpected instance.\n");
4332 IMFTopology_GetTopologyID(topology2
, &oldtopoid
);
4333 IMFTopology_GetTopologyID(full_topology
, &newtopoid
);
4334 todo_wine
ok(oldtopoid
== newtopoid
, "Expected the same topology id. %llu == %llu\n", oldtopoid
, newtopoid
);
4335 hr
= IMFTopology_GetUINT32(topology2
, &IID_IMFTopology
, &value
);
4336 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
4338 ref
= IMFTopology_Release(topology2
);
4339 ok(ref
== 0, "Release returned %ld\n", ref
);
4340 ref
= IMFTopology_Release(full_topology
);
4341 ok(ref
== 0, "Release returned %ld\n", ref
);
4344 hr
= IMFTopology_GetCount(topology
, &count
);
4345 ok(hr
== S_OK
, "Failed to get attribute count, hr %#lx.\n", hr
);
4346 ok(!count
, "Unexpected count %u.\n", count
);
4348 if (test
->flags
& LOADER_SET_MEDIA_TYPES
)
4349 ok(handler
.enum_count
, "got %lu GetMediaTypeByIndex\n", handler
.enum_count
);
4351 ok(!handler
.enum_count
, "got %lu GetMediaTypeByIndex\n", handler
.enum_count
);
4352 ok(!handler
.set_current_count
, "got %lu SetCurrentMediaType\n", handler
.set_current_count
);
4354 if (handler
.current_type
)
4355 IMFMediaType_Release(handler
.current_type
);
4356 handler
.current_type
= NULL
;
4358 hr
= IMFTopologyNode_SetUnknown(src_node
, &MF_TOPONODE_SOURCE
, NULL
);
4359 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
4360 hr
= IMFTopologyNode_SetUnknown(src_node
, &MF_TOPONODE_STREAM_DESCRIPTOR
, NULL
);
4361 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
4362 hr
= IMFTopologyNode_SetUnknown(src_node
, &MF_TOPONODE_PRESENTATION_DESCRIPTOR
, NULL
);
4363 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
4364 ref
= IMFMediaSource_Release(source
);
4365 ok(ref
== 0, "Release returned %ld\n", ref
);
4366 ref
= IMFPresentationDescriptor_Release(pd
);
4367 ok(ref
== 0, "Release returned %ld\n", ref
);
4368 ref
= IMFStreamDescriptor_Release(sd
);
4369 ok(ref
== 0, "Release returned %ld\n", ref
);
4371 winetest_pop_context();
4374 ref
= IMFTopology_Release(topology
);
4375 ok(ref
== 0, "Release returned %ld\n", ref
);
4376 ref
= IMFTopoLoader_Release(loader
);
4377 ok(ref
== 0, "Release returned %ld\n", ref
);
4378 ref
= IMFTopologyNode_Release(src_node
);
4379 ok(ref
== 0, "Release returned %ld\n", ref
);
4380 ref
= IMFTopologyNode_Release(sink_node
);
4381 ok(ref
== 0, "Release returned %ld\n", ref
);
4383 ref
= IMFMediaType_Release(input_type
);
4384 ok(ref
== 0, "Release returned %ld\n", ref
);
4385 ref
= IMFMediaType_Release(output_type
);
4386 ok(ref
== 0, "Release returned %ld\n", ref
);
4389 ok(hr
== S_OK
, "Shutdown failure, hr %#lx.\n", hr
);
4391 IMFSampleGrabberSinkCallback_Release(grabber_callback
);
4394 static void test_topology_loader_evr(void)
4396 static const media_type_desc media_type_desc
=
4398 ATTR_GUID(MF_MT_MAJOR_TYPE
, MFMediaType_Video
),
4399 ATTR_GUID(MF_MT_SUBTYPE
, MFVideoFormat_RGB32
),
4400 ATTR_RATIO(MF_MT_FRAME_SIZE
, 640, 480),
4401 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT
, TRUE
),
4404 IMFTopologyNode
*node
, *source_node
, *evr_node
;
4405 IMFTopology
*topology
, *full_topology
;
4406 IMFPresentationDescriptor
*pd
;
4407 IMFMediaTypeHandler
*handler
;
4408 unsigned int i
, count
, value
;
4409 IMFStreamSink
*stream_sink
;
4410 IMFMediaType
*media_type
;
4411 IMFStreamDescriptor
*sd
;
4412 IMFActivate
*activate
;
4413 IMFTopoLoader
*loader
;
4421 hr
= CoInitialize(NULL
);
4422 ok(hr
== S_OK
, "Failed to initialize, hr %#lx.\n", hr
);
4424 /* EVR sink node. */
4425 window
= create_window();
4427 hr
= MFCreateVideoRendererActivate(window
, &activate
);
4428 ok(hr
== S_OK
, "Failed to create activate object, hr %#lx.\n", hr
);
4430 hr
= IMFActivate_ActivateObject(activate
, &IID_IMFMediaSink
, (void **)&sink
);
4433 skip("Failed to create an EVR sink, skipping tests.\n");
4434 DestroyWindow(window
);
4435 IMFActivate_Release(activate
);
4439 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
4441 hr
= MFCreateTopoLoader(&loader
);
4442 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
4445 hr
= MFCreateTopologyNode(MF_TOPOLOGY_SOURCESTREAM_NODE
, &source_node
);
4446 ok(hr
== S_OK
, "Failed to create topology node, hr %#lx.\n", hr
);
4448 hr
= MFCreateMediaType(&media_type
);
4449 ok(hr
== S_OK
, "Failed to create media type, hr %#lx.\n", hr
);
4450 init_media_type(media_type
, media_type_desc
, -1);
4452 create_descriptors(1, &media_type
, &media_type_desc
, &pd
, &sd
);
4453 init_source_node(NULL
, -1, source_node
, pd
, sd
);
4454 IMFPresentationDescriptor_Release(pd
);
4455 IMFStreamDescriptor_Release(sd
);
4458 hr
= IMFMediaSink_GetStreamSinkById(sink
, 0, &stream_sink
);
4459 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
4461 hr
= MFCreateTopologyNode(MF_TOPOLOGY_OUTPUT_NODE
, &evr_node
);
4462 ok(hr
== S_OK
, "Failed to create topology node, hr %#lx.\n", hr
);
4464 hr
= IMFTopologyNode_SetObject(evr_node
, (IUnknown
*)stream_sink
);
4465 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
4467 hr
= IMFStreamSink_GetMediaTypeHandler(stream_sink
, &handler
);
4468 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
4469 hr
= IMFMediaTypeHandler_SetCurrentMediaType(handler
, media_type
);
4470 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
4471 IMFMediaTypeHandler_Release(handler
);
4473 IMFStreamSink_Release(stream_sink
);
4475 hr
= MFCreateTopology(&topology
);
4476 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
4478 hr
= IMFTopology_AddNode(topology
, source_node
);
4479 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
4480 hr
= IMFTopology_AddNode(topology
, evr_node
);
4481 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
4482 hr
= IMFTopologyNode_ConnectOutput(source_node
, 0, evr_node
, 0);
4483 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
4485 hr
= IMFTopologyNode_SetUINT32(evr_node
, &MF_TOPONODE_CONNECT_METHOD
, MF_CONNECT_DIRECT
);
4486 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
4488 hr
= IMFTopologyNode_GetCount(evr_node
, &count
);
4489 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
4490 ok(count
== 1, "Unexpected attribute count %u.\n", count
);
4492 hr
= IMFTopoLoader_Load(loader
, topology
, &full_topology
, NULL
);
4493 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
4495 hr
= IMFTopology_GetNodeCount(full_topology
, &node_count
);
4496 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
4497 ok(node_count
== 3, "Unexpected node count %u.\n", node_count
);
4499 for (i
= 0; i
< node_count
; ++i
)
4501 MF_TOPOLOGY_TYPE node_type
;
4503 hr
= IMFTopology_GetNode(full_topology
, i
, &node
);
4504 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
4506 hr
= IMFTopologyNode_GetNodeType(node
, &node_type
);
4507 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
4511 case MF_TOPOLOGY_OUTPUT_NODE
:
4514 hr
= IMFTopologyNode_GetUINT32(node
, &MF_TOPONODE_STREAMID
, &value
);
4515 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
4516 ok(!value
, "Unexpected stream id %u.\n", value
);
4519 case MF_TOPOLOGY_TRANSFORM_NODE
:
4521 IMFAttributes
*attrs
;
4522 IMFTransform
*copier
;
4525 hr
= IMFTopologyNode_GetObject(node
, (IUnknown
**)&obj
);
4526 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
4528 hr
= IUnknown_QueryInterface(obj
, &IID_IMFTransform
, (void **)&copier
);
4529 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
4531 hr
= IMFTransform_GetAttributes(copier
, &attrs
);
4532 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
4535 hr
= IMFAttributes_GetUINT32(attrs
, &MFT_SUPPORT_DYNAMIC_FORMAT_CHANGE
, &value
);
4536 ok(value
== 1, "Unexpected dynamic state support state %u.\n", value
);
4538 IMFAttributes_Release(attrs
);
4539 IMFTransform_Release(copier
);
4540 IUnknown_Release(obj
);
4543 case MF_TOPOLOGY_SOURCESTREAM_NODE
:
4546 hr
= IMFTopologyNode_GetUINT64(node
, &MF_TOPONODE_MEDIASTART
, &value64
);
4547 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
4548 ok(!value64
, "Unexpected value.\n");
4552 ok(0, "Got unexpected node type %u.\n", node_type
);
4556 IMFTopologyNode_Release(node
);
4559 ref
= IMFTopology_Release(full_topology
);
4560 ok(ref
== 0, "Release returned %ld\n", ref
);
4561 ref
= IMFTopoLoader_Release(loader
);
4562 ok(ref
== 0, "Release returned %ld\n", ref
);
4563 ref
= IMFTopology_Release(topology
);
4564 ok(ref
== 0, "Release returned %ld\n", ref
);
4565 ref
= IMFTopologyNode_Release(source_node
);
4566 ok(ref
== 0, "Release returned %ld\n", ref
);
4567 ref
= IMFTopologyNode_Release(evr_node
);
4568 ok(ref
== 0, "Release returned %ld\n", ref
);
4570 hr
= IMFActivate_ShutdownObject(activate
);
4571 ok(hr
== S_OK
, "Failed to shut down, hr %#lx.\n", hr
);
4572 ref
= IMFActivate_Release(activate
);
4573 ok(ref
== 0, "Release returned %ld\n", ref
);
4574 ref
= IMFMediaSink_Release(sink
);
4575 ok(ref
== 0, "Release returned %ld\n", ref
);
4577 ref
= IMFMediaType_Release(media_type
);
4578 ok(ref
== 0, "Release returned %ld\n", ref
);
4580 DestroyWindow(window
);
4585 static HRESULT WINAPI
testshutdown_QueryInterface(IMFShutdown
*iface
, REFIID riid
, void **obj
)
4587 if (IsEqualIID(riid
, &IID_IMFShutdown
) ||
4588 IsEqualIID(riid
, &IID_IUnknown
))
4591 IMFShutdown_AddRef(iface
);
4596 return E_NOINTERFACE
;
4599 static ULONG WINAPI
testshutdown_AddRef(IMFShutdown
*iface
)
4604 static ULONG WINAPI
testshutdown_Release(IMFShutdown
*iface
)
4609 static HRESULT WINAPI
testshutdown_Shutdown(IMFShutdown
*iface
)
4614 static HRESULT WINAPI
testshutdown_GetShutdownStatus(IMFShutdown
*iface
, MFSHUTDOWN_STATUS
*status
)
4616 ok(0, "Unexpected call.\n");
4620 static const IMFShutdownVtbl testshutdownvtbl
=
4622 testshutdown_QueryInterface
,
4623 testshutdown_AddRef
,
4624 testshutdown_Release
,
4625 testshutdown_Shutdown
,
4626 testshutdown_GetShutdownStatus
,
4629 static void test_MFShutdownObject(void)
4631 IMFShutdown testshutdown
= { &testshutdownvtbl
};
4632 IUnknown testshutdown2
= { &testservicevtbl
};
4635 hr
= MFShutdownObject(NULL
);
4636 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
4638 hr
= MFShutdownObject((IUnknown
*)&testshutdown
);
4639 ok(hr
== S_OK
, "Failed to shut down, hr %#lx.\n", hr
);
4641 hr
= MFShutdownObject(&testshutdown2
);
4642 ok(hr
== S_OK
, "Failed to shut down, hr %#lx.\n", hr
);
4652 static HRESULT WINAPI
test_clock_sink_QueryInterface(IMFClockStateSink
*iface
, REFIID riid
, void **obj
)
4654 if (IsEqualIID(riid
, &IID_IMFClockStateSink
) ||
4655 IsEqualIID(riid
, &IID_IUnknown
))
4658 IMFClockStateSink_AddRef(iface
);
4663 return E_NOINTERFACE
;
4666 static ULONG WINAPI
test_clock_sink_AddRef(IMFClockStateSink
*iface
)
4671 static ULONG WINAPI
test_clock_sink_Release(IMFClockStateSink
*iface
)
4676 static HRESULT WINAPI
test_clock_sink_OnClockStart(IMFClockStateSink
*iface
, MFTIME system_time
, LONGLONG offset
)
4681 static HRESULT WINAPI
test_clock_sink_OnClockStop(IMFClockStateSink
*iface
, MFTIME system_time
)
4686 static HRESULT WINAPI
test_clock_sink_OnClockPause(IMFClockStateSink
*iface
, MFTIME system_time
)
4691 static HRESULT WINAPI
test_clock_sink_OnClockRestart(IMFClockStateSink
*iface
, MFTIME system_time
)
4696 static HRESULT WINAPI
test_clock_sink_OnClockSetRate(IMFClockStateSink
*iface
, MFTIME system_time
, float rate
)
4701 static const IMFClockStateSinkVtbl test_clock_sink_vtbl
=
4703 test_clock_sink_QueryInterface
,
4704 test_clock_sink_AddRef
,
4705 test_clock_sink_Release
,
4706 test_clock_sink_OnClockStart
,
4707 test_clock_sink_OnClockStop
,
4708 test_clock_sink_OnClockPause
,
4709 test_clock_sink_OnClockRestart
,
4710 test_clock_sink_OnClockSetRate
,
4713 static void test_presentation_clock(void)
4715 static const struct clock_state_test
4717 enum clock_action action
;
4718 MFCLOCK_STATE clock_state
;
4719 MFCLOCK_STATE source_state
;
4722 clock_state_change
[] =
4724 { CLOCK_STOP
, MFCLOCK_STATE_STOPPED
, MFCLOCK_STATE_INVALID
},
4725 { CLOCK_PAUSE
, MFCLOCK_STATE_STOPPED
, MFCLOCK_STATE_INVALID
, MF_E_INVALIDREQUEST
},
4726 { CLOCK_STOP
, MFCLOCK_STATE_STOPPED
, MFCLOCK_STATE_INVALID
, MF_E_CLOCK_STATE_ALREADY_SET
},
4727 { CLOCK_START
, MFCLOCK_STATE_RUNNING
, MFCLOCK_STATE_RUNNING
},
4728 { CLOCK_START
, MFCLOCK_STATE_RUNNING
, MFCLOCK_STATE_RUNNING
},
4729 { CLOCK_PAUSE
, MFCLOCK_STATE_PAUSED
, MFCLOCK_STATE_PAUSED
},
4730 { CLOCK_PAUSE
, MFCLOCK_STATE_PAUSED
, MFCLOCK_STATE_PAUSED
, MF_E_CLOCK_STATE_ALREADY_SET
},
4731 { CLOCK_STOP
, MFCLOCK_STATE_STOPPED
, MFCLOCK_STATE_STOPPED
},
4732 { CLOCK_START
, MFCLOCK_STATE_RUNNING
, MFCLOCK_STATE_RUNNING
},
4733 { CLOCK_STOP
, MFCLOCK_STATE_STOPPED
, MFCLOCK_STATE_STOPPED
},
4734 { CLOCK_STOP
, MFCLOCK_STATE_STOPPED
, MFCLOCK_STATE_STOPPED
, MF_E_CLOCK_STATE_ALREADY_SET
},
4735 { CLOCK_PAUSE
, MFCLOCK_STATE_STOPPED
, MFCLOCK_STATE_STOPPED
, MF_E_INVALIDREQUEST
},
4736 { CLOCK_START
, MFCLOCK_STATE_RUNNING
, MFCLOCK_STATE_RUNNING
},
4737 { CLOCK_PAUSE
, MFCLOCK_STATE_PAUSED
, MFCLOCK_STATE_PAUSED
},
4738 { CLOCK_START
, MFCLOCK_STATE_RUNNING
, MFCLOCK_STATE_RUNNING
},
4740 IMFClockStateSink test_sink
= { &test_clock_sink_vtbl
};
4741 IMFPresentationTimeSource
*time_source
;
4742 struct test_callback
*timer_callback
;
4743 MFCLOCK_PROPERTIES props
, props2
;
4744 IMFRateControl
*rate_control
;
4745 IMFPresentationClock
*clock
;
4746 IMFAsyncCallback
*callback
;
4747 IUnknown
*timer_cancel_key
;
4748 MFSHUTDOWN_STATUS status
;
4749 IMFShutdown
*shutdown
;
4750 MFTIME systime
, time
;
4751 LONGLONG clock_time
;
4752 MFCLOCK_STATE state
;
4761 hr
= MFStartup(MF_VERSION
, MFSTARTUP_FULL
);
4762 ok(hr
== S_OK
, "Failed to start up, hr %#lx.\n", hr
);
4764 hr
= MFCreatePresentationClock(&clock
);
4765 ok(hr
== S_OK
, "Failed to create presentation clock, hr %#lx.\n", hr
);
4767 check_interface(clock
, &IID_IMFTimer
, TRUE
);
4768 check_interface(clock
, &IID_IMFRateControl
, TRUE
);
4769 check_interface(clock
, &IID_IMFPresentationClock
, TRUE
);
4770 check_interface(clock
, &IID_IMFShutdown
, TRUE
);
4771 check_interface(clock
, &IID_IMFClock
, TRUE
);
4773 hr
= IMFPresentationClock_QueryInterface(clock
, &IID_IMFRateControl
, (void **)&rate_control
);
4774 ok(hr
== S_OK
, "Failed to get rate control interface, hr %#lx.\n", hr
);
4776 hr
= IMFPresentationClock_GetTimeSource(clock
, &time_source
);
4777 ok(hr
== MF_E_CLOCK_NO_TIME_SOURCE
, "Unexpected hr %#lx.\n", hr
);
4779 hr
= IMFPresentationClock_GetTimeSource(clock
, NULL
);
4780 ok(hr
== E_INVALIDARG
, "Unexpected hr %#lx.\n", hr
);
4782 hr
= IMFPresentationClock_GetClockCharacteristics(clock
, &value
);
4783 ok(hr
== MF_E_CLOCK_NO_TIME_SOURCE
, "Unexpected hr %#lx.\n", hr
);
4785 hr
= IMFPresentationClock_GetClockCharacteristics(clock
, NULL
);
4786 ok(hr
== MF_E_CLOCK_NO_TIME_SOURCE
, "Unexpected hr %#lx.\n", hr
);
4788 hr
= IMFPresentationClock_GetTime(clock
, &time
);
4789 ok(hr
== MF_E_CLOCK_NO_TIME_SOURCE
, "Unexpected hr %#lx.\n", hr
);
4791 hr
= IMFPresentationClock_GetTime(clock
, NULL
);
4792 ok(hr
== E_POINTER
, "Unexpected hr %#lx.\n", hr
);
4795 hr
= IMFPresentationClock_GetContinuityKey(clock
, &value
);
4796 ok(hr
== S_OK
, "Failed to get continuity key, hr %#lx.\n", hr
);
4797 ok(value
== 0, "Unexpected value %lu.\n", value
);
4799 hr
= IMFPresentationClock_GetProperties(clock
, &props
);
4800 ok(hr
== MF_E_CLOCK_NO_TIME_SOURCE
, "Unexpected hr %#lx.\n", hr
);
4802 hr
= IMFPresentationClock_GetState(clock
, 0, &state
);
4803 ok(hr
== S_OK
, "Failed to get state, hr %#lx.\n", hr
);
4804 ok(state
== MFCLOCK_STATE_INVALID
, "Unexpected state %d.\n", state
);
4806 hr
= IMFPresentationClock_GetCorrelatedTime(clock
, 0, &clock_time
, &systime
);
4807 ok(hr
== MF_E_CLOCK_NO_TIME_SOURCE
, "Unexpected hr %#lx.\n", hr
);
4809 hr
= IMFPresentationClock_GetCorrelatedTime(clock
, 0, NULL
, &systime
);
4810 ok(hr
== MF_E_CLOCK_NO_TIME_SOURCE
, "Unexpected hr %#lx.\n", hr
);
4812 hr
= IMFPresentationClock_GetCorrelatedTime(clock
, 0, &time
, NULL
);
4813 ok(hr
== MF_E_CLOCK_NO_TIME_SOURCE
, "Unexpected hr %#lx.\n", hr
);
4816 hr
= IMFPresentationClock_AddClockStateSink(clock
, NULL
);
4817 ok(hr
== E_INVALIDARG
, "Unexpected hr %#lx.\n", hr
);
4819 hr
= IMFPresentationClock_AddClockStateSink(clock
, &test_sink
);
4820 ok(hr
== S_OK
, "Failed to add a sink, hr %#lx.\n", hr
);
4822 hr
= IMFPresentationClock_AddClockStateSink(clock
, &test_sink
);
4823 ok(hr
== E_INVALIDARG
, "Unexpected hr %#lx.\n", hr
);
4825 hr
= IMFPresentationClock_RemoveClockStateSink(clock
, NULL
);
4826 ok(hr
== E_INVALIDARG
, "Unexpected hr %#lx.\n", hr
);
4828 hr
= IMFPresentationClock_RemoveClockStateSink(clock
, &test_sink
);
4829 ok(hr
== S_OK
, "Failed to remove sink, hr %#lx.\n", hr
);
4831 hr
= IMFPresentationClock_RemoveClockStateSink(clock
, &test_sink
);
4832 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
4834 /* State change commands, time source is not set yet. */
4835 hr
= IMFPresentationClock_Start(clock
, 0);
4836 ok(hr
== MF_E_CLOCK_NO_TIME_SOURCE
, "Unexpected hr %#lx.\n", hr
);
4838 hr
= IMFPresentationClock_Pause(clock
);
4839 ok(hr
== MF_E_CLOCK_NO_TIME_SOURCE
, "Unexpected hr %#lx.\n", hr
);
4841 hr
= IMFPresentationClock_Stop(clock
);
4842 ok(hr
== MF_E_CLOCK_NO_TIME_SOURCE
, "Unexpected hr %#lx.\n", hr
);
4844 hr
= IMFRateControl_SetRate(rate_control
, FALSE
, 0.0f
);
4845 ok(hr
== MF_E_CLOCK_NO_TIME_SOURCE
, "Unexpected hr %#lx.\n", hr
);
4847 /* Set default time source. */
4848 hr
= MFCreateSystemTimeSource(&time_source
);
4849 ok(hr
== S_OK
, "Failed to create time source, hr %#lx.\n", hr
);
4851 hr
= IMFPresentationTimeSource_GetClockCharacteristics(time_source
, &value
);
4852 ok(hr
== S_OK
, "Failed to get time source flags, hr %#lx.\n", hr
);
4853 ok(value
== (MFCLOCK_CHARACTERISTICS_FLAG_FREQUENCY_10MHZ
| MFCLOCK_CHARACTERISTICS_FLAG_IS_SYSTEM_CLOCK
),
4854 "Unexpected clock flags %#lx.\n", value
);
4856 hr
= IMFPresentationClock_SetTimeSource(clock
, time_source
);
4857 ok(hr
== S_OK
, "Failed to set time source, hr %#lx.\n", hr
);
4859 hr
= IMFPresentationTimeSource_GetProperties(time_source
, &props2
);
4860 ok(hr
== S_OK
, "Failed to get time source properties, hr %#lx.\n", hr
);
4862 hr
= IMFPresentationClock_GetClockCharacteristics(clock
, &value
);
4863 ok(hr
== S_OK
, "Failed to get clock flags, hr %#lx.\n", hr
);
4864 ok(value
== (MFCLOCK_CHARACTERISTICS_FLAG_FREQUENCY_10MHZ
| MFCLOCK_CHARACTERISTICS_FLAG_IS_SYSTEM_CLOCK
),
4865 "Unexpected clock flags %#lx.\n", value
);
4867 hr
= IMFPresentationClock_GetProperties(clock
, &props
);
4868 ok(hr
== S_OK
, "Failed to get clock properties, hr %#lx.\n", hr
);
4869 ok(!memcmp(&props
, &props2
, sizeof(props
)), "Unexpected clock properties.\n");
4871 /* Changing rate at initial state. */
4872 hr
= IMFPresentationClock_GetState(clock
, 0, &state
);
4873 ok(hr
== S_OK
, "Failed to get clock state, hr %#lx.\n", hr
);
4874 ok(state
== MFCLOCK_STATE_INVALID
, "Unexpected state %d.\n", state
);
4876 hr
= IMFRateControl_SetRate(rate_control
, FALSE
, 0.0f
);
4877 ok(hr
== S_OK
, "Failed to set clock rate, hr %#lx.\n", hr
);
4878 hr
= IMFRateControl_GetRate(rate_control
, &thin
, &rate
);
4879 ok(hr
== S_OK
, "Failed to get clock rate, hr %#lx.\n", hr
);
4880 ok(rate
== 0.0f
, "Unexpected rate.\n");
4881 hr
= IMFRateControl_SetRate(rate_control
, FALSE
, 1.0f
);
4882 ok(hr
== S_OK
, "Failed to set clock rate, hr %#lx.\n", hr
);
4884 /* State changes. */
4885 for (i
= 0; i
< ARRAY_SIZE(clock_state_change
); ++i
)
4887 switch (clock_state_change
[i
].action
)
4890 hr
= IMFPresentationClock_Stop(clock
);
4893 hr
= IMFPresentationClock_Pause(clock
);
4896 hr
= IMFPresentationClock_Start(clock
, 0);
4901 ok(hr
== clock_state_change
[i
].hr
, "%u: unexpected hr %#lx.\n", i
, hr
);
4903 hr
= IMFPresentationTimeSource_GetState(time_source
, 0, &state
);
4904 ok(hr
== S_OK
, "%u: failed to get state, hr %#lx.\n", i
, hr
);
4905 ok(state
== clock_state_change
[i
].source_state
, "%u: unexpected state %d.\n", i
, state
);
4907 hr
= IMFPresentationClock_GetState(clock
, 0, &state
);
4908 ok(hr
== S_OK
, "%u: failed to get state, hr %#lx.\n", i
, hr
);
4909 ok(state
== clock_state_change
[i
].clock_state
, "%u: unexpected state %d.\n", i
, state
);
4912 /* Clock time stamps. */
4913 hr
= IMFPresentationClock_Start(clock
, 10);
4914 ok(hr
== S_OK
, "Failed to start presentation clock, hr %#lx.\n", hr
);
4916 hr
= IMFPresentationClock_Pause(clock
);
4917 ok(hr
== S_OK
, "Failed to pause presentation clock, hr %#lx.\n", hr
);
4919 hr
= IMFPresentationClock_GetTime(clock
, &time
);
4920 ok(hr
== S_OK
, "Failed to get clock time, hr %#lx.\n", hr
);
4922 hr
= IMFPresentationTimeSource_GetCorrelatedTime(time_source
, 0, &clock_time
, &systime
);
4923 ok(hr
== S_OK
, "Failed to get time source time, hr %#lx.\n", hr
);
4924 ok(time
== clock_time
, "Unexpected clock time.\n");
4926 hr
= IMFPresentationClock_GetCorrelatedTime(clock
, 0, &time
, &systime
);
4927 ok(hr
== S_OK
, "Failed to get clock time, hr %#lx.\n", hr
);
4928 ok(time
== clock_time
, "Unexpected clock time.\n");
4930 IMFPresentationTimeSource_Release(time_source
);
4932 hr
= IMFRateControl_GetRate(rate_control
, NULL
, &rate
);
4933 ok(hr
== S_OK
, "Failed to get clock rate, hr %#lx.\n", hr
);
4935 hr
= IMFRateControl_GetRate(rate_control
, &thin
, NULL
);
4936 ok(hr
== E_INVALIDARG
, "Unexpected hr %#lx.\n", hr
);
4938 hr
= IMFRateControl_GetRate(rate_control
, &thin
, &rate
);
4939 ok(hr
== S_OK
, "Failed to get clock rate, hr %#lx.\n", hr
);
4940 ok(rate
== 1.0f
, "Unexpected rate.\n");
4941 ok(!thin
, "Unexpected thinning.\n");
4943 hr
= IMFPresentationClock_GetState(clock
, 0, &state
);
4944 ok(hr
== S_OK
, "Failed to get clock state, hr %#lx.\n", hr
);
4945 ok(state
== MFCLOCK_STATE_PAUSED
, "Unexpected state %d.\n", state
);
4947 hr
= IMFPresentationClock_Start(clock
, 0);
4948 ok(hr
== S_OK
, "Failed to stop, hr %#lx.\n", hr
);
4950 hr
= IMFRateControl_SetRate(rate_control
, FALSE
, 0.0f
);
4951 ok(hr
== S_OK
, "Failed to set clock rate, hr %#lx.\n", hr
);
4952 hr
= IMFRateControl_GetRate(rate_control
, &thin
, &rate
);
4953 ok(hr
== S_OK
, "Failed to get clock rate, hr %#lx.\n", hr
);
4954 ok(rate
== 0.0f
, "Unexpected rate.\n");
4955 hr
= IMFRateControl_SetRate(rate_control
, FALSE
, 1.0f
);
4956 ok(hr
== S_OK
, "Failed to set clock rate, hr %#lx.\n", hr
);
4957 hr
= IMFRateControl_SetRate(rate_control
, FALSE
, 0.0f
);
4958 ok(hr
== S_OK
, "Failed to set clock rate, hr %#lx.\n", hr
);
4959 hr
= IMFRateControl_SetRate(rate_control
, FALSE
, 0.5f
);
4960 ok(hr
== S_OK
, "Failed to set clock rate, hr %#lx.\n", hr
);
4961 hr
= IMFRateControl_SetRate(rate_control
, TRUE
, -1.0f
);
4962 ok(hr
== MF_E_THINNING_UNSUPPORTED
, "Unexpected hr %#lx.\n", hr
);
4963 hr
= IMFRateControl_SetRate(rate_control
, TRUE
, 0.0f
);
4964 ok(hr
== MF_E_THINNING_UNSUPPORTED
, "Unexpected hr %#lx.\n", hr
);
4965 hr
= IMFRateControl_SetRate(rate_control
, TRUE
, 1.0f
);
4966 ok(hr
== MF_E_THINNING_UNSUPPORTED
, "Unexpected hr %#lx.\n", hr
);
4968 hr
= IMFPresentationClock_GetState(clock
, 0, &state
);
4969 ok(hr
== S_OK
, "Failed to get clock state, hr %#lx.\n", hr
);
4970 ok(state
== MFCLOCK_STATE_RUNNING
, "Unexpected state %d.\n", state
);
4972 hr
= IMFRateControl_GetRate(rate_control
, &thin
, &rate
);
4973 ok(hr
== S_OK
, "Failed to get clock rate, hr %#lx.\n", hr
);
4974 ok(rate
== 0.5f
, "Unexpected rate.\n");
4975 ok(!thin
, "Unexpected thinning.\n");
4977 IMFRateControl_Release(rate_control
);
4980 hr
= IMFPresentationClock_QueryInterface(clock
, &IID_IMFTimer
, (void **)&timer
);
4981 ok(hr
== S_OK
, "got hr %#lx.\n", hr
);
4983 hr
= IMFPresentationClock_Start(clock
, 200000);
4984 ok(hr
== S_OK
, "got hr %#lx.\n", hr
);
4986 hr
= IMFPresentationClock_GetCorrelatedTime(clock
, 0, &time
, &systime
);
4987 ok(hr
== S_OK
, "got hr %#lx.\n", hr
);
4989 callback
= create_test_callback(FALSE
);
4990 timer_callback
= impl_from_IMFAsyncCallback(callback
);
4991 hr
= IMFTimer_SetTimer(timer
, 0, 100000, callback
, NULL
, &timer_cancel_key
);
4992 ok(hr
== S_OK
, "got hr %#lx.\n", hr
);
4994 t1
= GetTickCount();
4995 ok(WaitForSingleObject(timer_callback
->event
, 4000) == WAIT_OBJECT_0
, "WaitForSingleObject failed.\n");
4996 t2
= GetTickCount();
4998 ok(t2
- t1
< 200, "unexpected time difference %lu.\n", t2
- t1
);
5000 IUnknown_Release(timer_cancel_key
);
5001 IMFTimer_Release(timer
);
5002 IMFAsyncCallback_Release(callback
);
5004 hr
= IMFPresentationClock_QueryInterface(clock
, &IID_IMFShutdown
, (void **)&shutdown
);
5005 ok(hr
== S_OK
, "Failed to get shutdown interface, hr %#lx.\n", hr
);
5007 /* Shutdown behavior. */
5008 hr
= IMFShutdown_GetShutdownStatus(shutdown
, NULL
);
5009 ok(hr
== E_INVALIDARG
, "Unexpected hr %#lx.\n", hr
);
5011 hr
= IMFShutdown_GetShutdownStatus(shutdown
, &status
);
5012 ok(hr
== MF_E_INVALIDREQUEST
, "Unexpected hr %#lx.\n", hr
);
5014 hr
= IMFShutdown_Shutdown(shutdown
);
5015 ok(hr
== S_OK
, "Failed to shut down, hr %#lx.\n", hr
);
5018 hr
= IMFPresentationClock_GetTimeSource(clock
, &time_source
);
5019 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
5020 ok(!!time_source
, "Unexpected instance %p.\n", time_source
);
5021 IMFPresentationTimeSource_Release(time_source
);
5023 hr
= IMFPresentationClock_GetTime(clock
, &time
);
5024 ok(hr
== S_OK
, "Failed to get time, hr %#lx.\n", hr
);
5026 hr
= IMFShutdown_GetShutdownStatus(shutdown
, &status
);
5027 ok(hr
== S_OK
, "Failed to get status, hr %#lx.\n", hr
);
5028 ok(status
== MFSHUTDOWN_COMPLETED
, "Unexpected status.\n");
5030 hr
= IMFPresentationClock_Start(clock
, 0);
5031 ok(hr
== S_OK
, "Failed to start the clock, hr %#lx.\n", hr
);
5033 hr
= IMFShutdown_GetShutdownStatus(shutdown
, &status
);
5034 ok(hr
== S_OK
, "Failed to get status, hr %#lx.\n", hr
);
5035 ok(status
== MFSHUTDOWN_COMPLETED
, "Unexpected status.\n");
5037 hr
= IMFShutdown_Shutdown(shutdown
);
5038 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
5040 IMFShutdown_Release(shutdown
);
5042 IMFPresentationClock_Release(clock
);
5045 ok(hr
== S_OK
, "Failed to shut down, hr %#lx.\n", hr
);
5048 static void test_sample_grabber(void)
5050 IMFSampleGrabberSinkCallback
*grabber_callback
= create_test_grabber_callback();
5051 IMFMediaType
*media_type
, *media_type2
, *media_type3
;
5052 IMFMediaTypeHandler
*handler
, *handler2
;
5053 IMFPresentationTimeSource
*time_source
;
5054 IMFPresentationClock
*clock
, *clock2
;
5055 IMFStreamSink
*stream
, *stream2
;
5056 IMFRateSupport
*rate_support
;
5057 IMFMediaEventGenerator
*eg
;
5058 IMFMediaSink
*sink
, *sink2
;
5059 DWORD flags
, count
, id
;
5060 IMFActivate
*activate
;
5061 IMFMediaEvent
*event
;
5068 hr
= MFStartup(MF_VERSION
, MFSTARTUP_FULL
);
5069 ok(hr
== S_OK
, "Failed to start up, hr %#lx.\n", hr
);
5071 hr
= MFCreateMediaType(&media_type
);
5072 ok(hr
== S_OK
, "Failed to create media type, hr %#lx.\n", hr
);
5074 hr
= MFCreateSampleGrabberSinkActivate(NULL
, NULL
, &activate
);
5075 ok(hr
== E_POINTER
, "Unexpected hr %#lx.\n", hr
);
5077 hr
= MFCreateSampleGrabberSinkActivate(NULL
, grabber_callback
, &activate
);
5078 ok(hr
== E_POINTER
, "Unexpected hr %#lx.\n", hr
);
5080 hr
= IMFMediaType_SetGUID(media_type
, &MF_MT_MAJOR_TYPE
, &MFMediaType_Audio
);
5081 ok(hr
== S_OK
, "Failed to set attribute, hr %#lx.\n", hr
);
5082 hr
= IMFMediaType_SetGUID(media_type
, &MF_MT_SUBTYPE
, &MFAudioFormat_PCM
);
5083 ok(hr
== S_OK
, "Failed to set attribute, hr %#lx.\n", hr
);
5085 EXPECT_REF(media_type
, 1);
5086 hr
= MFCreateSampleGrabberSinkActivate(media_type
, grabber_callback
, &activate
);
5087 ok(hr
== S_OK
, "Failed to create grabber activate, hr %#lx.\n", hr
);
5088 EXPECT_REF(media_type
, 2);
5090 hr
= IMFActivate_GetCount(activate
, &attr_count
);
5091 ok(hr
== S_OK
, "Failed to get attribute count, hr %#lx.\n", hr
);
5092 ok(!attr_count
, "Unexpected count %u.\n", attr_count
);
5094 hr
= IMFActivate_ActivateObject(activate
, &IID_IMFMediaSink
, (void **)&sink
);
5095 ok(hr
== S_OK
, "Failed to activate object, hr %#lx.\n", hr
);
5097 check_interface(sink
, &IID_IMFClockStateSink
, TRUE
);
5098 check_interface(sink
, &IID_IMFMediaEventGenerator
, TRUE
);
5099 check_interface(sink
, &IID_IMFGetService
, TRUE
);
5100 check_interface(sink
, &IID_IMFRateSupport
, TRUE
);
5101 check_service_interface(sink
, &MF_RATE_CONTROL_SERVICE
, &IID_IMFRateSupport
, TRUE
);
5103 if (SUCCEEDED(MFGetService((IUnknown
*)sink
, &MF_RATE_CONTROL_SERVICE
, &IID_IMFRateSupport
, (void **)&rate_support
)))
5105 hr
= IMFRateSupport_GetFastestRate(rate_support
, MFRATE_FORWARD
, FALSE
, &rate
);
5106 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
5107 ok(rate
== FLT_MAX
, "Unexpected rate %f.\n", rate
);
5109 hr
= IMFRateSupport_GetFastestRate(rate_support
, MFRATE_FORWARD
, TRUE
, &rate
);
5110 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
5111 ok(rate
== FLT_MAX
, "Unexpected rate %f.\n", rate
);
5113 hr
= IMFRateSupport_GetFastestRate(rate_support
, MFRATE_REVERSE
, FALSE
, &rate
);
5114 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
5115 ok(rate
== -FLT_MAX
, "Unexpected rate %f.\n", rate
);
5117 hr
= IMFRateSupport_GetFastestRate(rate_support
, MFRATE_REVERSE
, TRUE
, &rate
);
5118 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
5119 ok(rate
== -FLT_MAX
, "Unexpected rate %f.\n", rate
);
5121 hr
= IMFRateSupport_GetSlowestRate(rate_support
, MFRATE_FORWARD
, FALSE
, &rate
);
5122 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
5123 ok(rate
== 0.0f
, "Unexpected rate %f.\n", rate
);
5125 hr
= IMFRateSupport_GetSlowestRate(rate_support
, MFRATE_FORWARD
, TRUE
, &rate
);
5126 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
5127 ok(rate
== 0.0f
, "Unexpected rate %f.\n", rate
);
5129 hr
= IMFRateSupport_GetSlowestRate(rate_support
, MFRATE_REVERSE
, FALSE
, &rate
);
5130 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
5131 ok(rate
== 0.0f
, "Unexpected rate %f.\n", rate
);
5133 hr
= IMFRateSupport_GetSlowestRate(rate_support
, MFRATE_REVERSE
, TRUE
, &rate
);
5134 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
5135 ok(rate
== 0.0f
, "Unexpected rate %f.\n", rate
);
5137 hr
= IMFRateSupport_IsRateSupported(rate_support
, TRUE
, 1.0f
, &rate
);
5138 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
5139 ok(rate
== 1.0f
, "Unexpected rate %f.\n", rate
);
5141 IMFRateSupport_Release(rate_support
);
5144 hr
= IMFMediaSink_GetCharacteristics(sink
, &flags
);
5145 ok(hr
== S_OK
, "Failed to get sink flags, hr %#lx.\n", hr
);
5146 ok(flags
& MEDIASINK_FIXED_STREAMS
, "Unexpected flags %#lx.\n", flags
);
5148 hr
= IMFMediaSink_GetStreamSinkCount(sink
, &count
);
5149 ok(hr
== S_OK
, "Failed to get stream count, hr %#lx.\n", hr
);
5150 ok(count
== 1, "Unexpected stream count %lu.\n", count
);
5152 hr
= IMFMediaSink_GetStreamSinkByIndex(sink
, 0, &stream
);
5153 ok(hr
== S_OK
, "Failed to get sink stream, hr %#lx.\n", hr
);
5155 check_interface(stream
, &IID_IMFMediaEventGenerator
, TRUE
);
5156 check_interface(stream
, &IID_IMFMediaTypeHandler
, TRUE
);
5158 hr
= IMFStreamSink_GetIdentifier(stream
, &id
);
5159 ok(hr
== S_OK
, "Failed to get stream id, hr %#lx.\n", hr
);
5160 ok(id
== 0, "Unexpected id %#lx.\n", id
);
5162 hr
= IMFStreamSink_GetMediaSink(stream
, &sink2
);
5163 ok(hr
== S_OK
, "Failed to get media sink, hr %lx.\n", hr
);
5164 ok(sink2
== sink
, "Unexpected sink.\n");
5165 IMFMediaSink_Release(sink2
);
5167 hr
= IMFMediaSink_GetStreamSinkByIndex(sink
, 1, &stream2
);
5168 ok(hr
== MF_E_INVALIDINDEX
, "Unexpected hr %#lx.\n", hr
);
5170 hr
= IMFMediaSink_GetStreamSinkById(sink
, 1, &stream2
);
5171 ok(hr
== MF_E_INVALIDSTREAMNUMBER
, "Unexpected hr %#lx.\n", hr
);
5173 hr
= IMFMediaSink_AddStreamSink(sink
, 1, NULL
, &stream2
);
5174 ok(hr
== MF_E_STREAMSINKS_FIXED
, "Unexpected hr %#lx.\n", hr
);
5176 hr
= IMFMediaSink_RemoveStreamSink(sink
, 0);
5177 ok(hr
== MF_E_STREAMSINKS_FIXED
, "Unexpected hr %#lx.\n", hr
);
5179 hr
= IMFMediaSink_RemoveStreamSink(sink
, 1);
5180 ok(hr
== MF_E_STREAMSINKS_FIXED
, "Unexpected hr %#lx.\n", hr
);
5182 check_interface(sink
, &IID_IMFClockStateSink
, TRUE
);
5184 /* Event generator. */
5185 hr
= IMFMediaSink_QueryInterface(sink
, &IID_IMFMediaEventGenerator
, (void **)&eg
);
5186 ok(hr
== S_OK
, "Failed to get interface, hr %#lx.\n", hr
);
5188 hr
= IMFMediaEventGenerator_GetEvent(eg
, MF_EVENT_FLAG_NO_WAIT
, &event
);
5189 ok(hr
== MF_E_NO_EVENTS_AVAILABLE
, "Unexpected hr %#lx.\n", hr
);
5191 check_interface(sink
, &IID_IMFPresentationTimeSource
, FALSE
);
5193 hr
= IMFStreamSink_QueryInterface(stream
, &IID_IMFMediaTypeHandler
, (void **)&handler2
);
5194 ok(hr
== S_OK
, "Failed to get handler interface, hr %#lx.\n", hr
);
5196 hr
= IMFStreamSink_GetMediaTypeHandler(stream
, &handler
);
5197 ok(hr
== S_OK
, "Failed to get type handler, hr %#lx.\n", hr
);
5198 hr
= IMFMediaTypeHandler_GetMediaTypeCount(handler
, &count
);
5199 ok(hr
== S_OK
, "Failed to get media type count, hr %#lx.\n", hr
);
5200 ok(count
== 0, "Unexpected count %lu.\n", count
);
5201 ok(handler
== handler2
, "Unexpected handler.\n");
5203 IMFMediaTypeHandler_Release(handler
);
5204 IMFMediaTypeHandler_Release(handler2
);
5207 hr
= MFCreatePresentationClock(&clock
);
5208 ok(hr
== S_OK
, "Failed to create clock object, hr %#lx.\n", hr
);
5210 hr
= IMFMediaSink_GetPresentationClock(sink
, NULL
);
5211 ok(hr
== E_POINTER
, "Unexpected hr %#lx.\n", hr
);
5213 hr
= IMFMediaSink_GetPresentationClock(sink
, &clock2
);
5214 ok(hr
== MF_E_NO_CLOCK
, "Unexpected hr %#lx.\n", hr
);
5216 hr
= IMFMediaSink_SetPresentationClock(sink
, NULL
);
5217 ok(hr
== S_OK
, "Failed to set presentation clock, hr %#lx.\n", hr
);
5219 hr
= IMFMediaSink_SetPresentationClock(sink
, clock
);
5220 ok(hr
== S_OK
, "Failed to set presentation clock, hr %#lx.\n", hr
);
5222 hr
= MFCreateSystemTimeSource(&time_source
);
5223 ok(hr
== S_OK
, "Failed to create time source, hr %#lx.\n", hr
);
5225 hr
= IMFPresentationClock_SetTimeSource(clock
, time_source
);
5226 ok(hr
== S_OK
, "Failed to set time source, hr %#lx.\n", hr
);
5227 IMFPresentationTimeSource_Release(time_source
);
5229 hr
= IMFMediaSink_GetCharacteristics(sink
, &flags
);
5230 ok(hr
== S_OK
, "Failed to get sink flags, hr %#lx.\n", hr
);
5232 hr
= IMFActivate_ShutdownObject(activate
);
5233 ok(hr
== S_OK
, "Failed to shut down, hr %#lx.\n", hr
);
5235 hr
= IMFMediaSink_GetCharacteristics(sink
, &flags
);
5236 ok(hr
== S_OK
, "Failed to get sink flags, hr %#lx.\n", hr
);
5238 hr
= IMFStreamSink_GetMediaTypeHandler(stream
, &handler
);
5239 ok(hr
== S_OK
, "Failed to get type handler, hr %#lx.\n", hr
);
5241 /* On Win8+ this initialization happens automatically. */
5242 hr
= IMFMediaTypeHandler_SetCurrentMediaType(handler
, media_type
);
5243 ok(hr
== S_OK
, "Failed to set media type, hr %#lx.\n", hr
);
5245 hr
= IMFMediaTypeHandler_GetMediaTypeCount(handler
, NULL
);
5246 ok(hr
== E_POINTER
, "Unexpected hr %#lx.\n", hr
);
5248 hr
= IMFMediaTypeHandler_GetMediaTypeCount(handler
, &count
);
5249 ok(hr
== S_OK
, "Failed to get media type count, hr %#lx.\n", hr
);
5250 ok(count
== 0, "Unexpected count %lu.\n", count
);
5252 hr
= IMFMediaTypeHandler_GetMajorType(handler
, &guid
);
5253 ok(hr
== S_OK
, "Failed to get major type, hr %#lx.\n", hr
);
5254 ok(IsEqualGUID(&guid
, &MFMediaType_Audio
), "Unexpected major type %s.\n", wine_dbgstr_guid(&guid
));
5256 hr
= IMFMediaTypeHandler_GetCurrentMediaType(handler
, &media_type2
);
5257 ok(hr
== S_OK
, "Failed to get current type, hr %#lx.\n", hr
);
5258 ok(media_type2
== media_type
, "Unexpected media type.\n");
5259 IMFMediaType_Release(media_type2
);
5261 hr
= MFCreateMediaType(&media_type2
);
5262 ok(hr
== S_OK
, "Failed to create media type, hr %#lx.\n", hr
);
5264 hr
= IMFMediaTypeHandler_SetCurrentMediaType(handler
, media_type2
);
5265 ok(hr
== MF_E_INVALIDMEDIATYPE
, "Unexpected hr %#lx.\n", hr
);
5267 hr
= IMFMediaType_SetGUID(media_type2
, &MF_MT_MAJOR_TYPE
, &MFMediaType_Audio
);
5268 ok(hr
== S_OK
, "Failed to set attribute, hr %#lx.\n", hr
);
5270 hr
= IMFMediaTypeHandler_SetCurrentMediaType(handler
, media_type2
);
5271 ok(hr
== MF_E_INVALIDMEDIATYPE
, "Unexpected hr %#lx.\n", hr
);
5273 hr
= IMFMediaType_SetGUID(media_type2
, &MF_MT_SUBTYPE
, &MFAudioFormat_Float
);
5274 ok(hr
== S_OK
, "Failed to set attribute, hr %#lx.\n", hr
);
5276 hr
= IMFMediaTypeHandler_SetCurrentMediaType(handler
, media_type2
);
5277 ok(hr
== MF_E_INVALIDMEDIATYPE
, "Unexpected hr %#lx.\n", hr
);
5279 hr
= IMFMediaType_SetGUID(media_type2
, &MF_MT_SUBTYPE
, &MFAudioFormat_PCM
);
5280 ok(hr
== S_OK
, "Failed to set attribute, hr %#lx.\n", hr
);
5282 hr
= IMFMediaType_SetUINT32(media_type2
, &MF_MT_AUDIO_SAMPLES_PER_SECOND
, 44100);
5283 ok(hr
== S_OK
, "Failed to set attribute, hr %#lx.\n", hr
);
5285 hr
= IMFMediaTypeHandler_SetCurrentMediaType(handler
, media_type2
);
5286 ok(hr
== S_OK
, "Failed to get current type, hr %#lx.\n", hr
);
5287 IMFMediaType_Release(media_type
);
5289 hr
= IMFMediaTypeHandler_SetCurrentMediaType(handler
, NULL
);
5290 ok(hr
== E_POINTER
, "Unexpected hr %#lx.\n", hr
);
5292 hr
= IMFMediaTypeHandler_GetCurrentMediaType(handler
, &media_type
);
5293 ok(hr
== S_OK
, "Failed to get current type, hr %#lx.\n", hr
);
5294 ok(media_type2
== media_type
, "Unexpected media type.\n");
5295 IMFMediaType_Release(media_type
);
5297 hr
= IMFMediaTypeHandler_GetMediaTypeByIndex(handler
, 0, &media_type
);
5298 ok(hr
== MF_E_NO_MORE_TYPES
, "Unexpected hr %#lx.\n", hr
);
5300 hr
= IMFMediaTypeHandler_GetMediaTypeByIndex(handler
, 0, NULL
);
5301 ok(hr
== E_POINTER
, "Unexpected hr %#lx.\n", hr
);
5303 hr
= IMFMediaTypeHandler_IsMediaTypeSupported(handler
, media_type2
, NULL
);
5304 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
5306 hr
= MFCreateMediaType(&media_type
);
5307 ok(hr
== S_OK
, "Failed to create media type, hr %#lx.\n", hr
);
5309 hr
= IMFMediaType_SetGUID(media_type
, &MF_MT_MAJOR_TYPE
, &MFMediaType_Audio
);
5310 ok(hr
== S_OK
, "Failed to set attribute, hr %#lx.\n", hr
);
5312 hr
= IMFMediaTypeHandler_IsMediaTypeSupported(handler
, media_type
, NULL
);
5313 ok(hr
== MF_E_INVALIDMEDIATYPE
, "Unexpected hr %#lx.\n", hr
);
5315 hr
= IMFMediaTypeHandler_IsMediaTypeSupported(handler
, media_type
, &media_type3
);
5316 ok(hr
== MF_E_INVALIDMEDIATYPE
, "Unexpected hr %#lx.\n", hr
);
5318 hr
= IMFMediaType_SetGUID(media_type
, &MF_MT_SUBTYPE
, &MFAudioFormat_PCM
);
5319 ok(hr
== S_OK
, "Failed to set attribute, hr %#lx.\n", hr
);
5321 media_type3
= (void *)0xdeadbeef;
5322 hr
= IMFMediaTypeHandler_IsMediaTypeSupported(handler
, media_type
, &media_type3
);
5323 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
5324 ok(media_type3
== (void *)0xdeadbeef, "Unexpected media type %p.\n", media_type3
);
5326 hr
= IMFMediaType_SetUINT32(media_type
, &MF_MT_FIXED_SIZE_SAMPLES
, 1);
5327 ok(hr
== S_OK
, "Failed to set attribute, hr %#lx.\n", hr
);
5329 hr
= IMFMediaType_SetUINT32(media_type
, &MF_MT_SAMPLE_SIZE
, 1024);
5330 ok(hr
== S_OK
, "Failed to set attribute, hr %#lx.\n", hr
);
5332 media_type3
= (void *)0xdeadbeef;
5333 hr
= IMFMediaTypeHandler_IsMediaTypeSupported(handler
, media_type
, &media_type3
);
5334 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
5335 ok(media_type3
== (void *)0xdeadbeef, "Unexpected media type %p.\n", media_type3
);
5337 hr
= IMFMediaTypeHandler_IsMediaTypeSupported(handler
, NULL
, NULL
);
5338 ok(hr
== E_POINTER
, "Unexpected hr %#lx.\n", hr
);
5340 hr
= IMFMediaEventGenerator_GetEvent(eg
, MF_EVENT_FLAG_NO_WAIT
, &event
);
5341 ok(hr
== MF_E_NO_EVENTS_AVAILABLE
, "Unexpected hr %#lx.\n", hr
);
5343 hr
= IMFStreamSink_GetEvent(stream
, MF_EVENT_FLAG_NO_WAIT
, &event
);
5344 ok(hr
== MF_E_NO_EVENTS_AVAILABLE
, "Unexpected hr %#lx.\n", hr
);
5346 EXPECT_REF(clock
, 3);
5347 hr
= IMFMediaSink_Shutdown(sink
);
5348 ok(hr
== S_OK
, "Failed to shut down, hr %#lx.\n", hr
);
5349 EXPECT_REF(clock
, 1);
5351 hr
= IMFMediaSink_SetPresentationClock(sink
, NULL
);
5352 ok(hr
== MF_E_SHUTDOWN
, "Unexpected hr %#lx.\n", hr
);
5354 hr
= IMFMediaSink_SetPresentationClock(sink
, clock
);
5355 ok(hr
== MF_E_SHUTDOWN
, "Unexpected hr %#lx.\n", hr
);
5357 ref
= IMFPresentationClock_Release(clock
);
5358 ok(!ref
, "Unexpected refcount %ld.\n", ref
);
5360 hr
= IMFMediaEventGenerator_GetEvent(eg
, MF_EVENT_FLAG_NO_WAIT
, &event
);
5361 ok(hr
== MF_E_SHUTDOWN
, "Unexpected hr %#lx.\n", hr
);
5363 hr
= IMFMediaSink_Shutdown(sink
);
5364 ok(hr
== MF_E_SHUTDOWN
, "Unexpected hr %#lx.\n", hr
);
5366 hr
= IMFMediaSink_GetCharacteristics(sink
, &flags
);
5367 ok(hr
== MF_E_SHUTDOWN
, "Unexpected hr %#lx.\n", hr
);
5369 hr
= IMFMediaSink_AddStreamSink(sink
, 1, NULL
, &stream2
);
5370 ok(hr
== MF_E_SHUTDOWN
, "Unexpected hr %#lx.\n", hr
);
5372 hr
= IMFMediaSink_GetStreamSinkCount(sink
, &count
);
5373 ok(hr
== MF_E_SHUTDOWN
, "Unexpected hr %#lx.\n", hr
);
5375 hr
= IMFMediaSink_GetStreamSinkByIndex(sink
, 0, &stream2
);
5376 ok(hr
== MF_E_SHUTDOWN
, "Unexpected hr %#lx.\n", hr
);
5378 hr
= IMFStreamSink_GetEvent(stream
, MF_EVENT_FLAG_NO_WAIT
, &event
);
5379 ok(hr
== MF_E_STREAMSINK_REMOVED
, "Unexpected hr %#lx.\n", hr
);
5381 hr
= IMFStreamSink_GetMediaSink(stream
, &sink2
);
5382 ok(hr
== MF_E_STREAMSINK_REMOVED
, "Unexpected hr %#lx.\n", hr
);
5385 hr
= IMFStreamSink_GetIdentifier(stream
, &id
);
5386 ok(hr
== MF_E_STREAMSINK_REMOVED
, "Unexpected hr %#lx.\n", hr
);
5387 ok(id
== 1, "Unexpected id %lu.\n", id
);
5389 media_type3
= (void *)0xdeadbeef;
5390 hr
= IMFMediaTypeHandler_IsMediaTypeSupported(handler
, media_type
, &media_type3
);
5391 ok(hr
== MF_E_STREAMSINK_REMOVED
, "Unexpected hr %#lx.\n", hr
);
5392 ok(media_type3
== (void *)0xdeadbeef, "Unexpected media type %p.\n", media_type3
);
5394 hr
= IMFMediaTypeHandler_IsMediaTypeSupported(handler
, NULL
, NULL
);
5395 ok(hr
== MF_E_STREAMSINK_REMOVED
, "Unexpected hr %#lx.\n", hr
);
5397 hr
= IMFMediaTypeHandler_SetCurrentMediaType(handler
, NULL
);
5398 ok(hr
== MF_E_STREAMSINK_REMOVED
, "Unexpected hr %#lx.\n", hr
);
5400 hr
= IMFMediaTypeHandler_GetMediaTypeCount(handler
, &count
);
5401 ok(hr
== S_OK
, "Failed to get type count, hr %#lx.\n", hr
);
5403 ref
= IMFMediaType_Release(media_type2
);
5404 ok(!ref
, "Unexpected refcount %ld.\n", ref
);
5405 ref
= IMFMediaType_Release(media_type
);
5406 ok(!ref
, "Unexpected refcount %ld.\n", ref
);
5408 hr
= IMFMediaTypeHandler_GetMediaTypeByIndex(handler
, 0, &media_type
);
5409 ok(hr
== MF_E_NO_MORE_TYPES
, "Unexpected hr %#lx.\n", hr
);
5411 hr
= IMFMediaTypeHandler_GetCurrentMediaType(handler
, &media_type
);
5412 ok(hr
== MF_E_STREAMSINK_REMOVED
, "Unexpected hr %#lx.\n", hr
);
5414 hr
= IMFMediaTypeHandler_GetCurrentMediaType(handler
, NULL
);
5415 ok(hr
== E_POINTER
, "Unexpected hr %#lx.\n", hr
);
5417 hr
= IMFMediaTypeHandler_GetMajorType(handler
, NULL
);
5418 ok(hr
== E_POINTER
, "Unexpected hr %#lx.\n", hr
);
5420 hr
= IMFMediaTypeHandler_GetMajorType(handler
, &guid
);
5421 ok(hr
== MF_E_STREAMSINK_REMOVED
, "Unexpected hr %#lx.\n", hr
);
5423 IMFMediaTypeHandler_Release(handler
);
5425 handler
= (void *)0xdeadbeef;
5426 hr
= IMFStreamSink_GetMediaTypeHandler(stream
, &handler
);
5427 ok(hr
== MF_E_STREAMSINK_REMOVED
, "Unexpected hr %#lx.\n", hr
);
5428 ok(handler
== (void *)0xdeadbeef, "Unexpected pointer.\n");
5430 hr
= IMFStreamSink_GetMediaTypeHandler(stream
, NULL
);
5431 ok(hr
== E_POINTER
, "Unexpected hr %#lx.\n", hr
);
5433 IMFMediaEventGenerator_Release(eg
);
5434 IMFStreamSink_Release(stream
);
5436 ref
= IMFActivate_Release(activate
);
5437 ok(!ref
, "Unexpected refcount %ld.\n", ref
);
5438 ref
= IMFMediaSink_Release(sink
);
5439 ok(!ref
, "Unexpected refcount %ld.\n", ref
);
5441 /* Rateless mode with MF_SAMPLEGRABBERSINK_IGNORE_CLOCK. */
5442 hr
= MFCreateMediaType(&media_type
);
5443 ok(hr
== S_OK
, "Failed to create media type, hr %#lx.\n", hr
);
5445 hr
= IMFMediaType_SetGUID(media_type
, &MF_MT_MAJOR_TYPE
, &MFMediaType_Audio
);
5446 ok(hr
== S_OK
, "Failed to set attribute, hr %#lx.\n", hr
);
5447 hr
= IMFMediaType_SetGUID(media_type
, &MF_MT_SUBTYPE
, &MFAudioFormat_PCM
);
5448 ok(hr
== S_OK
, "Failed to set attribute, hr %#lx.\n", hr
);
5450 hr
= MFCreateSampleGrabberSinkActivate(media_type
, grabber_callback
, &activate
);
5451 ok(hr
== S_OK
, "Failed to create grabber activate, hr %#lx.\n", hr
);
5453 hr
= IMFActivate_SetUINT32(activate
, &MF_SAMPLEGRABBERSINK_IGNORE_CLOCK
, 1);
5454 ok(hr
== S_OK
, "Failed to set attribute, hr %#lx.\n", hr
);
5456 hr
= IMFActivate_ActivateObject(activate
, &IID_IMFMediaSink
, (void **)&sink
);
5457 ok(hr
== S_OK
, "Failed to activate object, hr %#lx.\n", hr
);
5459 hr
= IMFMediaSink_GetCharacteristics(sink
, &flags
);
5460 ok(hr
== S_OK
, "Failed to get sink flags, hr %#lx.\n", hr
);
5461 ok(flags
& MEDIASINK_RATELESS
, "Unexpected flags %#lx.\n", flags
);
5463 hr
= IMFActivate_ShutdownObject(activate
);
5464 ok(hr
== S_OK
, "Failed to shut down, hr %#lx.\n", hr
);
5466 /* required for the sink to be fully released */
5467 hr
= IMFMediaSink_Shutdown(sink
);
5468 ok(hr
== S_OK
, "Failed to shut down, hr %#lx.\n", hr
);
5470 ref
= IMFActivate_Release(activate
);
5471 ok(ref
== 0, "Release returned %ld\n", ref
);
5472 ref
= IMFMediaSink_Release(sink
);
5473 ok(ref
== 0, "Release returned %ld\n", ref
);
5476 hr
= MFCreateSampleGrabberSinkActivate(media_type
, grabber_callback
, &activate
);
5477 ok(hr
== S_OK
, "Failed to create grabber activate, hr %#lx.\n", hr
);
5479 hr
= IMFActivate_ActivateObject(activate
, &IID_IMFMediaSink
, (void **)&sink
);
5480 ok(hr
== S_OK
, "Failed to activate object, hr %#lx.\n", hr
);
5482 hr
= IMFActivate_ShutdownObject(activate
);
5483 ok(hr
== S_OK
, "Failed to shut down, hr %#lx.\n", hr
);
5485 hr
= IMFActivate_ActivateObject(activate
, &IID_IMFMediaSink
, (void **)&sink2
);
5486 ok(hr
== MF_E_SHUTDOWN
, "Unexpected hr %#lx.\n", hr
);
5488 hr
= IMFActivate_GetCount(activate
, &attr_count
);
5489 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
5491 hr
= IMFActivate_DetachObject(activate
);
5492 ok(hr
== E_NOTIMPL
, "Unexpected hr %#lx.\n", hr
);
5494 ref
= IMFActivate_Release(activate
);
5495 ok(ref
== 0, "Release returned %ld\n", ref
);
5497 /* required for the sink to be fully released */
5498 hr
= IMFMediaSink_Shutdown(sink
);
5499 ok(hr
== S_OK
, "Failed to shut down, hr %#lx.\n", hr
);
5501 ref
= IMFMediaSink_Release(sink
);
5502 ok(ref
== 0, "Release returned %ld\n", ref
);
5504 ref
= IMFMediaType_Release(media_type
);
5505 ok(ref
== 0, "Release returned %ld\n", ref
);
5508 ok(hr
== S_OK
, "Failed to shut down, hr %#lx.\n", hr
);
5510 IMFSampleGrabberSinkCallback_Release(grabber_callback
);
5513 static void test_sample_grabber_is_mediatype_supported(void)
5515 IMFSampleGrabberSinkCallback
*grabber_callback
= create_test_grabber_callback();
5516 IMFMediaType
*media_type
, *media_type2
, *media_type3
;
5517 IMFMediaTypeHandler
*handler
;
5518 IMFActivate
*activate
;
5519 IMFStreamSink
*stream
;
5525 /* IsMediaTypeSupported checks are done against the creation type, and check format data */
5526 hr
= MFCreateMediaType(&media_type
);
5527 ok(hr
== S_OK
, "Failed to create media type, hr %#lx.\n", hr
);
5529 hr
= IMFMediaType_SetGUID(media_type
, &MF_MT_MAJOR_TYPE
, &MFMediaType_Audio
);
5530 ok(hr
== S_OK
, "Failed to set attribute, hr %#lx.\n", hr
);
5531 hr
= IMFMediaType_SetGUID(media_type
, &MF_MT_SUBTYPE
, &MFAudioFormat_PCM
);
5532 ok(hr
== S_OK
, "Failed to set attribute, hr %#lx.\n", hr
);
5533 hr
= IMFMediaType_SetUINT32(media_type
, &MF_MT_AUDIO_SAMPLES_PER_SECOND
, 44100);
5534 ok(hr
== S_OK
, "Failed to set attribute, hr %#lx.\n", hr
);
5536 hr
= MFCreateSampleGrabberSinkActivate(media_type
, grabber_callback
, &activate
);
5537 ok(hr
== S_OK
, "Failed to create grabber activate, hr %#lx.\n", hr
);
5539 hr
= IMFActivate_ActivateObject(activate
, &IID_IMFMediaSink
, (void **)&sink
);
5540 ok(hr
== S_OK
, "Failed to activate object, hr %#lx.\n", hr
);
5542 hr
= IMFMediaSink_GetStreamSinkByIndex(sink
, 0, &stream
);
5543 ok(hr
== S_OK
, "Failed to get sink stream, hr %#lx.\n", hr
);
5544 hr
= IMFStreamSink_GetMediaTypeHandler(stream
, &handler
);
5545 ok(hr
== S_OK
, "Failed to get type handler, hr %#lx.\n", hr
);
5546 IMFStreamSink_Release(stream
);
5548 /* On Win8+ this initialization happens automatically. */
5549 hr
= IMFMediaTypeHandler_SetCurrentMediaType(handler
, media_type
);
5550 ok(hr
== S_OK
, "Failed to set media type, hr %#lx.\n", hr
);
5552 hr
= MFCreateMediaType(&media_type2
);
5553 ok(hr
== S_OK
, "Failed to create media type, hr %#lx.\n", hr
);
5555 hr
= IMFMediaType_SetGUID(media_type2
, &MF_MT_MAJOR_TYPE
, &MFMediaType_Audio
);
5556 ok(hr
== S_OK
, "Failed to set attribute, hr %#lx.\n", hr
);
5557 hr
= IMFMediaType_SetGUID(media_type2
, &MF_MT_SUBTYPE
, &MFAudioFormat_PCM
);
5558 ok(hr
== S_OK
, "Failed to set attribute, hr %#lx.\n", hr
);
5559 hr
= IMFMediaType_SetUINT32(media_type2
, &MF_MT_AUDIO_SAMPLES_PER_SECOND
, 48000);
5560 ok(hr
== S_OK
, "Failed to set attribute, hr %#lx.\n", hr
);
5562 hr
= IMFMediaTypeHandler_IsMediaTypeSupported(handler
, media_type2
, NULL
);
5563 ok(hr
== MF_E_INVALIDMEDIATYPE
, "Unexpected hr %#lx.\n", hr
);
5565 hr
= IMFMediaTypeHandler_SetCurrentMediaType(handler
, media_type2
);
5566 ok(hr
== MF_E_INVALIDMEDIATYPE
, "Failed to set media type, hr %#lx.\n", hr
);
5568 /* Make it match grabber type sample rate. */
5569 hr
= IMFMediaType_SetUINT32(media_type2
, &MF_MT_AUDIO_SAMPLES_PER_SECOND
, 44100);
5570 ok(hr
== S_OK
, "Failed to set attribute, hr %#lx.\n", hr
);
5572 hr
= IMFMediaTypeHandler_IsMediaTypeSupported(handler
, media_type2
, NULL
);
5573 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
5575 hr
= IMFMediaTypeHandler_SetCurrentMediaType(handler
, media_type2
);
5576 ok(hr
== S_OK
, "Failed to set media type, hr %#lx.\n", hr
);
5577 hr
= IMFMediaTypeHandler_GetCurrentMediaType(handler
, &media_type3
);
5578 ok(hr
== S_OK
, "Failed to set media type, hr %#lx.\n", hr
);
5579 ok(media_type3
== media_type2
, "Unexpected media type instance.\n");
5580 IMFMediaType_Release(media_type3
);
5582 /* Change original type. */
5583 hr
= IMFMediaType_SetUINT32(media_type
, &MF_MT_AUDIO_SAMPLES_PER_SECOND
, 48000);
5584 ok(hr
== S_OK
, "Failed to set attribute, hr %#lx.\n", hr
);
5586 hr
= IMFMediaTypeHandler_IsMediaTypeSupported(handler
, media_type2
, NULL
);
5587 ok(hr
== MF_E_INVALIDMEDIATYPE
, "Unexpected hr %#lx.\n", hr
);
5589 hr
= IMFMediaType_SetUINT32(media_type2
, &MF_MT_AUDIO_SAMPLES_PER_SECOND
, 48000);
5590 ok(hr
== S_OK
, "Failed to set attribute, hr %#lx.\n", hr
);
5592 hr
= IMFMediaTypeHandler_IsMediaTypeSupported(handler
, media_type2
, NULL
);
5593 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
5595 hr
= IMFMediaTypeHandler_GetMajorType(handler
, &guid
);
5596 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
5597 ok(IsEqualGUID(&guid
, &MFMediaType_Audio
), "Unexpected major type.\n");
5599 hr
= IMFMediaType_SetGUID(media_type
, &MF_MT_MAJOR_TYPE
, &MFMediaType_Video
);
5600 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
5602 hr
= IMFMediaTypeHandler_GetMajorType(handler
, &guid
);
5603 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
5604 ok(IsEqualGUID(&guid
, &MFMediaType_Audio
), "Unexpected major type.\n");
5606 IMFMediaTypeHandler_Release(handler
);
5608 hr
= IMFActivate_ShutdownObject(activate
);
5609 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
5611 ref
= IMFActivate_Release(activate
);
5612 ok(ref
== 0, "Release returned %ld\n", ref
);
5614 /* required for the sink to be fully released */
5615 hr
= IMFMediaSink_Shutdown(sink
);
5616 ok(hr
== S_OK
, "Failed to shut down, hr %#lx.\n", hr
);
5618 ref
= IMFMediaSink_Release(sink
);
5619 ok(ref
== 0, "Release returned %ld\n", ref
);
5621 ref
= IMFMediaType_Release(media_type2
);
5622 ok(ref
== 0, "Release returned %ld\n", ref
);
5623 ref
= IMFMediaType_Release(media_type
);
5624 ok(ref
== 0, "Release returned %ld\n", ref
);
5626 IMFSampleGrabberSinkCallback_Release(grabber_callback
);
5629 /* create a test topology with the specified source and sink, and return duration if required */
5630 static IMFTopology
*create_test_topology(IMFMediaSource
*source
, IMFActivate
*sink_activate
, UINT64
*duration
)
5632 IMFTopologyNode
*src_node
, *sink_node
;
5633 IMFPresentationDescriptor
*pd
;
5634 IMFTopology
*topology
= NULL
;
5635 IMFStreamDescriptor
*sd
;
5639 hr
= MFCreateTopology(&topology
);
5640 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
5641 hr
= MFCreateTopologyNode(MF_TOPOLOGY_OUTPUT_NODE
, &sink_node
);
5642 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
5643 hr
= MFCreateTopologyNode(MF_TOPOLOGY_SOURCESTREAM_NODE
, &src_node
);
5644 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
5645 hr
= IMFTopology_AddNode(topology
, sink_node
);
5646 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
5647 hr
= IMFTopology_AddNode(topology
, src_node
);
5648 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
5649 hr
= IMFTopologyNode_ConnectOutput(src_node
, 0, sink_node
, 0);
5650 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
5651 hr
= IMFMediaSource_CreatePresentationDescriptor(source
, &pd
);
5652 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
5653 hr
= IMFPresentationDescriptor_GetStreamDescriptorByIndex(pd
, 0, &selected
, &sd
);
5654 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
5655 ok(selected
, "got selected %u.\n", !!selected
);
5658 hr
= IMFPresentationDescriptor_GetUINT64(pd
, &MF_PD_DURATION
, duration
);
5659 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
5661 init_source_node(source
, -1, src_node
, pd
, sd
);
5662 hr
= IMFTopologyNode_SetObject(sink_node
, (IUnknown
*)sink_activate
);
5663 ok(hr
== S_OK
, "Failed to set object, hr %#lx.\n", hr
);
5664 hr
= IMFTopologyNode_SetUINT32(sink_node
, &MF_TOPONODE_CONNECT_METHOD
, MF_CONNECT_ALLOW_DECODER
);
5665 ok(hr
== S_OK
, "Failed to set connect method, hr %#lx.\n", hr
);
5666 hr
= IMFTopology_SetUINT32(topology
, &MF_TOPOLOGY_ENUMERATE_SOURCE_TYPES
, TRUE
);
5667 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
5669 IMFStreamDescriptor_Release(sd
);
5670 IMFPresentationDescriptor_Release(pd
);
5671 IMFTopologyNode_Release(src_node
);
5672 IMFTopologyNode_Release(sink_node
);
5676 static void test_sample_grabber_orientation(GUID subtype
)
5678 media_type_desc video_rgb32_desc
=
5680 ATTR_GUID(MF_MT_MAJOR_TYPE
, MFMediaType_Video
),
5681 ATTR_GUID(MF_MT_SUBTYPE
, subtype
),
5684 struct test_grabber_callback
*grabber_callback
;
5685 IMFAsyncCallback
*callback
;
5686 IMFActivate
*sink_activate
;
5687 IMFMediaType
*output_type
;
5688 IMFMediaSession
*session
;
5689 IMFMediaSource
*source
;
5690 IMFTopology
*topology
;
5691 PROPVARIANT propvar
;
5695 hr
= MFStartup(MF_VERSION
, MFSTARTUP_FULL
);
5696 ok(hr
== S_OK
, "Failed to start up, hr %#lx.\n", hr
);
5698 if (!(source
= create_media_source(L
"test.mp4", L
"video/mp4")))
5700 win_skip("MP4 media source is not supported, skipping tests.\n");
5704 callback
= create_test_callback(TRUE
);
5705 grabber_callback
= impl_from_IMFSampleGrabberSinkCallback(create_test_grabber_callback());
5707 grabber_callback
->ready_event
= CreateEventW(NULL
, FALSE
, FALSE
, NULL
);
5708 ok(!!grabber_callback
->ready_event
, "CreateEventW failed, error %lu\n", GetLastError());
5709 grabber_callback
->done_event
= CreateEventW(NULL
, FALSE
, FALSE
, NULL
);
5710 ok(!!grabber_callback
->done_event
, "CreateEventW failed, error %lu\n", GetLastError());
5712 hr
= MFCreateMediaSession(NULL
, &session
);
5713 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
5715 hr
= MFCreateMediaType(&output_type
);
5716 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
5717 init_media_type(output_type
, video_rgb32_desc
, -1);
5718 hr
= MFCreateSampleGrabberSinkActivate(output_type
, &grabber_callback
->IMFSampleGrabberSinkCallback_iface
, &sink_activate
);
5719 ok(hr
== S_OK
, "Failed to create grabber sink, hr %#lx.\n", hr
);
5720 IMFMediaType_Release(output_type
);
5722 topology
= create_test_topology(source
, sink_activate
, NULL
);
5723 hr
= IMFMediaSession_SetTopology(session
, 0, topology
);
5724 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
5725 IMFTopology_Release(topology
);
5727 propvar
.vt
= VT_EMPTY
;
5728 hr
= IMFMediaSession_Start(session
, &GUID_NULL
, &propvar
);
5729 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
5731 res
= WaitForSingleObject(grabber_callback
->ready_event
, 5000);
5732 ok(!res
, "WaitForSingleObject returned %#lx\n", res
);
5733 CloseHandle(grabber_callback
->ready_event
);
5734 grabber_callback
->ready_event
= NULL
;
5736 if (IsEqualGUID(&subtype
, &MFVideoFormat_RGB32
))
5738 const struct buffer_desc buffer_desc_rgb32
=
5740 .length
= 64 * 64 * 4, .compare
= compare_rgb32
, .dump
= dump_rgb32
, .rect
= {.right
= 64, .bottom
= 64},
5742 const struct sample_desc sample_desc_rgb32
=
5744 .sample_duration
= 333667, .buffer_count
= 1, .buffers
= &buffer_desc_rgb32
,
5746 check_mf_sample_collection(grabber_callback
->samples
, &sample_desc_rgb32
, L
"rgb32frame-grabber.bmp");
5748 else if (IsEqualGUID(&subtype
, &MFVideoFormat_NV12
))
5750 const struct buffer_desc buffer_desc_nv12
=
5752 .length
= 64 * 64 * 3 / 2, .compare
= compare_nv12
, .dump
= dump_nv12
, .rect
= {.right
= 64, .bottom
= 64},
5754 const struct sample_desc sample_desc_nv12
=
5756 .sample_duration
= 333667, .buffer_count
= 1, .buffers
= &buffer_desc_nv12
,
5758 check_mf_sample_collection(grabber_callback
->samples
, &sample_desc_nv12
, L
"nv12frame-grabber.bmp");
5761 SetEvent(grabber_callback
->done_event
);
5763 hr
= IMFMediaSession_ClearTopologies(session
);
5764 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
5765 hr
= IMFMediaSession_Close(session
);
5766 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
5767 hr
= wait_media_event(session
, callback
, MESessionClosed
, 1000, &propvar
);
5768 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
5769 ok(propvar
.vt
== VT_EMPTY
, "got vt %u\n", propvar
.vt
);
5771 hr
= IMFMediaSession_Shutdown(session
);
5772 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
5773 hr
= IMFMediaSource_Shutdown(source
);
5774 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
5775 hr
= IMFActivate_ShutdownObject(sink_activate
);
5776 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
5778 IMFActivate_Release(sink_activate
);
5779 IMFMediaSession_Release(session
);
5780 IMFMediaSource_Release(source
);
5782 IMFSampleGrabberSinkCallback_Release(&grabber_callback
->IMFSampleGrabberSinkCallback_iface
);
5786 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
5789 static void test_quality_manager(void)
5791 IMFPresentationClock
*clock
;
5792 IMFQualityManager
*manager
;
5793 IMFTopology
*topology
;
5797 hr
= MFStartup(MF_VERSION
, MFSTARTUP_FULL
);
5798 ok(hr
== S_OK
, "Startup failure, hr %#lx.\n", hr
);
5800 hr
= MFCreatePresentationClock(&clock
);
5801 ok(hr
== S_OK
, "Failed to create presentation clock, hr %#lx.\n", hr
);
5803 hr
= MFCreateStandardQualityManager(&manager
);
5804 ok(hr
== S_OK
, "Failed to create quality manager, hr %#lx.\n", hr
);
5806 check_interface(manager
, &IID_IMFQualityManager
, TRUE
);
5807 check_interface(manager
, &IID_IMFClockStateSink
, TRUE
);
5809 hr
= IMFQualityManager_NotifyPresentationClock(manager
, NULL
);
5810 ok(hr
== E_POINTER
, "Unexpected hr %#lx.\n", hr
);
5812 hr
= IMFQualityManager_NotifyTopology(manager
, NULL
);
5813 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
5815 /* Set clock, then shutdown. */
5816 EXPECT_REF(clock
, 1);
5817 EXPECT_REF(manager
, 1);
5818 hr
= IMFQualityManager_NotifyPresentationClock(manager
, clock
);
5819 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
5820 EXPECT_REF(clock
, 2);
5821 EXPECT_REF(manager
, 2);
5823 hr
= IMFQualityManager_Shutdown(manager
);
5824 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
5825 EXPECT_REF(clock
, 1);
5827 hr
= IMFQualityManager_NotifyPresentationClock(manager
, clock
);
5828 ok(hr
== MF_E_SHUTDOWN
, "Unexpected hr %#lx.\n", hr
);
5830 hr
= IMFQualityManager_NotifyTopology(manager
, NULL
);
5831 ok(hr
== MF_E_SHUTDOWN
, "Unexpected hr %#lx.\n", hr
);
5833 hr
= IMFQualityManager_NotifyPresentationClock(manager
, NULL
);
5834 ok(hr
== MF_E_SHUTDOWN
, "Unexpected hr %#lx.\n", hr
);
5836 hr
= IMFQualityManager_Shutdown(manager
);
5837 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
5839 ref
= IMFQualityManager_Release(manager
);
5840 ok(ref
== 0, "Release returned %ld\n", ref
);
5842 hr
= MFCreateStandardQualityManager(&manager
);
5843 ok(hr
== S_OK
, "Failed to create quality manager, hr %#lx.\n", hr
);
5845 EXPECT_REF(clock
, 1);
5846 EXPECT_REF(manager
, 1);
5847 hr
= IMFQualityManager_NotifyPresentationClock(manager
, clock
);
5848 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
5849 EXPECT_REF(manager
, 2);
5850 EXPECT_REF(clock
, 2);
5851 hr
= IMFQualityManager_Shutdown(manager
);
5852 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
5854 ref
= IMFQualityManager_Release(manager
);
5855 ok(ref
== 0, "Release returned %ld\n", ref
);
5856 ref
= IMFPresentationClock_Release(clock
);
5857 ok(ref
== 0, "Release returned %ld\n", ref
);
5860 hr
= MFCreateStandardQualityManager(&manager
);
5861 ok(hr
== S_OK
, "Failed to create quality manager, hr %#lx.\n", hr
);
5863 hr
= MFCreateTopology(&topology
);
5864 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
5866 EXPECT_REF(topology
, 1);
5867 hr
= IMFQualityManager_NotifyTopology(manager
, topology
);
5868 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
5869 EXPECT_REF(topology
, 2);
5871 hr
= IMFQualityManager_NotifyTopology(manager
, NULL
);
5872 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
5873 EXPECT_REF(topology
, 1);
5875 hr
= IMFQualityManager_NotifyTopology(manager
, topology
);
5876 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
5878 EXPECT_REF(topology
, 2);
5879 hr
= IMFQualityManager_Shutdown(manager
);
5880 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
5881 EXPECT_REF(topology
, 1);
5883 hr
= IMFQualityManager_NotifyTopology(manager
, topology
);
5884 ok(hr
== MF_E_SHUTDOWN
, "Unexpected hr %#lx.\n", hr
);
5886 ref
= IMFQualityManager_Release(manager
);
5887 ok(ref
== 0, "Release returned %ld\n", ref
);
5889 hr
= MFCreateStandardQualityManager(&manager
);
5890 ok(hr
== S_OK
, "Failed to create quality manager, hr %#lx.\n", hr
);
5892 EXPECT_REF(topology
, 1);
5893 hr
= IMFQualityManager_NotifyTopology(manager
, topology
);
5894 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
5895 EXPECT_REF(topology
, 2);
5897 ref
= IMFQualityManager_Release(manager
);
5898 ok(ref
== 0, "Release returned %ld\n", ref
);
5899 ref
= IMFTopology_Release(topology
);
5900 ok(ref
== 0, "Release returned %ld\n", ref
);
5903 ok(hr
== S_OK
, "Shutdown failure, hr %#lx.\n", hr
);
5906 static void check_sar_rate_support(IMFMediaSink
*sink
)
5908 IMFRateSupport
*rate_support
;
5909 IMFMediaTypeHandler
*handler
;
5910 IMFStreamSink
*stream_sink
;
5911 IMFMediaType
*media_type
;
5915 hr
= IMFMediaSink_QueryInterface(sink
, &IID_IMFRateSupport
, (void **)&rate_support
);
5917 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
5918 if (FAILED(hr
)) return;
5920 hr
= IMFMediaSink_GetStreamSinkByIndex(sink
, 0, &stream_sink
);
5921 if (hr
== MF_E_SHUTDOWN
)
5923 hr
= IMFRateSupport_GetSlowestRate(rate_support
, MFRATE_FORWARD
, FALSE
, NULL
);
5924 ok(hr
== E_POINTER
, "Unexpected hr %#lx.\n", hr
);
5926 hr
= IMFRateSupport_GetSlowestRate(rate_support
, MFRATE_FORWARD
, FALSE
, &rate
);
5927 ok(hr
== MF_E_SHUTDOWN
, "Unexpected hr %#lx.\n", hr
);
5929 hr
= IMFRateSupport_GetFastestRate(rate_support
, MFRATE_FORWARD
, FALSE
, &rate
);
5930 ok(hr
== MF_E_SHUTDOWN
, "Unexpected hr %#lx.\n", hr
);
5932 IMFRateSupport_Release(rate_support
);
5935 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
5937 hr
= IMFStreamSink_GetMediaTypeHandler(stream_sink
, &handler
);
5938 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
5940 IMFStreamSink_Release(stream_sink
);
5942 hr
= IMFRateSupport_GetSlowestRate(rate_support
, MFRATE_FORWARD
, FALSE
, NULL
);
5943 ok(hr
== E_POINTER
, "Unexpected hr %#lx.\n", hr
);
5945 hr
= IMFRateSupport_GetFastestRate(rate_support
, MFRATE_FORWARD
, FALSE
, NULL
);
5946 ok(hr
== E_POINTER
, "Unexpected hr %#lx.\n", hr
);
5948 hr
= IMFMediaTypeHandler_GetCurrentMediaType(handler
, &media_type
);
5951 hr
= IMFRateSupport_GetSlowestRate(rate_support
, MFRATE_FORWARD
, FALSE
, &rate
);
5952 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
5954 hr
= IMFRateSupport_GetSlowestRate(rate_support
, MFRATE_FORWARD
, TRUE
, &rate
);
5955 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
5957 hr
= IMFRateSupport_GetSlowestRate(rate_support
, MFRATE_REVERSE
, FALSE
, &rate
);
5958 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
5960 hr
= IMFRateSupport_GetSlowestRate(rate_support
, MFRATE_REVERSE
, TRUE
, &rate
);
5961 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
5963 hr
= IMFRateSupport_GetFastestRate(rate_support
, MFRATE_FORWARD
, FALSE
, &rate
);
5964 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
5966 hr
= IMFRateSupport_GetFastestRate(rate_support
, MFRATE_FORWARD
, TRUE
, &rate
);
5967 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
5969 hr
= IMFRateSupport_GetFastestRate(rate_support
, MFRATE_REVERSE
, FALSE
, &rate
);
5970 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
5972 hr
= IMFRateSupport_GetFastestRate(rate_support
, MFRATE_REVERSE
, TRUE
, &rate
);
5973 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
5975 IMFMediaType_Release(media_type
);
5979 hr
= IMFRateSupport_GetSlowestRate(rate_support
, MFRATE_FORWARD
, FALSE
, &rate
);
5980 ok(hr
== MF_E_NOT_INITIALIZED
, "Unexpected hr %#lx.\n", hr
);
5982 hr
= IMFRateSupport_GetSlowestRate(rate_support
, MFRATE_FORWARD
, TRUE
, &rate
);
5983 ok(hr
== MF_E_NOT_INITIALIZED
, "Unexpected hr %#lx.\n", hr
);
5985 hr
= IMFRateSupport_GetSlowestRate(rate_support
, MFRATE_REVERSE
, FALSE
, &rate
);
5986 ok(hr
== MF_E_NOT_INITIALIZED
, "Unexpected hr %#lx.\n", hr
);
5988 hr
= IMFRateSupport_GetSlowestRate(rate_support
, MFRATE_REVERSE
, TRUE
, &rate
);
5989 ok(hr
== MF_E_NOT_INITIALIZED
, "Unexpected hr %#lx.\n", hr
);
5991 hr
= IMFRateSupport_GetFastestRate(rate_support
, MFRATE_FORWARD
, FALSE
, &rate
);
5992 ok(hr
== MF_E_NOT_INITIALIZED
, "Unexpected hr %#lx.\n", hr
);
5994 hr
= IMFRateSupport_GetFastestRate(rate_support
, MFRATE_FORWARD
, TRUE
, &rate
);
5995 ok(hr
== MF_E_NOT_INITIALIZED
, "Unexpected hr %#lx.\n", hr
);
5997 hr
= IMFRateSupport_GetFastestRate(rate_support
, MFRATE_REVERSE
, FALSE
, &rate
);
5998 ok(hr
== MF_E_NOT_INITIALIZED
, "Unexpected hr %#lx.\n", hr
);
6000 hr
= IMFRateSupport_GetFastestRate(rate_support
, MFRATE_REVERSE
, TRUE
, &rate
);
6001 ok(hr
== MF_E_NOT_INITIALIZED
, "Unexpected hr %#lx.\n", hr
);
6004 IMFMediaTypeHandler_Release(handler
);
6005 IMFRateSupport_Release(rate_support
);
6008 static void test_sar(void)
6010 static const struct attribute_desc input_type_desc_48000
[] =
6012 ATTR_GUID(MF_MT_MAJOR_TYPE
, MFMediaType_Audio
, .required
= TRUE
),
6013 ATTR_GUID(MF_MT_SUBTYPE
, MFAudioFormat_Float
, .required
= TRUE
, .todo
= TRUE
),
6014 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS
, 2, .required
= TRUE
),
6015 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE
, 32, .required
= TRUE
),
6016 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND
, 48000, .required
= TRUE
),
6017 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT
, 2 * (32 / 8), .required
= TRUE
),
6018 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND
, 2 * (32 / 8) * 48000, .required
= TRUE
),
6021 static const struct attribute_desc input_type_desc_44100
[] =
6023 ATTR_GUID(MF_MT_MAJOR_TYPE
, MFMediaType_Audio
, .required
= TRUE
),
6024 ATTR_GUID(MF_MT_SUBTYPE
, MFAudioFormat_Float
, .required
= TRUE
, .todo
= TRUE
),
6025 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS
, 2, .required
= TRUE
),
6026 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE
, 32, .required
= TRUE
),
6027 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND
, 44100, .required
= TRUE
),
6028 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT
, 2 * (32 / 8), .required
= TRUE
),
6029 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND
, 2 * (32 / 8) * 44100, .required
= TRUE
),
6033 IMFPresentationClock
*present_clock
, *present_clock2
;
6034 IMFMediaType
*mediatype
, *mediatype2
, *mediatype3
;
6035 IMFClockStateSink
*state_sink
, *state_sink2
;
6036 IMFMediaTypeHandler
*handler
, *handler2
;
6037 IMFPresentationTimeSource
*time_source
;
6038 IMFSimpleAudioVolume
*simple_volume
;
6039 IMFAudioStreamVolume
*stream_volume
;
6040 IMFMediaSink
*sink
, *sink2
;
6041 IMFStreamSink
*stream_sink
;
6042 UINT32 channel_count
, rate
;
6043 IMFAttributes
*attributes
;
6044 DWORD id
, flags
, count
;
6045 IMFActivate
*activate
;
6046 MFCLOCK_STATE state
;
6054 hr
= CoInitialize(NULL
);
6055 ok(hr
== S_OK
, "Failed to initialize, hr %#lx.\n", hr
);
6057 hr
= MFCreateAudioRenderer(NULL
, &sink
);
6058 if (hr
== MF_E_NO_AUDIO_PLAYBACK_DEVICE
)
6060 skip("No audio playback device available.\n");
6064 ok(hr
== S_OK
, "Failed to create renderer, hr %#lx.\n", hr
);
6066 hr
= MFStartup(MF_VERSION
, MFSTARTUP_FULL
);
6067 ok(hr
== S_OK
, "Startup failure, hr %#lx.\n", hr
);
6069 hr
= MFCreatePresentationClock(&present_clock
);
6070 ok(hr
== S_OK
, "Failed to create presentation clock, hr %#lx.\n", hr
);
6072 hr
= IMFMediaSink_QueryInterface(sink
, &IID_IMFPresentationTimeSource
, (void **)&time_source
);
6074 ok(hr
== S_OK
, "Failed to get time source interface, hr %#lx.\n", hr
);
6078 hr
= IMFPresentationTimeSource_QueryInterface(time_source
, &IID_IMFClockStateSink
, (void **)&state_sink2
);
6079 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
6080 hr
= IMFPresentationTimeSource_QueryInterface(time_source
, &IID_IMFClockStateSink
, (void **)&state_sink
);
6081 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
6082 ok(state_sink
== state_sink2
, "Unexpected clock sink.\n");
6083 IMFClockStateSink_Release(state_sink2
);
6084 IMFClockStateSink_Release(state_sink
);
6086 hr
= IMFPresentationTimeSource_GetUnderlyingClock(time_source
, &clock
);
6087 ok(hr
== MF_E_NO_CLOCK
, "Unexpected hr %#lx.\n", hr
);
6089 hr
= IMFPresentationTimeSource_GetClockCharacteristics(time_source
, &flags
);
6090 ok(hr
== S_OK
, "Failed to get flags, hr %#lx.\n", hr
);
6091 ok(flags
== MFCLOCK_CHARACTERISTICS_FLAG_FREQUENCY_10MHZ
, "Unexpected flags %#lx.\n", flags
);
6093 hr
= IMFPresentationTimeSource_GetState(time_source
, 0, &state
);
6094 ok(hr
== S_OK
, "Failed to get clock state, hr %#lx.\n", hr
);
6095 ok(state
== MFCLOCK_STATE_INVALID
, "Unexpected state %d.\n", state
);
6097 hr
= IMFPresentationTimeSource_QueryInterface(time_source
, &IID_IMFClockStateSink
, (void **)&state_sink
);
6098 ok(hr
== S_OK
, "Failed to get state sink, hr %#lx.\n", hr
);
6100 hr
= IMFClockStateSink_OnClockStart(state_sink
, 0, 0);
6101 ok(hr
== MF_E_NOT_INITIALIZED
, "Unexpected hr %#lx.\n", hr
);
6103 IMFClockStateSink_Release(state_sink
);
6105 IMFPresentationTimeSource_Release(time_source
);
6107 hr
= IMFMediaSink_AddStreamSink(sink
, 123, NULL
, &stream_sink
);
6108 ok(hr
== MF_E_STREAMSINKS_FIXED
, "Unexpected hr %#lx.\n", hr
);
6110 hr
= IMFMediaSink_RemoveStreamSink(sink
, 0);
6111 ok(hr
== MF_E_STREAMSINKS_FIXED
, "Unexpected hr %#lx.\n", hr
);
6113 hr
= IMFMediaSink_GetStreamSinkCount(sink
, NULL
);
6114 ok(hr
== E_POINTER
, "Unexpected hr %#lx.\n", hr
);
6116 hr
= IMFMediaSink_GetStreamSinkCount(sink
, &count
);
6117 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
6118 ok(count
== 1, "Unexpected count %lu.\n", count
);
6120 hr
= IMFMediaSink_GetCharacteristics(sink
, &flags
);
6121 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
6122 ok(flags
== (MEDIASINK_FIXED_STREAMS
| MEDIASINK_CAN_PREROLL
), "Unexpected flags %#lx.\n", flags
);
6124 check_interface(sink
, &IID_IMFMediaSinkPreroll
, TRUE
);
6125 check_interface(sink
, &IID_IMFMediaEventGenerator
, TRUE
);
6126 check_interface(sink
, &IID_IMFClockStateSink
, TRUE
);
6127 check_interface(sink
, &IID_IMFGetService
, TRUE
);
6128 todo_wine
check_interface(sink
, &IID_IMFPresentationTimeSource
, TRUE
);
6129 todo_wine
check_service_interface(sink
, &MF_RATE_CONTROL_SERVICE
, &IID_IMFRateSupport
, TRUE
);
6130 check_service_interface(sink
, &MF_RATE_CONTROL_SERVICE
, &IID_IMFRateControl
, FALSE
);
6131 check_service_interface(sink
, &MR_POLICY_VOLUME_SERVICE
, &IID_IMFSimpleAudioVolume
, TRUE
);
6132 check_service_interface(sink
, &MR_STREAM_VOLUME_SERVICE
, &IID_IMFAudioStreamVolume
, TRUE
);
6135 hr
= IMFMediaSink_QueryInterface(sink
, &IID_IMFClockStateSink
, (void **)&state_sink
);
6136 ok(hr
== S_OK
, "Failed to get interface, hr %#lx.\n", hr
);
6138 hr
= IMFClockStateSink_OnClockStart(state_sink
, 0, 0);
6139 ok(hr
== MF_E_NOT_INITIALIZED
, "Unexpected hr %#lx.\n", hr
);
6141 hr
= IMFClockStateSink_OnClockPause(state_sink
, 0);
6142 ok(hr
== MF_E_INVALID_STATE_TRANSITION
, "Unexpected hr %#lx.\n", hr
);
6144 hr
= IMFClockStateSink_OnClockStop(state_sink
, 0);
6145 ok(hr
== MF_E_NOT_INITIALIZED
, "Unexpected hr %#lx.\n", hr
);
6147 hr
= IMFClockStateSink_OnClockRestart(state_sink
, 0);
6148 ok(hr
== MF_E_NOT_INITIALIZED
, "Unexpected hr %#lx.\n", hr
);
6150 IMFClockStateSink_Release(state_sink
);
6152 hr
= IMFMediaSink_SetPresentationClock(sink
, NULL
);
6153 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
6155 hr
= IMFMediaSink_SetPresentationClock(sink
, present_clock
);
6157 ok(hr
== MF_E_CLOCK_NO_TIME_SOURCE
, "Unexpected hr %#lx.\n", hr
);
6159 hr
= MFCreateSystemTimeSource(&time_source
);
6160 ok(hr
== S_OK
, "Failed to create time source, hr %#lx.\n", hr
);
6162 hr
= IMFPresentationClock_SetTimeSource(present_clock
, time_source
);
6163 ok(hr
== S_OK
, "Failed to set time source, hr %#lx.\n", hr
);
6164 IMFPresentationTimeSource_Release(time_source
);
6166 hr
= IMFMediaSink_SetPresentationClock(sink
, present_clock
);
6167 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
6169 hr
= IMFMediaSink_GetPresentationClock(sink
, NULL
);
6170 ok(hr
== E_POINTER
, "Unexpected hr %#lx.\n", hr
);
6172 hr
= IMFMediaSink_GetPresentationClock(sink
, &present_clock2
);
6173 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
6174 ok(present_clock
== present_clock2
, "Unexpected instance.\n");
6175 IMFPresentationClock_Release(present_clock2
);
6178 hr
= IMFMediaSink_GetStreamSinkByIndex(sink
, 0, &stream_sink
);
6179 ok(hr
== S_OK
, "Failed to get a stream, hr %#lx.\n", hr
);
6181 check_interface(stream_sink
, &IID_IMFMediaEventGenerator
, TRUE
);
6182 check_interface(stream_sink
, &IID_IMFMediaTypeHandler
, TRUE
);
6183 todo_wine
check_interface(stream_sink
, &IID_IMFGetService
, TRUE
);
6185 hr
= IMFStreamSink_GetIdentifier(stream_sink
, &id
);
6186 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
6187 ok(!id
, "Unexpected id.\n");
6189 hr
= IMFStreamSink_GetMediaSink(stream_sink
, &sink2
);
6190 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
6191 ok(sink
== sink2
, "Unexpected object.\n");
6192 IMFMediaSink_Release(sink2
);
6194 hr
= IMFStreamSink_GetMediaTypeHandler(stream_sink
, &handler
);
6195 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
6197 hr
= IMFStreamSink_QueryInterface(stream_sink
, &IID_IMFMediaTypeHandler
, (void **)&handler2
);
6198 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
6199 ok(handler2
== handler
, "Unexpected instance.\n");
6200 IMFMediaTypeHandler_Release(handler2
);
6202 hr
= IMFMediaTypeHandler_GetMajorType(handler
, &guid
);
6203 ok(hr
== S_OK
, "Failed to get major type, hr %#lx.\n", hr
);
6204 ok(IsEqualGUID(&guid
, &MFMediaType_Audio
), "Unexpected type %s.\n", wine_dbgstr_guid(&guid
));
6207 hr
= IMFMediaTypeHandler_GetMediaTypeCount(handler
, &count
);
6208 ok(hr
== S_OK
, "Failed to get type count, hr %#lx.\n", hr
);
6209 ok(!!count
, "Unexpected type count %lu.\n", count
);
6211 hr
= IMFMediaTypeHandler_GetMediaTypeByIndex(handler
, count
, &mediatype
);
6212 ok(hr
== MF_E_NO_MORE_TYPES
, "Unexpected hr %#lx.\n", hr
);
6214 hr
= IMFMediaTypeHandler_GetCurrentMediaType(handler
, &mediatype
);
6215 ok(hr
== MF_E_NOT_INITIALIZED
, "Unexpected hr %#lx.\n", hr
);
6217 hr
= IMFMediaTypeHandler_GetMediaTypeByIndex(handler
, 0, &mediatype
);
6218 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
6219 hr
= IMFMediaType_GetUINT32(mediatype
, &MF_MT_AUDIO_SAMPLES_PER_SECOND
, &rate
);
6220 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
6221 ok(rate
== 48000 || rate
== 44100, "got rate %u.\n", rate
);
6222 IMFMediaType_Release(mediatype
);
6224 check_handler_required_attributes(handler
, rate
== 44100 ? input_type_desc_44100
: input_type_desc_48000
);
6226 hr
= IMFMediaTypeHandler_GetCurrentMediaType(handler
, &mediatype
);
6227 ok(hr
== MF_E_NOT_INITIALIZED
, "Unexpected hr %#lx.\n", hr
);
6229 hr
= MFCreateMediaType(&mediatype
);
6230 ok(hr
== S_OK
, "Failed to create media type, hr %#lx.\n", hr
);
6232 /* Actual return value is MF_E_ATRIBUTENOTFOUND triggered by missing MF_MT_MAJOR_TYPE */
6233 hr
= IMFMediaTypeHandler_IsMediaTypeSupported(handler
, mediatype
, NULL
);
6234 ok(FAILED(hr
), "Unexpected hr %#lx.\n", hr
);
6236 hr
= IMFMediaType_SetGUID(mediatype
, &MF_MT_MAJOR_TYPE
, &MFMediaType_Video
);
6237 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
6238 hr
= IMFMediaTypeHandler_IsMediaTypeSupported(handler
, mediatype
, NULL
);
6239 ok(hr
== MF_E_INVALIDMEDIATYPE
, "Unexpected hr %#lx.\n", hr
);
6241 hr
= IMFMediaType_SetGUID(mediatype
, &MF_MT_MAJOR_TYPE
, &MFMediaType_Audio
);
6242 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
6243 hr
= IMFMediaTypeHandler_IsMediaTypeSupported(handler
, mediatype
, NULL
);
6244 ok(hr
== MF_E_INVALIDMEDIATYPE
, "Unexpected hr %#lx.\n", hr
);
6246 hr
= IMFMediaTypeHandler_SetCurrentMediaType(handler
, mediatype
);
6247 ok(hr
== MF_E_INVALIDMEDIATYPE
, "Unexpected hr %#lx.\n", hr
);
6249 hr
= IMFMediaTypeHandler_GetMediaTypeByIndex(handler
, count
- 1, &mediatype2
);
6250 ok(hr
== S_OK
, "Failed to get media type, hr %#lx.\n", hr
);
6251 hr
= IMFMediaTypeHandler_GetMediaTypeByIndex(handler
, count
- 1, &mediatype3
);
6252 ok(hr
== S_OK
, "Failed to get media type, hr %#lx.\n", hr
);
6253 ok(mediatype2
== mediatype3
, "Unexpected instance.\n");
6254 IMFMediaType_Release(mediatype3
);
6256 hr
= IMFMediaTypeHandler_IsMediaTypeSupported(handler
, mediatype2
, NULL
);
6257 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
6259 IMFMediaType_Release(mediatype
);
6261 check_sar_rate_support(sink
);
6263 hr
= IMFMediaTypeHandler_SetCurrentMediaType(handler
, mediatype2
);
6264 ok(hr
== S_OK
, "Failed to set current type, hr %#lx.\n", hr
);
6266 check_sar_rate_support(sink
);
6268 hr
= IMFMediaTypeHandler_GetCurrentMediaType(handler
, &mediatype
);
6269 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
6270 ok(mediatype
== mediatype2
, "Unexpected instance.\n");
6271 IMFMediaType_Release(mediatype
);
6273 IMFMediaType_Release(mediatype2
);
6275 /* Reset back to uninitialized state. */
6276 hr
= IMFMediaTypeHandler_SetCurrentMediaType(handler
, NULL
);
6277 ok(hr
== E_POINTER
, "Unexpected hr %#lx.\n", hr
);
6279 IMFMediaTypeHandler_Release(handler
);
6281 /* State change with initialized stream. */
6282 hr
= IMFMediaSink_QueryInterface(sink
, &IID_IMFClockStateSink
, (void **)&state_sink
);
6283 ok(hr
== S_OK
, "Failed to get interface, hr %#lx.\n", hr
);
6285 hr
= IMFClockStateSink_OnClockStart(state_sink
, 0, 0);
6286 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
6288 hr
= IMFClockStateSink_OnClockStart(state_sink
, 0, 0);
6289 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
6291 hr
= IMFClockStateSink_OnClockPause(state_sink
, 0);
6292 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
6294 hr
= IMFClockStateSink_OnClockStop(state_sink
, 0);
6295 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
6297 hr
= IMFClockStateSink_OnClockStop(state_sink
, 0);
6298 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
6300 hr
= IMFClockStateSink_OnClockPause(state_sink
, 0);
6301 ok(hr
== MF_E_INVALID_STATE_TRANSITION
, "Unexpected hr %#lx.\n", hr
);
6303 hr
= IMFClockStateSink_OnClockRestart(state_sink
, 0);
6304 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
6306 hr
= IMFClockStateSink_OnClockRestart(state_sink
, 0);
6307 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
6309 hr
= IMFClockStateSink_OnClockStop(state_sink
, 0);
6310 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
6312 IMFClockStateSink_Release(state_sink
);
6314 IMFStreamSink_Release(stream_sink
);
6316 /* Volume control */
6317 hr
= MFGetService((IUnknown
*)sink
, &MR_POLICY_VOLUME_SERVICE
, &IID_IMFSimpleAudioVolume
, (void **)&simple_volume
);
6318 ok(hr
== S_OK
, "Failed to get interface, hr %#lx.\n", hr
);
6320 hr
= IMFSimpleAudioVolume_GetMute(simple_volume
, &mute
);
6321 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
6323 IMFSimpleAudioVolume_Release(simple_volume
);
6325 hr
= MFGetService((IUnknown
*)sink
, &MR_STREAM_VOLUME_SERVICE
, &IID_IMFAudioStreamVolume
, (void **)&stream_volume
);
6326 ok(hr
== S_OK
, "Failed to get interface, hr %#lx.\n", hr
);
6328 hr
= IMFAudioStreamVolume_GetChannelCount(stream_volume
, &channel_count
);
6329 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
6331 hr
= IMFAudioStreamVolume_GetChannelCount(stream_volume
, NULL
);
6332 ok(hr
== E_POINTER
, "Unexpected hr %#lx.\n", hr
);
6334 IMFAudioStreamVolume_Release(stream_volume
);
6336 hr
= MFGetService((IUnknown
*)sink
, &MR_AUDIO_POLICY_SERVICE
, &IID_IMFAudioPolicy
, (void **)&unk
);
6337 ok(hr
== S_OK
, "Failed to get interface, hr %#lx.\n", hr
);
6338 IUnknown_Release(unk
);
6341 EXPECT_REF(present_clock
, 2);
6342 hr
= IMFMediaSink_Shutdown(sink
);
6343 ok(hr
== S_OK
, "Failed to shut down, hr %#lx.\n", hr
);
6344 EXPECT_REF(present_clock
, 1);
6346 hr
= IMFMediaSink_Shutdown(sink
);
6347 ok(hr
== MF_E_SHUTDOWN
, "Unexpected hr %#lx.\n", hr
);
6349 hr
= IMFMediaSink_AddStreamSink(sink
, 123, NULL
, &stream_sink
);
6350 ok(hr
== MF_E_SHUTDOWN
, "Unexpected hr %#lx.\n", hr
);
6352 hr
= IMFMediaSink_RemoveStreamSink(sink
, 0);
6353 ok(hr
== MF_E_SHUTDOWN
, "Unexpected hr %#lx.\n", hr
);
6355 hr
= IMFMediaSink_GetStreamSinkCount(sink
, NULL
);
6356 ok(hr
== E_POINTER
, "Unexpected hr %#lx.\n", hr
);
6358 hr
= IMFMediaSink_GetStreamSinkCount(sink
, &count
);
6359 ok(hr
== MF_E_SHUTDOWN
, "Unexpected hr %#lx.\n", hr
);
6361 hr
= IMFMediaSink_GetCharacteristics(sink
, &flags
);
6362 ok(hr
== MF_E_SHUTDOWN
, "Unexpected hr %#lx.\n", hr
);
6364 hr
= IMFMediaSink_SetPresentationClock(sink
, NULL
);
6365 ok(hr
== MF_E_SHUTDOWN
, "Unexpected hr %#lx.\n", hr
);
6367 hr
= IMFMediaSink_SetPresentationClock(sink
, present_clock
);
6368 ok(hr
== MF_E_SHUTDOWN
, "Unexpected hr %#lx.\n", hr
);
6370 hr
= IMFMediaSink_GetPresentationClock(sink
, NULL
);
6371 ok(hr
== E_POINTER
, "Unexpected hr %#lx.\n", hr
);
6373 hr
= IMFMediaSink_GetPresentationClock(sink
, &present_clock2
);
6374 ok(hr
== MF_E_SHUTDOWN
, "Unexpected hr %#lx.\n", hr
);
6376 check_sar_rate_support(sink
);
6378 ref
= IMFMediaSink_Release(sink
);
6380 ok(ref
== 0, "Release returned %ld\n", ref
);
6383 hr
= MFCreateAudioRendererActivate(&activate
);
6384 ok(hr
== S_OK
, "Failed to create activation object, hr %#lx.\n", hr
);
6386 hr
= IMFActivate_ActivateObject(activate
, &IID_IMFMediaSink
, (void **)&sink
);
6387 ok(hr
== S_OK
, "Failed to activate, hr %#lx.\n", hr
);
6389 hr
= IMFActivate_ActivateObject(activate
, &IID_IMFMediaSink
, (void **)&sink2
);
6390 ok(hr
== S_OK
, "Failed to activate, hr %#lx.\n", hr
);
6391 ok(sink
== sink2
, "Unexpected instance.\n");
6392 IMFMediaSink_Release(sink2
);
6394 hr
= IMFMediaSink_GetCharacteristics(sink
, &flags
);
6395 ok(hr
== S_OK
, "Failed to get sink flags, hr %#lx.\n", hr
);
6397 hr
= IMFActivate_ShutdownObject(activate
);
6398 ok(hr
== S_OK
, "Failed to shut down, hr %#lx.\n", hr
);
6400 hr
= IMFMediaSink_GetCharacteristics(sink
, &flags
);
6401 ok(hr
== MF_E_SHUTDOWN
, "Unexpected hr %#lx.\n", hr
);
6403 hr
= IMFActivate_ActivateObject(activate
, &IID_IMFMediaSink
, (void **)&sink2
);
6404 ok(hr
== S_OK
, "Failed to activate, hr %#lx.\n", hr
);
6406 ok(sink
== sink2
, "Unexpected instance.\n");
6408 hr
= IMFMediaSink_GetCharacteristics(sink2
, &flags
);
6410 ok(hr
== MF_E_SHUTDOWN
, "Unexpected hr %#lx.\n", hr
);
6412 IMFMediaSink_Release(sink2
);
6414 hr
= IMFActivate_DetachObject(activate
);
6415 ok(hr
== E_NOTIMPL
, "Unexpected hr %#lx.\n", hr
);
6417 hr
= IMFActivate_ShutdownObject(activate
);
6418 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
6420 ref
= IMFActivate_Release(activate
);
6421 ok(ref
== 0, "Release returned %ld\n", ref
);
6422 ref
= IMFMediaSink_Release(sink
);
6423 ok(ref
== 0, "Release returned %ld\n", ref
);
6425 ref
= IMFPresentationClock_Release(present_clock
);
6426 ok(ref
== 0, "Release returned %ld\n", ref
);
6429 ok(hr
== S_OK
, "Shutdown failure, hr %#lx.\n", hr
);
6431 /* SAR attributes */
6432 hr
= MFCreateAttributes(&attributes
, 0);
6433 ok(hr
== S_OK
, "Failed to create attributes, hr %#lx.\n", hr
);
6436 hr
= IMFAttributes_SetUINT32(attributes
, &MF_AUDIO_RENDERER_ATTRIBUTE_ENDPOINT_ROLE
, eMultimedia
);
6437 ok(hr
== S_OK
, "Failed to set attribute, hr %#lx.\n", hr
);
6439 hr
= MFCreateAudioRenderer(attributes
, &sink
);
6440 ok(hr
== S_OK
, "Failed to create a sink, hr %#lx.\n", hr
);
6442 /* required for the sink to be fully released */
6443 hr
= IMFMediaSink_Shutdown(sink
);
6444 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
6446 ref
= IMFMediaSink_Release(sink
);
6447 ok(ref
== 0, "Release returned %ld\n", ref
);
6449 /* Invalid endpoint. */
6450 hr
= IMFAttributes_SetString(attributes
, &MF_AUDIO_RENDERER_ATTRIBUTE_ENDPOINT_ID
, L
"endpoint");
6451 ok(hr
== S_OK
, "Failed to set attribute, hr %#lx.\n", hr
);
6453 hr
= MFCreateAudioRenderer(attributes
, &sink
);
6454 ok(hr
== E_INVALIDARG
, "Unexpected hr %#lx.\n", hr
);
6456 hr
= IMFAttributes_DeleteItem(attributes
, &MF_AUDIO_RENDERER_ATTRIBUTE_ENDPOINT_ROLE
);
6457 ok(hr
== S_OK
, "Failed to remove attribute, hr %#lx.\n", hr
);
6459 hr
= MFCreateAudioRenderer(attributes
, &sink
);
6460 ok(hr
== MF_E_NO_AUDIO_PLAYBACK_DEVICE
, "Failed to create a sink, hr %#lx.\n", hr
);
6462 ref
= IMFAttributes_Release(attributes
);
6463 ok(ref
== 0, "Release returned %ld\n", ref
);
6468 static void test_evr(void)
6470 static const float supported_rates
[] =
6472 0.0f
, 1.0f
, -20.0f
, 20.0f
, 1000.0f
, -1000.0f
,
6474 IMFVideoSampleAllocatorCallback
*allocator_callback
;
6475 IMFStreamSink
*stream_sink
, *stream_sink2
;
6476 IMFVideoDisplayControl
*display_control
;
6477 IMFMediaType
*media_type
, *media_type2
;
6478 IMFPresentationTimeSource
*time_source
;
6479 IMFVideoSampleAllocator
*allocator
;
6480 IMFMediaTypeHandler
*type_handler
;
6481 IMFVideoRenderer
*video_renderer
;
6482 IMFPresentationClock
*clock
;
6483 IMFMediaSink
*sink
, *sink2
;
6484 IMFAttributes
*attributes
;
6485 UINT32 attr_count
, value
;
6486 IMFActivate
*activate
;
6487 HWND window
, window2
;
6499 hr
= MFStartup(MF_VERSION
, MFSTARTUP_FULL
);
6500 ok(hr
== S_OK
, "Startup failure, hr %#lx.\n", hr
);
6502 hr
= MFCreateVideoRenderer(&IID_IMFVideoRenderer
, (void **)&video_renderer
);
6505 skip("Failed to create video renderer object, skipping tests.\n");
6510 hr
= IMFVideoRenderer_InitializeRenderer(video_renderer
, NULL
, NULL
);
6511 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
6513 /* required for the video renderer to be fully released */
6514 hr
= IMFVideoRenderer_QueryInterface(video_renderer
, &IID_IMFMediaSink
, (void **)&sink
);
6515 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
6516 hr
= IMFMediaSink_Shutdown(sink
);
6517 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
6518 IMFMediaSink_Release(sink
);
6520 ref
= IMFVideoRenderer_Release(video_renderer
);
6521 ok(ref
== 0, "Release returned %ld\n", ref
);
6523 hr
= MFCreateVideoRendererActivate(NULL
, NULL
);
6524 ok(hr
== E_POINTER
, "Unexpected hr %#lx.\n", hr
);
6527 window
= create_window();
6528 hr
= MFCreateVideoRendererActivate(window
, &activate
);
6529 ok(hr
== S_OK
, "Failed to create activate object, hr %#lx.\n", hr
);
6531 hr
= IMFActivate_GetUINT64(activate
, &MF_ACTIVATE_VIDEO_WINDOW
, &window3
);
6532 ok(hr
== S_OK
, "Failed to get attribute, hr %#lx.\n", hr
);
6533 ok(UlongToHandle(window3
) == window
, "Unexpected value.\n");
6535 hr
= IMFActivate_ActivateObject(activate
, &IID_IMFMediaSink
, (void **)&sink
);
6536 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
6538 check_interface(sink
, &IID_IMFMediaSinkPreroll
, TRUE
);
6539 check_interface(sink
, &IID_IMFVideoRenderer
, TRUE
);
6540 check_interface(sink
, &IID_IMFMediaEventGenerator
, TRUE
);
6541 check_interface(sink
, &IID_IMFClockStateSink
, TRUE
);
6542 check_interface(sink
, &IID_IMFGetService
, TRUE
);
6543 check_interface(sink
, &IID_IMFQualityAdvise
, TRUE
);
6544 check_interface(sink
, &IID_IMFRateSupport
, TRUE
);
6545 check_interface(sink
, &IID_IMFRateControl
, FALSE
);
6546 check_service_interface(sink
, &MR_VIDEO_MIXER_SERVICE
, &IID_IMFVideoProcessor
, TRUE
);
6547 check_service_interface(sink
, &MR_VIDEO_MIXER_SERVICE
, &IID_IMFVideoMixerBitmap
, TRUE
);
6548 check_service_interface(sink
, &MR_VIDEO_MIXER_SERVICE
, &IID_IMFVideoMixerControl
, TRUE
);
6549 check_service_interface(sink
, &MR_VIDEO_MIXER_SERVICE
, &IID_IMFVideoMixerControl2
, TRUE
);
6550 check_service_interface(sink
, &MR_VIDEO_RENDER_SERVICE
, &IID_IMFVideoDisplayControl
, TRUE
);
6551 check_service_interface(sink
, &MR_VIDEO_RENDER_SERVICE
, &IID_IMFVideoPositionMapper
, TRUE
);
6552 check_service_interface(sink
, &MR_VIDEO_ACCELERATION_SERVICE
, &IID_IMFVideoSampleAllocator
, FALSE
);
6553 check_service_interface(sink
, &MR_VIDEO_ACCELERATION_SERVICE
, &IID_IDirect3DDeviceManager9
, TRUE
);
6554 check_service_interface(sink
, &MF_RATE_CONTROL_SERVICE
, &IID_IMFRateSupport
, TRUE
);
6556 hr
= MFGetService((IUnknown
*)sink
, &MR_VIDEO_RENDER_SERVICE
, &IID_IMFVideoDisplayControl
,
6557 (void **)&display_control
);
6558 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
6561 hr
= IMFVideoDisplayControl_GetVideoWindow(display_control
, &window2
);
6562 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
6563 ok(window2
== window
, "Unexpected window %p.\n", window2
);
6565 IMFVideoDisplayControl_Release(display_control
);
6567 hr
= IMFActivate_ShutdownObject(activate
);
6568 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
6570 ref
= IMFActivate_Release(activate
);
6571 ok(ref
== 0, "Release returned %ld\n", ref
);
6572 ref
= IMFMediaSink_Release(sink
);
6573 ok(ref
== 0, "Release returned %ld\n", ref
);
6574 DestroyWindow(window
);
6576 hr
= MFCreateVideoRendererActivate(NULL
, &activate
);
6577 ok(hr
== S_OK
, "Failed to create activate object, hr %#lx.\n", hr
);
6579 hr
= IMFActivate_GetCount(activate
, &attr_count
);
6580 ok(hr
== S_OK
, "Failed to get attribute count, hr %#lx.\n", hr
);
6581 ok(attr_count
== 1, "Unexpected count %u.\n", attr_count
);
6583 hr
= IMFActivate_GetUINT64(activate
, &MF_ACTIVATE_VIDEO_WINDOW
, &window3
);
6584 ok(hr
== S_OK
, "Failed to get attribute, hr %#lx.\n", hr
);
6585 ok(!window3
, "Unexpected value.\n");
6587 hr
= IMFActivate_ActivateObject(activate
, &IID_IMFMediaSink
, (void **)&sink
);
6588 ok(hr
== S_OK
, "Failed to activate, hr %#lx.\n", hr
);
6590 hr
= IMFMediaSink_QueryInterface(sink
, &IID_IMFAttributes
, (void **)&attributes
);
6591 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
6592 check_interface(attributes
, &IID_IMFMediaSink
, TRUE
);
6594 hr
= IMFAttributes_GetCount(attributes
, &attr_count
);
6595 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
6596 ok(!!attr_count
, "Unexpected count %u.\n", attr_count
);
6597 /* Rendering preferences are not immediately propagated to the presenter. */
6598 hr
= IMFAttributes_SetUINT32(attributes
, &EVRConfig_ForceBob
, 1);
6599 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
6600 hr
= MFGetService((IUnknown
*)sink
, &MR_VIDEO_RENDER_SERVICE
, &IID_IMFVideoDisplayControl
, (void **)&display_control
);
6601 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
6602 hr
= IMFVideoDisplayControl_GetRenderingPrefs(display_control
, &flags
);
6603 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
6604 ok(!flags
, "Unexpected flags %#lx.\n", flags
);
6605 IMFVideoDisplayControl_Release(display_control
);
6606 IMFAttributes_Release(attributes
);
6608 /* Primary stream type handler. */
6609 hr
= IMFMediaSink_GetStreamSinkById(sink
, 0, &stream_sink
);
6610 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
6612 hr
= IMFStreamSink_QueryInterface(stream_sink
, &IID_IMFAttributes
, (void **)&attributes
);
6613 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
6614 hr
= IMFAttributes_GetCount(attributes
, &attr_count
);
6615 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
6616 ok(attr_count
== 2, "Unexpected count %u.\n", attr_count
);
6618 hr
= IMFAttributes_GetUINT32(attributes
, &MF_SA_REQUIRED_SAMPLE_COUNT
, &value
);
6619 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
6620 ok(value
== 1, "Unexpected attribute value %u.\n", value
);
6622 hr
= IMFAttributes_GetUINT32(attributes
, &MF_SA_D3D_AWARE
, &value
);
6623 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
6624 ok(value
== 1, "Unexpected attribute value %u.\n", value
);
6626 check_interface(attributes
, &IID_IMFStreamSink
, TRUE
);
6627 IMFAttributes_Release(attributes
);
6629 hr
= IMFStreamSink_GetMediaTypeHandler(stream_sink
, &type_handler
);
6630 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
6632 hr
= IMFMediaTypeHandler_GetMajorType(type_handler
, NULL
);
6633 ok(hr
== E_POINTER
, "Unexpected hr %#lx.\n", hr
);
6635 hr
= IMFMediaTypeHandler_GetMajorType(type_handler
, &guid
);
6636 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
6637 ok(IsEqualGUID(&guid
, &MFMediaType_Video
), "Unexpected type %s.\n", wine_dbgstr_guid(&guid
));
6639 /* Supported types are not advertised. */
6640 hr
= IMFMediaTypeHandler_GetMediaTypeCount(type_handler
, NULL
);
6641 ok(hr
== E_POINTER
, "Unexpected hr %#lx.\n", hr
);
6644 hr
= IMFMediaTypeHandler_GetMediaTypeCount(type_handler
, &count
);
6645 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
6646 ok(!count
, "Unexpected count %lu.\n", count
);
6648 hr
= IMFMediaTypeHandler_GetMediaTypeByIndex(type_handler
, 0, NULL
);
6649 ok(hr
== MF_E_NO_MORE_TYPES
, "Unexpected hr %#lx.\n", hr
);
6651 hr
= IMFMediaTypeHandler_GetMediaTypeByIndex(type_handler
, 0, &media_type
);
6652 ok(hr
== MF_E_NO_MORE_TYPES
, "Unexpected hr %#lx.\n", hr
);
6654 hr
= IMFMediaTypeHandler_GetCurrentMediaType(type_handler
, NULL
);
6655 ok(hr
== E_POINTER
, "Unexpected hr %#lx.\n", hr
);
6657 hr
= IMFMediaTypeHandler_GetCurrentMediaType(type_handler
, &media_type
);
6658 ok(hr
== MF_E_TRANSFORM_TYPE_NOT_SET
, "Unexpected hr %#lx.\n", hr
);
6660 hr
= IMFMediaTypeHandler_SetCurrentMediaType(type_handler
, NULL
);
6661 ok(hr
== E_POINTER
, "Unexpected hr %#lx.\n", hr
);
6663 hr
= MFCreateMediaType(&media_type
);
6664 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
6666 hr
= IMFMediaType_SetGUID(media_type
, &MF_MT_MAJOR_TYPE
, &MFMediaType_Video
);
6667 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
6669 hr
= IMFMediaType_SetGUID(media_type
, &MF_MT_SUBTYPE
, &MFVideoFormat_RGB32
);
6670 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
6672 hr
= IMFMediaType_SetUINT64(media_type
, &MF_MT_FRAME_SIZE
, (UINT64
)640 << 32 | 480);
6673 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
6675 hr
= IMFMediaTypeHandler_IsMediaTypeSupported(type_handler
, NULL
, NULL
);
6676 ok(hr
== E_POINTER
, "Unexpected hr %#lx.\n", hr
);
6678 hr
= IMFMediaTypeHandler_IsMediaTypeSupported(type_handler
, media_type
, &media_type2
);
6679 ok(hr
== MF_E_INVALIDMEDIATYPE
, "Unexpected hr %#lx.\n", hr
);
6681 hr
= IMFMediaType_SetUINT32(media_type
, &MF_MT_ALL_SAMPLES_INDEPENDENT
, TRUE
);
6682 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
6684 media_type2
= (void *)0x1;
6685 hr
= IMFMediaTypeHandler_IsMediaTypeSupported(type_handler
, media_type
, &media_type2
);
6686 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
6687 ok(!media_type2
, "Unexpected media type %p.\n", media_type2
);
6689 hr
= IMFMediaTypeHandler_SetCurrentMediaType(type_handler
, media_type
);
6690 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
6692 hr
= IMFMediaTypeHandler_GetCurrentMediaType(type_handler
, &media_type2
);
6693 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
6694 check_interface(media_type2
, &IID_IMFVideoMediaType
, TRUE
);
6695 IMFMediaType_Release(media_type2
);
6697 IMFMediaType_Release(media_type
);
6699 IMFMediaTypeHandler_Release(type_handler
);
6701 /* Stream uses an allocator. */
6702 check_service_interface(stream_sink
, &MR_VIDEO_ACCELERATION_SERVICE
, &IID_IMFVideoSampleAllocator
, TRUE
);
6703 check_service_interface(stream_sink
, &MR_VIDEO_ACCELERATION_SERVICE
, &IID_IDirect3DDeviceManager9
, TRUE
);
6705 check_service_interface(stream_sink
, &MR_VIDEO_MIXER_SERVICE
, &IID_IMFVideoProcessor
, TRUE
);
6706 check_service_interface(stream_sink
, &MR_VIDEO_MIXER_SERVICE
, &IID_IMFVideoMixerBitmap
, TRUE
);
6707 check_service_interface(stream_sink
, &MR_VIDEO_MIXER_SERVICE
, &IID_IMFVideoMixerControl
, TRUE
);
6708 check_service_interface(stream_sink
, &MR_VIDEO_MIXER_SERVICE
, &IID_IMFVideoMixerControl2
, TRUE
);
6709 check_service_interface(stream_sink
, &MR_VIDEO_RENDER_SERVICE
, &IID_IMFVideoDisplayControl
, TRUE
);
6710 check_service_interface(stream_sink
, &MR_VIDEO_RENDER_SERVICE
, &IID_IMFVideoPositionMapper
, TRUE
);
6711 check_service_interface(stream_sink
, &MF_RATE_CONTROL_SERVICE
, &IID_IMFRateSupport
, TRUE
);
6713 hr
= MFGetService((IUnknown
*)stream_sink
, &MR_VIDEO_ACCELERATION_SERVICE
, &IID_IMFVideoSampleAllocator
,
6714 (void **)&allocator
);
6715 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
6717 hr
= IMFVideoSampleAllocator_QueryInterface(allocator
, &IID_IMFVideoSampleAllocatorCallback
, (void **)&allocator_callback
);
6718 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
6721 hr
= IMFVideoSampleAllocatorCallback_GetFreeSampleCount(allocator_callback
, &sample_count
);
6722 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
6723 ok(!sample_count
, "Unexpected sample count %ld.\n", sample_count
);
6725 hr
= IMFVideoSampleAllocator_AllocateSample(allocator
, &sample
);
6726 ok(hr
== MF_E_NOT_INITIALIZED
, "Unexpected hr %#lx.\n", hr
);
6728 IMFVideoSampleAllocatorCallback_Release(allocator_callback
);
6729 IMFVideoSampleAllocator_Release(allocator
);
6730 IMFStreamSink_Release(stream_sink
);
6732 /* Same test for a substream. */
6733 hr
= IMFMediaSink_AddStreamSink(sink
, 1, NULL
, &stream_sink2
);
6734 ok(hr
== S_OK
|| broken(hr
== E_INVALIDARG
), "Unexpected hr %#lx.\n", hr
);
6738 hr
= MFGetService((IUnknown
*)stream_sink2
, &MR_VIDEO_ACCELERATION_SERVICE
, &IID_IMFVideoSampleAllocator
,
6739 (void **)&allocator
);
6740 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
6741 IMFVideoSampleAllocator_Release(allocator
);
6743 hr
= IMFMediaSink_RemoveStreamSink(sink
, 1);
6744 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
6746 ref
= IMFStreamSink_Release(stream_sink2
);
6747 ok(ref
== 0, "Release returned %ld\n", ref
);
6750 hr
= IMFMediaSink_GetCharacteristics(sink
, &flags
);
6751 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
6752 ok(flags
== (MEDIASINK_CAN_PREROLL
| MEDIASINK_CLOCK_REQUIRED
), "Unexpected flags %#lx.\n", flags
);
6754 hr
= IMFActivate_ShutdownObject(activate
);
6755 ok(hr
== S_OK
, "Failed to shut down, hr %#lx.\n", hr
);
6757 hr
= IMFMediaSink_GetCharacteristics(sink
, &flags
);
6758 ok(hr
== MF_E_SHUTDOWN
, "Unexpected hr %#lx.\n", hr
);
6760 /* Activate again. */
6761 hr
= IMFActivate_ActivateObject(activate
, &IID_IMFMediaSink
, (void **)&sink2
);
6762 ok(hr
== S_OK
, "Failed to activate, hr %#lx.\n", hr
);
6764 ok(sink
== sink2
, "Unexpected instance.\n");
6765 IMFMediaSink_Release(sink2
);
6767 hr
= IMFActivate_DetachObject(activate
);
6768 ok(hr
== E_NOTIMPL
, "Unexpected hr %#lx.\n", hr
);
6770 hr
= IMFMediaSink_GetCharacteristics(sink
, &flags
);
6771 ok(hr
== MF_E_SHUTDOWN
, "Unexpected hr %#lx.\n", hr
);
6773 hr
= IMFActivate_ActivateObject(activate
, &IID_IMFMediaSink
, (void **)&sink2
);
6774 ok(hr
== S_OK
, "Failed to activate, hr %#lx.\n", hr
);
6776 ok(sink
== sink2
, "Unexpected instance.\n");
6777 IMFMediaSink_Release(sink2
);
6779 hr
= IMFActivate_ShutdownObject(activate
);
6780 ok(hr
== S_OK
, "Failed to shut down, hr %#lx.\n", hr
);
6782 ref
= IMFActivate_Release(activate
);
6783 ok(ref
== 0, "Release returned %ld\n", ref
);
6784 ref
= IMFMediaSink_Release(sink
);
6786 ok(ref
== 0, "Release returned %ld\n", ref
);
6789 window
= create_window();
6791 hr
= MFCreateVideoRendererActivate(window
, &activate
);
6792 ok(hr
== S_OK
, "Failed to create activate object, hr %#lx.\n", hr
);
6794 hr
= IMFActivate_ActivateObject(activate
, &IID_IMFMediaSink
, (void **)&sink
);
6795 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
6796 ref
= IMFActivate_Release(activate
);
6797 ok(ref
== 0, "Release returned %ld\n", ref
);
6799 hr
= MFCreateSystemTimeSource(&time_source
);
6800 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
6802 hr
= MFCreatePresentationClock(&clock
);
6803 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
6805 hr
= IMFPresentationClock_SetTimeSource(clock
, time_source
);
6806 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
6807 IMFPresentationTimeSource_Release(time_source
);
6809 hr
= IMFMediaSink_SetPresentationClock(sink
, clock
);
6810 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
6812 hr
= IMFMediaSink_QueryInterface(sink
, &IID_IMFRateSupport
, (void **)&rs
);
6813 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
6816 hr
= IMFRateSupport_GetSlowestRate(rs
, MFRATE_FORWARD
, FALSE
, &rate
);
6817 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
6818 ok(rate
== 0.0f
, "Unexpected rate %f.\n", rate
);
6821 hr
= IMFRateSupport_GetSlowestRate(rs
, MFRATE_REVERSE
, FALSE
, &rate
);
6822 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
6823 ok(rate
== 0.0f
, "Unexpected rate %f.\n", rate
);
6826 hr
= IMFRateSupport_GetSlowestRate(rs
, MFRATE_FORWARD
, TRUE
, &rate
);
6827 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
6828 ok(rate
== 0.0f
, "Unexpected rate %f.\n", rate
);
6831 hr
= IMFRateSupport_GetSlowestRate(rs
, MFRATE_REVERSE
, TRUE
, &rate
);
6832 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
6833 ok(rate
== 0.0f
, "Unexpected rate %f.\n", rate
);
6835 hr
= IMFRateSupport_GetFastestRate(rs
, MFRATE_FORWARD
, FALSE
, &rate
);
6836 ok(hr
== MF_E_INVALIDREQUEST
, "Unexpected hr %#lx.\n", hr
);
6838 hr
= IMFRateSupport_GetFastestRate(rs
, MFRATE_REVERSE
, FALSE
, &rate
);
6839 ok(hr
== MF_E_INVALIDREQUEST
, "Unexpected hr %#lx.\n", hr
);
6841 hr
= IMFRateSupport_GetFastestRate(rs
, MFRATE_FORWARD
, TRUE
, &rate
);
6842 ok(hr
== MF_E_INVALIDREQUEST
, "Unexpected hr %#lx.\n", hr
);
6844 hr
= IMFRateSupport_GetFastestRate(rs
, MFRATE_REVERSE
, TRUE
, &rate
);
6845 ok(hr
== MF_E_INVALIDREQUEST
, "Unexpected hr %#lx.\n", hr
);
6847 hr
= IMFRateSupport_GetFastestRate(rs
, MFRATE_REVERSE
, TRUE
, NULL
);
6848 ok(hr
== E_POINTER
, "Unexpected hr %#lx.\n", hr
);
6850 for (i
= 0; i
< ARRAY_SIZE(supported_rates
); ++i
)
6852 rate
= supported_rates
[i
] + 1.0f
;
6853 hr
= IMFRateSupport_IsRateSupported(rs
, TRUE
, supported_rates
[i
], &rate
);
6854 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
6855 ok(rate
== supported_rates
[i
], "Unexpected rate %f.\n", rate
);
6857 rate
= supported_rates
[i
] + 1.0f
;
6858 hr
= IMFRateSupport_IsRateSupported(rs
, FALSE
, supported_rates
[i
], &rate
);
6859 ok(hr
== MF_E_INVALIDREQUEST
, "Unexpected hr %#lx.\n", hr
);
6860 ok(rate
== supported_rates
[i
], "Unexpected rate %f.\n", rate
);
6862 hr
= IMFRateSupport_IsRateSupported(rs
, TRUE
, supported_rates
[i
], NULL
);
6863 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
6865 hr
= IMFRateSupport_IsRateSupported(rs
, FALSE
, supported_rates
[i
], NULL
);
6866 ok(hr
== MF_E_INVALIDREQUEST
, "Unexpected hr %#lx.\n", hr
);
6869 /* Configuring stream type make rate support work. */
6870 hr
= IMFMediaSink_GetStreamSinkById(sink
, 0, &stream_sink
);
6871 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
6872 hr
= IMFStreamSink_GetMediaTypeHandler(stream_sink
, &type_handler
);
6873 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
6874 hr
= MFCreateMediaType(&media_type
);
6875 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
6876 hr
= IMFMediaType_SetGUID(media_type
, &MF_MT_MAJOR_TYPE
, &MFMediaType_Video
);
6877 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
6878 hr
= IMFMediaType_SetGUID(media_type
, &MF_MT_SUBTYPE
, &MFVideoFormat_RGB32
);
6879 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
6880 hr
= IMFMediaType_SetUINT64(media_type
, &MF_MT_FRAME_SIZE
, (UINT64
)64 << 32 | 64);
6881 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
6882 hr
= IMFMediaType_SetUINT32(media_type
, &MF_MT_ALL_SAMPLES_INDEPENDENT
, TRUE
);
6883 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
6884 hr
= IMFMediaTypeHandler_SetCurrentMediaType(type_handler
, media_type
);
6885 ok(hr
== S_OK
, "Failed to set current type, hr %#lx.\n", hr
);
6886 IMFMediaType_Release(media_type
);
6887 IMFMediaTypeHandler_Release(type_handler
);
6888 IMFStreamSink_Release(stream_sink
);
6891 hr
= IMFRateSupport_GetSlowestRate(rs
, MFRATE_FORWARD
, TRUE
, &rate
);
6892 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
6893 ok(rate
== 0.0f
, "Unexpected rate %f.\n", rate
);
6896 hr
= IMFRateSupport_GetSlowestRate(rs
, MFRATE_REVERSE
, TRUE
, &rate
);
6897 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
6898 ok(rate
== 0.0f
, "Unexpected rate %f.\n", rate
);
6901 hr
= IMFRateSupport_GetFastestRate(rs
, MFRATE_FORWARD
, TRUE
, &rate
);
6902 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
6903 ok(rate
== FLT_MAX
, "Unexpected rate %f.\n", rate
);
6906 hr
= IMFRateSupport_GetFastestRate(rs
, MFRATE_REVERSE
, TRUE
, &rate
);
6907 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
6908 ok(rate
== -FLT_MAX
, "Unexpected rate %f.\n", rate
);
6910 hr
= IMFRateSupport_GetFastestRate(rs
, MFRATE_REVERSE
, TRUE
, NULL
);
6911 ok(hr
== E_POINTER
, "Unexpected hr %#lx.\n", hr
);
6913 hr
= IMFRateSupport_GetSlowestRate(rs
, MFRATE_REVERSE
, TRUE
, NULL
);
6914 ok(hr
== E_POINTER
, "Unexpected hr %#lx.\n", hr
);
6916 for (i
= 0; i
< ARRAY_SIZE(supported_rates
); ++i
)
6918 rate
= supported_rates
[i
] + 1.0f
;
6919 hr
= IMFRateSupport_IsRateSupported(rs
, TRUE
, supported_rates
[i
], &rate
);
6920 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
6921 ok(rate
== supported_rates
[i
], "Unexpected rate %f.\n", rate
);
6923 rate
= supported_rates
[i
] + 1.0f
;
6924 hr
= IMFRateSupport_IsRateSupported(rs
, FALSE
, supported_rates
[i
], &rate
);
6925 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
6926 ok(rate
== supported_rates
[i
], "Unexpected rate %f.\n", rate
);
6928 hr
= IMFRateSupport_IsRateSupported(rs
, TRUE
, supported_rates
[i
], NULL
);
6929 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
6931 hr
= IMFRateSupport_IsRateSupported(rs
, FALSE
, supported_rates
[i
], NULL
);
6932 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
6935 hr
= IMFMediaSink_Shutdown(sink
);
6936 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
6938 hr
= IMFMediaSink_GetStreamSinkCount(sink
, NULL
);
6939 ok(hr
== MF_E_SHUTDOWN
, "Unexpected hr %#lx.\n", hr
);
6941 hr
= IMFMediaSink_GetStreamSinkCount(sink
, &count
);
6942 ok(hr
== MF_E_SHUTDOWN
, "Unexpected hr %#lx.\n", hr
);
6944 hr
= IMFRateSupport_GetSlowestRate(rs
, MFRATE_FORWARD
, FALSE
, &rate
);
6945 ok(hr
== MF_E_SHUTDOWN
, "Unexpected hr %#lx.\n", hr
);
6947 hr
= IMFRateSupport_GetFastestRate(rs
, MFRATE_FORWARD
, FALSE
, &rate
);
6948 ok(hr
== MF_E_SHUTDOWN
, "Unexpected hr %#lx.\n", hr
);
6950 hr
= IMFRateSupport_GetSlowestRate(rs
, MFRATE_FORWARD
, FALSE
, NULL
);
6951 ok(hr
== MF_E_SHUTDOWN
, "Unexpected hr %#lx.\n", hr
);
6953 hr
= IMFRateSupport_GetFastestRate(rs
, MFRATE_FORWARD
, FALSE
, NULL
);
6954 ok(hr
== MF_E_SHUTDOWN
, "Unexpected hr %#lx.\n", hr
);
6956 hr
= IMFRateSupport_IsRateSupported(rs
, TRUE
, 1.0f
, &rate
);
6957 ok(hr
== MF_E_SHUTDOWN
, "Unexpected hr %#lx.\n", hr
);
6959 ref
= IMFRateSupport_Release(rs
);
6960 ok(ref
== 1, "Release returned %ld\n", ref
);
6961 ref
= IMFMediaSink_Release(sink
);
6962 ok(ref
== 0, "Release returned %ld\n", ref
);
6963 ref
= IMFPresentationClock_Release(clock
);
6964 ok(ref
== 0, "Release returned %ld\n", ref
);
6966 DestroyWindow(window
);
6969 ok(hr
== S_OK
, "Shutdown failure, hr %#lx.\n", hr
);
6972 static void test_MFCreateSimpleTypeHandler(void)
6974 IMFMediaType
*media_type
, *media_type2
, *media_type3
;
6975 IMFMediaTypeHandler
*handler
;
6981 hr
= MFCreateSimpleTypeHandler(&handler
);
6982 ok(hr
== S_OK
, "Failed to create object, hr %#lx.\n", hr
);
6984 hr
= IMFMediaTypeHandler_GetMediaTypeCount(handler
, NULL
);
6985 ok(hr
== E_POINTER
, "Unexpected hr %#lx.\n", hr
);
6987 hr
= IMFMediaTypeHandler_IsMediaTypeSupported(handler
, NULL
, NULL
);
6988 ok(hr
== MF_E_UNEXPECTED
, "Unexpected hr %#lx.\n", hr
);
6991 hr
= IMFMediaTypeHandler_GetMediaTypeCount(handler
, &count
);
6992 ok(hr
== S_OK
, "Failed to get type count, hr %#lx.\n", hr
);
6993 ok(count
== 1, "Unexpected count %lu.\n", count
);
6995 hr
= IMFMediaTypeHandler_GetCurrentMediaType(handler
, NULL
);
6996 ok(hr
== E_POINTER
, "Unexpected hr %#lx.\n", hr
);
6998 media_type
= (void *)0xdeadbeef;
6999 hr
= IMFMediaTypeHandler_GetCurrentMediaType(handler
, &media_type
);
7000 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
7001 ok(!media_type
, "Unexpected pointer.\n");
7003 hr
= MFCreateMediaType(&media_type
);
7004 ok(hr
== S_OK
, "Failed to create media type, hr %#lx.\n", hr
);
7006 hr
= IMFMediaTypeHandler_IsMediaTypeSupported(handler
, media_type
, NULL
);
7007 ok(hr
== MF_E_UNEXPECTED
, "Unexpected hr %#lx.\n", hr
);
7009 hr
= IMFMediaTypeHandler_SetCurrentMediaType(handler
, media_type
);
7010 ok(hr
== S_OK
, "Failed to set current type, hr %#lx.\n", hr
);
7012 hr
= IMFMediaTypeHandler_GetMediaTypeByIndex(handler
, 0, &media_type2
);
7013 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
7014 ok(media_type2
== media_type
, "Unexpected type.\n");
7015 IMFMediaType_Release(media_type2
);
7017 hr
= IMFMediaTypeHandler_IsMediaTypeSupported(handler
, NULL
, NULL
);
7018 ok(hr
== E_INVALIDARG
, "Unexpected hr %#lx.\n", hr
);
7020 hr
= IMFMediaTypeHandler_IsMediaTypeSupported(handler
, media_type
, NULL
);
7021 ok(hr
== E_INVALIDARG
, "Unexpected hr %#lx.\n", hr
);
7023 hr
= IMFMediaTypeHandler_IsMediaTypeSupported(handler
, media_type
, &media_type2
);
7024 ok(hr
== E_INVALIDARG
, "Unexpected hr %#lx.\n", hr
);
7026 hr
= IMFMediaTypeHandler_GetMediaTypeByIndex(handler
, 1, &media_type2
);
7027 ok(hr
== MF_E_NO_MORE_TYPES
, "Unexpected hr %#lx.\n", hr
);
7029 hr
= IMFMediaTypeHandler_GetCurrentMediaType(handler
, &media_type2
);
7030 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
7031 ok(media_type
== media_type2
, "Unexpected pointer.\n");
7032 IMFMediaType_Release(media_type2
);
7034 hr
= IMFMediaTypeHandler_GetMajorType(handler
, &guid
);
7035 ok(hr
== MF_E_ATTRIBUTENOTFOUND
, "Unexpected hr %#lx.\n", hr
);
7037 hr
= IMFMediaType_SetGUID(media_type
, &MF_MT_MAJOR_TYPE
, &MFMediaType_Video
);
7038 ok(hr
== S_OK
, "Failed to set attribute, hr %#lx.\n", hr
);
7040 hr
= IMFMediaTypeHandler_GetMajorType(handler
, &guid
);
7041 ok(hr
== S_OK
, "Failed to get major type, hr %#lx.\n", hr
);
7042 ok(IsEqualGUID(&guid
, &MFMediaType_Video
), "Unexpected major type.\n");
7044 hr
= MFCreateMediaType(&media_type3
);
7045 ok(hr
== S_OK
, "Failed to create media type, hr %#lx.\n", hr
);
7047 hr
= IMFMediaTypeHandler_IsMediaTypeSupported(handler
, media_type3
, NULL
);
7048 ok(hr
== E_INVALIDARG
, "Unexpected hr %#lx.\n", hr
);
7050 hr
= IMFMediaType_SetGUID(media_type3
, &MF_MT_MAJOR_TYPE
, &MFMediaType_Audio
);
7051 ok(hr
== S_OK
, "Failed to set attribute, hr %#lx.\n", hr
);
7053 /* Different major types. */
7054 media_type2
= (void *)0xdeadbeef;
7055 hr
= IMFMediaTypeHandler_IsMediaTypeSupported(handler
, media_type3
, &media_type2
);
7056 ok(hr
== E_FAIL
, "Unexpected hr %#lx.\n", hr
);
7057 ok(!media_type2
, "Unexpected pointer.\n");
7059 hr
= IMFMediaType_SetGUID(media_type3
, &MF_MT_MAJOR_TYPE
, &MFMediaType_Video
);
7060 ok(hr
== S_OK
, "Failed to set attribute, hr %#lx.\n", hr
);
7062 media_type2
= (void *)0xdeadbeef;
7063 hr
= IMFMediaTypeHandler_IsMediaTypeSupported(handler
, media_type3
, &media_type2
);
7064 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
7065 ok(!media_type2
, "Unexpected pointer.\n");
7067 /* Handler missing subtype. */
7068 hr
= IMFMediaType_SetGUID(media_type3
, &MF_MT_SUBTYPE
, &MFVideoFormat_RGB8
);
7069 ok(hr
== S_OK
, "Failed to set attribute, hr %#lx.\n", hr
);
7071 media_type2
= (void *)0xdeadbeef;
7072 hr
= IMFMediaTypeHandler_IsMediaTypeSupported(handler
, media_type3
, &media_type2
);
7073 ok(hr
== E_FAIL
, "Unexpected hr %#lx.\n", hr
);
7074 ok(!media_type2
, "Unexpected pointer.\n");
7076 /* Different subtypes. */
7077 hr
= IMFMediaType_SetGUID(media_type
, &MF_MT_SUBTYPE
, &MFVideoFormat_RGB24
);
7078 ok(hr
== S_OK
, "Failed to set attribute, hr %#lx.\n", hr
);
7080 media_type2
= (void *)0xdeadbeef;
7081 hr
= IMFMediaTypeHandler_IsMediaTypeSupported(handler
, media_type3
, &media_type2
);
7082 ok(hr
== E_FAIL
, "Unexpected hr %#lx.\n", hr
);
7083 ok(!media_type2
, "Unexpected pointer.\n");
7085 /* Same major/subtype. */
7086 hr
= IMFMediaType_SetGUID(media_type3
, &MF_MT_SUBTYPE
, &MFVideoFormat_RGB24
);
7087 ok(hr
== S_OK
, "Failed to set attribute, hr %#lx.\n", hr
);
7089 media_type2
= (void *)0xdeadbeef;
7090 hr
= IMFMediaTypeHandler_IsMediaTypeSupported(handler
, media_type3
, &media_type2
);
7091 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
7092 ok(!media_type2
, "Unexpected pointer.\n");
7094 /* Set one more attribute. */
7095 hr
= IMFMediaType_SetUINT64(media_type
, &MF_MT_FRAME_SIZE
, (UINT64
)4 << 32 | 4);
7096 ok(hr
== S_OK
, "Failed to set attribute, hr %#lx.\n", hr
);
7098 media_type2
= (void *)0xdeadbeef;
7099 hr
= IMFMediaTypeHandler_IsMediaTypeSupported(handler
, media_type3
, &media_type2
);
7100 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
7101 ok(!media_type2
, "Unexpected pointer.\n");
7103 ref
= IMFMediaType_Release(media_type3
);
7104 ok(ref
== 0, "Release returned %ld\n", ref
);
7106 hr
= IMFMediaTypeHandler_SetCurrentMediaType(handler
, NULL
);
7107 ok(hr
== S_OK
, "Failed to set current type, hr %#lx.\n", hr
);
7109 media_type2
= (void *)0xdeadbeef;
7110 hr
= IMFMediaTypeHandler_GetCurrentMediaType(handler
, &media_type2
);
7111 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
7112 ok(!media_type2
, "Unexpected pointer.\n");
7114 hr
= IMFMediaTypeHandler_GetMajorType(handler
, &guid
);
7115 ok(hr
== MF_E_NOT_INITIALIZED
, "Unexpected hr %#lx.\n", hr
);
7117 ref
= IMFMediaTypeHandler_Release(handler
);
7118 ok(ref
== 0, "Release returned %ld\n", ref
);
7119 ref
= IMFMediaType_Release(media_type
);
7120 ok(ref
== 0, "Release returned %ld\n", ref
);
7123 static void test_MFGetSupportedMimeTypes(void)
7128 hr
= MFGetSupportedMimeTypes(NULL
);
7129 ok(hr
== E_POINTER
, "Unexpected hr %#lx.\n", hr
);
7131 value
.vt
= VT_EMPTY
;
7132 hr
= MFGetSupportedMimeTypes(&value
);
7133 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
7134 ok(value
.vt
== (VT_VECTOR
| VT_LPWSTR
), "Unexpected value type %#x.\n", value
.vt
);
7136 PropVariantClear(&value
);
7139 static void test_MFGetSupportedSchemes(void)
7144 hr
= MFGetSupportedSchemes(NULL
);
7145 ok(hr
== E_POINTER
, "Unexpected hr %#lx.\n", hr
);
7147 value
.vt
= VT_EMPTY
;
7148 hr
= MFGetSupportedSchemes(&value
);
7149 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
7150 ok(value
.vt
== (VT_VECTOR
| VT_LPWSTR
), "Unexpected value type %#x.\n", value
.vt
);
7152 PropVariantClear(&value
);
7155 static void test_scheme_resolvers(void)
7157 static const DWORD expect_caps
= MFBYTESTREAM_IS_READABLE
| MFBYTESTREAM_IS_SEEKABLE
;
7158 static const WCHAR
*urls
[] =
7160 L
"http://test.winehq.org/tests/test.mp3",
7161 L
"https://test.winehq.org/tests/test.mp3",
7162 L
"httpd://test.winehq.org/tests/test.mp3",
7163 L
"httpsd://test.winehq.org/tests/test.mp3",
7164 L
"mms://test.winehq.org/tests/test.mp3",
7166 static const WCHAR
*expect_domain
[] =
7168 L
"http://test.winehq.org",
7169 L
"https://test.winehq.org",
7170 L
"http://test.winehq.org",
7171 L
"https://test.winehq.org",
7172 L
"http://test.winehq.org",
7175 IMFSourceResolver
*resolver
;
7176 IMFByteStream
*byte_stream
;
7177 IMFAttributes
*attributes
;
7178 PROPVARIANT propvar
;
7179 MF_OBJECT_TYPE type
;
7185 hr
= MFStartup(MF_VERSION
, MFSTARTUP_FULL
);
7186 ok(hr
== S_OK
, "got hr %#lx\n", hr
);
7188 hr
= MFCreateSourceResolver(&resolver
);
7189 ok(hr
== S_OK
, "got hr %#lx\n", hr
);
7191 for (i
= 0; i
< ARRAY_SIZE(urls
); i
++)
7193 hr
= IMFSourceResolver_CreateObjectFromURL(resolver
, urls
[i
], MF_RESOLUTION_BYTESTREAM
, NULL
, &type
, &object
);
7194 todo_wine_if(i
>= 2)
7195 ok(hr
== S_OK
, "got hr %#lx\n", hr
);
7199 hr
= IUnknown_QueryInterface(object
, &IID_IMFAttributes
, (void **)&attributes
);
7200 ok(hr
== S_OK
, "got hr %#lx\n", hr
);
7201 hr
= IMFAttributes_GetItem(attributes
, &MF_BYTESTREAM_ORIGIN_NAME
, NULL
);
7202 ok(hr
== MF_E_ATTRIBUTENOTFOUND
, "got hr %#lx\n", hr
);
7204 PropVariantInit(&propvar
);
7205 hr
= IMFAttributes_GetItem(attributes
, &MF_BYTESTREAM_EFFECTIVE_URL
, &propvar
);
7206 ok(hr
== S_OK
|| broken(hr
== MF_E_ATTRIBUTENOTFOUND
) /* Win7 */, "got hr %#lx\n", hr
);
7209 ok(!wcsncmp(expect_domain
[i
], propvar
.pwszVal
, wcslen(expect_domain
[i
])),
7210 "got url %s\n", debugstr_w(propvar
.pwszVal
));
7212 hr
= PropVariantClear(&propvar
);
7213 ok(hr
== S_OK
, "got hr %#lx\n", hr
);
7215 hr
= IMFAttributes_GetItem(attributes
, &MF_BYTESTREAM_CONTENT_TYPE
, NULL
);
7216 ok(hr
== S_OK
, "got hr %#lx\n", hr
);
7217 hr
= IMFAttributes_GetItem(attributes
, &MF_BYTESTREAM_LAST_MODIFIED_TIME
, NULL
);
7219 ok(hr
== S_OK
, "got hr %#lx\n", hr
);
7220 IMFAttributes_Release(attributes
);
7222 hr
= IUnknown_QueryInterface(object
, &IID_IMFByteStream
, (void **)&byte_stream
);
7223 ok(hr
== S_OK
, "got hr %#lx\n", hr
);
7224 hr
= IMFByteStream_GetCapabilities(byte_stream
, &caps
);
7225 ok(hr
== S_OK
, "got hr %#lx\n", hr
);
7227 ok(caps
== (expect_caps
| MFBYTESTREAM_IS_PARTIALLY_DOWNLOADED
)
7228 || caps
== (expect_caps
| MFBYTESTREAM_DOES_NOT_USE_NETWORK
),
7229 "got caps %#lx\n", caps
);
7230 hr
= IMFByteStream_GetLength(byte_stream
, &length
);
7231 ok(hr
== S_OK
, "got hr %#lx\n", hr
);
7232 ok(length
== 0x110d, "got length %#I64x\n", length
);
7233 IMFByteStream_Release(byte_stream
);
7235 IUnknown_Release(object
);
7238 hr
= IMFSourceResolver_CreateObjectFromURL(resolver
, L
"httpt://test.winehq.org/tests/test.mp3", MF_RESOLUTION_BYTESTREAM
, NULL
, &type
, &object
);
7240 ok(hr
== MF_E_UNSUPPORTED_BYTESTREAM_TYPE
, "got hr %#lx\n", hr
);
7241 hr
= IMFSourceResolver_CreateObjectFromURL(resolver
, L
"httpu://test.winehq.org/tests/test.mp3", MF_RESOLUTION_BYTESTREAM
, NULL
, &type
, &object
);
7243 ok(hr
== MF_E_UNSUPPORTED_BYTESTREAM_TYPE
, "got hr %#lx\n", hr
);
7245 hr
= IMFSourceResolver_CreateObjectFromURL(resolver
, L
"http://test.winehq.bla/tests/test.mp3", MF_RESOLUTION_BYTESTREAM
, NULL
, &type
, &object
);
7247 ok(hr
== NS_E_SERVER_NOT_FOUND
, "got hr %#lx\n", hr
);
7248 hr
= IMFSourceResolver_CreateObjectFromURL(resolver
, L
"https://test.winehq.bla/tests/test.mp3", MF_RESOLUTION_BYTESTREAM
, NULL
, &type
, &object
);
7250 ok(hr
== WININET_E_NAME_NOT_RESOLVED
, "got hr %#lx\n", hr
);
7251 hr
= IMFSourceResolver_CreateObjectFromURL(resolver
, L
"httpd://test.winehq.bla/tests/test.mp3", MF_RESOLUTION_BYTESTREAM
, NULL
, &type
, &object
);
7253 ok(hr
== WININET_E_NAME_NOT_RESOLVED
, "got hr %#lx\n", hr
);
7254 hr
= IMFSourceResolver_CreateObjectFromURL(resolver
, L
"httpsd://test.winehq.bla/tests/test.mp3", MF_RESOLUTION_BYTESTREAM
, NULL
, &type
, &object
);
7256 ok(hr
== WININET_E_NAME_NOT_RESOLVED
, "got hr %#lx\n", hr
);
7257 hr
= IMFSourceResolver_CreateObjectFromURL(resolver
, L
"mms://test.winehq.bla/tests/test.mp3", MF_RESOLUTION_BYTESTREAM
, NULL
, &type
, &object
);
7259 ok(hr
== WININET_E_NAME_NOT_RESOLVED
, "got hr %#lx\n", hr
);
7261 hr
= IMFSourceResolver_CreateObjectFromURL(resolver
, L
"http://test.winehq.org/tests/invalid.mp3", MF_RESOLUTION_BYTESTREAM
, NULL
, &type
, &object
);
7263 ok(hr
== NS_E_FILE_NOT_FOUND
, "got hr %#lx\n", hr
);
7264 hr
= IMFSourceResolver_CreateObjectFromURL(resolver
, L
"https://test.winehq.org/tests/invalid.mp3", MF_RESOLUTION_BYTESTREAM
, NULL
, &type
, &object
);
7266 ok(hr
== NS_E_FILE_NOT_FOUND
, "got hr %#lx\n", hr
);
7267 hr
= IMFSourceResolver_CreateObjectFromURL(resolver
, L
"httpd://test.winehq.org/tests/invalid.mp3", MF_RESOLUTION_BYTESTREAM
, NULL
, &type
, &object
);
7269 ok(hr
== NS_E_FILE_NOT_FOUND
, "got hr %#lx\n", hr
);
7270 hr
= IMFSourceResolver_CreateObjectFromURL(resolver
, L
"httpsd://test.winehq.org/tests/invalid.mp3", MF_RESOLUTION_BYTESTREAM
, NULL
, &type
, &object
);
7272 ok(hr
== NS_E_FILE_NOT_FOUND
, "got hr %#lx\n", hr
);
7273 hr
= IMFSourceResolver_CreateObjectFromURL(resolver
, L
"mms://test.winehq.org/tests/invalid.mp3", MF_RESOLUTION_BYTESTREAM
, NULL
, &type
, &object
);
7275 ok(hr
== MF_E_UNSUPPORTED_BYTESTREAM_TYPE
, "got hr %#lx\n", hr
);
7277 IMFSourceResolver_Release(resolver
);
7280 ok(hr
== S_OK
, "got hr %#lx\n", hr
);
7283 static void test_MFGetTopoNodeCurrentType(void)
7285 static const struct attribute_desc media_type_desc
[] =
7287 ATTR_GUID(MF_MT_MAJOR_TYPE
, MFMediaType_Video
),
7288 ATTR_GUID(MF_MT_SUBTYPE
, MFVideoFormat_NV12
),
7289 ATTR_RATIO(MF_MT_FRAME_SIZE
, 1920, 1080),
7292 IMFMediaType
*media_type
, *input_types
[2], *output_types
[2];
7293 IMFStreamDescriptor
*input_descriptor
, *output_descriptor
;
7294 struct test_stream_sink stream_sink
= test_stream_sink
;
7295 IMFMediaTypeHandler
*input_handler
, *output_handler
;
7296 IMFTransform
*transform
;
7297 IMFTopologyNode
*node
;
7302 if (!pMFGetTopoNodeCurrentType
)
7304 win_skip("MFGetTopoNodeCurrentType() is unsupported.\n");
7308 hr
= CoInitialize(NULL
);
7309 ok(hr
== S_OK
, "Failed to initialize, hr %#lx.\n", hr
);
7311 hr
= MFCreateMediaType(&input_types
[0]);
7312 ok(hr
== S_OK
, "Failed to create media type, hr %#lx.\n", hr
);
7313 init_media_type(input_types
[0], media_type_desc
, -1);
7314 hr
= MFCreateMediaType(&input_types
[1]);
7315 ok(hr
== S_OK
, "Failed to create media type, hr %#lx.\n", hr
);
7316 init_media_type(input_types
[1], media_type_desc
, -1);
7317 hr
= MFCreateMediaType(&output_types
[0]);
7318 ok(hr
== S_OK
, "Failed to create media type, hr %#lx.\n", hr
);
7319 init_media_type(output_types
[0], media_type_desc
, -1);
7320 hr
= MFCreateMediaType(&output_types
[1]);
7321 ok(hr
== S_OK
, "Failed to create media type, hr %#lx.\n", hr
);
7322 init_media_type(output_types
[1], media_type_desc
, -1);
7324 hr
= MFCreateStreamDescriptor(0, 2, input_types
, &input_descriptor
);
7325 ok(hr
== S_OK
, "Failed to create IMFStreamDescriptor hr %#lx.\n", hr
);
7326 hr
= IMFStreamDescriptor_GetMediaTypeHandler(input_descriptor
, &input_handler
);
7327 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
7328 hr
= MFCreateStreamDescriptor(0, 2, output_types
, &output_descriptor
);
7329 ok(hr
== S_OK
, "Failed to create IMFStreamDescriptor hr %#lx.\n", hr
);
7330 hr
= IMFStreamDescriptor_GetMediaTypeHandler(output_descriptor
, &output_handler
);
7331 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
7333 hr
= CoCreateInstance(&CLSID_CColorConvertDMO
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IMFTransform
, (void **)&transform
);
7334 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
7338 hr
= MFCreateTopologyNode(MF_TOPOLOGY_TEE_NODE
, &node
);
7339 ok(hr
== S_OK
, "Failed to create a node, hr %#lx.\n", hr
);
7340 hr
= pMFGetTopoNodeCurrentType(node
, 0, TRUE
, &media_type
);
7341 ok(hr
== E_INVALIDARG
, "Unexpected hr %#lx.\n", hr
);
7342 hr
= pMFGetTopoNodeCurrentType(node
, 0, FALSE
, &media_type
);
7343 ok(hr
== E_INVALIDARG
, "Unexpected hr %#lx.\n", hr
);
7345 /* Set second output. */
7346 hr
= IMFTopologyNode_SetOutputPrefType(node
, 1, output_types
[1]);
7347 ok(hr
== S_OK
, "Failed to set media type, hr %#lx.\n", hr
);
7348 hr
= pMFGetTopoNodeCurrentType(node
, 0, TRUE
, &media_type
);
7349 ok(hr
== E_FAIL
, "Unexpected hr %#lx.\n", hr
);
7350 hr
= pMFGetTopoNodeCurrentType(node
, 0, FALSE
, &media_type
);
7351 ok(hr
== E_FAIL
, "Unexpected hr %#lx.\n", hr
);
7352 hr
= pMFGetTopoNodeCurrentType(node
, 1, TRUE
, &media_type
);
7353 ok(hr
== E_FAIL
, "Unexpected hr %#lx.\n", hr
);
7354 hr
= pMFGetTopoNodeCurrentType(node
, 1, FALSE
, &media_type
);
7355 ok(hr
== E_FAIL
, "Unexpected hr %#lx.\n", hr
);
7357 /* Set first output. */
7358 hr
= IMFTopologyNode_SetOutputPrefType(node
, 0, output_types
[0]);
7359 ok(hr
== S_OK
, "Failed to set media type, hr %#lx.\n", hr
);
7360 hr
= pMFGetTopoNodeCurrentType(node
, 0, TRUE
, &media_type
);
7361 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
7362 ok(media_type
== output_types
[0], "Unexpected pointer.\n");
7363 IMFMediaType_Release(media_type
);
7364 hr
= pMFGetTopoNodeCurrentType(node
, 1, TRUE
, &media_type
);
7365 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
7366 ok(media_type
== output_types
[0], "Unexpected pointer.\n");
7367 IMFMediaType_Release(media_type
);
7368 hr
= pMFGetTopoNodeCurrentType(node
, 0, FALSE
, &media_type
);
7369 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
7370 ok(media_type
== output_types
[0], "Unexpected pointer.\n");
7371 IMFMediaType_Release(media_type
);
7373 /* Set primary output. */
7374 hr
= IMFTopologyNode_SetOutputPrefType(node
, 1, output_types
[1]);
7375 ok(hr
== S_OK
, "Failed to set media type, hr %#lx.\n", hr
);
7376 hr
= IMFTopologyNode_SetUINT32(node
, &MF_TOPONODE_PRIMARYOUTPUT
, 1);
7377 ok(hr
== S_OK
, "Failed to set attribute, hr %#lx.\n", hr
);
7378 hr
= pMFGetTopoNodeCurrentType(node
, 0, TRUE
, &media_type
);
7379 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
7380 ok(media_type
== output_types
[1], "Unexpected pointer.\n");
7381 IMFMediaType_Release(media_type
);
7382 hr
= pMFGetTopoNodeCurrentType(node
, 0, FALSE
, &media_type
);
7383 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
7384 ok(media_type
== output_types
[1], "Unexpected pointer.\n");
7385 IMFMediaType_Release(media_type
);
7386 hr
= pMFGetTopoNodeCurrentType(node
, 1, FALSE
, &media_type
);
7387 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
7388 ok(media_type
== output_types
[1], "Unexpected pointer.\n");
7389 IMFMediaType_Release(media_type
);
7391 /* Input type returned, if set. */
7392 hr
= IMFTopologyNode_SetInputPrefType(node
, 0, input_types
[0]);
7393 ok(hr
== S_OK
, "Failed to set media type, hr %#lx.\n", hr
);
7394 hr
= pMFGetTopoNodeCurrentType(node
, 0, FALSE
, &media_type
);
7395 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
7396 ok(media_type
== input_types
[0], "Unexpected pointer.\n");
7397 IMFMediaType_Release(media_type
);
7398 hr
= pMFGetTopoNodeCurrentType(node
, 0, TRUE
, &media_type
);
7399 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
7400 ok(media_type
== input_types
[0], "Unexpected pointer.\n");
7401 IMFMediaType_Release(media_type
);
7403 hr
= IMFTopologyNode_SetInputPrefType(node
, 0, NULL
);
7404 ok(hr
== S_OK
, "Failed to set media type, hr %#lx.\n", hr
);
7405 hr
= IMFTopologyNode_SetOutputPrefType(node
, 0, NULL
);
7406 ok(hr
== S_OK
, "Failed to set media type, hr %#lx.\n", hr
);
7407 hr
= IMFTopologyNode_SetOutputPrefType(node
, 1, NULL
);
7408 ok(hr
== S_OK
, "Failed to set media type, hr %#lx.\n", hr
);
7409 ref
= IMFTopologyNode_Release(node
);
7410 ok(ref
== 0, "Release returned %ld\n", ref
);
7414 hr
= MFCreateTopologyNode(MF_TOPOLOGY_SOURCESTREAM_NODE
, &node
);
7415 ok(hr
== S_OK
, "Failed to create a node, hr %#lx.\n", hr
);
7416 hr
= pMFGetTopoNodeCurrentType(node
, 0, TRUE
, &media_type
);
7417 ok(hr
== MF_E_ATTRIBUTENOTFOUND
, "Unexpected hr %#lx.\n", hr
);
7418 hr
= pMFGetTopoNodeCurrentType(node
, 1, TRUE
, &media_type
);
7419 ok(hr
== MF_E_INVALIDSTREAMNUMBER
, "Unexpected hr %#lx.\n", hr
);
7420 hr
= pMFGetTopoNodeCurrentType(node
, 0, FALSE
, &media_type
);
7421 ok(hr
== MF_E_INVALIDSTREAMNUMBER
, "Unexpected hr %#lx.\n", hr
);
7423 hr
= IMFTopologyNode_SetUnknown(node
, &MF_TOPONODE_STREAM_DESCRIPTOR
, (IUnknown
*)input_descriptor
);
7424 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
7425 hr
= pMFGetTopoNodeCurrentType(node
, 0, TRUE
, &media_type
);
7426 ok(hr
== MF_E_NOT_INITIALIZED
, "Unexpected hr %#lx.\n", hr
);
7428 hr
= IMFMediaTypeHandler_SetCurrentMediaType(input_handler
, output_types
[0]);
7429 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
7430 hr
= pMFGetTopoNodeCurrentType(node
, 0, TRUE
, &media_type
);
7431 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
7432 ok(media_type
== output_types
[0], "Unexpected pointer.\n");
7433 IMFMediaType_Release(media_type
);
7435 ref
= IMFTopologyNode_Release(node
);
7436 ok(ref
== 0, "Release returned %ld\n", ref
);
7440 hr
= MFCreateTopologyNode(MF_TOPOLOGY_OUTPUT_NODE
, &node
);
7441 ok(hr
== S_OK
, "Failed to create a node, hr %#lx.\n", hr
);
7442 hr
= pMFGetTopoNodeCurrentType(node
, 0, FALSE
, &media_type
);
7443 ok(hr
== E_FAIL
, "Unexpected hr %#lx.\n", hr
);
7444 hr
= pMFGetTopoNodeCurrentType(node
, 1, FALSE
, &media_type
);
7445 ok(hr
== MF_E_INVALIDSTREAMNUMBER
, "Unexpected hr %#lx.\n", hr
);
7446 hr
= pMFGetTopoNodeCurrentType(node
, 0, TRUE
, &media_type
);
7447 ok(hr
== MF_E_INVALIDSTREAMNUMBER
, "Unexpected hr %#lx.\n", hr
);
7449 stream_sink
.handler
= output_handler
;
7450 hr
= IMFTopologyNode_SetObject(node
, (IUnknown
*)&stream_sink
.IMFStreamSink_iface
);
7451 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
7452 hr
= pMFGetTopoNodeCurrentType(node
, 0, FALSE
, &media_type
);
7453 ok(hr
== MF_E_NOT_INITIALIZED
, "Unexpected hr %#lx.\n", hr
);
7455 hr
= IMFMediaTypeHandler_SetCurrentMediaType(output_handler
, input_types
[0]);
7456 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
7457 hr
= pMFGetTopoNodeCurrentType(node
, 0, FALSE
, &media_type
);
7458 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
7459 ok(media_type
== input_types
[0], "Unexpected pointer.\n");
7460 IMFMediaType_Release(media_type
);
7462 ref
= IMFTopologyNode_Release(node
);
7463 ok(ref
== 0, "Release returned %ld\n", ref
);
7466 /* Transform node. */
7467 hr
= MFCreateTopologyNode(MF_TOPOLOGY_TRANSFORM_NODE
, &node
);
7468 ok(hr
== S_OK
, "Failed to create a node, hr %#lx.\n", hr
);
7469 hr
= pMFGetTopoNodeCurrentType(node
, 0, TRUE
, &media_type
);
7470 ok(hr
== E_FAIL
, "Unexpected hr %#lx.\n", hr
);
7471 hr
= pMFGetTopoNodeCurrentType(node
, 1, TRUE
, &media_type
);
7472 ok(hr
== E_FAIL
, "Unexpected hr %#lx.\n", hr
);
7473 hr
= pMFGetTopoNodeCurrentType(node
, 0, FALSE
, &media_type
);
7474 ok(hr
== E_FAIL
, "Unexpected hr %#lx.\n", hr
);
7475 hr
= pMFGetTopoNodeCurrentType(node
, 1, FALSE
, &media_type
);
7476 ok(hr
== E_FAIL
, "Unexpected hr %#lx.\n", hr
);
7478 hr
= IMFTopologyNode_SetObject(node
, (IUnknown
*)transform
);
7479 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
7480 hr
= pMFGetTopoNodeCurrentType(node
, 0, TRUE
, &media_type
);
7481 ok(hr
== MF_E_TRANSFORM_TYPE_NOT_SET
, "Unexpected hr %#lx.\n", hr
);
7482 hr
= pMFGetTopoNodeCurrentType(node
, 1, TRUE
, &media_type
);
7483 ok(hr
== MF_E_INVALIDSTREAMNUMBER
, "Unexpected hr %#lx.\n", hr
);
7484 hr
= pMFGetTopoNodeCurrentType(node
, 0, FALSE
, &media_type
);
7485 ok(hr
== MF_E_TRANSFORM_TYPE_NOT_SET
, "Unexpected hr %#lx.\n", hr
);
7486 hr
= pMFGetTopoNodeCurrentType(node
, 1, FALSE
, &media_type
);
7487 ok(hr
== MF_E_INVALIDSTREAMNUMBER
, "Unexpected hr %#lx.\n", hr
);
7489 hr
= IMFTransform_SetInputType(transform
, 0, input_types
[0], 0);
7490 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
7491 hr
= pMFGetTopoNodeCurrentType(node
, 0, TRUE
, &media_type
);
7492 ok(hr
== MF_E_TRANSFORM_TYPE_NOT_SET
, "Unexpected hr %#lx.\n", hr
);
7493 hr
= pMFGetTopoNodeCurrentType(node
, 0, FALSE
, &media_type
);
7494 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
7495 hr
= IMFMediaType_IsEqual(media_type
, input_types
[0], &flags
);
7496 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
7497 IMFMediaType_Release(media_type
);
7499 hr
= IMFTransform_SetOutputType(transform
, 0, output_types
[0], 0);
7500 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
7501 hr
= pMFGetTopoNodeCurrentType(node
, 0, TRUE
, &media_type
);
7502 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
7503 hr
= IMFMediaType_IsEqual(media_type
, output_types
[0], &flags
);
7504 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
7505 IMFMediaType_Release(media_type
);
7507 ref
= IMFTopologyNode_Release(node
);
7508 ok(ref
== 0, "Release returned %ld\n", ref
);
7511 ref
= IMFTransform_Release(transform
);
7512 ok(ref
== 0, "Release returned %ld\n", ref
);
7514 IMFMediaTypeHandler_Release(input_handler
);
7515 IMFMediaTypeHandler_Release(output_handler
);
7516 ref
= IMFStreamDescriptor_Release(input_descriptor
);
7517 ok(ref
== 0, "Release returned %ld\n", ref
);
7518 ref
= IMFStreamDescriptor_Release(output_descriptor
);
7519 ok(ref
== 0, "Release returned %ld\n", ref
);
7521 ref
= IMFMediaType_Release(input_types
[0]);
7522 ok(ref
== 0, "Release returned %ld\n", ref
);
7523 ref
= IMFMediaType_Release(input_types
[1]);
7524 ok(ref
== 0, "Release returned %ld\n", ref
);
7525 ref
= IMFMediaType_Release(output_types
[0]);
7526 ok(ref
== 0, "Release returned %ld\n", ref
);
7527 ref
= IMFMediaType_Release(output_types
[1]);
7528 ok(ref
== 0, "Release returned %ld\n", ref
);
7533 void init_functions(void)
7535 HMODULE mod
= GetModuleHandleA("mf.dll");
7536 IMFTransform
*transform
;
7539 #define X(f) p##f = (void*)GetProcAddress(mod, #f)
7540 X(MFCreateSampleCopierMFT
);
7541 X(MFGetTopoNodeCurrentType
);
7543 mod
= GetModuleHandleA("mfplat.dll");
7544 X(MFCreateDXGIDeviceManager
);
7547 hr
= CoInitialize(NULL
);
7548 ok(hr
== S_OK
, "Failed to initialize, hr %#lx.\n", hr
);
7550 hr
= CoCreateInstance(&CLSID_VideoProcessorMFT
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IMFTransform
, (void **)&transform
);
7553 has_video_processor
= TRUE
;
7554 IMFTransform_Release(transform
);
7560 static void test_MFRequireProtectedEnvironment(void)
7562 IMFPresentationDescriptor
*pd
;
7563 IMFMediaType
*mediatype
;
7564 IMFStreamDescriptor
*sd
;
7568 hr
= MFCreateMediaType(&mediatype
);
7569 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
7571 hr
= MFCreateStreamDescriptor(0, 1, &mediatype
, &sd
);
7572 ok(hr
== S_OK
, "Failed to create stream descriptor, hr %#lx.\n", hr
);
7574 hr
= MFCreatePresentationDescriptor(1, &sd
, &pd
);
7575 ok(hr
== S_OK
, "Failed to create presentation descriptor, hr %#lx.\n", hr
);
7577 hr
= IMFPresentationDescriptor_SelectStream(pd
, 0);
7578 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
7580 hr
= MFRequireProtectedEnvironment(pd
);
7581 ok(hr
== S_FALSE
, "Unexpected hr %#lx.\n", hr
);
7583 hr
= IMFStreamDescriptor_SetUINT32(sd
, &MF_SD_PROTECTED
, 1);
7584 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
7586 hr
= MFRequireProtectedEnvironment(pd
);
7587 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
7589 hr
= IMFPresentationDescriptor_DeselectStream(pd
, 0);
7590 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
7592 hr
= MFRequireProtectedEnvironment(pd
);
7593 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
7595 ref
= IMFPresentationDescriptor_Release(pd
);
7596 ok(ref
== 0, "Release returned %ld\n", ref
);
7597 ref
= IMFStreamDescriptor_Release(sd
);
7598 ok(ref
== 0, "Release returned %ld\n", ref
);
7599 ref
= IMFMediaType_Release(mediatype
);
7600 ok(ref
== 0, "Release returned %ld\n", ref
);
7603 static void test_mpeg4_media_sink(void)
7605 IMFMediaSink
*sink
= NULL
, *sink2
= NULL
, *sink_audio
= NULL
, *sink_video
= NULL
, *sink_empty
= NULL
;
7606 IMFByteStream
*bytestream
, *bytestream_audio
, *bytestream_video
, *bytestream_empty
;
7607 DWORD id
, count
, flags
, width
= 96, height
= 96;
7608 IMFMediaType
*audio_type
, *video_type
, *media_type
;
7609 IMFMediaTypeHandler
*type_handler
= NULL
;
7610 IMFPresentationClock
*clock
;
7611 IMFStreamSink
*stream_sink
;
7615 /* Test sink creation. */
7616 hr
= MFCreateMediaType(&audio_type
);
7617 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
7618 hr
= MFCreateMediaType(&video_type
);
7619 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
7621 hr
= IMFMediaType_SetGUID(audio_type
, &MF_MT_MAJOR_TYPE
, &MFMediaType_Audio
);
7622 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
7623 hr
= IMFMediaType_SetGUID(audio_type
, &MF_MT_SUBTYPE
, &MFAudioFormat_AAC
);
7624 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
7625 hr
= IMFMediaType_SetUINT32(audio_type
, &MF_MT_AUDIO_NUM_CHANNELS
, 1);
7626 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
7627 hr
= IMFMediaType_SetUINT32(audio_type
, &MF_MT_AUDIO_BITS_PER_SAMPLE
, 16);
7628 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
7629 hr
= IMFMediaType_SetUINT32(audio_type
, &MF_MT_AUDIO_SAMPLES_PER_SECOND
, 44100);
7630 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
7631 hr
= IMFMediaType_SetUINT32(audio_type
, &MF_MT_AUDIO_AVG_BYTES_PER_SECOND
, 12000);
7632 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
7633 hr
= IMFMediaType_SetUINT32(audio_type
, &MF_MT_AAC_AUDIO_PROFILE_LEVEL_INDICATION
, 41);
7634 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
7635 hr
= IMFMediaType_SetUINT32(audio_type
, &MF_MT_AAC_PAYLOAD_TYPE
, 0);
7636 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
7637 hr
= IMFMediaType_SetBlob(audio_type
, &MF_MT_USER_DATA
, test_aac_codec_data
, sizeof(test_aac_codec_data
));
7638 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
7640 hr
= IMFMediaType_SetGUID(video_type
, &MF_MT_MAJOR_TYPE
, &MFMediaType_Video
);
7641 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
7642 hr
= IMFMediaType_SetGUID(video_type
, &MF_MT_SUBTYPE
, &MFVideoFormat_H264
);
7643 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
7644 hr
= IMFMediaType_SetUINT64(video_type
, &MF_MT_FRAME_SIZE
, ((UINT64
)width
<< 32) | height
);
7645 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
7646 hr
= IMFMediaType_SetUINT64(video_type
, &MF_MT_FRAME_RATE
, ((UINT64
)30000 << 32) | 1001);
7647 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
7648 hr
= IMFMediaType_SetBlob(video_type
, &MF_MT_MPEG_SEQUENCE_HEADER
,
7649 test_h264_sequence_header
, sizeof(test_h264_sequence_header
));
7650 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
7652 hr
= MFCreateTempFile(MF_ACCESSMODE_WRITE
, MF_OPENMODE_DELETE_IF_EXIST
, 0, &bytestream_audio
);
7653 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
7654 hr
= MFCreateTempFile(MF_ACCESSMODE_WRITE
, MF_OPENMODE_DELETE_IF_EXIST
, 0, &bytestream_video
);
7655 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
7656 hr
= MFCreateTempFile(MF_ACCESSMODE_WRITE
, MF_OPENMODE_DELETE_IF_EXIST
, 0, &bytestream_empty
);
7657 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
7658 hr
= MFCreateTempFile(MF_ACCESSMODE_WRITE
, MF_OPENMODE_DELETE_IF_EXIST
, 0, &bytestream
);
7659 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
7661 hr
= MFCreateMPEG4MediaSink(NULL
, NULL
, NULL
, NULL
);
7662 ok(hr
== E_POINTER
, "Unexpected hr %#lx.\n", hr
);
7664 sink
= (void *)0xdeadbeef;
7665 hr
= MFCreateMPEG4MediaSink(NULL
, NULL
, NULL
, &sink
);
7666 ok(hr
== E_POINTER
, "Unexpected hr %#lx.\n", hr
);
7667 ok(sink
== (void *)0xdeadbeef, "Unexpected pointer %p.\n", sink
);
7670 hr
= MFCreateMPEG4MediaSink(bytestream_empty
, NULL
, NULL
, &sink_empty
);
7671 ok(hr
== S_OK
|| broken(hr
== E_INVALIDARG
), "Unexpected hr %#lx.\n", hr
);
7673 hr
= MFCreateMPEG4MediaSink(bytestream_audio
, NULL
, audio_type
, &sink_audio
);
7674 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
7676 hr
= MFCreateMPEG4MediaSink(bytestream_video
, video_type
, NULL
, &sink_video
);
7677 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
7679 hr
= MFCreateMPEG4MediaSink(bytestream
, video_type
, audio_type
, &sink
);
7680 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
7684 hr
= IMFMediaSink_GetCharacteristics(sink
, &flags
);
7686 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
7688 ok(flags
== MEDIASINK_RATELESS
|| broken(flags
== (MEDIASINK_RATELESS
| MEDIASINK_FIXED_STREAMS
)),
7689 "Unexpected flags %#lx.\n", flags
);
7691 check_interface(sink
, &IID_IMFMediaEventGenerator
, TRUE
);
7692 check_interface(sink
, &IID_IMFFinalizableMediaSink
, TRUE
);
7693 check_interface(sink
, &IID_IMFClockStateSink
, TRUE
);
7695 check_interface(sink
, &IID_IMFGetService
, TRUE
);
7697 /* Test sink stream count. */
7698 hr
= IMFMediaSink_GetStreamSinkCount(sink
, NULL
);
7699 ok(hr
== E_POINTER
, "Unexpected hr %#lx.\n", hr
);
7701 hr
= IMFMediaSink_GetStreamSinkCount(sink
, &count
);
7702 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
7703 ok(count
== 2, "Unexpected count %lu.\n", count
);
7705 hr
= IMFMediaSink_GetStreamSinkCount(sink_audio
, &count
);
7706 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
7707 ok(count
== 1, "Unexpected count %lu.\n", count
);
7709 hr
= IMFMediaSink_GetStreamSinkCount(sink_video
, &count
);
7710 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
7711 ok(count
== 1, "Unexpected count %lu.\n", count
);
7715 hr
= IMFMediaSink_GetStreamSinkCount(sink_empty
, &count
);
7716 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
7717 ok(count
== 0, "Unexpected count %lu.\n", count
);
7720 /* Test GetStreamSinkByIndex. */
7721 hr
= IMFMediaSink_GetStreamSinkByIndex(sink_video
, 0, &stream_sink
);
7722 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
7723 hr
= IMFStreamSink_GetIdentifier(stream_sink
, &id
);
7724 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
7725 ok(id
== 1, "Unexpected id %lu.\n", id
);
7726 IMFStreamSink_Release(stream_sink
);
7728 hr
= IMFMediaSink_GetStreamSinkByIndex(sink_audio
, 0, &stream_sink
);
7729 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
7730 hr
= IMFStreamSink_GetIdentifier(stream_sink
, &id
);
7731 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
7732 ok(id
== 2, "Unexpected id %lu.\n", id
);
7733 IMFStreamSink_Release(stream_sink
);
7735 stream_sink
= (void *)0xdeadbeef;
7736 hr
= IMFMediaSink_GetStreamSinkByIndex(sink_audio
, 1, &stream_sink
);
7737 ok(hr
== MF_E_INVALIDINDEX
, "Unexpected hr %#lx.\n", hr
);
7738 ok(stream_sink
== (void *)0xdeadbeef, "Unexpected pointer %p.\n", stream_sink
);
7740 stream_sink
= (void *)0xdeadbeef;
7741 hr
= IMFMediaSink_GetStreamSinkByIndex(sink_video
, 1, &stream_sink
);
7742 ok(hr
== MF_E_INVALIDINDEX
, "Unexpected hr %#lx.\n", hr
);
7743 ok(stream_sink
== (void *)0xdeadbeef, "Unexpected pointer %p.\n", stream_sink
);
7745 /* Test GetStreamSinkById. */
7746 hr
= IMFMediaSink_GetStreamSinkById(sink
, 1, &stream_sink
);
7747 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
7748 IMFStreamSink_Release(stream_sink
);
7749 hr
= IMFMediaSink_GetStreamSinkById(sink
, 2, &stream_sink
);
7750 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
7751 IMFStreamSink_Release(stream_sink
);
7752 hr
= IMFMediaSink_GetStreamSinkById(sink_video
, 1, &stream_sink
);
7753 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
7754 IMFStreamSink_Release(stream_sink
);
7755 hr
= IMFMediaSink_GetStreamSinkById(sink_audio
, 2, &stream_sink
);
7756 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
7757 IMFStreamSink_Release(stream_sink
);
7759 stream_sink
= (void *)0xdeadbeef;
7760 hr
= IMFMediaSink_GetStreamSinkById(sink_video
, 2, &stream_sink
);
7761 ok(hr
== MF_E_INVALIDSTREAMNUMBER
, "Unexpected hr %#lx.\n", hr
);
7762 ok(stream_sink
== (void *)0xdeadbeef, "Unexpected pointer %p.\n", stream_sink
);
7764 stream_sink
= (void *)0xdeadbeef;
7765 hr
= IMFMediaSink_GetStreamSinkById(sink_audio
, 1, &stream_sink
);
7766 ok(hr
== MF_E_INVALIDSTREAMNUMBER
, "Unexpected hr %#lx.\n", hr
);
7767 ok(stream_sink
== (void *)0xdeadbeef, "Unexpected pointer %p.\n", stream_sink
);
7769 /* Test adding and removing stream sink. */
7770 if (!(flags
& MEDIASINK_FIXED_STREAMS
))
7772 hr
= IMFMediaSink_AddStreamSink(sink
, 123, video_type
, &stream_sink
);
7773 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
7774 IMFStreamSink_Release(stream_sink
);
7775 hr
= IMFMediaSink_GetStreamSinkByIndex(sink
, 2, &stream_sink
);
7776 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
7777 hr
= IMFStreamSink_GetIdentifier(stream_sink
, &id
);
7778 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
7779 ok(id
== 123, "Unexpected id %lu.\n", id
);
7780 IMFStreamSink_Release(stream_sink
);
7782 stream_sink
= (void *)0xdeadbeef;
7783 hr
= IMFMediaSink_AddStreamSink(sink
, 1, audio_type
, &stream_sink
);
7784 ok(hr
== MF_E_STREAMSINK_EXISTS
, "Unexpected hr %#lx.\n", hr
);
7785 ok(!stream_sink
, "Unexpected pointer %p.\n", stream_sink
);
7787 hr
= IMFMediaSink_RemoveStreamSink(sink
, 1);
7788 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
7789 hr
= IMFMediaSink_AddStreamSink(sink
, 1, audio_type
, &stream_sink
);
7790 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
7791 IMFStreamSink_Release(stream_sink
);
7792 hr
= IMFMediaSink_GetStreamSinkByIndex(sink
, 2, &stream_sink
);
7793 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
7794 hr
= IMFStreamSink_GetIdentifier(stream_sink
, &id
);
7795 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
7796 ok(id
== 1, "Unexpected id %lu.\n", id
);
7797 IMFStreamSink_Release(stream_sink
);
7799 hr
= IMFMediaSink_RemoveStreamSink(sink
, 123);
7800 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
7801 hr
= IMFMediaSink_RemoveStreamSink(sink
, 123);
7802 ok(hr
== MF_E_INVALIDSTREAMNUMBER
, "Unexpected hr %#lx.\n", hr
);
7805 /* Test PresentationClock. */
7806 hr
= MFCreatePresentationClock(&clock
);
7807 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
7808 hr
= IMFMediaSink_SetPresentationClock(sink
, NULL
);
7810 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
7812 hr
= IMFMediaSink_SetPresentationClock(sink
, clock
);
7814 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
7815 IMFPresentationClock_Release(clock
);
7818 hr
= IMFMediaSink_GetStreamSinkByIndex(sink_audio
, 0, &stream_sink
);
7819 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
7821 hr
= IMFStreamSink_GetMediaSink(stream_sink
, &sink2
);
7822 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
7823 IMFMediaSink_Release(sink2
);
7825 check_interface(stream_sink
, &IID_IMFMediaEventGenerator
, TRUE
);
7826 check_interface(stream_sink
, &IID_IMFMediaTypeHandler
, TRUE
);
7828 hr
= IMFStreamSink_GetMediaTypeHandler(stream_sink
, &type_handler
);
7829 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
7831 hr
= IMFMediaTypeHandler_GetMajorType(type_handler
, NULL
);
7833 ok(hr
== E_POINTER
, "Unexpected hr %#lx.\n", hr
);
7834 hr
= IMFMediaTypeHandler_GetMajorType(type_handler
, &guid
);
7836 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
7838 ok(IsEqualGUID(&guid
, &MFMediaType_Audio
), "Unexpected major type.\n");
7840 hr
= IMFMediaTypeHandler_GetMediaTypeCount(type_handler
, &count
);
7842 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
7844 ok(count
== 1, "Unexpected count %lu.\n", count
);
7846 hr
= IMFMediaTypeHandler_GetCurrentMediaType(type_handler
, &media_type
);
7847 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
7849 hr
= IMFMediaType_SetUINT32(media_type
, &MF_MT_AUDIO_NUM_CHANNELS
, 1);
7850 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
7852 hr
= IMFMediaTypeHandler_SetCurrentMediaType(type_handler
, NULL
);
7854 ok(hr
== E_POINTER
, "Unexpected hr %#lx.\n", hr
);
7855 hr
= IMFMediaTypeHandler_SetCurrentMediaType(type_handler
, media_type
);
7857 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
7859 IMFMediaType_Release(media_type
);
7861 /* Test shutdown state. */
7862 hr
= IMFMediaSink_Shutdown(sink
);
7863 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
7864 hr
= IMFMediaSink_Shutdown(sink
);
7865 ok(hr
== MF_E_SHUTDOWN
, "Unexpected hr %#lx.\n", hr
);
7867 hr
= IMFStreamSink_GetMediaSink(stream_sink
, &sink2
);
7868 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
7869 IMFMediaSink_Release(sink2
);
7871 hr
= IMFStreamSink_GetIdentifier(stream_sink
, &id
);
7872 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
7874 hr
= IMFMediaTypeHandler_GetMajorType(type_handler
, NULL
);
7876 ok(hr
== E_POINTER
, "Unexpected hr %#lx.\n", hr
);
7877 hr
= IMFMediaTypeHandler_GetMajorType(type_handler
, &guid
);
7879 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
7881 IMFStreamSink_Release(stream_sink
);
7883 hr
= IMFMediaSink_AddStreamSink(sink
, 0, audio_type
, &stream_sink
);
7885 ok(hr
== MF_E_SHUTDOWN
, "Unexpected hr %#lx.\n", hr
);
7886 hr
= IMFMediaSink_GetStreamSinkByIndex(sink
, 0, &stream_sink
);
7888 ok(hr
== MF_E_SHUTDOWN
, "Unexpected hr %#lx.\n", hr
);
7889 hr
= IMFMediaSink_GetStreamSinkById(sink
, 0, &stream_sink
);
7891 ok(hr
== MF_E_SHUTDOWN
, "Unexpected hr %#lx.\n", hr
);
7892 hr
= IMFMediaSink_GetCharacteristics(sink
, &flags
);
7894 ok(hr
== MF_E_SHUTDOWN
, "Unexpected hr %#lx.\n", hr
);
7896 IMFMediaTypeHandler_Release(type_handler
);
7897 IMFMediaSink_Release(sink
);
7898 IMFMediaSink_Release(sink_video
);
7899 IMFMediaSink_Release(sink_audio
);
7901 IMFMediaSink_Release(sink_empty
);
7902 IMFByteStream_Release(bytestream
);
7903 IMFByteStream_Release(bytestream_empty
);
7904 IMFByteStream_Release(bytestream_video
);
7905 IMFByteStream_Release(bytestream_audio
);
7906 IMFMediaType_Release(video_type
);
7907 IMFMediaType_Release(audio_type
);
7910 static void test_MFCreateSequencerSegmentOffset(void)
7912 PROPVARIANT propvar
;
7915 hr
= MFCreateSequencerSegmentOffset(0, 0, NULL
);
7916 ok(hr
== E_POINTER
, "Unexpected hr %#lx.\n", hr
);
7918 propvar
.vt
= VT_EMPTY
;
7919 hr
= MFCreateSequencerSegmentOffset(0, 0, &propvar
);
7920 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
7921 ok(propvar
.vt
== VT_UNKNOWN
, "Unexpected type %d.\n", propvar
.vt
);
7922 ok(!!propvar
.punkVal
, "Unexpected pointer.\n");
7923 PropVariantClear(&propvar
);
7926 static void test_media_session_Start(void)
7928 static const struct object_state_record expected_object_state_records
[] =
7930 {{SOURCE_START
, SINK_ON_CLOCK_START
}, 2},
7931 {{SOURCE_STOP
, SOURCE_START
, SINK_ON_CLOCK_START
}, 3},
7932 {{SOURCE_STOP
, SOURCE_START
, SINK_ON_CLOCK_START
}, 3},
7934 media_type_desc video_rgb32_desc
=
7936 ATTR_GUID(MF_MT_MAJOR_TYPE
, MFMediaType_Video
),
7937 ATTR_GUID(MF_MT_SUBTYPE
, MFVideoFormat_RGB32
),
7939 static const MFTIME allowed_error
= 5000000;
7940 IMFClockStateSink test_seek_clock_sink
= {&test_seek_clock_sink_vtbl
};
7941 struct test_grabber_callback
*grabber_callback
;
7942 IMFPresentationClock
*presentation_clock
;
7943 enum source_state initial_state
;
7944 IMFActivate
*sink_activate
;
7945 IMFAsyncCallback
*callback
;
7946 IMFMediaType
*output_type
;
7947 IMFMediaSession
*session
;
7948 IMFMediaSource
*source
;
7949 IMFTopology
*topology
;
7950 MFTIME time
, old_time
;
7951 PROPVARIANT propvar
;
7957 hr
= MFStartup(MF_VERSION
, MFSTARTUP_FULL
);
7958 ok(hr
== S_OK
, "Failed to start up, hr %#lx.\n", hr
);
7960 if (!(source
= create_media_source(L
"test.mp4", L
"video/mp4")))
7962 todo_wine
/* Gitlab CI Debian runner */
7963 win_skip("MP4 media source is not supported, skipping tests.\n");
7968 grabber_callback
= impl_from_IMFSampleGrabberSinkCallback(create_test_grabber_callback());
7969 hr
= MFCreateMediaType(&output_type
);
7970 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
7971 init_media_type(output_type
, video_rgb32_desc
, -1);
7972 hr
= MFCreateSampleGrabberSinkActivate(output_type
, &grabber_callback
->IMFSampleGrabberSinkCallback_iface
, &sink_activate
);
7973 ok(hr
== S_OK
, "Failed to create grabber sink, hr %#lx.\n", hr
);
7974 IMFMediaType_Release(output_type
);
7976 hr
= MFCreateMediaSession(NULL
, &session
);
7977 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
7978 topology
= create_test_topology(source
, sink_activate
, &duration
);
7979 hr
= IMFMediaSession_SetTopology(session
, 0, topology
);
7980 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
7981 IMFTopology_Release(topology
);
7983 hr
= IMFMediaSession_GetClock(session
, &clock
);
7984 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
7985 hr
= IMFClock_QueryInterface(clock
, &IID_IMFPresentationClock
, (void **)&presentation_clock
);
7986 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
7987 IMFClock_Release(clock
);
7989 propvar
.vt
= VT_EMPTY
;
7990 hr
= IMFMediaSession_Start(session
, &GUID_NULL
, &propvar
);
7991 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
7992 callback
= create_test_callback(TRUE
);
7993 hr
= wait_media_event(session
, callback
, MESessionStarted
, 5000, &propvar
);
7994 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
7998 propvar
.hVal
.QuadPart
= 10000000;
7999 hr
= IMFMediaSession_Start(session
, &GUID_NULL
, &propvar
);
8000 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
8001 hr
= wait_media_event(session
, callback
, MESessionStarted
, 1000, &propvar
);
8002 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
8003 hr
= IMFPresentationClock_GetTime(presentation_clock
, &time
);
8004 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
8005 ok(llabs(time
- 10000000) <= allowed_error
, "Unexpected time %I64d.\n", time
);
8007 /* Seek to beyond duration */
8009 propvar
.hVal
.QuadPart
= duration
+ 10000000;
8010 hr
= IMFMediaSession_Start(session
, &GUID_NULL
, &propvar
);
8011 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
8012 hr
= wait_media_event(session
, callback
, MESessionStarted
, 1000, &propvar
);
8013 ok(hr
== MF_E_INVALID_POSITION
, "Unexpected hr %#lx.\n", hr
);
8015 /* Seek to negative position */
8017 propvar
.hVal
.QuadPart
= -10000000;
8018 hr
= IMFMediaSession_Start(session
, &GUID_NULL
, &propvar
);
8019 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
8020 hr
= wait_media_event(session
, callback
, MESessionStarted
, 1000, &propvar
);
8021 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
8022 hr
= IMFPresentationClock_GetTime(presentation_clock
, &time
);
8023 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
8024 ok(llabs(time
- (-10000000)) <= allowed_error
, "Unexpected time %I64d.\n", time
);
8026 /* Seek backwards to 0s */
8028 propvar
.hVal
.QuadPart
= 0;
8029 hr
= IMFMediaSession_Start(session
, &GUID_NULL
, &propvar
);
8030 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
8031 hr
= wait_media_event(session
, callback
, MESessionStarted
, 1000, &propvar
);
8032 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
8033 hr
= IMFPresentationClock_GetTime(presentation_clock
, &time
);
8034 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
8035 ok(llabs(time
) <= allowed_error
, "Unexpected time %I64d.\n", time
);
8037 /* Seek to 1s while in paused state */
8038 hr
= IMFMediaSession_Pause(session
);
8039 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
8040 hr
= wait_media_event(session
, callback
, MESessionPaused
, 1000, &propvar
);
8041 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
8044 propvar
.hVal
.QuadPart
= 10000000;
8045 hr
= IMFMediaSession_Start(session
, &GUID_NULL
, &propvar
);
8046 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
8047 hr
= wait_media_event(session
, callback
, MESessionStarted
, 1000, &propvar
);
8048 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
8050 hr
= IMFPresentationClock_GetTime(presentation_clock
, &time
);
8051 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
8052 ok(llabs(time
- 10000000) <= allowed_error
, "Unexpected time %I64d.\n", time
);
8055 /* Expected the presentation clock is running */
8057 hr
= IMFPresentationClock_GetTime(presentation_clock
, &time
);
8058 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
8059 ok(time
> old_time
, "Unexpected time %I64d.\n", time
);
8061 hr
= IMFMediaSession_Stop(session
);
8062 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
8063 hr
= IMFMediaSession_Close(session
);
8064 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
8066 /* Media session is shut down */
8067 hr
= IMFMediaSource_Shutdown(source
);
8068 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
8069 hr
= IMFMediaSession_Shutdown(session
);
8070 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
8073 propvar
.hVal
.QuadPart
= 10000000;
8074 hr
= IMFMediaSession_Start(session
, &GUID_NULL
, NULL
);
8075 ok(hr
== E_POINTER
, "Unexpected hr %#lx.\n", hr
);
8078 propvar
.hVal
.QuadPart
= 10000000;
8079 hr
= IMFMediaSession_Start(session
, &GUID_NULL
, &propvar
);
8080 ok(hr
== MF_E_SHUTDOWN
, "Unexpected hr %#lx.\n", hr
);
8082 propvar
.vt
= VT_EMPTY
;
8083 hr
= IMFMediaSession_Start(session
, &GUID_NULL
, &propvar
);
8084 ok(hr
== MF_E_SHUTDOWN
, "Unexpected hr %#lx.\n", hr
);
8086 IMFPresentationClock_Release(presentation_clock
);
8087 IMFMediaSource_Release(source
);
8088 IMFAsyncCallback_Release(callback
);
8089 /* sometimes briefly leaking */
8090 IMFMediaSession_Release(session
);
8091 IMFActivate_ShutdownObject(sink_activate
);
8092 IMFActivate_Release(sink_activate
);
8093 IMFSampleGrabberSinkCallback_Release(&grabber_callback
->IMFSampleGrabberSinkCallback_iface
);
8095 /* Unseekable media source */
8096 source
= create_test_seek_source(FALSE
);
8097 hr
= IMFMediaSource_GetCharacteristics(source
, &caps
);
8098 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
8099 ok((caps
& MFMEDIASOURCE_CAN_SEEK
) == 0, "Got unexpected caps %#lx.\n", caps
);
8100 grabber_callback
= impl_from_IMFSampleGrabberSinkCallback(create_test_grabber_callback());
8101 hr
= MFCreateMediaType(&output_type
);
8102 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
8103 init_media_type(output_type
, video_rgb32_desc
, -1);
8104 hr
= MFCreateSampleGrabberSinkActivate(output_type
, &grabber_callback
->IMFSampleGrabberSinkCallback_iface
, &sink_activate
);
8105 ok(hr
== S_OK
, "Failed to create grabber sink, hr %#lx.\n", hr
);
8106 IMFMediaType_Release(output_type
);
8108 hr
= MFCreateMediaSession(NULL
, &session
);
8109 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
8110 topology
= create_test_topology(source
, sink_activate
, &duration
);
8111 hr
= IMFMediaSession_SetTopology(session
, 0, topology
);
8112 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
8113 IMFTopology_Release(topology
);
8115 hr
= IMFMediaSession_GetClock(session
, &clock
);
8116 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
8117 hr
= IMFClock_QueryInterface(clock
, &IID_IMFPresentationClock
, (void **)&presentation_clock
);
8118 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
8119 IMFClock_Release(clock
);
8121 propvar
.vt
= VT_EMPTY
;
8122 hr
= IMFMediaSession_Start(session
, &GUID_NULL
, &propvar
);
8123 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
8124 callback
= create_test_callback(TRUE
);
8125 hr
= wait_media_event(session
, callback
, MESessionStarted
, 1000, &propvar
);
8126 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
8128 hr
= IMFMediaSession_GetSessionCapabilities(session
, &caps
);
8129 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
8130 ok((caps
& MFSESSIONCAP_SEEK
) == 0, "Got unexpected caps %#lx\n", caps
);
8134 propvar
.hVal
.QuadPart
= 10000000;
8135 hr
= IMFMediaSession_Start(session
, &GUID_NULL
, &propvar
);
8136 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
8137 hr
= wait_media_event(session
, callback
, MESessionStarted
, 1000, &propvar
);
8138 ok(hr
== E_FAIL
, "Unexpected hr %#lx.\n", hr
);
8139 hr
= IMFPresentationClock_GetTime(presentation_clock
, &time
);
8140 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
8141 ok(llabs(time
) <= allowed_error
, "Unexpected time %I64d.\n", time
);
8143 hr
= IMFMediaSession_Stop(session
);
8144 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
8145 hr
= IMFMediaSession_Close(session
);
8146 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
8147 hr
= IMFMediaSession_Shutdown(session
);
8148 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
8149 hr
= IMFMediaSource_Shutdown(source
);
8150 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
8152 IMFPresentationClock_Release(presentation_clock
);
8153 IMFAsyncCallback_Release(callback
);
8154 IMFMediaSession_Release(session
);
8155 IMFMediaSource_Release(source
);
8156 IMFActivate_ShutdownObject(sink_activate
);
8157 IMFActivate_Release(sink_activate
);
8158 IMFSampleGrabberSinkCallback_Release(&grabber_callback
->IMFSampleGrabberSinkCallback_iface
);
8160 /* Test object state transitions */
8161 for (initial_state
= SOURCE_STOPPED
; initial_state
<= SOURCE_PAUSED
; initial_state
++)
8163 winetest_push_context("Test %d", initial_state
);
8165 source
= create_test_seek_source(TRUE
);
8166 callback
= create_test_callback(TRUE
);
8168 grabber_callback
= impl_from_IMFSampleGrabberSinkCallback(create_test_grabber_callback());
8169 hr
= MFCreateMediaType(&output_type
);
8170 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
8171 init_media_type(output_type
, video_rgb32_desc
, -1);
8172 hr
= MFCreateSampleGrabberSinkActivate(output_type
, &grabber_callback
->IMFSampleGrabberSinkCallback_iface
, &sink_activate
);
8173 ok(hr
== S_OK
, "Failed to create grabber sink, hr %#lx.\n", hr
);
8174 IMFMediaType_Release(output_type
);
8176 hr
= MFCreateMediaSession(NULL
, &session
);
8177 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
8178 topology
= create_test_topology(source
, sink_activate
, &duration
);
8179 hr
= IMFMediaSession_SetTopology(session
, 0, topology
);
8180 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
8181 IMFTopology_Release(topology
);
8183 hr
= IMFMediaSession_GetClock(session
, &clock
);
8184 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
8185 hr
= IMFClock_QueryInterface(clock
, &IID_IMFPresentationClock
, (void **)&presentation_clock
);
8186 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
8187 hr
= IMFPresentationClock_AddClockStateSink(presentation_clock
, &test_seek_clock_sink
);
8188 ok(hr
== S_OK
, "Failed to add a sink, hr %#lx.\n", hr
);
8189 IMFClock_Release(clock
);
8191 if (initial_state
== SOURCE_RUNNING
|| initial_state
== SOURCE_PAUSED
)
8193 propvar
.vt
= VT_EMPTY
;
8194 hr
= IMFMediaSession_Start(session
, &GUID_NULL
, &propvar
);
8195 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
8196 hr
= wait_media_event(session
, callback
, MESessionStarted
, 5000, &propvar
);
8197 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
8199 if (initial_state
== SOURCE_PAUSED
)
8201 hr
= IMFMediaSession_Pause(session
);
8202 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
8203 hr
= wait_media_event(session
, callback
, MESessionPaused
, 5000, &propvar
);
8204 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
8208 memset(&actual_object_state_record
, 0, sizeof(actual_object_state_record
));
8211 propvar
.hVal
.QuadPart
= 10000000;
8212 hr
= IMFMediaSession_Start(session
, &GUID_NULL
, &propvar
);
8213 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
8214 hr
= wait_media_event(session
, callback
, MESessionStarted
, 5000, &propvar
);
8215 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
8216 todo_wine_if(initial_state
== SOURCE_PAUSED
)
8217 compare_object_states(&actual_object_state_record
, &expected_object_state_records
[initial_state
]);
8219 hr
= IMFMediaSession_Stop(session
);
8220 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
8221 hr
= IMFMediaSession_Close(session
);
8222 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
8223 hr
= IMFMediaSession_Shutdown(session
);
8224 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
8225 hr
= IMFMediaSource_Shutdown(source
);
8226 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
8228 IMFPresentationClock_RemoveClockStateSink(presentation_clock
, &test_seek_clock_sink
);
8229 IMFPresentationClock_Release(presentation_clock
);
8230 IMFAsyncCallback_Release(callback
);
8231 IMFMediaSession_Release(session
);
8232 IMFMediaSource_Release(source
);
8233 IMFActivate_ShutdownObject(sink_activate
);
8234 IMFActivate_Release(sink_activate
);
8235 IMFSampleGrabberSinkCallback_Release(&grabber_callback
->IMFSampleGrabberSinkCallback_iface
);
8236 winetest_pop_context();
8240 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
8249 win_skip("Skipping tests on Vista.\n");
8254 test_topology_tee_node();
8255 test_topology_loader();
8256 test_topology_loader_evr();
8257 test_MFGetService();
8258 test_sequencer_source();
8259 test_media_session();
8260 test_media_session_events();
8261 test_media_session_rate_control();
8262 test_MFShutdownObject();
8263 test_presentation_clock();
8264 test_sample_grabber();
8265 test_sample_grabber_is_mediatype_supported();
8266 test_sample_grabber_orientation(MFVideoFormat_RGB32
);
8267 test_sample_grabber_orientation(MFVideoFormat_NV12
);
8268 test_quality_manager();
8271 test_MFCreateSimpleTypeHandler();
8272 test_MFGetSupportedMimeTypes();
8273 test_MFGetSupportedSchemes();
8274 test_scheme_resolvers();
8275 test_MFGetTopoNodeCurrentType();
8276 test_MFRequireProtectedEnvironment();
8277 test_mpeg4_media_sink();
8278 test_MFCreateSequencerSegmentOffset();
8279 test_media_session_Start();