2 * Video Mixing Renderer 9 unit tests
4 * Copyright 2019 Zebediah Figura
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
31 #include "wmcodecdsp.h"
32 #include "wine/strmbase.h"
33 #include "wine/test.h"
35 static IBaseFilter
*create_vmr9(DWORD mode
)
37 IBaseFilter
*filter
= NULL
;
38 IVMRFilterConfig9
*config
;
39 HRESULT hr
= CoCreateInstance(&CLSID_VideoMixingRenderer9
, NULL
, CLSCTX_INPROC_SERVER
,
40 &IID_IBaseFilter
, (void **)&filter
);
41 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
44 hr
= IBaseFilter_QueryInterface(filter
, &IID_IVMRFilterConfig9
, (void **)&config
);
45 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
46 hr
= IVMRFilterConfig9_SetRenderingMode(config
, mode
);
47 ok(hr
== S_OK
|| broken(hr
== E_FAIL
), "Got hr %#lx.\n", hr
);
48 IVMRFilterConfig9_Release(config
);
53 static HRESULT
set_mixing_mode(IBaseFilter
*filter
, DWORD count
)
55 IVMRFilterConfig9
*config
;
58 hr
= IBaseFilter_QueryInterface(filter
, &IID_IVMRFilterConfig9
, (void **)&config
);
59 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
61 hr
= IVMRFilterConfig9_SetNumberOfStreams(config
, count
);
62 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
64 IVMRFilterConfig9_Release(config
);
68 static inline BOOL
compare_media_types(const AM_MEDIA_TYPE
*a
, const AM_MEDIA_TYPE
*b
)
70 return !memcmp(a
, b
, offsetof(AM_MEDIA_TYPE
, pbFormat
))
71 && !memcmp(a
->pbFormat
, b
->pbFormat
, a
->cbFormat
);
74 static BOOL
compare_double(double f
, double g
, unsigned int ulps
)
76 uint64_t x
= *(ULONGLONG
*)&f
;
77 uint64_t y
= *(ULONGLONG
*)&g
;
82 x
|= ((ULONGLONG
)1)<<63;
86 y
|= ((ULONGLONG
)1)<<63;
88 return (x
>y
? x
-y
: y
-x
) <= ulps
;
91 static IFilterGraph2
*create_graph(void)
95 hr
= CoCreateInstance(&CLSID_FilterGraph
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IFilterGraph2
, (void **)&ret
);
96 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
100 static ULONG
get_refcount(void *iface
)
102 IUnknown
*unknown
= iface
;
103 IUnknown_AddRef(unknown
);
104 return IUnknown_Release(unknown
);
107 static void test_filter_config(void)
109 IVMRFilterConfig9
*config
;
114 hr
= CoCreateInstance(&CLSID_VideoMixingRenderer9
, NULL
, CLSCTX_INPROC_SERVER
,
115 &IID_IVMRFilterConfig9
, (void **)&config
);
116 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
118 hr
= IVMRFilterConfig9_GetRenderingMode(config
, &mode
);
119 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
120 ok(mode
== VMRMode_Windowed
, "Got mode %#lx.\n", mode
);
122 hr
= IVMRFilterConfig9_SetRenderingMode(config
, VMR9Mode_Windowed
);
123 ok(hr
== S_OK
|| broken(hr
== E_FAIL
), "Got hr %#lx.\n", hr
);
125 hr
= IVMRFilterConfig9_GetRenderingMode(config
, &mode
);
126 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
127 ok(mode
== VMR9Mode_Windowed
, "Got mode %#lx.\n", mode
);
129 hr
= IVMRFilterConfig9_SetRenderingMode(config
, VMR9Mode_Windowed
);
130 ok(hr
== VFW_E_WRONG_STATE
, "Got hr %#lx.\n", hr
);
132 ref
= IVMRFilterConfig9_Release(config
);
133 ok(!ref
, "Got outstanding refcount %ld.\n", ref
);
135 hr
= CoCreateInstance(&CLSID_VideoMixingRenderer9
, NULL
, CLSCTX_INPROC_SERVER
,
136 &IID_IVMRFilterConfig9
, (void **)&config
);
137 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
139 hr
= IVMRFilterConfig9_SetRenderingMode(config
, VMR9Mode_Windowless
);
140 ok(hr
== S_OK
|| broken(hr
== E_FAIL
), "Got hr %#lx.\n", hr
);
142 hr
= IVMRFilterConfig9_GetRenderingMode(config
, &mode
);
143 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
144 ok(mode
== VMR9Mode_Windowless
, "Got mode %#lx.\n", mode
);
146 hr
= IVMRFilterConfig9_SetRenderingMode(config
, VMR9Mode_Windowed
);
147 ok(hr
== VFW_E_WRONG_STATE
, "Got hr %#lx.\n", hr
);
149 ref
= IVMRFilterConfig9_Release(config
);
150 ok(!ref
, "Got outstanding refcount %ld.\n", ref
);
152 hr
= CoCreateInstance(&CLSID_VideoMixingRenderer9
, NULL
, CLSCTX_INPROC_SERVER
,
153 &IID_IVMRFilterConfig9
, (void **)&config
);
154 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
156 hr
= IVMRFilterConfig9_SetRenderingMode(config
, VMR9Mode_Renderless
);
157 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
159 hr
= IVMRFilterConfig9_GetRenderingMode(config
, &mode
);
160 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
161 ok(mode
== VMR9Mode_Renderless
, "Got mode %#lx.\n", mode
);
163 hr
= IVMRFilterConfig9_SetRenderingMode(config
, VMR9Mode_Windowless
);
164 ok(hr
== VFW_E_WRONG_STATE
, "Got hr %#lx.\n", hr
);
166 ref
= IVMRFilterConfig9_Release(config
);
167 ok(!ref
, "Got outstanding refcount %ld.\n", ref
);
169 hr
= CoCreateInstance(&CLSID_VideoMixingRenderer9
, NULL
, CLSCTX_INPROC_SERVER
,
170 &IID_IVMRFilterConfig9
, (void **)&config
);
171 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
173 hr
= IVMRFilterConfig9_GetNumberOfStreams(config
, &count
);
174 ok(hr
== VFW_E_VMR_NOT_IN_MIXER_MODE
, "Got hr %#lx.\n", hr
);
176 hr
= IVMRFilterConfig9_SetNumberOfStreams(config
, 3);
177 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
179 hr
= IVMRFilterConfig9_GetNumberOfStreams(config
, &count
);
180 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
181 ok(count
== 3, "Got count %lu.\n", count
);
183 hr
= IVMRFilterConfig9_GetRenderingMode(config
, &mode
);
184 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
185 ok(mode
== VMR9Mode_Windowed
, "Got mode %#lx.\n", mode
);
187 /* Despite MSDN, you can still change the rendering mode after setting the
189 hr
= IVMRFilterConfig9_SetRenderingMode(config
, VMR9Mode_Windowless
);
190 ok(hr
== S_OK
|| broken(hr
== E_FAIL
), "Got hr %#lx.\n", hr
);
192 hr
= IVMRFilterConfig9_GetRenderingMode(config
, &mode
);
193 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
194 ok(mode
== VMR9Mode_Windowless
, "Got mode %#lx.\n", mode
);
196 hr
= IVMRFilterConfig9_GetNumberOfStreams(config
, &count
);
197 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
198 ok(count
== 3, "Got count %lu.\n", count
);
200 ref
= IVMRFilterConfig9_Release(config
);
201 ok(!ref
, "Got outstanding refcount %ld.\n", ref
);
204 #define check_interface_broken(a, b, c) check_interface_(__LINE__, a, b, c, TRUE)
205 #define check_interface(a, b, c) check_interface_(__LINE__, a, b, c, FALSE)
206 static HRESULT
check_interface_(unsigned int line
, void *iface
, REFIID riid
, BOOL supported
, BOOL is_broken
)
208 HRESULT hr
, expected_hr
, broken_hr
;
209 IUnknown
*unknown
= iface
, *out
;
214 broken_hr
= E_NOINTERFACE
;
218 expected_hr
= E_NOINTERFACE
;
222 hr
= IUnknown_QueryInterface(unknown
, riid
, (void **)&out
);
223 ok_(__FILE__
, line
)(hr
== expected_hr
|| broken(is_broken
&& hr
== broken_hr
),
224 "Got hr %#lx, expected %#lx.\n", hr
, expected_hr
);
226 IUnknown_Release(out
);
230 static void test_common_interfaces(IBaseFilter
*filter
)
234 check_interface(filter
, &IID_IAMCertifiedOutputProtection
, TRUE
);
235 check_interface(filter
, &IID_IAMFilterMiscFlags
, TRUE
);
236 check_interface(filter
, &IID_IBaseFilter
, TRUE
);
237 todo_wine
check_interface(filter
, &IID_IKsPropertySet
, TRUE
);
238 check_interface(filter
, &IID_IMediaFilter
, TRUE
);
239 check_interface(filter
, &IID_IMediaPosition
, TRUE
);
240 check_interface(filter
, &IID_IMediaSeeking
, TRUE
);
241 check_interface(filter
, &IID_IPersist
, TRUE
);
242 check_interface(filter
, &IID_IQualityControl
, TRUE
);
243 todo_wine
check_interface(filter
, &IID_IQualProp
, TRUE
);
244 check_interface(filter
, &IID_IUnknown
, TRUE
);
245 check_interface(filter
, &IID_IVMRAspectRatioControl9
, TRUE
);
246 todo_wine
check_interface(filter
, &IID_IVMRDeinterlaceControl9
, TRUE
);
247 check_interface(filter
, &IID_IVMRFilterConfig9
, TRUE
);
248 check_interface(filter
, &IID_IVMRMixerBitmap9
, TRUE
);
250 check_interface(filter
, &IID_IAMVideoAccelerator
, FALSE
);
251 check_interface(filter
, &IID_IBasicAudio
, FALSE
);
252 check_interface(filter
, &IID_IDirectDrawVideo
, FALSE
);
253 check_interface(filter
, &IID_IPersistPropertyBag
, FALSE
);
254 check_interface(filter
, &IID_IPin
, FALSE
);
255 check_interface(filter
, &IID_IReferenceClock
, FALSE
);
256 check_interface(filter
, &IID_IVMRAspectRatioControl
, FALSE
);
257 check_interface(filter
, &IID_IVMRDeinterlaceControl
, FALSE
);
258 check_interface(filter
, &IID_IVMRFilterConfig
, FALSE
);
259 check_interface(filter
, &IID_IVMRMixerBitmap
, FALSE
);
260 check_interface(filter
, &IID_IVMRMixerControl
, FALSE
);
261 check_interface(filter
, &IID_IVMRMonitorConfig
, FALSE
);
262 check_interface(filter
, &IID_IVMRSurfaceAllocatorNotify
, FALSE
);
263 check_interface(filter
, &IID_IVMRWindowlessControl
, FALSE
);
265 IBaseFilter_FindPin(filter
, L
"VMR Input0", &pin
);
267 check_interface(pin
, &IID_IAMVideoAccelerator
, TRUE
);
268 check_interface(pin
, &IID_IMemInputPin
, TRUE
);
269 check_interface(pin
, &IID_IOverlay
, TRUE
);
270 check_interface(pin
, &IID_IPin
, TRUE
);
271 todo_wine
check_interface(pin
, &IID_IQualityControl
, TRUE
);
272 check_interface(pin
, &IID_IUnknown
, TRUE
);
274 check_interface(pin
, &IID_IKsPropertySet
, FALSE
);
275 check_interface(pin
, &IID_IMediaPosition
, FALSE
);
276 check_interface(pin
, &IID_IMediaSeeking
, FALSE
);
281 static void test_interfaces(void)
283 IBaseFilter
*filter
= create_vmr9(0);
286 test_common_interfaces(filter
);
288 check_interface(filter
, &IID_IBasicVideo
, TRUE
);
289 todo_wine
check_interface(filter
, &IID_IBasicVideo2
, TRUE
);
290 check_interface(filter
, &IID_IVideoWindow
, TRUE
);
291 /* IVMRMonitorConfig9 may not be available if the d3d9 device has
292 * insufficient support. */
293 check_interface_broken(filter
, &IID_IVMRMonitorConfig9
, TRUE
);
295 check_interface(filter
, &IID_IVMRMixerControl9
, FALSE
);
296 check_interface(filter
, &IID_IVMRSurfaceAllocatorNotify9
, FALSE
);
297 check_interface(filter
, &IID_IVMRWindowlessControl9
, FALSE
);
299 ref
= IBaseFilter_Release(filter
);
300 ok(!ref
, "Got outstanding refcount %ld.\n", ref
);
302 filter
= create_vmr9(VMR9Mode_Windowless
);
303 test_common_interfaces(filter
);
305 /* IVMRMonitorConfig9 may not be available if the d3d9 device has
306 * insufficient support. */
307 check_interface_broken(filter
, &IID_IVMRMonitorConfig9
, TRUE
);
308 check_interface(filter
, &IID_IVMRWindowlessControl9
, TRUE
);
310 todo_wine
check_interface(filter
, &IID_IBasicVideo
, FALSE
);
311 check_interface(filter
, &IID_IBasicVideo2
, FALSE
);
312 todo_wine
check_interface(filter
, &IID_IVideoWindow
, FALSE
);
313 check_interface(filter
, &IID_IVMRMixerControl9
, FALSE
);
314 check_interface(filter
, &IID_IVMRSurfaceAllocatorNotify9
, FALSE
);
316 ref
= IBaseFilter_Release(filter
);
317 ok(!ref
, "Got outstanding refcount %ld.\n", ref
);
319 filter
= create_vmr9(VMR9Mode_Renderless
);
320 test_common_interfaces(filter
);
322 check_interface(filter
, &IID_IVMRSurfaceAllocatorNotify9
, TRUE
);
324 todo_wine
check_interface(filter
, &IID_IBasicVideo
, FALSE
);
325 check_interface(filter
, &IID_IBasicVideo2
, FALSE
);
326 todo_wine
check_interface(filter
, &IID_IVideoWindow
, FALSE
);
327 check_interface(filter
, &IID_IVMRMonitorConfig9
, FALSE
);
328 check_interface(filter
, &IID_IVMRWindowlessControl9
, FALSE
);
330 ref
= IBaseFilter_Release(filter
);
331 ok(!ref
, "Got outstanding refcount %ld.\n", ref
);
333 filter
= create_vmr9(VMR9Mode_Windowed
);
334 set_mixing_mode(filter
, 1);
335 test_common_interfaces(filter
);
337 check_interface(filter
, &IID_IBasicVideo
, TRUE
);
338 todo_wine
check_interface(filter
, &IID_IBasicVideo2
, TRUE
);
339 check_interface(filter
, &IID_IVideoWindow
, TRUE
);
340 check_interface(filter
, &IID_IVMRMixerControl9
, TRUE
);
341 /* IVMRMonitorConfig9 may not be available if the d3d9 device has
342 * insufficient support. */
343 check_interface_broken(filter
, &IID_IVMRMonitorConfig9
, TRUE
);
345 check_interface(filter
, &IID_IVMRSurfaceAllocatorNotify9
, FALSE
);
346 check_interface(filter
, &IID_IVMRWindowlessControl9
, FALSE
);
348 ref
= IBaseFilter_Release(filter
);
349 ok(!ref
, "Got outstanding refcount %ld.\n", ref
);
352 static const GUID test_iid
= {0x33333333};
353 static LONG outer_ref
= 1;
355 static HRESULT WINAPI
outer_QueryInterface(IUnknown
*iface
, REFIID iid
, void **out
)
357 if (IsEqualGUID(iid
, &IID_IUnknown
)
358 || IsEqualGUID(iid
, &IID_IBaseFilter
)
359 || IsEqualGUID(iid
, &test_iid
))
361 *out
= (IUnknown
*)0xdeadbeef;
364 ok(0, "unexpected call %s\n", wine_dbgstr_guid(iid
));
365 return E_NOINTERFACE
;
368 static ULONG WINAPI
outer_AddRef(IUnknown
*iface
)
370 return InterlockedIncrement(&outer_ref
);
373 static ULONG WINAPI
outer_Release(IUnknown
*iface
)
375 return InterlockedDecrement(&outer_ref
);
378 static const IUnknownVtbl outer_vtbl
=
380 outer_QueryInterface
,
385 static IUnknown test_outer
= {&outer_vtbl
};
387 static void test_aggregation(void)
389 IBaseFilter
*filter
, *filter2
;
390 IUnknown
*unk
, *unk2
;
394 filter
= (IBaseFilter
*)0xdeadbeef;
395 hr
= CoCreateInstance(&CLSID_VideoMixingRenderer9
, &test_outer
, CLSCTX_INPROC_SERVER
,
396 &IID_IBaseFilter
, (void **)&filter
);
397 ok(hr
== E_NOINTERFACE
, "Got hr %#lx.\n", hr
);
398 ok(!filter
, "Got interface %p.\n", filter
);
400 hr
= CoCreateInstance(&CLSID_VideoMixingRenderer9
, &test_outer
, CLSCTX_INPROC_SERVER
,
401 &IID_IUnknown
, (void **)&unk
);
402 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
403 ok(outer_ref
== 1, "Got unexpected refcount %ld.\n", outer_ref
);
404 ok(unk
!= &test_outer
, "Returned IUnknown should not be outer IUnknown.\n");
405 ref
= get_refcount(unk
);
406 ok(ref
== 1, "Got unexpected refcount %ld.\n", ref
);
408 ref
= IUnknown_AddRef(unk
);
409 ok(ref
== 2, "Got unexpected refcount %ld.\n", ref
);
410 ok(outer_ref
== 1, "Got unexpected refcount %ld.\n", outer_ref
);
412 ref
= IUnknown_Release(unk
);
413 ok(ref
== 1, "Got unexpected refcount %ld.\n", ref
);
414 ok(outer_ref
== 1, "Got unexpected refcount %ld.\n", outer_ref
);
416 hr
= IUnknown_QueryInterface(unk
, &IID_IUnknown
, (void **)&unk2
);
417 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
418 ok(unk2
== unk
, "Got unexpected IUnknown %p.\n", unk2
);
419 IUnknown_Release(unk2
);
421 hr
= IUnknown_QueryInterface(unk
, &IID_IBaseFilter
, (void **)&filter
);
422 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
424 hr
= IBaseFilter_QueryInterface(filter
, &IID_IUnknown
, (void **)&unk2
);
425 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
426 ok(unk2
== (IUnknown
*)0xdeadbeef, "Got unexpected IUnknown %p.\n", unk2
);
428 hr
= IBaseFilter_QueryInterface(filter
, &IID_IBaseFilter
, (void **)&filter2
);
429 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
430 ok(filter2
== (IBaseFilter
*)0xdeadbeef, "Got unexpected IBaseFilter %p.\n", filter2
);
432 hr
= IUnknown_QueryInterface(unk
, &test_iid
, (void **)&unk2
);
433 ok(hr
== E_NOINTERFACE
, "Got hr %#lx.\n", hr
);
434 ok(!unk2
, "Got unexpected IUnknown %p.\n", unk2
);
436 hr
= IBaseFilter_QueryInterface(filter
, &test_iid
, (void **)&unk2
);
437 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
438 ok(unk2
== (IUnknown
*)0xdeadbeef, "Got unexpected IUnknown %p.\n", unk2
);
440 IBaseFilter_Release(filter
);
441 ref
= IUnknown_Release(unk
);
442 ok(!ref
, "Got unexpected refcount %ld.\n", ref
);
443 ok(outer_ref
== 1, "Got unexpected refcount %ld.\n", outer_ref
);
446 static void test_enum_pins(void)
448 IBaseFilter
*filter
= create_vmr9(0);
449 IEnumPins
*enum1
, *enum2
;
454 ref
= get_refcount(filter
);
455 ok(ref
== 1, "Got unexpected refcount %ld.\n", ref
);
457 hr
= IBaseFilter_EnumPins(filter
, NULL
);
458 ok(hr
== E_POINTER
, "Got hr %#lx.\n", hr
);
460 hr
= IBaseFilter_EnumPins(filter
, &enum1
);
461 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
462 ref
= get_refcount(filter
);
463 ok(ref
== 2, "Got unexpected refcount %ld.\n", ref
);
464 ref
= get_refcount(enum1
);
465 ok(ref
== 1, "Got unexpected refcount %ld.\n", ref
);
467 hr
= IEnumPins_Next(enum1
, 1, NULL
, NULL
);
468 ok(hr
== E_POINTER
, "Got hr %#lx.\n", hr
);
470 hr
= IEnumPins_Next(enum1
, 1, pins
, NULL
);
471 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
472 ref
= get_refcount(filter
);
473 ok(ref
== 3, "Got unexpected refcount %ld.\n", ref
);
474 ref
= get_refcount(pins
[0]);
475 ok(ref
== 3, "Got unexpected refcount %ld.\n", ref
);
476 ref
= get_refcount(enum1
);
477 ok(ref
== 1, "Got unexpected refcount %ld.\n", ref
);
478 IPin_Release(pins
[0]);
479 ref
= get_refcount(filter
);
480 ok(ref
== 2, "Got unexpected refcount %ld.\n", ref
);
482 hr
= IEnumPins_Next(enum1
, 1, pins
, NULL
);
483 ok(hr
== S_FALSE
, "Got hr %#lx.\n", hr
);
485 hr
= IEnumPins_Reset(enum1
);
486 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
488 hr
= IEnumPins_Next(enum1
, 1, pins
, &count
);
489 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
490 ok(count
== 1, "Got count %lu.\n", count
);
491 IPin_Release(pins
[0]);
493 hr
= IEnumPins_Next(enum1
, 1, pins
, &count
);
494 ok(hr
== S_FALSE
, "Got hr %#lx.\n", hr
);
495 ok(!count
, "Got count %lu.\n", count
);
497 hr
= IEnumPins_Reset(enum1
);
498 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
500 hr
= IEnumPins_Next(enum1
, 2, pins
, NULL
);
501 ok(hr
== E_INVALIDARG
, "Got hr %#lx.\n", hr
);
503 hr
= IEnumPins_Next(enum1
, 2, pins
, &count
);
504 ok(hr
== S_FALSE
, "Got hr %#lx.\n", hr
);
505 ok(count
== 1, "Got count %lu.\n", count
);
506 IPin_Release(pins
[0]);
508 hr
= IEnumPins_Reset(enum1
);
509 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
511 hr
= IEnumPins_Clone(enum1
, &enum2
);
512 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
514 hr
= IEnumPins_Skip(enum1
, 2);
515 ok(hr
== S_FALSE
, "Got hr %#lx.\n", hr
);
517 hr
= IEnumPins_Skip(enum1
, 1);
518 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
520 hr
= IEnumPins_Skip(enum1
, 1);
521 ok(hr
== S_FALSE
, "Got hr %#lx.\n", hr
);
523 hr
= IEnumPins_Next(enum1
, 1, pins
, NULL
);
524 ok(hr
== S_FALSE
, "Got hr %#lx.\n", hr
);
526 hr
= IEnumPins_Next(enum2
, 1, pins
, NULL
);
527 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
528 IPin_Release(pins
[0]);
530 IEnumPins_Release(enum2
);
532 set_mixing_mode(filter
, 2);
534 hr
= IEnumPins_Next(enum1
, 1, pins
, NULL
);
535 ok(hr
== S_FALSE
, "Got hr %#lx.\n", hr
);
537 hr
= IEnumPins_Reset(enum1
);
538 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
540 hr
= IEnumPins_Next(enum1
, 1, pins
, NULL
);
541 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
542 IPin_Release(pins
[0]);
544 hr
= IEnumPins_Next(enum1
, 1, pins
, NULL
);
545 todo_wine
ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
546 if (hr
== S_OK
) IPin_Release(pins
[0]);
548 hr
= IEnumPins_Next(enum1
, 1, pins
, NULL
);
549 ok(hr
== S_FALSE
, "Got hr %#lx.\n", hr
);
551 hr
= IEnumPins_Reset(enum1
);
552 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
554 hr
= IEnumPins_Next(enum1
, 2, pins
, &count
);
555 todo_wine
ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
556 todo_wine
ok(count
== 2, "Got count %lu.\n", count
);
557 IPin_Release(pins
[0]);
558 if (count
> 1) IPin_Release(pins
[1]);
560 hr
= IEnumPins_Reset(enum1
);
561 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
563 hr
= IEnumPins_Next(enum1
, 3, pins
, &count
);
564 ok(hr
== S_FALSE
, "Got hr %#lx.\n", hr
);
565 todo_wine
ok(count
== 2, "Got count %lu.\n", count
);
566 IPin_Release(pins
[0]);
567 if (count
> 1) IPin_Release(pins
[1]);
569 IEnumPins_Release(enum1
);
570 ref
= IBaseFilter_Release(filter
);
571 ok(!ref
, "Got outstanding refcount %ld.\n", ref
);
574 static void test_find_pin(void)
576 IBaseFilter
*filter
= create_vmr9(0);
577 IEnumPins
*enum_pins
;
582 IBaseFilter_EnumPins(filter
, &enum_pins
);
584 hr
= IBaseFilter_FindPin(filter
, L
"input pin", &pin
);
585 ok(hr
== VFW_E_NOT_FOUND
, "Got hr %#lx.\n", hr
);
587 hr
= IBaseFilter_FindPin(filter
, L
"In", &pin
);
588 ok(hr
== VFW_E_NOT_FOUND
, "Got hr %#lx.\n", hr
);
590 hr
= IBaseFilter_FindPin(filter
, L
"VMR Input0", &pin
);
591 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
592 hr
= IEnumPins_Next(enum_pins
, 1, &pin2
, NULL
);
593 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
594 ok(pin
== pin2
, "Pins did not match.\n");
598 hr
= IBaseFilter_FindPin(filter
, L
"VMR Input1", &pin
);
599 ok(hr
== VFW_E_NOT_FOUND
, "Got hr %#lx.\n", hr
);
601 set_mixing_mode(filter
, 2);
603 IEnumPins_Reset(enum_pins
);
605 hr
= IBaseFilter_FindPin(filter
, L
"VMR Input0", &pin
);
606 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
607 hr
= IEnumPins_Next(enum_pins
, 1, &pin2
, NULL
);
608 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
609 ok(pin
== pin2
, "Pins did not match.\n");
613 hr
= IBaseFilter_FindPin(filter
, L
"VMR Input1", &pin
);
614 todo_wine
ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
617 hr
= IEnumPins_Next(enum_pins
, 1, &pin2
, NULL
);
618 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
619 ok(pin
== pin2
, "Pins did not match.\n");
624 hr
= IBaseFilter_FindPin(filter
, L
"VMR Input2", &pin
);
625 ok(hr
== VFW_E_NOT_FOUND
, "Got hr %#lx.\n", hr
);
627 IEnumPins_Release(enum_pins
);
628 ref
= IBaseFilter_Release(filter
);
629 ok(!ref
, "Got outstanding refcount %ld.\n", ref
);
632 static void test_pin_info(void)
634 IBaseFilter
*filter
= create_vmr9(0);
642 IBaseFilter_FindPin(filter
, L
"VMR Input0", &pin
);
643 hr
= IPin_QueryPinInfo(pin
, &info
);
644 ok(info
.pFilter
== filter
, "Expected filter %p, got %p.\n", filter
, info
.pFilter
);
645 ok(info
.dir
== PINDIR_INPUT
, "Got direction %d.\n", info
.dir
);
646 ok(!wcscmp(info
.achName
, L
"VMR Input0"), "Got name %s.\n", wine_dbgstr_w(info
.achName
));
647 IBaseFilter_Release(info
.pFilter
);
649 hr
= IPin_QueryDirection(pin
, &dir
);
650 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
651 ok(dir
== PINDIR_INPUT
, "Got direction %d.\n", dir
);
653 hr
= IPin_QueryId(pin
, &id
);
654 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
655 ok(!wcscmp(id
, L
"VMR Input0"), "Got id %s.\n", wine_dbgstr_w(id
));
658 hr
= IPin_QueryInternalConnections(pin
, NULL
, &count
);
659 ok(hr
== E_NOTIMPL
, "Got hr %#lx.\n", hr
);
663 set_mixing_mode(filter
, 2);
665 hr
= IBaseFilter_FindPin(filter
, L
"VMR Input1", &pin
);
666 todo_wine
ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
669 hr
= IPin_QueryPinInfo(pin
, &info
);
670 ok(info
.pFilter
== filter
, "Expected filter %p, got %p.\n", filter
, info
.pFilter
);
671 ok(info
.dir
== PINDIR_INPUT
, "Got direction %d.\n", info
.dir
);
672 ok(!wcscmp(info
.achName
, L
"VMR Input1"), "Got name %s.\n", wine_dbgstr_w(info
.achName
));
673 IBaseFilter_Release(info
.pFilter
);
675 hr
= IPin_QueryDirection(pin
, &dir
);
676 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
677 ok(dir
== PINDIR_INPUT
, "Got direction %d.\n", dir
);
679 hr
= IPin_QueryId(pin
, &id
);
680 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
681 ok(!wcscmp(id
, L
"VMR Input1"), "Got id %s.\n", wine_dbgstr_w(id
));
684 hr
= IPin_QueryInternalConnections(pin
, NULL
, &count
);
685 ok(hr
== E_NOTIMPL
, "Got hr %#lx.\n", hr
);
690 ref
= IBaseFilter_Release(filter
);
691 ok(!ref
, "Got outstanding refcount %ld.\n", ref
);
694 static void test_media_types(void)
696 IBaseFilter
*filter
= create_vmr9(0);
697 AM_MEDIA_TYPE
*mt
, req_mt
= {{0}};
698 VIDEOINFOHEADER vih
=
701 {sizeof(BITMAPINFOHEADER
), 32, 24, 1, 0, 0xdeadbeef}
703 IEnumMediaTypes
*enummt
;
709 static const GUID
*subtype_tests
[] =
711 &MEDIASUBTYPE_RGB565
,
716 IBaseFilter_FindPin(filter
, L
"VMR Input0", &pin
);
718 hr
= IPin_EnumMediaTypes(pin
, &enummt
);
719 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
721 hr
= IEnumMediaTypes_Next(enummt
, 1, &mt
, NULL
);
722 ok(hr
== S_FALSE
, "Got hr %#lx.\n", hr
);
724 IEnumMediaTypes_Release(enummt
);
726 req_mt
.majortype
= MEDIATYPE_Video
;
727 req_mt
.formattype
= FORMAT_VideoInfo
;
728 req_mt
.cbFormat
= sizeof(VIDEOINFOHEADER
);
729 req_mt
.pbFormat
= (BYTE
*)&vih
;
731 for (i
= 0; i
< ARRAY_SIZE(subtype_tests
); ++i
)
733 req_mt
.subtype
= *subtype_tests
[i
];
734 hr
= IPin_QueryAccept(pin
, &req_mt
);
735 ok(hr
== S_OK
, "Got hr %#lx for subtype %s.\n", hr
, wine_dbgstr_guid(subtype_tests
[i
]));
738 req_mt
.subtype
= MEDIASUBTYPE_RGB8
;
739 hr
= IPin_QueryAccept(pin
, &req_mt
);
740 todo_wine
ok(hr
== S_FALSE
, "Got hr %#lx.\n", hr
);
741 req_mt
.subtype
= MEDIASUBTYPE_NULL
;
742 hr
= IPin_QueryAccept(pin
, &req_mt
);
743 todo_wine
ok(hr
== S_FALSE
, "Got hr %#lx.\n", hr
);
744 req_mt
.subtype
= MEDIASUBTYPE_RGB24
;
746 req_mt
.majortype
= MEDIATYPE_NULL
;
747 hr
= IPin_QueryAccept(pin
, &req_mt
);
748 ok(hr
== S_FALSE
, "Got hr %#lx.\n", hr
);
749 req_mt
.majortype
= MEDIATYPE_Video
;
751 req_mt
.formattype
= FORMAT_None
;
752 hr
= IPin_QueryAccept(pin
, &req_mt
);
753 ok(hr
== S_FALSE
, "Got hr %#lx.\n", hr
);
755 req_mt
.formattype
= GUID_NULL
;
756 hr
= IPin_QueryAccept(pin
, &req_mt
);
757 ok(hr
== S_FALSE
, "Got hr %#lx.\n", hr
);
760 ref
= IBaseFilter_Release(filter
);
761 ok(!ref
, "Got outstanding refcount %ld.\n", ref
);
764 static void test_enum_media_types(void)
766 IBaseFilter
*filter
= create_vmr9(0);
767 IEnumMediaTypes
*enum1
, *enum2
;
768 AM_MEDIA_TYPE
*mts
[2];
773 IBaseFilter_FindPin(filter
, L
"VMR Input0", &pin
);
775 hr
= IPin_EnumMediaTypes(pin
, &enum1
);
776 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
778 hr
= IEnumMediaTypes_Next(enum1
, 1, mts
, NULL
);
779 ok(hr
== S_FALSE
, "Got hr %#lx.\n", hr
);
781 hr
= IEnumMediaTypes_Next(enum1
, 1, mts
, &count
);
782 ok(hr
== S_FALSE
, "Got hr %#lx.\n", hr
);
783 ok(!count
, "Got count %lu.\n", count
);
785 hr
= IEnumMediaTypes_Reset(enum1
);
786 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
788 hr
= IEnumMediaTypes_Next(enum1
, 1, mts
, NULL
);
789 ok(hr
== S_FALSE
, "Got hr %#lx.\n", hr
);
791 hr
= IEnumMediaTypes_Clone(enum1
, &enum2
);
792 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
794 hr
= IEnumMediaTypes_Skip(enum1
, 1);
795 ok(hr
== S_FALSE
, "Got hr %#lx.\n", hr
);
797 hr
= IEnumMediaTypes_Next(enum2
, 1, mts
, NULL
);
798 ok(hr
== S_FALSE
, "Got hr %#lx.\n", hr
);
800 IEnumMediaTypes_Release(enum1
);
801 IEnumMediaTypes_Release(enum2
);
804 ref
= IBaseFilter_Release(filter
);
805 ok(!ref
, "Got outstanding refcount %ld.\n", ref
);
808 static void test_unconnected_filter_state(void)
810 IBaseFilter
*filter
= create_vmr9(0);
815 hr
= IBaseFilter_GetState(filter
, 0, &state
);
816 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
817 ok(state
== State_Stopped
, "Got state %u.\n", state
);
819 hr
= IBaseFilter_Pause(filter
);
820 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
822 hr
= IBaseFilter_GetState(filter
, 0, &state
);
823 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
824 ok(state
== State_Paused
, "Got state %u.\n", state
);
826 hr
= IBaseFilter_Run(filter
, 0);
827 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
829 hr
= IBaseFilter_GetState(filter
, 0, &state
);
830 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
831 ok(state
== State_Running
, "Got state %u.\n", state
);
833 hr
= IBaseFilter_Pause(filter
);
834 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
836 hr
= IBaseFilter_GetState(filter
, 0, &state
);
837 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
838 ok(state
== State_Paused
, "Got state %u.\n", state
);
840 hr
= IBaseFilter_Stop(filter
);
841 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
843 hr
= IBaseFilter_GetState(filter
, 0, &state
);
844 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
845 ok(state
== State_Stopped
, "Got state %u.\n", state
);
847 hr
= IBaseFilter_Run(filter
, 0);
848 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
850 hr
= IBaseFilter_GetState(filter
, 0, &state
);
851 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
852 ok(state
== State_Running
, "Got state %u.\n", state
);
854 hr
= IBaseFilter_Stop(filter
);
855 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
857 hr
= IBaseFilter_GetState(filter
, 0, &state
);
858 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
859 ok(state
== State_Stopped
, "Got state %u.\n", state
);
861 ref
= IBaseFilter_Release(filter
);
862 ok(!ref
, "Got outstanding refcount %ld.\n", ref
);
867 struct strmbase_filter filter
;
868 struct strmbase_source source
;
871 static inline struct testfilter
*impl_from_strmbase_filter(struct strmbase_filter
*iface
)
873 return CONTAINING_RECORD(iface
, struct testfilter
, filter
);
876 static struct strmbase_pin
*testfilter_get_pin(struct strmbase_filter
*iface
, unsigned int index
)
878 struct testfilter
*filter
= impl_from_strmbase_filter(iface
);
880 return &filter
->source
.pin
;
884 static void testfilter_destroy(struct strmbase_filter
*iface
)
886 struct testfilter
*filter
= impl_from_strmbase_filter(iface
);
887 strmbase_source_cleanup(&filter
->source
);
888 strmbase_filter_cleanup(&filter
->filter
);
891 static const struct strmbase_filter_ops testfilter_ops
=
893 .filter_get_pin
= testfilter_get_pin
,
894 .filter_destroy
= testfilter_destroy
,
897 static HRESULT WINAPI
testsource_DecideAllocator(struct strmbase_source
*iface
,
898 IMemInputPin
*peer
, IMemAllocator
**allocator
)
903 static const struct strmbase_source_ops testsource_ops
=
905 .pfnAttemptConnection
= BaseOutputPinImpl_AttemptConnection
,
906 .pfnDecideAllocator
= testsource_DecideAllocator
,
909 static void testfilter_init(struct testfilter
*filter
)
911 static const GUID clsid
= {0xabacab};
912 strmbase_filter_init(&filter
->filter
, NULL
, &clsid
, &testfilter_ops
);
913 strmbase_source_init(&filter
->source
, &filter
->filter
, L
"", &testsource_ops
);
916 static void test_allocator(IMemInputPin
*input
)
918 IMemAllocator
*req_allocator
, *ret_allocator
;
919 ALLOCATOR_PROPERTIES props
, req_props
;
922 hr
= IMemInputPin_GetAllocatorRequirements(input
, &props
);
923 ok(hr
== E_NOTIMPL
, "Got hr %#lx.\n", hr
);
925 hr
= IMemInputPin_GetAllocator(input
, &ret_allocator
);
926 todo_wine
ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
930 hr
= IMemAllocator_GetProperties(ret_allocator
, &props
);
931 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
932 ok(!props
.cBuffers
, "Got %ld buffers.\n", props
.cBuffers
);
933 ok(!props
.cbBuffer
, "Got size %ld.\n", props
.cbBuffer
);
934 ok(!props
.cbAlign
, "Got alignment %ld.\n", props
.cbAlign
);
935 ok(!props
.cbPrefix
, "Got prefix %ld.\n", props
.cbPrefix
);
937 hr
= IMemInputPin_NotifyAllocator(input
, ret_allocator
, TRUE
);
938 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
940 req_props
.cBuffers
= 1;
941 req_props
.cbBuffer
= 32 * 16 * 4;
942 req_props
.cbAlign
= 1;
943 req_props
.cbPrefix
= 0;
944 hr
= IMemAllocator_SetProperties(ret_allocator
, &req_props
, &props
);
945 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
946 ok(props
.cBuffers
== 1, "Got %ld buffers.\n", props
.cBuffers
);
947 ok(props
.cbBuffer
== 32 * 16 * 4, "Got size %ld.\n", props
.cbBuffer
);
948 ok(props
.cbAlign
== 1, "Got alignment %ld.\n", props
.cbAlign
);
949 ok(!props
.cbPrefix
, "Got prefix %ld.\n", props
.cbPrefix
);
951 IMemAllocator_Release(ret_allocator
);
954 hr
= IMemInputPin_NotifyAllocator(input
, NULL
, TRUE
);
955 todo_wine
ok(hr
== E_FAIL
, "Got hr %#lx.\n", hr
);
957 CoCreateInstance(&CLSID_MemoryAllocator
, NULL
, CLSCTX_INPROC_SERVER
,
958 &IID_IMemAllocator
, (void **)&req_allocator
);
960 hr
= IMemInputPin_NotifyAllocator(input
, req_allocator
, TRUE
);
961 todo_wine
ok(hr
== E_FAIL
, "Got hr %#lx.\n", hr
);
963 IMemAllocator_Release(req_allocator
);
966 struct frame_thread_params
969 IMediaSample
*sample
;
972 static DWORD WINAPI
frame_thread(void *arg
)
974 struct frame_thread_params
*params
= arg
;
977 if (winetest_debug
> 1) trace("%04lx: Sending frame.\n", GetCurrentThreadId());
978 hr
= IMemInputPin_Receive(params
->sink
, params
->sample
);
979 if (winetest_debug
> 1) trace("%04lx: Returned %#lx.\n", GetCurrentThreadId(), hr
);
980 IMediaSample_Release(params
->sample
);
985 static HANDLE
send_frame_time(IMemInputPin
*sink
, REFERENCE_TIME start_time
, DWORD color
)
987 struct frame_thread_params
*params
= malloc(sizeof(*params
));
988 IMemAllocator
*allocator
;
989 REFERENCE_TIME end_time
;
990 IMediaSample
*sample
;
996 hr
= IMemInputPin_GetAllocator(sink
, &allocator
);
997 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
999 hr
= IMemAllocator_GetBuffer(allocator
, &sample
, NULL
, NULL
, 0);
1000 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
1002 size
= IMediaSample_GetSize(sample
);
1003 hr
= IMediaSample_GetPointer(sample
, &data
);
1004 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
1005 for (i
= 0; i
< size
/ sizeof(DWORD
); ++i
)
1006 ((DWORD
*)data
)[i
] = color
;
1008 hr
= IMediaSample_SetActualDataLength(sample
, size
);
1009 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
1011 start_time
*= 10000000;
1012 end_time
= start_time
+ 10000000;
1013 hr
= IMediaSample_SetTime(sample
, &start_time
, &end_time
);
1014 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
1016 hr
= IMediaSample_SetPreroll(sample
, TRUE
);
1017 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
1019 params
->sink
= sink
;
1020 params
->sample
= sample
;
1021 thread
= CreateThread(NULL
, 0, frame_thread
, params
, 0, NULL
);
1023 IMemAllocator_Release(allocator
);
1027 static HANDLE
send_frame(IMemInputPin
*sink
)
1029 return send_frame_time(sink
, 0, 0x007f007f);
1032 static HRESULT
join_thread_(int line
, HANDLE thread
)
1035 ok_(__FILE__
, line
)(!WaitForSingleObject(thread
, 1000), "Wait failed.\n");
1036 GetExitCodeThread(thread
, &ret
);
1037 CloseHandle(thread
);
1040 #define join_thread(a) join_thread_(__LINE__, a)
1042 static void commit_allocator(IMemInputPin
*input
)
1044 IMemAllocator
*allocator
;
1047 hr
= IMemInputPin_GetAllocator(input
, &allocator
);
1048 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
1049 hr
= IMemAllocator_Commit(allocator
);
1050 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
1051 IMemAllocator_Release(allocator
);
1054 static void test_filter_state(IMemInputPin
*input
, IMediaControl
*control
)
1056 IMemAllocator
*allocator
;
1057 IMediaSample
*sample
;
1058 OAFilterState state
;
1062 thread
= send_frame(input
);
1063 hr
= join_thread(thread
);
1064 ok(hr
== VFW_E_WRONG_STATE
, "Got hr %#lx.\n", hr
);
1066 /* The renderer is not fully paused until it receives a sample. The thread
1067 * sending the sample blocks in IMemInputPin_Receive() until the filter is
1068 * stopped or run. */
1070 hr
= IMediaControl_Pause(control
);
1071 ok(hr
== S_FALSE
, "Got hr %#lx.\n", hr
);
1073 hr
= IMediaControl_GetState(control
, 0, &state
);
1074 ok(hr
== VFW_S_STATE_INTERMEDIATE
, "Got hr %#lx.\n", hr
);
1076 thread
= send_frame(input
);
1078 hr
= IMediaControl_GetState(control
, 1000, &state
);
1079 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
1081 ok(WaitForSingleObject(thread
, 100) == WAIT_TIMEOUT
, "Thread should block in Receive().\n");
1083 hr
= IMediaControl_Stop(control
);
1084 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
1086 hr
= join_thread(thread
);
1087 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
1089 /* The sink will decommit our allocator for us when stopping, however it
1090 * will not recommit it when pausing. */
1091 hr
= IMemInputPin_GetAllocator(input
, &allocator
);
1092 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
1093 hr
= IMemAllocator_GetBuffer(allocator
, &sample
, NULL
, NULL
, 0);
1094 todo_wine
ok(hr
== VFW_E_NOT_COMMITTED
, "Got hr %#lx.\n", hr
);
1095 if (hr
== S_OK
) IMediaSample_Release(sample
);
1097 hr
= IMemAllocator_Commit(allocator
);
1098 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
1099 thread
= send_frame(input
);
1100 hr
= join_thread(thread
);
1101 ok(hr
== VFW_E_WRONG_STATE
, "Got hr %#lx.\n", hr
);
1103 hr
= IMediaControl_Pause(control
);
1104 ok(hr
== S_FALSE
, "Got hr %#lx.\n", hr
);
1106 hr
= IMediaControl_GetState(control
, 0, &state
);
1107 ok(hr
== VFW_S_STATE_INTERMEDIATE
, "Got hr %#lx.\n", hr
);
1109 thread
= send_frame(input
);
1111 hr
= IMediaControl_GetState(control
, 1000, &state
);
1112 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
1114 ok(WaitForSingleObject(thread
, 100) == WAIT_TIMEOUT
, "Thread should block in Receive().\n");
1116 hr
= IMediaControl_Run(control
);
1117 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
1119 hr
= IMediaControl_GetState(control
, 0, &state
);
1120 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
1122 hr
= join_thread(thread
);
1123 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
1125 thread
= send_frame(input
);
1126 hr
= join_thread(thread
);
1127 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
1129 hr
= IMediaControl_Pause(control
);
1130 todo_wine
ok(hr
== S_FALSE
, "Got hr %#lx.\n", hr
);
1132 hr
= IMediaControl_GetState(control
, 0, &state
);
1133 todo_wine
ok(hr
== VFW_S_STATE_INTERMEDIATE
, "Got hr %#lx.\n", hr
);
1135 thread
= send_frame(input
);
1137 hr
= IMediaControl_GetState(control
, 1000, &state
);
1138 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
1140 ok(WaitForSingleObject(thread
, 100) == WAIT_TIMEOUT
, "Thread should block in Receive().\n");
1142 hr
= IMediaControl_Run(control
);
1143 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
1145 hr
= IMediaControl_GetState(control
, 0, &state
);
1146 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
1148 hr
= join_thread(thread
);
1149 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
1151 hr
= IMediaControl_Pause(control
);
1152 todo_wine
ok(hr
== S_FALSE
, "Got hr %#lx.\n", hr
);
1154 hr
= IMediaControl_GetState(control
, 0, &state
);
1155 todo_wine
ok(hr
== VFW_S_STATE_INTERMEDIATE
, "Got hr %#lx.\n", hr
);
1157 hr
= IMediaControl_Stop(control
);
1158 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
1160 hr
= IMediaControl_GetState(control
, 0, &state
);
1161 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
1163 commit_allocator(input
);
1164 hr
= IMediaControl_Pause(control
);
1165 ok(hr
== S_FALSE
, "Got hr %#lx.\n", hr
);
1167 hr
= IMediaControl_GetState(control
, 0, &state
);
1168 ok(hr
== VFW_S_STATE_INTERMEDIATE
, "Got hr %#lx.\n", hr
);
1170 hr
= IMediaControl_Run(control
);
1171 todo_wine
ok(hr
== S_FALSE
, "Got hr %#lx.\n", hr
);
1173 hr
= IMediaControl_GetState(control
, 0, &state
);
1174 todo_wine
ok(hr
== VFW_S_STATE_INTERMEDIATE
, "Got hr %#lx.\n", hr
);
1176 thread
= send_frame(input
);
1177 hr
= join_thread(thread
);
1178 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
1180 hr
= IMediaControl_GetState(control
, 0, &state
);
1181 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
1183 hr
= IMediaControl_Stop(control
);
1184 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
1186 hr
= IMediaControl_GetState(control
, 0, &state
);
1187 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
1189 IMemAllocator_Release(allocator
);
1192 static void test_flushing(IPin
*pin
, IMemInputPin
*input
, IMediaControl
*control
)
1194 OAFilterState state
;
1198 commit_allocator(input
);
1199 hr
= IMediaControl_Pause(control
);
1200 ok(hr
== S_FALSE
, "Got hr %#lx.\n", hr
);
1202 thread
= send_frame(input
);
1203 ok(WaitForSingleObject(thread
, 100) == WAIT_TIMEOUT
, "Thread should block in Receive().\n");
1205 hr
= IMediaControl_GetState(control
, 1000, &state
);
1206 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
1208 hr
= IPin_BeginFlush(pin
);
1209 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
1211 hr
= join_thread(thread
);
1212 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
1214 thread
= send_frame(input
);
1215 hr
= join_thread(thread
);
1216 ok(hr
== S_FALSE
, "Got hr %#lx.\n", hr
);
1218 hr
= IPin_EndFlush(pin
);
1219 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
1221 /* We dropped the sample we were holding, so now we need a new one... */
1223 hr
= IMediaControl_GetState(control
, 0, &state
);
1224 todo_wine
ok(hr
== VFW_S_STATE_INTERMEDIATE
, "Got hr %#lx.\n", hr
);
1225 ok(state
== State_Paused
, "Got state %#lx.\n", state
);
1227 thread
= send_frame(input
);
1228 ok(WaitForSingleObject(thread
, 100) == WAIT_TIMEOUT
, "Thread should block in Receive().\n");
1230 hr
= IMediaControl_GetState(control
, 1000, &state
);
1231 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
1232 ok(state
== State_Paused
, "Got state %#lx.\n", state
);
1234 hr
= IMediaControl_Run(control
);
1235 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
1236 hr
= join_thread(thread
);
1237 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
1239 hr
= IPin_BeginFlush(pin
);
1240 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
1242 thread
= send_frame(input
);
1243 hr
= join_thread(thread
);
1244 ok(hr
== S_FALSE
, "Got hr %#lx.\n", hr
);
1246 hr
= IPin_EndFlush(pin
);
1247 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
1249 thread
= send_frame(input
);
1250 hr
= join_thread(thread
);
1251 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
1253 hr
= IMediaControl_Stop(control
);
1254 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
1257 static unsigned int check_event_code(IMediaEvent
*eventsrc
, DWORD timeout
, LONG expected_code
, LONG_PTR expected1
, LONG_PTR expected2
)
1259 LONG_PTR param1
, param2
;
1260 unsigned int ret
= 0;
1264 while ((hr
= IMediaEvent_GetEvent(eventsrc
, &code
, ¶m1
, ¶m2
, timeout
)) == S_OK
)
1266 if (code
== expected_code
)
1268 ok(param1
== expected1
, "Got param1 %#Ix.\n", param1
);
1269 ok(param2
== expected2
, "Got param2 %#Ix.\n", param2
);
1272 IMediaEvent_FreeEventParams(eventsrc
, code
, param1
, param2
);
1275 ok(hr
== E_ABORT
, "Got hr %#lx.\n", hr
);
1280 static inline unsigned int check_ec_complete(IMediaEvent
*eventsrc
, DWORD timeout
)
1282 return check_event_code(eventsrc
, timeout
, EC_COMPLETE
, S_OK
, 0);
1285 static void test_eos(IPin
*pin
, IMemInputPin
*input
, IMediaControl
*control
)
1287 IMediaEvent
*eventsrc
;
1288 OAFilterState state
;
1292 IMediaControl_QueryInterface(control
, &IID_IMediaEvent
, (void **)&eventsrc
);
1294 commit_allocator(input
);
1295 hr
= IMediaControl_Pause(control
);
1296 ok(hr
== S_FALSE
, "Got hr %#lx.\n", hr
);
1297 ret
= check_ec_complete(eventsrc
, 0);
1298 ok(!ret
, "Got unexpected EC_COMPLETE.\n");
1300 hr
= IPin_EndOfStream(pin
);
1301 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
1303 hr
= IMediaControl_GetState(control
, 1000, &state
);
1304 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
1305 ret
= check_ec_complete(eventsrc
, 0);
1306 ok(!ret
, "Got unexpected EC_COMPLETE.\n");
1308 hr
= join_thread(send_frame(input
));
1309 todo_wine
ok(hr
== E_UNEXPECTED
, "Got hr %#lx.\n", hr
);
1311 hr
= IMediaControl_Run(control
);
1312 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
1313 ret
= check_ec_complete(eventsrc
, 0);
1314 ok(ret
== 1, "Expected EC_COMPLETE.\n");
1316 hr
= IMediaControl_Stop(control
);
1317 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
1318 ret
= check_ec_complete(eventsrc
, 0);
1319 ok(!ret
, "Got unexpected EC_COMPLETE.\n");
1321 /* We do not receive an EC_COMPLETE notification until the last sample is
1322 * done rendering. */
1324 commit_allocator(input
);
1325 hr
= IMediaControl_Run(control
);
1326 ok(hr
== S_FALSE
, "Got hr %#lx.\n", hr
);
1327 hr
= join_thread(send_frame(input
));
1328 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
1329 hr
= IMediaControl_GetState(control
, 1000, &state
);
1330 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
1331 ret
= check_ec_complete(eventsrc
, 0);
1332 ok(!ret
, "Got unexpected EC_COMPLETE.\n");
1334 hr
= IPin_EndOfStream(pin
);
1335 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
1336 ret
= check_ec_complete(eventsrc
, 0);
1337 todo_wine
ok(!ret
, "Got unexpected EC_COMPLETE.\n");
1338 ret
= check_ec_complete(eventsrc
, 1600);
1339 todo_wine
ok(ret
== 1, "Expected EC_COMPLETE.\n");
1341 hr
= IMediaControl_Stop(control
);
1342 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
1343 ret
= check_ec_complete(eventsrc
, 0);
1344 ok(!ret
, "Got unexpected EC_COMPLETE.\n");
1346 /* Test sending EOS while flushing. */
1348 commit_allocator(input
);
1349 hr
= IMediaControl_Run(control
);
1350 ok(hr
== S_FALSE
, "Got hr %#lx.\n", hr
);
1351 hr
= join_thread(send_frame(input
));
1352 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
1354 hr
= IPin_BeginFlush(pin
);
1355 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
1356 hr
= IPin_EndOfStream(pin
);
1357 todo_wine
ok(hr
== S_FALSE
, "Got hr %#lx.\n", hr
);
1358 hr
= IPin_EndFlush(pin
);
1359 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
1361 hr
= IMediaControl_Stop(control
);
1362 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
1363 ret
= check_ec_complete(eventsrc
, 0);
1364 todo_wine
ok(!ret
, "Got unexpected EC_COMPLETE.\n");
1366 /* Test sending EOS and then flushing or stopping. */
1368 commit_allocator(input
);
1369 hr
= IMediaControl_Run(control
);
1370 ok(hr
== S_FALSE
, "Got hr %#lx.\n", hr
);
1371 hr
= join_thread(send_frame(input
));
1372 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
1373 hr
= IMediaControl_GetState(control
, 1000, &state
);
1374 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
1376 hr
= IPin_EndOfStream(pin
);
1377 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
1378 ret
= check_ec_complete(eventsrc
, 0);
1379 todo_wine
ok(!ret
, "Got unexpected EC_COMPLETE.\n");
1381 hr
= IPin_BeginFlush(pin
);
1382 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
1383 hr
= IPin_EndFlush(pin
);
1384 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
1386 hr
= join_thread(send_frame(input
));
1387 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
1388 hr
= IPin_EndOfStream(pin
);
1389 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
1390 ret
= check_ec_complete(eventsrc
, 0);
1391 ok(!ret
, "Got unexpected EC_COMPLETE.\n");
1393 hr
= IMediaControl_Stop(control
);
1394 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
1395 ret
= check_ec_complete(eventsrc
, 0);
1396 ok(!ret
, "Got unexpected EC_COMPLETE.\n");
1398 IMediaEvent_Release(eventsrc
);
1401 static void test_sample_time(IPin
*pin
, IMemInputPin
*input
, IMediaControl
*control
)
1403 OAFilterState state
;
1407 commit_allocator(input
);
1408 hr
= IMediaControl_Pause(control
);
1409 ok(hr
== S_FALSE
, "Got hr %#lx.\n", hr
);
1411 hr
= IMediaControl_GetState(control
, 0, &state
);
1412 ok(hr
== VFW_S_STATE_INTERMEDIATE
, "Got hr %#lx.\n", hr
);
1414 thread
= send_frame_time(input
, 1, 0x000000ff); /* blue */
1416 hr
= IMediaControl_GetState(control
, 1000, &state
);
1417 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
1419 ok(WaitForSingleObject(thread
, 100) == WAIT_TIMEOUT
, "Thread should block in Receive().\n");
1421 hr
= IMediaControl_Run(control
);
1422 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
1424 ok(WaitForSingleObject(thread
, 500) == WAIT_TIMEOUT
, "Thread should block in Receive().\n");
1426 hr
= join_thread(thread
);
1427 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
1429 /* Sample time is relative to the time passed to Run(). Thus a sample
1430 * stamped at or earlier than 1s will now be displayed immediately, because
1431 * that time has already passed.
1432 * One may manually verify that all of the frames in this function are
1433 * rendered, including (by adding a Sleep() after sending the frame) the
1434 * cyan and green frames. Thus the VMR does not attempt to drop any frames
1435 * that it considers late. This remains true if the frames are marked as
1438 hr
= join_thread(send_frame_time(input
, 1, 0x0000ffff)); /* cyan */
1439 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
1441 hr
= join_thread(send_frame_time(input
, 0, 0x0000ff00)); /* green */
1442 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
1444 hr
= join_thread(send_frame_time(input
, -2, 0x00ff0000)); /* red */
1445 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
1447 thread
= send_frame_time(input
, 1000000, 0x00ffffff); /* white */
1448 ok(WaitForSingleObject(thread
, 100) == WAIT_TIMEOUT
, "Thread should block in Receive().\n");
1450 hr
= IPin_BeginFlush(pin
);
1451 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
1452 hr
= join_thread(thread
);
1453 /* If the frame makes it to Receive() in time to be rendered, we get S_OK. */
1454 ok(hr
== S_OK
|| hr
== S_FALSE
, "Got hr %#lx.\n", hr
);
1455 hr
= IPin_EndFlush(pin
);
1456 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
1458 thread
= send_frame_time(input
, 1000000, 0x00ffff00); /* yellow */
1459 ok(WaitForSingleObject(thread
, 100) == WAIT_TIMEOUT
, "Thread should block in Receive().\n");
1461 hr
= IMediaControl_Stop(control
);
1462 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
1463 hr
= join_thread(thread
);
1464 /* If the frame makes it to Receive() in time to be rendered, we get S_OK. */
1465 ok(hr
== S_OK
|| hr
== VFW_E_WRONG_STATE
, "Got hr %#lx.\n", hr
);
1468 static void test_current_image(IBaseFilter
*filter
, IMemInputPin
*input
,
1469 IMediaControl
*control
, const BITMAPINFOHEADER
*req_bih
)
1471 LONG buffer
[(sizeof(BITMAPINFOHEADER
) + 32 * 16 * 4) / 4];
1472 const BITMAPINFOHEADER
*bih
= (BITMAPINFOHEADER
*)buffer
;
1473 const DWORD
*data
= (DWORD
*)((char *)buffer
+ sizeof(BITMAPINFOHEADER
));
1474 BITMAPINFOHEADER expect_bih
= *req_bih
;
1475 OAFilterState state
;
1482 expect_bih
.biSizeImage
= 32 * 16 * 4;
1484 IBaseFilter_QueryInterface(filter
, &IID_IBasicVideo
, (void **)&video
);
1486 hr
= IBasicVideo_GetCurrentImage(video
, NULL
, NULL
);
1487 ok(hr
== E_POINTER
, "Got hr %#lx.\n", hr
);
1489 hr
= IBasicVideo_GetCurrentImage(video
, NULL
, buffer
);
1490 ok(hr
== E_POINTER
, "Got hr %#lx.\n", hr
);
1493 hr
= IBasicVideo_GetCurrentImage(video
, &size
, NULL
);
1494 todo_wine
ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
1495 todo_wine
ok(size
== sizeof(BITMAPINFOHEADER
) + 32 * 16 * 4, "Got size %ld.\n", size
);
1497 size
= sizeof(buffer
);
1498 hr
= IBasicVideo_GetCurrentImage(video
, &size
, buffer
);
1499 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
1500 ok(size
== sizeof(buffer
), "Got size %ld.\n", size
);
1501 ok(!memcmp(bih
, &expect_bih
, sizeof(BITMAPINFOHEADER
)), "Bitmap headers didn't match.\n");
1502 /* The contents seem to reflect the last frame rendered. */
1504 commit_allocator(input
);
1505 hr
= IMediaControl_Pause(control
);
1506 ok(hr
== S_FALSE
, "Got hr %#lx.\n", hr
);
1508 size
= sizeof(buffer
);
1509 hr
= IBasicVideo_GetCurrentImage(video
, &size
, buffer
);
1510 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
1511 ok(size
== sizeof(buffer
), "Got size %ld.\n", size
);
1512 ok(!memcmp(bih
, &expect_bih
, sizeof(BITMAPINFOHEADER
)), "Bitmap headers didn't match.\n");
1513 /* The contents seem to reflect the last frame rendered. */
1515 thread
= send_frame(input
);
1516 hr
= IMediaControl_GetState(control
, 1000, &state
);
1517 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
1520 memset(buffer
, 0xcc, sizeof(buffer
));
1521 hr
= IBasicVideo_GetCurrentImage(video
, &size
, buffer
);
1522 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
1523 ok(size
== 1, "Got size %ld.\n", size
);
1525 size
= sizeof(buffer
);
1526 memset(buffer
, 0xcc, sizeof(buffer
));
1527 hr
= IBasicVideo_GetCurrentImage(video
, &size
, buffer
);
1528 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
1529 ok(size
== sizeof(buffer
), "Got size %ld.\n", size
);
1530 ok(!memcmp(bih
, &expect_bih
, sizeof(BITMAPINFOHEADER
)), "Bitmap headers didn't match.\n");
1531 for (i
= 0; i
< 32 * 16; ++i
)
1532 ok((data
[i
] & 0xffffff) == 0x7f007f, "Got unexpected color %08lx at %u.\n", data
[i
], i
);
1534 hr
= IMediaControl_Run(control
);
1535 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
1536 join_thread(thread
);
1538 size
= sizeof(buffer
);
1539 memset(buffer
, 0xcc, sizeof(buffer
));
1540 hr
= IBasicVideo_GetCurrentImage(video
, &size
, buffer
);
1541 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
1542 ok(size
== sizeof(buffer
), "Got size %ld.\n", size
);
1543 ok(!memcmp(bih
, &expect_bih
, sizeof(BITMAPINFOHEADER
)), "Bitmap headers didn't match.\n");
1544 for (i
= 0; i
< 32 * 16; ++i
)
1545 ok((data
[i
] & 0xffffff) == 0x7f007f, "Got unexpected color %08lx at %u.\n", data
[i
], i
);
1547 hr
= IMediaControl_Stop(control
);
1548 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
1550 IBasicVideo_Release(video
);
1553 static inline unsigned int check_ec_userabort(IMediaEvent
*eventsrc
, DWORD timeout
)
1555 return check_event_code(eventsrc
, timeout
, EC_USERABORT
, 0, 0);
1558 static void test_window_close(IPin
*pin
, IMemInputPin
*input
, IMediaControl
*control
)
1560 IMediaEvent
*eventsrc
;
1561 OAFilterState state
;
1568 IMediaControl_QueryInterface(control
, &IID_IMediaEvent
, (void **)&eventsrc
);
1569 IPin_QueryInterface(pin
, &IID_IOverlay
, (void **)&overlay
);
1571 hr
= IOverlay_GetWindowHandle(overlay
, &hwnd
);
1572 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
1573 IOverlay_Release(overlay
);
1575 commit_allocator(input
);
1576 hr
= IMediaControl_Pause(control
);
1577 ok(hr
== S_FALSE
, "Got hr %#lx.\n", hr
);
1578 ret
= check_ec_userabort(eventsrc
, 0);
1579 ok(!ret
, "Got unexpected EC_USERABORT.\n");
1581 SendMessageW(hwnd
, WM_CLOSE
, 0, 0);
1583 hr
= IMediaControl_GetState(control
, 1000, &state
);
1584 ok(hr
== VFW_S_STATE_INTERMEDIATE
, "Got hr %#lx.\n", hr
);
1585 ret
= check_ec_userabort(eventsrc
, 0);
1586 ok(ret
== 1, "Expected EC_USERABORT.\n");
1588 ok(IsWindow(hwnd
), "Window should exist.\n");
1589 ok(!IsWindowVisible(hwnd
), "Window should be visible.\n");
1591 thread
= send_frame(input
);
1592 ret
= WaitForSingleObject(thread
, 1000);
1593 todo_wine
ok(ret
== WAIT_OBJECT_0
, "Wait failed\n");
1594 if (ret
== WAIT_OBJECT_0
)
1596 GetExitCodeThread(thread
, (DWORD
*)&hr
);
1597 ok(hr
== E_UNEXPECTED
, "Got hr %#lx.\n", hr
);
1599 CloseHandle(thread
);
1601 hr
= IMediaControl_Run(control
);
1602 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
1603 ret
= check_ec_userabort(eventsrc
, 0);
1604 ok(!ret
, "Got unexpected EC_USERABORT.\n");
1606 hr
= IMediaControl_Stop(control
);
1607 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
1608 ret
= check_ec_userabort(eventsrc
, 0);
1609 ok(!ret
, "Got unexpected EC_USERABORT.\n");
1611 /* We receive an EC_USERABORT notification immediately. */
1613 commit_allocator(input
);
1614 hr
= IMediaControl_Run(control
);
1615 ok(hr
== S_FALSE
, "Got hr %#lx.\n", hr
);
1616 hr
= join_thread(send_frame(input
));
1617 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
1618 hr
= IMediaControl_GetState(control
, 1000, &state
);
1619 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
1620 ret
= check_ec_userabort(eventsrc
, 0);
1621 ok(!ret
, "Got unexpected EC_USERABORT.\n");
1623 SendMessageW(hwnd
, WM_CLOSE
, 0, 0);
1625 ret
= check_ec_userabort(eventsrc
, 0);
1626 ok(ret
== 1, "Expected EC_USERABORT.\n");
1628 ok(IsWindow(hwnd
), "Window should exist.\n");
1629 ok(!IsWindowVisible(hwnd
), "Window should be visible.\n");
1631 hr
= IMediaControl_Stop(control
);
1632 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
1633 ret
= check_ec_userabort(eventsrc
, 0);
1634 ok(!ret
, "Got unexpected EC_USERABORT.\n");
1636 IMediaEvent_Release(eventsrc
);
1639 static void test_connect_pin(void)
1641 VIDEOINFOHEADER vih
=
1643 .bmiHeader
.biSize
= sizeof(BITMAPINFOHEADER
),
1644 .bmiHeader
.biBitCount
= 32,
1645 .bmiHeader
.biWidth
= 32,
1646 .bmiHeader
.biHeight
= 16,
1647 .bmiHeader
.biPlanes
= 1,
1648 .bmiHeader
.biCompression
= BI_RGB
,
1650 AM_MEDIA_TYPE req_mt
=
1652 .majortype
= MEDIATYPE_Video
,
1653 .formattype
= FORMAT_VideoInfo
,
1654 .cbFormat
= sizeof(vih
),
1655 .pbFormat
= (BYTE
*)&vih
,
1657 ALLOCATOR_PROPERTIES req_props
= {1, 32 * 16 * 4, 1, 0}, ret_props
;
1658 IBaseFilter
*filter
= create_vmr9(VMR9Mode_Windowed
);
1659 IFilterGraph2
*graph
= create_graph();
1660 struct testfilter source
;
1661 IMemAllocator
*allocator
;
1662 IMediaControl
*control
;
1663 IMemInputPin
*input
;
1670 static const GUID
*subtype_tests
[] =
1672 &MEDIASUBTYPE_RGB555
,
1673 &MEDIASUBTYPE_RGB565
,
1674 &MEDIASUBTYPE_RGB24
,
1675 &MEDIASUBTYPE_RGB32
,
1677 static const WORD bpp_tests
[] = {15, 16, 24, 32};
1679 testfilter_init(&source
);
1681 IFilterGraph2_AddFilter(graph
, &source
.filter
.IBaseFilter_iface
, NULL
);
1682 IFilterGraph2_AddFilter(graph
, filter
, NULL
);
1683 IFilterGraph2_QueryInterface(graph
, &IID_IMediaControl
, (void **)&control
);
1685 IBaseFilter_FindPin(filter
, L
"VMR Input0", &pin
);
1686 IPin_QueryInterface(pin
, &IID_IMemInputPin
, (void **)&input
);
1688 for (i
= 0; i
< ARRAY_SIZE(subtype_tests
); ++i
)
1690 req_mt
.subtype
= *subtype_tests
[i
];
1692 for (j
= 0; j
< ARRAY_SIZE(bpp_tests
); ++j
)
1694 vih
.bmiHeader
.biBitCount
= bpp_tests
[j
];
1696 hr
= IFilterGraph2_ConnectDirect(graph
, &source
.source
.pin
.IPin_iface
, pin
, &req_mt
);
1699 skip("Got E_FAIL when connecting.\n");
1702 ok(hr
== S_OK
, "Got hr %#lx for subtype %s and bpp %u.\n", hr
,
1703 wine_dbgstr_guid(subtype_tests
[i
]), bpp_tests
[j
]);
1705 hr
= IFilterGraph2_Disconnect(graph
, &source
.source
.pin
.IPin_iface
);
1706 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
1707 hr
= IFilterGraph2_Disconnect(graph
, pin
);
1708 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
1712 req_mt
.formattype
= FORMAT_None
;
1713 hr
= IFilterGraph2_ConnectDirect(graph
, &source
.source
.pin
.IPin_iface
, pin
, &req_mt
);
1714 ok(hr
== VFW_E_TYPE_NOT_ACCEPTED
, "Got hr %#lx.\n", hr
);
1715 req_mt
.formattype
= FORMAT_VideoInfo
;
1717 req_mt
.subtype
= MEDIASUBTYPE_RGB8
;
1718 hr
= IFilterGraph2_ConnectDirect(graph
, &source
.source
.pin
.IPin_iface
, pin
, &req_mt
);
1719 ok(hr
== VFW_E_TYPE_NOT_ACCEPTED
, "Got hr %#lx.\n", hr
);
1720 req_mt
.subtype
= MEDIASUBTYPE_WAVE
;
1721 hr
= IFilterGraph2_ConnectDirect(graph
, &source
.source
.pin
.IPin_iface
, pin
, &req_mt
);
1722 ok(hr
== VFW_E_TYPE_NOT_ACCEPTED
, "Got hr %#lx.\n", hr
);
1723 req_mt
.subtype
= MEDIASUBTYPE_RGB32
;
1725 peer
= (IPin
*)0xdeadbeef;
1726 hr
= IPin_ConnectedTo(pin
, &peer
);
1727 ok(hr
== VFW_E_NOT_CONNECTED
, "Got hr %#lx.\n", hr
);
1728 ok(!peer
, "Got peer %p.\n", peer
);
1730 hr
= IPin_ConnectionMediaType(pin
, &mt
);
1731 ok(hr
== VFW_E_NOT_CONNECTED
, "Got hr %#lx.\n", hr
);
1733 hr
= IMediaControl_Pause(control
);
1734 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
1735 hr
= IFilterGraph2_ConnectDirect(graph
, &source
.source
.pin
.IPin_iface
, pin
, &req_mt
);
1736 ok(hr
== VFW_E_NOT_STOPPED
, "Got hr %#lx.\n", hr
);
1737 hr
= IMediaControl_Stop(control
);
1738 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
1740 hr
= IFilterGraph2_ConnectDirect(graph
, &source
.source
.pin
.IPin_iface
, pin
, &req_mt
);
1741 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
1743 hr
= IPin_ConnectedTo(pin
, &peer
);
1744 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
1745 ok(peer
== &source
.source
.pin
.IPin_iface
, "Got peer %p.\n", peer
);
1748 hr
= IPin_ConnectionMediaType(pin
, &mt
);
1749 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
1750 ok(compare_media_types(&mt
, &req_mt
), "Media types didn't match.\n");
1752 /* Disconnecting while not stopped is broken: it returns S_OK, but
1753 * subsequent attempts to connect return VFW_E_ALREADY_CONNECTED. */
1755 test_allocator(input
);
1757 hr
= IMemInputPin_GetAllocator(input
, &allocator
);
1758 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
1759 hr
= IMemAllocator_SetProperties(allocator
, &req_props
, &ret_props
);
1760 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
1761 ok(!memcmp(&ret_props
, &req_props
, sizeof(req_props
)), "Properties did not match.\n");
1762 hr
= IMemAllocator_Commit(allocator
);
1763 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
1764 IMemAllocator_Release(allocator
);
1766 hr
= IMemInputPin_ReceiveCanBlock(input
);
1767 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
1769 test_filter_state(input
, control
);
1770 test_flushing(pin
, input
, control
);
1771 test_eos(pin
, input
, control
);
1772 test_sample_time(pin
, input
, control
);
1773 test_current_image(filter
, input
, control
, &vih
.bmiHeader
);
1774 test_window_close(pin
, input
, control
);
1776 hr
= IFilterGraph2_Disconnect(graph
, pin
);
1777 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
1778 hr
= IFilterGraph2_Disconnect(graph
, pin
);
1779 ok(hr
== S_FALSE
, "Got hr %#lx.\n", hr
);
1780 ok(source
.source
.pin
.peer
== pin
, "Got peer %p.\n", source
.source
.pin
.peer
);
1781 IFilterGraph2_Disconnect(graph
, &source
.source
.pin
.IPin_iface
);
1783 peer
= (IPin
*)0xdeadbeef;
1784 hr
= IPin_ConnectedTo(pin
, &peer
);
1785 ok(hr
== VFW_E_NOT_CONNECTED
, "Got hr %#lx.\n", hr
);
1786 ok(!peer
, "Got peer %p.\n", peer
);
1788 hr
= IPin_ConnectionMediaType(pin
, &mt
);
1789 ok(hr
== VFW_E_NOT_CONNECTED
, "Got hr %#lx.\n", hr
);
1792 IMediaControl_Release(control
);
1793 ref
= IFilterGraph2_Release(graph
);
1794 ok(!ref
, "Got outstanding refcount %ld.\n", ref
);
1795 IMemInputPin_Release(input
);
1797 ref
= IBaseFilter_Release(filter
);
1798 ok(!ref
, "Got outstanding refcount %ld.\n", ref
);
1799 ref
= IBaseFilter_Release(&source
.filter
.IBaseFilter_iface
);
1800 ok(!ref
, "Got outstanding refcount %ld.\n", ref
);
1803 static void test_overlay(void)
1805 IBaseFilter
*filter
= create_vmr9(0);
1812 IBaseFilter_FindPin(filter
, L
"VMR Input0", &pin
);
1814 hr
= IPin_QueryInterface(pin
, &IID_IOverlay
, (void **)&overlay
);
1815 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
1817 hwnd
= (HWND
)0xdeadbeef;
1818 hr
= IOverlay_GetWindowHandle(overlay
, &hwnd
);
1819 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
1820 ok(hwnd
&& hwnd
!= (HWND
)0xdeadbeef, "Got invalid window %p.\n", hwnd
);
1822 IOverlay_Release(overlay
);
1824 ref
= IBaseFilter_Release(filter
);
1825 ok(!ref
, "Got outstanding refcount %ld.\n", ref
);
1827 filter
= create_vmr9(VMR9Mode_Windowless
);
1828 IBaseFilter_FindPin(filter
, L
"VMR Input0", &pin
);
1830 hr
= IPin_QueryInterface(pin
, &IID_IOverlay
, (void **)&overlay
);
1831 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
1833 hwnd
= (HWND
)0xdeadbeef;
1834 hr
= IOverlay_GetWindowHandle(overlay
, &hwnd
);
1835 ok(hr
== VFW_E_WRONG_STATE
, "Got hr %#lx.\n", hr
);
1836 ok(hwnd
== (HWND
)0xdeadbeef, "Got window %p.\n", hwnd
);
1838 IOverlay_Release(overlay
);
1840 ref
= IBaseFilter_Release(filter
);
1841 ok(!ref
, "Got outstanding refcount %ld.\n", ref
);
1843 filter
= create_vmr9(VMR9Mode_Renderless
);
1844 IBaseFilter_FindPin(filter
, L
"VMR Input0", &pin
);
1846 hr
= IPin_QueryInterface(pin
, &IID_IOverlay
, (void **)&overlay
);
1847 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
1849 hwnd
= (HWND
)0xdeadbeef;
1850 hr
= IOverlay_GetWindowHandle(overlay
, &hwnd
);
1851 ok(hr
== VFW_E_WRONG_STATE
, "Got hr %#lx.\n", hr
);
1852 ok(hwnd
== (HWND
)0xdeadbeef, "Got window %p.\n", hwnd
);
1854 IOverlay_Release(overlay
);
1856 ref
= IBaseFilter_Release(filter
);
1857 ok(!ref
, "Got outstanding refcount %ld.\n", ref
);
1860 /* try to make sure pending X events have been processed before continuing */
1861 static void flush_events(void)
1867 time
= GetTickCount() + diff
;
1870 if (MsgWaitForMultipleObjects(0, NULL
, FALSE
, 100, QS_ALLINPUT
) == WAIT_TIMEOUT
)
1872 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
))
1873 DispatchMessageA(&msg
);
1874 diff
= time
- GetTickCount();
1878 static LRESULT CALLBACK
window_proc(HWND hwnd
, UINT msg
, WPARAM wparam
, LPARAM lparam
)
1880 if (winetest_debug
> 1)
1881 trace("hwnd %p, msg %#x, wparam %#Ix, lparam %#Ix.\n", hwnd
, msg
, wparam
, lparam
);
1883 if (wparam
== 0xdeadbeef)
1886 return DefWindowProcA(hwnd
, msg
, wparam
, lparam
);
1889 static void test_video_window_caption(IVideoWindow
*window
, HWND hwnd
)
1895 hr
= IVideoWindow_get_Caption(window
, &caption
);
1896 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
1897 ok(!wcscmp(caption
, L
"ActiveMovie Window"), "Got caption %s.\n", wine_dbgstr_w(caption
));
1898 SysFreeString(caption
);
1900 GetWindowTextW(hwnd
, text
, ARRAY_SIZE(text
));
1901 ok(!wcscmp(text
, L
"ActiveMovie Window"), "Got caption %s.\n", wine_dbgstr_w(text
));
1903 caption
= SysAllocString(L
"foo");
1904 hr
= IVideoWindow_put_Caption(window
, caption
);
1905 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
1906 SysFreeString(caption
);
1908 hr
= IVideoWindow_get_Caption(window
, &caption
);
1909 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
1910 ok(!wcscmp(caption
, L
"foo"), "Got caption %s.\n", wine_dbgstr_w(caption
));
1911 SysFreeString(caption
);
1913 GetWindowTextW(hwnd
, text
, ARRAY_SIZE(text
));
1914 ok(!wcscmp(text
, L
"foo"), "Got caption %s.\n", wine_dbgstr_w(text
));
1917 static void test_video_window_style(IVideoWindow
*window
, HWND hwnd
, HWND our_hwnd
)
1922 hr
= IVideoWindow_get_WindowStyle(window
, &style
);
1923 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
1924 ok(style
== (WS_CLIPSIBLINGS
| WS_CLIPCHILDREN
| WS_OVERLAPPEDWINDOW
),
1925 "Got style %#lx.\n", style
);
1927 style
= GetWindowLongA(hwnd
, GWL_STYLE
);
1928 ok(style
== (WS_CLIPSIBLINGS
| WS_CLIPCHILDREN
| WS_OVERLAPPEDWINDOW
),
1929 "Got style %#lx.\n", style
);
1931 hr
= IVideoWindow_put_WindowStyle(window
, style
| WS_DISABLED
);
1932 ok(hr
== E_INVALIDARG
, "Got hr %#lx.\n", hr
);
1933 hr
= IVideoWindow_put_WindowStyle(window
, style
| WS_HSCROLL
);
1934 ok(hr
== E_INVALIDARG
, "Got hr %#lx.\n", hr
);
1935 hr
= IVideoWindow_put_WindowStyle(window
, style
| WS_VSCROLL
);
1936 ok(hr
== E_INVALIDARG
, "Got hr %#lx.\n", hr
);
1937 hr
= IVideoWindow_put_WindowStyle(window
, style
| WS_MAXIMIZE
);
1938 ok(hr
== E_INVALIDARG
, "Got hr %#lx.\n", hr
);
1939 hr
= IVideoWindow_put_WindowStyle(window
, style
| WS_MINIMIZE
);
1940 ok(hr
== E_INVALIDARG
, "Got hr %#lx.\n", hr
);
1942 hr
= IVideoWindow_put_WindowStyle(window
, style
& ~WS_CLIPCHILDREN
);
1943 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
1945 hr
= IVideoWindow_get_WindowStyle(window
, &style
);
1946 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
1947 ok(style
== (WS_CLIPSIBLINGS
| WS_OVERLAPPEDWINDOW
), "Got style %#lx.\n", style
);
1949 style
= GetWindowLongA(hwnd
, GWL_STYLE
);
1950 ok(style
== (WS_CLIPSIBLINGS
| WS_OVERLAPPEDWINDOW
), "Got style %#lx.\n", style
);
1953 ok(GetActiveWindow() == our_hwnd
, "Got active window %p.\n", GetActiveWindow());
1955 hr
= IVideoWindow_get_WindowStyleEx(window
, &style
);
1956 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
1957 ok(style
== WS_EX_WINDOWEDGE
, "Got style %#lx.\n", style
);
1959 style
= GetWindowLongA(hwnd
, GWL_EXSTYLE
);
1960 ok(style
== WS_EX_WINDOWEDGE
, "Got style %#lx.\n", style
);
1962 hr
= IVideoWindow_put_WindowStyleEx(window
, style
| WS_EX_TRANSPARENT
);
1963 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
1965 hr
= IVideoWindow_get_WindowStyleEx(window
, &style
);
1966 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
1967 ok(style
== (WS_EX_WINDOWEDGE
| WS_EX_TRANSPARENT
), "Got style %#lx.\n", style
);
1969 style
= GetWindowLongA(hwnd
, GWL_EXSTYLE
);
1970 ok(style
== (WS_EX_WINDOWEDGE
| WS_EX_TRANSPARENT
), "Got style %#lx.\n", style
);
1973 static BOOL CALLBACK
top_window_cb(HWND hwnd
, LPARAM ctx
)
1976 GetWindowThreadProcessId(hwnd
, &pid
);
1977 if (pid
== GetCurrentProcessId() && (GetWindowLongW(hwnd
, GWL_STYLE
) & WS_VISIBLE
))
1979 *(HWND
*)ctx
= hwnd
;
1985 static HWND
get_top_window(void)
1988 EnumWindows(top_window_cb
, (LPARAM
)&hwnd
);
1992 static void test_video_window_state(IVideoWindow
*window
, HWND hwnd
, HWND our_hwnd
)
1998 SetWindowPos(our_hwnd
, HWND_TOP
, 0, 0, 0, 0, SWP_NOMOVE
| SWP_NOSIZE
);
2000 hr
= IVideoWindow_get_WindowState(window
, &state
);
2001 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
2002 ok(state
== SW_HIDE
, "Got state %ld.\n", state
);
2004 hr
= IVideoWindow_get_Visible(window
, &state
);
2005 ok(state
== OAFALSE
, "Got state %ld.\n", state
);
2007 ok(!IsWindowVisible(hwnd
), "Window should not be visible.\n");
2008 ok(!IsIconic(hwnd
), "Window should not be minimized.\n");
2009 ok(!IsZoomed(hwnd
), "Window should not be maximized.\n");
2011 hr
= IVideoWindow_put_WindowState(window
, SW_SHOWNA
);
2012 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
2014 hr
= IVideoWindow_get_WindowState(window
, &state
);
2015 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
2016 ok(state
== SW_SHOW
, "Got state %ld.\n", state
);
2018 hr
= IVideoWindow_get_Visible(window
, &state
);
2019 ok(state
== OATRUE
, "Got state %ld.\n", state
);
2021 ok(IsWindowVisible(hwnd
), "Window should be visible.\n");
2022 ok(!IsIconic(hwnd
), "Window should not be minimized.\n");
2023 ok(!IsZoomed(hwnd
), "Window should not be maximized.\n");
2024 ok(GetActiveWindow() == our_hwnd
, "Got active window %p.\n", GetActiveWindow());
2025 top
= get_top_window();
2026 ok(top
== hwnd
, "Got top window %p.\n", top
);
2028 hr
= IVideoWindow_put_WindowState(window
, SW_MINIMIZE
);
2029 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
2031 hr
= IVideoWindow_get_WindowState(window
, &state
);
2032 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
2033 ok(state
== SW_MINIMIZE
, "Got state %ld.\n", state
);
2035 hr
= IVideoWindow_get_Visible(window
, &state
);
2036 ok(state
== OATRUE
, "Got state %ld.\n", state
);
2038 ok(IsWindowVisible(hwnd
), "Window should be visible.\n");
2039 ok(IsIconic(hwnd
), "Window should be minimized.\n");
2040 ok(!IsZoomed(hwnd
), "Window should not be maximized.\n");
2041 ok(GetActiveWindow() == our_hwnd
, "Got active window %p.\n", GetActiveWindow());
2043 hr
= IVideoWindow_put_WindowState(window
, SW_RESTORE
);
2044 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
2046 hr
= IVideoWindow_get_WindowState(window
, &state
);
2047 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
2048 ok(state
== SW_SHOW
, "Got state %ld.\n", state
);
2050 hr
= IVideoWindow_get_Visible(window
, &state
);
2051 ok(state
== OATRUE
, "Got state %ld.\n", state
);
2053 ok(IsWindowVisible(hwnd
), "Window should be visible.\n");
2054 ok(!IsIconic(hwnd
), "Window should not be minimized.\n");
2055 ok(!IsZoomed(hwnd
), "Window should not be maximized.\n");
2056 ok(GetActiveWindow() == hwnd
, "Got active window %p.\n", GetActiveWindow());
2058 hr
= IVideoWindow_put_WindowState(window
, SW_MAXIMIZE
);
2059 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
2061 hr
= IVideoWindow_get_WindowState(window
, &state
);
2062 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
2063 ok(state
== SW_MAXIMIZE
, "Got state %ld.\n", state
);
2065 hr
= IVideoWindow_get_Visible(window
, &state
);
2066 ok(state
== OATRUE
, "Got state %ld.\n", state
);
2068 ok(IsWindowVisible(hwnd
), "Window should be visible.\n");
2069 ok(!IsIconic(hwnd
), "Window should be minimized.\n");
2070 ok(IsZoomed(hwnd
), "Window should not be maximized.\n");
2071 ok(GetActiveWindow() == hwnd
, "Got active window %p.\n", GetActiveWindow());
2073 hr
= IVideoWindow_put_WindowState(window
, SW_RESTORE
);
2074 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
2076 hr
= IVideoWindow_put_WindowState(window
, SW_HIDE
);
2077 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
2079 hr
= IVideoWindow_get_WindowState(window
, &state
);
2080 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
2081 ok(state
== SW_HIDE
, "Got state %ld.\n", state
);
2083 hr
= IVideoWindow_get_Visible(window
, &state
);
2084 ok(state
== OAFALSE
, "Got state %ld.\n", state
);
2086 ok(!IsWindowVisible(hwnd
), "Window should not be visible.\n");
2087 ok(!IsIconic(hwnd
), "Window should not be minimized.\n");
2088 ok(!IsZoomed(hwnd
), "Window should not be maximized.\n");
2089 ok(GetActiveWindow() == our_hwnd
, "Got active window %p.\n", GetActiveWindow());
2091 hr
= IVideoWindow_put_Visible(window
, OATRUE
);
2092 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
2094 hr
= IVideoWindow_get_WindowState(window
, &state
);
2095 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
2096 ok(state
== SW_SHOW
, "Got state %ld.\n", state
);
2098 hr
= IVideoWindow_get_Visible(window
, &state
);
2099 ok(state
== OATRUE
, "Got state %ld.\n", state
);
2101 ok(IsWindowVisible(hwnd
), "Window should be visible.\n");
2102 ok(!IsIconic(hwnd
), "Window should not be minimized.\n");
2103 ok(!IsZoomed(hwnd
), "Window should not be maximized.\n");
2104 ok(GetActiveWindow() == hwnd
, "Got active window %p.\n", GetActiveWindow());
2106 hr
= IVideoWindow_put_Visible(window
, OAFALSE
);
2107 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
2109 hr
= IVideoWindow_get_WindowState(window
, &state
);
2110 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
2111 ok(state
== SW_HIDE
, "Got state %ld.\n", state
);
2113 hr
= IVideoWindow_get_Visible(window
, &state
);
2114 ok(state
== OAFALSE
, "Got state %ld.\n", state
);
2116 ok(!IsWindowVisible(hwnd
), "Window should not be visible.\n");
2117 ok(!IsIconic(hwnd
), "Window should not be minimized.\n");
2118 ok(!IsZoomed(hwnd
), "Window should not be maximized.\n");
2119 ok(GetActiveWindow() == our_hwnd
, "Got active window %p.\n", GetActiveWindow());
2121 hr
= IVideoWindow_put_WindowState(window
, SW_SHOWNA
);
2122 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
2124 hr
= IVideoWindow_SetWindowForeground(window
, TRUE
);
2125 ok(hr
== E_INVALIDARG
, "Got hr %#lx.\n", hr
);
2127 SetWindowPos(our_hwnd
, HWND_TOP
, 0, 0, 0, 0, SWP_NOMOVE
| SWP_NOSIZE
);
2128 hr
= IVideoWindow_SetWindowForeground(window
, OATRUE
);
2129 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
2130 ok(GetActiveWindow() == hwnd
, "Got active window %p.\n", GetActiveWindow());
2131 ok(GetFocus() == hwnd
, "Got focus window %p.\n", GetFocus());
2132 ok(GetForegroundWindow() == hwnd
, "Got foreground window %p.\n", GetForegroundWindow());
2133 top
= get_top_window();
2134 ok(top
== hwnd
, "Got top window %p.\n", top
);
2136 hr
= IVideoWindow_SetWindowForeground(window
, OAFALSE
);
2137 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
2138 ok(GetActiveWindow() == hwnd
, "Got active window %p.\n", GetActiveWindow());
2139 ok(GetFocus() == hwnd
, "Got focus window %p.\n", GetFocus());
2140 ok(GetForegroundWindow() == hwnd
, "Got foreground window %p.\n", GetForegroundWindow());
2141 top
= get_top_window();
2142 ok(top
== hwnd
, "Got top window %p.\n", top
);
2144 SetWindowPos(our_hwnd
, HWND_TOP
, 0, 0, 0, 0, SWP_NOMOVE
| SWP_NOSIZE
);
2145 hr
= IVideoWindow_SetWindowForeground(window
, OAFALSE
);
2146 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
2147 ok(GetActiveWindow() == our_hwnd
, "Got active window %p.\n", GetActiveWindow());
2148 ok(GetFocus() == our_hwnd
, "Got focus window %p.\n", GetFocus());
2149 ok(GetForegroundWindow() == our_hwnd
, "Got foreground window %p.\n", GetForegroundWindow());
2150 top
= get_top_window();
2151 ok(top
== hwnd
, "Got top window %p.\n", top
);
2154 static void test_video_window_position(IVideoWindow
*window
, HWND hwnd
, HWND our_hwnd
)
2156 LONG left
, width
, top
, height
, expect_width
, expect_height
;
2157 RECT rect
= {0, 0, 600, 400};
2161 SetWindowPos(our_hwnd
, HWND_TOP
, 0, 0, 0, 0, SWP_NOMOVE
| SWP_NOSIZE
);
2163 AdjustWindowRect(&rect
, GetWindowLongA(hwnd
, GWL_STYLE
), FALSE
);
2164 expect_width
= rect
.right
- rect
.left
;
2165 expect_height
= rect
.bottom
- rect
.top
;
2167 hr
= IVideoWindow_put_Left(window
, 0);
2168 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
2169 hr
= IVideoWindow_put_Top(window
, 0);
2170 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
2172 hr
= IVideoWindow_get_Left(window
, &left
);
2173 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
2174 ok(left
== 0, "Got left %ld.\n", left
);
2175 hr
= IVideoWindow_get_Top(window
, &top
);
2176 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
2177 ok(top
== 0, "Got top %ld.\n", top
);
2178 hr
= IVideoWindow_get_Width(window
, &width
);
2179 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
2180 ok(width
== expect_width
, "Got width %ld.\n", width
);
2181 hr
= IVideoWindow_get_Height(window
, &height
);
2182 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
2183 ok(height
== expect_height
, "Got height %ld.\n", height
);
2184 hr
= IVideoWindow_GetWindowPosition(window
, &left
, &top
, &width
, &height
);
2185 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
2186 ok(left
== 0, "Got left %ld.\n", left
);
2187 ok(top
== 0, "Got top %ld.\n", top
);
2188 ok(width
== expect_width
, "Got width %ld.\n", width
);
2189 ok(height
== expect_height
, "Got height %ld.\n", height
);
2190 GetWindowRect(hwnd
, &rect
);
2191 ok(rect
.left
== 0, "Got window left %ld.\n", rect
.left
);
2192 ok(rect
.top
== 0, "Got window top %ld.\n", rect
.top
);
2193 ok(rect
.right
== expect_width
, "Got window right %ld.\n", rect
.right
);
2194 ok(rect
.bottom
== expect_height
, "Got window bottom %ld.\n", rect
.bottom
);
2196 hr
= IVideoWindow_put_Left(window
, 10);
2197 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
2199 hr
= IVideoWindow_get_Left(window
, &left
);
2200 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
2201 ok(left
== 10, "Got left %ld.\n", left
);
2202 hr
= IVideoWindow_get_Top(window
, &top
);
2203 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
2204 ok(top
== 0, "Got top %ld.\n", top
);
2205 hr
= IVideoWindow_get_Width(window
, &width
);
2206 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
2207 ok(width
== expect_width
, "Got width %ld.\n", width
);
2208 hr
= IVideoWindow_get_Height(window
, &height
);
2209 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
2210 ok(height
== expect_height
, "Got height %ld.\n", height
);
2211 hr
= IVideoWindow_GetWindowPosition(window
, &left
, &top
, &width
, &height
);
2212 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
2213 ok(left
== 10, "Got left %ld.\n", left
);
2214 ok(top
== 0, "Got top %ld.\n", top
);
2215 ok(width
== expect_width
, "Got width %ld.\n", width
);
2216 ok(height
== expect_height
, "Got height %ld.\n", height
);
2217 GetWindowRect(hwnd
, &rect
);
2218 ok(rect
.left
== 10, "Got window left %ld.\n", rect
.left
);
2219 ok(rect
.top
== 0, "Got window top %ld.\n", rect
.top
);
2220 ok(rect
.right
== 10 + expect_width
, "Got window right %ld.\n", rect
.right
);
2221 ok(rect
.bottom
== expect_height
, "Got window bottom %ld.\n", rect
.bottom
);
2223 hr
= IVideoWindow_put_Height(window
, 200);
2224 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
2226 hr
= IVideoWindow_get_Left(window
, &left
);
2227 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
2228 ok(left
== 10, "Got left %ld.\n", left
);
2229 hr
= IVideoWindow_get_Top(window
, &top
);
2230 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
2231 ok(top
== 0, "Got top %ld.\n", top
);
2232 hr
= IVideoWindow_get_Width(window
, &width
);
2233 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
2234 ok(width
== expect_width
, "Got width %ld.\n", width
);
2235 hr
= IVideoWindow_get_Height(window
, &height
);
2236 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
2237 ok(height
== 200, "Got height %ld.\n", height
);
2238 hr
= IVideoWindow_GetWindowPosition(window
, &left
, &top
, &width
, &height
);
2239 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
2240 ok(left
== 10, "Got left %ld.\n", left
);
2241 ok(top
== 0, "Got top %ld.\n", top
);
2242 ok(width
== expect_width
, "Got width %ld.\n", width
);
2243 ok(height
== 200, "Got height %ld.\n", height
);
2244 GetWindowRect(hwnd
, &rect
);
2245 ok(rect
.left
== 10, "Got window left %ld.\n", rect
.left
);
2246 ok(rect
.top
== 0, "Got window top %ld.\n", rect
.top
);
2247 ok(rect
.right
== 10 + expect_width
, "Got window right %ld.\n", rect
.right
);
2248 ok(rect
.bottom
== 200, "Got window bottom %ld.\n", rect
.bottom
);
2250 hr
= IVideoWindow_SetWindowPosition(window
, 100, 200, 300, 400);
2251 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
2253 hr
= IVideoWindow_get_Left(window
, &left
);
2254 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
2255 ok(left
== 100, "Got left %ld.\n", left
);
2256 hr
= IVideoWindow_get_Top(window
, &top
);
2257 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
2258 ok(top
== 200, "Got top %ld.\n", top
);
2259 hr
= IVideoWindow_get_Width(window
, &width
);
2260 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
2261 ok(width
== 300, "Got width %ld.\n", width
);
2262 hr
= IVideoWindow_get_Height(window
, &height
);
2263 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
2264 ok(height
== 400, "Got height %ld.\n", height
);
2265 hr
= IVideoWindow_GetWindowPosition(window
, &left
, &top
, &width
, &height
);
2266 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
2267 ok(left
== 100, "Got left %ld.\n", left
);
2268 ok(top
== 200, "Got top %ld.\n", top
);
2269 ok(width
== 300, "Got width %ld.\n", width
);
2270 ok(height
== 400, "Got height %ld.\n", height
);
2271 GetWindowRect(hwnd
, &rect
);
2272 ok(rect
.left
== 100, "Got window left %ld.\n", rect
.left
);
2273 ok(rect
.top
== 200, "Got window top %ld.\n", rect
.top
);
2274 ok(rect
.right
== 400, "Got window right %ld.\n", rect
.right
);
2275 ok(rect
.bottom
== 600, "Got window bottom %ld.\n", rect
.bottom
);
2277 ok(GetActiveWindow() == our_hwnd
, "Got active window %p.\n", GetActiveWindow());
2278 top_hwnd
= get_top_window();
2279 ok(top_hwnd
== our_hwnd
, "Got top window %p.\n", top_hwnd
);
2282 static void test_video_window_owner(IVideoWindow
*window
, HWND hwnd
, HWND our_hwnd
)
2284 HWND parent
, top_hwnd
;
2289 SetWindowPos(our_hwnd
, HWND_TOP
, 0, 0, 0, 0, SWP_NOMOVE
| SWP_NOSIZE
);
2291 hr
= IVideoWindow_get_Owner(window
, &oahwnd
);
2292 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
2293 ok(!oahwnd
, "Got owner %#Ix.\n", oahwnd
);
2295 parent
= GetAncestor(hwnd
, GA_PARENT
);
2296 ok(parent
== GetDesktopWindow(), "Got parent %p.\n", parent
);
2297 style
= GetWindowLongA(hwnd
, GWL_STYLE
);
2298 ok(!(style
& WS_CHILD
), "Got style %#lx.\n", style
);
2300 hr
= IVideoWindow_put_Owner(window
, (OAHWND
)our_hwnd
);
2301 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
2303 hr
= IVideoWindow_get_Owner(window
, &oahwnd
);
2304 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
2305 ok(oahwnd
== (OAHWND
)our_hwnd
, "Got owner %#Ix.\n", oahwnd
);
2307 parent
= GetAncestor(hwnd
, GA_PARENT
);
2308 ok(parent
== our_hwnd
, "Got parent %p.\n", parent
);
2309 style
= GetWindowLongA(hwnd
, GWL_STYLE
);
2310 ok((style
& WS_CHILD
), "Got style %#lx.\n", style
);
2312 ok(GetActiveWindow() == our_hwnd
, "Got active window %p.\n", GetActiveWindow());
2313 top_hwnd
= get_top_window();
2314 ok(top_hwnd
== our_hwnd
, "Got top window %p.\n", top_hwnd
);
2316 ShowWindow(our_hwnd
, SW_HIDE
);
2318 hr
= IVideoWindow_put_Visible(window
, OATRUE
);
2319 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
2321 hr
= IVideoWindow_get_Visible(window
, &state
);
2322 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
2323 ok(state
== OAFALSE
, "Got state %ld.\n", state
);
2325 hr
= IVideoWindow_put_Owner(window
, 0);
2326 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
2328 hr
= IVideoWindow_get_Owner(window
, &oahwnd
);
2329 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
2330 ok(!oahwnd
, "Got owner %#Ix.\n", oahwnd
);
2332 parent
= GetAncestor(hwnd
, GA_PARENT
);
2333 ok(parent
== GetDesktopWindow(), "Got parent %p.\n", parent
);
2334 style
= GetWindowLongA(hwnd
, GWL_STYLE
);
2335 ok(!(style
& WS_CHILD
), "Got style %#lx.\n", style
);
2337 ok(GetActiveWindow() == hwnd
, "Got active window %p.\n", GetActiveWindow());
2338 top_hwnd
= get_top_window();
2339 ok(top_hwnd
== hwnd
, "Got top window %p.\n", top_hwnd
);
2341 hr
= IVideoWindow_get_Visible(window
, &state
);
2342 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
2343 ok(state
== OATRUE
, "Got state %ld.\n", state
);
2346 struct notify_message_params
2348 IVideoWindow
*window
;
2353 static DWORD CALLBACK
notify_message_proc(void *arg
)
2355 const struct notify_message_params
*params
= arg
;
2356 HRESULT hr
= IVideoWindow_NotifyOwnerMessage(params
->window
, (OAHWND
)params
->hwnd
, params
->message
, 0, 0);
2357 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
2361 static void test_video_window_messages(IVideoWindow
*window
, HWND hwnd
, HWND our_hwnd
)
2363 struct notify_message_params params
;
2371 static UINT drain_tests
[] =
2399 hr
= IVideoWindow_get_MessageDrain(window
, &oahwnd
);
2400 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
2401 ok(!oahwnd
, "Got window %#Ix.\n", oahwnd
);
2403 hr
= IVideoWindow_put_MessageDrain(window
, (OAHWND
)our_hwnd
);
2404 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
2406 hr
= IVideoWindow_get_MessageDrain(window
, &oahwnd
);
2407 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
2408 ok(oahwnd
== (OAHWND
)our_hwnd
, "Got window %#Ix.\n", oahwnd
);
2410 for (i
= 0; i
< ARRAY_SIZE(drain_tests
); ++i
)
2412 SendMessageA(hwnd
, drain_tests
[i
], 0xdeadbeef, 0);
2413 ret
= PeekMessageA(&msg
, 0, drain_tests
[i
], drain_tests
[i
], PM_REMOVE
);
2414 ok(ret
, "Expected a message.\n");
2415 ok(msg
.hwnd
== our_hwnd
, "Got hwnd %p.\n", msg
.hwnd
);
2416 ok(msg
.message
== drain_tests
[i
], "Got message %#x.\n", msg
.message
);
2417 ok(msg
.wParam
== 0xdeadbeef, "Got wparam %#Ix.\n", msg
.wParam
);
2418 ok(!msg
.lParam
, "Got lparam %#Ix.\n", msg
.lParam
);
2419 DispatchMessageA(&msg
);
2421 ret
= PeekMessageA(&msg
, 0, drain_tests
[i
], drain_tests
[i
], PM_REMOVE
);
2422 ok(!ret
, "Got unexpected message %#x.\n", msg
.message
);
2425 hr
= IVideoWindow_put_MessageDrain(window
, 0);
2426 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
2428 hr
= IVideoWindow_put_Owner(window
, (OAHWND
)our_hwnd
);
2429 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
2433 /* Demonstrate that messages should be sent, not posted, and that only some
2434 * messages should be forwarded. A previous implementation unconditionally
2435 * posted all messages. */
2437 hr
= IVideoWindow_NotifyOwnerMessage(window
, (OAHWND
)our_hwnd
, WM_SYSCOLORCHANGE
, 0, 0);
2438 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
2440 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
))
2442 ok(msg
.message
!= WM_SYSCOLORCHANGE
, "WM_SYSCOLORCHANGE should not be posted.\n");
2443 DispatchMessageA(&msg
);
2446 hr
= IVideoWindow_NotifyOwnerMessage(window
, (OAHWND
)our_hwnd
, WM_FONTCHANGE
, 0, 0);
2447 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
2449 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
))
2451 ok(msg
.message
!= WM_FONTCHANGE
, "WM_FONTCHANGE should not be posted.\n");
2452 DispatchMessageA(&msg
);
2455 params
.window
= window
;
2456 params
.hwnd
= our_hwnd
;
2457 params
.message
= WM_SYSCOLORCHANGE
;
2458 thread
= CreateThread(NULL
, 0, notify_message_proc
, ¶ms
, 0, NULL
);
2459 ok(WaitForSingleObject(thread
, 100) == WAIT_TIMEOUT
, "Thread should block.\n");
2461 while ((ret
= MsgWaitForMultipleObjects(1, &thread
, FALSE
, 1000, QS_ALLINPUT
)) == 1)
2463 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
))
2465 ok(msg
.message
!= WM_SYSCOLORCHANGE
, "WM_SYSCOLORCHANGE should not be posted.\n");
2466 DispatchMessageA(&msg
);
2469 ok(!ret
, "Wait timed out.\n");
2470 CloseHandle(thread
);
2472 params
.message
= WM_FONTCHANGE
;
2473 thread
= CreateThread(NULL
, 0, notify_message_proc
, ¶ms
, 0, NULL
);
2474 ok(!WaitForSingleObject(thread
, 1000), "Thread should not block.\n");
2475 CloseHandle(thread
);
2477 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
))
2479 ok(msg
.message
!= WM_FONTCHANGE
, "WM_FONTCHANGE should not be posted.\n");
2480 DispatchMessageA(&msg
);
2483 hr
= IVideoWindow_put_Owner(window
, 0);
2484 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
2487 static void test_video_window_autoshow(IVideoWindow
*window
, IFilterGraph2
*graph
, HWND hwnd
)
2489 IMediaControl
*control
;
2493 IFilterGraph2_QueryInterface(graph
, &IID_IMediaControl
, (void **)&control
);
2495 hr
= IVideoWindow_get_AutoShow(window
, &l
);
2496 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
2497 ok(l
== OATRUE
, "Got %ld.\n", l
);
2499 hr
= IVideoWindow_put_Visible(window
, OAFALSE
);
2500 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
2502 hr
= IMediaControl_Pause(control
);
2503 ok(hr
== S_FALSE
, "Got hr %#lx.\n", hr
);
2505 hr
= IVideoWindow_get_Visible(window
, &l
);
2506 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
2507 ok(l
== OATRUE
, "Got %ld.\n", l
);
2509 hr
= IMediaControl_Stop(control
);
2510 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
2512 hr
= IVideoWindow_get_Visible(window
, &l
);
2513 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
2514 ok(l
== OATRUE
, "Got %ld.\n", l
);
2516 hr
= IVideoWindow_put_AutoShow(window
, OAFALSE
);
2517 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
2519 hr
= IVideoWindow_put_Visible(window
, OAFALSE
);
2520 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
2522 hr
= IMediaControl_Pause(control
);
2523 ok(hr
== S_FALSE
, "Got hr %#lx.\n", hr
);
2525 hr
= IVideoWindow_get_Visible(window
, &l
);
2526 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
2527 ok(l
== OAFALSE
, "Got %ld.\n", l
);
2529 hr
= IMediaControl_Stop(control
);
2530 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
2532 IMediaControl_Release(control
);
2535 static void test_video_window(void)
2537 ALLOCATOR_PROPERTIES req_props
= {1, 600 * 400 * 4, 1, 0}, ret_props
;
2538 VIDEOINFOHEADER vih
=
2540 .bmiHeader
.biSize
= sizeof(BITMAPINFOHEADER
),
2541 .bmiHeader
.biBitCount
= 32,
2542 .bmiHeader
.biWidth
= 600,
2543 .bmiHeader
.biHeight
= 400,
2544 .bmiHeader
.biPlanes
= 1,
2545 .bmiHeader
.biCompression
= BI_RGB
,
2547 AM_MEDIA_TYPE req_mt
=
2549 .majortype
= MEDIATYPE_Video
,
2550 .subtype
= MEDIASUBTYPE_RGB32
,
2551 .formattype
= FORMAT_VideoInfo
,
2552 .cbFormat
= sizeof(vih
),
2553 .pbFormat
= (BYTE
*)&vih
,
2555 IFilterGraph2
*graph
= create_graph();
2556 WNDCLASSA window_class
= {0};
2557 struct testfilter source
;
2558 IMemAllocator
*allocator
;
2559 MONITORINFO monitorinfo
;
2560 IMediaControl
*control
;
2561 LONG width
, height
, l
;
2562 IVideoWindow
*window
;
2563 IMemInputPin
*input
;
2564 IBaseFilter
*filter
;
2565 HWND hwnd
, our_hwnd
;
2574 window_class
.lpszClassName
= "wine_test_class";
2575 window_class
.lpfnWndProc
= window_proc
;
2576 RegisterClassA(&window_class
);
2577 our_hwnd
= CreateWindowA("wine_test_class", "test window", WS_VISIBLE
| WS_OVERLAPPEDWINDOW
,
2578 100, 200, 300, 400, NULL
, NULL
, NULL
, NULL
);
2581 filter
= create_vmr9(VMR9Mode_Windowed
);
2585 ok(GetActiveWindow() == our_hwnd
, "Got active window %p.\n", GetActiveWindow());
2587 IBaseFilter_FindPin(filter
, L
"VMR Input0", &pin
);
2588 IPin_QueryInterface(pin
, &IID_IMemInputPin
, (void **)&input
);
2590 hr
= IPin_QueryInterface(pin
, &IID_IOverlay
, (void **)&overlay
);
2591 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
2593 hr
= IOverlay_GetWindowHandle(overlay
, &hwnd
);
2594 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
2595 if (winetest_debug
> 1) trace("ours %p, theirs %p\n", our_hwnd
, hwnd
);
2596 GetWindowRect(hwnd
, &rect
);
2598 tid
= GetWindowThreadProcessId(hwnd
, NULL
);
2599 ok(tid
== GetCurrentThreadId(), "Expected tid %#lx, got %#lx.\n", GetCurrentThreadId(), tid
);
2601 hr
= IBaseFilter_QueryInterface(filter
, &IID_IVideoWindow
, (void **)&window
);
2602 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
2604 hr
= IVideoWindow_get_Caption(window
, &caption
);
2605 todo_wine
ok(hr
== VFW_E_NOT_CONNECTED
, "Got hr %#lx.\n", hr
);
2607 caption
= SysAllocString(L
"foo");
2608 hr
= IVideoWindow_put_Caption(window
, caption
);
2609 ok(hr
== VFW_E_NOT_CONNECTED
, "Got hr %#lx.\n", hr
);
2610 SysFreeString(caption
);
2612 hr
= IVideoWindow_get_WindowStyle(window
, &l
);
2613 todo_wine
ok(hr
== VFW_E_NOT_CONNECTED
, "Got hr %#lx.\n", hr
);
2615 hr
= IVideoWindow_put_WindowStyle(window
, WS_CHILD
| WS_VISIBLE
| WS_CLIPSIBLINGS
| WS_CLIPCHILDREN
);
2616 ok(hr
== VFW_E_NOT_CONNECTED
, "Got hr %#lx.\n", hr
);
2618 hr
= IVideoWindow_get_AutoShow(window
, &l
);
2619 todo_wine
ok(hr
== VFW_E_NOT_CONNECTED
, "Got hr %#lx.\n", hr
);
2621 hr
= IVideoWindow_put_AutoShow(window
, OAFALSE
);
2622 ok(hr
== VFW_E_NOT_CONNECTED
, "Got hr %#lx.\n", hr
);
2624 hr
= IVideoWindow_put_Owner(window
, (OAHWND
)our_hwnd
);
2625 ok(hr
== VFW_E_NOT_CONNECTED
, "Got hr %#lx.\n", hr
);
2627 hr
= IVideoWindow_put_MessageDrain(window
, (OAHWND
)our_hwnd
);
2628 ok(hr
== VFW_E_NOT_CONNECTED
, "Got hr %#lx.\n", hr
);
2630 hr
= IVideoWindow_put_Visible(window
, OATRUE
);
2631 ok(hr
== VFW_E_NOT_CONNECTED
, "Got hr %#lx.\n", hr
);
2633 hr
= IVideoWindow_SetWindowPosition(window
, 100, 200, 300, 400);
2634 ok(hr
== VFW_E_NOT_CONNECTED
, "Got hr %#lx.\n", hr
);
2636 testfilter_init(&source
);
2637 IFilterGraph2_AddFilter(graph
, &source
.filter
.IBaseFilter_iface
, NULL
);
2638 IFilterGraph2_AddFilter(graph
, filter
, NULL
);
2639 IFilterGraph2_QueryInterface(graph
, &IID_IMediaControl
, (void **)&control
);
2640 hr
= IFilterGraph2_ConnectDirect(graph
, &source
.source
.pin
.IPin_iface
, pin
, &req_mt
);
2643 skip("Got E_FAIL when connecting.\n");
2646 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
2648 hr
= IMemInputPin_GetAllocator(input
, &allocator
);
2649 todo_wine
ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
2652 hr
= IMemAllocator_SetProperties(allocator
, &req_props
, &ret_props
);
2653 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
2654 ok(!memcmp(&ret_props
, &req_props
, sizeof(req_props
)), "Properties did not match.\n");
2655 hr
= IMemAllocator_Commit(allocator
);
2656 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
2657 IMemAllocator_Release(allocator
);
2661 ok(GetActiveWindow() == our_hwnd
, "Got active window %p.\n", GetActiveWindow());
2663 test_video_window_caption(window
, hwnd
);
2664 test_video_window_style(window
, hwnd
, our_hwnd
);
2665 test_video_window_state(window
, hwnd
, our_hwnd
);
2666 test_video_window_position(window
, hwnd
, our_hwnd
);
2667 test_video_window_autoshow(window
, graph
, hwnd
);
2668 test_video_window_owner(window
, hwnd
, our_hwnd
);
2669 test_video_window_messages(window
, hwnd
, our_hwnd
);
2671 hr
= IVideoWindow_put_FullScreenMode(window
, OATRUE
);
2672 ok(hr
== E_NOTIMPL
, "Got hr %#lx.\n", hr
);
2673 hr
= IVideoWindow_get_FullScreenMode(window
, &l
);
2674 ok(hr
== E_NOTIMPL
, "Got hr %#lx.\n", hr
);
2676 hr
= IVideoWindow_GetMinIdealImageSize(window
, &width
, &height
);
2677 todo_wine
ok(hr
== VFW_E_WRONG_STATE
, "Got hr %#lx.\n", hr
);
2678 hr
= IVideoWindow_GetMaxIdealImageSize(window
, &width
, &height
);
2679 todo_wine
ok(hr
== VFW_E_WRONG_STATE
, "Got hr %#lx.\n", hr
);
2681 hr
= IMediaControl_Pause(control
);
2682 ok(hr
== S_FALSE
, "Got hr %#lx.\n", hr
);
2684 monitorinfo
.cbSize
= sizeof(monitorinfo
);
2685 GetMonitorInfoW(MonitorFromWindow(hwnd
, MONITOR_DEFAULTTOPRIMARY
), &monitorinfo
);
2687 hr
= IVideoWindow_GetMinIdealImageSize(window
, &width
, &height
);
2688 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
2689 todo_wine
ok(width
== 1, "Got width %ld.\n", width
);
2690 todo_wine
ok(height
== 1, "Got height %ld.\n", height
);
2691 hr
= IVideoWindow_GetMaxIdealImageSize(window
, &width
, &height
);
2692 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
2693 todo_wine
ok(width
== monitorinfo
.rcMonitor
.right
+ 1, "Expected width %ld, got %ld.\n",
2694 monitorinfo
.rcMonitor
.right
+ 1, width
);
2695 todo_wine
ok(height
== monitorinfo
.rcMonitor
.bottom
+ 1, "Expected height %ld, got %ld.\n",
2696 monitorinfo
.rcMonitor
.bottom
+ 1, height
);
2698 hr
= IMediaControl_Stop(control
);
2699 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
2702 IMediaControl_Release(control
);
2703 IFilterGraph2_Release(graph
);
2704 IVideoWindow_Release(window
);
2705 IOverlay_Release(overlay
);
2706 IMemInputPin_Release(input
);
2708 ref
= IBaseFilter_Release(filter
);
2709 ok(!ref
, "Got outstanding refcount %ld.\n", ref
);
2710 ref
= IBaseFilter_Release(&source
.filter
.IBaseFilter_iface
);
2711 ok(!ref
, "Got outstanding refcount %ld.\n", ref
);
2712 DestroyWindow(our_hwnd
);
2715 static IDirect3DDevice9
*create_device(HWND window
)
2717 D3DPRESENT_PARAMETERS present_parameters
=
2720 .hDeviceWindow
= window
,
2721 .SwapEffect
= D3DSWAPEFFECT_DISCARD
,
2722 .BackBufferWidth
= 640,
2723 .BackBufferHeight
= 480,
2724 .BackBufferFormat
= D3DFMT_A8R8G8B8
,
2726 IDirect3DDevice9
*device
;
2730 d3d
= Direct3DCreate9(D3D_SDK_VERSION
);
2731 ok(!!d3d
, "Failed to create a D3D object.\n");
2733 hr
= IDirect3D9_CreateDevice(d3d
, D3DADAPTER_DEFAULT
, D3DDEVTYPE_HAL
, window
,
2734 D3DCREATE_HARDWARE_VERTEXPROCESSING
, &present_parameters
, &device
);
2735 IDirect3D9_Release(d3d
);
2738 skip("Failed to create a 3D device, hr %#lx.\n", hr
);
2744 static void test_allocate_surface_helper(void)
2746 VMR9AllocationInfo info
=
2748 .dwFlags
= VMR9AllocFlag_OffscreenSurface
,
2751 .Format
= D3DFMT_X8R8G8B8
,
2752 .Pool
= D3DPOOL_DEFAULT
,
2754 .szAspectRatio
= {32, 16},
2755 .szNativeSize
= {32, 16},
2757 IBaseFilter
*filter
= create_vmr9(VMR9Mode_Renderless
);
2758 IVMRSurfaceAllocatorNotify9
*notify
;
2759 IDirect3DSurface9
*surfaces
[2] = {};
2760 IDirect3DDevice9
*device
, *device2
;
2761 RECT rect
= {0, 0, 640, 480};
2762 IDirect3DTexture9
*container
;
2763 D3DSURFACE_DESC desc
;
2769 AdjustWindowRect(&rect
, WS_OVERLAPPEDWINDOW
, FALSE
);
2770 window
= CreateWindowA("static", "quartz_test", WS_OVERLAPPEDWINDOW
, 0, 0,
2771 rect
.right
- rect
.left
, rect
.bottom
- rect
.top
, NULL
, NULL
, NULL
, NULL
);
2772 if (!(device
= create_device(window
)))
2774 IBaseFilter_Release(filter
);
2775 DestroyWindow(window
);
2779 IBaseFilter_QueryInterface(filter
, &IID_IVMRSurfaceAllocatorNotify9
, (void **)¬ify
);
2782 hr
= IVMRSurfaceAllocatorNotify9_AllocateSurfaceHelper(notify
, &info
, &count
, surfaces
);
2783 todo_wine
ok(hr
== E_FAIL
, "Got hr %#lx.\n", hr
);
2785 hr
= IVMRSurfaceAllocatorNotify9_SetD3DDevice(notify
, device
, MonitorFromWindow(window
, MONITOR_DEFAULTTOPRIMARY
));
2786 if (hr
== E_NOINTERFACE
)
2788 win_skip("Direct3D does not support video rendering.\n");
2791 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
2793 if (0) /* crashes on Windows */
2795 hr
= IVMRSurfaceAllocatorNotify9_AllocateSurfaceHelper(notify
, NULL
, &count
, surfaces
);
2796 ok(hr
== E_POINTER
, "Got hr %#lx.\n", hr
);
2798 hr
= IVMRSurfaceAllocatorNotify9_AllocateSurfaceHelper(notify
, &info
, NULL
, surfaces
);
2799 ok(hr
== E_POINTER
, "Got hr %#lx.\n", hr
);
2802 hr
= IVMRSurfaceAllocatorNotify9_AllocateSurfaceHelper(notify
, &info
, &count
, NULL
);
2803 ok(hr
== E_POINTER
, "Got hr %#lx.\n", hr
);
2805 hr
= IVMRSurfaceAllocatorNotify9_AllocateSurfaceHelper(notify
, &info
, &count
, surfaces
);
2806 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
2807 ok(count
== 2, "Got count %lu.\n", count
);
2808 ok(!!surfaces
[0], "Surface 0 was not allocated.\n");
2809 ok(!!surfaces
[1], "Surface 1 was not allocated.\n");
2811 hr
= IDirect3DSurface9_GetDevice(surfaces
[0], &device2
);
2812 ok(hr
== D3D_OK
, "Got hr %#lx.\n", hr
);
2813 ok(device2
== device
, "Devices did not match.\n");
2814 IDirect3DDevice9_Release(device2
);
2816 hr
= IDirect3DSurface9_GetContainer(surfaces
[0], &IID_IDirect3DTexture9
, (void **)&container
);
2817 ok(hr
== E_NOINTERFACE
, "Got hr %#lx.\n", hr
);
2819 hr
= IDirect3DSurface9_GetDesc(surfaces
[0], &desc
);
2820 ok(hr
== D3D_OK
, "Got hr %#lx.\n", hr
);
2821 ok(desc
.Format
== info
.Format
, "Got format %#x.\n", desc
.Format
);
2822 ok(desc
.Type
== D3DRTYPE_SURFACE
, "Got type %u.\n", desc
.Type
);
2823 ok(!desc
.Usage
, "Got usage %#lx.\n", desc
.Usage
);
2824 ok(desc
.Pool
== D3DPOOL_DEFAULT
, "Got pool %u.\n", desc
.Pool
);
2825 ok(desc
.MultiSampleType
== D3DMULTISAMPLE_NONE
, "Got multisample type %u.\n", desc
.MultiSampleType
);
2826 ok(!desc
.MultiSampleQuality
, "Got multisample quality %lu.\n", desc
.MultiSampleQuality
);
2827 ok(desc
.Width
== 32, "Got width %u.\n", desc
.Width
);
2828 ok(desc
.Height
== 16, "Got height %u.\n", desc
.Height
);
2830 IDirect3DSurface9_Release(surfaces
[0]);
2831 IDirect3DSurface9_Release(surfaces
[1]);
2833 surfaces
[0] = surfaces
[1] = NULL
;
2835 hr
= IVMRSurfaceAllocatorNotify9_AllocateSurfaceHelper(notify
, &info
, &count
, surfaces
);
2836 todo_wine
ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
2837 todo_wine
ok(!count
, "Got count %lu.\n", count
);
2838 ok(!surfaces
[0], "Surface 0 was allocated.\n");
2839 ok(!surfaces
[1], "Surface 1 was allocated.\n");
2842 info
.MinBuffers
= 1;
2843 hr
= IVMRSurfaceAllocatorNotify9_AllocateSurfaceHelper(notify
, &info
, &count
, surfaces
);
2844 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
2845 ok(count
== 2, "Got count %lu.\n", count
);
2846 ok(!!surfaces
[0], "Surface 0 was not allocated.\n");
2847 ok(!!surfaces
[1], "Surface 1 was not allocated.\n");
2848 IDirect3DSurface9_Release(surfaces
[0]);
2849 IDirect3DSurface9_Release(surfaces
[1]);
2852 info
.dwFlags
= VMR9AllocFlag_TextureSurface
;
2853 surfaces
[0] = surfaces
[1] = NULL
;
2854 hr
= IVMRSurfaceAllocatorNotify9_AllocateSurfaceHelper(notify
, &info
, &count
, surfaces
);
2855 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
2856 ok(count
== 2, "Got count %lu.\n", count
);
2857 ok(!!surfaces
[0], "Surface 0 was not allocated.\n");
2858 ok(!!surfaces
[1], "Surface 1 was not allocated.\n");
2860 hr
= IDirect3DSurface9_GetDevice(surfaces
[0], &device2
);
2861 ok(hr
== D3D_OK
, "Got hr %#lx.\n", hr
);
2862 ok(device2
== device
, "Devices did not match.\n");
2863 IDirect3DDevice9_Release(device2
);
2865 hr
= IDirect3DSurface9_GetContainer(surfaces
[0], &IID_IDirect3DTexture9
, (void **)&container
);
2866 ok(hr
== D3D_OK
, "Got hr %#lx.\n", hr
);
2867 IDirect3DTexture9_Release(container
);
2869 hr
= IDirect3DSurface9_GetDesc(surfaces
[1], &desc
);
2870 ok(hr
== D3D_OK
, "Got hr %#lx.\n", hr
);
2871 ok(desc
.Format
== info
.Format
, "Got format %#x.\n", desc
.Format
);
2872 ok(desc
.Type
== D3DRTYPE_SURFACE
, "Got type %u.\n", desc
.Type
);
2873 ok(desc
.Usage
== D3DUSAGE_DYNAMIC
, "Got usage %#lx.\n", desc
.Usage
);
2874 ok(desc
.Pool
== D3DPOOL_DEFAULT
, "Got pool %u.\n", desc
.Pool
);
2875 ok(desc
.MultiSampleType
== D3DMULTISAMPLE_NONE
, "Got multisample type %u.\n", desc
.MultiSampleType
);
2876 ok(!desc
.MultiSampleQuality
, "Got multisample quality %lu.\n", desc
.MultiSampleQuality
);
2877 ok(desc
.Width
== 32, "Got width %u.\n", desc
.Width
);
2878 ok(desc
.Height
== 16, "Got height %u.\n", desc
.Height
);
2880 IDirect3DSurface9_Release(surfaces
[0]);
2881 IDirect3DSurface9_Release(surfaces
[1]);
2883 info
.Format
= D3DFMT_R8G8B8
;
2884 surfaces
[0] = surfaces
[1] = NULL
;
2885 hr
= IVMRSurfaceAllocatorNotify9_AllocateSurfaceHelper(notify
, &info
, &count
, surfaces
);
2886 ok(hr
== D3DERR_INVALIDCALL
, "Got hr %#lx.\n", hr
);
2887 ok(!count
, "Got count %lu.\n", count
);
2888 ok(!surfaces
[0], "Surface 0 was allocated.\n");
2889 ok(!surfaces
[1], "Surface 1 was allocated.\n");
2892 info
.dwFlags
= VMR9AllocFlag_3DRenderTarget
;
2894 hr
= IVMRSurfaceAllocatorNotify9_AllocateSurfaceHelper(notify
, &info
, &count
, surfaces
);
2895 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
2896 ok(count
== 1, "Got count %lu.\n", count
);
2897 ok(!!surfaces
[0], "Surface 0 was not allocated.\n");
2898 ok(info
.Format
!= 0, "Expected a format.\n");
2900 hr
= IDirect3DSurface9_GetDesc(surfaces
[0], &desc
);
2901 ok(hr
== D3D_OK
, "Got hr %#lx.\n", hr
);
2902 ok(desc
.Format
== info
.Format
, "Expected format %#x, got %#x.\n", info
.Format
, desc
.Format
);
2903 ok(desc
.Type
== D3DRTYPE_SURFACE
, "Got type %u.\n", desc
.Type
);
2904 ok(desc
.Usage
== D3DUSAGE_RENDERTARGET
, "Got usage %#lx.\n", desc
.Usage
);
2905 ok(desc
.Pool
== D3DPOOL_DEFAULT
, "Got pool %u.\n", desc
.Pool
);
2906 ok(desc
.MultiSampleType
== D3DMULTISAMPLE_NONE
, "Got multisample type %u.\n", desc
.MultiSampleType
);
2907 ok(!desc
.MultiSampleQuality
, "Got multisample quality %lu.\n", desc
.MultiSampleQuality
);
2908 ok(desc
.Width
== 32, "Got width %u.\n", desc
.Width
);
2909 ok(desc
.Height
== 16, "Got height %u.\n", desc
.Height
);
2911 IDirect3DSurface9_Release(surfaces
[0]);
2913 info
.Format
= D3DFMT_A8R8G8B8
;
2914 info
.dwFlags
= VMR9AllocFlag_OffscreenSurface
| VMR9AllocFlag_TextureSurface
;
2916 hr
= IVMRSurfaceAllocatorNotify9_AllocateSurfaceHelper(notify
, &info
, &count
, surfaces
);
2917 ok(hr
== E_INVALIDARG
, "Got hr %#lx.\n", hr
);
2918 ok(count
== 1, "Got count %lu.\n", count
);
2921 IVMRSurfaceAllocatorNotify9_Release(notify
);
2922 ref
= IBaseFilter_Release(filter
);
2923 ok(!ref
, "Got outstanding refcount %ld.\n", ref
);
2924 ref
= IDirect3DDevice9_Release(device
);
2925 ok(!ref
, "Got outstanding refcount %ld.\n", ref
);
2926 DestroyWindow(window
);
2931 IVMRSurfaceAllocator9 IVMRSurfaceAllocator9_iface
;
2932 IVMRImagePresenter9 IVMRImagePresenter9_iface
;
2937 IDirect3DSurface9
*surfaces
[5];
2938 IVMRSurfaceAllocatorNotify9
*notify
;
2939 unsigned int got_PresentImage
, got_TerminateDevice
;
2942 static struct presenter
*impl_from_IVMRImagePresenter9(IVMRImagePresenter9
*iface
)
2944 return CONTAINING_RECORD(iface
, struct presenter
, IVMRImagePresenter9_iface
);
2947 static HRESULT WINAPI
presenter_QueryInterface(IVMRImagePresenter9
*iface
, REFIID iid
, void **out
)
2949 struct presenter
*presenter
= impl_from_IVMRImagePresenter9(iface
);
2950 return IVMRSurfaceAllocator9_QueryInterface(&presenter
->IVMRSurfaceAllocator9_iface
, iid
, out
);
2953 static ULONG WINAPI
presenter_AddRef(IVMRImagePresenter9
*iface
)
2955 struct presenter
*presenter
= impl_from_IVMRImagePresenter9(iface
);
2956 return IVMRSurfaceAllocator9_AddRef(&presenter
->IVMRSurfaceAllocator9_iface
);
2959 static ULONG WINAPI
presenter_Release(IVMRImagePresenter9
*iface
)
2961 struct presenter
*presenter
= impl_from_IVMRImagePresenter9(iface
);
2962 return IVMRSurfaceAllocator9_Release(&presenter
->IVMRSurfaceAllocator9_iface
);
2965 static HRESULT WINAPI
presenter_StartPresenting(IVMRImagePresenter9
*iface
, DWORD_PTR cookie
)
2967 if (winetest_debug
> 1) trace("StartPresenting()\n");
2968 ok(cookie
== 0xabacab, "Got cookie %#Ix.\n", cookie
);
2972 static HRESULT WINAPI
presenter_StopPresenting(IVMRImagePresenter9
*iface
, DWORD_PTR cookie
)
2974 if (winetest_debug
> 1) trace("StopPresenting()\n");
2975 ok(cookie
== 0xabacab, "Got cookie %#Ix.\n", cookie
);
2979 static HRESULT WINAPI
presenter_PresentImage(IVMRImagePresenter9
*iface
, DWORD_PTR cookie
, VMR9PresentationInfo
*info
)
2981 struct presenter
*presenter
= impl_from_IVMRImagePresenter9(iface
);
2982 static const RECT rect
;
2984 if (winetest_debug
> 1) trace("PresentImage()\n");
2985 ok(cookie
== 0xabacab, "Got cookie %#Ix.\n", cookie
);
2986 todo_wine
ok(info
->dwFlags
== VMR9Sample_TimeValid
, "Got flags %#lx.\n", info
->dwFlags
);
2987 ok(!info
->rtStart
, "Got start time %s.\n", wine_dbgstr_longlong(info
->rtStart
));
2988 ok(info
->rtEnd
== 10000000, "Got end time %s.\n", wine_dbgstr_longlong(info
->rtEnd
));
2989 todo_wine
ok(info
->szAspectRatio
.cx
== 120, "Got aspect ratio width %ld.\n", info
->szAspectRatio
.cx
);
2990 todo_wine
ok(info
->szAspectRatio
.cy
== 60, "Got aspect ratio height %ld.\n", info
->szAspectRatio
.cy
);
2991 ok(EqualRect(&info
->rcSrc
, &rect
), "Got source rect %s.\n", wine_dbgstr_rect(&info
->rcSrc
));
2992 ok(EqualRect(&info
->rcDst
, &rect
), "Got dest rect %s.\n", wine_dbgstr_rect(&info
->rcDst
));
2993 ok(!info
->dwReserved1
, "Got dwReserved1 %#lx.\n", info
->dwReserved1
);
2994 ok(!info
->dwReserved2
, "Got dwReserved2 %#lx.\n", info
->dwReserved2
);
2996 ++presenter
->got_PresentImage
;
3000 static const IVMRImagePresenter9Vtbl presenter_vtbl
=
3002 presenter_QueryInterface
,
3005 presenter_StartPresenting
,
3006 presenter_StopPresenting
,
3007 presenter_PresentImage
,
3010 static struct presenter
*impl_from_IVMRSurfaceAllocator9(IVMRSurfaceAllocator9
*iface
)
3012 return CONTAINING_RECORD(iface
, struct presenter
, IVMRSurfaceAllocator9_iface
);
3015 static HRESULT WINAPI
allocator_QueryInterface(IVMRSurfaceAllocator9
*iface
, REFIID iid
, void **out
)
3017 struct presenter
*presenter
= impl_from_IVMRSurfaceAllocator9(iface
);
3019 if (winetest_debug
> 1) trace("QueryInterface(%s)\n", wine_dbgstr_guid(iid
));
3021 if (IsEqualGUID(iid
, &IID_IVMRImagePresenter9
))
3023 *out
= &presenter
->IVMRImagePresenter9_iface
;
3024 IVMRImagePresenter9_AddRef(&presenter
->IVMRImagePresenter9_iface
);
3027 ok(!IsEqualGUID(iid
, &IID_IVMRSurfaceAllocatorEx9
), "Unexpected query for IVMRSurfaceAllocatorEx9.\n");
3032 static ULONG WINAPI
allocator_AddRef(IVMRSurfaceAllocator9
*iface
)
3034 struct presenter
*presenter
= impl_from_IVMRSurfaceAllocator9(iface
);
3035 return InterlockedIncrement(&presenter
->refcount
);
3038 static ULONG WINAPI
allocator_Release(IVMRSurfaceAllocator9
*iface
)
3040 struct presenter
*presenter
= impl_from_IVMRSurfaceAllocator9(iface
);
3041 return InterlockedDecrement(&presenter
->refcount
);
3044 static HRESULT WINAPI
allocator_InitializeDevice(IVMRSurfaceAllocator9
*iface
,
3045 DWORD_PTR cookie
, VMR9AllocationInfo
*info
, DWORD
*buffer_count
)
3047 struct presenter
*presenter
= impl_from_IVMRSurfaceAllocator9(iface
);
3049 if (winetest_debug
> 1) trace("InitializeDevice(flags %#lx, format %u)\n",
3050 info
->dwFlags
, info
->Format
);
3051 ok(cookie
== 0xabacab, "Got cookie %#Ix.\n", cookie
);
3052 ok(info
->dwWidth
== 32, "Got width %lu.\n", info
->dwWidth
);
3053 ok(info
->dwHeight
== 16, "Got height %lu.\n", info
->dwHeight
);
3054 todo_wine
ok(info
->MinBuffers
== 5, "Got buffer count %lu.\n", info
->MinBuffers
);
3055 ok(info
->Pool
== D3DPOOL_DEFAULT
, "Got pool %u\n", info
->Pool
);
3056 todo_wine
ok(info
->szAspectRatio
.cx
== 120, "Got aspect ratio width %ld.\n", info
->szAspectRatio
.cx
);
3057 todo_wine
ok(info
->szAspectRatio
.cy
== 60, "Got aspect ratio height %ld.\n", info
->szAspectRatio
.cy
);
3058 ok(info
->szNativeSize
.cx
== 32, "Got native width %ld.\n", info
->szNativeSize
.cx
);
3059 ok(info
->szNativeSize
.cy
== 16, "Got native height %ld.\n", info
->szNativeSize
.cy
);
3060 todo_wine
ok(*buffer_count
== 5, "Got buffer count %lu.\n", *buffer_count
);
3062 presenter
->format
= info
->Format
;
3064 if (info
->dwFlags
!= presenter
->accept_flags
)
3066 return IVMRSurfaceAllocatorNotify9_AllocateSurfaceHelper(presenter
->notify
,
3067 info
, buffer_count
, presenter
->surfaces
);
3070 static HRESULT WINAPI
allocator_TerminateDevice(IVMRSurfaceAllocator9
*iface
, DWORD_PTR cookie
)
3072 struct presenter
*presenter
= impl_from_IVMRSurfaceAllocator9(iface
);
3074 if (winetest_debug
> 1) trace("TerminateDevice()\n");
3075 ok(cookie
== 0xabacab, "Got cookie %#Ix.\n", cookie
);
3076 /* Don't dereference the surfaces here, to mimic How to Survive. */
3077 ++presenter
->got_TerminateDevice
;
3081 static HRESULT WINAPI
allocator_GetSurface(IVMRSurfaceAllocator9
*iface
,
3082 DWORD_PTR cookie
, DWORD index
, DWORD flags
, IDirect3DSurface9
**surface
)
3084 struct presenter
*presenter
= impl_from_IVMRSurfaceAllocator9(iface
);
3086 if (winetest_debug
> 1) trace("GetSurface(index %lu)\n", index
);
3087 ok(cookie
== 0xabacab, "Got cookie %#Ix.\n", cookie
);
3088 ok(!flags
, "Got flags %#lx.\n", flags
);
3089 ok(index
< 5, "Got index %lu.\n", index
);
3091 /* Don't reference the surface here, to mimic How to Survive. */
3092 *surface
= presenter
->surfaces
[index
];
3096 static HRESULT WINAPI
allocator_AdviseNotify(IVMRSurfaceAllocator9
*iface
, IVMRSurfaceAllocatorNotify9
*notify
)
3098 ok(0, "Unexpected call.\n");
3102 static const IVMRSurfaceAllocator9Vtbl allocator_vtbl
=
3104 allocator_QueryInterface
,
3107 allocator_InitializeDevice
,
3108 allocator_TerminateDevice
,
3109 allocator_GetSurface
,
3110 allocator_AdviseNotify
,
3113 static void test_renderless_present(struct presenter
*presenter
,
3114 IFilterGraph2
*graph
, IMemInputPin
*input
)
3116 IMediaControl
*control
;
3117 OAFilterState state
;
3121 IFilterGraph2_QueryInterface(graph
, &IID_IMediaControl
, (void **)&control
);
3123 presenter
->got_PresentImage
= 0;
3125 hr
= IMediaControl_Pause(control
);
3126 ok(hr
== S_FALSE
, "Got hr %#lx.\n", hr
);
3127 thread
= send_frame(input
);
3128 hr
= IMediaControl_GetState(control
, 1000, &state
);
3129 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
3130 /* Atelier Sophie uses the VMR in renderless mode, calls
3131 * IMediaControl::Run() from a stopped state and expects that
3132 * IMediaControl::GetState() returns S_OK only after PresentImage() has
3134 ok(presenter
->got_PresentImage
== 1, "Got %u calls to PresentImage().\n", presenter
->got_PresentImage
);
3136 hr
= IMediaControl_Run(control
);
3137 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
3138 hr
= join_thread(thread
);
3139 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
3140 ok(presenter
->got_PresentImage
== 1, "Got %u calls to PresentImage().\n", presenter
->got_PresentImage
);
3142 hr
= IMediaControl_Stop(control
);
3143 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
3145 IMediaControl_Release(control
);
3148 static void test_renderless_formats(void)
3150 VIDEOINFOHEADER vih
=
3152 .rcSource
= {4, 6, 16, 12},
3153 .rcTarget
= {40, 60, 160, 120},
3154 .bmiHeader
.biSize
= sizeof(BITMAPINFOHEADER
),
3155 .bmiHeader
.biWidth
= 32,
3156 .bmiHeader
.biHeight
= 16,
3158 AM_MEDIA_TYPE req_mt
=
3160 .majortype
= MEDIATYPE_Video
,
3161 .formattype
= FORMAT_VideoInfo
,
3162 .cbFormat
= sizeof(vih
),
3163 .pbFormat
= (BYTE
*)&vih
,
3165 ALLOCATOR_PROPERTIES req_props
= {5, 32 * 16 * 4, 1, 0}, ret_props
;
3166 struct presenter presenter
=
3168 .IVMRSurfaceAllocator9_iface
.lpVtbl
= &allocator_vtbl
,
3169 .IVMRImagePresenter9_iface
.lpVtbl
= &presenter_vtbl
,
3172 struct presenter presenter2
= presenter
;
3173 IVMRSurfaceAllocatorNotify9
*notify
;
3174 RECT rect
= {0, 0, 640, 480};
3175 struct testfilter source
;
3176 IDirect3DDevice9
*device
;
3177 IMemAllocator
*allocator
;
3178 IFilterGraph2
*graph
;
3179 IMemInputPin
*input
;
3180 IBaseFilter
*filter
;
3189 const GUID
*subtype
;
3195 {&MEDIASUBTYPE_ARGB1555
, D3DFMT_A1R5G5B5
, VMR9AllocFlag_TextureSurface
},
3196 {&MEDIASUBTYPE_ARGB32
, D3DFMT_A8R8G8B8
, VMR9AllocFlag_TextureSurface
},
3197 {&MEDIASUBTYPE_ARGB4444
, D3DFMT_A4R4G4B4
, VMR9AllocFlag_TextureSurface
},
3199 {&MEDIASUBTYPE_RGB555
, D3DFMT_X1R5G5B5
, VMR9AllocFlag_OffscreenSurface
},
3200 {&MEDIASUBTYPE_RGB555
, D3DFMT_X1R5G5B5
, VMR9AllocFlag_TextureSurface
},
3201 {&MEDIASUBTYPE_RGB565
, D3DFMT_R5G6B5
, VMR9AllocFlag_OffscreenSurface
},
3202 {&MEDIASUBTYPE_RGB565
, D3DFMT_R5G6B5
, VMR9AllocFlag_TextureSurface
},
3203 {&MEDIASUBTYPE_RGB24
, D3DFMT_R8G8B8
, VMR9AllocFlag_OffscreenSurface
},
3204 {&MEDIASUBTYPE_RGB24
, D3DFMT_R8G8B8
, VMR9AllocFlag_TextureSurface
},
3205 {&MEDIASUBTYPE_RGB32
, D3DFMT_X8R8G8B8
, VMR9AllocFlag_OffscreenSurface
},
3206 {&MEDIASUBTYPE_RGB32
, D3DFMT_X8R8G8B8
, VMR9AllocFlag_TextureSurface
},
3208 {&MEDIASUBTYPE_NV12
, MAKEFOURCC('N','V','1','2'), VMR9AllocFlag_OffscreenSurface
},
3209 {&MEDIASUBTYPE_UYVY
, D3DFMT_UYVY
, VMR9AllocFlag_OffscreenSurface
},
3210 {&MEDIASUBTYPE_YUY2
, D3DFMT_YUY2
, VMR9AllocFlag_OffscreenSurface
},
3211 {&MEDIASUBTYPE_YV12
, MAKEFOURCC('Y','V','1','2'), VMR9AllocFlag_OffscreenSurface
},
3214 AdjustWindowRect(&rect
, WS_OVERLAPPEDWINDOW
, FALSE
);
3215 window
= CreateWindowA("static", "quartz_test", WS_OVERLAPPEDWINDOW
, 0, 0,
3216 rect
.right
- rect
.left
, rect
.bottom
- rect
.top
, NULL
, NULL
, NULL
, NULL
);
3217 if (!(device
= create_device(window
)))
3219 DestroyWindow(window
);
3223 filter
= create_vmr9(VMR9Mode_Renderless
);
3224 IBaseFilter_QueryInterface(filter
, &IID_IVMRSurfaceAllocatorNotify9
, (void **)¬ify
);
3226 hr
= IVMRSurfaceAllocatorNotify9_SetD3DDevice(notify
, device
, MonitorFromWindow(window
, MONITOR_DEFAULTTOPRIMARY
));
3227 if (hr
== E_NOINTERFACE
)
3229 win_skip("Direct3D does not support video rendering.\n");
3232 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
3234 hr
= IVMRSurfaceAllocatorNotify9_AdviseSurfaceAllocator(notify
, 0xabacab,
3235 &presenter
.IVMRSurfaceAllocator9_iface
);
3236 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
3238 presenter
.notify
= notify
;
3240 testfilter_init(&source
);
3241 graph
= create_graph();
3242 IFilterGraph2_AddFilter(graph
, &source
.filter
.IBaseFilter_iface
, NULL
);
3243 IFilterGraph2_AddFilter(graph
, filter
, NULL
);
3244 IBaseFilter_FindPin(filter
, L
"VMR Input0", &pin
);
3245 IPin_QueryInterface(pin
, &IID_IMemInputPin
, (void **)&input
);
3247 for (i
= 0; i
< ARRAY_SIZE(tests
); ++i
)
3249 req_mt
.subtype
= *tests
[i
].subtype
;
3250 presenter
.accept_flags
= tests
[i
].flags
;
3252 hr
= IFilterGraph2_ConnectDirect(graph
, &source
.source
.pin
.IPin_iface
, pin
, &req_mt
);
3253 /* Connection never fails on Native, but Wine currently creates D3D
3254 * surfaces during IPin::ReceiveConnection() instead of
3255 * IMemAllocator::SetProperties(), so let that fail here for now. */
3258 skip("Format %u (%#x), flags %#lx are not supported, hr %#lx.\n",
3259 tests
[i
].format
, tests
[i
].format
, tests
[i
].flags
, hr
);
3262 ok(hr
== S_OK
, "Test %u: Got hr %#lx.\n", i
, hr
);
3264 hr
= IMemInputPin_GetAllocator(input
, &allocator
);
3265 todo_wine
ok(hr
== S_OK
, "Test %u: Got hr %#lx.\n", i
, hr
);
3268 test_allocator(input
);
3269 hr
= IMemInputPin_GetAllocator(input
, &allocator
);
3272 hr
= IMemAllocator_SetProperties(allocator
, &req_props
, &ret_props
);
3275 skip("Format %u (%#x), flags %#lx are not supported, hr %#lx.\n",
3276 tests
[i
].format
, tests
[i
].format
, tests
[i
].flags
, hr
);
3277 IMemAllocator_Release(allocator
);
3278 hr
= IFilterGraph2_Disconnect(graph
, &source
.source
.pin
.IPin_iface
);
3279 ok(hr
== S_OK
, "Test %u: Got hr %#lx.\n", i
, hr
);
3280 hr
= IFilterGraph2_Disconnect(graph
, pin
);
3281 ok(hr
== S_OK
, "Test %u: Got hr %#lx.\n", i
, hr
);
3284 ok(!memcmp(&ret_props
, &req_props
, sizeof(req_props
)), "Properties did not match.\n");
3285 hr
= IMemAllocator_Commit(allocator
);
3286 ok(hr
== S_OK
, "Test %u: Got hr %#lx.\n", i
, hr
);
3288 hr
= IVMRSurfaceAllocatorNotify9_AdviseSurfaceAllocator(notify
, 0xabacab,
3289 &presenter2
.IVMRSurfaceAllocator9_iface
);
3290 ok(hr
== VFW_E_WRONG_STATE
, "Got hr %#lx.\n", hr
);
3292 ok(presenter
.format
== tests
[i
].format
, "Test %u: Got format %u (%#x).\n",
3293 i
, presenter
.format
, presenter
.format
);
3295 test_renderless_present(&presenter
, graph
, input
);
3297 hr
= IMemAllocator_Decommit(allocator
);
3298 ok(hr
== S_OK
, "Test %u: Got hr %#lx.\n", i
, hr
);
3299 IMemAllocator_Release(allocator
);
3301 hr
= IFilterGraph2_Disconnect(graph
, &source
.source
.pin
.IPin_iface
);
3302 ok(hr
== S_OK
, "Test %u: Got hr %#lx.\n", i
, hr
);
3303 hr
= IFilterGraph2_Disconnect(graph
, pin
);
3304 ok(hr
== S_OK
, "Test %u: Got hr %#lx.\n", i
, hr
);
3307 hr
= IVMRSurfaceAllocatorNotify9_AdviseSurfaceAllocator(notify
, 0xabacab, &presenter2
.IVMRSurfaceAllocator9_iface
);
3308 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
3310 ref
= IFilterGraph2_Release(graph
);
3311 ok(!ref
, "Got outstanding refcount %ld.\n", ref
);
3312 IMemInputPin_Release(input
);
3316 IVMRSurfaceAllocatorNotify9_Release(notify
);
3317 ref
= IBaseFilter_Release(filter
);
3318 ok(!ref
, "Got outstanding refcount %ld.\n", ref
);
3319 ok(presenter
.refcount
== 1, "Got outstanding refcount %ld.\n", presenter
.refcount
);
3320 ok(presenter2
.refcount
== 1, "Got outstanding refcount %ld.\n", presenter2
.refcount
);
3321 ref
= IDirect3DDevice9_Release(device
);
3322 ok(!ref
, "Got outstanding refcount %ld.\n", ref
);
3323 DestroyWindow(window
);
3326 static void test_mixing_mode(void)
3328 IVMRWindowlessControl9
*windowless_control
;
3329 IVMRMixerControl9
*mixer_control
;
3330 IVMRFilterConfig9
*config
;
3331 DWORD stream_count
= 0;
3332 IBaseFilter
*filter
;
3338 static const VMR9Mode modes
[] =
3342 VMR9Mode_Windowless
,
3343 VMR9Mode_Renderless
,
3346 for (i
= 0; i
< ARRAY_SIZE(modes
); ++i
)
3348 filter
= create_vmr9(modes
[i
]);
3349 IBaseFilter_QueryInterface(filter
, &IID_IVMRFilterConfig9
, (void **)&config
);
3351 hr
= IBaseFilter_QueryInterface(filter
, &IID_IVMRMixerControl9
, (void **)&mixer_control
);
3352 ok(hr
== E_NOINTERFACE
, "Got hr %#lx.\n", hr
);
3354 hr
= IVMRFilterConfig9_GetNumberOfStreams(config
, &stream_count
);
3355 ok(hr
== VFW_E_VMR_NOT_IN_MIXER_MODE
, "Got hr %#lx.\n", hr
);
3357 hr
= IVMRFilterConfig9_SetNumberOfStreams(config
, 1);
3358 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
3360 hr
= IVMRFilterConfig9_GetNumberOfStreams(config
, &stream_count
);
3361 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
3362 ok(stream_count
== 1, "Got %lu streams.\n", stream_count
);
3364 hr
= IBaseFilter_QueryInterface(filter
, &IID_IVMRMixerControl9
, (void **)&mixer_control
);
3365 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
3366 IVMRMixerControl9_Release(mixer_control
);
3368 hr
= IVMRFilterConfig9_SetNumberOfStreams(config
, 2);
3369 ok(hr
== VFW_E_WRONG_STATE
, "Got hr %#lx.\n", hr
);
3371 hr
= IVMRFilterConfig9_GetNumberOfStreams(config
, &stream_count
);
3372 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
3373 ok(stream_count
== 1, "Got %lu streams.\n", stream_count
);
3375 IVMRFilterConfig9_Release(config
);
3376 ref
= IBaseFilter_Release(filter
);
3377 ok(!ref
, "Got outstanding refcount %ld.\n", ref
);
3380 filter
= create_vmr9(VMR9Mode_Windowless
);
3381 IBaseFilter_QueryInterface(filter
, &IID_IVMRFilterConfig9
, (void **)&config
);
3382 IBaseFilter_QueryInterface(filter
, &IID_IVMRWindowlessControl9
, (void **)&windowless_control
);
3384 window
= CreateWindowA("static", "quartz_test", WS_OVERLAPPEDWINDOW
, 0, 0, 640, 480, 0, 0, 0, 0);
3385 ok(!!window
, "Failed to create a window.\n");
3386 hr
= IVMRWindowlessControl9_SetVideoClippingWindow(windowless_control
, window
);
3387 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
3389 hr
= IVMRFilterConfig9_GetNumberOfStreams(config
, &stream_count
);
3390 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
3391 ok(stream_count
== 4, "Got %lu streams.\n", stream_count
);
3393 hr
= IBaseFilter_QueryInterface(filter
, &IID_IVMRMixerControl9
, (void **)&mixer_control
);
3394 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
3395 IVMRMixerControl9_Release(mixer_control
);
3397 hr
= IVMRFilterConfig9_SetNumberOfStreams(config
, 2);
3398 ok(hr
== VFW_E_WRONG_STATE
, "Got hr %#lx.\n", hr
);
3400 hr
= IVMRFilterConfig9_GetNumberOfStreams(config
, &stream_count
);
3401 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
3402 ok(stream_count
== 4, "Got %lu streams.\n", stream_count
);
3404 IVMRWindowlessControl9_Release(windowless_control
);
3405 IVMRFilterConfig9_Release(config
);
3406 ref
= IBaseFilter_Release(filter
);
3407 ok(!ref
, "Got outstanding refcount %ld.\n", ref
);
3408 DestroyWindow(window
);
3411 static void test_clipping_window(void)
3413 VIDEOINFOHEADER vih
=
3415 .bmiHeader
.biSize
= sizeof(BITMAPINFOHEADER
),
3416 .bmiHeader
.biWidth
= 32,
3417 .bmiHeader
.biHeight
= 16,
3418 .bmiHeader
.biBitCount
= 32,
3422 .majortype
= MEDIATYPE_Video
,
3423 .subtype
= MEDIASUBTYPE_RGB32
,
3424 .formattype
= FORMAT_VideoInfo
,
3425 .cbFormat
= sizeof(vih
),
3426 .pbFormat
= (BYTE
*)&vih
,
3428 IBaseFilter
*filter
= create_vmr9(VMR9Mode_Windowless
);
3429 IVMRWindowlessControl9
*windowless_control
;
3430 IFilterGraph2
*graph
= create_graph();
3431 struct testfilter source
;
3437 IBaseFilter_QueryInterface(filter
, &IID_IVMRWindowlessControl9
, (void **)&windowless_control
);
3438 IBaseFilter_FindPin(filter
, L
"VMR Input0", &pin
);
3439 testfilter_init(&source
);
3440 IFilterGraph2_AddFilter(graph
, &source
.filter
.IBaseFilter_iface
, L
"source");
3441 IFilterGraph2_AddFilter(graph
, filter
, L
"vmr9");
3442 window
= CreateWindowA("static", "quartz_test", WS_OVERLAPPEDWINDOW
, 0, 0, 640, 480, 0, 0, 0, 0);
3443 ok(!!window
, "Failed to create a window.\n");
3445 hr
= IVMRWindowlessControl9_SetVideoClippingWindow(windowless_control
, NULL
);
3446 ok(hr
== E_INVALIDARG
, "Got hr %#lx.\n", hr
);
3447 hr
= IVMRWindowlessControl9_SetVideoClippingWindow(windowless_control
, (HWND
)0xdeadbeef);
3448 ok(hr
== E_INVALIDARG
, "Got hr %#lx.\n", hr
);
3450 hr
= IFilterGraph2_ConnectDirect(graph
, &source
.source
.pin
.IPin_iface
, pin
, &mt
);
3451 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
3453 hr
= IVMRWindowlessControl9_SetVideoClippingWindow(windowless_control
, window
);
3454 ok(hr
== VFW_E_WRONG_STATE
, "Got hr %#lx.\n", hr
);
3456 hr
= IFilterGraph2_Disconnect(graph
, &source
.source
.pin
.IPin_iface
);
3457 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
3458 hr
= IFilterGraph2_Disconnect(graph
, pin
);
3459 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
3461 hr
= IVMRWindowlessControl9_SetVideoClippingWindow(windowless_control
, window
);
3462 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
3464 ref
= IFilterGraph2_Release(graph
);
3465 ok(!ref
, "Got outstanding refcount %ld.\n", ref
);
3467 IVMRWindowlessControl9_Release(windowless_control
);
3468 ref
= IBaseFilter_Release(filter
);
3469 ok(!ref
, "Got outstanding refcount %ld.\n", ref
);
3470 DestroyWindow(window
);
3473 static void test_surface_allocator_notify_refcount(void)
3475 struct presenter presenter
=
3477 .IVMRSurfaceAllocator9_iface
.lpVtbl
= &allocator_vtbl
,
3478 .IVMRImagePresenter9_iface
.lpVtbl
= &presenter_vtbl
,
3481 IBaseFilter
*filter
= create_vmr9(VMR9Mode_Renderless
);
3482 IVMRSurfaceAllocatorNotify9
*notify
;
3486 set_mixing_mode(filter
, 2);
3488 IBaseFilter_QueryInterface(filter
, &IID_IVMRSurfaceAllocatorNotify9
, (void **)¬ify
);
3490 hr
= IVMRSurfaceAllocatorNotify9_AdviseSurfaceAllocator(notify
, 0xabacab,
3491 &presenter
.IVMRSurfaceAllocator9_iface
);
3492 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
3494 ref
= IBaseFilter_Release(filter
);
3495 ok(!ref
, "Got outstanding refcount %ld.\n", ref
);
3496 ok(presenter
.got_TerminateDevice
== 1, "Got %u calls to TerminateDevice().\n",
3497 presenter
.got_TerminateDevice
);
3498 ok(presenter
.refcount
== 1, "Got outstanding refcount %ld.\n", presenter
.refcount
);
3500 ref
= IVMRSurfaceAllocatorNotify9_Release(notify
);
3501 ok(!ref
, "Got outstanding refcount %ld.\n", ref
);
3504 static void check_source_position_(int line
, IBasicVideo
*video
,
3505 LONG expect_left
, LONG expect_top
, LONG expect_width
, LONG expect_height
)
3507 LONG left
, top
, width
, height
, l
;
3510 left
= top
= width
= height
= 0xdeadbeef;
3511 hr
= IBasicVideo_GetSourcePosition(video
, &left
, &top
, &width
, &height
);
3512 ok_(__FILE__
,line
)(hr
== S_OK
, "Got hr %#lx.\n", hr
);
3513 ok_(__FILE__
,line
)(left
== expect_left
, "Got left %ld.\n", left
);
3514 ok_(__FILE__
,line
)(top
== expect_top
, "Got top %ld.\n", top
);
3515 ok_(__FILE__
,line
)(width
== expect_width
, "Got width %ld.\n", width
);
3516 ok_(__FILE__
,line
)(height
== expect_height
, "Got height %ld.\n", height
);
3519 hr
= IBasicVideo_get_SourceLeft(video
, &l
);
3520 ok_(__FILE__
,line
)(hr
== S_OK
, "Failed to get left, hr %#lx.\n", hr
);
3521 ok_(__FILE__
,line
)(l
== left
, "Got left %ld.\n", l
);
3524 hr
= IBasicVideo_get_SourceTop(video
, &l
);
3525 ok_(__FILE__
,line
)(hr
== S_OK
, "Failed to get top, hr %#lx.\n", hr
);
3526 ok_(__FILE__
,line
)(l
== top
, "Got top %ld.\n", l
);
3529 hr
= IBasicVideo_get_SourceWidth(video
, &l
);
3530 ok_(__FILE__
,line
)(hr
== S_OK
, "Failed to get width, hr %#lx.\n", hr
);
3531 ok_(__FILE__
,line
)(l
== width
, "Got width %ld.\n", l
);
3534 hr
= IBasicVideo_get_SourceHeight(video
, &l
);
3535 ok_(__FILE__
,line
)(hr
== S_OK
, "Failed to get height, hr %#lx.\n", hr
);
3536 ok_(__FILE__
,line
)(l
== height
, "Got height %ld.\n", l
);
3538 #define check_source_position(a,b,c,d,e) check_source_position_(__LINE__,a,b,c,d,e)
3540 static void test_basic_video_source(IBasicVideo
*video
)
3544 check_source_position(video
, 0, 0, 600, 400);
3545 hr
= IBasicVideo_IsUsingDefaultSource(video
);
3546 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
3548 hr
= IBasicVideo_put_SourceLeft(video
, -10);
3549 ok(hr
== E_INVALIDARG
, "Got hr %#lx.\n", hr
);
3550 hr
= IBasicVideo_put_SourceLeft(video
, 10);
3551 ok(hr
== E_INVALIDARG
, "Got hr %#lx.\n", hr
);
3553 hr
= IBasicVideo_put_SourceTop(video
, -10);
3554 ok(hr
== E_INVALIDARG
, "Got hr %#lx.\n", hr
);
3555 hr
= IBasicVideo_put_SourceTop(video
, 10);
3556 ok(hr
== E_INVALIDARG
, "Got hr %#lx.\n", hr
);
3558 hr
= IBasicVideo_put_SourceWidth(video
, -500);
3559 ok(hr
== E_INVALIDARG
, "Got hr %#lx.\n", hr
);
3560 hr
= IBasicVideo_put_SourceWidth(video
, 0);
3561 ok(hr
== E_INVALIDARG
, "Got hr %#lx.\n", hr
);
3562 hr
= IBasicVideo_put_SourceWidth(video
, 700);
3563 ok(hr
== E_INVALIDARG
, "Got hr %#lx.\n", hr
);
3564 hr
= IBasicVideo_put_SourceWidth(video
, 500);
3565 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
3566 check_source_position(video
, 0, 0, 500, 400);
3567 hr
= IBasicVideo_IsUsingDefaultSource(video
);
3568 ok(hr
== S_FALSE
, "Got hr %#lx.\n", hr
);
3570 hr
= IBasicVideo_put_SourceHeight(video
, -300);
3571 ok(hr
== E_INVALIDARG
, "Got hr %#lx.\n", hr
);
3572 hr
= IBasicVideo_put_SourceHeight(video
, 0);
3573 ok(hr
== E_INVALIDARG
, "Got hr %#lx.\n", hr
);
3574 hr
= IBasicVideo_put_SourceHeight(video
, 600);
3575 ok(hr
== E_INVALIDARG
, "Got hr %#lx.\n", hr
);
3576 hr
= IBasicVideo_put_SourceHeight(video
, 300);
3577 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
3578 check_source_position(video
, 0, 0, 500, 300);
3579 hr
= IBasicVideo_IsUsingDefaultSource(video
);
3580 ok(hr
== S_FALSE
, "Got hr %#lx.\n", hr
);
3582 hr
= IBasicVideo_put_SourceLeft(video
, -10);
3583 ok(hr
== E_INVALIDARG
, "Got hr %#lx.\n", hr
);
3584 hr
= IBasicVideo_put_SourceLeft(video
, 10);
3585 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
3586 check_source_position(video
, 10, 0, 500, 300);
3587 hr
= IBasicVideo_IsUsingDefaultSource(video
);
3588 ok(hr
== S_FALSE
, "Got hr %#lx.\n", hr
);
3590 hr
= IBasicVideo_put_SourceTop(video
, -10);
3591 ok(hr
== E_INVALIDARG
, "Got hr %#lx.\n", hr
);
3592 hr
= IBasicVideo_put_SourceTop(video
, 20);
3593 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
3594 check_source_position(video
, 10, 20, 500, 300);
3595 hr
= IBasicVideo_IsUsingDefaultSource(video
);
3596 ok(hr
== S_FALSE
, "Got hr %#lx.\n", hr
);
3598 hr
= IBasicVideo_SetSourcePosition(video
, 4, 5, 60, 40);
3599 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
3600 check_source_position(video
, 4, 5, 60, 40);
3601 hr
= IBasicVideo_IsUsingDefaultSource(video
);
3602 ok(hr
== S_FALSE
, "Got hr %#lx.\n", hr
);
3604 hr
= IBasicVideo_SetSourcePosition(video
, 0, 0, 600, 400);
3605 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
3606 check_source_position(video
, 0, 0, 600, 400);
3607 hr
= IBasicVideo_IsUsingDefaultSource(video
);
3608 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
3610 hr
= IBasicVideo_SetSourcePosition(video
, 4, 5, 60, 40);
3611 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
3612 hr
= IBasicVideo_SetDefaultSourcePosition(video
);
3613 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
3614 check_source_position(video
, 0, 0, 600, 400);
3615 hr
= IBasicVideo_IsUsingDefaultSource(video
);
3616 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
3619 static void check_destination_position_(int line
, IBasicVideo
*video
,
3620 LONG expect_left
, LONG expect_top
, LONG expect_width
, LONG expect_height
)
3622 LONG left
, top
, width
, height
, l
;
3625 left
= top
= width
= height
= 0xdeadbeef;
3626 hr
= IBasicVideo_GetDestinationPosition(video
, &left
, &top
, &width
, &height
);
3627 ok_(__FILE__
,line
)(hr
== S_OK
, "Failed to get position, hr %#lx.\n", hr
);
3628 ok_(__FILE__
,line
)(left
== expect_left
, "Got left %ld.\n", left
);
3629 ok_(__FILE__
,line
)(top
== expect_top
, "Got top %ld.\n", top
);
3630 ok_(__FILE__
,line
)(width
== expect_width
, "Got width %ld.\n", width
);
3631 ok_(__FILE__
,line
)(height
== expect_height
, "Got height %ld.\n", height
);
3634 hr
= IBasicVideo_get_DestinationLeft(video
, &l
);
3635 ok_(__FILE__
,line
)(hr
== S_OK
, "Failed to get left, hr %#lx.\n", hr
);
3636 ok_(__FILE__
,line
)(l
== left
, "Got left %ld.\n", l
);
3639 hr
= IBasicVideo_get_DestinationTop(video
, &l
);
3640 ok_(__FILE__
,line
)(hr
== S_OK
, "Failed to get top, hr %#lx.\n", hr
);
3641 ok_(__FILE__
,line
)(l
== top
, "Got top %ld.\n", l
);
3644 hr
= IBasicVideo_get_DestinationWidth(video
, &l
);
3645 ok_(__FILE__
,line
)(hr
== S_OK
, "Failed to get width, hr %#lx.\n", hr
);
3646 ok_(__FILE__
,line
)(l
== width
, "Got width %ld.\n", l
);
3649 hr
= IBasicVideo_get_DestinationHeight(video
, &l
);
3650 ok_(__FILE__
,line
)(hr
== S_OK
, "Failed to get height, hr %#lx.\n", hr
);
3651 ok_(__FILE__
,line
)(l
== height
, "Got height %ld.\n", l
);
3653 #define check_destination_position(a,b,c,d,e) check_destination_position_(__LINE__,a,b,c,d,e)
3655 static void test_basic_video_destination(IBasicVideo
*video
)
3657 IVideoWindow
*window
;
3661 IBasicVideo_QueryInterface(video
, &IID_IVideoWindow
, (void **)&window
);
3663 check_destination_position(video
, 0, 0, 600, 400);
3664 hr
= IBasicVideo_IsUsingDefaultDestination(video
);
3665 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
3667 hr
= IBasicVideo_put_DestinationLeft(video
, -10);
3668 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
3669 check_destination_position(video
, -10, 0, 600, 400);
3670 hr
= IBasicVideo_IsUsingDefaultDestination(video
);
3671 ok(hr
== S_FALSE
, "Got hr %#lx.\n", hr
);
3673 hr
= IBasicVideo_put_DestinationLeft(video
, 10);
3674 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
3675 check_destination_position(video
, 10, 0, 600, 400);
3676 hr
= IBasicVideo_IsUsingDefaultDestination(video
);
3677 ok(hr
== S_FALSE
, "Got hr %#lx.\n", hr
);
3679 hr
= IBasicVideo_put_DestinationTop(video
, -20);
3680 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
3681 check_destination_position(video
, 10, -20, 600, 400);
3682 hr
= IBasicVideo_IsUsingDefaultDestination(video
);
3683 ok(hr
== S_FALSE
, "Got hr %#lx.\n", hr
);
3685 hr
= IBasicVideo_put_DestinationTop(video
, 20);
3686 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
3687 check_destination_position(video
, 10, 20, 600, 400);
3688 hr
= IBasicVideo_IsUsingDefaultDestination(video
);
3689 ok(hr
== S_FALSE
, "Got hr %#lx.\n", hr
);
3691 hr
= IBasicVideo_put_DestinationWidth(video
, -700);
3692 ok(hr
== E_INVALIDARG
, "Got hr %#lx.\n", hr
);
3693 hr
= IBasicVideo_put_DestinationWidth(video
, 0);
3694 ok(hr
== E_INVALIDARG
, "Got hr %#lx.\n", hr
);
3695 hr
= IBasicVideo_put_DestinationWidth(video
, 700);
3696 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
3697 check_destination_position(video
, 10, 20, 700, 400);
3698 hr
= IBasicVideo_IsUsingDefaultDestination(video
);
3699 ok(hr
== S_FALSE
, "Got hr %#lx.\n", hr
);
3701 hr
= IBasicVideo_put_DestinationWidth(video
, 500);
3702 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
3703 check_destination_position(video
, 10, 20, 500, 400);
3704 hr
= IBasicVideo_IsUsingDefaultDestination(video
);
3705 ok(hr
== S_FALSE
, "Got hr %#lx.\n", hr
);
3707 hr
= IBasicVideo_put_DestinationHeight(video
, -500);
3708 ok(hr
== E_INVALIDARG
, "Got hr %#lx.\n", hr
);
3709 hr
= IBasicVideo_put_DestinationHeight(video
, 0);
3710 ok(hr
== E_INVALIDARG
, "Got hr %#lx.\n", hr
);
3711 hr
= IBasicVideo_put_DestinationHeight(video
, 500);
3712 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
3713 check_destination_position(video
, 10, 20, 500, 500);
3714 hr
= IBasicVideo_IsUsingDefaultDestination(video
);
3715 ok(hr
== S_FALSE
, "Got hr %#lx.\n", hr
);
3717 hr
= IBasicVideo_put_DestinationHeight(video
, 300);
3718 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
3719 check_destination_position(video
, 10, 20, 500, 300);
3720 hr
= IBasicVideo_IsUsingDefaultDestination(video
);
3721 ok(hr
== S_FALSE
, "Got hr %#lx.\n", hr
);
3723 hr
= IBasicVideo_SetDestinationPosition(video
, 4, 5, 60, 40);
3724 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
3725 check_destination_position(video
, 4, 5, 60, 40);
3726 hr
= IBasicVideo_IsUsingDefaultDestination(video
);
3727 ok(hr
== S_FALSE
, "Got hr %#lx.\n", hr
);
3729 hr
= IBasicVideo_SetDestinationPosition(video
, 0, 0, 600, 400);
3730 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
3731 check_destination_position(video
, 0, 0, 600, 400);
3732 hr
= IBasicVideo_IsUsingDefaultDestination(video
);
3733 ok(hr
== S_FALSE
, "Got hr %#lx.\n", hr
);
3735 hr
= IBasicVideo_SetDestinationPosition(video
, 4, 5, 60, 40);
3736 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
3737 hr
= IBasicVideo_SetDefaultDestinationPosition(video
);
3738 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
3739 check_destination_position(video
, 0, 0, 600, 400);
3740 hr
= IBasicVideo_IsUsingDefaultDestination(video
);
3741 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
3743 SetRect(&rect
, 100, 200, 500, 500);
3744 AdjustWindowRect(&rect
, WS_OVERLAPPEDWINDOW
, FALSE
);
3745 hr
= IVideoWindow_SetWindowPosition(window
, rect
.left
, rect
.top
,
3746 rect
.right
- rect
.left
, rect
.bottom
- rect
.top
);
3747 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
3748 check_destination_position(video
, 0, 0, 400, 300);
3749 hr
= IBasicVideo_IsUsingDefaultDestination(video
);
3750 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
3752 hr
= IBasicVideo_SetDestinationPosition(video
, 0, 0, 400, 300);
3753 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
3754 check_destination_position(video
, 0, 0, 400, 300);
3755 hr
= IBasicVideo_IsUsingDefaultDestination(video
);
3756 ok(hr
== S_FALSE
, "Got hr %#lx.\n", hr
);
3758 SetRect(&rect
, 100, 200, 600, 600);
3759 AdjustWindowRect(&rect
, WS_OVERLAPPEDWINDOW
, FALSE
);
3760 hr
= IVideoWindow_SetWindowPosition(window
, rect
.left
, rect
.top
,
3761 rect
.right
- rect
.left
, rect
.bottom
- rect
.top
);
3762 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
3763 check_destination_position(video
, 0, 0, 400, 300);
3764 hr
= IBasicVideo_IsUsingDefaultDestination(video
);
3765 ok(hr
== S_FALSE
, "Got hr %#lx.\n", hr
);
3767 IVideoWindow_Release(window
);
3770 static void test_basic_video(void)
3772 ALLOCATOR_PROPERTIES req_props
= {1, 600 * 400 * 4, 1, 0}, ret_props
;
3773 VIDEOINFOHEADER vih
=
3775 .AvgTimePerFrame
= 200000,
3776 .rcSource
= {4, 6, 16, 12},
3777 .rcTarget
= {40, 60, 120, 160},
3778 .bmiHeader
.biSize
= sizeof(BITMAPINFOHEADER
),
3779 .bmiHeader
.biBitCount
= 32,
3780 .bmiHeader
.biWidth
= 600,
3781 .bmiHeader
.biHeight
= 400,
3782 .bmiHeader
.biPlanes
= 1,
3783 .bmiHeader
.biCompression
= BI_RGB
,
3785 AM_MEDIA_TYPE req_mt
=
3787 .majortype
= MEDIATYPE_Video
,
3788 .subtype
= MEDIASUBTYPE_RGB32
,
3789 .formattype
= FORMAT_VideoInfo
,
3790 .cbFormat
= sizeof(vih
),
3791 .pbFormat
= (BYTE
*)&vih
,
3793 IBaseFilter
*filter
= create_vmr9(VMR9Mode_Windowed
);
3794 IFilterGraph2
*graph
= create_graph();
3795 LONG left
, top
, width
, height
, l
;
3796 struct testfilter source
;
3797 IMemAllocator
*allocator
;
3798 IMemInputPin
*input
;
3799 ITypeInfo
*typeinfo
;
3809 IBaseFilter_QueryInterface(filter
, &IID_IBasicVideo
, (void **)&video
);
3810 IBaseFilter_FindPin(filter
, L
"VMR Input0", &pin
);
3811 IPin_QueryInterface(pin
, &IID_IMemInputPin
, (void **)&input
);
3813 hr
= IBasicVideo_GetTypeInfoCount(video
, &count
);
3814 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
3815 ok(count
== 1, "Got count %u.\n", count
);
3817 hr
= IBasicVideo_GetTypeInfo(video
, 0, 0, &typeinfo
);
3818 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
3819 hr
= ITypeInfo_GetTypeAttr(typeinfo
, &typeattr
);
3820 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
3821 ok(typeattr
->typekind
== TKIND_DISPATCH
, "Got kind %u.\n", typeattr
->typekind
);
3822 ok(IsEqualGUID(&typeattr
->guid
, &IID_IBasicVideo
), "Got IID %s.\n", wine_dbgstr_guid(&typeattr
->guid
));
3823 ITypeInfo_ReleaseTypeAttr(typeinfo
, typeattr
);
3824 ITypeInfo_Release(typeinfo
);
3826 hr
= IBasicVideo_get_AvgTimePerFrame(video
, NULL
);
3827 ok(hr
== E_POINTER
, "Got hr %#lx.\n", hr
);
3828 hr
= IBasicVideo_get_AvgTimePerFrame(video
, &reftime
);
3829 ok(hr
== VFW_E_NOT_CONNECTED
, "Got hr %#lx.\n", hr
);
3831 hr
= IBasicVideo_get_BitRate(video
, NULL
);
3832 ok(hr
== E_POINTER
, "Got hr %#lx.\n", hr
);
3833 hr
= IBasicVideo_get_BitRate(video
, &l
);
3834 ok(hr
== VFW_E_NOT_CONNECTED
, "Got hr %#lx.\n", hr
);
3836 hr
= IBasicVideo_get_BitErrorRate(video
, NULL
);
3837 ok(hr
== E_POINTER
, "Got hr %#lx.\n", hr
);
3838 hr
= IBasicVideo_get_BitErrorRate(video
, &l
);
3839 ok(hr
== VFW_E_NOT_CONNECTED
, "Got hr %#lx.\n", hr
);
3841 hr
= IBasicVideo_get_VideoWidth(video
, NULL
);
3842 ok(hr
== E_POINTER
, "Got hr %#lx.\n", hr
);
3843 hr
= IBasicVideo_get_VideoHeight(video
, NULL
);
3844 ok(hr
== E_POINTER
, "Got hr %#lx.\n", hr
);
3846 hr
= IBasicVideo_get_SourceLeft(video
, NULL
);
3847 ok(hr
== E_POINTER
, "Got hr %#lx.\n", hr
);
3848 hr
= IBasicVideo_get_SourceWidth(video
, NULL
);
3849 ok(hr
== E_POINTER
, "Got hr %#lx.\n", hr
);
3850 hr
= IBasicVideo_get_SourceTop(video
, NULL
);
3851 ok(hr
== E_POINTER
, "Got hr %#lx.\n", hr
);
3852 hr
= IBasicVideo_get_SourceHeight(video
, NULL
);
3853 ok(hr
== E_POINTER
, "Got hr %#lx.\n", hr
);
3855 hr
= IBasicVideo_get_DestinationLeft(video
, NULL
);
3856 ok(hr
== E_POINTER
, "Got hr %#lx.\n", hr
);
3857 hr
= IBasicVideo_get_DestinationWidth(video
, NULL
);
3858 ok(hr
== E_POINTER
, "Got hr %#lx.\n", hr
);
3859 hr
= IBasicVideo_get_DestinationTop(video
, NULL
);
3860 ok(hr
== E_POINTER
, "Got hr %#lx.\n", hr
);
3861 hr
= IBasicVideo_get_DestinationHeight(video
, NULL
);
3862 ok(hr
== E_POINTER
, "Got hr %#lx.\n", hr
);
3864 hr
= IBasicVideo_GetSourcePosition(video
, NULL
, &top
, &width
, &height
);
3865 ok(hr
== E_POINTER
, "Got hr %#lx.\n", hr
);
3866 hr
= IBasicVideo_GetSourcePosition(video
, &left
, NULL
, &width
, &height
);
3867 ok(hr
== E_POINTER
, "Got hr %#lx.\n", hr
);
3868 hr
= IBasicVideo_GetSourcePosition(video
, &left
, &top
, NULL
, &height
);
3869 ok(hr
== E_POINTER
, "Got hr %#lx.\n", hr
);
3870 hr
= IBasicVideo_GetSourcePosition(video
, &left
, &top
, &width
, NULL
);
3871 ok(hr
== E_POINTER
, "Got hr %#lx.\n", hr
);
3873 hr
= IBasicVideo_GetDestinationPosition(video
, NULL
, &top
, &width
, &height
);
3874 ok(hr
== E_POINTER
, "Got hr %#lx.\n", hr
);
3875 hr
= IBasicVideo_GetDestinationPosition(video
, &left
, NULL
, &width
, &height
);
3876 ok(hr
== E_POINTER
, "Got hr %#lx.\n", hr
);
3877 hr
= IBasicVideo_GetDestinationPosition(video
, &left
, &top
, NULL
, &height
);
3878 ok(hr
== E_POINTER
, "Got hr %#lx.\n", hr
);
3879 hr
= IBasicVideo_GetDestinationPosition(video
, &left
, &top
, &width
, NULL
);
3880 ok(hr
== E_POINTER
, "Got hr %#lx.\n", hr
);
3882 hr
= IBasicVideo_GetVideoSize(video
, &width
, NULL
);
3883 ok(hr
== E_POINTER
, "Got hr %#lx.\n", hr
);
3884 hr
= IBasicVideo_GetVideoSize(video
, NULL
, &height
);
3885 ok(hr
== E_POINTER
, "Got hr %#lx.\n", hr
);
3886 hr
= IBasicVideo_GetVideoSize(video
, &width
, &height
);
3887 ok(hr
== VFW_E_NOT_CONNECTED
, "Got hr %#lx.\n", hr
);
3889 hr
= IBasicVideo_GetVideoPaletteEntries(video
, 0, 1, NULL
, &l
);
3890 ok(hr
== E_POINTER
, "Got hr %#lx.\n", hr
);
3891 hr
= IBasicVideo_GetVideoPaletteEntries(video
, 0, 1, &l
, NULL
);
3892 todo_wine
ok(hr
== VFW_E_NOT_CONNECTED
, "Got hr %#lx.\n", hr
);
3894 testfilter_init(&source
);
3895 IFilterGraph2_AddFilter(graph
, &source
.filter
.IBaseFilter_iface
, L
"vmr9");
3896 IFilterGraph2_AddFilter(graph
, filter
, L
"source");
3897 hr
= IFilterGraph2_ConnectDirect(graph
, &source
.source
.pin
.IPin_iface
, pin
, &req_mt
);
3900 skip("Got E_FAIL when connecting.\n");
3903 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
3905 hr
= IMemInputPin_GetAllocator(input
, &allocator
);
3906 todo_wine
ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
3909 hr
= IMemAllocator_SetProperties(allocator
, &req_props
, &ret_props
);
3910 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
3911 ok(!memcmp(&ret_props
, &req_props
, sizeof(req_props
)), "Properties did not match.\n");
3912 hr
= IMemAllocator_Commit(allocator
);
3913 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
3914 IMemAllocator_Release(allocator
);
3918 hr
= IBasicVideo_get_AvgTimePerFrame(video
, &reftime
);
3919 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
3920 ok(compare_double(reftime
, 0.02, 1 << 28), "Got frame rate %.16e.\n", reftime
);
3923 hr
= IBasicVideo_get_BitRate(video
, &l
);
3924 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
3925 ok(!l
, "Got bit rate %ld.\n", l
);
3928 hr
= IBasicVideo_get_BitErrorRate(video
, &l
);
3929 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
3930 ok(!l
, "Got bit rate %ld.\n", l
);
3932 hr
= IBasicVideo_GetVideoPaletteEntries(video
, 0, 1, &l
, NULL
);
3933 todo_wine
ok(hr
== VFW_E_NO_PALETTE_AVAILABLE
, "Got hr %#lx.\n", hr
);
3935 width
= height
= 0xdeadbeef;
3936 hr
= IBasicVideo_GetVideoSize(video
, &width
, &height
);
3937 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
3938 ok(width
== 600, "Got width %ld.\n", width
);
3939 ok(height
== 400, "Got height %ld.\n", height
);
3941 test_basic_video_source(video
);
3942 test_basic_video_destination(video
);
3944 hr
= IFilterGraph2_Disconnect(graph
, &source
.source
.pin
.IPin_iface
);
3945 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
3946 hr
= IFilterGraph2_Disconnect(graph
, pin
);
3947 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
3949 vih
.bmiHeader
.biWidth
= 16;
3950 vih
.bmiHeader
.biHeight
= 16;
3951 hr
= IFilterGraph2_ConnectDirect(graph
, &source
.source
.pin
.IPin_iface
, pin
, &req_mt
);
3952 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
3954 hr
= IMemInputPin_GetAllocator(input
, &allocator
);
3955 todo_wine
ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
3958 hr
= IMemAllocator_SetProperties(allocator
, &req_props
, &ret_props
);
3959 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
3960 ok(!memcmp(&ret_props
, &req_props
, sizeof(req_props
)), "Properties did not match.\n");
3961 hr
= IMemAllocator_Commit(allocator
);
3962 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
3963 IMemAllocator_Release(allocator
);
3966 check_source_position(video
, 0, 0, 16, 16);
3968 SetRect(&rect
, 0, 0, 0, 0);
3969 AdjustWindowRectEx(&rect
, WS_CLIPSIBLINGS
| WS_CLIPCHILDREN
| WS_OVERLAPPEDWINDOW
, FALSE
, 0);
3970 check_destination_position(video
, 0, 0, max(16, GetSystemMetrics(SM_CXMIN
) - (rect
.right
- rect
.left
)),
3971 max(16, GetSystemMetrics(SM_CYMIN
) - (rect
.bottom
- rect
.top
)));
3974 ref
= IFilterGraph2_Release(graph
);
3975 ok(!ref
, "Got outstanding refcount %ld.\n", ref
);
3976 IBasicVideo_Release(video
);
3977 IMemInputPin_Release(input
);
3979 ref
= IBaseFilter_Release(filter
);
3980 ok(!ref
, "Got outstanding refcount %ld.\n", ref
);
3981 ref
= IBaseFilter_Release(&source
.filter
.IBaseFilter_iface
);
3982 ok(!ref
, "Got outstanding refcount %ld.\n", ref
);
3985 static void test_windowless_size(void)
3987 ALLOCATOR_PROPERTIES req_props
= {1, 32 * 16 * 4, 1, 0}, ret_props
;
3988 VIDEOINFOHEADER vih
=
3990 .bmiHeader
.biSize
= sizeof(BITMAPINFOHEADER
),
3991 .bmiHeader
.biWidth
= 32,
3992 .bmiHeader
.biHeight
= 16,
3993 .bmiHeader
.biBitCount
= 32,
3994 .bmiHeader
.biPlanes
= 1,
3998 .majortype
= MEDIATYPE_Video
,
3999 .subtype
= MEDIASUBTYPE_RGB32
,
4000 .formattype
= FORMAT_VideoInfo
,
4001 .cbFormat
= sizeof(vih
),
4002 .pbFormat
= (BYTE
*)&vih
,
4004 IBaseFilter
*filter
= create_vmr9(VMR9Mode_Windowless
);
4005 LONG width
, height
, aspect_width
, aspect_height
;
4006 IVMRAspectRatioControl9
*aspect_ratio_control
;
4007 IVMRWindowlessControl9
*windowless_control
;
4008 IFilterGraph2
*graph
= create_graph();
4009 struct testfilter source
;
4010 IMemAllocator
*allocator
;
4011 RECT src
, dst
, expect
;
4012 IMemInputPin
*input
;
4019 IBaseFilter_QueryInterface(filter
, &IID_IVMRWindowlessControl9
, (void **)&windowless_control
);
4020 IBaseFilter_QueryInterface(filter
, &IID_IVMRAspectRatioControl9
, (void **)&aspect_ratio_control
);
4021 IBaseFilter_FindPin(filter
, L
"VMR Input0", &pin
);
4022 IPin_QueryInterface(pin
, &IID_IMemInputPin
, (void **)&input
);
4023 testfilter_init(&source
);
4024 IFilterGraph2_AddFilter(graph
, &source
.filter
.IBaseFilter_iface
, L
"source");
4025 IFilterGraph2_AddFilter(graph
, filter
, L
"vmr9");
4026 window
= CreateWindowA("static", "quartz_test", WS_OVERLAPPEDWINDOW
, 0, 0, 640, 480, 0, 0, 0, 0);
4027 ok(!!window
, "Failed to create a window.\n");
4029 hr
= IVMRWindowlessControl9_SetVideoClippingWindow(windowless_control
, window
);
4030 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
4032 hr
= IFilterGraph2_ConnectDirect(graph
, &source
.source
.pin
.IPin_iface
, pin
, &mt
);
4033 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
4034 hr
= IMemInputPin_GetAllocator(input
, &allocator
);
4035 todo_wine
ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
4038 hr
= IMemAllocator_SetProperties(allocator
, &req_props
, &ret_props
);
4039 IMemAllocator_Release(allocator
);
4042 skip("Got E_FAIL when setting allocator properties.\n");
4045 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
4046 ok(!memcmp(&ret_props
, &req_props
, sizeof(req_props
)), "Properties did not match.\n");
4049 hr
= IVMRWindowlessControl9_GetNativeVideoSize(windowless_control
, NULL
, &height
, &aspect_width
, &aspect_height
);
4050 ok(hr
== E_POINTER
, "Got hr %#lx.\n", hr
);
4051 hr
= IVMRWindowlessControl9_GetNativeVideoSize(windowless_control
, &width
, NULL
, &aspect_width
, &aspect_height
);
4052 ok(hr
== E_POINTER
, "Got hr %#lx.\n", hr
);
4054 aspect_mode
= 0xdeadbeef;
4055 hr
= IVMRWindowlessControl9_GetAspectRatioMode(windowless_control
, &aspect_mode
);
4056 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
4057 ok(aspect_mode
== VMR9ARMode_None
, "Got mode %lu.\n", aspect_mode
);
4059 aspect_mode
= 0xdeadbeef;
4060 hr
= IVMRAspectRatioControl9_GetAspectRatioMode(aspect_ratio_control
, &aspect_mode
);
4061 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
4062 ok(aspect_mode
== VMR9ARMode_None
, "Got mode %lu.\n", aspect_mode
);
4064 width
= height
= 0xdeadbeef;
4065 hr
= IVMRWindowlessControl9_GetNativeVideoSize(windowless_control
, &width
, &height
, NULL
, NULL
);
4066 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
4067 ok(width
== 32, "Got width %ld.\n", width
);
4068 ok(height
== 16, "Got height %ld.\n", height
);
4070 aspect_width
= aspect_height
= 0xdeadbeef;
4071 hr
= IVMRWindowlessControl9_GetNativeVideoSize(windowless_control
, &width
, &height
, &aspect_width
, &aspect_height
);
4072 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
4073 ok(aspect_width
== 32, "Got width %ld.\n", aspect_width
);
4074 ok(aspect_height
== 16, "Got height %ld.\n", aspect_height
);
4076 memset(&src
, 0xcc, sizeof(src
));
4077 hr
= IVMRWindowlessControl9_GetVideoPosition(windowless_control
, &src
, NULL
);
4078 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
4079 SetRect(&expect
, 0, 0, 32, 16);
4080 ok(EqualRect(&src
, &expect
), "Got source rect %s.\n", wine_dbgstr_rect(&src
));
4082 memset(&dst
, 0xcc, sizeof(dst
));
4083 hr
= IVMRWindowlessControl9_GetVideoPosition(windowless_control
, NULL
, &dst
);
4084 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
4085 SetRect(&expect
, 0, 0, 0, 0);
4086 ok(EqualRect(&dst
, &expect
), "Got dest rect %s.\n", wine_dbgstr_rect(&dst
));
4088 SetRect(&src
, 4, 6, 16, 12);
4089 hr
= IVMRWindowlessControl9_SetVideoPosition(windowless_control
, &src
, NULL
);
4090 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
4092 memset(&src
, 0xcc, sizeof(src
));
4093 memset(&dst
, 0xcc, sizeof(dst
));
4094 hr
= IVMRWindowlessControl9_GetVideoPosition(windowless_control
, &src
, &dst
);
4095 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
4096 SetRect(&expect
, 4, 6, 16, 12);
4097 ok(EqualRect(&src
, &expect
), "Got source rect %s.\n", wine_dbgstr_rect(&src
));
4098 SetRect(&expect
, 0, 0, 0, 0);
4099 ok(EqualRect(&dst
, &expect
), "Got dest rect %s.\n", wine_dbgstr_rect(&dst
));
4101 SetRect(&dst
, 40, 60, 120, 160);
4102 hr
= IVMRWindowlessControl9_SetVideoPosition(windowless_control
, NULL
, &dst
);
4103 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
4105 memset(&src
, 0xcc, sizeof(src
));
4106 memset(&dst
, 0xcc, sizeof(dst
));
4107 hr
= IVMRWindowlessControl9_GetVideoPosition(windowless_control
, &src
, &dst
);
4108 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
4109 SetRect(&expect
, 4, 6, 16, 12);
4110 ok(EqualRect(&src
, &expect
), "Got source rect %s.\n", wine_dbgstr_rect(&src
));
4111 SetRect(&expect
, 40, 60, 120, 160);
4112 ok(EqualRect(&dst
, &expect
), "Got dest rect %s.\n", wine_dbgstr_rect(&dst
));
4114 GetWindowRect(window
, &src
);
4115 SetRect(&expect
, 0, 0, 640, 480);
4116 ok(EqualRect(&src
, &expect
), "Got window rect %s.\n", wine_dbgstr_rect(&src
));
4118 hr
= IVMRAspectRatioControl9_SetAspectRatioMode(aspect_ratio_control
, VMR9ARMode_LetterBox
);
4119 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
4121 aspect_mode
= 0xdeadbeef;
4122 hr
= IVMRWindowlessControl9_GetAspectRatioMode(windowless_control
, &aspect_mode
);
4123 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
4124 ok(aspect_mode
== VMR9ARMode_LetterBox
, "Got mode %lu.\n", aspect_mode
);
4126 hr
= IVMRWindowlessControl9_SetAspectRatioMode(windowless_control
, VMR9ARMode_None
);
4127 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
4129 aspect_mode
= 0xdeadbeef;
4130 hr
= IVMRAspectRatioControl9_GetAspectRatioMode(aspect_ratio_control
, &aspect_mode
);
4131 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
4132 ok(aspect_mode
== VMR9ARMode_None
, "Got mode %lu.\n", aspect_mode
);
4134 hr
= IVMRWindowlessControl9_SetAspectRatioMode(windowless_control
, VMR9ARMode_LetterBox
);
4135 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
4137 memset(&src
, 0xcc, sizeof(src
));
4138 memset(&dst
, 0xcc, sizeof(dst
));
4139 hr
= IVMRWindowlessControl9_GetVideoPosition(windowless_control
, &src
, &dst
);
4140 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
4141 SetRect(&expect
, 4, 6, 16, 12);
4142 ok(EqualRect(&src
, &expect
), "Got source rect %s.\n", wine_dbgstr_rect(&src
));
4143 SetRect(&expect
, 40, 60, 120, 160);
4144 ok(EqualRect(&dst
, &expect
), "Got dest rect %s.\n", wine_dbgstr_rect(&dst
));
4146 SetRect(&src
, 0, 0, 32, 16);
4147 SetRect(&dst
, 0, 0, 640, 480);
4148 hr
= IVMRWindowlessControl9_SetVideoPosition(windowless_control
, &src
, &dst
);
4149 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
4151 memset(&src
, 0xcc, sizeof(src
));
4152 memset(&dst
, 0xcc, sizeof(dst
));
4153 hr
= IVMRWindowlessControl9_GetVideoPosition(windowless_control
, &src
, &dst
);
4154 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
4155 SetRect(&expect
, 0, 0, 32, 16);
4156 ok(EqualRect(&src
, &expect
), "Got source rect %s.\n", wine_dbgstr_rect(&src
));
4157 SetRect(&expect
, 0, 0, 640, 480);
4158 ok(EqualRect(&dst
, &expect
), "Got dest rect %s.\n", wine_dbgstr_rect(&dst
));
4161 ref
= IFilterGraph2_Release(graph
);
4162 ok(!ref
, "Got outstanding refcount %ld.\n", ref
);
4163 IMemInputPin_Release(input
);
4165 IVMRWindowlessControl9_Release(windowless_control
);
4166 IVMRAspectRatioControl9_Release(aspect_ratio_control
);
4167 ref
= IBaseFilter_Release(filter
);
4168 ok(!ref
, "Got outstanding refcount %ld.\n", ref
);
4169 DestroyWindow(window
);
4172 static void test_mixing_prefs(void)
4174 IBaseFilter
*filter
= create_vmr9(VMR9Mode_Windowed
);
4175 IVMRMixerControl9
*mixer_control
;
4180 set_mixing_mode(filter
, 1);
4182 hr
= IBaseFilter_QueryInterface(filter
, &IID_IVMRMixerControl9
, (void **)&mixer_control
);
4183 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
4185 hr
= IVMRMixerControl9_GetMixingPrefs(mixer_control
, &flags
);
4186 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
4187 ok(flags
== (MixerPref9_NoDecimation
| MixerPref9_ARAdjustXorY
| MixerPref9_BiLinearFiltering
4188 | MixerPref9_RenderTargetRGB
), "Got flags %#lx.\n", flags
);
4190 hr
= IVMRMixerControl9_SetMixingPrefs(mixer_control
, MixerPref9_NoDecimation
4191 | MixerPref9_ARAdjustXorY
| MixerPref9_PointFiltering
| MixerPref9_RenderTargetRGB
);
4192 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
4194 hr
= IVMRMixerControl9_GetMixingPrefs(mixer_control
, &flags
);
4195 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
4196 ok(flags
== (MixerPref9_NoDecimation
| MixerPref9_ARAdjustXorY
| MixerPref9_PointFiltering
4197 | MixerPref9_RenderTargetRGB
), "Got flags %#lx.\n", flags
);
4199 IVMRMixerControl9_Release(mixer_control
);
4200 ref
= IBaseFilter_Release(filter
);
4201 ok(!ref
, "Got outstanding refcount %ld.\n", ref
);
4204 static void test_unconnected_eos(void)
4206 IFilterGraph2
*graph
= create_graph();
4207 IBaseFilter
*filter
= create_vmr9(0);
4208 IMediaControl
*control
;
4209 IMediaEvent
*eventsrc
;
4214 hr
= IFilterGraph2_AddFilter(graph
, filter
, L
"renderer");
4215 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
4217 hr
= IFilterGraph2_QueryInterface(graph
, &IID_IMediaControl
, (void **)&control
);
4218 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
4220 hr
= IFilterGraph2_QueryInterface(graph
, &IID_IMediaEvent
, (void **)&eventsrc
);
4221 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
4223 ret
= check_ec_complete(eventsrc
, 0);
4224 ok(!ret
, "Got %u EC_COMPLETE events.\n", ret
);
4226 hr
= IMediaControl_Pause(control
);
4227 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
4229 ret
= check_ec_complete(eventsrc
, 0);
4230 ok(!ret
, "Got %u EC_COMPLETE events.\n", ret
);
4232 hr
= IMediaControl_Run(control
);
4233 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
4235 ret
= check_ec_complete(eventsrc
, 0);
4236 ok(ret
== 1, "Got %u EC_COMPLETE events.\n", ret
);
4238 hr
= IMediaControl_Pause(control
);
4239 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
4241 ret
= check_ec_complete(eventsrc
, 0);
4242 ok(!ret
, "Got %u EC_COMPLETE events.\n", ret
);
4244 hr
= IMediaControl_Run(control
);
4245 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
4247 ret
= check_ec_complete(eventsrc
, 0);
4248 ok(ret
== 1, "Got %u EC_COMPLETE events.\n", ret
);
4250 hr
= IMediaControl_Stop(control
);
4251 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
4253 ret
= check_ec_complete(eventsrc
, 0);
4254 ok(!ret
, "Got %u EC_COMPLETE events.\n", ret
);
4256 hr
= IMediaControl_Run(control
);
4257 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
4259 ret
= check_ec_complete(eventsrc
, 0);
4260 ok(ret
== 1, "Got %u EC_COMPLETE events.\n", ret
);
4262 IMediaControl_Release(control
);
4263 IMediaEvent_Release(eventsrc
);
4264 ref
= IFilterGraph2_Release(graph
);
4265 ok(!ref
, "Got outstanding refcount %ld.\n", ref
);
4266 ref
= IBaseFilter_Release(filter
);
4267 ok(!ref
, "Got outstanding refcount %ld.\n", ref
);
4272 IBaseFilter
*filter
;
4277 if (FAILED(hr
= CoCreateInstance(&CLSID_VideoMixingRenderer9
, NULL
,
4278 CLSCTX_INPROC_SERVER
, &IID_IBaseFilter
, (void **)&filter
)))
4280 skip("Failed to create VMR9, hr %#lx.\n", hr
);
4283 IBaseFilter_Release(filter
);
4285 test_filter_config();
4292 test_enum_media_types();
4293 test_unconnected_filter_state();
4296 test_video_window();
4297 test_allocate_surface_helper();
4298 test_renderless_formats();
4300 test_clipping_window();
4301 test_surface_allocator_notify_refcount();
4303 test_windowless_size();
4304 test_mixing_prefs();
4305 test_unconnected_eos();