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
30 #include "wmcodecdsp.h"
31 #include "wine/heap.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 %#x.\n", hr
);
44 hr
= IBaseFilter_QueryInterface(filter
, &IID_IVMRFilterConfig9
, (void **)&config
);
45 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
46 hr
= IVMRFilterConfig9_SetRenderingMode(config
, mode
);
47 ok(hr
== S_OK
|| broken(hr
== E_FAIL
), "Got hr %#x.\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 %#x.\n", hr
);
61 hr
= IVMRFilterConfig9_SetNumberOfStreams(config
, count
);
62 todo_wine_if (count
!= 1) ok(hr
== S_OK
, "Got hr %#x.\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 int64_t x
= *(int64_t *)&f
;
77 int64_t y
= *(int64_t *)&g
;
84 if (abs(x
- y
) > ulps
)
90 static IFilterGraph2
*create_graph(void)
94 hr
= CoCreateInstance(&CLSID_FilterGraph
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IFilterGraph2
, (void **)&ret
);
95 ok(hr
== S_OK
, "Failed to create FilterGraph: %#x\n", hr
);
99 static ULONG
get_refcount(void *iface
)
101 IUnknown
*unknown
= iface
;
102 IUnknown_AddRef(unknown
);
103 return IUnknown_Release(unknown
);
106 static void test_filter_config(void)
108 IVMRFilterConfig9
*config
;
113 hr
= CoCreateInstance(&CLSID_VideoMixingRenderer9
, NULL
, CLSCTX_INPROC_SERVER
,
114 &IID_IVMRFilterConfig9
, (void **)&config
);
115 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
117 hr
= IVMRFilterConfig9_GetRenderingMode(config
, &mode
);
118 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
119 ok(mode
== VMRMode_Windowed
, "Got mode %#x.\n", mode
);
121 hr
= IVMRFilterConfig9_SetRenderingMode(config
, VMR9Mode_Windowed
);
122 ok(hr
== S_OK
|| broken(hr
== E_FAIL
), "Got hr %#x.\n", hr
);
124 hr
= IVMRFilterConfig9_GetRenderingMode(config
, &mode
);
125 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
126 ok(mode
== VMR9Mode_Windowed
, "Got mode %#x.\n", mode
);
128 hr
= IVMRFilterConfig9_SetRenderingMode(config
, VMR9Mode_Windowed
);
129 ok(hr
== VFW_E_WRONG_STATE
, "Got hr %#x.\n", hr
);
131 ref
= IVMRFilterConfig9_Release(config
);
132 ok(!ref
, "Got outstanding refcount %d.\n", ref
);
134 hr
= CoCreateInstance(&CLSID_VideoMixingRenderer9
, NULL
, CLSCTX_INPROC_SERVER
,
135 &IID_IVMRFilterConfig9
, (void **)&config
);
136 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
138 hr
= IVMRFilterConfig9_SetRenderingMode(config
, VMR9Mode_Windowless
);
139 ok(hr
== S_OK
|| broken(hr
== E_FAIL
), "Got hr %#x.\n", hr
);
141 hr
= IVMRFilterConfig9_GetRenderingMode(config
, &mode
);
142 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
143 ok(mode
== VMR9Mode_Windowless
, "Got mode %#x.\n", mode
);
145 hr
= IVMRFilterConfig9_SetRenderingMode(config
, VMR9Mode_Windowed
);
146 ok(hr
== VFW_E_WRONG_STATE
, "Got hr %#x.\n", hr
);
148 ref
= IVMRFilterConfig9_Release(config
);
149 ok(!ref
, "Got outstanding refcount %d.\n", ref
);
151 hr
= CoCreateInstance(&CLSID_VideoMixingRenderer9
, NULL
, CLSCTX_INPROC_SERVER
,
152 &IID_IVMRFilterConfig9
, (void **)&config
);
153 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
155 hr
= IVMRFilterConfig9_SetRenderingMode(config
, VMR9Mode_Renderless
);
156 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
158 hr
= IVMRFilterConfig9_GetRenderingMode(config
, &mode
);
159 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
160 ok(mode
== VMR9Mode_Renderless
, "Got mode %#x.\n", mode
);
162 hr
= IVMRFilterConfig9_SetRenderingMode(config
, VMR9Mode_Windowless
);
163 ok(hr
== VFW_E_WRONG_STATE
, "Got hr %#x.\n", hr
);
165 ref
= IVMRFilterConfig9_Release(config
);
166 ok(!ref
, "Got outstanding refcount %d.\n", ref
);
168 hr
= CoCreateInstance(&CLSID_VideoMixingRenderer9
, NULL
, CLSCTX_INPROC_SERVER
,
169 &IID_IVMRFilterConfig9
, (void **)&config
);
170 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
172 hr
= IVMRFilterConfig9_GetNumberOfStreams(config
, &count
);
173 todo_wine
ok(hr
== VFW_E_VMR_NOT_IN_MIXER_MODE
, "Got hr %#x.\n", hr
);
175 hr
= IVMRFilterConfig9_SetNumberOfStreams(config
, 3);
176 todo_wine
ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
178 hr
= IVMRFilterConfig9_GetNumberOfStreams(config
, &count
);
180 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
181 ok(count
== 3, "Got count %u.\n", count
);
184 hr
= IVMRFilterConfig9_GetRenderingMode(config
, &mode
);
185 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
186 ok(mode
== VMR9Mode_Windowed
, "Got mode %#x.\n", mode
);
188 /* Despite MSDN, you can still change the rendering mode after setting the
190 hr
= IVMRFilterConfig9_SetRenderingMode(config
, VMR9Mode_Windowless
);
191 ok(hr
== S_OK
|| broken(hr
== E_FAIL
), "Got hr %#x.\n", hr
);
193 hr
= IVMRFilterConfig9_GetRenderingMode(config
, &mode
);
194 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
195 ok(mode
== VMR9Mode_Windowless
, "Got mode %#x.\n", mode
);
197 hr
= IVMRFilterConfig9_GetNumberOfStreams(config
, &count
);
199 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
200 ok(count
== 3, "Got count %u.\n", count
);
203 ref
= IVMRFilterConfig9_Release(config
);
204 ok(!ref
, "Got outstanding refcount %d.\n", ref
);
207 #define check_interface_broken(a, b, c) check_interface_(__LINE__, a, b, c, TRUE)
208 #define check_interface(a, b, c) check_interface_(__LINE__, a, b, c, FALSE)
209 static HRESULT
check_interface_(unsigned int line
, void *iface
, REFIID riid
, BOOL supported
, BOOL is_broken
)
211 HRESULT hr
, expected_hr
, broken_hr
;
212 IUnknown
*unknown
= iface
, *out
;
217 broken_hr
= E_NOINTERFACE
;
221 expected_hr
= E_NOINTERFACE
;
225 hr
= IUnknown_QueryInterface(unknown
, riid
, (void **)&out
);
226 ok_(__FILE__
, line
)(hr
== expected_hr
|| broken(is_broken
&& hr
== broken_hr
),
227 "Got hr %#x, expected %#x.\n", hr
, expected_hr
);
229 IUnknown_Release(out
);
233 static void test_common_interfaces(IBaseFilter
*filter
)
237 check_interface(filter
, &IID_IAMCertifiedOutputProtection
, TRUE
);
238 check_interface(filter
, &IID_IAMFilterMiscFlags
, TRUE
);
239 check_interface(filter
, &IID_IBaseFilter
, TRUE
);
240 todo_wine
check_interface(filter
, &IID_IKsPropertySet
, TRUE
);
241 check_interface(filter
, &IID_IMediaFilter
, TRUE
);
242 check_interface(filter
, &IID_IMediaPosition
, TRUE
);
243 check_interface(filter
, &IID_IMediaSeeking
, TRUE
);
244 check_interface(filter
, &IID_IPersist
, TRUE
);
245 check_interface(filter
, &IID_IQualityControl
, TRUE
);
246 todo_wine
check_interface(filter
, &IID_IQualProp
, TRUE
);
247 check_interface(filter
, &IID_IUnknown
, TRUE
);
248 todo_wine
check_interface(filter
, &IID_IVMRAspectRatioControl9
, TRUE
);
249 todo_wine
check_interface(filter
, &IID_IVMRDeinterlaceControl9
, TRUE
);
250 check_interface(filter
, &IID_IVMRFilterConfig9
, TRUE
);
251 check_interface(filter
, &IID_IVMRMixerBitmap9
, TRUE
);
253 check_interface(filter
, &IID_IBasicAudio
, FALSE
);
254 check_interface(filter
, &IID_IDirectDrawVideo
, FALSE
);
255 check_interface(filter
, &IID_IPersistPropertyBag
, FALSE
);
256 check_interface(filter
, &IID_IPin
, FALSE
);
257 check_interface(filter
, &IID_IReferenceClock
, FALSE
);
258 check_interface(filter
, &IID_IVMRAspectRatioControl
, FALSE
);
259 check_interface(filter
, &IID_IVMRDeinterlaceControl
, FALSE
);
260 todo_wine
check_interface(filter
, &IID_IVMRFilterConfig
, FALSE
);
261 check_interface(filter
, &IID_IVMRMixerBitmap
, FALSE
);
262 check_interface(filter
, &IID_IVMRMixerControl
, FALSE
);
263 todo_wine
check_interface(filter
, &IID_IVMRMonitorConfig
, FALSE
);
264 check_interface(filter
, &IID_IVMRSurfaceAllocatorNotify
, FALSE
);
265 check_interface(filter
, &IID_IVMRWindowlessControl
, FALSE
);
267 IBaseFilter_FindPin(filter
, L
"VMR Input0", &pin
);
269 check_interface(pin
, &IID_IMemInputPin
, TRUE
);
270 check_interface(pin
, &IID_IOverlay
, TRUE
);
271 check_interface(pin
, &IID_IPin
, TRUE
);
272 todo_wine
check_interface(pin
, &IID_IQualityControl
, TRUE
);
273 check_interface(pin
, &IID_IUnknown
, TRUE
);
275 check_interface(pin
, &IID_IKsPropertySet
, FALSE
);
276 check_interface(pin
, &IID_IMediaPosition
, FALSE
);
277 check_interface(pin
, &IID_IMediaSeeking
, FALSE
);
282 static void test_interfaces(void)
284 IBaseFilter
*filter
= create_vmr9(0);
287 test_common_interfaces(filter
);
289 check_interface(filter
, &IID_IBasicVideo
, TRUE
);
290 todo_wine
check_interface(filter
, &IID_IBasicVideo2
, TRUE
);
291 check_interface(filter
, &IID_IVideoWindow
, TRUE
);
292 /* IVMRMonitorConfig9 may not be available if the d3d9 device has
293 * insufficient support. */
294 check_interface_broken(filter
, &IID_IVMRMonitorConfig9
, TRUE
);
296 check_interface(filter
, &IID_IVMRMixerControl9
, FALSE
);
297 check_interface(filter
, &IID_IVMRSurfaceAllocatorNotify9
, FALSE
);
298 check_interface(filter
, &IID_IVMRWindowlessControl9
, FALSE
);
300 ref
= IBaseFilter_Release(filter
);
301 ok(!ref
, "Got outstanding refcount %d.\n", ref
);
303 filter
= create_vmr9(VMR9Mode_Windowless
);
304 test_common_interfaces(filter
);
306 /* IVMRMonitorConfig9 may not be available if the d3d9 device has
307 * insufficient support. */
308 check_interface_broken(filter
, &IID_IVMRMonitorConfig9
, TRUE
);
309 check_interface(filter
, &IID_IVMRWindowlessControl9
, TRUE
);
311 todo_wine
check_interface(filter
, &IID_IBasicVideo
, FALSE
);
312 check_interface(filter
, &IID_IBasicVideo2
, FALSE
);
313 todo_wine
check_interface(filter
, &IID_IVideoWindow
, FALSE
);
314 check_interface(filter
, &IID_IVMRMixerControl9
, FALSE
);
315 check_interface(filter
, &IID_IVMRSurfaceAllocatorNotify9
, FALSE
);
317 ref
= IBaseFilter_Release(filter
);
318 ok(!ref
, "Got outstanding refcount %d.\n", ref
);
320 filter
= create_vmr9(VMR9Mode_Renderless
);
321 test_common_interfaces(filter
);
323 check_interface(filter
, &IID_IVMRSurfaceAllocatorNotify9
, TRUE
);
325 todo_wine
check_interface(filter
, &IID_IBasicVideo
, FALSE
);
326 check_interface(filter
, &IID_IBasicVideo2
, FALSE
);
327 todo_wine
check_interface(filter
, &IID_IVideoWindow
, FALSE
);
328 todo_wine
check_interface(filter
, &IID_IVMRMonitorConfig9
, FALSE
);
329 check_interface(filter
, &IID_IVMRWindowlessControl9
, FALSE
);
331 ref
= IBaseFilter_Release(filter
);
332 ok(!ref
, "Got outstanding refcount %d.\n", ref
);
334 filter
= create_vmr9(VMR9Mode_Windowed
);
335 if (SUCCEEDED(set_mixing_mode(filter
, 1)))
337 test_common_interfaces(filter
);
339 check_interface(filter
, &IID_IBasicVideo
, TRUE
);
340 todo_wine
check_interface(filter
, &IID_IBasicVideo2
, TRUE
);
341 check_interface(filter
, &IID_IVideoWindow
, TRUE
);
342 todo_wine
check_interface(filter
, &IID_IVMRMixerControl9
, TRUE
);
343 /* IVMRMonitorConfig9 may not be available if the d3d9 device has
344 * insufficient support. */
345 check_interface_broken(filter
, &IID_IVMRMonitorConfig9
, TRUE
);
347 check_interface(filter
, &IID_IVMRSurfaceAllocatorNotify9
, FALSE
);
348 check_interface(filter
, &IID_IVMRWindowlessControl9
, FALSE
);
350 ref
= IBaseFilter_Release(filter
);
351 ok(!ref
, "Got outstanding refcount %d.\n", ref
);
355 static const GUID test_iid
= {0x33333333};
356 static LONG outer_ref
= 1;
358 static HRESULT WINAPI
outer_QueryInterface(IUnknown
*iface
, REFIID iid
, void **out
)
360 if (IsEqualGUID(iid
, &IID_IUnknown
)
361 || IsEqualGUID(iid
, &IID_IBaseFilter
)
362 || IsEqualGUID(iid
, &test_iid
))
364 *out
= (IUnknown
*)0xdeadbeef;
367 ok(0, "unexpected call %s\n", wine_dbgstr_guid(iid
));
368 return E_NOINTERFACE
;
371 static ULONG WINAPI
outer_AddRef(IUnknown
*iface
)
373 return InterlockedIncrement(&outer_ref
);
376 static ULONG WINAPI
outer_Release(IUnknown
*iface
)
378 return InterlockedDecrement(&outer_ref
);
381 static const IUnknownVtbl outer_vtbl
=
383 outer_QueryInterface
,
388 static IUnknown test_outer
= {&outer_vtbl
};
390 static void test_aggregation(void)
392 IBaseFilter
*filter
, *filter2
;
393 IUnknown
*unk
, *unk2
;
397 filter
= (IBaseFilter
*)0xdeadbeef;
398 hr
= CoCreateInstance(&CLSID_VideoMixingRenderer9
, &test_outer
, CLSCTX_INPROC_SERVER
,
399 &IID_IBaseFilter
, (void **)&filter
);
400 ok(hr
== E_NOINTERFACE
, "Got hr %#x.\n", hr
);
401 ok(!filter
, "Got interface %p.\n", filter
);
403 hr
= CoCreateInstance(&CLSID_VideoMixingRenderer9
, &test_outer
, CLSCTX_INPROC_SERVER
,
404 &IID_IUnknown
, (void **)&unk
);
405 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
406 ok(outer_ref
== 1, "Got unexpected refcount %d.\n", outer_ref
);
407 ok(unk
!= &test_outer
, "Returned IUnknown should not be outer IUnknown.\n");
408 ref
= get_refcount(unk
);
409 ok(ref
== 1, "Got unexpected refcount %d.\n", ref
);
411 ref
= IUnknown_AddRef(unk
);
412 ok(ref
== 2, "Got unexpected refcount %d.\n", ref
);
413 ok(outer_ref
== 1, "Got unexpected refcount %d.\n", outer_ref
);
415 ref
= IUnknown_Release(unk
);
416 ok(ref
== 1, "Got unexpected refcount %d.\n", ref
);
417 ok(outer_ref
== 1, "Got unexpected refcount %d.\n", outer_ref
);
419 hr
= IUnknown_QueryInterface(unk
, &IID_IUnknown
, (void **)&unk2
);
420 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
421 ok(unk2
== unk
, "Got unexpected IUnknown %p.\n", unk2
);
422 IUnknown_Release(unk2
);
424 hr
= IUnknown_QueryInterface(unk
, &IID_IBaseFilter
, (void **)&filter
);
425 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
427 hr
= IBaseFilter_QueryInterface(filter
, &IID_IUnknown
, (void **)&unk2
);
428 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
429 ok(unk2
== (IUnknown
*)0xdeadbeef, "Got unexpected IUnknown %p.\n", unk2
);
431 hr
= IBaseFilter_QueryInterface(filter
, &IID_IBaseFilter
, (void **)&filter2
);
432 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
433 ok(filter2
== (IBaseFilter
*)0xdeadbeef, "Got unexpected IBaseFilter %p.\n", filter2
);
435 hr
= IUnknown_QueryInterface(unk
, &test_iid
, (void **)&unk2
);
436 ok(hr
== E_NOINTERFACE
, "Got hr %#x.\n", hr
);
437 ok(!unk2
, "Got unexpected IUnknown %p.\n", unk2
);
439 hr
= IBaseFilter_QueryInterface(filter
, &test_iid
, (void **)&unk2
);
440 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
441 ok(unk2
== (IUnknown
*)0xdeadbeef, "Got unexpected IUnknown %p.\n", unk2
);
443 IBaseFilter_Release(filter
);
444 ref
= IUnknown_Release(unk
);
445 ok(!ref
, "Got unexpected refcount %d.\n", ref
);
446 ok(outer_ref
== 1, "Got unexpected refcount %d.\n", outer_ref
);
449 static void test_enum_pins(void)
451 IBaseFilter
*filter
= create_vmr9(0);
452 IEnumPins
*enum1
, *enum2
;
457 ref
= get_refcount(filter
);
458 ok(ref
== 1, "Got unexpected refcount %d.\n", ref
);
460 hr
= IBaseFilter_EnumPins(filter
, NULL
);
461 ok(hr
== E_POINTER
, "Got hr %#x.\n", hr
);
463 hr
= IBaseFilter_EnumPins(filter
, &enum1
);
464 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
465 ref
= get_refcount(filter
);
466 ok(ref
== 2, "Got unexpected refcount %d.\n", ref
);
467 ref
= get_refcount(enum1
);
468 ok(ref
== 1, "Got unexpected refcount %d.\n", ref
);
470 hr
= IEnumPins_Next(enum1
, 1, NULL
, NULL
);
471 ok(hr
== E_POINTER
, "Got hr %#x.\n", hr
);
473 hr
= IEnumPins_Next(enum1
, 1, pins
, NULL
);
474 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
475 ref
= get_refcount(filter
);
476 ok(ref
== 3, "Got unexpected refcount %d.\n", ref
);
477 ref
= get_refcount(pins
[0]);
478 ok(ref
== 3, "Got unexpected refcount %d.\n", ref
);
479 ref
= get_refcount(enum1
);
480 ok(ref
== 1, "Got unexpected refcount %d.\n", ref
);
481 IPin_Release(pins
[0]);
482 ref
= get_refcount(filter
);
483 ok(ref
== 2, "Got unexpected refcount %d.\n", ref
);
485 hr
= IEnumPins_Next(enum1
, 1, pins
, NULL
);
486 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
488 hr
= IEnumPins_Reset(enum1
);
489 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
491 hr
= IEnumPins_Next(enum1
, 1, pins
, &count
);
492 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
493 ok(count
== 1, "Got count %u.\n", count
);
494 IPin_Release(pins
[0]);
496 hr
= IEnumPins_Next(enum1
, 1, pins
, &count
);
497 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
498 ok(!count
, "Got count %u.\n", count
);
500 hr
= IEnumPins_Reset(enum1
);
501 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
503 hr
= IEnumPins_Next(enum1
, 2, pins
, NULL
);
504 ok(hr
== E_INVALIDARG
, "Got hr %#x.\n", hr
);
506 hr
= IEnumPins_Next(enum1
, 2, pins
, &count
);
507 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
508 ok(count
== 1, "Got count %u.\n", count
);
509 IPin_Release(pins
[0]);
511 hr
= IEnumPins_Reset(enum1
);
512 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
514 hr
= IEnumPins_Clone(enum1
, &enum2
);
515 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
517 hr
= IEnumPins_Skip(enum1
, 2);
518 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
520 hr
= IEnumPins_Skip(enum1
, 1);
521 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
523 hr
= IEnumPins_Skip(enum1
, 1);
524 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
526 hr
= IEnumPins_Next(enum1
, 1, pins
, NULL
);
527 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
529 hr
= IEnumPins_Next(enum2
, 1, pins
, NULL
);
530 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
531 IPin_Release(pins
[0]);
533 IEnumPins_Release(enum2
);
535 if (SUCCEEDED(set_mixing_mode(filter
, 2)))
537 hr
= IEnumPins_Next(enum1
, 1, pins
, NULL
);
538 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
540 hr
= IEnumPins_Reset(enum1
);
541 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
543 hr
= IEnumPins_Next(enum1
, 1, pins
, NULL
);
544 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
545 IPin_Release(pins
[0]);
547 hr
= IEnumPins_Next(enum1
, 1, pins
, NULL
);
548 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
549 IPin_Release(pins
[0]);
551 hr
= IEnumPins_Next(enum1
, 1, pins
, NULL
);
552 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
554 hr
= IEnumPins_Reset(enum1
);
555 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
557 hr
= IEnumPins_Next(enum1
, 2, pins
, &count
);
558 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
559 ok(count
== 2, "Got count %u.\n", count
);
560 IPin_Release(pins
[0]);
561 IPin_Release(pins
[1]);
563 hr
= IEnumPins_Reset(enum1
);
564 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
566 hr
= IEnumPins_Next(enum1
, 3, pins
, &count
);
567 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
568 ok(count
== 2, "Got count %u.\n", count
);
569 IPin_Release(pins
[0]);
570 IPin_Release(pins
[1]);
573 IEnumPins_Release(enum1
);
574 ref
= IBaseFilter_Release(filter
);
575 ok(!ref
, "Got outstanding refcount %d.\n", ref
);
578 static void test_find_pin(void)
580 IBaseFilter
*filter
= create_vmr9(0);
581 IEnumPins
*enum_pins
;
586 IBaseFilter_EnumPins(filter
, &enum_pins
);
588 hr
= IBaseFilter_FindPin(filter
, L
"input pin", &pin
);
589 ok(hr
== VFW_E_NOT_FOUND
, "Got hr %#x.\n", hr
);
591 hr
= IBaseFilter_FindPin(filter
, L
"In", &pin
);
592 ok(hr
== VFW_E_NOT_FOUND
, "Got hr %#x.\n", hr
);
594 hr
= IBaseFilter_FindPin(filter
, L
"VMR Input0", &pin
);
595 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
596 hr
= IEnumPins_Next(enum_pins
, 1, &pin2
, NULL
);
597 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
598 ok(pin
== pin2
, "Pins did not match.\n");
602 hr
= IBaseFilter_FindPin(filter
, L
"VMR Input1", &pin
);
603 ok(hr
== VFW_E_NOT_FOUND
, "Got hr %#x.\n", hr
);
605 if (SUCCEEDED(set_mixing_mode(filter
, 2)))
607 IEnumPins_Reset(enum_pins
);
609 hr
= IBaseFilter_FindPin(filter
, L
"VMR Input0", &pin
);
610 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
611 hr
= IEnumPins_Next(enum_pins
, 1, &pin2
, NULL
);
612 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
613 ok(pin
== pin2
, "Pins did not match.\n");
617 hr
= IBaseFilter_FindPin(filter
, L
"VMR Input1", &pin
);
618 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
619 hr
= IEnumPins_Next(enum_pins
, 1, &pin2
, NULL
);
620 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
621 ok(pin
== pin2
, "Pins did not match.\n");
625 hr
= IBaseFilter_FindPin(filter
, L
"VMR Input2", &pin
);
626 ok(hr
== VFW_E_NOT_FOUND
, "Got hr %#x.\n", hr
);
629 IEnumPins_Release(enum_pins
);
630 ref
= IBaseFilter_Release(filter
);
631 ok(!ref
, "Got outstanding refcount %d.\n", ref
);
634 static void test_pin_info(void)
636 IBaseFilter
*filter
= create_vmr9(0);
644 IBaseFilter_FindPin(filter
, L
"VMR Input0", &pin
);
645 hr
= IPin_QueryPinInfo(pin
, &info
);
646 ok(info
.pFilter
== filter
, "Expected filter %p, got %p.\n", filter
, info
.pFilter
);
647 ok(info
.dir
== PINDIR_INPUT
, "Got direction %d.\n", info
.dir
);
648 ok(!wcscmp(info
.achName
, L
"VMR Input0"), "Got name %s.\n", wine_dbgstr_w(info
.achName
));
649 IBaseFilter_Release(info
.pFilter
);
651 hr
= IPin_QueryDirection(pin
, &dir
);
652 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
653 ok(dir
== PINDIR_INPUT
, "Got direction %d.\n", dir
);
655 hr
= IPin_QueryId(pin
, &id
);
656 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
657 ok(!wcscmp(id
, L
"VMR Input0"), "Got id %s.\n", wine_dbgstr_w(id
));
660 hr
= IPin_QueryInternalConnections(pin
, NULL
, &count
);
661 ok(hr
== E_NOTIMPL
, "Got hr %#x.\n", hr
);
665 if (SUCCEEDED(set_mixing_mode(filter
, 2)))
667 IBaseFilter_FindPin(filter
, L
"VMR Input1", &pin
);
668 hr
= IPin_QueryPinInfo(pin
, &info
);
669 ok(info
.pFilter
== filter
, "Expected filter %p, got %p.\n", filter
, info
.pFilter
);
670 ok(info
.dir
== PINDIR_INPUT
, "Got direction %d.\n", info
.dir
);
671 ok(!wcscmp(info
.achName
, L
"VMR Input1"), "Got name %s.\n", wine_dbgstr_w(info
.achName
));
672 IBaseFilter_Release(info
.pFilter
);
674 hr
= IPin_QueryDirection(pin
, &dir
);
675 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
676 ok(dir
== PINDIR_INPUT
, "Got direction %d.\n", dir
);
678 hr
= IPin_QueryId(pin
, &id
);
679 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
680 ok(!wcscmp(id
, L
"VMR Input1"), "Got id %s.\n", wine_dbgstr_w(id
));
683 hr
= IPin_QueryInternalConnections(pin
, NULL
, &count
);
684 ok(hr
== E_NOTIMPL
, "Got hr %#x.\n", hr
);
689 ref
= IBaseFilter_Release(filter
);
690 ok(!ref
, "Got outstanding refcount %d.\n", ref
);
693 static void test_media_types(void)
695 IBaseFilter
*filter
= create_vmr9(0);
696 AM_MEDIA_TYPE
*mt
, req_mt
= {{0}};
697 VIDEOINFOHEADER vih
=
700 {sizeof(BITMAPINFOHEADER
), 32, 24, 1, 0, BI_RGB
}
702 IEnumMediaTypes
*enummt
;
708 static const GUID
*subtype_tests
[] =
710 &MEDIASUBTYPE_RGB565
,
715 IBaseFilter_FindPin(filter
, L
"VMR Input0", &pin
);
717 hr
= IPin_EnumMediaTypes(pin
, &enummt
);
718 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
720 hr
= IEnumMediaTypes_Next(enummt
, 1, &mt
, NULL
);
721 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
723 IEnumMediaTypes_Release(enummt
);
725 req_mt
.majortype
= MEDIATYPE_Video
;
726 req_mt
.formattype
= FORMAT_VideoInfo
;
727 req_mt
.cbFormat
= sizeof(VIDEOINFOHEADER
);
728 req_mt
.pbFormat
= (BYTE
*)&vih
;
730 for (i
= 0; i
< ARRAY_SIZE(subtype_tests
); ++i
)
732 req_mt
.subtype
= *subtype_tests
[i
];
733 hr
= IPin_QueryAccept(pin
, &req_mt
);
734 ok(hr
== S_OK
, "Got hr %#x for subtype %s.\n", hr
, wine_dbgstr_guid(subtype_tests
[i
]));
737 req_mt
.subtype
= MEDIASUBTYPE_RGB8
;
738 hr
= IPin_QueryAccept(pin
, &req_mt
);
739 todo_wine
ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
740 req_mt
.subtype
= MEDIASUBTYPE_NULL
;
741 hr
= IPin_QueryAccept(pin
, &req_mt
);
742 todo_wine
ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
743 req_mt
.subtype
= MEDIASUBTYPE_RGB24
;
745 req_mt
.majortype
= MEDIATYPE_NULL
;
746 hr
= IPin_QueryAccept(pin
, &req_mt
);
747 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
748 req_mt
.majortype
= MEDIATYPE_Video
;
750 req_mt
.formattype
= FORMAT_None
;
751 hr
= IPin_QueryAccept(pin
, &req_mt
);
752 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
754 req_mt
.formattype
= GUID_NULL
;
755 hr
= IPin_QueryAccept(pin
, &req_mt
);
756 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
759 ref
= IBaseFilter_Release(filter
);
760 ok(!ref
, "Got outstanding refcount %d.\n", ref
);
763 static void test_enum_media_types(void)
765 IBaseFilter
*filter
= create_vmr9(0);
766 IEnumMediaTypes
*enum1
, *enum2
;
767 AM_MEDIA_TYPE
*mts
[2];
772 IBaseFilter_FindPin(filter
, L
"VMR Input0", &pin
);
774 hr
= IPin_EnumMediaTypes(pin
, &enum1
);
775 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
777 hr
= IEnumMediaTypes_Next(enum1
, 1, mts
, NULL
);
778 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
780 hr
= IEnumMediaTypes_Next(enum1
, 1, mts
, &count
);
781 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
782 ok(!count
, "Got count %u.\n", count
);
784 hr
= IEnumMediaTypes_Reset(enum1
);
785 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
787 hr
= IEnumMediaTypes_Next(enum1
, 1, mts
, NULL
);
788 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
790 hr
= IEnumMediaTypes_Clone(enum1
, &enum2
);
791 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
793 hr
= IEnumMediaTypes_Skip(enum1
, 1);
794 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
796 hr
= IEnumMediaTypes_Next(enum2
, 1, mts
, NULL
);
797 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
799 IEnumMediaTypes_Release(enum1
);
800 IEnumMediaTypes_Release(enum2
);
803 ref
= IBaseFilter_Release(filter
);
804 ok(!ref
, "Got outstanding refcount %d.\n", ref
);
807 static void test_unconnected_filter_state(void)
809 IBaseFilter
*filter
= create_vmr9(0);
814 hr
= IBaseFilter_GetState(filter
, 0, &state
);
815 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
816 ok(state
== State_Stopped
, "Got state %u.\n", state
);
818 hr
= IBaseFilter_Pause(filter
);
819 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
821 hr
= IBaseFilter_GetState(filter
, 0, &state
);
822 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
823 ok(state
== State_Paused
, "Got state %u.\n", state
);
825 hr
= IBaseFilter_Run(filter
, 0);
826 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
828 hr
= IBaseFilter_GetState(filter
, 0, &state
);
829 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
830 ok(state
== State_Running
, "Got state %u.\n", state
);
832 hr
= IBaseFilter_Pause(filter
);
833 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
835 hr
= IBaseFilter_GetState(filter
, 0, &state
);
836 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
837 ok(state
== State_Paused
, "Got state %u.\n", state
);
839 hr
= IBaseFilter_Stop(filter
);
840 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
842 hr
= IBaseFilter_GetState(filter
, 0, &state
);
843 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
844 ok(state
== State_Stopped
, "Got state %u.\n", state
);
846 hr
= IBaseFilter_Run(filter
, 0);
847 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
849 hr
= IBaseFilter_GetState(filter
, 0, &state
);
850 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
851 ok(state
== State_Running
, "Got state %u.\n", state
);
853 hr
= IBaseFilter_Stop(filter
);
854 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
856 hr
= IBaseFilter_GetState(filter
, 0, &state
);
857 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
858 ok(state
== State_Stopped
, "Got state %u.\n", state
);
860 ref
= IBaseFilter_Release(filter
);
861 ok(!ref
, "Got outstanding refcount %d.\n", ref
);
866 struct strmbase_filter filter
;
867 struct strmbase_source source
;
870 static inline struct testfilter
*impl_from_strmbase_filter(struct strmbase_filter
*iface
)
872 return CONTAINING_RECORD(iface
, struct testfilter
, filter
);
875 static struct strmbase_pin
*testfilter_get_pin(struct strmbase_filter
*iface
, unsigned int index
)
877 struct testfilter
*filter
= impl_from_strmbase_filter(iface
);
879 return &filter
->source
.pin
;
883 static void testfilter_destroy(struct strmbase_filter
*iface
)
885 struct testfilter
*filter
= impl_from_strmbase_filter(iface
);
886 strmbase_source_cleanup(&filter
->source
);
887 strmbase_filter_cleanup(&filter
->filter
);
890 static const struct strmbase_filter_ops testfilter_ops
=
892 .filter_get_pin
= testfilter_get_pin
,
893 .filter_destroy
= testfilter_destroy
,
896 static HRESULT WINAPI
testsource_DecideAllocator(struct strmbase_source
*iface
,
897 IMemInputPin
*peer
, IMemAllocator
**allocator
)
902 static const struct strmbase_source_ops testsource_ops
=
904 .pfnAttemptConnection
= BaseOutputPinImpl_AttemptConnection
,
905 .pfnDecideAllocator
= testsource_DecideAllocator
,
908 static void testfilter_init(struct testfilter
*filter
)
910 static const GUID clsid
= {0xabacab};
911 strmbase_filter_init(&filter
->filter
, NULL
, &clsid
, &testfilter_ops
);
912 strmbase_source_init(&filter
->source
, &filter
->filter
, L
"", &testsource_ops
);
915 static void test_allocator(IMemInputPin
*input
)
917 IMemAllocator
*req_allocator
, *ret_allocator
;
918 ALLOCATOR_PROPERTIES props
, req_props
;
921 hr
= IMemInputPin_GetAllocatorRequirements(input
, &props
);
922 ok(hr
== E_NOTIMPL
, "Got hr %#x.\n", hr
);
924 hr
= IMemInputPin_GetAllocator(input
, &ret_allocator
);
925 todo_wine
ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
929 hr
= IMemAllocator_GetProperties(ret_allocator
, &props
);
930 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
931 ok(!props
.cBuffers
, "Got %d buffers.\n", props
.cBuffers
);
932 ok(!props
.cbBuffer
, "Got size %d.\n", props
.cbBuffer
);
933 ok(!props
.cbAlign
, "Got alignment %d.\n", props
.cbAlign
);
934 ok(!props
.cbPrefix
, "Got prefix %d.\n", props
.cbPrefix
);
936 hr
= IMemInputPin_NotifyAllocator(input
, ret_allocator
, TRUE
);
937 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
939 req_props
.cBuffers
= 1;
940 req_props
.cbBuffer
= 32 * 16 * 4;
941 req_props
.cbAlign
= 1;
942 req_props
.cbPrefix
= 0;
943 hr
= IMemAllocator_SetProperties(ret_allocator
, &req_props
, &props
);
944 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
945 ok(props
.cBuffers
== 1, "Got %d buffers.\n", props
.cBuffers
);
946 ok(props
.cbBuffer
== 32 * 16 * 4, "Got size %d.\n", props
.cbBuffer
);
947 ok(props
.cbAlign
== 1, "Got alignment %d.\n", props
.cbAlign
);
948 ok(!props
.cbPrefix
, "Got prefix %d.\n", props
.cbPrefix
);
950 IMemAllocator_Release(ret_allocator
);
953 hr
= IMemInputPin_NotifyAllocator(input
, NULL
, TRUE
);
954 todo_wine
ok(hr
== E_FAIL
, "Got hr %#x.\n", hr
);
956 CoCreateInstance(&CLSID_MemoryAllocator
, NULL
, CLSCTX_INPROC_SERVER
,
957 &IID_IMemAllocator
, (void **)&req_allocator
);
959 hr
= IMemInputPin_NotifyAllocator(input
, req_allocator
, TRUE
);
960 todo_wine
ok(hr
== E_FAIL
, "Got hr %#x.\n", hr
);
962 IMemAllocator_Release(req_allocator
);
965 struct frame_thread_params
968 IMediaSample
*sample
;
971 static DWORD WINAPI
frame_thread(void *arg
)
973 struct frame_thread_params
*params
= arg
;
976 if (winetest_debug
> 1) trace("%04x: Sending frame.\n", GetCurrentThreadId());
977 hr
= IMemInputPin_Receive(params
->sink
, params
->sample
);
978 if (winetest_debug
> 1) trace("%04x: Returned %#x.\n", GetCurrentThreadId(), hr
);
979 IMediaSample_Release(params
->sample
);
984 static HANDLE
send_frame_time(IMemInputPin
*sink
, REFERENCE_TIME start_time
, DWORD color
)
986 struct frame_thread_params
*params
= heap_alloc(sizeof(*params
));
987 IMemAllocator
*allocator
;
988 REFERENCE_TIME end_time
;
989 IMediaSample
*sample
;
995 hr
= IMemInputPin_GetAllocator(sink
, &allocator
);
996 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
998 hr
= IMemAllocator_GetBuffer(allocator
, &sample
, NULL
, NULL
, 0);
999 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1001 size
= IMediaSample_GetSize(sample
);
1002 hr
= IMediaSample_GetPointer(sample
, &data
);
1003 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1004 for (i
= 0; i
< size
/ sizeof(DWORD
); ++i
)
1005 ((DWORD
*)data
)[i
] = color
;
1007 hr
= IMediaSample_SetActualDataLength(sample
, size
);
1008 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1010 start_time
*= 10000000;
1011 end_time
= start_time
+ 10000000;
1012 hr
= IMediaSample_SetTime(sample
, &start_time
, &end_time
);
1013 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1015 params
->sink
= sink
;
1016 params
->sample
= sample
;
1017 thread
= CreateThread(NULL
, 0, frame_thread
, params
, 0, NULL
);
1019 IMemAllocator_Release(allocator
);
1023 static HANDLE
send_frame(IMemInputPin
*sink
)
1025 return send_frame_time(sink
, 0, 0x007f007f);
1028 static HRESULT
join_thread_(int line
, HANDLE thread
)
1031 ok_(__FILE__
, line
)(!WaitForSingleObject(thread
, 1000), "Wait failed.\n");
1032 GetExitCodeThread(thread
, &ret
);
1033 CloseHandle(thread
);
1036 #define join_thread(a) join_thread_(__LINE__, a)
1038 static void commit_allocator(IMemInputPin
*input
)
1040 IMemAllocator
*allocator
;
1043 hr
= IMemInputPin_GetAllocator(input
, &allocator
);
1044 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1045 hr
= IMemAllocator_Commit(allocator
);
1046 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1047 IMemAllocator_Release(allocator
);
1050 static void test_filter_state(IMemInputPin
*input
, IMediaControl
*control
)
1052 IMemAllocator
*allocator
;
1053 IMediaSample
*sample
;
1054 OAFilterState state
;
1058 thread
= send_frame(input
);
1059 hr
= join_thread(thread
);
1060 ok(hr
== VFW_E_WRONG_STATE
, "Got hr %#x.\n", hr
);
1062 /* The renderer is not fully paused until it receives a sample. The thread
1063 * sending the sample blocks in IMemInputPin_Receive() until the filter is
1064 * stopped or run. */
1066 hr
= IMediaControl_Pause(control
);
1067 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
1069 hr
= IMediaControl_GetState(control
, 0, &state
);
1070 ok(hr
== VFW_S_STATE_INTERMEDIATE
, "Got hr %#x.\n", hr
);
1072 thread
= send_frame(input
);
1074 hr
= IMediaControl_GetState(control
, 1000, &state
);
1075 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1077 ok(WaitForSingleObject(thread
, 100) == WAIT_TIMEOUT
, "Thread should block in Receive().\n");
1079 hr
= IMediaControl_Stop(control
);
1080 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1082 hr
= join_thread(thread
);
1083 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1085 /* The sink will decommit our allocator for us when stopping, however it
1086 * will not recommit it when pausing. */
1087 hr
= IMemInputPin_GetAllocator(input
, &allocator
);
1088 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1089 hr
= IMemAllocator_GetBuffer(allocator
, &sample
, NULL
, NULL
, 0);
1090 todo_wine
ok(hr
== VFW_E_NOT_COMMITTED
, "Got hr %#x.\n", hr
);
1091 if (hr
== S_OK
) IMediaSample_Release(sample
);
1093 hr
= IMemAllocator_Commit(allocator
);
1094 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1095 thread
= send_frame(input
);
1096 hr
= join_thread(thread
);
1097 ok(hr
== VFW_E_WRONG_STATE
, "Got hr %#x.\n", hr
);
1099 hr
= IMediaControl_Pause(control
);
1100 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
1102 hr
= IMediaControl_GetState(control
, 0, &state
);
1103 ok(hr
== VFW_S_STATE_INTERMEDIATE
, "Got hr %#x.\n", hr
);
1105 thread
= send_frame(input
);
1107 hr
= IMediaControl_GetState(control
, 1000, &state
);
1108 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1110 ok(WaitForSingleObject(thread
, 100) == WAIT_TIMEOUT
, "Thread should block in Receive().\n");
1112 hr
= IMediaControl_Run(control
);
1113 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1115 hr
= IMediaControl_GetState(control
, 0, &state
);
1116 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1118 hr
= join_thread(thread
);
1119 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1121 thread
= send_frame(input
);
1122 hr
= join_thread(thread
);
1123 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1125 hr
= IMediaControl_Pause(control
);
1126 todo_wine
ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
1128 hr
= IMediaControl_GetState(control
, 0, &state
);
1129 todo_wine
ok(hr
== VFW_S_STATE_INTERMEDIATE
, "Got hr %#x.\n", hr
);
1131 thread
= send_frame(input
);
1133 hr
= IMediaControl_GetState(control
, 1000, &state
);
1134 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1136 ok(WaitForSingleObject(thread
, 100) == WAIT_TIMEOUT
, "Thread should block in Receive().\n");
1138 hr
= IMediaControl_Run(control
);
1139 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1141 hr
= IMediaControl_GetState(control
, 0, &state
);
1142 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1144 hr
= join_thread(thread
);
1145 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1147 hr
= IMediaControl_Pause(control
);
1148 todo_wine
ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
1150 hr
= IMediaControl_GetState(control
, 0, &state
);
1151 todo_wine
ok(hr
== VFW_S_STATE_INTERMEDIATE
, "Got hr %#x.\n", hr
);
1153 hr
= IMediaControl_Stop(control
);
1154 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1156 hr
= IMediaControl_GetState(control
, 0, &state
);
1157 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1159 commit_allocator(input
);
1160 hr
= IMediaControl_Pause(control
);
1161 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
1163 hr
= IMediaControl_GetState(control
, 0, &state
);
1164 ok(hr
== VFW_S_STATE_INTERMEDIATE
, "Got hr %#x.\n", hr
);
1166 hr
= IMediaControl_Run(control
);
1167 todo_wine
ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
1169 hr
= IMediaControl_GetState(control
, 0, &state
);
1170 todo_wine
ok(hr
== VFW_S_STATE_INTERMEDIATE
, "Got hr %#x.\n", hr
);
1172 thread
= send_frame(input
);
1173 hr
= join_thread(thread
);
1174 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1176 hr
= IMediaControl_GetState(control
, 0, &state
);
1177 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1179 hr
= IMediaControl_Stop(control
);
1180 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1182 hr
= IMediaControl_GetState(control
, 0, &state
);
1183 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1185 IMemAllocator_Release(allocator
);
1188 static void test_flushing(IPin
*pin
, IMemInputPin
*input
, IMediaControl
*control
)
1190 OAFilterState state
;
1194 commit_allocator(input
);
1195 hr
= IMediaControl_Pause(control
);
1196 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
1198 thread
= send_frame(input
);
1199 ok(WaitForSingleObject(thread
, 100) == WAIT_TIMEOUT
, "Thread should block in Receive().\n");
1201 hr
= IMediaControl_GetState(control
, 0, &state
);
1202 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1204 hr
= IPin_BeginFlush(pin
);
1205 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1207 hr
= join_thread(thread
);
1208 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1210 thread
= send_frame(input
);
1211 hr
= join_thread(thread
);
1212 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
1214 hr
= IPin_EndFlush(pin
);
1215 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1217 /* We dropped the sample we were holding, so now we need a new one... */
1219 hr
= IMediaControl_GetState(control
, 0, &state
);
1220 todo_wine
ok(hr
== VFW_S_STATE_INTERMEDIATE
, "Got hr %#x.\n", hr
);
1222 thread
= send_frame(input
);
1223 ok(WaitForSingleObject(thread
, 100) == WAIT_TIMEOUT
, "Thread should block in Receive().\n");
1225 hr
= IMediaControl_Run(control
);
1226 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1227 hr
= join_thread(thread
);
1228 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1230 hr
= IPin_BeginFlush(pin
);
1231 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1233 thread
= send_frame(input
);
1234 hr
= join_thread(thread
);
1235 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
1237 hr
= IPin_EndFlush(pin
);
1238 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1240 thread
= send_frame(input
);
1241 hr
= join_thread(thread
);
1242 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1244 hr
= IMediaControl_Stop(control
);
1245 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1248 static unsigned int check_ec_complete(IMediaEvent
*eventsrc
, DWORD timeout
)
1250 LONG_PTR param1
, param2
;
1251 unsigned int ret
= 0;
1255 while ((hr
= IMediaEvent_GetEvent(eventsrc
, &code
, ¶m1
, ¶m2
, timeout
)) == S_OK
)
1257 if (code
== EC_COMPLETE
)
1259 ok(param1
== S_OK
, "Got param1 %#lx.\n", param1
);
1260 ok(!param2
, "Got param2 %#lx.\n", param2
);
1263 IMediaEvent_FreeEventParams(eventsrc
, code
, param1
, param2
);
1266 ok(hr
== E_ABORT
, "Got hr %#x.\n", hr
);
1271 static void test_eos(IPin
*pin
, IMemInputPin
*input
, IMediaControl
*control
)
1273 IMediaEvent
*eventsrc
;
1274 OAFilterState state
;
1278 IMediaControl_QueryInterface(control
, &IID_IMediaEvent
, (void **)&eventsrc
);
1280 commit_allocator(input
);
1281 hr
= IMediaControl_Pause(control
);
1282 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
1283 ret
= check_ec_complete(eventsrc
, 0);
1284 ok(!ret
, "Got unexpected EC_COMPLETE.\n");
1286 hr
= IPin_EndOfStream(pin
);
1287 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1289 hr
= IMediaControl_GetState(control
, 1000, &state
);
1290 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1291 ret
= check_ec_complete(eventsrc
, 0);
1292 todo_wine
ok(!ret
, "Got unexpected EC_COMPLETE.\n");
1294 hr
= join_thread(send_frame(input
));
1295 todo_wine
ok(hr
== E_UNEXPECTED
, "Got hr %#x.\n", hr
);
1297 hr
= IMediaControl_Run(control
);
1298 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1299 ret
= check_ec_complete(eventsrc
, 0);
1300 todo_wine
ok(ret
== 1, "Expected EC_COMPLETE.\n");
1302 hr
= IMediaControl_Stop(control
);
1303 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1304 ret
= check_ec_complete(eventsrc
, 0);
1305 ok(!ret
, "Got unexpected EC_COMPLETE.\n");
1307 /* We do not receive an EC_COMPLETE notification until the last sample is
1308 * done rendering. */
1310 commit_allocator(input
);
1311 hr
= IMediaControl_Run(control
);
1312 todo_wine
ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
1313 hr
= join_thread(send_frame(input
));
1314 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1315 hr
= IMediaControl_GetState(control
, 1000, &state
);
1316 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1317 ret
= check_ec_complete(eventsrc
, 0);
1318 ok(!ret
, "Got unexpected EC_COMPLETE.\n");
1320 hr
= IPin_EndOfStream(pin
);
1321 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1322 ret
= check_ec_complete(eventsrc
, 0);
1323 todo_wine
ok(!ret
, "Got unexpected EC_COMPLETE.\n");
1324 ret
= check_ec_complete(eventsrc
, 1600);
1325 todo_wine
ok(ret
== 1, "Expected EC_COMPLETE.\n");
1327 hr
= IMediaControl_Stop(control
);
1328 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1329 ret
= check_ec_complete(eventsrc
, 0);
1330 ok(!ret
, "Got unexpected EC_COMPLETE.\n");
1332 /* Test sending EOS while flushing. */
1334 commit_allocator(input
);
1335 hr
= IMediaControl_Run(control
);
1336 todo_wine
ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
1337 hr
= join_thread(send_frame(input
));
1338 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1340 hr
= IPin_BeginFlush(pin
);
1341 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1342 hr
= IPin_EndOfStream(pin
);
1343 todo_wine
ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
1344 hr
= IPin_EndFlush(pin
);
1345 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1347 hr
= IMediaControl_Stop(control
);
1348 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1349 ret
= check_ec_complete(eventsrc
, 0);
1350 todo_wine
ok(!ret
, "Got unexpected EC_COMPLETE.\n");
1352 /* Test sending EOS and then flushing or stopping. */
1354 commit_allocator(input
);
1355 hr
= IMediaControl_Run(control
);
1356 todo_wine
ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
1357 hr
= join_thread(send_frame(input
));
1358 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1359 hr
= IMediaControl_GetState(control
, 1000, &state
);
1360 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1362 hr
= IPin_EndOfStream(pin
);
1363 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1364 ret
= check_ec_complete(eventsrc
, 0);
1365 todo_wine
ok(!ret
, "Got unexpected EC_COMPLETE.\n");
1367 hr
= IPin_BeginFlush(pin
);
1368 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1369 hr
= IPin_EndFlush(pin
);
1370 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1372 hr
= join_thread(send_frame(input
));
1373 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1374 hr
= IPin_EndOfStream(pin
);
1375 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1376 ret
= check_ec_complete(eventsrc
, 0);
1377 ok(!ret
, "Got unexpected EC_COMPLETE.\n");
1379 hr
= IMediaControl_Stop(control
);
1380 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1381 ret
= check_ec_complete(eventsrc
, 0);
1382 ok(!ret
, "Got unexpected EC_COMPLETE.\n");
1384 IMediaEvent_Release(eventsrc
);
1387 static void test_sample_time(IPin
*pin
, IMemInputPin
*input
, IMediaControl
*control
)
1389 OAFilterState state
;
1393 commit_allocator(input
);
1394 hr
= IMediaControl_Pause(control
);
1395 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
1397 hr
= IMediaControl_GetState(control
, 0, &state
);
1398 ok(hr
== VFW_S_STATE_INTERMEDIATE
, "Got hr %#x.\n", hr
);
1400 thread
= send_frame_time(input
, 1, 0x000000ff); /* blue */
1402 hr
= IMediaControl_GetState(control
, 1000, &state
);
1403 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1405 ok(WaitForSingleObject(thread
, 100) == WAIT_TIMEOUT
, "Thread should block in Receive().\n");
1407 hr
= IMediaControl_Run(control
);
1408 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1410 ok(WaitForSingleObject(thread
, 500) == WAIT_TIMEOUT
, "Thread should block in Receive().\n");
1412 hr
= join_thread(thread
);
1413 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1415 /* Sample time is relative to the time passed to Run(). Thus a sample
1416 * stamped at or earlier than 1s will now be displayed immediately, because
1417 * that time has already passed.
1418 * One may manually verify that all of the frames in this function are
1419 * rendered, including (by adding a Sleep() after sending the frame) the
1420 * cyan and green frames. Thus the VMR does not attempt to drop any frames
1421 * that it considers late. This remains true if the frames are marked as
1424 hr
= join_thread(send_frame_time(input
, 1, 0x0000ffff)); /* cyan */
1425 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1427 hr
= join_thread(send_frame_time(input
, 0, 0x0000ff00)); /* green */
1428 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1430 hr
= join_thread(send_frame_time(input
, -2, 0x00ff0000)); /* red */
1431 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1433 thread
= send_frame_time(input
, 2, 0x00ff00ff); /* magenta */
1434 ok(WaitForSingleObject(thread
, 800) == WAIT_TIMEOUT
, "Thread should block in Receive().\n");
1435 hr
= join_thread(thread
);
1436 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1438 thread
= send_frame_time(input
, 1000000, 0x00ffffff); /* white */
1439 ok(WaitForSingleObject(thread
, 100) == WAIT_TIMEOUT
, "Thread should block in Receive().\n");
1441 hr
= IPin_BeginFlush(pin
);
1442 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1443 hr
= join_thread(thread
);
1444 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1445 hr
= IPin_EndFlush(pin
);
1446 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1448 thread
= send_frame_time(input
, 1000000, 0x00ffff00); /* yellow */
1449 ok(WaitForSingleObject(thread
, 100) == WAIT_TIMEOUT
, "Thread should block in Receive().\n");
1451 hr
= IMediaControl_Stop(control
);
1452 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1453 hr
= join_thread(thread
);
1454 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1457 static void test_current_image(IBaseFilter
*filter
, IMemInputPin
*input
,
1458 IMediaControl
*control
, const BITMAPINFOHEADER
*req_bih
)
1460 LONG buffer
[(sizeof(BITMAPINFOHEADER
) + 32 * 16 * 4) / 4];
1461 const BITMAPINFOHEADER
*bih
= (BITMAPINFOHEADER
*)buffer
;
1462 const DWORD
*data
= (DWORD
*)((char *)buffer
+ sizeof(BITMAPINFOHEADER
));
1463 BITMAPINFOHEADER expect_bih
= *req_bih
;
1464 OAFilterState state
;
1471 expect_bih
.biSizeImage
= 32 * 16 * 4;
1473 IBaseFilter_QueryInterface(filter
, &IID_IBasicVideo
, (void **)&video
);
1475 hr
= IBasicVideo_GetCurrentImage(video
, NULL
, NULL
);
1476 ok(hr
== E_POINTER
, "Got hr %#x.\n", hr
);
1478 hr
= IBasicVideo_GetCurrentImage(video
, NULL
, buffer
);
1479 ok(hr
== E_POINTER
, "Got hr %#x.\n", hr
);
1482 hr
= IBasicVideo_GetCurrentImage(video
, &size
, NULL
);
1483 todo_wine
ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1484 todo_wine
ok(size
== sizeof(BITMAPINFOHEADER
) + 32 * 16 * 4, "Got size %d.\n", size
);
1486 size
= sizeof(buffer
);
1487 hr
= IBasicVideo_GetCurrentImage(video
, &size
, buffer
);
1488 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1489 ok(size
== sizeof(buffer
), "Got size %d.\n", size
);
1490 ok(!memcmp(bih
, &expect_bih
, sizeof(BITMAPINFOHEADER
)), "Bitmap headers didn't match.\n");
1491 /* The contents seem to reflect the last frame rendered. */
1493 commit_allocator(input
);
1494 hr
= IMediaControl_Pause(control
);
1495 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
1497 size
= sizeof(buffer
);
1498 hr
= IBasicVideo_GetCurrentImage(video
, &size
, buffer
);
1499 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1500 ok(size
== sizeof(buffer
), "Got size %d.\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 thread
= send_frame(input
);
1505 hr
= IMediaControl_GetState(control
, 1000, &state
);
1506 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1509 memset(buffer
, 0xcc, sizeof(buffer
));
1510 hr
= IBasicVideo_GetCurrentImage(video
, &size
, buffer
);
1511 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1512 ok(size
== 1, "Got size %d.\n", size
);
1514 size
= sizeof(buffer
);
1515 memset(buffer
, 0xcc, sizeof(buffer
));
1516 hr
= IBasicVideo_GetCurrentImage(video
, &size
, buffer
);
1517 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1518 ok(size
== sizeof(buffer
), "Got size %d.\n", size
);
1519 ok(!memcmp(bih
, &expect_bih
, sizeof(BITMAPINFOHEADER
)), "Bitmap headers didn't match.\n");
1520 for (i
= 0; i
< 32 * 16; ++i
)
1521 ok((data
[i
] & 0xffffff) == 0x7f007f, "Got unexpected color %08x at %u.\n", data
[i
], i
);
1523 hr
= IMediaControl_Run(control
);
1524 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1525 join_thread(thread
);
1527 size
= sizeof(buffer
);
1528 memset(buffer
, 0xcc, sizeof(buffer
));
1529 hr
= IBasicVideo_GetCurrentImage(video
, &size
, buffer
);
1530 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1531 ok(size
== sizeof(buffer
), "Got size %d.\n", size
);
1532 ok(!memcmp(bih
, &expect_bih
, sizeof(BITMAPINFOHEADER
)), "Bitmap headers didn't match.\n");
1533 for (i
= 0; i
< 32 * 16; ++i
)
1534 ok((data
[i
] & 0xffffff) == 0x7f007f, "Got unexpected color %08x at %u.\n", data
[i
], i
);
1536 hr
= IMediaControl_Stop(control
);
1537 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1539 IBasicVideo_Release(video
);
1542 static void test_connect_pin(void)
1544 VIDEOINFOHEADER vih
=
1546 .bmiHeader
.biSize
= sizeof(BITMAPINFOHEADER
),
1547 .bmiHeader
.biBitCount
= 32,
1548 .bmiHeader
.biWidth
= 32,
1549 .bmiHeader
.biHeight
= 16,
1550 .bmiHeader
.biPlanes
= 1,
1551 .bmiHeader
.biCompression
= BI_RGB
,
1553 AM_MEDIA_TYPE req_mt
=
1555 .majortype
= MEDIATYPE_Video
,
1556 .formattype
= FORMAT_VideoInfo
,
1557 .cbFormat
= sizeof(vih
),
1558 .pbFormat
= (BYTE
*)&vih
,
1560 ALLOCATOR_PROPERTIES req_props
= {1, 32 * 16 * 4, 1, 0}, ret_props
;
1561 IBaseFilter
*filter
= create_vmr9(VMR9Mode_Windowed
);
1562 IFilterGraph2
*graph
= create_graph();
1563 struct testfilter source
;
1564 IMemAllocator
*allocator
;
1565 IMediaControl
*control
;
1566 IMemInputPin
*input
;
1573 static const GUID
*subtype_tests
[] =
1575 &MEDIASUBTYPE_RGB555
,
1576 &MEDIASUBTYPE_RGB565
,
1577 &MEDIASUBTYPE_RGB24
,
1578 &MEDIASUBTYPE_RGB32
,
1580 static const WORD bpp_tests
[] = {15, 16, 24, 32};
1582 testfilter_init(&source
);
1584 IFilterGraph2_AddFilter(graph
, &source
.filter
.IBaseFilter_iface
, NULL
);
1585 IFilterGraph2_AddFilter(graph
, filter
, NULL
);
1586 IFilterGraph2_QueryInterface(graph
, &IID_IMediaControl
, (void **)&control
);
1588 IBaseFilter_FindPin(filter
, L
"VMR Input0", &pin
);
1589 IPin_QueryInterface(pin
, &IID_IMemInputPin
, (void **)&input
);
1591 for (i
= 0; i
< ARRAY_SIZE(subtype_tests
); ++i
)
1593 req_mt
.subtype
= *subtype_tests
[i
];
1595 for (j
= 0; j
< ARRAY_SIZE(bpp_tests
); ++j
)
1597 vih
.bmiHeader
.biBitCount
= bpp_tests
[j
];
1599 hr
= IFilterGraph2_ConnectDirect(graph
, &source
.source
.pin
.IPin_iface
, pin
, &req_mt
);
1602 skip("Got E_FAIL when connecting.\n");
1605 ok(hr
== S_OK
, "Got hr %#x for subtype %s and bpp %u.\n", hr
,
1606 wine_dbgstr_guid(subtype_tests
[i
]), bpp_tests
[j
]);
1608 hr
= IFilterGraph2_Disconnect(graph
, &source
.source
.pin
.IPin_iface
);
1609 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1610 hr
= IFilterGraph2_Disconnect(graph
, pin
);
1611 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1615 req_mt
.formattype
= FORMAT_None
;
1616 hr
= IFilterGraph2_ConnectDirect(graph
, &source
.source
.pin
.IPin_iface
, pin
, &req_mt
);
1617 ok(hr
== VFW_E_TYPE_NOT_ACCEPTED
, "Got hr %#x.\n", hr
);
1618 req_mt
.formattype
= FORMAT_VideoInfo
;
1620 req_mt
.subtype
= MEDIASUBTYPE_RGB8
;
1621 hr
= IFilterGraph2_ConnectDirect(graph
, &source
.source
.pin
.IPin_iface
, pin
, &req_mt
);
1622 todo_wine
ok(hr
== VFW_E_TYPE_NOT_ACCEPTED
, "Got hr %#x.\n", hr
);
1625 IFilterGraph2_Disconnect(graph
, &source
.source
.pin
.IPin_iface
);
1626 IFilterGraph2_Disconnect(graph
, pin
);
1628 req_mt
.subtype
= MEDIASUBTYPE_WAVE
;
1629 hr
= IFilterGraph2_ConnectDirect(graph
, &source
.source
.pin
.IPin_iface
, pin
, &req_mt
);
1630 todo_wine
ok(hr
== VFW_E_TYPE_NOT_ACCEPTED
, "Got hr %#x.\n", hr
);
1633 IFilterGraph2_Disconnect(graph
, &source
.source
.pin
.IPin_iface
);
1634 IFilterGraph2_Disconnect(graph
, pin
);
1636 req_mt
.subtype
= MEDIASUBTYPE_RGB32
;
1638 peer
= (IPin
*)0xdeadbeef;
1639 hr
= IPin_ConnectedTo(pin
, &peer
);
1640 ok(hr
== VFW_E_NOT_CONNECTED
, "Got hr %#x.\n", hr
);
1641 ok(!peer
, "Got peer %p.\n", peer
);
1643 hr
= IPin_ConnectionMediaType(pin
, &mt
);
1644 ok(hr
== VFW_E_NOT_CONNECTED
, "Got hr %#x.\n", hr
);
1646 hr
= IFilterGraph2_ConnectDirect(graph
, &source
.source
.pin
.IPin_iface
, pin
, &req_mt
);
1647 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1649 hr
= IPin_ConnectedTo(pin
, &peer
);
1650 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1651 ok(peer
== &source
.source
.pin
.IPin_iface
, "Got peer %p.\n", peer
);
1654 hr
= IPin_ConnectionMediaType(pin
, &mt
);
1655 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1656 ok(compare_media_types(&mt
, &req_mt
), "Media types didn't match.\n");
1658 test_allocator(input
);
1660 hr
= IMemInputPin_GetAllocator(input
, &allocator
);
1661 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1662 hr
= IMemAllocator_SetProperties(allocator
, &req_props
, &ret_props
);
1663 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1664 ok(!memcmp(&ret_props
, &req_props
, sizeof(req_props
)), "Properties did not match.\n");
1665 hr
= IMemAllocator_Commit(allocator
);
1666 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1667 IMemAllocator_Release(allocator
);
1669 hr
= IMemInputPin_ReceiveCanBlock(input
);
1670 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1672 test_filter_state(input
, control
);
1673 test_flushing(pin
, input
, control
);
1674 test_eos(pin
, input
, control
);
1675 test_sample_time(pin
, input
, control
);
1676 test_current_image(filter
, input
, control
, &vih
.bmiHeader
);
1678 hr
= IFilterGraph2_Disconnect(graph
, pin
);
1679 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1680 hr
= IFilterGraph2_Disconnect(graph
, pin
);
1681 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
1682 ok(source
.source
.pin
.peer
== pin
, "Got peer %p.\n", source
.source
.pin
.peer
);
1683 IFilterGraph2_Disconnect(graph
, &source
.source
.pin
.IPin_iface
);
1685 peer
= (IPin
*)0xdeadbeef;
1686 hr
= IPin_ConnectedTo(pin
, &peer
);
1687 ok(hr
== VFW_E_NOT_CONNECTED
, "Got hr %#x.\n", hr
);
1688 ok(!peer
, "Got peer %p.\n", peer
);
1690 hr
= IPin_ConnectionMediaType(pin
, &mt
);
1691 ok(hr
== VFW_E_NOT_CONNECTED
, "Got hr %#x.\n", hr
);
1694 IMediaControl_Release(control
);
1695 ref
= IFilterGraph2_Release(graph
);
1696 ok(!ref
, "Got outstanding refcount %d.\n", ref
);
1697 IMemInputPin_Release(input
);
1699 ref
= IBaseFilter_Release(filter
);
1700 ok(!ref
, "Got outstanding refcount %d.\n", ref
);
1701 ref
= IBaseFilter_Release(&source
.filter
.IBaseFilter_iface
);
1702 ok(!ref
, "Got outstanding refcount %d.\n", ref
);
1705 static void test_overlay(void)
1707 IBaseFilter
*filter
= create_vmr9(0);
1714 IBaseFilter_FindPin(filter
, L
"VMR Input0", &pin
);
1716 hr
= IPin_QueryInterface(pin
, &IID_IOverlay
, (void **)&overlay
);
1717 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1719 hwnd
= (HWND
)0xdeadbeef;
1720 hr
= IOverlay_GetWindowHandle(overlay
, &hwnd
);
1721 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1722 ok(hwnd
&& hwnd
!= (HWND
)0xdeadbeef, "Got invalid window %p.\n", hwnd
);
1724 IOverlay_Release(overlay
);
1726 ref
= IBaseFilter_Release(filter
);
1727 ok(!ref
, "Got outstanding refcount %d.\n", ref
);
1729 filter
= create_vmr9(VMR9Mode_Windowless
);
1730 IBaseFilter_FindPin(filter
, L
"VMR Input0", &pin
);
1732 hr
= IPin_QueryInterface(pin
, &IID_IOverlay
, (void **)&overlay
);
1733 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1735 hwnd
= (HWND
)0xdeadbeef;
1736 hr
= IOverlay_GetWindowHandle(overlay
, &hwnd
);
1737 todo_wine
ok(hr
== VFW_E_WRONG_STATE
, "Got hr %#x.\n", hr
);
1738 todo_wine
ok(hwnd
== (HWND
)0xdeadbeef, "Got invalid window %p.\n", hwnd
);
1740 IOverlay_Release(overlay
);
1742 ref
= IBaseFilter_Release(filter
);
1743 ok(!ref
, "Got outstanding refcount %d.\n", ref
);
1745 filter
= create_vmr9(VMR9Mode_Renderless
);
1746 IBaseFilter_FindPin(filter
, L
"VMR Input0", &pin
);
1748 hr
= IPin_QueryInterface(pin
, &IID_IOverlay
, (void **)&overlay
);
1749 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1751 hwnd
= (HWND
)0xdeadbeef;
1752 hr
= IOverlay_GetWindowHandle(overlay
, &hwnd
);
1753 todo_wine
ok(hr
== VFW_E_WRONG_STATE
, "Got hr %#x.\n", hr
);
1754 todo_wine
ok(hwnd
== (HWND
)0xdeadbeef, "Got invalid window %p.\n", hwnd
);
1756 IOverlay_Release(overlay
);
1758 ref
= IBaseFilter_Release(filter
);
1759 ok(!ref
, "Got outstanding refcount %d.\n", ref
);
1762 /* try to make sure pending X events have been processed before continuing */
1763 static void flush_events(void)
1769 time
= GetTickCount() + diff
;
1772 if (MsgWaitForMultipleObjects(0, NULL
, FALSE
, 100, QS_ALLINPUT
) == WAIT_TIMEOUT
)
1774 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
))
1775 DispatchMessageA(&msg
);
1776 diff
= time
- GetTickCount();
1780 static LRESULT CALLBACK
window_proc(HWND hwnd
, UINT msg
, WPARAM wparam
, LPARAM lparam
)
1782 if (winetest_debug
> 1)
1783 trace("hwnd %p, msg %#x, wparam %#lx, lparam %#lx.\n", hwnd
, msg
, wparam
, lparam
);
1785 if (wparam
== 0xdeadbeef)
1788 return DefWindowProcA(hwnd
, msg
, wparam
, lparam
);
1791 static void test_video_window_caption(IVideoWindow
*window
, HWND hwnd
)
1797 hr
= IVideoWindow_get_Caption(window
, &caption
);
1798 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1799 ok(!wcscmp(caption
, L
"ActiveMovie Window"), "Got caption %s.\n", wine_dbgstr_w(caption
));
1800 SysFreeString(caption
);
1802 GetWindowTextW(hwnd
, text
, ARRAY_SIZE(text
));
1803 ok(!wcscmp(text
, L
"ActiveMovie Window"), "Got caption %s.\n", wine_dbgstr_w(text
));
1805 caption
= SysAllocString(L
"foo");
1806 hr
= IVideoWindow_put_Caption(window
, caption
);
1807 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1808 SysFreeString(caption
);
1810 hr
= IVideoWindow_get_Caption(window
, &caption
);
1811 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1812 ok(!wcscmp(caption
, L
"foo"), "Got caption %s.\n", wine_dbgstr_w(caption
));
1813 SysFreeString(caption
);
1815 GetWindowTextW(hwnd
, text
, ARRAY_SIZE(text
));
1816 ok(!wcscmp(text
, L
"foo"), "Got caption %s.\n", wine_dbgstr_w(text
));
1819 static void test_video_window_style(IVideoWindow
*window
, HWND hwnd
, HWND our_hwnd
)
1824 hr
= IVideoWindow_get_WindowStyle(window
, &style
);
1825 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1826 ok(style
== (WS_CLIPSIBLINGS
| WS_CLIPCHILDREN
| WS_OVERLAPPEDWINDOW
),
1827 "Got style %#x.\n", style
);
1829 style
= GetWindowLongA(hwnd
, GWL_STYLE
);
1830 ok(style
== (WS_CLIPSIBLINGS
| WS_CLIPCHILDREN
| WS_OVERLAPPEDWINDOW
),
1831 "Got style %#x.\n", style
);
1833 hr
= IVideoWindow_put_WindowStyle(window
, style
| WS_DISABLED
);
1834 ok(hr
== E_INVALIDARG
, "Got hr %#x.\n", hr
);
1835 hr
= IVideoWindow_put_WindowStyle(window
, style
| WS_HSCROLL
);
1836 ok(hr
== E_INVALIDARG
, "Got hr %#x.\n", hr
);
1837 hr
= IVideoWindow_put_WindowStyle(window
, style
| WS_VSCROLL
);
1838 ok(hr
== E_INVALIDARG
, "Got hr %#x.\n", hr
);
1839 hr
= IVideoWindow_put_WindowStyle(window
, style
| WS_MAXIMIZE
);
1840 ok(hr
== E_INVALIDARG
, "Got hr %#x.\n", hr
);
1841 hr
= IVideoWindow_put_WindowStyle(window
, style
| WS_MINIMIZE
);
1842 ok(hr
== E_INVALIDARG
, "Got hr %#x.\n", hr
);
1844 hr
= IVideoWindow_put_WindowStyle(window
, style
& ~WS_CLIPCHILDREN
);
1845 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1847 hr
= IVideoWindow_get_WindowStyle(window
, &style
);
1848 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1849 ok(style
== (WS_CLIPSIBLINGS
| WS_OVERLAPPEDWINDOW
), "Got style %#x.\n", style
);
1851 style
= GetWindowLongA(hwnd
, GWL_STYLE
);
1852 ok(style
== (WS_CLIPSIBLINGS
| WS_OVERLAPPEDWINDOW
), "Got style %#x.\n", style
);
1854 ok(GetActiveWindow() == our_hwnd
, "Got active window %p.\n", GetActiveWindow());
1856 hr
= IVideoWindow_get_WindowStyleEx(window
, &style
);
1857 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1858 ok(style
== WS_EX_WINDOWEDGE
, "Got style %#x.\n", style
);
1860 style
= GetWindowLongA(hwnd
, GWL_EXSTYLE
);
1861 ok(style
== WS_EX_WINDOWEDGE
, "Got style %#x.\n", style
);
1863 hr
= IVideoWindow_put_WindowStyleEx(window
, style
| WS_EX_TRANSPARENT
);
1864 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1866 hr
= IVideoWindow_get_WindowStyleEx(window
, &style
);
1867 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1868 ok(style
== (WS_EX_WINDOWEDGE
| WS_EX_TRANSPARENT
), "Got style %#x.\n", style
);
1870 style
= GetWindowLongA(hwnd
, GWL_EXSTYLE
);
1871 ok(style
== (WS_EX_WINDOWEDGE
| WS_EX_TRANSPARENT
), "Got style %#x.\n", style
);
1874 static BOOL CALLBACK
top_window_cb(HWND hwnd
, LPARAM ctx
)
1877 GetWindowThreadProcessId(hwnd
, &pid
);
1878 if (pid
== GetCurrentProcessId() && (GetWindowLongW(hwnd
, GWL_STYLE
) & WS_VISIBLE
))
1880 *(HWND
*)ctx
= hwnd
;
1886 static HWND
get_top_window(void)
1889 EnumWindows(top_window_cb
, (LPARAM
)&hwnd
);
1893 static void test_video_window_state(IVideoWindow
*window
, HWND hwnd
, HWND our_hwnd
)
1899 SetWindowPos(our_hwnd
, HWND_TOP
, 0, 0, 0, 0, SWP_NOMOVE
| SWP_NOSIZE
);
1901 hr
= IVideoWindow_get_WindowState(window
, &state
);
1902 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1903 ok(state
== SW_HIDE
, "Got state %d.\n", state
);
1905 hr
= IVideoWindow_get_Visible(window
, &state
);
1906 ok(state
== OAFALSE
, "Got state %d.\n", state
);
1908 ok(!IsWindowVisible(hwnd
), "Window should not be visible.\n");
1909 ok(!IsIconic(hwnd
), "Window should not be minimized.\n");
1910 ok(!IsZoomed(hwnd
), "Window should not be maximized.\n");
1912 hr
= IVideoWindow_put_WindowState(window
, SW_SHOWNA
);
1913 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1915 hr
= IVideoWindow_get_WindowState(window
, &state
);
1916 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1917 ok(state
== SW_SHOW
, "Got state %d.\n", state
);
1919 hr
= IVideoWindow_get_Visible(window
, &state
);
1920 ok(state
== OATRUE
, "Got state %d.\n", state
);
1922 ok(IsWindowVisible(hwnd
), "Window should be visible.\n");
1923 ok(!IsIconic(hwnd
), "Window should not be minimized.\n");
1924 ok(!IsZoomed(hwnd
), "Window should not be maximized.\n");
1925 ok(GetActiveWindow() == our_hwnd
, "Got active window %p.\n", GetActiveWindow());
1926 top
= get_top_window();
1927 ok(top
== hwnd
, "Got top window %p.\n", top
);
1929 hr
= IVideoWindow_put_WindowState(window
, SW_MINIMIZE
);
1930 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1932 hr
= IVideoWindow_get_WindowState(window
, &state
);
1933 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1934 ok(state
== SW_MINIMIZE
, "Got state %d.\n", state
);
1936 hr
= IVideoWindow_get_Visible(window
, &state
);
1937 ok(state
== OATRUE
, "Got state %d.\n", state
);
1939 ok(IsWindowVisible(hwnd
), "Window should be visible.\n");
1940 ok(IsIconic(hwnd
), "Window should be minimized.\n");
1941 ok(!IsZoomed(hwnd
), "Window should not be maximized.\n");
1942 ok(GetActiveWindow() == our_hwnd
, "Got active window %p.\n", GetActiveWindow());
1944 hr
= IVideoWindow_put_WindowState(window
, SW_RESTORE
);
1945 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1947 hr
= IVideoWindow_get_WindowState(window
, &state
);
1948 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1949 ok(state
== SW_SHOW
, "Got state %d.\n", state
);
1951 hr
= IVideoWindow_get_Visible(window
, &state
);
1952 ok(state
== OATRUE
, "Got state %d.\n", state
);
1954 ok(IsWindowVisible(hwnd
), "Window should be visible.\n");
1955 ok(!IsIconic(hwnd
), "Window should not be minimized.\n");
1956 ok(!IsZoomed(hwnd
), "Window should not be maximized.\n");
1957 ok(GetActiveWindow() == hwnd
, "Got active window %p.\n", GetActiveWindow());
1959 hr
= IVideoWindow_put_WindowState(window
, SW_MAXIMIZE
);
1960 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1962 hr
= IVideoWindow_get_WindowState(window
, &state
);
1963 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1964 ok(state
== SW_MAXIMIZE
, "Got state %d.\n", state
);
1966 hr
= IVideoWindow_get_Visible(window
, &state
);
1967 ok(state
== OATRUE
, "Got state %d.\n", state
);
1969 ok(IsWindowVisible(hwnd
), "Window should be visible.\n");
1970 ok(!IsIconic(hwnd
), "Window should be minimized.\n");
1971 ok(IsZoomed(hwnd
), "Window should not be maximized.\n");
1972 ok(GetActiveWindow() == hwnd
, "Got active window %p.\n", GetActiveWindow());
1974 hr
= IVideoWindow_put_WindowState(window
, SW_RESTORE
);
1975 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1977 hr
= IVideoWindow_put_WindowState(window
, SW_HIDE
);
1978 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1980 hr
= IVideoWindow_get_WindowState(window
, &state
);
1981 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1982 ok(state
== SW_HIDE
, "Got state %d.\n", state
);
1984 hr
= IVideoWindow_get_Visible(window
, &state
);
1985 ok(state
== OAFALSE
, "Got state %d.\n", state
);
1987 ok(!IsWindowVisible(hwnd
), "Window should not be visible.\n");
1988 ok(!IsIconic(hwnd
), "Window should not be minimized.\n");
1989 ok(!IsZoomed(hwnd
), "Window should not be maximized.\n");
1990 ok(GetActiveWindow() == our_hwnd
, "Got active window %p.\n", GetActiveWindow());
1992 hr
= IVideoWindow_put_Visible(window
, OATRUE
);
1993 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1995 hr
= IVideoWindow_get_WindowState(window
, &state
);
1996 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1997 ok(state
== SW_SHOW
, "Got state %d.\n", state
);
1999 hr
= IVideoWindow_get_Visible(window
, &state
);
2000 ok(state
== OATRUE
, "Got state %d.\n", state
);
2002 ok(IsWindowVisible(hwnd
), "Window should be visible.\n");
2003 ok(!IsIconic(hwnd
), "Window should not be minimized.\n");
2004 ok(!IsZoomed(hwnd
), "Window should not be maximized.\n");
2005 ok(GetActiveWindow() == hwnd
, "Got active window %p.\n", GetActiveWindow());
2007 hr
= IVideoWindow_put_Visible(window
, OAFALSE
);
2008 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2010 hr
= IVideoWindow_get_WindowState(window
, &state
);
2011 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2012 ok(state
== SW_HIDE
, "Got state %d.\n", state
);
2014 hr
= IVideoWindow_get_Visible(window
, &state
);
2015 ok(state
== OAFALSE
, "Got state %d.\n", state
);
2017 ok(!IsWindowVisible(hwnd
), "Window should not be visible.\n");
2018 ok(!IsIconic(hwnd
), "Window should not be minimized.\n");
2019 ok(!IsZoomed(hwnd
), "Window should not be maximized.\n");
2020 ok(GetActiveWindow() == our_hwnd
, "Got active window %p.\n", GetActiveWindow());
2022 hr
= IVideoWindow_put_WindowState(window
, SW_SHOWNA
);
2023 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2025 hr
= IVideoWindow_SetWindowForeground(window
, TRUE
);
2026 ok(hr
== E_INVALIDARG
, "Got hr %#x.\n", hr
);
2028 SetWindowPos(our_hwnd
, HWND_TOP
, 0, 0, 0, 0, SWP_NOMOVE
| SWP_NOSIZE
);
2029 hr
= IVideoWindow_SetWindowForeground(window
, OATRUE
);
2030 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2031 ok(GetActiveWindow() == hwnd
, "Got active window %p.\n", GetActiveWindow());
2032 ok(GetFocus() == hwnd
, "Got focus window %p.\n", GetFocus());
2033 ok(GetForegroundWindow() == hwnd
, "Got foreground window %p.\n", GetForegroundWindow());
2034 top
= get_top_window();
2035 ok(top
== hwnd
, "Got top window %p.\n", top
);
2037 hr
= IVideoWindow_SetWindowForeground(window
, OAFALSE
);
2038 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2039 ok(GetActiveWindow() == hwnd
, "Got active window %p.\n", GetActiveWindow());
2040 ok(GetFocus() == hwnd
, "Got focus window %p.\n", GetFocus());
2041 ok(GetForegroundWindow() == hwnd
, "Got foreground window %p.\n", GetForegroundWindow());
2042 top
= get_top_window();
2043 ok(top
== hwnd
, "Got top window %p.\n", top
);
2045 SetWindowPos(our_hwnd
, HWND_TOP
, 0, 0, 0, 0, SWP_NOMOVE
| SWP_NOSIZE
);
2046 hr
= IVideoWindow_SetWindowForeground(window
, OAFALSE
);
2047 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2048 ok(GetActiveWindow() == our_hwnd
, "Got active window %p.\n", GetActiveWindow());
2049 ok(GetFocus() == our_hwnd
, "Got focus window %p.\n", GetFocus());
2050 ok(GetForegroundWindow() == our_hwnd
, "Got foreground window %p.\n", GetForegroundWindow());
2051 top
= get_top_window();
2052 ok(top
== hwnd
, "Got top window %p.\n", top
);
2055 static void test_video_window_position(IVideoWindow
*window
, HWND hwnd
, HWND our_hwnd
)
2057 LONG left
, width
, top
, height
, expect_width
, expect_height
;
2058 RECT rect
= {0, 0, 600, 400};
2062 SetWindowPos(our_hwnd
, HWND_TOP
, 0, 0, 0, 0, SWP_NOMOVE
| SWP_NOSIZE
);
2064 AdjustWindowRect(&rect
, GetWindowLongA(hwnd
, GWL_STYLE
), FALSE
);
2065 expect_width
= rect
.right
- rect
.left
;
2066 expect_height
= rect
.bottom
- rect
.top
;
2068 hr
= IVideoWindow_put_Left(window
, 0);
2069 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2070 hr
= IVideoWindow_put_Top(window
, 0);
2071 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2073 hr
= IVideoWindow_get_Left(window
, &left
);
2074 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2075 ok(left
== 0, "Got left %d.\n", left
);
2076 hr
= IVideoWindow_get_Top(window
, &top
);
2077 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2078 ok(top
== 0, "Got top %d.\n", top
);
2079 hr
= IVideoWindow_get_Width(window
, &width
);
2080 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2081 ok(width
== expect_width
, "Got width %d.\n", width
);
2082 hr
= IVideoWindow_get_Height(window
, &height
);
2083 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2084 ok(height
== expect_height
, "Got height %d.\n", height
);
2085 hr
= IVideoWindow_GetWindowPosition(window
, &left
, &top
, &width
, &height
);
2086 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2087 ok(left
== 0, "Got left %d.\n", left
);
2088 ok(top
== 0, "Got top %d.\n", top
);
2089 ok(width
== expect_width
, "Got width %d.\n", width
);
2090 ok(height
== expect_height
, "Got height %d.\n", height
);
2091 GetWindowRect(hwnd
, &rect
);
2092 ok(rect
.left
== 0, "Got window left %d.\n", rect
.left
);
2093 ok(rect
.top
== 0, "Got window top %d.\n", rect
.top
);
2094 ok(rect
.right
== expect_width
, "Got window right %d.\n", rect
.right
);
2095 ok(rect
.bottom
== expect_height
, "Got window bottom %d.\n", rect
.bottom
);
2097 hr
= IVideoWindow_put_Left(window
, 10);
2098 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2100 hr
= IVideoWindow_get_Left(window
, &left
);
2101 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2102 ok(left
== 10, "Got left %d.\n", left
);
2103 hr
= IVideoWindow_get_Top(window
, &top
);
2104 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2105 ok(top
== 0, "Got top %d.\n", top
);
2106 hr
= IVideoWindow_get_Width(window
, &width
);
2107 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2108 ok(width
== expect_width
, "Got width %d.\n", width
);
2109 hr
= IVideoWindow_get_Height(window
, &height
);
2110 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2111 ok(height
== expect_height
, "Got height %d.\n", height
);
2112 hr
= IVideoWindow_GetWindowPosition(window
, &left
, &top
, &width
, &height
);
2113 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2114 ok(left
== 10, "Got left %d.\n", left
);
2115 ok(top
== 0, "Got top %d.\n", top
);
2116 ok(width
== expect_width
, "Got width %d.\n", width
);
2117 ok(height
== expect_height
, "Got height %d.\n", height
);
2118 GetWindowRect(hwnd
, &rect
);
2119 ok(rect
.left
== 10, "Got window left %d.\n", rect
.left
);
2120 ok(rect
.top
== 0, "Got window top %d.\n", rect
.top
);
2121 ok(rect
.right
== 10 + expect_width
, "Got window right %d.\n", rect
.right
);
2122 ok(rect
.bottom
== expect_height
, "Got window bottom %d.\n", rect
.bottom
);
2124 hr
= IVideoWindow_put_Height(window
, 200);
2125 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2127 hr
= IVideoWindow_get_Left(window
, &left
);
2128 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2129 ok(left
== 10, "Got left %d.\n", left
);
2130 hr
= IVideoWindow_get_Top(window
, &top
);
2131 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2132 ok(top
== 0, "Got top %d.\n", top
);
2133 hr
= IVideoWindow_get_Width(window
, &width
);
2134 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2135 ok(width
== expect_width
, "Got width %d.\n", width
);
2136 hr
= IVideoWindow_get_Height(window
, &height
);
2137 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2138 ok(height
== 200, "Got height %d.\n", height
);
2139 hr
= IVideoWindow_GetWindowPosition(window
, &left
, &top
, &width
, &height
);
2140 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2141 ok(left
== 10, "Got left %d.\n", left
);
2142 ok(top
== 0, "Got top %d.\n", top
);
2143 ok(width
== expect_width
, "Got width %d.\n", width
);
2144 ok(height
== 200, "Got height %d.\n", height
);
2145 GetWindowRect(hwnd
, &rect
);
2146 ok(rect
.left
== 10, "Got window left %d.\n", rect
.left
);
2147 ok(rect
.top
== 0, "Got window top %d.\n", rect
.top
);
2148 ok(rect
.right
== 10 + expect_width
, "Got window right %d.\n", rect
.right
);
2149 ok(rect
.bottom
== 200, "Got window bottom %d.\n", rect
.bottom
);
2151 hr
= IVideoWindow_SetWindowPosition(window
, 100, 200, 300, 400);
2152 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2154 hr
= IVideoWindow_get_Left(window
, &left
);
2155 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2156 ok(left
== 100, "Got left %d.\n", left
);
2157 hr
= IVideoWindow_get_Top(window
, &top
);
2158 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2159 ok(top
== 200, "Got top %d.\n", top
);
2160 hr
= IVideoWindow_get_Width(window
, &width
);
2161 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2162 ok(width
== 300, "Got width %d.\n", width
);
2163 hr
= IVideoWindow_get_Height(window
, &height
);
2164 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2165 ok(height
== 400, "Got height %d.\n", height
);
2166 hr
= IVideoWindow_GetWindowPosition(window
, &left
, &top
, &width
, &height
);
2167 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2168 ok(left
== 100, "Got left %d.\n", left
);
2169 ok(top
== 200, "Got top %d.\n", top
);
2170 ok(width
== 300, "Got width %d.\n", width
);
2171 ok(height
== 400, "Got height %d.\n", height
);
2172 GetWindowRect(hwnd
, &rect
);
2173 ok(rect
.left
== 100, "Got window left %d.\n", rect
.left
);
2174 ok(rect
.top
== 200, "Got window top %d.\n", rect
.top
);
2175 ok(rect
.right
== 400, "Got window right %d.\n", rect
.right
);
2176 ok(rect
.bottom
== 600, "Got window bottom %d.\n", rect
.bottom
);
2178 ok(GetActiveWindow() == our_hwnd
, "Got active window %p.\n", GetActiveWindow());
2179 top_hwnd
= get_top_window();
2180 ok(top_hwnd
== our_hwnd
, "Got top window %p.\n", top_hwnd
);
2183 static void test_video_window_owner(IVideoWindow
*window
, HWND hwnd
, HWND our_hwnd
)
2185 HWND parent
, top_hwnd
;
2190 SetWindowPos(our_hwnd
, HWND_TOP
, 0, 0, 0, 0, SWP_NOMOVE
| SWP_NOSIZE
);
2192 hr
= IVideoWindow_get_Owner(window
, &oahwnd
);
2193 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2194 ok(!oahwnd
, "Got owner %#lx.\n", oahwnd
);
2196 parent
= GetAncestor(hwnd
, GA_PARENT
);
2197 ok(parent
== GetDesktopWindow(), "Got parent %p.\n", parent
);
2198 style
= GetWindowLongA(hwnd
, GWL_STYLE
);
2199 ok(!(style
& WS_CHILD
), "Got style %#x.\n", style
);
2201 hr
= IVideoWindow_put_Owner(window
, (OAHWND
)our_hwnd
);
2202 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2204 hr
= IVideoWindow_get_Owner(window
, &oahwnd
);
2205 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2206 ok(oahwnd
== (OAHWND
)our_hwnd
, "Got owner %#lx.\n", oahwnd
);
2208 parent
= GetAncestor(hwnd
, GA_PARENT
);
2209 ok(parent
== our_hwnd
, "Got parent %p.\n", parent
);
2210 style
= GetWindowLongA(hwnd
, GWL_STYLE
);
2211 ok((style
& WS_CHILD
), "Got style %#x.\n", style
);
2213 ok(GetActiveWindow() == our_hwnd
, "Got active window %p.\n", GetActiveWindow());
2214 top_hwnd
= get_top_window();
2215 ok(top_hwnd
== our_hwnd
, "Got top window %p.\n", top_hwnd
);
2217 ShowWindow(our_hwnd
, SW_HIDE
);
2219 hr
= IVideoWindow_put_Visible(window
, OATRUE
);
2220 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2222 hr
= IVideoWindow_get_Visible(window
, &state
);
2223 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2224 ok(state
== OAFALSE
, "Got state %d.\n", state
);
2226 hr
= IVideoWindow_put_Owner(window
, 0);
2227 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2229 hr
= IVideoWindow_get_Owner(window
, &oahwnd
);
2230 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2231 ok(!oahwnd
, "Got owner %#lx.\n", oahwnd
);
2233 parent
= GetAncestor(hwnd
, GA_PARENT
);
2234 ok(parent
== GetDesktopWindow(), "Got parent %p.\n", parent
);
2235 style
= GetWindowLongA(hwnd
, GWL_STYLE
);
2236 ok(!(style
& WS_CHILD
), "Got style %#x.\n", style
);
2238 ok(GetActiveWindow() == hwnd
, "Got active window %p.\n", GetActiveWindow());
2239 top_hwnd
= get_top_window();
2240 ok(top_hwnd
== hwnd
, "Got top window %p.\n", top_hwnd
);
2242 hr
= IVideoWindow_get_Visible(window
, &state
);
2243 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2244 ok(state
== OATRUE
, "Got state %d.\n", state
);
2247 struct notify_message_params
2249 IVideoWindow
*window
;
2254 static DWORD CALLBACK
notify_message_proc(void *arg
)
2256 const struct notify_message_params
*params
= arg
;
2257 HRESULT hr
= IVideoWindow_NotifyOwnerMessage(params
->window
, (OAHWND
)params
->hwnd
, params
->message
, 0, 0);
2258 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2262 static void test_video_window_messages(IVideoWindow
*window
, HWND hwnd
, HWND our_hwnd
)
2264 struct notify_message_params params
;
2272 static UINT drain_tests
[] =
2300 hr
= IVideoWindow_get_MessageDrain(window
, &oahwnd
);
2301 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2302 ok(!oahwnd
, "Got window %#lx.\n", oahwnd
);
2304 hr
= IVideoWindow_put_MessageDrain(window
, (OAHWND
)our_hwnd
);
2305 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2307 hr
= IVideoWindow_get_MessageDrain(window
, &oahwnd
);
2308 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2309 ok(oahwnd
== (OAHWND
)our_hwnd
, "Got window %#lx.\n", oahwnd
);
2311 for (i
= 0; i
< ARRAY_SIZE(drain_tests
); ++i
)
2313 SendMessageA(hwnd
, drain_tests
[i
], 0xdeadbeef, 0);
2314 ret
= PeekMessageA(&msg
, 0, drain_tests
[i
], drain_tests
[i
], PM_REMOVE
);
2315 ok(ret
, "Expected a message.\n");
2316 ok(msg
.hwnd
== our_hwnd
, "Got hwnd %p.\n", msg
.hwnd
);
2317 ok(msg
.message
== drain_tests
[i
], "Got message %#x.\n", msg
.message
);
2318 ok(msg
.wParam
== 0xdeadbeef, "Got wparam %#lx.\n", msg
.wParam
);
2319 ok(!msg
.lParam
, "Got lparam %#lx.\n", msg
.lParam
);
2320 DispatchMessageA(&msg
);
2322 ret
= PeekMessageA(&msg
, 0, drain_tests
[i
], drain_tests
[i
], PM_REMOVE
);
2323 ok(!ret
, "Got unexpected message %#x.\n", msg
.message
);
2326 hr
= IVideoWindow_put_MessageDrain(window
, 0);
2327 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2329 hr
= IVideoWindow_put_Owner(window
, (OAHWND
)our_hwnd
);
2330 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2334 hr
= IVideoWindow_NotifyOwnerMessage(window
, (OAHWND
)our_hwnd
, WM_SYSCOLORCHANGE
, 0, 0);
2335 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2337 ret
= GetQueueStatus(QS_SENDMESSAGE
| QS_POSTMESSAGE
);
2338 ok(!ret
, "Got unexpected status %#x.\n", ret
);
2340 hr
= IVideoWindow_NotifyOwnerMessage(window
, (OAHWND
)our_hwnd
, WM_SETCURSOR
,
2341 (WPARAM
)hwnd
, MAKELONG(HTCLIENT
, WM_MOUSEMOVE
));
2342 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2344 ret
= GetQueueStatus(QS_SENDMESSAGE
| QS_POSTMESSAGE
);
2345 ok(!ret
, "Got unexpected status %#x.\n", ret
);
2347 params
.window
= window
;
2348 params
.hwnd
= our_hwnd
;
2349 params
.message
= WM_SYSCOLORCHANGE
;
2350 thread
= CreateThread(NULL
, 0, notify_message_proc
, ¶ms
, 0, NULL
);
2351 ok(WaitForSingleObject(thread
, 100) == WAIT_TIMEOUT
, "Thread should block.\n");
2352 ret
= GetQueueStatus(QS_SENDMESSAGE
| QS_POSTMESSAGE
);
2353 ok(ret
== ((QS_SENDMESSAGE
<< 16) | QS_SENDMESSAGE
), "Got unexpected status %#x.\n", ret
);
2355 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
2356 ok(!WaitForSingleObject(thread
, 1000), "Wait timed out.\n");
2357 CloseHandle(thread
);
2359 params
.message
= WM_SETCURSOR
;
2360 thread
= CreateThread(NULL
, 0, notify_message_proc
, ¶ms
, 0, NULL
);
2361 ok(!WaitForSingleObject(thread
, 1000), "Thread should not block.\n");
2362 CloseHandle(thread
);
2363 ret
= GetQueueStatus(QS_SENDMESSAGE
| QS_POSTMESSAGE
);
2364 ok(!ret
, "Got unexpected status %#x.\n", ret
);
2366 hr
= IVideoWindow_put_Owner(window
, 0);
2367 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2370 static void test_video_window_autoshow(IVideoWindow
*window
, IFilterGraph2
*graph
, HWND hwnd
)
2372 IMediaControl
*control
;
2376 IFilterGraph2_QueryInterface(graph
, &IID_IMediaControl
, (void **)&control
);
2378 hr
= IVideoWindow_get_AutoShow(window
, &l
);
2379 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2380 ok(l
== OATRUE
, "Got %d.\n", l
);
2382 hr
= IVideoWindow_put_Visible(window
, OAFALSE
);
2383 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2385 hr
= IMediaControl_Pause(control
);
2386 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
2388 hr
= IVideoWindow_get_Visible(window
, &l
);
2389 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2390 todo_wine
ok(l
== OATRUE
, "Got %d.\n", l
);
2392 hr
= IMediaControl_Stop(control
);
2393 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2395 hr
= IVideoWindow_get_Visible(window
, &l
);
2396 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2397 todo_wine
ok(l
== OATRUE
, "Got %d.\n", l
);
2399 hr
= IVideoWindow_put_AutoShow(window
, OAFALSE
);
2400 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2402 hr
= IVideoWindow_put_Visible(window
, OAFALSE
);
2403 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2405 hr
= IMediaControl_Pause(control
);
2406 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
2408 hr
= IVideoWindow_get_Visible(window
, &l
);
2409 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2410 ok(l
== OAFALSE
, "Got %d.\n", l
);
2412 hr
= IMediaControl_Stop(control
);
2413 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2415 IMediaControl_Release(control
);
2418 static void test_video_window(void)
2420 ALLOCATOR_PROPERTIES req_props
= {1, 600 * 400 * 4, 1, 0}, ret_props
;
2421 VIDEOINFOHEADER vih
=
2423 .bmiHeader
.biSize
= sizeof(BITMAPINFOHEADER
),
2424 .bmiHeader
.biBitCount
= 32,
2425 .bmiHeader
.biWidth
= 600,
2426 .bmiHeader
.biHeight
= 400,
2427 .bmiHeader
.biPlanes
= 1,
2428 .bmiHeader
.biCompression
= BI_RGB
,
2430 AM_MEDIA_TYPE req_mt
=
2432 .majortype
= MEDIATYPE_Video
,
2433 .subtype
= MEDIASUBTYPE_RGB32
,
2434 .formattype
= FORMAT_VideoInfo
,
2435 .cbFormat
= sizeof(vih
),
2436 .pbFormat
= (BYTE
*)&vih
,
2438 IFilterGraph2
*graph
= create_graph();
2439 WNDCLASSA window_class
= {0};
2440 struct testfilter source
;
2441 IMemAllocator
*allocator
;
2442 MONITORINFO monitorinfo
;
2443 IMediaControl
*control
;
2444 LONG width
, height
, l
;
2445 IVideoWindow
*window
;
2446 IMemInputPin
*input
;
2447 IBaseFilter
*filter
;
2448 HWND hwnd
, our_hwnd
;
2457 window_class
.lpszClassName
= "wine_test_class";
2458 window_class
.lpfnWndProc
= window_proc
;
2459 RegisterClassA(&window_class
);
2460 our_hwnd
= CreateWindowA("wine_test_class", "test window", WS_VISIBLE
| WS_OVERLAPPEDWINDOW
,
2461 100, 200, 300, 400, NULL
, NULL
, NULL
, NULL
);
2464 filter
= create_vmr9(VMR9Mode_Windowed
);
2467 ok(GetActiveWindow() == our_hwnd
, "Got active window %p.\n", GetActiveWindow());
2469 IBaseFilter_FindPin(filter
, L
"VMR Input0", &pin
);
2470 IPin_QueryInterface(pin
, &IID_IMemInputPin
, (void **)&input
);
2472 hr
= IPin_QueryInterface(pin
, &IID_IOverlay
, (void **)&overlay
);
2473 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2475 hr
= IOverlay_GetWindowHandle(overlay
, &hwnd
);
2476 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2477 if (winetest_debug
> 1) trace("ours %p, theirs %p\n", our_hwnd
, hwnd
);
2478 GetWindowRect(hwnd
, &rect
);
2480 tid
= GetWindowThreadProcessId(hwnd
, NULL
);
2481 ok(tid
== GetCurrentThreadId(), "Expected tid %#x, got %#x.\n", GetCurrentThreadId(), tid
);
2483 hr
= IBaseFilter_QueryInterface(filter
, &IID_IVideoWindow
, (void **)&window
);
2484 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2486 hr
= IVideoWindow_get_Caption(window
, &caption
);
2487 todo_wine
ok(hr
== VFW_E_NOT_CONNECTED
, "Got hr %#x.\n", hr
);
2489 hr
= IVideoWindow_get_WindowStyle(window
, &l
);
2490 todo_wine
ok(hr
== VFW_E_NOT_CONNECTED
, "Got hr %#x.\n", hr
);
2492 hr
= IVideoWindow_get_AutoShow(window
, &l
);
2493 todo_wine
ok(hr
== VFW_E_NOT_CONNECTED
, "Got hr %#x.\n", hr
);
2495 testfilter_init(&source
);
2496 IFilterGraph2_AddFilter(graph
, &source
.filter
.IBaseFilter_iface
, NULL
);
2497 IFilterGraph2_AddFilter(graph
, filter
, NULL
);
2498 IFilterGraph2_QueryInterface(graph
, &IID_IMediaControl
, (void **)&control
);
2499 hr
= IFilterGraph2_ConnectDirect(graph
, &source
.source
.pin
.IPin_iface
, pin
, &req_mt
);
2502 skip("Got E_FAIL when connecting.\n");
2505 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2507 hr
= IMemInputPin_GetAllocator(input
, &allocator
);
2508 todo_wine
ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2511 hr
= IMemAllocator_SetProperties(allocator
, &req_props
, &ret_props
);
2512 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2513 ok(!memcmp(&ret_props
, &req_props
, sizeof(req_props
)), "Properties did not match.\n");
2514 hr
= IMemAllocator_Commit(allocator
);
2515 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2516 IMemAllocator_Release(allocator
);
2519 ok(GetActiveWindow() == our_hwnd
, "Got active window %p.\n", GetActiveWindow());
2521 test_video_window_caption(window
, hwnd
);
2522 test_video_window_style(window
, hwnd
, our_hwnd
);
2523 test_video_window_state(window
, hwnd
, our_hwnd
);
2524 test_video_window_position(window
, hwnd
, our_hwnd
);
2525 test_video_window_autoshow(window
, graph
, hwnd
);
2526 test_video_window_owner(window
, hwnd
, our_hwnd
);
2527 test_video_window_messages(window
, hwnd
, our_hwnd
);
2529 hr
= IVideoWindow_put_FullScreenMode(window
, OATRUE
);
2530 ok(hr
== E_NOTIMPL
, "Got hr %#x.\n", hr
);
2531 hr
= IVideoWindow_get_FullScreenMode(window
, &l
);
2532 ok(hr
== E_NOTIMPL
, "Got hr %#x.\n", hr
);
2534 hr
= IVideoWindow_GetMinIdealImageSize(window
, &width
, &height
);
2535 todo_wine
ok(hr
== VFW_E_WRONG_STATE
, "Got hr %#x.\n", hr
);
2536 hr
= IVideoWindow_GetMaxIdealImageSize(window
, &width
, &height
);
2537 todo_wine
ok(hr
== VFW_E_WRONG_STATE
, "Got hr %#x.\n", hr
);
2539 hr
= IMediaControl_Pause(control
);
2540 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
2542 monitorinfo
.cbSize
= sizeof(monitorinfo
);
2543 GetMonitorInfoW(MonitorFromWindow(hwnd
, MONITOR_DEFAULTTOPRIMARY
), &monitorinfo
);
2545 hr
= IVideoWindow_GetMinIdealImageSize(window
, &width
, &height
);
2546 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2547 todo_wine
ok(width
== 1, "Got width %d.\n", width
);
2548 todo_wine
ok(height
== 1, "Got height %d.\n", height
);
2549 hr
= IVideoWindow_GetMaxIdealImageSize(window
, &width
, &height
);
2550 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2551 todo_wine
ok(width
== monitorinfo
.rcMonitor
.right
+ 1, "Expected width %d, got %d.\n",
2552 monitorinfo
.rcMonitor
.right
+ 1, width
);
2553 todo_wine
ok(height
== monitorinfo
.rcMonitor
.bottom
+ 1, "Expected height %d, got %d.\n",
2554 monitorinfo
.rcMonitor
.bottom
+ 1, height
);
2556 hr
= IMediaControl_Stop(control
);
2557 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2560 IMediaControl_Release(control
);
2561 IFilterGraph2_Release(graph
);
2562 IVideoWindow_Release(window
);
2563 IOverlay_Release(overlay
);
2564 IMemInputPin_Release(input
);
2566 ref
= IBaseFilter_Release(filter
);
2567 ok(!ref
, "Got outstanding refcount %d.\n", ref
);
2568 ref
= IBaseFilter_Release(&source
.filter
.IBaseFilter_iface
);
2569 ok(!ref
, "Got outstanding refcount %d.\n", ref
);
2570 DestroyWindow(our_hwnd
);
2573 static IDirect3DDevice9
*create_device(HWND window
)
2575 D3DPRESENT_PARAMETERS present_parameters
=
2578 .hDeviceWindow
= window
,
2579 .SwapEffect
= D3DSWAPEFFECT_DISCARD
,
2580 .BackBufferWidth
= 640,
2581 .BackBufferHeight
= 480,
2582 .BackBufferFormat
= D3DFMT_A8R8G8B8
,
2584 IDirect3DDevice9
*device
;
2588 d3d
= Direct3DCreate9(D3D_SDK_VERSION
);
2589 ok(!!d3d
, "Failed to create a D3D object.\n");
2591 hr
= IDirect3D9_CreateDevice(d3d
, D3DADAPTER_DEFAULT
, D3DDEVTYPE_HAL
, window
,
2592 D3DCREATE_HARDWARE_VERTEXPROCESSING
, &present_parameters
, &device
);
2593 IDirect3D9_Release(d3d
);
2596 skip("Failed to create a 3D device, hr %#x.\n", hr
);
2602 static void test_allocate_surface_helper(void)
2604 VMR9AllocationInfo info
=
2606 .dwFlags
= VMR9AllocFlag_OffscreenSurface
,
2609 .Format
= D3DFMT_X8R8G8B8
,
2610 .Pool
= D3DPOOL_DEFAULT
,
2612 .szAspectRatio
= {32, 16},
2613 .szNativeSize
= {32, 16},
2615 IBaseFilter
*filter
= create_vmr9(VMR9Mode_Renderless
);
2616 IVMRSurfaceAllocatorNotify9
*notify
;
2617 IDirect3DSurface9
*surfaces
[2] = {};
2618 IDirect3DDevice9
*device
, *device2
;
2619 RECT rect
= {0, 0, 640, 480};
2620 IDirect3DTexture9
*container
;
2621 D3DSURFACE_DESC desc
;
2627 IBaseFilter_QueryInterface(filter
, &IID_IVMRSurfaceAllocatorNotify9
, (void **)¬ify
);
2630 hr
= IVMRSurfaceAllocatorNotify9_AllocateSurfaceHelper(notify
, &info
, &count
, surfaces
);
2631 todo_wine
ok(hr
== E_FAIL
, "Got hr %#x.\n", hr
);
2633 AdjustWindowRect(&rect
, WS_OVERLAPPEDWINDOW
, FALSE
);
2634 window
= CreateWindowA("static", "quartz_test", WS_OVERLAPPEDWINDOW
, 0, 0,
2635 rect
.right
- rect
.left
, rect
.bottom
- rect
.top
, NULL
, NULL
, NULL
, NULL
);
2636 if (!(device
= create_device(window
)))
2639 hr
= IVMRSurfaceAllocatorNotify9_SetD3DDevice(notify
, device
, MonitorFromWindow(window
, MONITOR_DEFAULTTOPRIMARY
));
2640 if (hr
== E_NOINTERFACE
)
2642 win_skip("Direct3D does not support video rendering.\n");
2645 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2647 if (0) /* crashes on Windows */
2649 hr
= IVMRSurfaceAllocatorNotify9_AllocateSurfaceHelper(notify
, NULL
, &count
, surfaces
);
2650 ok(hr
== E_POINTER
, "Got hr %#x.\n", hr
);
2652 hr
= IVMRSurfaceAllocatorNotify9_AllocateSurfaceHelper(notify
, &info
, NULL
, surfaces
);
2653 ok(hr
== E_POINTER
, "Got hr %#x.\n", hr
);
2656 hr
= IVMRSurfaceAllocatorNotify9_AllocateSurfaceHelper(notify
, &info
, &count
, NULL
);
2657 ok(hr
== E_POINTER
, "Got hr %#x.\n", hr
);
2659 hr
= IVMRSurfaceAllocatorNotify9_AllocateSurfaceHelper(notify
, &info
, &count
, surfaces
);
2660 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2661 ok(count
== 2, "Got count %u.\n", count
);
2662 ok(!!surfaces
[0], "Surface 0 was not allocated.\n");
2663 ok(!!surfaces
[1], "Surface 1 was not allocated.\n");
2665 hr
= IDirect3DSurface9_GetDevice(surfaces
[0], &device2
);
2666 ok(hr
== D3D_OK
, "Got hr %#x.\n", hr
);
2667 ok(device2
== device
, "Devices did not match.\n");
2668 IDirect3DDevice9_Release(device2
);
2670 hr
= IDirect3DSurface9_GetContainer(surfaces
[0], &IID_IDirect3DTexture9
, (void **)&container
);
2671 ok(hr
== E_NOINTERFACE
, "Got hr %#x.\n", hr
);
2673 hr
= IDirect3DSurface9_GetDesc(surfaces
[0], &desc
);
2674 ok(hr
== D3D_OK
, "Got hr %#x.\n", hr
);
2675 ok(desc
.Format
== info
.Format
, "Got format %#x.\n", desc
.Format
);
2676 ok(desc
.Type
== D3DRTYPE_SURFACE
, "Got type %u.\n", desc
.Type
);
2677 ok(!desc
.Usage
, "Got usage %#x.\n", desc
.Usage
);
2678 ok(desc
.Pool
== D3DPOOL_DEFAULT
, "Got pool %u.\n", desc
.Pool
);
2679 ok(desc
.MultiSampleType
== D3DMULTISAMPLE_NONE
, "Got multisample type %u.\n", desc
.MultiSampleType
);
2680 ok(!desc
.MultiSampleQuality
, "Got multisample quality %u.\n", desc
.MultiSampleQuality
);
2681 ok(desc
.Width
== 32, "Got width %u.\n", desc
.Width
);
2682 ok(desc
.Height
== 16, "Got height %u.\n", desc
.Height
);
2684 IDirect3DSurface9_Release(surfaces
[0]);
2685 IDirect3DSurface9_Release(surfaces
[1]);
2687 surfaces
[0] = surfaces
[1] = NULL
;
2689 hr
= IVMRSurfaceAllocatorNotify9_AllocateSurfaceHelper(notify
, &info
, &count
, surfaces
);
2690 todo_wine
ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2691 todo_wine
ok(!count
, "Got count %u.\n", count
);
2692 ok(!surfaces
[0], "Surface 0 was allocated.\n");
2693 ok(!surfaces
[1], "Surface 1 was allocated.\n");
2696 info
.MinBuffers
= 1;
2697 hr
= IVMRSurfaceAllocatorNotify9_AllocateSurfaceHelper(notify
, &info
, &count
, surfaces
);
2698 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2699 ok(count
== 2, "Got count %u.\n", count
);
2700 ok(!!surfaces
[0], "Surface 0 was not allocated.\n");
2701 ok(!!surfaces
[1], "Surface 1 was not allocated.\n");
2702 IDirect3DSurface9_Release(surfaces
[0]);
2703 IDirect3DSurface9_Release(surfaces
[1]);
2706 info
.dwFlags
= VMR9AllocFlag_TextureSurface
;
2707 surfaces
[0] = surfaces
[1] = NULL
;
2708 hr
= IVMRSurfaceAllocatorNotify9_AllocateSurfaceHelper(notify
, &info
, &count
, surfaces
);
2709 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2710 ok(count
== 2, "Got count %u.\n", count
);
2711 ok(!!surfaces
[0], "Surface 0 was not allocated.\n");
2712 ok(!!surfaces
[1], "Surface 1 was not allocated.\n");
2714 hr
= IDirect3DSurface9_GetDevice(surfaces
[0], &device2
);
2715 ok(hr
== D3D_OK
, "Got hr %#x.\n", hr
);
2716 ok(device2
== device
, "Devices did not match.\n");
2717 IDirect3DDevice9_Release(device2
);
2719 hr
= IDirect3DSurface9_GetContainer(surfaces
[0], &IID_IDirect3DTexture9
, (void **)&container
);
2720 ok(hr
== D3D_OK
, "Got hr %#x.\n", hr
);
2721 IDirect3DTexture9_Release(container
);
2723 hr
= IDirect3DSurface9_GetDesc(surfaces
[1], &desc
);
2724 ok(hr
== D3D_OK
, "Got hr %#x.\n", hr
);
2725 ok(desc
.Format
== info
.Format
, "Got format %#x.\n", desc
.Format
);
2726 ok(desc
.Type
== D3DRTYPE_SURFACE
, "Got type %u.\n", desc
.Type
);
2727 ok(desc
.Usage
== D3DUSAGE_DYNAMIC
, "Got usage %#x.\n", desc
.Usage
);
2728 ok(desc
.Pool
== D3DPOOL_DEFAULT
, "Got pool %u.\n", desc
.Pool
);
2729 ok(desc
.MultiSampleType
== D3DMULTISAMPLE_NONE
, "Got multisample type %u.\n", desc
.MultiSampleType
);
2730 ok(!desc
.MultiSampleQuality
, "Got multisample quality %u.\n", desc
.MultiSampleQuality
);
2731 ok(desc
.Width
== 32, "Got width %u.\n", desc
.Width
);
2732 ok(desc
.Height
== 16, "Got height %u.\n", desc
.Height
);
2734 IDirect3DSurface9_Release(surfaces
[0]);
2735 IDirect3DSurface9_Release(surfaces
[1]);
2737 info
.Format
= D3DFMT_R8G8B8
;
2738 surfaces
[0] = surfaces
[1] = NULL
;
2739 hr
= IVMRSurfaceAllocatorNotify9_AllocateSurfaceHelper(notify
, &info
, &count
, surfaces
);
2740 ok(hr
== D3DERR_INVALIDCALL
, "Got hr %#x.\n", hr
);
2741 ok(!count
, "Got count %u.\n", count
);
2742 ok(!surfaces
[0], "Surface 0 was allocated.\n");
2743 ok(!surfaces
[1], "Surface 1 was allocated.\n");
2746 info
.dwFlags
= VMR9AllocFlag_3DRenderTarget
;
2748 hr
= IVMRSurfaceAllocatorNotify9_AllocateSurfaceHelper(notify
, &info
, &count
, surfaces
);
2749 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2750 ok(count
== 1, "Got count %u.\n", count
);
2751 ok(!!surfaces
[0], "Surface 0 was not allocated.\n");
2752 ok(info
.Format
!= 0, "Expected a format.\n");
2754 hr
= IDirect3DSurface9_GetDesc(surfaces
[0], &desc
);
2755 ok(hr
== D3D_OK
, "Got hr %#x.\n", hr
);
2756 ok(desc
.Format
== info
.Format
, "Expected format %#x, got %#x.\n", info
.Format
, desc
.Format
);
2757 ok(desc
.Type
== D3DRTYPE_SURFACE
, "Got type %u.\n", desc
.Type
);
2758 ok(desc
.Usage
== D3DUSAGE_RENDERTARGET
, "Got usage %#x.\n", desc
.Usage
);
2759 ok(desc
.Pool
== D3DPOOL_DEFAULT
, "Got pool %u.\n", desc
.Pool
);
2760 ok(desc
.MultiSampleType
== D3DMULTISAMPLE_NONE
, "Got multisample type %u.\n", desc
.MultiSampleType
);
2761 ok(!desc
.MultiSampleQuality
, "Got multisample quality %u.\n", desc
.MultiSampleQuality
);
2762 ok(desc
.Width
== 32, "Got width %u.\n", desc
.Width
);
2763 ok(desc
.Height
== 16, "Got height %u.\n", desc
.Height
);
2765 IDirect3DSurface9_Release(surfaces
[0]);
2768 IVMRSurfaceAllocatorNotify9_Release(notify
);
2769 ref
= IBaseFilter_Release(filter
);
2770 ok(!ref
, "Got outstanding refcount %d.\n", ref
);
2771 ref
= IDirect3DDevice9_Release(device
);
2772 ok(!ref
, "Got outstanding refcount %d.\n", ref
);
2773 DestroyWindow(window
);
2776 static IVMRSurfaceAllocator9 allocator_iface
;
2777 static IVMRImagePresenter9 presenter_iface
;
2778 static LONG allocator_refcount
= 1;
2779 static D3DFORMAT allocator_format
;
2780 static DWORD allocator_accept_flags
;
2781 static IDirect3DSurface9
*allocator_surfaces
[5];
2782 static IVMRSurfaceAllocatorNotify9
*allocator_notify
;
2783 static unsigned int allocator_got_PresentImage
, allocator_got_TerminateDevice
;
2785 static HRESULT WINAPI
presenter_QueryInterface(IVMRImagePresenter9
*iface
, REFIID iid
, void **out
)
2787 return IVMRSurfaceAllocator9_QueryInterface(&allocator_iface
, iid
, out
);
2790 static ULONG WINAPI
presenter_AddRef(IVMRImagePresenter9
*iface
)
2792 return IVMRSurfaceAllocator9_AddRef(&allocator_iface
);
2795 static ULONG WINAPI
presenter_Release(IVMRImagePresenter9
*iface
)
2797 return IVMRSurfaceAllocator9_Release(&allocator_iface
);
2800 static HRESULT WINAPI
presenter_StartPresenting(IVMRImagePresenter9
*iface
, DWORD_PTR cookie
)
2802 if (winetest_debug
> 1) trace("StartPresenting()\n");
2803 ok(cookie
== 0xabacab, "Got cookie %#lx.\n", cookie
);
2807 static HRESULT WINAPI
presenter_StopPresenting(IVMRImagePresenter9
*iface
, DWORD_PTR cookie
)
2809 if (winetest_debug
> 1) trace("StopPresenting()\n");
2810 ok(cookie
== 0xabacab, "Got cookie %#lx.\n", cookie
);
2814 static HRESULT WINAPI
presenter_PresentImage(IVMRImagePresenter9
*iface
, DWORD_PTR cookie
, VMR9PresentationInfo
*info
)
2816 static const RECT rect
;
2817 if (winetest_debug
> 1) trace("PresentImage()\n");
2818 ok(cookie
== 0xabacab, "Got cookie %#lx.\n", cookie
);
2819 todo_wine
ok(info
->dwFlags
== VMR9Sample_TimeValid
, "Got flags %#x.\n", info
->dwFlags
);
2820 ok(!info
->rtStart
, "Got start time %s.\n", wine_dbgstr_longlong(info
->rtStart
));
2821 ok(info
->rtEnd
== 10000000, "Got end time %s.\n", wine_dbgstr_longlong(info
->rtEnd
));
2822 todo_wine
ok(info
->szAspectRatio
.cx
== 120, "Got aspect ratio width %d.\n", info
->szAspectRatio
.cx
);
2823 todo_wine
ok(info
->szAspectRatio
.cy
== 60, "Got aspect ratio height %d.\n", info
->szAspectRatio
.cy
);
2824 ok(EqualRect(&info
->rcSrc
, &rect
), "Got source rect %s.\n", wine_dbgstr_rect(&info
->rcSrc
));
2825 ok(EqualRect(&info
->rcDst
, &rect
), "Got dest rect %s.\n", wine_dbgstr_rect(&info
->rcDst
));
2826 ok(!info
->dwReserved1
, "Got dwReserved1 %#x.\n", info
->dwReserved1
);
2827 ok(!info
->dwReserved2
, "Got dwReserved2 %#x.\n", info
->dwReserved2
);
2829 ++allocator_got_PresentImage
;
2833 static const IVMRImagePresenter9Vtbl presenter_vtbl
=
2835 presenter_QueryInterface
,
2838 presenter_StartPresenting
,
2839 presenter_StopPresenting
,
2840 presenter_PresentImage
,
2843 static HRESULT WINAPI
allocator_QueryInterface(IVMRSurfaceAllocator9
*iface
, REFIID iid
, void **out
)
2845 if (winetest_debug
> 1) trace("QueryInterface(%s)\n", wine_dbgstr_guid(iid
));
2847 if (IsEqualGUID(iid
, &IID_IVMRImagePresenter9
))
2849 *out
= &presenter_iface
;
2850 IVMRImagePresenter9_AddRef(&presenter_iface
);
2857 static ULONG WINAPI
allocator_AddRef(IVMRSurfaceAllocator9
*iface
)
2859 return InterlockedIncrement(&allocator_refcount
);
2862 static ULONG WINAPI
allocator_Release(IVMRSurfaceAllocator9
*iface
)
2864 return InterlockedDecrement(&allocator_refcount
);
2867 static HRESULT WINAPI
allocator_InitializeDevice(IVMRSurfaceAllocator9
*iface
,
2868 DWORD_PTR cookie
, VMR9AllocationInfo
*info
, DWORD
*buffer_count
)
2870 if (winetest_debug
> 1) trace("InitializeDevice(flags %#x, format %u)\n",
2871 info
->dwFlags
, info
->Format
);
2872 ok(cookie
== 0xabacab, "Got cookie %#lx.\n", cookie
);
2873 ok(info
->dwWidth
== 32, "Got width %u.\n", info
->dwWidth
);
2874 ok(info
->dwHeight
== 16, "Got height %u.\n", info
->dwHeight
);
2875 todo_wine
ok(info
->MinBuffers
== 5, "Got buffer count %u.\n", info
->MinBuffers
);
2876 ok(info
->Pool
== D3DPOOL_DEFAULT
, "Got pool %u\n", info
->Pool
);
2877 todo_wine
ok(info
->szAspectRatio
.cx
== 120, "Got aspect ratio width %d.\n", info
->szAspectRatio
.cx
);
2878 todo_wine
ok(info
->szAspectRatio
.cy
== 60, "Got aspect ratio height %d.\n", info
->szAspectRatio
.cy
);
2879 ok(info
->szNativeSize
.cx
== 32, "Got native width %d.\n", info
->szNativeSize
.cx
);
2880 ok(info
->szNativeSize
.cy
== 16, "Got native height %d.\n", info
->szNativeSize
.cy
);
2881 todo_wine
ok(*buffer_count
== 5, "Got buffer count %u.\n", *buffer_count
);
2883 allocator_format
= info
->Format
;
2885 if (info
->dwFlags
!= allocator_accept_flags
)
2887 return IVMRSurfaceAllocatorNotify9_AllocateSurfaceHelper(allocator_notify
,
2888 info
, buffer_count
, allocator_surfaces
);
2891 static HRESULT WINAPI
allocator_TerminateDevice(IVMRSurfaceAllocator9
*iface
, DWORD_PTR cookie
)
2893 if (winetest_debug
> 1) trace("TerminateDevice()\n");
2894 ok(cookie
== 0xabacab, "Got cookie %#lx.\n", cookie
);
2895 /* Don't dereference the surfaces here, to mimic How to Survive. */
2896 ++allocator_got_TerminateDevice
;
2900 static HRESULT WINAPI
allocator_GetSurface(IVMRSurfaceAllocator9
*iface
,
2901 DWORD_PTR cookie
, DWORD index
, DWORD flags
, IDirect3DSurface9
**surface
)
2903 if (winetest_debug
> 1) trace("GetSurface(index %u)\n", index
);
2904 ok(cookie
== 0xabacab, "Got cookie %#lx.\n", cookie
);
2905 ok(!flags
, "Got flags %#x.\n", flags
);
2906 ok(index
< 5, "Got index %u.\n", index
);
2908 /* Don't reference the surface here, to mimic How to Survive. */
2909 *surface
= allocator_surfaces
[index
];
2913 static HRESULT WINAPI
allocator_AdviseNotify(IVMRSurfaceAllocator9
*iface
, IVMRSurfaceAllocatorNotify9
*notify
)
2915 ok(0, "Unexpected call.\n");
2919 static const IVMRSurfaceAllocator9Vtbl allocator_vtbl
=
2921 allocator_QueryInterface
,
2924 allocator_InitializeDevice
,
2925 allocator_TerminateDevice
,
2926 allocator_GetSurface
,
2927 allocator_AdviseNotify
,
2930 static IVMRSurfaceAllocator9 allocator_iface
= {&allocator_vtbl
};
2931 static IVMRImagePresenter9 presenter_iface
= {&presenter_vtbl
};
2933 static void test_renderless_present(IFilterGraph2
*graph
, IMemInputPin
*input
)
2935 IMediaControl
*control
;
2936 OAFilterState state
;
2940 IFilterGraph2_QueryInterface(graph
, &IID_IMediaControl
, (void **)&control
);
2942 allocator_got_PresentImage
= 0;
2944 hr
= IMediaControl_Pause(control
);
2945 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
2946 thread
= send_frame(input
);
2947 hr
= IMediaControl_GetState(control
, 1000, &state
);
2948 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2950 hr
= IMediaControl_Run(control
);
2951 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2952 hr
= join_thread(thread
);
2953 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2954 ok(allocator_got_PresentImage
== 1, "Got %u calls to PresentImage().\n", allocator_got_PresentImage
);
2956 hr
= IMediaControl_Stop(control
);
2957 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2959 IMediaControl_Release(control
);
2962 static void test_renderless_formats(void)
2964 VIDEOINFOHEADER vih
=
2966 .rcSource
= {4, 6, 16, 12},
2967 .rcTarget
= {40, 60, 160, 120},
2968 .bmiHeader
.biSize
= sizeof(BITMAPINFOHEADER
),
2969 .bmiHeader
.biWidth
= 32,
2970 .bmiHeader
.biHeight
= 16,
2972 AM_MEDIA_TYPE req_mt
=
2974 .majortype
= MEDIATYPE_Video
,
2975 .formattype
= FORMAT_VideoInfo
,
2976 .cbFormat
= sizeof(vih
),
2977 .pbFormat
= (BYTE
*)&vih
,
2979 ALLOCATOR_PROPERTIES req_props
= {5, 32 * 16 * 4, 1, 0}, ret_props
;
2980 IBaseFilter
*filter
= create_vmr9(VMR9Mode_Renderless
);
2981 IFilterGraph2
*graph
= create_graph();
2982 IVMRSurfaceAllocatorNotify9
*notify
;
2983 RECT rect
= {0, 0, 640, 480};
2984 struct testfilter source
;
2985 IDirect3DDevice9
*device
;
2986 IMemAllocator
*allocator
;
2987 IMemInputPin
*input
;
2996 const GUID
*subtype
;
3002 {&MEDIASUBTYPE_ARGB1555
, D3DFMT_A1R5G5B5
, VMR9AllocFlag_TextureSurface
},
3003 {&MEDIASUBTYPE_ARGB32
, D3DFMT_A8R8G8B8
, VMR9AllocFlag_TextureSurface
},
3004 {&MEDIASUBTYPE_ARGB4444
, D3DFMT_A4R4G4B4
, VMR9AllocFlag_TextureSurface
},
3006 {&MEDIASUBTYPE_RGB555
, D3DFMT_X1R5G5B5
, VMR9AllocFlag_OffscreenSurface
},
3007 {&MEDIASUBTYPE_RGB555
, D3DFMT_X1R5G5B5
, VMR9AllocFlag_TextureSurface
},
3008 {&MEDIASUBTYPE_RGB565
, D3DFMT_R5G6B5
, VMR9AllocFlag_OffscreenSurface
},
3009 {&MEDIASUBTYPE_RGB565
, D3DFMT_R5G6B5
, VMR9AllocFlag_TextureSurface
},
3010 {&MEDIASUBTYPE_RGB24
, D3DFMT_R8G8B8
, VMR9AllocFlag_OffscreenSurface
},
3011 {&MEDIASUBTYPE_RGB24
, D3DFMT_R8G8B8
, VMR9AllocFlag_TextureSurface
},
3012 {&MEDIASUBTYPE_RGB32
, D3DFMT_X8R8G8B8
, VMR9AllocFlag_OffscreenSurface
},
3013 {&MEDIASUBTYPE_RGB32
, D3DFMT_X8R8G8B8
, VMR9AllocFlag_TextureSurface
},
3015 {&MEDIASUBTYPE_NV12
, MAKEFOURCC('N','V','1','2'), VMR9AllocFlag_OffscreenSurface
},
3016 {&MEDIASUBTYPE_UYVY
, D3DFMT_UYVY
, VMR9AllocFlag_OffscreenSurface
},
3017 {&MEDIASUBTYPE_YUY2
, D3DFMT_YUY2
, VMR9AllocFlag_OffscreenSurface
},
3018 {&MEDIASUBTYPE_YV12
, MAKEFOURCC('Y','V','1','2'), VMR9AllocFlag_OffscreenSurface
},
3021 IBaseFilter_QueryInterface(filter
, &IID_IVMRSurfaceAllocatorNotify9
, (void **)¬ify
);
3023 AdjustWindowRect(&rect
, WS_OVERLAPPEDWINDOW
, FALSE
);
3024 window
= CreateWindowA("static", "quartz_test", WS_OVERLAPPEDWINDOW
, 0, 0,
3025 rect
.right
- rect
.left
, rect
.bottom
- rect
.top
, NULL
, NULL
, NULL
, NULL
);
3026 if (!(device
= create_device(window
)))
3029 hr
= IVMRSurfaceAllocatorNotify9_SetD3DDevice(notify
, device
, MonitorFromWindow(window
, MONITOR_DEFAULTTOPRIMARY
));
3030 if (hr
== E_NOINTERFACE
)
3032 win_skip("Direct3D does not support video rendering.\n");
3035 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
3037 hr
= IVMRSurfaceAllocatorNotify9_AdviseSurfaceAllocator(notify
, 0xabacab, &allocator_iface
);
3038 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
3040 allocator_notify
= notify
;
3042 testfilter_init(&source
);
3043 IFilterGraph2_AddFilter(graph
, &source
.filter
.IBaseFilter_iface
, NULL
);
3044 IFilterGraph2_AddFilter(graph
, filter
, NULL
);
3045 IBaseFilter_FindPin(filter
, L
"VMR Input0", &pin
);
3046 IPin_QueryInterface(pin
, &IID_IMemInputPin
, (void **)&input
);
3048 for (i
= 0; i
< ARRAY_SIZE(tests
); ++i
)
3050 req_mt
.subtype
= *tests
[i
].subtype
;
3051 allocator_accept_flags
= tests
[i
].flags
;
3053 hr
= IFilterGraph2_ConnectDirect(graph
, &source
.source
.pin
.IPin_iface
, pin
, &req_mt
);
3054 /* Connection never fails on Native, but Wine currently creates D3D
3055 * surfaces during IPin::ReceiveConnection() instead of
3056 * IMemAllocator::SetProperties(), so let that fail here for now. */
3059 skip("Format %u (%#x), flags %#x are not supported, hr %#x.\n",
3060 tests
[i
].format
, tests
[i
].format
, tests
[i
].flags
, hr
);
3063 ok(hr
== S_OK
, "Test %u: Got hr %#x.\n", i
, hr
);
3065 hr
= IMemInputPin_GetAllocator(input
, &allocator
);
3066 todo_wine_if (i
== 0) ok(hr
== S_OK
, "Test %u: Got hr %#x.\n", i
, hr
);
3069 test_allocator(input
);
3070 hr
= IMemInputPin_GetAllocator(input
, &allocator
);
3073 hr
= IMemAllocator_SetProperties(allocator
, &req_props
, &ret_props
);
3076 skip("Format %u (%#x), flags %#x are not supported, hr %#x.\n",
3077 tests
[i
].format
, tests
[i
].format
, tests
[i
].flags
, hr
);
3078 IMemAllocator_Release(allocator
);
3079 hr
= IFilterGraph2_Disconnect(graph
, &source
.source
.pin
.IPin_iface
);
3080 ok(hr
== S_OK
, "Test %u: Got hr %#x.\n", i
, hr
);
3081 hr
= IFilterGraph2_Disconnect(graph
, pin
);
3082 ok(hr
== S_OK
, "Test %u: Got hr %#x.\n", i
, hr
);
3085 ok(!memcmp(&ret_props
, &req_props
, sizeof(req_props
)), "Properties did not match.\n");
3086 hr
= IMemAllocator_Commit(allocator
);
3087 ok(hr
== S_OK
, "Test %u: Got hr %#x.\n", i
, hr
);
3089 ok(allocator_format
== tests
[i
].format
, "Test %u: Got format %u (%#x).\n",
3090 i
, allocator_format
, allocator_format
);
3092 test_renderless_present(graph
, input
);
3094 hr
= IMemAllocator_Decommit(allocator
);
3095 ok(hr
== S_OK
, "Test %u: Got hr %#x.\n", i
, hr
);
3096 IMemAllocator_Release(allocator
);
3098 hr
= IFilterGraph2_Disconnect(graph
, &source
.source
.pin
.IPin_iface
);
3099 ok(hr
== S_OK
, "Test %u: Got hr %#x.\n", i
, hr
);
3100 hr
= IFilterGraph2_Disconnect(graph
, pin
);
3101 ok(hr
== S_OK
, "Test %u: Got hr %#x.\n", i
, hr
);
3104 ref
= IFilterGraph2_Release(graph
);
3105 ok(!ref
, "Got outstanding refcount %d.\n", ref
);
3106 IMemInputPin_Release(input
);
3110 IVMRSurfaceAllocatorNotify9_Release(notify
);
3111 ref
= IBaseFilter_Release(filter
);
3112 ok(!ref
, "Got outstanding refcount %d.\n", ref
);
3113 ok(allocator_refcount
== 1, "Got outstanding refcount %d.\n", allocator_refcount
);
3114 ref
= IDirect3DDevice9_Release(device
);
3115 ok(!ref
, "Got outstanding refcount %d.\n", ref
);
3116 DestroyWindow(window
);
3119 static void test_mixing_mode(void)
3121 IVMRWindowlessControl9
*windowless_control
;
3122 IVMRMixerControl9
*mixer_control
;
3123 IVMRFilterConfig9
*config
;
3124 DWORD stream_count
= 0;
3125 IBaseFilter
*filter
;
3131 static const VMR9Mode modes
[] =
3135 VMR9Mode_Windowless
,
3136 VMR9Mode_Renderless
,
3139 for (i
= 0; i
< ARRAY_SIZE(modes
); ++i
)
3141 filter
= create_vmr9(modes
[i
]);
3142 IBaseFilter_QueryInterface(filter
, &IID_IVMRFilterConfig9
, (void **)&config
);
3144 hr
= IBaseFilter_QueryInterface(filter
, &IID_IVMRMixerControl9
, (void **)&mixer_control
);
3145 ok(hr
== E_NOINTERFACE
, "Got hr %#x.\n", hr
);
3147 hr
= IVMRFilterConfig9_GetNumberOfStreams(config
, &stream_count
);
3148 todo_wine
ok(hr
== VFW_E_VMR_NOT_IN_MIXER_MODE
, "Got hr %#x.\n", hr
);
3150 hr
= IVMRFilterConfig9_SetNumberOfStreams(config
, 1);
3151 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
3153 hr
= IVMRFilterConfig9_GetNumberOfStreams(config
, &stream_count
);
3154 todo_wine
ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
3155 todo_wine
ok(stream_count
== 1, "Got %u streams.\n", stream_count
);
3157 hr
= IBaseFilter_QueryInterface(filter
, &IID_IVMRMixerControl9
, (void **)&mixer_control
);
3158 todo_wine
ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
3160 IVMRMixerControl9_Release(mixer_control
);
3162 hr
= IVMRFilterConfig9_SetNumberOfStreams(config
, 2);
3163 todo_wine
ok(hr
== VFW_E_WRONG_STATE
, "Got hr %#x.\n", hr
);
3165 hr
= IVMRFilterConfig9_GetNumberOfStreams(config
, &stream_count
);
3166 todo_wine
ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
3167 todo_wine
ok(stream_count
== 1, "Got %u streams.\n", stream_count
);
3169 IVMRFilterConfig9_Release(config
);
3170 ref
= IBaseFilter_Release(filter
);
3171 ok(!ref
, "Got outstanding refcount %d.\n", ref
);
3174 filter
= create_vmr9(VMR9Mode_Windowless
);
3175 IBaseFilter_QueryInterface(filter
, &IID_IVMRFilterConfig9
, (void **)&config
);
3176 IBaseFilter_QueryInterface(filter
, &IID_IVMRWindowlessControl9
, (void **)&windowless_control
);
3178 window
= CreateWindowA("static", "quartz_test", WS_OVERLAPPEDWINDOW
, 0, 0, 640, 480, 0, 0, 0, 0);
3179 ok(!!window
, "Failed to create a window.\n");
3180 hr
= IVMRWindowlessControl9_SetVideoClippingWindow(windowless_control
, window
);
3181 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
3183 hr
= IVMRFilterConfig9_GetNumberOfStreams(config
, &stream_count
);
3184 todo_wine
ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
3185 todo_wine
ok(stream_count
== 4, "Got %u streams.\n", stream_count
);
3187 hr
= IBaseFilter_QueryInterface(filter
, &IID_IVMRMixerControl9
, (void **)&mixer_control
);
3188 todo_wine
ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
3190 IVMRMixerControl9_Release(mixer_control
);
3192 hr
= IVMRFilterConfig9_SetNumberOfStreams(config
, 2);
3193 todo_wine
ok(hr
== VFW_E_WRONG_STATE
, "Got hr %#x.\n", hr
);
3195 hr
= IVMRFilterConfig9_GetNumberOfStreams(config
, &stream_count
);
3196 todo_wine
ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
3197 todo_wine
ok(stream_count
== 4, "Got %u streams.\n", stream_count
);
3199 IVMRWindowlessControl9_Release(windowless_control
);
3200 IVMRFilterConfig9_Release(config
);
3201 ref
= IBaseFilter_Release(filter
);
3202 ok(!ref
, "Got outstanding refcount %d.\n", ref
);
3203 DestroyWindow(window
);
3206 static void test_clipping_window(void)
3208 VIDEOINFOHEADER vih
=
3210 .bmiHeader
.biSize
= sizeof(BITMAPINFOHEADER
),
3211 .bmiHeader
.biWidth
= 32,
3212 .bmiHeader
.biHeight
= 16,
3213 .bmiHeader
.biBitCount
= 32,
3217 .majortype
= MEDIATYPE_Video
,
3218 .subtype
= MEDIASUBTYPE_RGB32
,
3219 .formattype
= FORMAT_VideoInfo
,
3220 .cbFormat
= sizeof(vih
),
3221 .pbFormat
= (BYTE
*)&vih
,
3223 IBaseFilter
*filter
= create_vmr9(VMR9Mode_Windowless
);
3224 IVMRWindowlessControl9
*windowless_control
;
3225 IFilterGraph2
*graph
= create_graph();
3226 struct testfilter source
;
3232 IBaseFilter_QueryInterface(filter
, &IID_IVMRWindowlessControl9
, (void **)&windowless_control
);
3233 IBaseFilter_FindPin(filter
, L
"VMR Input0", &pin
);
3234 testfilter_init(&source
);
3235 IFilterGraph2_AddFilter(graph
, &source
.filter
.IBaseFilter_iface
, L
"source");
3236 IFilterGraph2_AddFilter(graph
, filter
, L
"vmr9");
3237 window
= CreateWindowA("static", "quartz_test", WS_OVERLAPPEDWINDOW
, 0, 0, 640, 480, 0, 0, 0, 0);
3238 ok(!!window
, "Failed to create a window.\n");
3240 hr
= IVMRWindowlessControl9_SetVideoClippingWindow(windowless_control
, NULL
);
3241 ok(hr
== E_INVALIDARG
, "Got hr %#x.\n", hr
);
3242 hr
= IVMRWindowlessControl9_SetVideoClippingWindow(windowless_control
, (HWND
)0xdeadbeef);
3243 ok(hr
== E_INVALIDARG
, "Got hr %#x.\n", hr
);
3245 hr
= IFilterGraph2_ConnectDirect(graph
, &source
.source
.pin
.IPin_iface
, pin
, &mt
);
3246 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
3248 hr
= IVMRWindowlessControl9_SetVideoClippingWindow(windowless_control
, window
);
3249 ok(hr
== VFW_E_WRONG_STATE
, "Got hr %#x.\n", hr
);
3251 hr
= IFilterGraph2_Disconnect(graph
, &source
.source
.pin
.IPin_iface
);
3252 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
3253 hr
= IFilterGraph2_Disconnect(graph
, pin
);
3254 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
3256 hr
= IVMRWindowlessControl9_SetVideoClippingWindow(windowless_control
, window
);
3257 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
3259 ref
= IFilterGraph2_Release(graph
);
3260 ok(!ref
, "Got outstanding refcount %d.\n", ref
);
3262 IVMRWindowlessControl9_Release(windowless_control
);
3263 ref
= IBaseFilter_Release(filter
);
3264 ok(!ref
, "Got outstanding refcount %d.\n", ref
);
3265 DestroyWindow(window
);
3268 static void test_surface_allocator_notify_refcount(void)
3270 IBaseFilter
*filter
= create_vmr9(VMR9Mode_Renderless
);
3271 IVMRSurfaceAllocatorNotify9
*notify
;
3275 allocator_got_TerminateDevice
= 0;
3277 set_mixing_mode(filter
, 2);
3279 IBaseFilter_QueryInterface(filter
, &IID_IVMRSurfaceAllocatorNotify9
, (void **)¬ify
);
3281 hr
= IVMRSurfaceAllocatorNotify9_AdviseSurfaceAllocator(notify
, 0xabacab, &allocator_iface
);
3282 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
3284 ref
= IBaseFilter_Release(filter
);
3285 ok(!ref
, "Got outstanding refcount %d.\n", ref
);
3286 ok(allocator_got_TerminateDevice
== 1, "Got %u calls to TerminateDevice().\n",
3287 allocator_got_TerminateDevice
);
3288 ok(allocator_refcount
== 1, "Got outstanding refcount %d.\n", allocator_refcount
);
3290 ref
= IVMRSurfaceAllocatorNotify9_Release(notify
);
3291 ok(!ref
, "Got outstanding refcount %d.\n", ref
);
3294 static void check_source_position_(int line
, IBasicVideo
*video
,
3295 LONG expect_left
, LONG expect_top
, LONG expect_width
, LONG expect_height
)
3297 LONG left
, top
, width
, height
, l
;
3300 left
= top
= width
= height
= 0xdeadbeef;
3301 hr
= IBasicVideo_GetSourcePosition(video
, &left
, &top
, &width
, &height
);
3302 ok_(__FILE__
,line
)(hr
== S_OK
, "Got hr %#x.\n", hr
);
3303 ok_(__FILE__
,line
)(left
== expect_left
, "Got left %d.\n", left
);
3304 ok_(__FILE__
,line
)(top
== expect_top
, "Got top %d.\n", top
);
3305 ok_(__FILE__
,line
)(width
== expect_width
, "Got width %d.\n", width
);
3306 ok_(__FILE__
,line
)(height
== expect_height
, "Got height %d.\n", height
);
3309 hr
= IBasicVideo_get_SourceLeft(video
, &l
);
3310 ok_(__FILE__
,line
)(hr
== S_OK
, "Failed to get left, hr %#x.\n", hr
);
3311 ok_(__FILE__
,line
)(l
== left
, "Got left %d.\n", l
);
3314 hr
= IBasicVideo_get_SourceTop(video
, &l
);
3315 ok_(__FILE__
,line
)(hr
== S_OK
, "Failed to get top, hr %#x.\n", hr
);
3316 ok_(__FILE__
,line
)(l
== top
, "Got top %d.\n", l
);
3319 hr
= IBasicVideo_get_SourceWidth(video
, &l
);
3320 ok_(__FILE__
,line
)(hr
== S_OK
, "Failed to get width, hr %#x.\n", hr
);
3321 ok_(__FILE__
,line
)(l
== width
, "Got width %d.\n", l
);
3324 hr
= IBasicVideo_get_SourceHeight(video
, &l
);
3325 ok_(__FILE__
,line
)(hr
== S_OK
, "Failed to get height, hr %#x.\n", hr
);
3326 ok_(__FILE__
,line
)(l
== height
, "Got height %d.\n", l
);
3328 #define check_source_position(a,b,c,d,e) check_source_position_(__LINE__,a,b,c,d,e)
3330 static void test_basic_video_source(IBasicVideo
*video
)
3334 check_source_position(video
, 0, 0, 600, 400);
3335 hr
= IBasicVideo_IsUsingDefaultSource(video
);
3336 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
3338 hr
= IBasicVideo_put_SourceLeft(video
, -10);
3339 ok(hr
== E_INVALIDARG
, "Got hr %#x.\n", hr
);
3340 hr
= IBasicVideo_put_SourceLeft(video
, 10);
3341 ok(hr
== E_INVALIDARG
, "Got hr %#x.\n", hr
);
3343 hr
= IBasicVideo_put_SourceTop(video
, -10);
3344 ok(hr
== E_INVALIDARG
, "Got hr %#x.\n", hr
);
3345 hr
= IBasicVideo_put_SourceTop(video
, 10);
3346 ok(hr
== E_INVALIDARG
, "Got hr %#x.\n", hr
);
3348 hr
= IBasicVideo_put_SourceWidth(video
, -500);
3349 ok(hr
== E_INVALIDARG
, "Got hr %#x.\n", hr
);
3350 hr
= IBasicVideo_put_SourceWidth(video
, 0);
3351 ok(hr
== E_INVALIDARG
, "Got hr %#x.\n", hr
);
3352 hr
= IBasicVideo_put_SourceWidth(video
, 700);
3353 ok(hr
== E_INVALIDARG
, "Got hr %#x.\n", hr
);
3354 hr
= IBasicVideo_put_SourceWidth(video
, 500);
3355 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
3356 check_source_position(video
, 0, 0, 500, 400);
3357 hr
= IBasicVideo_IsUsingDefaultSource(video
);
3358 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
3360 hr
= IBasicVideo_put_SourceHeight(video
, -300);
3361 ok(hr
== E_INVALIDARG
, "Got hr %#x.\n", hr
);
3362 hr
= IBasicVideo_put_SourceHeight(video
, 0);
3363 ok(hr
== E_INVALIDARG
, "Got hr %#x.\n", hr
);
3364 hr
= IBasicVideo_put_SourceHeight(video
, 600);
3365 ok(hr
== E_INVALIDARG
, "Got hr %#x.\n", hr
);
3366 hr
= IBasicVideo_put_SourceHeight(video
, 300);
3367 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
3368 check_source_position(video
, 0, 0, 500, 300);
3369 hr
= IBasicVideo_IsUsingDefaultSource(video
);
3370 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
3372 hr
= IBasicVideo_put_SourceLeft(video
, -10);
3373 ok(hr
== E_INVALIDARG
, "Got hr %#x.\n", hr
);
3374 hr
= IBasicVideo_put_SourceLeft(video
, 10);
3375 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
3376 check_source_position(video
, 10, 0, 500, 300);
3377 hr
= IBasicVideo_IsUsingDefaultSource(video
);
3378 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
3380 hr
= IBasicVideo_put_SourceTop(video
, -10);
3381 ok(hr
== E_INVALIDARG
, "Got hr %#x.\n", hr
);
3382 hr
= IBasicVideo_put_SourceTop(video
, 20);
3383 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
3384 check_source_position(video
, 10, 20, 500, 300);
3385 hr
= IBasicVideo_IsUsingDefaultSource(video
);
3386 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
3388 hr
= IBasicVideo_SetSourcePosition(video
, 4, 5, 60, 40);
3389 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
3390 check_source_position(video
, 4, 5, 60, 40);
3391 hr
= IBasicVideo_IsUsingDefaultSource(video
);
3392 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
3394 hr
= IBasicVideo_SetSourcePosition(video
, 0, 0, 600, 400);
3395 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
3396 check_source_position(video
, 0, 0, 600, 400);
3397 hr
= IBasicVideo_IsUsingDefaultSource(video
);
3398 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
3400 hr
= IBasicVideo_SetSourcePosition(video
, 4, 5, 60, 40);
3401 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
3402 hr
= IBasicVideo_SetDefaultSourcePosition(video
);
3403 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
3404 check_source_position(video
, 0, 0, 600, 400);
3405 hr
= IBasicVideo_IsUsingDefaultSource(video
);
3406 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
3409 static void check_destination_position_(int line
, IBasicVideo
*video
,
3410 LONG expect_left
, LONG expect_top
, LONG expect_width
, LONG expect_height
)
3412 LONG left
, top
, width
, height
, l
;
3415 left
= top
= width
= height
= 0xdeadbeef;
3416 hr
= IBasicVideo_GetDestinationPosition(video
, &left
, &top
, &width
, &height
);
3417 ok_(__FILE__
,line
)(hr
== S_OK
, "Failed to get position, hr %#x.\n", hr
);
3418 ok_(__FILE__
,line
)(left
== expect_left
, "Got left %d.\n", left
);
3419 ok_(__FILE__
,line
)(top
== expect_top
, "Got top %d.\n", top
);
3420 ok_(__FILE__
,line
)(width
== expect_width
, "Got width %d.\n", width
);
3421 ok_(__FILE__
,line
)(height
== expect_height
, "Got height %d.\n", height
);
3424 hr
= IBasicVideo_get_DestinationLeft(video
, &l
);
3425 ok_(__FILE__
,line
)(hr
== S_OK
, "Failed to get left, hr %#x.\n", hr
);
3426 ok_(__FILE__
,line
)(l
== left
, "Got left %d.\n", l
);
3429 hr
= IBasicVideo_get_DestinationTop(video
, &l
);
3430 ok_(__FILE__
,line
)(hr
== S_OK
, "Failed to get top, hr %#x.\n", hr
);
3431 ok_(__FILE__
,line
)(l
== top
, "Got top %d.\n", l
);
3434 hr
= IBasicVideo_get_DestinationWidth(video
, &l
);
3435 ok_(__FILE__
,line
)(hr
== S_OK
, "Failed to get width, hr %#x.\n", hr
);
3436 ok_(__FILE__
,line
)(l
== width
, "Got width %d.\n", l
);
3439 hr
= IBasicVideo_get_DestinationHeight(video
, &l
);
3440 ok_(__FILE__
,line
)(hr
== S_OK
, "Failed to get height, hr %#x.\n", hr
);
3441 ok_(__FILE__
,line
)(l
== height
, "Got height %d.\n", l
);
3443 #define check_destination_position(a,b,c,d,e) check_destination_position_(__LINE__,a,b,c,d,e)
3445 static void test_basic_video_destination(IBasicVideo
*video
)
3447 IVideoWindow
*window
;
3451 IBasicVideo_QueryInterface(video
, &IID_IVideoWindow
, (void **)&window
);
3453 check_destination_position(video
, 0, 0, 600, 400);
3454 hr
= IBasicVideo_IsUsingDefaultDestination(video
);
3455 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
3457 hr
= IBasicVideo_put_DestinationLeft(video
, -10);
3458 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
3459 check_destination_position(video
, -10, 0, 600, 400);
3460 hr
= IBasicVideo_IsUsingDefaultDestination(video
);
3461 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
3463 hr
= IBasicVideo_put_DestinationLeft(video
, 10);
3464 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
3465 check_destination_position(video
, 10, 0, 600, 400);
3466 hr
= IBasicVideo_IsUsingDefaultDestination(video
);
3467 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
3469 hr
= IBasicVideo_put_DestinationTop(video
, -20);
3470 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
3471 check_destination_position(video
, 10, -20, 600, 400);
3472 hr
= IBasicVideo_IsUsingDefaultDestination(video
);
3473 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
3475 hr
= IBasicVideo_put_DestinationTop(video
, 20);
3476 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
3477 check_destination_position(video
, 10, 20, 600, 400);
3478 hr
= IBasicVideo_IsUsingDefaultDestination(video
);
3479 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
3481 hr
= IBasicVideo_put_DestinationWidth(video
, -700);
3482 ok(hr
== E_INVALIDARG
, "Got hr %#x.\n", hr
);
3483 hr
= IBasicVideo_put_DestinationWidth(video
, 0);
3484 ok(hr
== E_INVALIDARG
, "Got hr %#x.\n", hr
);
3485 hr
= IBasicVideo_put_DestinationWidth(video
, 700);
3486 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
3487 check_destination_position(video
, 10, 20, 700, 400);
3488 hr
= IBasicVideo_IsUsingDefaultDestination(video
);
3489 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
3491 hr
= IBasicVideo_put_DestinationWidth(video
, 500);
3492 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
3493 check_destination_position(video
, 10, 20, 500, 400);
3494 hr
= IBasicVideo_IsUsingDefaultDestination(video
);
3495 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
3497 hr
= IBasicVideo_put_DestinationHeight(video
, -500);
3498 ok(hr
== E_INVALIDARG
, "Got hr %#x.\n", hr
);
3499 hr
= IBasicVideo_put_DestinationHeight(video
, 0);
3500 ok(hr
== E_INVALIDARG
, "Got hr %#x.\n", hr
);
3501 hr
= IBasicVideo_put_DestinationHeight(video
, 500);
3502 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
3503 check_destination_position(video
, 10, 20, 500, 500);
3504 hr
= IBasicVideo_IsUsingDefaultDestination(video
);
3505 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
3507 hr
= IBasicVideo_put_DestinationHeight(video
, 300);
3508 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
3509 check_destination_position(video
, 10, 20, 500, 300);
3510 hr
= IBasicVideo_IsUsingDefaultDestination(video
);
3511 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
3513 hr
= IBasicVideo_SetDestinationPosition(video
, 4, 5, 60, 40);
3514 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
3515 check_destination_position(video
, 4, 5, 60, 40);
3516 hr
= IBasicVideo_IsUsingDefaultDestination(video
);
3517 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
3519 hr
= IBasicVideo_SetDestinationPosition(video
, 0, 0, 600, 400);
3520 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
3521 check_destination_position(video
, 0, 0, 600, 400);
3522 hr
= IBasicVideo_IsUsingDefaultDestination(video
);
3523 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
3525 hr
= IBasicVideo_SetDestinationPosition(video
, 4, 5, 60, 40);
3526 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
3527 hr
= IBasicVideo_SetDefaultDestinationPosition(video
);
3528 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
3529 check_destination_position(video
, 0, 0, 600, 400);
3530 hr
= IBasicVideo_IsUsingDefaultDestination(video
);
3531 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
3533 SetRect(&rect
, 100, 200, 500, 500);
3534 AdjustWindowRect(&rect
, WS_OVERLAPPEDWINDOW
, FALSE
);
3535 hr
= IVideoWindow_SetWindowPosition(window
, rect
.left
, rect
.top
,
3536 rect
.right
- rect
.left
, rect
.bottom
- rect
.top
);
3537 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
3538 check_destination_position(video
, 0, 0, 400, 300);
3539 hr
= IBasicVideo_IsUsingDefaultDestination(video
);
3540 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
3542 hr
= IBasicVideo_SetDestinationPosition(video
, 0, 0, 400, 300);
3543 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
3544 check_destination_position(video
, 0, 0, 400, 300);
3545 hr
= IBasicVideo_IsUsingDefaultDestination(video
);
3546 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
3548 SetRect(&rect
, 100, 200, 600, 600);
3549 AdjustWindowRect(&rect
, WS_OVERLAPPEDWINDOW
, FALSE
);
3550 hr
= IVideoWindow_SetWindowPosition(window
, rect
.left
, rect
.top
,
3551 rect
.right
- rect
.left
, rect
.bottom
- rect
.top
);
3552 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
3553 check_destination_position(video
, 0, 0, 400, 300);
3554 hr
= IBasicVideo_IsUsingDefaultDestination(video
);
3555 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
3557 IVideoWindow_Release(window
);
3560 static void test_basic_video(void)
3562 ALLOCATOR_PROPERTIES req_props
= {1, 600 * 400 * 4, 1, 0}, ret_props
;
3563 VIDEOINFOHEADER vih
=
3565 .AvgTimePerFrame
= 200000,
3566 .rcSource
= {4, 6, 16, 12},
3567 .rcTarget
= {40, 60, 120, 160},
3568 .bmiHeader
.biSize
= sizeof(BITMAPINFOHEADER
),
3569 .bmiHeader
.biBitCount
= 32,
3570 .bmiHeader
.biWidth
= 600,
3571 .bmiHeader
.biHeight
= 400,
3572 .bmiHeader
.biPlanes
= 1,
3573 .bmiHeader
.biCompression
= BI_RGB
,
3575 AM_MEDIA_TYPE req_mt
=
3577 .majortype
= MEDIATYPE_Video
,
3578 .subtype
= MEDIASUBTYPE_RGB32
,
3579 .formattype
= FORMAT_VideoInfo
,
3580 .cbFormat
= sizeof(vih
),
3581 .pbFormat
= (BYTE
*)&vih
,
3583 IBaseFilter
*filter
= create_vmr9(VMR9Mode_Windowed
);
3584 IFilterGraph2
*graph
= create_graph();
3585 LONG left
, top
, width
, height
, l
;
3586 struct testfilter source
;
3587 IMemAllocator
*allocator
;
3588 IMemInputPin
*input
;
3589 ITypeInfo
*typeinfo
;
3598 IBaseFilter_QueryInterface(filter
, &IID_IBasicVideo
, (void **)&video
);
3599 IBaseFilter_FindPin(filter
, L
"VMR Input0", &pin
);
3600 IPin_QueryInterface(pin
, &IID_IMemInputPin
, (void **)&input
);
3602 hr
= IBasicVideo_GetTypeInfoCount(video
, &count
);
3603 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
3604 ok(count
== 1, "Got count %u.\n", count
);
3606 hr
= IBasicVideo_GetTypeInfo(video
, 0, 0, &typeinfo
);
3607 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
3608 hr
= ITypeInfo_GetTypeAttr(typeinfo
, &typeattr
);
3609 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
3610 ok(typeattr
->typekind
== TKIND_DISPATCH
, "Got kind %u.\n", typeattr
->typekind
);
3611 ok(IsEqualGUID(&typeattr
->guid
, &IID_IBasicVideo
), "Got IID %s.\n", wine_dbgstr_guid(&typeattr
->guid
));
3612 ITypeInfo_ReleaseTypeAttr(typeinfo
, typeattr
);
3613 ITypeInfo_Release(typeinfo
);
3615 hr
= IBasicVideo_get_AvgTimePerFrame(video
, NULL
);
3616 ok(hr
== E_POINTER
, "Got hr %#x.\n", hr
);
3617 hr
= IBasicVideo_get_AvgTimePerFrame(video
, &reftime
);
3618 ok(hr
== VFW_E_NOT_CONNECTED
, "Got hr %#x.\n", hr
);
3620 hr
= IBasicVideo_get_BitRate(video
, NULL
);
3621 ok(hr
== E_POINTER
, "Got hr %#x.\n", hr
);
3622 hr
= IBasicVideo_get_BitRate(video
, &l
);
3623 ok(hr
== VFW_E_NOT_CONNECTED
, "Got hr %#x.\n", hr
);
3625 hr
= IBasicVideo_get_BitErrorRate(video
, NULL
);
3626 ok(hr
== E_POINTER
, "Got hr %#x.\n", hr
);
3627 hr
= IBasicVideo_get_BitErrorRate(video
, &l
);
3628 ok(hr
== VFW_E_NOT_CONNECTED
, "Got hr %#x.\n", hr
);
3630 hr
= IBasicVideo_get_VideoWidth(video
, NULL
);
3631 ok(hr
== E_POINTER
, "Got hr %#x.\n", hr
);
3632 hr
= IBasicVideo_get_VideoHeight(video
, NULL
);
3633 ok(hr
== E_POINTER
, "Got hr %#x.\n", hr
);
3635 hr
= IBasicVideo_get_SourceLeft(video
, NULL
);
3636 ok(hr
== E_POINTER
, "Got hr %#x.\n", hr
);
3637 hr
= IBasicVideo_get_SourceWidth(video
, NULL
);
3638 ok(hr
== E_POINTER
, "Got hr %#x.\n", hr
);
3639 hr
= IBasicVideo_get_SourceTop(video
, NULL
);
3640 ok(hr
== E_POINTER
, "Got hr %#x.\n", hr
);
3641 hr
= IBasicVideo_get_SourceHeight(video
, NULL
);
3642 ok(hr
== E_POINTER
, "Got hr %#x.\n", hr
);
3644 hr
= IBasicVideo_get_DestinationLeft(video
, NULL
);
3645 ok(hr
== E_POINTER
, "Got hr %#x.\n", hr
);
3646 hr
= IBasicVideo_get_DestinationWidth(video
, NULL
);
3647 ok(hr
== E_POINTER
, "Got hr %#x.\n", hr
);
3648 hr
= IBasicVideo_get_DestinationTop(video
, NULL
);
3649 ok(hr
== E_POINTER
, "Got hr %#x.\n", hr
);
3650 hr
= IBasicVideo_get_DestinationHeight(video
, NULL
);
3651 ok(hr
== E_POINTER
, "Got hr %#x.\n", hr
);
3653 hr
= IBasicVideo_GetSourcePosition(video
, NULL
, &top
, &width
, &height
);
3654 ok(hr
== E_POINTER
, "Got hr %#x.\n", hr
);
3655 hr
= IBasicVideo_GetSourcePosition(video
, &left
, NULL
, &width
, &height
);
3656 ok(hr
== E_POINTER
, "Got hr %#x.\n", hr
);
3657 hr
= IBasicVideo_GetSourcePosition(video
, &left
, &top
, NULL
, &height
);
3658 ok(hr
== E_POINTER
, "Got hr %#x.\n", hr
);
3659 hr
= IBasicVideo_GetSourcePosition(video
, &left
, &top
, &width
, NULL
);
3660 ok(hr
== E_POINTER
, "Got hr %#x.\n", hr
);
3662 hr
= IBasicVideo_GetDestinationPosition(video
, NULL
, &top
, &width
, &height
);
3663 ok(hr
== E_POINTER
, "Got hr %#x.\n", hr
);
3664 hr
= IBasicVideo_GetDestinationPosition(video
, &left
, NULL
, &width
, &height
);
3665 ok(hr
== E_POINTER
, "Got hr %#x.\n", hr
);
3666 hr
= IBasicVideo_GetDestinationPosition(video
, &left
, &top
, NULL
, &height
);
3667 ok(hr
== E_POINTER
, "Got hr %#x.\n", hr
);
3668 hr
= IBasicVideo_GetDestinationPosition(video
, &left
, &top
, &width
, NULL
);
3669 ok(hr
== E_POINTER
, "Got hr %#x.\n", hr
);
3671 hr
= IBasicVideo_GetVideoSize(video
, &width
, NULL
);
3672 ok(hr
== E_POINTER
, "Got hr %#x.\n", hr
);
3673 hr
= IBasicVideo_GetVideoSize(video
, NULL
, &height
);
3674 ok(hr
== E_POINTER
, "Got hr %#x.\n", hr
);
3676 hr
= IBasicVideo_GetVideoPaletteEntries(video
, 0, 1, NULL
, &l
);
3677 ok(hr
== E_POINTER
, "Got hr %#x.\n", hr
);
3678 hr
= IBasicVideo_GetVideoPaletteEntries(video
, 0, 1, &l
, NULL
);
3679 todo_wine
ok(hr
== VFW_E_NOT_CONNECTED
, "Got hr %#x.\n", hr
);
3681 testfilter_init(&source
);
3682 IFilterGraph2_AddFilter(graph
, &source
.filter
.IBaseFilter_iface
, L
"vmr9");
3683 IFilterGraph2_AddFilter(graph
, filter
, L
"source");
3684 hr
= IFilterGraph2_ConnectDirect(graph
, &source
.source
.pin
.IPin_iface
, pin
, &req_mt
);
3687 skip("Got E_FAIL when connecting.\n");
3690 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
3692 hr
= IMemInputPin_GetAllocator(input
, &allocator
);
3693 todo_wine
ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
3696 hr
= IMemAllocator_SetProperties(allocator
, &req_props
, &ret_props
);
3697 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
3698 ok(!memcmp(&ret_props
, &req_props
, sizeof(req_props
)), "Properties did not match.\n");
3699 hr
= IMemAllocator_Commit(allocator
);
3700 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
3701 IMemAllocator_Release(allocator
);
3705 hr
= IBasicVideo_get_AvgTimePerFrame(video
, &reftime
);
3706 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
3707 todo_wine
ok(compare_double(reftime
, 0.02, 1 << 28), "Got frame rate %.16e.\n", reftime
);
3710 hr
= IBasicVideo_get_BitRate(video
, &l
);
3711 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
3712 ok(!l
, "Got bit rate %d.\n", l
);
3715 hr
= IBasicVideo_get_BitErrorRate(video
, &l
);
3716 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
3717 ok(!l
, "Got bit rate %d.\n", l
);
3719 hr
= IBasicVideo_GetVideoPaletteEntries(video
, 0, 1, &l
, NULL
);
3720 todo_wine
ok(hr
== VFW_E_NO_PALETTE_AVAILABLE
, "Got hr %#x.\n", hr
);
3722 width
= height
= 0xdeadbeef;
3723 hr
= IBasicVideo_GetVideoSize(video
, &width
, &height
);
3724 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
3725 ok(width
== 600, "Got width %d.\n", width
);
3726 ok(height
== 400, "Got height %d.\n", height
);
3728 test_basic_video_source(video
);
3729 test_basic_video_destination(video
);
3732 ref
= IFilterGraph2_Release(graph
);
3733 ok(!ref
, "Got outstanding refcount %d.\n", ref
);
3734 IBasicVideo_Release(video
);
3735 IMemInputPin_Release(input
);
3737 ref
= IBaseFilter_Release(filter
);
3738 ok(!ref
, "Got outstanding refcount %d.\n", ref
);
3739 ref
= IBaseFilter_Release(&source
.filter
.IBaseFilter_iface
);
3740 ok(!ref
, "Got outstanding refcount %d.\n", ref
);
3743 static void test_windowless_size(void)
3745 ALLOCATOR_PROPERTIES req_props
= {1, 32 * 16 * 4, 1, 0}, ret_props
;
3746 VIDEOINFOHEADER vih
=
3748 .bmiHeader
.biSize
= sizeof(BITMAPINFOHEADER
),
3749 .bmiHeader
.biWidth
= 32,
3750 .bmiHeader
.biHeight
= 16,
3751 .bmiHeader
.biBitCount
= 32,
3752 .bmiHeader
.biPlanes
= 1,
3756 .majortype
= MEDIATYPE_Video
,
3757 .subtype
= MEDIASUBTYPE_RGB32
,
3758 .formattype
= FORMAT_VideoInfo
,
3759 .cbFormat
= sizeof(vih
),
3760 .pbFormat
= (BYTE
*)&vih
,
3762 IBaseFilter
*filter
= create_vmr9(VMR9Mode_Windowless
);
3763 LONG width
, height
, aspect_width
, aspect_height
;
3764 IVMRWindowlessControl9
*windowless_control
;
3765 IFilterGraph2
*graph
= create_graph();
3766 struct testfilter source
;
3767 IMemAllocator
*allocator
;
3768 RECT src
, dst
, expect
;
3769 IMemInputPin
*input
;
3775 IBaseFilter_QueryInterface(filter
, &IID_IVMRWindowlessControl9
, (void **)&windowless_control
);
3776 IBaseFilter_FindPin(filter
, L
"VMR Input0", &pin
);
3777 IPin_QueryInterface(pin
, &IID_IMemInputPin
, (void **)&input
);
3778 testfilter_init(&source
);
3779 IFilterGraph2_AddFilter(graph
, &source
.filter
.IBaseFilter_iface
, L
"source");
3780 IFilterGraph2_AddFilter(graph
, filter
, L
"vmr9");
3781 window
= CreateWindowA("static", "quartz_test", WS_OVERLAPPEDWINDOW
, 0, 0, 640, 480, 0, 0, 0, 0);
3782 ok(!!window
, "Failed to create a window.\n");
3784 hr
= IVMRWindowlessControl9_SetVideoClippingWindow(windowless_control
, window
);
3785 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
3787 hr
= IFilterGraph2_ConnectDirect(graph
, &source
.source
.pin
.IPin_iface
, pin
, &mt
);
3788 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
3789 hr
= IMemInputPin_GetAllocator(input
, &allocator
);
3790 todo_wine
ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
3793 hr
= IMemAllocator_SetProperties(allocator
, &req_props
, &ret_props
);
3794 IMemAllocator_Release(allocator
);
3797 skip("Got E_FAIL when setting allocator properties.\n");
3800 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
3801 ok(!memcmp(&ret_props
, &req_props
, sizeof(req_props
)), "Properties did not match.\n");
3804 hr
= IVMRWindowlessControl9_GetNativeVideoSize(windowless_control
, NULL
, &height
, &aspect_width
, &aspect_height
);
3805 ok(hr
== E_POINTER
, "Got hr %#x.\n", hr
);
3806 hr
= IVMRWindowlessControl9_GetNativeVideoSize(windowless_control
, &width
, NULL
, &aspect_width
, &aspect_height
);
3807 ok(hr
== E_POINTER
, "Got hr %#x.\n", hr
);
3809 width
= height
= 0xdeadbeef;
3810 hr
= IVMRWindowlessControl9_GetNativeVideoSize(windowless_control
, &width
, &height
, NULL
, NULL
);
3811 todo_wine
ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
3812 todo_wine
ok(width
== 32, "Got width %d.\n", width
);
3813 todo_wine
ok(height
== 16, "Got height %d.\n", height
);
3815 aspect_width
= aspect_height
= 0xdeadbeef;
3816 hr
= IVMRWindowlessControl9_GetNativeVideoSize(windowless_control
, &width
, &height
, &aspect_width
, &aspect_height
);
3817 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
3818 ok(aspect_width
== 32, "Got width %d.\n", aspect_width
);
3819 ok(aspect_height
== 16, "Got height %d.\n", aspect_height
);
3821 memset(&src
, 0xcc, sizeof(src
));
3822 hr
= IVMRWindowlessControl9_GetVideoPosition(windowless_control
, &src
, NULL
);
3823 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
3824 SetRect(&expect
, 0, 0, 32, 16);
3825 ok(EqualRect(&src
, &expect
), "Got source rect %s.\n", wine_dbgstr_rect(&src
));
3827 memset(&dst
, 0xcc, sizeof(dst
));
3828 hr
= IVMRWindowlessControl9_GetVideoPosition(windowless_control
, NULL
, &dst
);
3829 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
3830 SetRect(&expect
, 0, 0, 0, 0);
3831 todo_wine
ok(EqualRect(&dst
, &expect
), "Got dest rect %s.\n", wine_dbgstr_rect(&dst
));
3833 SetRect(&src
, 4, 6, 16, 12);
3834 hr
= IVMRWindowlessControl9_SetVideoPosition(windowless_control
, &src
, NULL
);
3835 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
3837 memset(&src
, 0xcc, sizeof(src
));
3838 memset(&dst
, 0xcc, sizeof(dst
));
3839 hr
= IVMRWindowlessControl9_GetVideoPosition(windowless_control
, &src
, &dst
);
3840 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
3841 SetRect(&expect
, 4, 6, 16, 12);
3842 ok(EqualRect(&src
, &expect
), "Got source rect %s.\n", wine_dbgstr_rect(&src
));
3843 SetRect(&expect
, 0, 0, 0, 0);
3844 todo_wine
ok(EqualRect(&dst
, &expect
), "Got dest rect %s.\n", wine_dbgstr_rect(&dst
));
3846 SetRect(&dst
, 40, 60, 120, 160);
3847 hr
= IVMRWindowlessControl9_SetVideoPosition(windowless_control
, NULL
, &dst
);
3848 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
3850 memset(&src
, 0xcc, sizeof(src
));
3851 memset(&dst
, 0xcc, sizeof(dst
));
3852 hr
= IVMRWindowlessControl9_GetVideoPosition(windowless_control
, &src
, &dst
);
3853 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
3854 SetRect(&expect
, 4, 6, 16, 12);
3855 ok(EqualRect(&src
, &expect
), "Got source rect %s.\n", wine_dbgstr_rect(&src
));
3856 SetRect(&expect
, 40, 60, 120, 160);
3857 todo_wine
ok(EqualRect(&dst
, &expect
), "Got dest rect %s.\n", wine_dbgstr_rect(&dst
));
3859 GetWindowRect(window
, &src
);
3860 SetRect(&expect
, 0, 0, 640, 480);
3861 ok(EqualRect(&src
, &expect
), "Got window rect %s.\n", wine_dbgstr_rect(&src
));
3864 ref
= IFilterGraph2_Release(graph
);
3865 ok(!ref
, "Got outstanding refcount %d.\n", ref
);
3866 IMemInputPin_Release(input
);
3868 IVMRWindowlessControl9_Release(windowless_control
);
3869 ref
= IBaseFilter_Release(filter
);
3870 ok(!ref
, "Got outstanding refcount %d.\n", ref
);
3871 DestroyWindow(window
);
3876 IBaseFilter
*filter
;
3881 if (FAILED(hr
= CoCreateInstance(&CLSID_VideoMixingRenderer9
, NULL
,
3882 CLSCTX_INPROC_SERVER
, &IID_IBaseFilter
, (void **)&filter
)))
3884 skip("Failed to create VMR9, hr %#x.\n", hr
);
3887 IBaseFilter_Release(filter
);
3889 test_filter_config();
3896 test_enum_media_types();
3897 test_unconnected_filter_state();
3900 test_video_window();
3901 test_allocate_surface_helper();
3902 test_renderless_formats();
3904 test_clipping_window();
3905 test_surface_allocator_notify_refcount();
3907 test_windowless_size();