mf/test: Check the topologies id's in topo loader.
[wine.git] / dlls / mf / tests / mf.c
blob58688c0cfba07e37d9a3b04cce95f85ca8181ff2
1 /*
2 * Unit tests for mf.dll.
4 * Copyright 2017 Nikolay Sivov
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #include <stdarg.h>
22 #include <string.h>
23 #include <float.h>
25 #define COBJMACROS
26 #include "windef.h"
27 #include "winbase.h"
29 #include "d3d9.h"
30 #include "mfapi.h"
31 #include "mferror.h"
32 #include "mfidl.h"
33 #include "mmdeviceapi.h"
34 #include "uuids.h"
35 #include "wmcodecdsp.h"
36 #include "nserror.h"
38 #include "mf_test.h"
40 #include "wine/test.h"
42 #include "initguid.h"
43 #include "evr9.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) \
52 do { \
53 ok(expect_ ##func, "unexpected call " #func "\n"); \
54 called_ ## func = TRUE; \
55 }while(0)
57 #define CHECK_EXPECT(func) \
58 do { \
59 CHECK_EXPECT2(func); \
60 expect_ ## func = FALSE; \
61 }while(0)
63 #define CHECK_CALLED(func) \
64 do { \
65 ok(called_ ## func, "expected " #func "\n"); \
66 expect_ ## func = called_ ## func = FALSE; \
67 }while(0)
69 #define CHECK_NOT_CALLED(func) \
70 do { \
71 ok(!called_ ## func, "unexpected " #func "\n"); \
72 expect_ ## func = called_ ## func = FALSE; \
73 }while(0)
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)
93 ULONG refcount;
94 IUnknown_AddRef(obj);
95 refcount = IUnknown_Release(obj);
96 ok_(__FILE__, line)(refcount == expected_refcount, "Unexpected refcount %ld, expected %ld.\n", refcount,
97 expected_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;
105 IUnknown *unk;
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);
111 if (SUCCEEDED(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;
120 IUnknown *unk;
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);
126 if (SUCCEEDED(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;
143 IMFSample *sample;
144 DWORD length;
145 BYTE *buffer;
146 HRESULT hr;
147 ULONG ret;
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);
167 return sample;
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;
175 HRESULT hr;
176 ULONG ref;
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)
204 HRESULT hr;
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);
212 if (current_desc)
214 IMFMediaTypeHandler *handler;
215 IMFMediaType *type;
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)
234 HRESULT hr;
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);
244 if (method != -1)
246 hr = IMFTopologyNode_SetUINT32(node, &MF_TOPONODE_CONNECT_METHOD, method);
247 ok(hr == S_OK, "Failed to set connect method, hr %#lx.\n", hr);
250 if (source)
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)
259 HRESULT hr;
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);
267 if (method != -1)
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);
278 struct test_source
280 IMFMediaSource IMFMediaSource_iface;
281 LONG refcount;
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))
297 *out = iface;
299 else
301 *out = NULL;
302 return E_NOINTERFACE;
305 IMFMediaSource_AddRef(iface);
306 return S_OK;
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);
320 if (!refcount)
322 IMFPresentationDescriptor_Release(source->pd);
323 free(source);
326 return refcount;
329 static HRESULT WINAPI test_source_GetEvent(IMFMediaSource *iface, DWORD flags, IMFMediaEvent **event)
331 ok(0, "Unexpected call.\n");
332 return E_NOTIMPL;
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");
345 return E_NOTIMPL;
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);
352 return E_NOTIMPL;
355 static HRESULT WINAPI test_source_GetCharacteristics(IMFMediaSource *iface, DWORD *flags)
357 *flags = 0;
358 return S_OK;
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);
371 return E_NOTIMPL;
374 static HRESULT WINAPI test_source_Stop(IMFMediaSource *iface)
376 ok(0, "Unexpected call.\n");
377 return E_NOTIMPL;
380 static HRESULT WINAPI test_source_Pause(IMFMediaSource *iface)
382 ok(0, "Unexpected call.\n");
383 return E_NOTIMPL;
386 static HRESULT WINAPI test_source_Shutdown(IMFMediaSource *iface)
388 ok(0, "Unexpected call.\n");
389 return E_NOTIMPL;
392 static const IMFMediaSourceVtbl test_source_vtbl =
394 test_source_QueryInterface,
395 test_source_AddRef,
396 test_source_Release,
397 test_source_GetEvent,
398 test_source_BeginGetEvent,
399 test_source_EndGetEvent,
400 test_source_QueueEvent,
401 test_source_GetCharacteristics,
402 test_source_CreatePresentationDescriptor,
403 test_source_Start,
404 test_source_Stop,
405 test_source_Pause,
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))
426 *obj = iface;
427 IUnknown_AddRef(iface);
428 return S_OK;
431 *obj = NULL;
432 return E_NOINTERFACE;
435 static ULONG WINAPI test_unk_AddRef(IUnknown *iface)
437 return 2;
440 static ULONG WINAPI test_unk_Release(IUnknown *iface)
442 return 1;
445 static const IUnknownVtbl test_unk_vtbl =
447 test_unk_QueryInterface,
448 test_unk_AddRef,
449 test_unk_Release,
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;
462 IUnknown *object;
463 WORD node_count;
464 UINT32 count;
465 HRESULT hr;
466 TOPOID id;
467 LONG ref;
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);
530 node_count = 1;
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);
539 node_count = 0;
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);
590 node_count = 0;
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);
608 node_count = 0;
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);
616 node_count = 1;
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);
846 /* Source node. */
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);
867 /* Tee node. */
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);
952 if (SUCCEEDED(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);
965 /* Connect nodes. */
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);
972 EXPECT_REF(node, 1);
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);
978 EXPECT_REF(node, 2);
979 EXPECT_REF(node2, 2);
981 IMFTopologyNode_Release(node);
983 EXPECT_REF(node, 1);
984 EXPECT_REF(node2, 2);
986 IMFTopologyNode_Release(node2);
988 EXPECT_REF(node, 1);
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;
1255 DWORD count;
1256 HRESULT hr;
1257 LONG ref;
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))
1329 *obj = iface;
1330 return S_OK;
1333 *obj = NULL;
1334 return E_NOINTERFACE;
1337 static ULONG WINAPI test_getservice_AddRef(IMFGetService *iface)
1339 return 2;
1342 static ULONG WINAPI test_getservice_Release(IMFGetService *iface)
1344 return 1;
1347 static HRESULT WINAPI test_getservice_GetService(IMFGetService *iface, REFGUID service, REFIID riid, void **obj)
1349 *obj = (void *)0xdeadbeef;
1350 return 0x83eddead;
1353 static const IMFGetServiceVtbl testmfgetservicevtbl =
1355 test_getservice_QI,
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))
1367 *obj = iface;
1368 return S_OK;
1371 *obj = NULL;
1373 if (IsEqualIID(riid, &IID_IMFGetService))
1374 return 0x82eddead;
1376 return E_NOINTERFACE;
1379 static HRESULT WINAPI testservice2_QI(IUnknown *iface, REFIID riid, void **obj)
1381 if (IsEqualIID(riid, &IID_IUnknown))
1383 *obj = iface;
1384 return S_OK;
1387 if (IsEqualIID(riid, &IID_IMFGetService))
1389 *obj = &test_getservice;
1390 return S_OK;
1393 *obj = NULL;
1394 return E_NOINTERFACE;
1397 static ULONG WINAPI testservice_AddRef(IUnknown *iface)
1399 return 2;
1402 static ULONG WINAPI testservice_Release(IUnknown *iface)
1404 return 1;
1407 static const IUnknownVtbl testservicevtbl =
1409 testservice_QI,
1410 testservice_AddRef,
1411 testservice_Release,
1414 static const IUnknownVtbl testservice2vtbl =
1416 testservice2_QI,
1417 testservice_AddRef,
1418 testservice_Release,
1421 static IUnknown testservice = { &testservicevtbl };
1422 static IUnknown testservice2 = { &testservice2vtbl };
1424 static void test_MFGetService(void)
1426 IUnknown *unk;
1427 HRESULT hr;
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");
1445 unk = NULL;
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;
1454 HRESULT hr;
1455 LONG ref;
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);
1468 hr = MFShutdown();
1469 ok(hr == S_OK, "Shutdown failure, hr %#lx.\n", hr);
1472 struct test_handler
1474 IMFMediaTypeHandler IMFMediaTypeHandler_iface;
1476 ULONG set_current_count;
1477 IMFMediaType *current_type;
1478 IMFMediaType *invalid_type;
1480 ULONG enum_count;
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));
1496 return S_OK;
1499 *obj = NULL;
1500 return E_NOINTERFACE;
1503 static ULONG WINAPI test_handler_AddRef(IMFMediaTypeHandler *iface)
1505 return 2;
1508 static ULONG WINAPI test_handler_Release(IMFMediaTypeHandler *iface)
1510 return 1;
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);
1517 BOOL result;
1519 if (out_type)
1520 *out_type = NULL;
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)
1527 return S_OK;
1529 if (IMFMediaType_Compare(impl->current_type, (IMFAttributes *)in_type,
1530 MF_ATTRIBUTES_MATCH_OUR_ITEMS, &result) == S_OK && result)
1531 return S_OK;
1533 return MF_E_INVALIDMEDIATYPE;
1536 static HRESULT WINAPI test_handler_GetMediaTypeCount(IMFMediaTypeHandler *iface, DWORD *count)
1538 ok(0, "Unexpected call.\n");
1539 return E_NOTIMPL;
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)
1549 impl->enum_count++;
1551 if (index >= impl->media_types_count)
1552 return MF_E_NO_MORE_TYPES;
1554 IMFMediaType_AddRef((*type = impl->media_types[index]));
1555 return S_OK;
1558 ok(0, "Unexpected call.\n");
1559 return E_NOTIMPL;
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++;
1571 return S_OK;
1574 static HRESULT WINAPI test_handler_GetCurrentMediaType(IMFMediaTypeHandler *iface, IMFMediaType **media_type)
1576 struct test_handler *impl = impl_from_IMFMediaTypeHandler(iface);
1577 HRESULT hr;
1579 if (!impl->current_type)
1581 if (!impl->media_types)
1582 return E_FAIL;
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)))
1589 return hr;
1591 hr = IMFMediaType_CopyAllItems(impl->current_type, (IMFAttributes *)*media_type);
1592 if (FAILED(hr))
1593 IMFMediaType_Release(*media_type);
1595 return hr;
1598 static HRESULT WINAPI test_handler_GetMajorType(IMFMediaTypeHandler *iface, GUID *type)
1600 ok(0, "Unexpected call.\n");
1601 return E_NOTIMPL;
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;
1622 BOOL shutdown;
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));
1636 return S_OK;
1639 *obj = NULL;
1640 return E_NOINTERFACE;
1643 static ULONG WINAPI test_media_sink_AddRef(IMFMediaSink *iface)
1645 return 2;
1648 static ULONG WINAPI test_media_sink_Release(IMFMediaSink *iface)
1650 return 1;
1653 static HRESULT WINAPI test_media_sink_GetCharacteristics(IMFMediaSink *iface, DWORD *characteristics)
1655 *characteristics = 0;
1656 return S_OK;
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");
1663 return E_NOTIMPL;
1666 static HRESULT WINAPI test_media_sink_RemoveStreamSink(IMFMediaSink *iface, DWORD stream_sink_id)
1668 ok(0, "Unexpected call.\n");
1669 return E_NOTIMPL;
1672 static HRESULT WINAPI test_media_sink_GetStreamSinkCount(IMFMediaSink *iface, DWORD *count)
1674 ok(0, "Unexpected call.\n");
1675 return E_NOTIMPL;
1678 static HRESULT WINAPI test_media_sink_GetStreamSinkByIndex(IMFMediaSink *iface, DWORD index, IMFStreamSink **sink)
1680 ok(0, "Unexpected call.\n");
1681 return E_NOTIMPL;
1684 static HRESULT WINAPI test_media_sink_GetStreamSinkById(IMFMediaSink *iface, DWORD stream_sink_id, IMFStreamSink **sink)
1686 ok(0, "Unexpected call.\n");
1687 return E_NOTIMPL;
1690 static HRESULT WINAPI test_media_sink_SetPresentationClock(IMFMediaSink *iface, IMFPresentationClock *clock)
1692 ok(0, "Unexpected call.\n");
1693 return E_NOTIMPL;
1696 static HRESULT WINAPI test_media_sink_GetPresentationClock(IMFMediaSink *iface, IMFPresentationClock **clock)
1698 ok(0, "Unexpected call.\n");
1699 return E_NOTIMPL;
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;
1707 return S_OK;
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));
1747 return S_OK;
1750 *obj = NULL;
1751 return E_NOINTERFACE;
1754 static ULONG WINAPI test_stream_sink_AddRef(IMFStreamSink *iface)
1756 return 2;
1759 static ULONG WINAPI test_stream_sink_Release(IMFStreamSink *iface)
1761 return 1;
1764 static HRESULT WINAPI test_stream_sink_GetEvent(IMFStreamSink *iface, DWORD flags, IMFMediaEvent **event)
1766 ok(0, "Unexpected call.\n");
1767 return E_NOTIMPL;
1770 static HRESULT WINAPI test_stream_sink_BeginGetEvent(IMFStreamSink *iface, IMFAsyncCallback *callback, IUnknown *state)
1772 ok(0, "Unexpected call.\n");
1773 return E_NOTIMPL;
1776 static HRESULT WINAPI test_stream_sink_EndGetEvent(IMFStreamSink *iface, IMFAsyncResult *result,
1777 IMFMediaEvent **event)
1779 ok(0, "Unexpected call.\n");
1780 return E_NOTIMPL;
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");
1787 return E_NOTIMPL;
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));
1797 return S_OK;
1800 todo_wine
1801 ok(0, "Unexpected call.\n");
1802 return E_NOTIMPL;
1805 static HRESULT WINAPI test_stream_sink_GetIdentifier(IMFStreamSink *iface, DWORD *id)
1807 ok(0, "Unexpected call.\n");
1808 return E_NOTIMPL;
1811 static HRESULT WINAPI test_stream_sink_GetMediaTypeHandler(IMFStreamSink *iface, IMFMediaTypeHandler **handler)
1813 struct test_stream_sink *impl = impl_from_IMFStreamSink(iface);
1815 if (impl->handler)
1817 IMFMediaTypeHandler_AddRef((*handler = impl->handler));
1818 return S_OK;
1821 ok(0, "Unexpected call.\n");
1822 return E_NOTIMPL;
1825 static HRESULT WINAPI test_stream_sink_ProcessSample(IMFStreamSink *iface, IMFSample *sample)
1827 ok(0, "Unexpected call.\n");
1828 return E_NOTIMPL;
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");
1835 return E_NOTIMPL;
1838 static HRESULT WINAPI test_stream_sink_Flush(IMFStreamSink *iface)
1840 ok(0, "Unexpected call.\n");
1841 return E_NOTIMPL;
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;
1866 LONG refcount;
1868 HANDLE event;
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))
1883 *obj = iface;
1884 IMFAsyncCallback_AddRef(iface);
1885 return S_OK;
1888 *obj = NULL;
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);
1903 if (!refcount)
1905 if (callback->media_event)
1906 IMFMediaEvent_Release(callback->media_event);
1907 CloseHandle(callback->event);
1908 free(callback);
1911 return refcount;
1914 static HRESULT WINAPI testcallback_GetParameters(IMFAsyncCallback *iface, DWORD *flags, DWORD *queue)
1916 ok(flags != NULL && queue != NULL, "Unexpected arguments.\n");
1917 return E_NOTIMPL;
1920 static HRESULT WINAPI testcallback_Invoke(IMFAsyncCallback *iface, IMFAsyncResult *result)
1922 struct test_callback *callback = CONTAINING_RECORD(iface, struct test_callback, IMFAsyncCallback_iface);
1923 IUnknown *object;
1924 HRESULT hr;
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);
1946 return S_OK;
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))))
1963 return NULL;
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;
1980 HRESULT hr, status;
1981 DWORD ret;
1982 GUID guid;
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);
2006 return status;
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;
2015 HRESULT hr, status;
2016 DWORD ret;
2017 GUID guid;
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);
2041 return status;
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;
2052 ULONG resource_len;
2053 HRSRC resource;
2054 HRESULT hr;
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);
2083 if (FAILED(hr))
2084 return NULL;
2086 ok(obj_type == MF_OBJECT_MEDIASOURCE, "got %d\n", obj_type);
2087 return source;
2090 enum object_state
2092 SOURCE_START,
2093 SOURCE_PAUSE,
2094 SOURCE_STOP,
2095 SOURCE_SHUTDOWN,
2096 SINK_ON_CLOCK_START,
2097 SINK_ON_CLOCK_PAUSE,
2098 SINK_ON_CLOCK_STOP,
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");
2129 enum source_state
2131 SOURCE_STOPPED,
2132 SOURCE_RUNNING,
2133 SOURCE_PAUSED,
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;
2144 BOOL is_new;
2145 LONG refcount;
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))
2159 *out = iface;
2161 else
2163 *out = NULL;
2164 return E_NOINTERFACE;
2167 IMFMediaStream_AddRef(iface);
2168 return S_OK;
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);
2182 if (!refcount)
2184 IMFMediaEventQueue_Release(stream->event_queue);
2185 free(stream);
2188 return refcount;
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);
2223 return S_OK;
2226 static HRESULT WINAPI test_media_stream_GetStreamDescriptor(IMFMediaStream *iface, IMFStreamDescriptor **sd)
2228 struct test_media_stream *stream = impl_from_IMFMediaStream(iface);
2230 *sd = stream->sd;
2231 IMFStreamDescriptor_AddRef(*sd);
2233 return S_OK;
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;
2240 IMFSample *sample;
2241 HRESULT hr;
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;
2255 else
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);
2264 if (token)
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);
2279 return S_OK;
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;
2307 BOOL seekable;
2308 LONG refcount;
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))
2322 *out = iface;
2324 else
2326 *out = NULL;
2327 return E_NOINTERFACE;
2330 IMFMediaSource_AddRef(iface);
2331 return S_OK;
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);
2345 if (!refcount)
2347 IMFMediaEventQueue_Release(source->event_queue);
2348 free(source);
2351 return refcount;
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;
2385 else
2386 *flags = MFMEDIASOURCE_CAN_PAUSE;
2387 return S_OK;
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;
2395 HRESULT hr = S_OK;
2396 int i;
2398 EnterCriticalSection(&source->cs);
2400 if (source->pd)
2402 *pd = source->pd;
2403 IMFPresentationDescriptor_AddRef(*pd);
2405 else
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]);
2434 *pd = source->pd;
2435 IMFPresentationDescriptor_AddRef(*pd);
2438 LeaveCriticalSection(&source->cs);
2440 return hr;
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);
2451 return selected;
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;
2459 PROPVARIANT var;
2460 HRESULT hr;
2461 int i;
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)
2475 return E_FAIL;
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))
2486 continue;
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,
2497 S_OK, NULL);
2498 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2501 source->state = SOURCE_RUNNING;
2503 LeaveCriticalSection(&source->cs);
2505 return S_OK;
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;
2512 HRESULT hr;
2513 int i;
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))
2526 continue;
2528 event_type = MEStreamStopped;
2529 hr = IMFMediaEventQueue_QueueEventParamVar(source->streams[i]->event_queue, event_type, &GUID_NULL,
2530 S_OK, NULL);
2531 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2534 source->state = SOURCE_STOPPED;
2536 LeaveCriticalSection(&source->cs);
2538 return S_OK;
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;
2545 HRESULT hr;
2546 int i;
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))
2559 continue;
2561 event_type = MEStreamPaused;
2562 hr = IMFMediaEventQueue_QueueEventParamVar(source->streams[i]->event_queue, event_type, &GUID_NULL,
2563 S_OK, NULL);
2564 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2567 source->state = SOURCE_PAUSED;
2568 LeaveCriticalSection(&source->cs);
2570 return S_OK;
2573 static HRESULT WINAPI test_seek_source_Shutdown(IMFMediaSource *iface)
2575 struct test_seek_source *source = impl_test_seek_source_from_IMFMediaSource(iface);
2576 HRESULT hr;
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);
2583 return S_OK;
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))
2608 *obj = iface;
2609 IMFClockStateSink_AddRef(iface);
2610 return S_OK;
2613 *obj = NULL;
2614 return E_NOINTERFACE;
2617 static ULONG WINAPI test_seek_clock_sink_AddRef(IMFClockStateSink *iface)
2619 return 2;
2622 static ULONG WINAPI test_seek_clock_sink_Release(IMFClockStateSink *iface)
2624 return 1;
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);
2630 return S_OK;
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);
2636 return S_OK;
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);
2642 return S_OK;
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);
2648 return S_OK;
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);
2654 return S_OK;
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;
2673 BOOL selected;
2674 HRESULT hr;
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);
2689 return stream;
2692 static IMFMediaSource *create_test_seek_source(BOOL seekable)
2694 struct test_seek_source *source;
2695 int i;
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;
2748 HRESULT hr;
2749 ULONG ref;
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);
2766 /* Async case. */
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);
2828 todo_wine
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);
2835 todo_wine
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);
2980 todo_wine
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);
3239 hr = MFShutdown();
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;
3252 IMFGetService *gs;
3253 IMFClock *clock;
3254 HRESULT hr;
3255 DWORD caps;
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;
3368 IMFClock *clock;
3369 HRESULT hr;
3370 float rate;
3371 BOOL thin;
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);
3388 rate = 0.0f;
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);
3396 thin = TRUE;
3397 rate = 0.0f;
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);
3412 rate = 0.0f;
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);
3435 rate = 0.0f;
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);
3451 hr = MFShutdown();
3452 ok(hr == S_OK, "Shutdown failure, hr %#lx.\n", hr);
3455 struct test_grabber_callback
3457 IMFSampleGrabberSinkCallback IMFSampleGrabberSinkCallback_iface;
3458 LONG refcount;
3460 IMFCollection *samples;
3461 HANDLE ready_event;
3462 HANDLE done_event;
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))
3476 *obj = iface;
3477 IMFSampleGrabberSinkCallback_AddRef(iface);
3478 return S_OK;
3481 *obj = NULL;
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);
3496 if (!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);
3503 free(grabber);
3506 return refcount;
3509 static HRESULT WINAPI test_grabber_callback_OnClockStart(IMFSampleGrabberSinkCallback *iface, MFTIME time, LONGLONG offset)
3511 return S_OK;
3514 static HRESULT WINAPI test_grabber_callback_OnClockStop(IMFSampleGrabberSinkCallback *iface, MFTIME time)
3516 return S_OK;
3519 static HRESULT WINAPI test_grabber_callback_OnClockPause(IMFSampleGrabberSinkCallback *iface, MFTIME time)
3521 return S_OK;
3524 static HRESULT WINAPI test_grabber_callback_OnClockRestart(IMFSampleGrabberSinkCallback *iface, MFTIME time)
3526 return S_OK;
3529 static HRESULT WINAPI test_grabber_callback_OnClockSetRate(IMFSampleGrabberSinkCallback *iface, MFTIME time, float rate)
3531 return S_OK;
3534 static HRESULT WINAPI test_grabber_callback_OnSetPresentationClock(IMFSampleGrabberSinkCallback *iface,
3535 IMFPresentationClock *clock)
3537 return S_OK;
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);
3544 IMFSample *sample;
3545 HRESULT hr;
3546 DWORD res;
3548 if (!grabber->ready_event)
3549 return E_NOTIMPL;
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);
3566 return S_OK;
3569 static HRESULT WINAPI test_grabber_callback_OnShutdown(IMFSampleGrabberSinkCallback *iface)
3571 return S_OK;
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;
3592 HRESULT hr;
3594 if (!(grabber = calloc(1, sizeof(*grabber))))
3595 return NULL;
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
3607 LOADER_TODO = 0x4,
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;
3756 unsigned int flags;
3757 GUID decoder_class;
3758 GUID converter_class;
3760 loader_tests[] =
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,
3862 /* MP3 -> PCM */
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,
3875 /* MP3 -> PCM */
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,
3882 /* MP3 -> PCM */
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;
3953 WORD node_count;
3954 TOPOID node_id, oldtopoid, newtopoid;
3955 DWORD index;
3956 HRESULT hr;
3957 BOOL ret;
3958 LONG ref;
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;
4086 else
4087 IMFMediaType_AddRef((handler.current_type = output_type));
4089 if (test->flags & LOADER_SET_INVALID_INPUT)
4090 handler.invalid_type = input_type;
4091 else
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;
4100 else
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);
4134 else
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);
4165 else
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);
4187 todo_wine
4188 ok(count == (test->flags & LOADER_SET_ENUMERATE_SOURCE_TYPES ? 2 : 1),
4189 "Unexpected count %u.\n", count);
4191 value = 0xdeadbeef;
4192 hr = IMFTopology_GetUINT32(full_topology, &MF_TOPOLOGY_RESOLUTION_STATUS, &value);
4193 todo_wine {
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);
4197 count = 2;
4198 if (!IsEqualGUID(&test->decoder_class, &GUID_NULL))
4199 count++;
4200 if (!IsEqualGUID(&test->converter_class, &GUID_NULL))
4201 count++;
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))
4222 GUID class_id;
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);
4232 value = 0;
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))
4276 GUID class_id;
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);
4350 else
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);
4388 hr = MFShutdown();
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),
4402 {0},
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;
4414 IMFMediaSink *sink;
4415 WORD node_count;
4416 UINT64 value64;
4417 HWND window;
4418 HRESULT hr;
4419 LONG ref;
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);
4431 if (FAILED(hr))
4433 skip("Failed to create an EVR sink, skipping tests.\n");
4434 DestroyWindow(window);
4435 IMFActivate_Release(activate);
4436 CoUninitialize();
4437 return;
4439 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4441 hr = MFCreateTopoLoader(&loader);
4442 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4444 /* Source node. */
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);
4509 switch (node_type)
4511 case MF_TOPOLOGY_OUTPUT_NODE:
4513 value = 1;
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);
4517 break;
4519 case MF_TOPOLOGY_TRANSFORM_NODE:
4521 IMFAttributes *attrs;
4522 IMFTransform *copier;
4523 IUnknown *obj;
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);
4534 value = 0xdeadbeef;
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);
4541 break;
4543 case MF_TOPOLOGY_SOURCESTREAM_NODE:
4545 value64 = 1;
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");
4549 break;
4551 default:
4552 ok(0, "Got unexpected node type %u.\n", node_type);
4553 break;
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);
4582 CoUninitialize();
4585 static HRESULT WINAPI testshutdown_QueryInterface(IMFShutdown *iface, REFIID riid, void **obj)
4587 if (IsEqualIID(riid, &IID_IMFShutdown) ||
4588 IsEqualIID(riid, &IID_IUnknown))
4590 *obj = iface;
4591 IMFShutdown_AddRef(iface);
4592 return S_OK;
4595 *obj = NULL;
4596 return E_NOINTERFACE;
4599 static ULONG WINAPI testshutdown_AddRef(IMFShutdown *iface)
4601 return 2;
4604 static ULONG WINAPI testshutdown_Release(IMFShutdown *iface)
4606 return 1;
4609 static HRESULT WINAPI testshutdown_Shutdown(IMFShutdown *iface)
4611 return 0xdead;
4614 static HRESULT WINAPI testshutdown_GetShutdownStatus(IMFShutdown *iface, MFSHUTDOWN_STATUS *status)
4616 ok(0, "Unexpected call.\n");
4617 return E_NOTIMPL;
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 };
4633 HRESULT hr;
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);
4645 enum clock_action
4647 CLOCK_START,
4648 CLOCK_STOP,
4649 CLOCK_PAUSE,
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))
4657 *obj = iface;
4658 IMFClockStateSink_AddRef(iface);
4659 return S_OK;
4662 *obj = NULL;
4663 return E_NOINTERFACE;
4666 static ULONG WINAPI test_clock_sink_AddRef(IMFClockStateSink *iface)
4668 return 2;
4671 static ULONG WINAPI test_clock_sink_Release(IMFClockStateSink *iface)
4673 return 1;
4676 static HRESULT WINAPI test_clock_sink_OnClockStart(IMFClockStateSink *iface, MFTIME system_time, LONGLONG offset)
4678 return E_NOTIMPL;
4681 static HRESULT WINAPI test_clock_sink_OnClockStop(IMFClockStateSink *iface, MFTIME system_time)
4683 return E_NOTIMPL;
4686 static HRESULT WINAPI test_clock_sink_OnClockPause(IMFClockStateSink *iface, MFTIME system_time)
4688 return E_NOTIMPL;
4691 static HRESULT WINAPI test_clock_sink_OnClockRestart(IMFClockStateSink *iface, MFTIME system_time)
4693 return E_NOTIMPL;
4696 static HRESULT WINAPI test_clock_sink_OnClockSetRate(IMFClockStateSink *iface, MFTIME system_time, float rate)
4698 return E_NOTIMPL;
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;
4720 HRESULT hr;
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;
4753 IMFTimer *timer;
4754 unsigned int i;
4755 DWORD t1, t2;
4756 DWORD value;
4757 float rate;
4758 HRESULT hr;
4759 BOOL thin;
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);
4794 value = 1;
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);
4815 /* Sinks. */
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)
4889 case CLOCK_STOP:
4890 hr = IMFPresentationClock_Stop(clock);
4891 break;
4892 case CLOCK_PAUSE:
4893 hr = IMFPresentationClock_Pause(clock);
4894 break;
4895 case CLOCK_START:
4896 hr = IMFPresentationClock_Start(clock, 0);
4897 break;
4898 default:
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);
5017 time_source = NULL;
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);
5044 hr = MFShutdown();
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;
5062 UINT32 attr_count;
5063 float rate;
5064 HRESULT hr;
5065 GUID guid;
5066 LONG ref;
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);
5206 /* Set clock. */
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);
5384 id = 1;
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);
5475 /* Detaching */
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);
5507 hr = MFShutdown();
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;
5520 IMFMediaSink *sink;
5521 HRESULT hr;
5522 GUID guid;
5523 LONG ref;
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;
5636 BOOL selected;
5637 HRESULT hr;
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);
5656 if (duration)
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);
5673 return topology;
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;
5692 HRESULT hr;
5693 DWORD res;
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");
5701 goto done;
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);
5784 done:
5785 hr = MFShutdown();
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;
5794 HRESULT hr;
5795 LONG ref;
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);
5859 /* Set topology. */
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);
5902 hr = MFShutdown();
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;
5912 HRESULT hr;
5913 float rate;
5915 hr = IMFMediaSink_QueryInterface(sink, &IID_IMFRateSupport, (void **)&rate_support);
5916 todo_wine
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);
5933 return;
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);
5949 if (SUCCEEDED(hr))
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);
5977 else
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),
6019 {0},
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),
6030 {0},
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;
6047 IMFClock *clock;
6048 IUnknown *unk;
6049 HRESULT hr;
6050 GUID guid;
6051 BOOL mute;
6052 LONG ref;
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");
6061 CoUninitialize();
6062 return;
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);
6073 todo_wine
6074 ok(hr == S_OK, "Failed to get time source interface, hr %#lx.\n", hr);
6076 if (SUCCEEDED(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);
6134 /* Clock */
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);
6156 todo_wine
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);
6177 /* Stream */
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));
6206 count = 0;
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);
6340 /* Shutdown */
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);
6379 todo_wine
6380 ok(ref == 0, "Release returned %ld\n", ref);
6382 /* Activation */
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);
6405 todo_wine
6406 ok(sink == sink2, "Unexpected instance.\n");
6408 hr = IMFMediaSink_GetCharacteristics(sink2, &flags);
6409 todo_wine
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);
6428 hr = MFShutdown();
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);
6435 /* Specify role. */
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);
6465 CoUninitialize();
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;
6488 IMFRateSupport *rs;
6489 DWORD flags, count;
6490 LONG sample_count;
6491 IMFSample *sample;
6492 unsigned int i;
6493 UINT64 window3;
6494 float rate;
6495 HRESULT hr;
6496 GUID guid;
6497 LONG ref;
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);
6503 if (FAILED(hr))
6505 skip("Failed to create video renderer object, skipping tests.\n");
6506 MFShutdown();
6507 return;
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);
6526 /* Window */
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);
6560 window2 = NULL;
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);
6617 value = 0;
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);
6621 value = 0;
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);
6643 count = 1;
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);
6704 todo_wine {
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);
6720 sample_count = 0;
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);
6736 if (SUCCEEDED(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);
6763 todo_wine
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);
6775 todo_wine
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);
6785 todo_wine
6786 ok(ref == 0, "Release returned %ld\n", ref);
6788 /* Set clock. */
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);
6815 rate = 1.0f;
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);
6820 rate = 1.0f;
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);
6825 rate = 1.0f;
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);
6830 rate = 1.0f;
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);
6890 rate = 1.0f;
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);
6895 rate = 1.0f;
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);
6900 rate = 0.0f;
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);
6905 rate = 0.0f;
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);
6968 hr = MFShutdown();
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;
6976 DWORD count;
6977 HRESULT hr;
6978 GUID guid;
6979 LONG ref;
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);
6990 count = 0;
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)
7125 PROPVARIANT value;
7126 HRESULT hr;
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)
7141 PROPVARIANT value;
7142 HRESULT hr;
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;
7180 IUnknown *object;
7181 UINT64 length;
7182 DWORD i, caps;
7183 HRESULT hr;
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);
7196 if (hr != S_OK)
7197 continue;
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);
7207 if (hr == S_OK)
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);
7218 todo_wine
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);
7226 todo_wine
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);
7239 todo_wine
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);
7242 todo_wine
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);
7246 todo_wine
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);
7249 todo_wine
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);
7252 todo_wine
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);
7255 todo_wine
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);
7258 todo_wine
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);
7262 todo_wine
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);
7265 todo_wine
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);
7268 todo_wine
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);
7271 todo_wine
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);
7274 todo_wine
7275 ok(hr == MF_E_UNSUPPORTED_BYTESTREAM_TYPE, "got hr %#lx\n", hr);
7277 IMFSourceResolver_Release(resolver);
7279 hr = MFShutdown();
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),
7290 {0},
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;
7298 DWORD flags;
7299 HRESULT hr;
7300 LONG ref;
7302 if (!pMFGetTopoNodeCurrentType)
7304 win_skip("MFGetTopoNodeCurrentType() is unsupported.\n");
7305 return;
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);
7337 /* Tee node. */
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);
7413 /* Source node. */
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);
7439 /* Output node. */
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);
7530 CoUninitialize();
7533 void init_functions(void)
7535 HMODULE mod = GetModuleHandleA("mf.dll");
7536 IMFTransform *transform;
7537 HRESULT hr;
7539 #define X(f) p##f = (void*)GetProcAddress(mod, #f)
7540 X(MFCreateSampleCopierMFT);
7541 X(MFGetTopoNodeCurrentType);
7543 mod = GetModuleHandleA("mfplat.dll");
7544 X(MFCreateDXGIDeviceManager);
7545 #undef X
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);
7551 if (hr == S_OK)
7553 has_video_processor = TRUE;
7554 IMFTransform_Release(transform);
7557 CoUninitialize();
7560 static void test_MFRequireProtectedEnvironment(void)
7562 IMFPresentationDescriptor *pd;
7563 IMFMediaType *mediatype;
7564 IMFStreamDescriptor *sd;
7565 HRESULT hr;
7566 LONG ref;
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;
7612 HRESULT hr;
7613 GUID guid;
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);
7668 sink = NULL;
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);
7682 /* Test sink. */
7683 flags = 0xdeadbeef;
7684 hr = IMFMediaSink_GetCharacteristics(sink, &flags);
7685 todo_wine
7686 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
7687 todo_wine
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);
7694 todo_wine
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);
7713 if (sink_empty)
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);
7809 todo_wine
7810 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
7811 todo_wine
7812 hr = IMFMediaSink_SetPresentationClock(sink, clock);
7813 todo_wine
7814 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
7815 IMFPresentationClock_Release(clock);
7817 /* Test stream. */
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);
7832 todo_wine
7833 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
7834 hr = IMFMediaTypeHandler_GetMajorType(type_handler, &guid);
7835 todo_wine
7836 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
7837 todo_wine
7838 ok(IsEqualGUID(&guid, &MFMediaType_Audio), "Unexpected major type.\n");
7840 hr = IMFMediaTypeHandler_GetMediaTypeCount(type_handler, &count);
7841 todo_wine
7842 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
7843 todo_wine
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);
7853 todo_wine
7854 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
7855 hr = IMFMediaTypeHandler_SetCurrentMediaType(type_handler, media_type);
7856 todo_wine
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);
7875 todo_wine
7876 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
7877 hr = IMFMediaTypeHandler_GetMajorType(type_handler, &guid);
7878 todo_wine
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);
7884 todo_wine
7885 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
7886 hr = IMFMediaSink_GetStreamSinkByIndex(sink, 0, &stream_sink);
7887 todo_wine
7888 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
7889 hr = IMFMediaSink_GetStreamSinkById(sink, 0, &stream_sink);
7890 todo_wine
7891 ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
7892 hr = IMFMediaSink_GetCharacteristics(sink, &flags);
7893 todo_wine
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);
7900 if (sink_empty)
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;
7913 HRESULT hr;
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;
7952 IMFClock *clock;
7953 UINT64 duration;
7954 DWORD caps;
7955 HRESULT hr;
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");
7964 MFShutdown();
7965 return;
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);
7996 /* Seek to 1s */
7997 propvar.vt = VT_I8;
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 */
8008 propvar.vt = VT_I8;
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 */
8016 propvar.vt = VT_I8;
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 */
8027 propvar.vt = VT_I8;
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);
8043 propvar.vt = VT_I8;
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);
8053 old_time = time;
8055 /* Expected the presentation clock is running */
8056 Sleep(100);
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);
8072 propvar.vt = VT_I8;
8073 propvar.hVal.QuadPart = 10000000;
8074 hr = IMFMediaSession_Start(session, &GUID_NULL, NULL);
8075 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
8077 propvar.vt = VT_I8;
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);
8132 /* Seek to 1s */
8133 propvar.vt = VT_I8;
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);
8207 /* Seek to 1s */
8208 memset(&actual_object_state_record, 0, sizeof(actual_object_state_record));
8210 propvar.vt = VT_I8;
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();
8239 hr = MFShutdown();
8240 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
8243 START_TEST(mf)
8245 init_functions();
8247 if (is_vista())
8249 win_skip("Skipping tests on Vista.\n");
8250 return;
8253 test_topology();
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();
8269 test_sar();
8270 test_evr();
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();