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 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 uint64_t x
= *(ULONGLONG
*)&f
;
77 uint64_t y
= *(ULONGLONG
*)&g
;
82 x
|= ((ULONGLONG
)1)<<63;
86 y
|= ((ULONGLONG
)1)<<63;
88 return (x
>y
? x
-y
: y
-x
) <= ulps
;
91 static IFilterGraph2
*create_graph(void)
95 hr
= CoCreateInstance(&CLSID_FilterGraph
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IFilterGraph2
, (void **)&ret
);
96 ok(hr
== S_OK
, "Failed to create FilterGraph: %#x\n", hr
);
100 static ULONG
get_refcount(void *iface
)
102 IUnknown
*unknown
= iface
;
103 IUnknown_AddRef(unknown
);
104 return IUnknown_Release(unknown
);
107 static void test_filter_config(void)
109 IVMRFilterConfig9
*config
;
114 hr
= CoCreateInstance(&CLSID_VideoMixingRenderer9
, NULL
, CLSCTX_INPROC_SERVER
,
115 &IID_IVMRFilterConfig9
, (void **)&config
);
116 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
118 hr
= IVMRFilterConfig9_GetRenderingMode(config
, &mode
);
119 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
120 ok(mode
== VMRMode_Windowed
, "Got mode %#x.\n", mode
);
122 hr
= IVMRFilterConfig9_SetRenderingMode(config
, VMR9Mode_Windowed
);
123 ok(hr
== S_OK
|| broken(hr
== E_FAIL
), "Got hr %#x.\n", hr
);
125 hr
= IVMRFilterConfig9_GetRenderingMode(config
, &mode
);
126 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
127 ok(mode
== VMR9Mode_Windowed
, "Got mode %#x.\n", mode
);
129 hr
= IVMRFilterConfig9_SetRenderingMode(config
, VMR9Mode_Windowed
);
130 ok(hr
== VFW_E_WRONG_STATE
, "Got hr %#x.\n", hr
);
132 ref
= IVMRFilterConfig9_Release(config
);
133 ok(!ref
, "Got outstanding refcount %d.\n", ref
);
135 hr
= CoCreateInstance(&CLSID_VideoMixingRenderer9
, NULL
, CLSCTX_INPROC_SERVER
,
136 &IID_IVMRFilterConfig9
, (void **)&config
);
137 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
139 hr
= IVMRFilterConfig9_SetRenderingMode(config
, VMR9Mode_Windowless
);
140 ok(hr
== S_OK
|| broken(hr
== E_FAIL
), "Got hr %#x.\n", hr
);
142 hr
= IVMRFilterConfig9_GetRenderingMode(config
, &mode
);
143 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
144 ok(mode
== VMR9Mode_Windowless
, "Got mode %#x.\n", mode
);
146 hr
= IVMRFilterConfig9_SetRenderingMode(config
, VMR9Mode_Windowed
);
147 ok(hr
== VFW_E_WRONG_STATE
, "Got hr %#x.\n", hr
);
149 ref
= IVMRFilterConfig9_Release(config
);
150 ok(!ref
, "Got outstanding refcount %d.\n", ref
);
152 hr
= CoCreateInstance(&CLSID_VideoMixingRenderer9
, NULL
, CLSCTX_INPROC_SERVER
,
153 &IID_IVMRFilterConfig9
, (void **)&config
);
154 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
156 hr
= IVMRFilterConfig9_SetRenderingMode(config
, VMR9Mode_Renderless
);
157 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
159 hr
= IVMRFilterConfig9_GetRenderingMode(config
, &mode
);
160 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
161 ok(mode
== VMR9Mode_Renderless
, "Got mode %#x.\n", mode
);
163 hr
= IVMRFilterConfig9_SetRenderingMode(config
, VMR9Mode_Windowless
);
164 ok(hr
== VFW_E_WRONG_STATE
, "Got hr %#x.\n", hr
);
166 ref
= IVMRFilterConfig9_Release(config
);
167 ok(!ref
, "Got outstanding refcount %d.\n", ref
);
169 hr
= CoCreateInstance(&CLSID_VideoMixingRenderer9
, NULL
, CLSCTX_INPROC_SERVER
,
170 &IID_IVMRFilterConfig9
, (void **)&config
);
171 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
173 hr
= IVMRFilterConfig9_GetNumberOfStreams(config
, &count
);
174 ok(hr
== VFW_E_VMR_NOT_IN_MIXER_MODE
, "Got hr %#x.\n", hr
);
176 hr
= IVMRFilterConfig9_SetNumberOfStreams(config
, 3);
177 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
179 hr
= IVMRFilterConfig9_GetNumberOfStreams(config
, &count
);
180 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
181 ok(count
== 3, "Got count %u.\n", count
);
183 hr
= IVMRFilterConfig9_GetRenderingMode(config
, &mode
);
184 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
185 ok(mode
== VMR9Mode_Windowed
, "Got mode %#x.\n", mode
);
187 /* Despite MSDN, you can still change the rendering mode after setting the
189 hr
= IVMRFilterConfig9_SetRenderingMode(config
, VMR9Mode_Windowless
);
190 ok(hr
== S_OK
|| broken(hr
== E_FAIL
), "Got hr %#x.\n", hr
);
192 hr
= IVMRFilterConfig9_GetRenderingMode(config
, &mode
);
193 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
194 ok(mode
== VMR9Mode_Windowless
, "Got mode %#x.\n", mode
);
196 hr
= IVMRFilterConfig9_GetNumberOfStreams(config
, &count
);
197 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
198 ok(count
== 3, "Got count %u.\n", count
);
200 ref
= IVMRFilterConfig9_Release(config
);
201 ok(!ref
, "Got outstanding refcount %d.\n", ref
);
204 #define check_interface_broken(a, b, c) check_interface_(__LINE__, a, b, c, TRUE)
205 #define check_interface(a, b, c) check_interface_(__LINE__, a, b, c, FALSE)
206 static HRESULT
check_interface_(unsigned int line
, void *iface
, REFIID riid
, BOOL supported
, BOOL is_broken
)
208 HRESULT hr
, expected_hr
, broken_hr
;
209 IUnknown
*unknown
= iface
, *out
;
214 broken_hr
= E_NOINTERFACE
;
218 expected_hr
= E_NOINTERFACE
;
222 hr
= IUnknown_QueryInterface(unknown
, riid
, (void **)&out
);
223 ok_(__FILE__
, line
)(hr
== expected_hr
|| broken(is_broken
&& hr
== broken_hr
),
224 "Got hr %#x, expected %#x.\n", hr
, expected_hr
);
226 IUnknown_Release(out
);
230 static void test_common_interfaces(IBaseFilter
*filter
)
234 check_interface(filter
, &IID_IAMCertifiedOutputProtection
, TRUE
);
235 check_interface(filter
, &IID_IAMFilterMiscFlags
, TRUE
);
236 check_interface(filter
, &IID_IBaseFilter
, TRUE
);
237 todo_wine
check_interface(filter
, &IID_IKsPropertySet
, TRUE
);
238 check_interface(filter
, &IID_IMediaFilter
, TRUE
);
239 check_interface(filter
, &IID_IMediaPosition
, TRUE
);
240 check_interface(filter
, &IID_IMediaSeeking
, TRUE
);
241 check_interface(filter
, &IID_IPersist
, TRUE
);
242 check_interface(filter
, &IID_IQualityControl
, TRUE
);
243 todo_wine
check_interface(filter
, &IID_IQualProp
, TRUE
);
244 check_interface(filter
, &IID_IUnknown
, TRUE
);
245 check_interface(filter
, &IID_IVMRAspectRatioControl9
, TRUE
);
246 todo_wine
check_interface(filter
, &IID_IVMRDeinterlaceControl9
, TRUE
);
247 check_interface(filter
, &IID_IVMRFilterConfig9
, TRUE
);
248 check_interface(filter
, &IID_IVMRMixerBitmap9
, TRUE
);
250 check_interface(filter
, &IID_IBasicAudio
, FALSE
);
251 check_interface(filter
, &IID_IDirectDrawVideo
, FALSE
);
252 check_interface(filter
, &IID_IPersistPropertyBag
, FALSE
);
253 check_interface(filter
, &IID_IPin
, FALSE
);
254 check_interface(filter
, &IID_IReferenceClock
, FALSE
);
255 check_interface(filter
, &IID_IVMRAspectRatioControl
, FALSE
);
256 check_interface(filter
, &IID_IVMRDeinterlaceControl
, FALSE
);
257 check_interface(filter
, &IID_IVMRFilterConfig
, FALSE
);
258 check_interface(filter
, &IID_IVMRMixerBitmap
, FALSE
);
259 check_interface(filter
, &IID_IVMRMixerControl
, FALSE
);
260 check_interface(filter
, &IID_IVMRMonitorConfig
, FALSE
);
261 check_interface(filter
, &IID_IVMRSurfaceAllocatorNotify
, FALSE
);
262 check_interface(filter
, &IID_IVMRWindowlessControl
, FALSE
);
264 IBaseFilter_FindPin(filter
, L
"VMR Input0", &pin
);
266 check_interface(pin
, &IID_IMemInputPin
, TRUE
);
267 check_interface(pin
, &IID_IOverlay
, TRUE
);
268 check_interface(pin
, &IID_IPin
, TRUE
);
269 todo_wine
check_interface(pin
, &IID_IQualityControl
, TRUE
);
270 check_interface(pin
, &IID_IUnknown
, TRUE
);
272 check_interface(pin
, &IID_IKsPropertySet
, FALSE
);
273 check_interface(pin
, &IID_IMediaPosition
, FALSE
);
274 check_interface(pin
, &IID_IMediaSeeking
, FALSE
);
279 static void test_interfaces(void)
281 IBaseFilter
*filter
= create_vmr9(0);
284 test_common_interfaces(filter
);
286 check_interface(filter
, &IID_IBasicVideo
, TRUE
);
287 todo_wine
check_interface(filter
, &IID_IBasicVideo2
, TRUE
);
288 check_interface(filter
, &IID_IVideoWindow
, TRUE
);
289 /* IVMRMonitorConfig9 may not be available if the d3d9 device has
290 * insufficient support. */
291 check_interface_broken(filter
, &IID_IVMRMonitorConfig9
, TRUE
);
293 check_interface(filter
, &IID_IVMRMixerControl9
, FALSE
);
294 check_interface(filter
, &IID_IVMRSurfaceAllocatorNotify9
, FALSE
);
295 check_interface(filter
, &IID_IVMRWindowlessControl9
, FALSE
);
297 ref
= IBaseFilter_Release(filter
);
298 ok(!ref
, "Got outstanding refcount %d.\n", ref
);
300 filter
= create_vmr9(VMR9Mode_Windowless
);
301 test_common_interfaces(filter
);
303 /* IVMRMonitorConfig9 may not be available if the d3d9 device has
304 * insufficient support. */
305 check_interface_broken(filter
, &IID_IVMRMonitorConfig9
, TRUE
);
306 check_interface(filter
, &IID_IVMRWindowlessControl9
, TRUE
);
308 todo_wine
check_interface(filter
, &IID_IBasicVideo
, FALSE
);
309 check_interface(filter
, &IID_IBasicVideo2
, FALSE
);
310 todo_wine
check_interface(filter
, &IID_IVideoWindow
, FALSE
);
311 check_interface(filter
, &IID_IVMRMixerControl9
, FALSE
);
312 check_interface(filter
, &IID_IVMRSurfaceAllocatorNotify9
, FALSE
);
314 ref
= IBaseFilter_Release(filter
);
315 ok(!ref
, "Got outstanding refcount %d.\n", ref
);
317 filter
= create_vmr9(VMR9Mode_Renderless
);
318 test_common_interfaces(filter
);
320 check_interface(filter
, &IID_IVMRSurfaceAllocatorNotify9
, TRUE
);
322 todo_wine
check_interface(filter
, &IID_IBasicVideo
, FALSE
);
323 check_interface(filter
, &IID_IBasicVideo2
, FALSE
);
324 todo_wine
check_interface(filter
, &IID_IVideoWindow
, FALSE
);
325 check_interface(filter
, &IID_IVMRMonitorConfig9
, FALSE
);
326 check_interface(filter
, &IID_IVMRWindowlessControl9
, FALSE
);
328 ref
= IBaseFilter_Release(filter
);
329 ok(!ref
, "Got outstanding refcount %d.\n", ref
);
331 filter
= create_vmr9(VMR9Mode_Windowed
);
332 set_mixing_mode(filter
, 1);
333 test_common_interfaces(filter
);
335 check_interface(filter
, &IID_IBasicVideo
, TRUE
);
336 todo_wine
check_interface(filter
, &IID_IBasicVideo2
, TRUE
);
337 check_interface(filter
, &IID_IVideoWindow
, TRUE
);
338 check_interface(filter
, &IID_IVMRMixerControl9
, TRUE
);
339 /* IVMRMonitorConfig9 may not be available if the d3d9 device has
340 * insufficient support. */
341 check_interface_broken(filter
, &IID_IVMRMonitorConfig9
, TRUE
);
343 check_interface(filter
, &IID_IVMRSurfaceAllocatorNotify9
, FALSE
);
344 check_interface(filter
, &IID_IVMRWindowlessControl9
, FALSE
);
346 ref
= IBaseFilter_Release(filter
);
347 ok(!ref
, "Got outstanding refcount %d.\n", ref
);
350 static const GUID test_iid
= {0x33333333};
351 static LONG outer_ref
= 1;
353 static HRESULT WINAPI
outer_QueryInterface(IUnknown
*iface
, REFIID iid
, void **out
)
355 if (IsEqualGUID(iid
, &IID_IUnknown
)
356 || IsEqualGUID(iid
, &IID_IBaseFilter
)
357 || IsEqualGUID(iid
, &test_iid
))
359 *out
= (IUnknown
*)0xdeadbeef;
362 ok(0, "unexpected call %s\n", wine_dbgstr_guid(iid
));
363 return E_NOINTERFACE
;
366 static ULONG WINAPI
outer_AddRef(IUnknown
*iface
)
368 return InterlockedIncrement(&outer_ref
);
371 static ULONG WINAPI
outer_Release(IUnknown
*iface
)
373 return InterlockedDecrement(&outer_ref
);
376 static const IUnknownVtbl outer_vtbl
=
378 outer_QueryInterface
,
383 static IUnknown test_outer
= {&outer_vtbl
};
385 static void test_aggregation(void)
387 IBaseFilter
*filter
, *filter2
;
388 IUnknown
*unk
, *unk2
;
392 filter
= (IBaseFilter
*)0xdeadbeef;
393 hr
= CoCreateInstance(&CLSID_VideoMixingRenderer9
, &test_outer
, CLSCTX_INPROC_SERVER
,
394 &IID_IBaseFilter
, (void **)&filter
);
395 ok(hr
== E_NOINTERFACE
, "Got hr %#x.\n", hr
);
396 ok(!filter
, "Got interface %p.\n", filter
);
398 hr
= CoCreateInstance(&CLSID_VideoMixingRenderer9
, &test_outer
, CLSCTX_INPROC_SERVER
,
399 &IID_IUnknown
, (void **)&unk
);
400 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
401 ok(outer_ref
== 1, "Got unexpected refcount %d.\n", outer_ref
);
402 ok(unk
!= &test_outer
, "Returned IUnknown should not be outer IUnknown.\n");
403 ref
= get_refcount(unk
);
404 ok(ref
== 1, "Got unexpected refcount %d.\n", ref
);
406 ref
= IUnknown_AddRef(unk
);
407 ok(ref
== 2, "Got unexpected refcount %d.\n", ref
);
408 ok(outer_ref
== 1, "Got unexpected refcount %d.\n", outer_ref
);
410 ref
= IUnknown_Release(unk
);
411 ok(ref
== 1, "Got unexpected refcount %d.\n", ref
);
412 ok(outer_ref
== 1, "Got unexpected refcount %d.\n", outer_ref
);
414 hr
= IUnknown_QueryInterface(unk
, &IID_IUnknown
, (void **)&unk2
);
415 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
416 ok(unk2
== unk
, "Got unexpected IUnknown %p.\n", unk2
);
417 IUnknown_Release(unk2
);
419 hr
= IUnknown_QueryInterface(unk
, &IID_IBaseFilter
, (void **)&filter
);
420 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
422 hr
= IBaseFilter_QueryInterface(filter
, &IID_IUnknown
, (void **)&unk2
);
423 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
424 ok(unk2
== (IUnknown
*)0xdeadbeef, "Got unexpected IUnknown %p.\n", unk2
);
426 hr
= IBaseFilter_QueryInterface(filter
, &IID_IBaseFilter
, (void **)&filter2
);
427 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
428 ok(filter2
== (IBaseFilter
*)0xdeadbeef, "Got unexpected IBaseFilter %p.\n", filter2
);
430 hr
= IUnknown_QueryInterface(unk
, &test_iid
, (void **)&unk2
);
431 ok(hr
== E_NOINTERFACE
, "Got hr %#x.\n", hr
);
432 ok(!unk2
, "Got unexpected IUnknown %p.\n", unk2
);
434 hr
= IBaseFilter_QueryInterface(filter
, &test_iid
, (void **)&unk2
);
435 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
436 ok(unk2
== (IUnknown
*)0xdeadbeef, "Got unexpected IUnknown %p.\n", unk2
);
438 IBaseFilter_Release(filter
);
439 ref
= IUnknown_Release(unk
);
440 ok(!ref
, "Got unexpected refcount %d.\n", ref
);
441 ok(outer_ref
== 1, "Got unexpected refcount %d.\n", outer_ref
);
444 static void test_enum_pins(void)
446 IBaseFilter
*filter
= create_vmr9(0);
447 IEnumPins
*enum1
, *enum2
;
452 ref
= get_refcount(filter
);
453 ok(ref
== 1, "Got unexpected refcount %d.\n", ref
);
455 hr
= IBaseFilter_EnumPins(filter
, NULL
);
456 ok(hr
== E_POINTER
, "Got hr %#x.\n", hr
);
458 hr
= IBaseFilter_EnumPins(filter
, &enum1
);
459 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
460 ref
= get_refcount(filter
);
461 ok(ref
== 2, "Got unexpected refcount %d.\n", ref
);
462 ref
= get_refcount(enum1
);
463 ok(ref
== 1, "Got unexpected refcount %d.\n", ref
);
465 hr
= IEnumPins_Next(enum1
, 1, NULL
, NULL
);
466 ok(hr
== E_POINTER
, "Got hr %#x.\n", hr
);
468 hr
= IEnumPins_Next(enum1
, 1, pins
, NULL
);
469 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
470 ref
= get_refcount(filter
);
471 ok(ref
== 3, "Got unexpected refcount %d.\n", ref
);
472 ref
= get_refcount(pins
[0]);
473 ok(ref
== 3, "Got unexpected refcount %d.\n", ref
);
474 ref
= get_refcount(enum1
);
475 ok(ref
== 1, "Got unexpected refcount %d.\n", ref
);
476 IPin_Release(pins
[0]);
477 ref
= get_refcount(filter
);
478 ok(ref
== 2, "Got unexpected refcount %d.\n", ref
);
480 hr
= IEnumPins_Next(enum1
, 1, pins
, NULL
);
481 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
483 hr
= IEnumPins_Reset(enum1
);
484 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
486 hr
= IEnumPins_Next(enum1
, 1, pins
, &count
);
487 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
488 ok(count
== 1, "Got count %u.\n", count
);
489 IPin_Release(pins
[0]);
491 hr
= IEnumPins_Next(enum1
, 1, pins
, &count
);
492 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
493 ok(!count
, "Got count %u.\n", count
);
495 hr
= IEnumPins_Reset(enum1
);
496 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
498 hr
= IEnumPins_Next(enum1
, 2, pins
, NULL
);
499 ok(hr
== E_INVALIDARG
, "Got hr %#x.\n", hr
);
501 hr
= IEnumPins_Next(enum1
, 2, pins
, &count
);
502 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
503 ok(count
== 1, "Got count %u.\n", count
);
504 IPin_Release(pins
[0]);
506 hr
= IEnumPins_Reset(enum1
);
507 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
509 hr
= IEnumPins_Clone(enum1
, &enum2
);
510 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
512 hr
= IEnumPins_Skip(enum1
, 2);
513 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
515 hr
= IEnumPins_Skip(enum1
, 1);
516 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
518 hr
= IEnumPins_Skip(enum1
, 1);
519 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
521 hr
= IEnumPins_Next(enum1
, 1, pins
, NULL
);
522 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
524 hr
= IEnumPins_Next(enum2
, 1, pins
, NULL
);
525 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
526 IPin_Release(pins
[0]);
528 IEnumPins_Release(enum2
);
530 set_mixing_mode(filter
, 2);
532 hr
= IEnumPins_Next(enum1
, 1, pins
, NULL
);
533 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
535 hr
= IEnumPins_Reset(enum1
);
536 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
538 hr
= IEnumPins_Next(enum1
, 1, pins
, NULL
);
539 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
540 IPin_Release(pins
[0]);
542 hr
= IEnumPins_Next(enum1
, 1, pins
, NULL
);
543 todo_wine
ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
544 if (hr
== S_OK
) IPin_Release(pins
[0]);
546 hr
= IEnumPins_Next(enum1
, 1, pins
, NULL
);
547 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
549 hr
= IEnumPins_Reset(enum1
);
550 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
552 hr
= IEnumPins_Next(enum1
, 2, pins
, &count
);
553 todo_wine
ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
554 todo_wine
ok(count
== 2, "Got count %u.\n", count
);
555 IPin_Release(pins
[0]);
556 if (count
> 1) IPin_Release(pins
[1]);
558 hr
= IEnumPins_Reset(enum1
);
559 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
561 hr
= IEnumPins_Next(enum1
, 3, pins
, &count
);
562 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
563 todo_wine
ok(count
== 2, "Got count %u.\n", count
);
564 IPin_Release(pins
[0]);
565 if (count
> 1) IPin_Release(pins
[1]);
567 IEnumPins_Release(enum1
);
568 ref
= IBaseFilter_Release(filter
);
569 ok(!ref
, "Got outstanding refcount %d.\n", ref
);
572 static void test_find_pin(void)
574 IBaseFilter
*filter
= create_vmr9(0);
575 IEnumPins
*enum_pins
;
580 IBaseFilter_EnumPins(filter
, &enum_pins
);
582 hr
= IBaseFilter_FindPin(filter
, L
"input pin", &pin
);
583 ok(hr
== VFW_E_NOT_FOUND
, "Got hr %#x.\n", hr
);
585 hr
= IBaseFilter_FindPin(filter
, L
"In", &pin
);
586 ok(hr
== VFW_E_NOT_FOUND
, "Got hr %#x.\n", hr
);
588 hr
= IBaseFilter_FindPin(filter
, L
"VMR Input0", &pin
);
589 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
590 hr
= IEnumPins_Next(enum_pins
, 1, &pin2
, NULL
);
591 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
592 ok(pin
== pin2
, "Pins did not match.\n");
596 hr
= IBaseFilter_FindPin(filter
, L
"VMR Input1", &pin
);
597 ok(hr
== VFW_E_NOT_FOUND
, "Got hr %#x.\n", hr
);
599 set_mixing_mode(filter
, 2);
601 IEnumPins_Reset(enum_pins
);
603 hr
= IBaseFilter_FindPin(filter
, L
"VMR Input0", &pin
);
604 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
605 hr
= IEnumPins_Next(enum_pins
, 1, &pin2
, NULL
);
606 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
607 ok(pin
== pin2
, "Pins did not match.\n");
611 hr
= IBaseFilter_FindPin(filter
, L
"VMR Input1", &pin
);
612 todo_wine
ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
615 hr
= IEnumPins_Next(enum_pins
, 1, &pin2
, NULL
);
616 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
617 ok(pin
== pin2
, "Pins did not match.\n");
622 hr
= IBaseFilter_FindPin(filter
, L
"VMR Input2", &pin
);
623 ok(hr
== VFW_E_NOT_FOUND
, "Got hr %#x.\n", hr
);
625 IEnumPins_Release(enum_pins
);
626 ref
= IBaseFilter_Release(filter
);
627 ok(!ref
, "Got outstanding refcount %d.\n", ref
);
630 static void test_pin_info(void)
632 IBaseFilter
*filter
= create_vmr9(0);
640 IBaseFilter_FindPin(filter
, L
"VMR Input0", &pin
);
641 hr
= IPin_QueryPinInfo(pin
, &info
);
642 ok(info
.pFilter
== filter
, "Expected filter %p, got %p.\n", filter
, info
.pFilter
);
643 ok(info
.dir
== PINDIR_INPUT
, "Got direction %d.\n", info
.dir
);
644 ok(!wcscmp(info
.achName
, L
"VMR Input0"), "Got name %s.\n", wine_dbgstr_w(info
.achName
));
645 IBaseFilter_Release(info
.pFilter
);
647 hr
= IPin_QueryDirection(pin
, &dir
);
648 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
649 ok(dir
== PINDIR_INPUT
, "Got direction %d.\n", dir
);
651 hr
= IPin_QueryId(pin
, &id
);
652 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
653 ok(!wcscmp(id
, L
"VMR Input0"), "Got id %s.\n", wine_dbgstr_w(id
));
656 hr
= IPin_QueryInternalConnections(pin
, NULL
, &count
);
657 ok(hr
== E_NOTIMPL
, "Got hr %#x.\n", hr
);
661 set_mixing_mode(filter
, 2);
663 hr
= IBaseFilter_FindPin(filter
, L
"VMR Input1", &pin
);
664 todo_wine
ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
667 hr
= IPin_QueryPinInfo(pin
, &info
);
668 ok(info
.pFilter
== filter
, "Expected filter %p, got %p.\n", filter
, info
.pFilter
);
669 ok(info
.dir
== PINDIR_INPUT
, "Got direction %d.\n", info
.dir
);
670 ok(!wcscmp(info
.achName
, L
"VMR Input1"), "Got name %s.\n", wine_dbgstr_w(info
.achName
));
671 IBaseFilter_Release(info
.pFilter
);
673 hr
= IPin_QueryDirection(pin
, &dir
);
674 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
675 ok(dir
== PINDIR_INPUT
, "Got direction %d.\n", dir
);
677 hr
= IPin_QueryId(pin
, &id
);
678 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
679 ok(!wcscmp(id
, L
"VMR Input1"), "Got id %s.\n", wine_dbgstr_w(id
));
682 hr
= IPin_QueryInternalConnections(pin
, NULL
, &count
);
683 ok(hr
== E_NOTIMPL
, "Got hr %#x.\n", hr
);
688 ref
= IBaseFilter_Release(filter
);
689 ok(!ref
, "Got outstanding refcount %d.\n", ref
);
692 static void test_media_types(void)
694 IBaseFilter
*filter
= create_vmr9(0);
695 AM_MEDIA_TYPE
*mt
, req_mt
= {{0}};
696 VIDEOINFOHEADER vih
=
699 {sizeof(BITMAPINFOHEADER
), 32, 24, 1, 0, 0xdeadbeef}
701 IEnumMediaTypes
*enummt
;
707 static const GUID
*subtype_tests
[] =
709 &MEDIASUBTYPE_RGB565
,
714 IBaseFilter_FindPin(filter
, L
"VMR Input0", &pin
);
716 hr
= IPin_EnumMediaTypes(pin
, &enummt
);
717 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
719 hr
= IEnumMediaTypes_Next(enummt
, 1, &mt
, NULL
);
720 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
722 IEnumMediaTypes_Release(enummt
);
724 req_mt
.majortype
= MEDIATYPE_Video
;
725 req_mt
.formattype
= FORMAT_VideoInfo
;
726 req_mt
.cbFormat
= sizeof(VIDEOINFOHEADER
);
727 req_mt
.pbFormat
= (BYTE
*)&vih
;
729 for (i
= 0; i
< ARRAY_SIZE(subtype_tests
); ++i
)
731 req_mt
.subtype
= *subtype_tests
[i
];
732 hr
= IPin_QueryAccept(pin
, &req_mt
);
733 ok(hr
== S_OK
, "Got hr %#x for subtype %s.\n", hr
, wine_dbgstr_guid(subtype_tests
[i
]));
736 req_mt
.subtype
= MEDIASUBTYPE_RGB8
;
737 hr
= IPin_QueryAccept(pin
, &req_mt
);
738 todo_wine
ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
739 req_mt
.subtype
= MEDIASUBTYPE_NULL
;
740 hr
= IPin_QueryAccept(pin
, &req_mt
);
741 todo_wine
ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
742 req_mt
.subtype
= MEDIASUBTYPE_RGB24
;
744 req_mt
.majortype
= MEDIATYPE_NULL
;
745 hr
= IPin_QueryAccept(pin
, &req_mt
);
746 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
747 req_mt
.majortype
= MEDIATYPE_Video
;
749 req_mt
.formattype
= FORMAT_None
;
750 hr
= IPin_QueryAccept(pin
, &req_mt
);
751 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
753 req_mt
.formattype
= GUID_NULL
;
754 hr
= IPin_QueryAccept(pin
, &req_mt
);
755 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
758 ref
= IBaseFilter_Release(filter
);
759 ok(!ref
, "Got outstanding refcount %d.\n", ref
);
762 static void test_enum_media_types(void)
764 IBaseFilter
*filter
= create_vmr9(0);
765 IEnumMediaTypes
*enum1
, *enum2
;
766 AM_MEDIA_TYPE
*mts
[2];
771 IBaseFilter_FindPin(filter
, L
"VMR Input0", &pin
);
773 hr
= IPin_EnumMediaTypes(pin
, &enum1
);
774 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
776 hr
= IEnumMediaTypes_Next(enum1
, 1, mts
, NULL
);
777 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
779 hr
= IEnumMediaTypes_Next(enum1
, 1, mts
, &count
);
780 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
781 ok(!count
, "Got count %u.\n", count
);
783 hr
= IEnumMediaTypes_Reset(enum1
);
784 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
786 hr
= IEnumMediaTypes_Next(enum1
, 1, mts
, NULL
);
787 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
789 hr
= IEnumMediaTypes_Clone(enum1
, &enum2
);
790 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
792 hr
= IEnumMediaTypes_Skip(enum1
, 1);
793 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
795 hr
= IEnumMediaTypes_Next(enum2
, 1, mts
, NULL
);
796 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
798 IEnumMediaTypes_Release(enum1
);
799 IEnumMediaTypes_Release(enum2
);
802 ref
= IBaseFilter_Release(filter
);
803 ok(!ref
, "Got outstanding refcount %d.\n", ref
);
806 static void test_unconnected_filter_state(void)
808 IBaseFilter
*filter
= create_vmr9(0);
813 hr
= IBaseFilter_GetState(filter
, 0, &state
);
814 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
815 ok(state
== State_Stopped
, "Got state %u.\n", state
);
817 hr
= IBaseFilter_Pause(filter
);
818 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
820 hr
= IBaseFilter_GetState(filter
, 0, &state
);
821 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
822 ok(state
== State_Paused
, "Got state %u.\n", state
);
824 hr
= IBaseFilter_Run(filter
, 0);
825 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
827 hr
= IBaseFilter_GetState(filter
, 0, &state
);
828 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
829 ok(state
== State_Running
, "Got state %u.\n", state
);
831 hr
= IBaseFilter_Pause(filter
);
832 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
834 hr
= IBaseFilter_GetState(filter
, 0, &state
);
835 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
836 ok(state
== State_Paused
, "Got state %u.\n", state
);
838 hr
= IBaseFilter_Stop(filter
);
839 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
841 hr
= IBaseFilter_GetState(filter
, 0, &state
);
842 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
843 ok(state
== State_Stopped
, "Got state %u.\n", state
);
845 hr
= IBaseFilter_Run(filter
, 0);
846 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
848 hr
= IBaseFilter_GetState(filter
, 0, &state
);
849 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
850 ok(state
== State_Running
, "Got state %u.\n", state
);
852 hr
= IBaseFilter_Stop(filter
);
853 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
855 hr
= IBaseFilter_GetState(filter
, 0, &state
);
856 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
857 ok(state
== State_Stopped
, "Got state %u.\n", state
);
859 ref
= IBaseFilter_Release(filter
);
860 ok(!ref
, "Got outstanding refcount %d.\n", ref
);
865 struct strmbase_filter filter
;
866 struct strmbase_source source
;
869 static inline struct testfilter
*impl_from_strmbase_filter(struct strmbase_filter
*iface
)
871 return CONTAINING_RECORD(iface
, struct testfilter
, filter
);
874 static struct strmbase_pin
*testfilter_get_pin(struct strmbase_filter
*iface
, unsigned int index
)
876 struct testfilter
*filter
= impl_from_strmbase_filter(iface
);
878 return &filter
->source
.pin
;
882 static void testfilter_destroy(struct strmbase_filter
*iface
)
884 struct testfilter
*filter
= impl_from_strmbase_filter(iface
);
885 strmbase_source_cleanup(&filter
->source
);
886 strmbase_filter_cleanup(&filter
->filter
);
889 static const struct strmbase_filter_ops testfilter_ops
=
891 .filter_get_pin
= testfilter_get_pin
,
892 .filter_destroy
= testfilter_destroy
,
895 static HRESULT WINAPI
testsource_DecideAllocator(struct strmbase_source
*iface
,
896 IMemInputPin
*peer
, IMemAllocator
**allocator
)
901 static const struct strmbase_source_ops testsource_ops
=
903 .pfnAttemptConnection
= BaseOutputPinImpl_AttemptConnection
,
904 .pfnDecideAllocator
= testsource_DecideAllocator
,
907 static void testfilter_init(struct testfilter
*filter
)
909 static const GUID clsid
= {0xabacab};
910 strmbase_filter_init(&filter
->filter
, NULL
, &clsid
, &testfilter_ops
);
911 strmbase_source_init(&filter
->source
, &filter
->filter
, L
"", &testsource_ops
);
914 static void test_allocator(IMemInputPin
*input
)
916 IMemAllocator
*req_allocator
, *ret_allocator
;
917 ALLOCATOR_PROPERTIES props
, req_props
;
920 hr
= IMemInputPin_GetAllocatorRequirements(input
, &props
);
921 ok(hr
== E_NOTIMPL
, "Got hr %#x.\n", hr
);
923 hr
= IMemInputPin_GetAllocator(input
, &ret_allocator
);
924 todo_wine
ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
928 hr
= IMemAllocator_GetProperties(ret_allocator
, &props
);
929 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
930 ok(!props
.cBuffers
, "Got %d buffers.\n", props
.cBuffers
);
931 ok(!props
.cbBuffer
, "Got size %d.\n", props
.cbBuffer
);
932 ok(!props
.cbAlign
, "Got alignment %d.\n", props
.cbAlign
);
933 ok(!props
.cbPrefix
, "Got prefix %d.\n", props
.cbPrefix
);
935 hr
= IMemInputPin_NotifyAllocator(input
, ret_allocator
, TRUE
);
936 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
938 req_props
.cBuffers
= 1;
939 req_props
.cbBuffer
= 32 * 16 * 4;
940 req_props
.cbAlign
= 1;
941 req_props
.cbPrefix
= 0;
942 hr
= IMemAllocator_SetProperties(ret_allocator
, &req_props
, &props
);
943 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
944 ok(props
.cBuffers
== 1, "Got %d buffers.\n", props
.cBuffers
);
945 ok(props
.cbBuffer
== 32 * 16 * 4, "Got size %d.\n", props
.cbBuffer
);
946 ok(props
.cbAlign
== 1, "Got alignment %d.\n", props
.cbAlign
);
947 ok(!props
.cbPrefix
, "Got prefix %d.\n", props
.cbPrefix
);
949 IMemAllocator_Release(ret_allocator
);
952 hr
= IMemInputPin_NotifyAllocator(input
, NULL
, TRUE
);
953 todo_wine
ok(hr
== E_FAIL
, "Got hr %#x.\n", hr
);
955 CoCreateInstance(&CLSID_MemoryAllocator
, NULL
, CLSCTX_INPROC_SERVER
,
956 &IID_IMemAllocator
, (void **)&req_allocator
);
958 hr
= IMemInputPin_NotifyAllocator(input
, req_allocator
, TRUE
);
959 todo_wine
ok(hr
== E_FAIL
, "Got hr %#x.\n", hr
);
961 IMemAllocator_Release(req_allocator
);
964 struct frame_thread_params
967 IMediaSample
*sample
;
970 static DWORD WINAPI
frame_thread(void *arg
)
972 struct frame_thread_params
*params
= arg
;
975 if (winetest_debug
> 1) trace("%04x: Sending frame.\n", GetCurrentThreadId());
976 hr
= IMemInputPin_Receive(params
->sink
, params
->sample
);
977 if (winetest_debug
> 1) trace("%04x: Returned %#x.\n", GetCurrentThreadId(), hr
);
978 IMediaSample_Release(params
->sample
);
983 static HANDLE
send_frame_time(IMemInputPin
*sink
, REFERENCE_TIME start_time
, DWORD color
)
985 struct frame_thread_params
*params
= heap_alloc(sizeof(*params
));
986 IMemAllocator
*allocator
;
987 REFERENCE_TIME end_time
;
988 IMediaSample
*sample
;
994 hr
= IMemInputPin_GetAllocator(sink
, &allocator
);
995 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
997 hr
= IMemAllocator_GetBuffer(allocator
, &sample
, NULL
, NULL
, 0);
998 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1000 size
= IMediaSample_GetSize(sample
);
1001 hr
= IMediaSample_GetPointer(sample
, &data
);
1002 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1003 for (i
= 0; i
< size
/ sizeof(DWORD
); ++i
)
1004 ((DWORD
*)data
)[i
] = color
;
1006 hr
= IMediaSample_SetActualDataLength(sample
, size
);
1007 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1009 start_time
*= 10000000;
1010 end_time
= start_time
+ 10000000;
1011 hr
= IMediaSample_SetTime(sample
, &start_time
, &end_time
);
1012 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1014 hr
= IMediaSample_SetPreroll(sample
, TRUE
);
1015 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1017 params
->sink
= sink
;
1018 params
->sample
= sample
;
1019 thread
= CreateThread(NULL
, 0, frame_thread
, params
, 0, NULL
);
1021 IMemAllocator_Release(allocator
);
1025 static HANDLE
send_frame(IMemInputPin
*sink
)
1027 return send_frame_time(sink
, 0, 0x007f007f);
1030 static HRESULT
join_thread_(int line
, HANDLE thread
)
1033 ok_(__FILE__
, line
)(!WaitForSingleObject(thread
, 1000), "Wait failed.\n");
1034 GetExitCodeThread(thread
, &ret
);
1035 CloseHandle(thread
);
1038 #define join_thread(a) join_thread_(__LINE__, a)
1040 static void commit_allocator(IMemInputPin
*input
)
1042 IMemAllocator
*allocator
;
1045 hr
= IMemInputPin_GetAllocator(input
, &allocator
);
1046 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1047 hr
= IMemAllocator_Commit(allocator
);
1048 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1049 IMemAllocator_Release(allocator
);
1052 static void test_filter_state(IMemInputPin
*input
, IMediaControl
*control
)
1054 IMemAllocator
*allocator
;
1055 IMediaSample
*sample
;
1056 OAFilterState state
;
1060 thread
= send_frame(input
);
1061 hr
= join_thread(thread
);
1062 ok(hr
== VFW_E_WRONG_STATE
, "Got hr %#x.\n", hr
);
1064 /* The renderer is not fully paused until it receives a sample. The thread
1065 * sending the sample blocks in IMemInputPin_Receive() until the filter is
1066 * stopped or run. */
1068 hr
= IMediaControl_Pause(control
);
1069 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
1071 hr
= IMediaControl_GetState(control
, 0, &state
);
1072 ok(hr
== VFW_S_STATE_INTERMEDIATE
, "Got hr %#x.\n", hr
);
1074 thread
= send_frame(input
);
1076 hr
= IMediaControl_GetState(control
, 1000, &state
);
1077 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1079 ok(WaitForSingleObject(thread
, 100) == WAIT_TIMEOUT
, "Thread should block in Receive().\n");
1081 hr
= IMediaControl_Stop(control
);
1082 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1084 hr
= join_thread(thread
);
1085 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1087 /* The sink will decommit our allocator for us when stopping, however it
1088 * will not recommit it when pausing. */
1089 hr
= IMemInputPin_GetAllocator(input
, &allocator
);
1090 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1091 hr
= IMemAllocator_GetBuffer(allocator
, &sample
, NULL
, NULL
, 0);
1092 todo_wine
ok(hr
== VFW_E_NOT_COMMITTED
, "Got hr %#x.\n", hr
);
1093 if (hr
== S_OK
) IMediaSample_Release(sample
);
1095 hr
= IMemAllocator_Commit(allocator
);
1096 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1097 thread
= send_frame(input
);
1098 hr
= join_thread(thread
);
1099 ok(hr
== VFW_E_WRONG_STATE
, "Got hr %#x.\n", hr
);
1101 hr
= IMediaControl_Pause(control
);
1102 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
1104 hr
= IMediaControl_GetState(control
, 0, &state
);
1105 ok(hr
== VFW_S_STATE_INTERMEDIATE
, "Got hr %#x.\n", hr
);
1107 thread
= send_frame(input
);
1109 hr
= IMediaControl_GetState(control
, 1000, &state
);
1110 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1112 ok(WaitForSingleObject(thread
, 100) == WAIT_TIMEOUT
, "Thread should block in Receive().\n");
1114 hr
= IMediaControl_Run(control
);
1115 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1117 hr
= IMediaControl_GetState(control
, 0, &state
);
1118 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1120 hr
= join_thread(thread
);
1121 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1123 thread
= send_frame(input
);
1124 hr
= join_thread(thread
);
1125 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1127 hr
= IMediaControl_Pause(control
);
1128 todo_wine
ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
1130 hr
= IMediaControl_GetState(control
, 0, &state
);
1131 todo_wine
ok(hr
== VFW_S_STATE_INTERMEDIATE
, "Got hr %#x.\n", hr
);
1133 thread
= send_frame(input
);
1135 hr
= IMediaControl_GetState(control
, 1000, &state
);
1136 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1138 ok(WaitForSingleObject(thread
, 100) == WAIT_TIMEOUT
, "Thread should block in Receive().\n");
1140 hr
= IMediaControl_Run(control
);
1141 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1143 hr
= IMediaControl_GetState(control
, 0, &state
);
1144 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1146 hr
= join_thread(thread
);
1147 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1149 hr
= IMediaControl_Pause(control
);
1150 todo_wine
ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
1152 hr
= IMediaControl_GetState(control
, 0, &state
);
1153 todo_wine
ok(hr
== VFW_S_STATE_INTERMEDIATE
, "Got hr %#x.\n", hr
);
1155 hr
= IMediaControl_Stop(control
);
1156 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1158 hr
= IMediaControl_GetState(control
, 0, &state
);
1159 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1161 commit_allocator(input
);
1162 hr
= IMediaControl_Pause(control
);
1163 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
1165 hr
= IMediaControl_GetState(control
, 0, &state
);
1166 ok(hr
== VFW_S_STATE_INTERMEDIATE
, "Got hr %#x.\n", hr
);
1168 hr
= IMediaControl_Run(control
);
1169 todo_wine
ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
1171 hr
= IMediaControl_GetState(control
, 0, &state
);
1172 todo_wine
ok(hr
== VFW_S_STATE_INTERMEDIATE
, "Got hr %#x.\n", hr
);
1174 thread
= send_frame(input
);
1175 hr
= join_thread(thread
);
1176 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1178 hr
= IMediaControl_GetState(control
, 0, &state
);
1179 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1181 hr
= IMediaControl_Stop(control
);
1182 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1184 hr
= IMediaControl_GetState(control
, 0, &state
);
1185 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1187 IMemAllocator_Release(allocator
);
1190 static void test_flushing(IPin
*pin
, IMemInputPin
*input
, IMediaControl
*control
)
1192 OAFilterState state
;
1196 commit_allocator(input
);
1197 hr
= IMediaControl_Pause(control
);
1198 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
1200 thread
= send_frame(input
);
1201 ok(WaitForSingleObject(thread
, 100) == WAIT_TIMEOUT
, "Thread should block in Receive().\n");
1203 hr
= IMediaControl_GetState(control
, 0, &state
);
1204 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1206 hr
= IPin_BeginFlush(pin
);
1207 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1209 hr
= join_thread(thread
);
1210 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1212 thread
= send_frame(input
);
1213 hr
= join_thread(thread
);
1214 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
1216 hr
= IPin_EndFlush(pin
);
1217 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1219 /* We dropped the sample we were holding, so now we need a new one... */
1221 hr
= IMediaControl_GetState(control
, 0, &state
);
1222 todo_wine
ok(hr
== VFW_S_STATE_INTERMEDIATE
, "Got hr %#x.\n", hr
);
1224 thread
= send_frame(input
);
1225 ok(WaitForSingleObject(thread
, 100) == WAIT_TIMEOUT
, "Thread should block in Receive().\n");
1227 hr
= IMediaControl_Run(control
);
1228 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1229 hr
= join_thread(thread
);
1230 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1232 hr
= IPin_BeginFlush(pin
);
1233 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1235 thread
= send_frame(input
);
1236 hr
= join_thread(thread
);
1237 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
1239 hr
= IPin_EndFlush(pin
);
1240 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1242 thread
= send_frame(input
);
1243 hr
= join_thread(thread
);
1244 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1246 hr
= IMediaControl_Stop(control
);
1247 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1250 static unsigned int check_ec_complete(IMediaEvent
*eventsrc
, DWORD timeout
)
1252 LONG_PTR param1
, param2
;
1253 unsigned int ret
= 0;
1257 while ((hr
= IMediaEvent_GetEvent(eventsrc
, &code
, ¶m1
, ¶m2
, timeout
)) == S_OK
)
1259 if (code
== EC_COMPLETE
)
1261 ok(param1
== S_OK
, "Got param1 %#lx.\n", param1
);
1262 ok(!param2
, "Got param2 %#lx.\n", param2
);
1265 IMediaEvent_FreeEventParams(eventsrc
, code
, param1
, param2
);
1268 ok(hr
== E_ABORT
, "Got hr %#x.\n", hr
);
1273 static void test_eos(IPin
*pin
, IMemInputPin
*input
, IMediaControl
*control
)
1275 IMediaEvent
*eventsrc
;
1276 OAFilterState state
;
1280 IMediaControl_QueryInterface(control
, &IID_IMediaEvent
, (void **)&eventsrc
);
1282 commit_allocator(input
);
1283 hr
= IMediaControl_Pause(control
);
1284 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
1285 ret
= check_ec_complete(eventsrc
, 0);
1286 ok(!ret
, "Got unexpected EC_COMPLETE.\n");
1288 hr
= IPin_EndOfStream(pin
);
1289 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1291 hr
= IMediaControl_GetState(control
, 1000, &state
);
1292 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1293 ret
= check_ec_complete(eventsrc
, 0);
1294 todo_wine
ok(!ret
, "Got unexpected EC_COMPLETE.\n");
1296 hr
= join_thread(send_frame(input
));
1297 todo_wine
ok(hr
== E_UNEXPECTED
, "Got hr %#x.\n", hr
);
1299 hr
= IMediaControl_Run(control
);
1300 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1301 ret
= check_ec_complete(eventsrc
, 0);
1302 todo_wine
ok(ret
== 1, "Expected EC_COMPLETE.\n");
1304 hr
= IMediaControl_Stop(control
);
1305 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1306 ret
= check_ec_complete(eventsrc
, 0);
1307 ok(!ret
, "Got unexpected EC_COMPLETE.\n");
1309 /* We do not receive an EC_COMPLETE notification until the last sample is
1310 * done rendering. */
1312 commit_allocator(input
);
1313 hr
= IMediaControl_Run(control
);
1314 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
1315 hr
= join_thread(send_frame(input
));
1316 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1317 hr
= IMediaControl_GetState(control
, 1000, &state
);
1318 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1319 ret
= check_ec_complete(eventsrc
, 0);
1320 ok(!ret
, "Got unexpected EC_COMPLETE.\n");
1322 hr
= IPin_EndOfStream(pin
);
1323 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1324 ret
= check_ec_complete(eventsrc
, 0);
1325 todo_wine
ok(!ret
, "Got unexpected EC_COMPLETE.\n");
1326 ret
= check_ec_complete(eventsrc
, 1600);
1327 todo_wine
ok(ret
== 1, "Expected EC_COMPLETE.\n");
1329 hr
= IMediaControl_Stop(control
);
1330 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1331 ret
= check_ec_complete(eventsrc
, 0);
1332 ok(!ret
, "Got unexpected EC_COMPLETE.\n");
1334 /* Test sending EOS while flushing. */
1336 commit_allocator(input
);
1337 hr
= IMediaControl_Run(control
);
1338 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
1339 hr
= join_thread(send_frame(input
));
1340 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1342 hr
= IPin_BeginFlush(pin
);
1343 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1344 hr
= IPin_EndOfStream(pin
);
1345 todo_wine
ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
1346 hr
= IPin_EndFlush(pin
);
1347 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1349 hr
= IMediaControl_Stop(control
);
1350 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1351 ret
= check_ec_complete(eventsrc
, 0);
1352 todo_wine
ok(!ret
, "Got unexpected EC_COMPLETE.\n");
1354 /* Test sending EOS and then flushing or stopping. */
1356 commit_allocator(input
);
1357 hr
= IMediaControl_Run(control
);
1358 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
1359 hr
= join_thread(send_frame(input
));
1360 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1361 hr
= IMediaControl_GetState(control
, 1000, &state
);
1362 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1364 hr
= IPin_EndOfStream(pin
);
1365 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1366 ret
= check_ec_complete(eventsrc
, 0);
1367 todo_wine
ok(!ret
, "Got unexpected EC_COMPLETE.\n");
1369 hr
= IPin_BeginFlush(pin
);
1370 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1371 hr
= IPin_EndFlush(pin
);
1372 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1374 hr
= join_thread(send_frame(input
));
1375 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1376 hr
= IPin_EndOfStream(pin
);
1377 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1378 ret
= check_ec_complete(eventsrc
, 0);
1379 ok(!ret
, "Got unexpected EC_COMPLETE.\n");
1381 hr
= IMediaControl_Stop(control
);
1382 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1383 ret
= check_ec_complete(eventsrc
, 0);
1384 ok(!ret
, "Got unexpected EC_COMPLETE.\n");
1386 IMediaEvent_Release(eventsrc
);
1389 static void test_sample_time(IPin
*pin
, IMemInputPin
*input
, IMediaControl
*control
)
1391 OAFilterState state
;
1395 commit_allocator(input
);
1396 hr
= IMediaControl_Pause(control
);
1397 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
1399 hr
= IMediaControl_GetState(control
, 0, &state
);
1400 ok(hr
== VFW_S_STATE_INTERMEDIATE
, "Got hr %#x.\n", hr
);
1402 thread
= send_frame_time(input
, 1, 0x000000ff); /* blue */
1404 hr
= IMediaControl_GetState(control
, 1000, &state
);
1405 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1407 ok(WaitForSingleObject(thread
, 100) == WAIT_TIMEOUT
, "Thread should block in Receive().\n");
1409 hr
= IMediaControl_Run(control
);
1410 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1412 ok(WaitForSingleObject(thread
, 500) == WAIT_TIMEOUT
, "Thread should block in Receive().\n");
1414 hr
= join_thread(thread
);
1415 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1417 /* Sample time is relative to the time passed to Run(). Thus a sample
1418 * stamped at or earlier than 1s will now be displayed immediately, because
1419 * that time has already passed.
1420 * One may manually verify that all of the frames in this function are
1421 * rendered, including (by adding a Sleep() after sending the frame) the
1422 * cyan and green frames. Thus the VMR does not attempt to drop any frames
1423 * that it considers late. This remains true if the frames are marked as
1426 hr
= join_thread(send_frame_time(input
, 1, 0x0000ffff)); /* cyan */
1427 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1429 hr
= join_thread(send_frame_time(input
, 0, 0x0000ff00)); /* green */
1430 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1432 hr
= join_thread(send_frame_time(input
, -2, 0x00ff0000)); /* red */
1433 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1435 thread
= send_frame_time(input
, 2, 0x00ff00ff); /* magenta */
1436 ok(WaitForSingleObject(thread
, 500) == WAIT_TIMEOUT
, "Thread should block in Receive().\n");
1437 hr
= join_thread(thread
);
1438 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1440 thread
= send_frame_time(input
, 1000000, 0x00ffffff); /* white */
1441 ok(WaitForSingleObject(thread
, 100) == WAIT_TIMEOUT
, "Thread should block in Receive().\n");
1443 hr
= IPin_BeginFlush(pin
);
1444 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1445 hr
= join_thread(thread
);
1446 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1447 hr
= IPin_EndFlush(pin
);
1448 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1450 thread
= send_frame_time(input
, 1000000, 0x00ffff00); /* yellow */
1451 ok(WaitForSingleObject(thread
, 100) == WAIT_TIMEOUT
, "Thread should block in Receive().\n");
1453 hr
= IMediaControl_Stop(control
);
1454 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1455 hr
= join_thread(thread
);
1456 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1459 static void test_current_image(IBaseFilter
*filter
, IMemInputPin
*input
,
1460 IMediaControl
*control
, const BITMAPINFOHEADER
*req_bih
)
1462 LONG buffer
[(sizeof(BITMAPINFOHEADER
) + 32 * 16 * 4) / 4];
1463 const BITMAPINFOHEADER
*bih
= (BITMAPINFOHEADER
*)buffer
;
1464 const DWORD
*data
= (DWORD
*)((char *)buffer
+ sizeof(BITMAPINFOHEADER
));
1465 BITMAPINFOHEADER expect_bih
= *req_bih
;
1466 OAFilterState state
;
1473 expect_bih
.biSizeImage
= 32 * 16 * 4;
1475 IBaseFilter_QueryInterface(filter
, &IID_IBasicVideo
, (void **)&video
);
1477 hr
= IBasicVideo_GetCurrentImage(video
, NULL
, NULL
);
1478 ok(hr
== E_POINTER
, "Got hr %#x.\n", hr
);
1480 hr
= IBasicVideo_GetCurrentImage(video
, NULL
, buffer
);
1481 ok(hr
== E_POINTER
, "Got hr %#x.\n", hr
);
1484 hr
= IBasicVideo_GetCurrentImage(video
, &size
, NULL
);
1485 todo_wine
ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1486 todo_wine
ok(size
== sizeof(BITMAPINFOHEADER
) + 32 * 16 * 4, "Got size %d.\n", size
);
1488 size
= sizeof(buffer
);
1489 hr
= IBasicVideo_GetCurrentImage(video
, &size
, buffer
);
1490 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1491 ok(size
== sizeof(buffer
), "Got size %d.\n", size
);
1492 ok(!memcmp(bih
, &expect_bih
, sizeof(BITMAPINFOHEADER
)), "Bitmap headers didn't match.\n");
1493 /* The contents seem to reflect the last frame rendered. */
1495 commit_allocator(input
);
1496 hr
= IMediaControl_Pause(control
);
1497 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
1499 size
= sizeof(buffer
);
1500 hr
= IBasicVideo_GetCurrentImage(video
, &size
, buffer
);
1501 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1502 ok(size
== sizeof(buffer
), "Got size %d.\n", size
);
1503 ok(!memcmp(bih
, &expect_bih
, sizeof(BITMAPINFOHEADER
)), "Bitmap headers didn't match.\n");
1504 /* The contents seem to reflect the last frame rendered. */
1506 thread
= send_frame(input
);
1507 hr
= IMediaControl_GetState(control
, 1000, &state
);
1508 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1511 memset(buffer
, 0xcc, sizeof(buffer
));
1512 hr
= IBasicVideo_GetCurrentImage(video
, &size
, buffer
);
1513 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1514 ok(size
== 1, "Got size %d.\n", size
);
1516 size
= sizeof(buffer
);
1517 memset(buffer
, 0xcc, sizeof(buffer
));
1518 hr
= IBasicVideo_GetCurrentImage(video
, &size
, buffer
);
1519 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1520 ok(size
== sizeof(buffer
), "Got size %d.\n", size
);
1521 ok(!memcmp(bih
, &expect_bih
, sizeof(BITMAPINFOHEADER
)), "Bitmap headers didn't match.\n");
1522 for (i
= 0; i
< 32 * 16; ++i
)
1523 ok((data
[i
] & 0xffffff) == 0x7f007f, "Got unexpected color %08x at %u.\n", data
[i
], i
);
1525 hr
= IMediaControl_Run(control
);
1526 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1527 join_thread(thread
);
1529 size
= sizeof(buffer
);
1530 memset(buffer
, 0xcc, sizeof(buffer
));
1531 hr
= IBasicVideo_GetCurrentImage(video
, &size
, buffer
);
1532 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1533 ok(size
== sizeof(buffer
), "Got size %d.\n", size
);
1534 ok(!memcmp(bih
, &expect_bih
, sizeof(BITMAPINFOHEADER
)), "Bitmap headers didn't match.\n");
1535 for (i
= 0; i
< 32 * 16; ++i
)
1536 ok((data
[i
] & 0xffffff) == 0x7f007f, "Got unexpected color %08x at %u.\n", data
[i
], i
);
1538 hr
= IMediaControl_Stop(control
);
1539 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1541 IBasicVideo_Release(video
);
1544 static void test_connect_pin(void)
1546 VIDEOINFOHEADER vih
=
1548 .bmiHeader
.biSize
= sizeof(BITMAPINFOHEADER
),
1549 .bmiHeader
.biBitCount
= 32,
1550 .bmiHeader
.biWidth
= 32,
1551 .bmiHeader
.biHeight
= 16,
1552 .bmiHeader
.biPlanes
= 1,
1553 .bmiHeader
.biCompression
= BI_RGB
,
1555 AM_MEDIA_TYPE req_mt
=
1557 .majortype
= MEDIATYPE_Video
,
1558 .formattype
= FORMAT_VideoInfo
,
1559 .cbFormat
= sizeof(vih
),
1560 .pbFormat
= (BYTE
*)&vih
,
1562 ALLOCATOR_PROPERTIES req_props
= {1, 32 * 16 * 4, 1, 0}, ret_props
;
1563 IBaseFilter
*filter
= create_vmr9(VMR9Mode_Windowed
);
1564 IFilterGraph2
*graph
= create_graph();
1565 struct testfilter source
;
1566 IMemAllocator
*allocator
;
1567 IMediaControl
*control
;
1568 IMemInputPin
*input
;
1575 static const GUID
*subtype_tests
[] =
1577 &MEDIASUBTYPE_RGB555
,
1578 &MEDIASUBTYPE_RGB565
,
1579 &MEDIASUBTYPE_RGB24
,
1580 &MEDIASUBTYPE_RGB32
,
1582 static const WORD bpp_tests
[] = {15, 16, 24, 32};
1584 testfilter_init(&source
);
1586 IFilterGraph2_AddFilter(graph
, &source
.filter
.IBaseFilter_iface
, NULL
);
1587 IFilterGraph2_AddFilter(graph
, filter
, NULL
);
1588 IFilterGraph2_QueryInterface(graph
, &IID_IMediaControl
, (void **)&control
);
1590 IBaseFilter_FindPin(filter
, L
"VMR Input0", &pin
);
1591 IPin_QueryInterface(pin
, &IID_IMemInputPin
, (void **)&input
);
1593 for (i
= 0; i
< ARRAY_SIZE(subtype_tests
); ++i
)
1595 req_mt
.subtype
= *subtype_tests
[i
];
1597 for (j
= 0; j
< ARRAY_SIZE(bpp_tests
); ++j
)
1599 vih
.bmiHeader
.biBitCount
= bpp_tests
[j
];
1601 hr
= IFilterGraph2_ConnectDirect(graph
, &source
.source
.pin
.IPin_iface
, pin
, &req_mt
);
1604 skip("Got E_FAIL when connecting.\n");
1607 ok(hr
== S_OK
, "Got hr %#x for subtype %s and bpp %u.\n", hr
,
1608 wine_dbgstr_guid(subtype_tests
[i
]), bpp_tests
[j
]);
1610 hr
= IFilterGraph2_Disconnect(graph
, &source
.source
.pin
.IPin_iface
);
1611 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1612 hr
= IFilterGraph2_Disconnect(graph
, pin
);
1613 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1617 req_mt
.formattype
= FORMAT_None
;
1618 hr
= IFilterGraph2_ConnectDirect(graph
, &source
.source
.pin
.IPin_iface
, pin
, &req_mt
);
1619 ok(hr
== VFW_E_TYPE_NOT_ACCEPTED
, "Got hr %#x.\n", hr
);
1620 req_mt
.formattype
= FORMAT_VideoInfo
;
1622 req_mt
.subtype
= MEDIASUBTYPE_RGB8
;
1623 hr
= IFilterGraph2_ConnectDirect(graph
, &source
.source
.pin
.IPin_iface
, pin
, &req_mt
);
1624 ok(hr
== VFW_E_TYPE_NOT_ACCEPTED
, "Got hr %#x.\n", hr
);
1625 req_mt
.subtype
= MEDIASUBTYPE_WAVE
;
1626 hr
= IFilterGraph2_ConnectDirect(graph
, &source
.source
.pin
.IPin_iface
, pin
, &req_mt
);
1627 ok(hr
== VFW_E_TYPE_NOT_ACCEPTED
, "Got hr %#x.\n", hr
);
1628 req_mt
.subtype
= MEDIASUBTYPE_RGB32
;
1630 peer
= (IPin
*)0xdeadbeef;
1631 hr
= IPin_ConnectedTo(pin
, &peer
);
1632 ok(hr
== VFW_E_NOT_CONNECTED
, "Got hr %#x.\n", hr
);
1633 ok(!peer
, "Got peer %p.\n", peer
);
1635 hr
= IPin_ConnectionMediaType(pin
, &mt
);
1636 ok(hr
== VFW_E_NOT_CONNECTED
, "Got hr %#x.\n", hr
);
1638 hr
= IMediaControl_Pause(control
);
1639 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1640 hr
= IFilterGraph2_ConnectDirect(graph
, &source
.source
.pin
.IPin_iface
, pin
, &req_mt
);
1641 ok(hr
== VFW_E_NOT_STOPPED
, "Got hr %#x.\n", hr
);
1642 hr
= IMediaControl_Stop(control
);
1643 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1645 hr
= IFilterGraph2_ConnectDirect(graph
, &source
.source
.pin
.IPin_iface
, pin
, &req_mt
);
1646 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1648 hr
= IPin_ConnectedTo(pin
, &peer
);
1649 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1650 ok(peer
== &source
.source
.pin
.IPin_iface
, "Got peer %p.\n", peer
);
1653 hr
= IPin_ConnectionMediaType(pin
, &mt
);
1654 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1655 ok(compare_media_types(&mt
, &req_mt
), "Media types didn't match.\n");
1657 /* Disconnecting while not stopped is broken: it returns S_OK, but
1658 * subsequent attempts to connect return VFW_E_ALREADY_CONNECTED. */
1660 test_allocator(input
);
1662 hr
= IMemInputPin_GetAllocator(input
, &allocator
);
1663 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1664 hr
= IMemAllocator_SetProperties(allocator
, &req_props
, &ret_props
);
1665 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1666 ok(!memcmp(&ret_props
, &req_props
, sizeof(req_props
)), "Properties did not match.\n");
1667 hr
= IMemAllocator_Commit(allocator
);
1668 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1669 IMemAllocator_Release(allocator
);
1671 hr
= IMemInputPin_ReceiveCanBlock(input
);
1672 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1674 test_filter_state(input
, control
);
1675 test_flushing(pin
, input
, control
);
1676 test_eos(pin
, input
, control
);
1677 test_sample_time(pin
, input
, control
);
1678 test_current_image(filter
, input
, control
, &vih
.bmiHeader
);
1680 hr
= IFilterGraph2_Disconnect(graph
, pin
);
1681 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1682 hr
= IFilterGraph2_Disconnect(graph
, pin
);
1683 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
1684 ok(source
.source
.pin
.peer
== pin
, "Got peer %p.\n", source
.source
.pin
.peer
);
1685 IFilterGraph2_Disconnect(graph
, &source
.source
.pin
.IPin_iface
);
1687 peer
= (IPin
*)0xdeadbeef;
1688 hr
= IPin_ConnectedTo(pin
, &peer
);
1689 ok(hr
== VFW_E_NOT_CONNECTED
, "Got hr %#x.\n", hr
);
1690 ok(!peer
, "Got peer %p.\n", peer
);
1692 hr
= IPin_ConnectionMediaType(pin
, &mt
);
1693 ok(hr
== VFW_E_NOT_CONNECTED
, "Got hr %#x.\n", hr
);
1696 IMediaControl_Release(control
);
1697 ref
= IFilterGraph2_Release(graph
);
1698 ok(!ref
, "Got outstanding refcount %d.\n", ref
);
1699 IMemInputPin_Release(input
);
1701 ref
= IBaseFilter_Release(filter
);
1702 ok(!ref
, "Got outstanding refcount %d.\n", ref
);
1703 ref
= IBaseFilter_Release(&source
.filter
.IBaseFilter_iface
);
1704 ok(!ref
, "Got outstanding refcount %d.\n", ref
);
1707 static void test_overlay(void)
1709 IBaseFilter
*filter
= create_vmr9(0);
1716 IBaseFilter_FindPin(filter
, L
"VMR Input0", &pin
);
1718 hr
= IPin_QueryInterface(pin
, &IID_IOverlay
, (void **)&overlay
);
1719 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1721 hwnd
= (HWND
)0xdeadbeef;
1722 hr
= IOverlay_GetWindowHandle(overlay
, &hwnd
);
1723 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1724 ok(hwnd
&& hwnd
!= (HWND
)0xdeadbeef, "Got invalid window %p.\n", hwnd
);
1726 IOverlay_Release(overlay
);
1728 ref
= IBaseFilter_Release(filter
);
1729 ok(!ref
, "Got outstanding refcount %d.\n", ref
);
1731 filter
= create_vmr9(VMR9Mode_Windowless
);
1732 IBaseFilter_FindPin(filter
, L
"VMR Input0", &pin
);
1734 hr
= IPin_QueryInterface(pin
, &IID_IOverlay
, (void **)&overlay
);
1735 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1737 hwnd
= (HWND
)0xdeadbeef;
1738 hr
= IOverlay_GetWindowHandle(overlay
, &hwnd
);
1739 ok(hr
== VFW_E_WRONG_STATE
, "Got hr %#x.\n", hr
);
1740 ok(hwnd
== (HWND
)0xdeadbeef, "Got window %p.\n", hwnd
);
1742 IOverlay_Release(overlay
);
1744 ref
= IBaseFilter_Release(filter
);
1745 ok(!ref
, "Got outstanding refcount %d.\n", ref
);
1747 filter
= create_vmr9(VMR9Mode_Renderless
);
1748 IBaseFilter_FindPin(filter
, L
"VMR Input0", &pin
);
1750 hr
= IPin_QueryInterface(pin
, &IID_IOverlay
, (void **)&overlay
);
1751 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1753 hwnd
= (HWND
)0xdeadbeef;
1754 hr
= IOverlay_GetWindowHandle(overlay
, &hwnd
);
1755 ok(hr
== VFW_E_WRONG_STATE
, "Got hr %#x.\n", hr
);
1756 ok(hwnd
== (HWND
)0xdeadbeef, "Got window %p.\n", hwnd
);
1758 IOverlay_Release(overlay
);
1760 ref
= IBaseFilter_Release(filter
);
1761 ok(!ref
, "Got outstanding refcount %d.\n", ref
);
1764 /* try to make sure pending X events have been processed before continuing */
1765 static void flush_events(void)
1771 time
= GetTickCount() + diff
;
1774 if (MsgWaitForMultipleObjects(0, NULL
, FALSE
, 100, QS_ALLINPUT
) == WAIT_TIMEOUT
)
1776 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
))
1777 DispatchMessageA(&msg
);
1778 diff
= time
- GetTickCount();
1782 static LRESULT CALLBACK
window_proc(HWND hwnd
, UINT msg
, WPARAM wparam
, LPARAM lparam
)
1784 if (winetest_debug
> 1)
1785 trace("hwnd %p, msg %#x, wparam %#lx, lparam %#lx.\n", hwnd
, msg
, wparam
, lparam
);
1787 if (wparam
== 0xdeadbeef)
1790 return DefWindowProcA(hwnd
, msg
, wparam
, lparam
);
1793 static void test_video_window_caption(IVideoWindow
*window
, HWND hwnd
)
1799 hr
= IVideoWindow_get_Caption(window
, &caption
);
1800 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1801 ok(!wcscmp(caption
, L
"ActiveMovie Window"), "Got caption %s.\n", wine_dbgstr_w(caption
));
1802 SysFreeString(caption
);
1804 GetWindowTextW(hwnd
, text
, ARRAY_SIZE(text
));
1805 ok(!wcscmp(text
, L
"ActiveMovie Window"), "Got caption %s.\n", wine_dbgstr_w(text
));
1807 caption
= SysAllocString(L
"foo");
1808 hr
= IVideoWindow_put_Caption(window
, caption
);
1809 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1810 SysFreeString(caption
);
1812 hr
= IVideoWindow_get_Caption(window
, &caption
);
1813 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1814 ok(!wcscmp(caption
, L
"foo"), "Got caption %s.\n", wine_dbgstr_w(caption
));
1815 SysFreeString(caption
);
1817 GetWindowTextW(hwnd
, text
, ARRAY_SIZE(text
));
1818 ok(!wcscmp(text
, L
"foo"), "Got caption %s.\n", wine_dbgstr_w(text
));
1821 static void test_video_window_style(IVideoWindow
*window
, HWND hwnd
, HWND our_hwnd
)
1826 hr
= IVideoWindow_get_WindowStyle(window
, &style
);
1827 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1828 ok(style
== (WS_CLIPSIBLINGS
| WS_CLIPCHILDREN
| WS_OVERLAPPEDWINDOW
),
1829 "Got style %#x.\n", style
);
1831 style
= GetWindowLongA(hwnd
, GWL_STYLE
);
1832 ok(style
== (WS_CLIPSIBLINGS
| WS_CLIPCHILDREN
| WS_OVERLAPPEDWINDOW
),
1833 "Got style %#x.\n", style
);
1835 hr
= IVideoWindow_put_WindowStyle(window
, style
| WS_DISABLED
);
1836 ok(hr
== E_INVALIDARG
, "Got hr %#x.\n", hr
);
1837 hr
= IVideoWindow_put_WindowStyle(window
, style
| WS_HSCROLL
);
1838 ok(hr
== E_INVALIDARG
, "Got hr %#x.\n", hr
);
1839 hr
= IVideoWindow_put_WindowStyle(window
, style
| WS_VSCROLL
);
1840 ok(hr
== E_INVALIDARG
, "Got hr %#x.\n", hr
);
1841 hr
= IVideoWindow_put_WindowStyle(window
, style
| WS_MAXIMIZE
);
1842 ok(hr
== E_INVALIDARG
, "Got hr %#x.\n", hr
);
1843 hr
= IVideoWindow_put_WindowStyle(window
, style
| WS_MINIMIZE
);
1844 ok(hr
== E_INVALIDARG
, "Got hr %#x.\n", hr
);
1846 hr
= IVideoWindow_put_WindowStyle(window
, style
& ~WS_CLIPCHILDREN
);
1847 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1849 hr
= IVideoWindow_get_WindowStyle(window
, &style
);
1850 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1851 ok(style
== (WS_CLIPSIBLINGS
| WS_OVERLAPPEDWINDOW
), "Got style %#x.\n", style
);
1853 style
= GetWindowLongA(hwnd
, GWL_STYLE
);
1854 ok(style
== (WS_CLIPSIBLINGS
| WS_OVERLAPPEDWINDOW
), "Got style %#x.\n", style
);
1856 ok(GetActiveWindow() == our_hwnd
, "Got active window %p.\n", GetActiveWindow());
1858 hr
= IVideoWindow_get_WindowStyleEx(window
, &style
);
1859 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1860 ok(style
== WS_EX_WINDOWEDGE
, "Got style %#x.\n", style
);
1862 style
= GetWindowLongA(hwnd
, GWL_EXSTYLE
);
1863 ok(style
== WS_EX_WINDOWEDGE
, "Got style %#x.\n", style
);
1865 hr
= IVideoWindow_put_WindowStyleEx(window
, style
| WS_EX_TRANSPARENT
);
1866 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1868 hr
= IVideoWindow_get_WindowStyleEx(window
, &style
);
1869 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1870 ok(style
== (WS_EX_WINDOWEDGE
| WS_EX_TRANSPARENT
), "Got style %#x.\n", style
);
1872 style
= GetWindowLongA(hwnd
, GWL_EXSTYLE
);
1873 ok(style
== (WS_EX_WINDOWEDGE
| WS_EX_TRANSPARENT
), "Got style %#x.\n", style
);
1876 static BOOL CALLBACK
top_window_cb(HWND hwnd
, LPARAM ctx
)
1879 GetWindowThreadProcessId(hwnd
, &pid
);
1880 if (pid
== GetCurrentProcessId() && (GetWindowLongW(hwnd
, GWL_STYLE
) & WS_VISIBLE
))
1882 *(HWND
*)ctx
= hwnd
;
1888 static HWND
get_top_window(void)
1891 EnumWindows(top_window_cb
, (LPARAM
)&hwnd
);
1895 static void test_video_window_state(IVideoWindow
*window
, HWND hwnd
, HWND our_hwnd
)
1901 SetWindowPos(our_hwnd
, HWND_TOP
, 0, 0, 0, 0, SWP_NOMOVE
| SWP_NOSIZE
);
1903 hr
= IVideoWindow_get_WindowState(window
, &state
);
1904 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1905 ok(state
== SW_HIDE
, "Got state %d.\n", state
);
1907 hr
= IVideoWindow_get_Visible(window
, &state
);
1908 ok(state
== OAFALSE
, "Got state %d.\n", state
);
1910 ok(!IsWindowVisible(hwnd
), "Window should not be visible.\n");
1911 ok(!IsIconic(hwnd
), "Window should not be minimized.\n");
1912 ok(!IsZoomed(hwnd
), "Window should not be maximized.\n");
1914 hr
= IVideoWindow_put_WindowState(window
, SW_SHOWNA
);
1915 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1917 hr
= IVideoWindow_get_WindowState(window
, &state
);
1918 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1919 ok(state
== SW_SHOW
, "Got state %d.\n", state
);
1921 hr
= IVideoWindow_get_Visible(window
, &state
);
1922 ok(state
== OATRUE
, "Got state %d.\n", state
);
1924 ok(IsWindowVisible(hwnd
), "Window should be visible.\n");
1925 ok(!IsIconic(hwnd
), "Window should not be minimized.\n");
1926 ok(!IsZoomed(hwnd
), "Window should not be maximized.\n");
1927 ok(GetActiveWindow() == our_hwnd
, "Got active window %p.\n", GetActiveWindow());
1928 top
= get_top_window();
1929 ok(top
== hwnd
, "Got top window %p.\n", top
);
1931 hr
= IVideoWindow_put_WindowState(window
, SW_MINIMIZE
);
1932 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1934 hr
= IVideoWindow_get_WindowState(window
, &state
);
1935 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1936 ok(state
== SW_MINIMIZE
, "Got state %d.\n", state
);
1938 hr
= IVideoWindow_get_Visible(window
, &state
);
1939 ok(state
== OATRUE
, "Got state %d.\n", state
);
1941 ok(IsWindowVisible(hwnd
), "Window should be visible.\n");
1942 ok(IsIconic(hwnd
), "Window should be minimized.\n");
1943 ok(!IsZoomed(hwnd
), "Window should not be maximized.\n");
1944 ok(GetActiveWindow() == our_hwnd
, "Got active window %p.\n", GetActiveWindow());
1946 hr
= IVideoWindow_put_WindowState(window
, SW_RESTORE
);
1947 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1949 hr
= IVideoWindow_get_WindowState(window
, &state
);
1950 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1951 ok(state
== SW_SHOW
, "Got state %d.\n", state
);
1953 hr
= IVideoWindow_get_Visible(window
, &state
);
1954 ok(state
== OATRUE
, "Got state %d.\n", state
);
1956 ok(IsWindowVisible(hwnd
), "Window should be visible.\n");
1957 ok(!IsIconic(hwnd
), "Window should not be minimized.\n");
1958 ok(!IsZoomed(hwnd
), "Window should not be maximized.\n");
1959 ok(GetActiveWindow() == hwnd
, "Got active window %p.\n", GetActiveWindow());
1961 hr
= IVideoWindow_put_WindowState(window
, SW_MAXIMIZE
);
1962 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1964 hr
= IVideoWindow_get_WindowState(window
, &state
);
1965 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1966 ok(state
== SW_MAXIMIZE
, "Got state %d.\n", state
);
1968 hr
= IVideoWindow_get_Visible(window
, &state
);
1969 ok(state
== OATRUE
, "Got state %d.\n", state
);
1971 ok(IsWindowVisible(hwnd
), "Window should be visible.\n");
1972 ok(!IsIconic(hwnd
), "Window should be minimized.\n");
1973 ok(IsZoomed(hwnd
), "Window should not be maximized.\n");
1974 ok(GetActiveWindow() == hwnd
, "Got active window %p.\n", GetActiveWindow());
1976 hr
= IVideoWindow_put_WindowState(window
, SW_RESTORE
);
1977 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1979 hr
= IVideoWindow_put_WindowState(window
, SW_HIDE
);
1980 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1982 hr
= IVideoWindow_get_WindowState(window
, &state
);
1983 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1984 ok(state
== SW_HIDE
, "Got state %d.\n", state
);
1986 hr
= IVideoWindow_get_Visible(window
, &state
);
1987 ok(state
== OAFALSE
, "Got state %d.\n", state
);
1989 ok(!IsWindowVisible(hwnd
), "Window should not be visible.\n");
1990 ok(!IsIconic(hwnd
), "Window should not be minimized.\n");
1991 ok(!IsZoomed(hwnd
), "Window should not be maximized.\n");
1992 ok(GetActiveWindow() == our_hwnd
, "Got active window %p.\n", GetActiveWindow());
1994 hr
= IVideoWindow_put_Visible(window
, OATRUE
);
1995 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1997 hr
= IVideoWindow_get_WindowState(window
, &state
);
1998 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1999 ok(state
== SW_SHOW
, "Got state %d.\n", state
);
2001 hr
= IVideoWindow_get_Visible(window
, &state
);
2002 ok(state
== OATRUE
, "Got state %d.\n", state
);
2004 ok(IsWindowVisible(hwnd
), "Window should be visible.\n");
2005 ok(!IsIconic(hwnd
), "Window should not be minimized.\n");
2006 ok(!IsZoomed(hwnd
), "Window should not be maximized.\n");
2007 ok(GetActiveWindow() == hwnd
, "Got active window %p.\n", GetActiveWindow());
2009 hr
= IVideoWindow_put_Visible(window
, OAFALSE
);
2010 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2012 hr
= IVideoWindow_get_WindowState(window
, &state
);
2013 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2014 ok(state
== SW_HIDE
, "Got state %d.\n", state
);
2016 hr
= IVideoWindow_get_Visible(window
, &state
);
2017 ok(state
== OAFALSE
, "Got state %d.\n", state
);
2019 ok(!IsWindowVisible(hwnd
), "Window should not be visible.\n");
2020 ok(!IsIconic(hwnd
), "Window should not be minimized.\n");
2021 ok(!IsZoomed(hwnd
), "Window should not be maximized.\n");
2022 ok(GetActiveWindow() == our_hwnd
, "Got active window %p.\n", GetActiveWindow());
2024 hr
= IVideoWindow_put_WindowState(window
, SW_SHOWNA
);
2025 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2027 hr
= IVideoWindow_SetWindowForeground(window
, TRUE
);
2028 ok(hr
== E_INVALIDARG
, "Got hr %#x.\n", hr
);
2030 SetWindowPos(our_hwnd
, HWND_TOP
, 0, 0, 0, 0, SWP_NOMOVE
| SWP_NOSIZE
);
2031 hr
= IVideoWindow_SetWindowForeground(window
, OATRUE
);
2032 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2033 ok(GetActiveWindow() == hwnd
, "Got active window %p.\n", GetActiveWindow());
2034 ok(GetFocus() == hwnd
, "Got focus window %p.\n", GetFocus());
2035 ok(GetForegroundWindow() == hwnd
, "Got foreground window %p.\n", GetForegroundWindow());
2036 top
= get_top_window();
2037 ok(top
== hwnd
, "Got top window %p.\n", top
);
2039 hr
= IVideoWindow_SetWindowForeground(window
, OAFALSE
);
2040 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2041 ok(GetActiveWindow() == hwnd
, "Got active window %p.\n", GetActiveWindow());
2042 ok(GetFocus() == hwnd
, "Got focus window %p.\n", GetFocus());
2043 ok(GetForegroundWindow() == hwnd
, "Got foreground window %p.\n", GetForegroundWindow());
2044 top
= get_top_window();
2045 ok(top
== hwnd
, "Got top window %p.\n", top
);
2047 SetWindowPos(our_hwnd
, HWND_TOP
, 0, 0, 0, 0, SWP_NOMOVE
| SWP_NOSIZE
);
2048 hr
= IVideoWindow_SetWindowForeground(window
, OAFALSE
);
2049 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2050 ok(GetActiveWindow() == our_hwnd
, "Got active window %p.\n", GetActiveWindow());
2051 ok(GetFocus() == our_hwnd
, "Got focus window %p.\n", GetFocus());
2052 ok(GetForegroundWindow() == our_hwnd
, "Got foreground window %p.\n", GetForegroundWindow());
2053 top
= get_top_window();
2054 ok(top
== hwnd
, "Got top window %p.\n", top
);
2057 static void test_video_window_position(IVideoWindow
*window
, HWND hwnd
, HWND our_hwnd
)
2059 LONG left
, width
, top
, height
, expect_width
, expect_height
;
2060 RECT rect
= {0, 0, 600, 400};
2064 SetWindowPos(our_hwnd
, HWND_TOP
, 0, 0, 0, 0, SWP_NOMOVE
| SWP_NOSIZE
);
2066 AdjustWindowRect(&rect
, GetWindowLongA(hwnd
, GWL_STYLE
), FALSE
);
2067 expect_width
= rect
.right
- rect
.left
;
2068 expect_height
= rect
.bottom
- rect
.top
;
2070 hr
= IVideoWindow_put_Left(window
, 0);
2071 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2072 hr
= IVideoWindow_put_Top(window
, 0);
2073 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2075 hr
= IVideoWindow_get_Left(window
, &left
);
2076 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2077 ok(left
== 0, "Got left %d.\n", left
);
2078 hr
= IVideoWindow_get_Top(window
, &top
);
2079 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2080 ok(top
== 0, "Got top %d.\n", top
);
2081 hr
= IVideoWindow_get_Width(window
, &width
);
2082 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2083 ok(width
== expect_width
, "Got width %d.\n", width
);
2084 hr
= IVideoWindow_get_Height(window
, &height
);
2085 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2086 ok(height
== expect_height
, "Got height %d.\n", height
);
2087 hr
= IVideoWindow_GetWindowPosition(window
, &left
, &top
, &width
, &height
);
2088 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2089 ok(left
== 0, "Got left %d.\n", left
);
2090 ok(top
== 0, "Got top %d.\n", top
);
2091 ok(width
== expect_width
, "Got width %d.\n", width
);
2092 ok(height
== expect_height
, "Got height %d.\n", height
);
2093 GetWindowRect(hwnd
, &rect
);
2094 ok(rect
.left
== 0, "Got window left %d.\n", rect
.left
);
2095 ok(rect
.top
== 0, "Got window top %d.\n", rect
.top
);
2096 ok(rect
.right
== expect_width
, "Got window right %d.\n", rect
.right
);
2097 ok(rect
.bottom
== expect_height
, "Got window bottom %d.\n", rect
.bottom
);
2099 hr
= IVideoWindow_put_Left(window
, 10);
2100 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2102 hr
= IVideoWindow_get_Left(window
, &left
);
2103 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2104 ok(left
== 10, "Got left %d.\n", left
);
2105 hr
= IVideoWindow_get_Top(window
, &top
);
2106 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2107 ok(top
== 0, "Got top %d.\n", top
);
2108 hr
= IVideoWindow_get_Width(window
, &width
);
2109 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2110 ok(width
== expect_width
, "Got width %d.\n", width
);
2111 hr
= IVideoWindow_get_Height(window
, &height
);
2112 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2113 ok(height
== expect_height
, "Got height %d.\n", height
);
2114 hr
= IVideoWindow_GetWindowPosition(window
, &left
, &top
, &width
, &height
);
2115 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2116 ok(left
== 10, "Got left %d.\n", left
);
2117 ok(top
== 0, "Got top %d.\n", top
);
2118 ok(width
== expect_width
, "Got width %d.\n", width
);
2119 ok(height
== expect_height
, "Got height %d.\n", height
);
2120 GetWindowRect(hwnd
, &rect
);
2121 ok(rect
.left
== 10, "Got window left %d.\n", rect
.left
);
2122 ok(rect
.top
== 0, "Got window top %d.\n", rect
.top
);
2123 ok(rect
.right
== 10 + expect_width
, "Got window right %d.\n", rect
.right
);
2124 ok(rect
.bottom
== expect_height
, "Got window bottom %d.\n", rect
.bottom
);
2126 hr
= IVideoWindow_put_Height(window
, 200);
2127 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2129 hr
= IVideoWindow_get_Left(window
, &left
);
2130 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2131 ok(left
== 10, "Got left %d.\n", left
);
2132 hr
= IVideoWindow_get_Top(window
, &top
);
2133 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2134 ok(top
== 0, "Got top %d.\n", top
);
2135 hr
= IVideoWindow_get_Width(window
, &width
);
2136 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2137 ok(width
== expect_width
, "Got width %d.\n", width
);
2138 hr
= IVideoWindow_get_Height(window
, &height
);
2139 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2140 ok(height
== 200, "Got height %d.\n", height
);
2141 hr
= IVideoWindow_GetWindowPosition(window
, &left
, &top
, &width
, &height
);
2142 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2143 ok(left
== 10, "Got left %d.\n", left
);
2144 ok(top
== 0, "Got top %d.\n", top
);
2145 ok(width
== expect_width
, "Got width %d.\n", width
);
2146 ok(height
== 200, "Got height %d.\n", height
);
2147 GetWindowRect(hwnd
, &rect
);
2148 ok(rect
.left
== 10, "Got window left %d.\n", rect
.left
);
2149 ok(rect
.top
== 0, "Got window top %d.\n", rect
.top
);
2150 ok(rect
.right
== 10 + expect_width
, "Got window right %d.\n", rect
.right
);
2151 ok(rect
.bottom
== 200, "Got window bottom %d.\n", rect
.bottom
);
2153 hr
= IVideoWindow_SetWindowPosition(window
, 100, 200, 300, 400);
2154 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2156 hr
= IVideoWindow_get_Left(window
, &left
);
2157 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2158 ok(left
== 100, "Got left %d.\n", left
);
2159 hr
= IVideoWindow_get_Top(window
, &top
);
2160 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2161 ok(top
== 200, "Got top %d.\n", top
);
2162 hr
= IVideoWindow_get_Width(window
, &width
);
2163 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2164 ok(width
== 300, "Got width %d.\n", width
);
2165 hr
= IVideoWindow_get_Height(window
, &height
);
2166 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2167 ok(height
== 400, "Got height %d.\n", height
);
2168 hr
= IVideoWindow_GetWindowPosition(window
, &left
, &top
, &width
, &height
);
2169 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2170 ok(left
== 100, "Got left %d.\n", left
);
2171 ok(top
== 200, "Got top %d.\n", top
);
2172 ok(width
== 300, "Got width %d.\n", width
);
2173 ok(height
== 400, "Got height %d.\n", height
);
2174 GetWindowRect(hwnd
, &rect
);
2175 ok(rect
.left
== 100, "Got window left %d.\n", rect
.left
);
2176 ok(rect
.top
== 200, "Got window top %d.\n", rect
.top
);
2177 ok(rect
.right
== 400, "Got window right %d.\n", rect
.right
);
2178 ok(rect
.bottom
== 600, "Got window bottom %d.\n", rect
.bottom
);
2180 ok(GetActiveWindow() == our_hwnd
, "Got active window %p.\n", GetActiveWindow());
2181 top_hwnd
= get_top_window();
2182 ok(top_hwnd
== our_hwnd
, "Got top window %p.\n", top_hwnd
);
2185 static void test_video_window_owner(IVideoWindow
*window
, HWND hwnd
, HWND our_hwnd
)
2187 HWND parent
, top_hwnd
;
2192 SetWindowPos(our_hwnd
, HWND_TOP
, 0, 0, 0, 0, SWP_NOMOVE
| SWP_NOSIZE
);
2194 hr
= IVideoWindow_get_Owner(window
, &oahwnd
);
2195 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2196 ok(!oahwnd
, "Got owner %#lx.\n", oahwnd
);
2198 parent
= GetAncestor(hwnd
, GA_PARENT
);
2199 ok(parent
== GetDesktopWindow(), "Got parent %p.\n", parent
);
2200 style
= GetWindowLongA(hwnd
, GWL_STYLE
);
2201 ok(!(style
& WS_CHILD
), "Got style %#x.\n", style
);
2203 hr
= IVideoWindow_put_Owner(window
, (OAHWND
)our_hwnd
);
2204 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2206 hr
= IVideoWindow_get_Owner(window
, &oahwnd
);
2207 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2208 ok(oahwnd
== (OAHWND
)our_hwnd
, "Got owner %#lx.\n", oahwnd
);
2210 parent
= GetAncestor(hwnd
, GA_PARENT
);
2211 ok(parent
== our_hwnd
, "Got parent %p.\n", parent
);
2212 style
= GetWindowLongA(hwnd
, GWL_STYLE
);
2213 ok((style
& WS_CHILD
), "Got style %#x.\n", style
);
2215 ok(GetActiveWindow() == our_hwnd
, "Got active window %p.\n", GetActiveWindow());
2216 top_hwnd
= get_top_window();
2217 ok(top_hwnd
== our_hwnd
, "Got top window %p.\n", top_hwnd
);
2219 ShowWindow(our_hwnd
, SW_HIDE
);
2221 hr
= IVideoWindow_put_Visible(window
, OATRUE
);
2222 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2224 hr
= IVideoWindow_get_Visible(window
, &state
);
2225 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2226 ok(state
== OAFALSE
, "Got state %d.\n", state
);
2228 hr
= IVideoWindow_put_Owner(window
, 0);
2229 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2231 hr
= IVideoWindow_get_Owner(window
, &oahwnd
);
2232 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2233 ok(!oahwnd
, "Got owner %#lx.\n", oahwnd
);
2235 parent
= GetAncestor(hwnd
, GA_PARENT
);
2236 ok(parent
== GetDesktopWindow(), "Got parent %p.\n", parent
);
2237 style
= GetWindowLongA(hwnd
, GWL_STYLE
);
2238 ok(!(style
& WS_CHILD
), "Got style %#x.\n", style
);
2240 ok(GetActiveWindow() == hwnd
, "Got active window %p.\n", GetActiveWindow());
2241 top_hwnd
= get_top_window();
2242 ok(top_hwnd
== hwnd
, "Got top window %p.\n", top_hwnd
);
2244 hr
= IVideoWindow_get_Visible(window
, &state
);
2245 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2246 ok(state
== OATRUE
, "Got state %d.\n", state
);
2249 struct notify_message_params
2251 IVideoWindow
*window
;
2256 static DWORD CALLBACK
notify_message_proc(void *arg
)
2258 const struct notify_message_params
*params
= arg
;
2259 HRESULT hr
= IVideoWindow_NotifyOwnerMessage(params
->window
, (OAHWND
)params
->hwnd
, params
->message
, 0, 0);
2260 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2264 static void test_video_window_messages(IVideoWindow
*window
, HWND hwnd
, HWND our_hwnd
)
2266 struct notify_message_params params
;
2274 static UINT drain_tests
[] =
2302 hr
= IVideoWindow_get_MessageDrain(window
, &oahwnd
);
2303 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2304 ok(!oahwnd
, "Got window %#lx.\n", oahwnd
);
2306 hr
= IVideoWindow_put_MessageDrain(window
, (OAHWND
)our_hwnd
);
2307 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2309 hr
= IVideoWindow_get_MessageDrain(window
, &oahwnd
);
2310 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2311 ok(oahwnd
== (OAHWND
)our_hwnd
, "Got window %#lx.\n", oahwnd
);
2313 for (i
= 0; i
< ARRAY_SIZE(drain_tests
); ++i
)
2315 SendMessageA(hwnd
, drain_tests
[i
], 0xdeadbeef, 0);
2316 ret
= PeekMessageA(&msg
, 0, drain_tests
[i
], drain_tests
[i
], PM_REMOVE
);
2317 ok(ret
, "Expected a message.\n");
2318 ok(msg
.hwnd
== our_hwnd
, "Got hwnd %p.\n", msg
.hwnd
);
2319 ok(msg
.message
== drain_tests
[i
], "Got message %#x.\n", msg
.message
);
2320 ok(msg
.wParam
== 0xdeadbeef, "Got wparam %#lx.\n", msg
.wParam
);
2321 ok(!msg
.lParam
, "Got lparam %#lx.\n", msg
.lParam
);
2322 DispatchMessageA(&msg
);
2324 ret
= PeekMessageA(&msg
, 0, drain_tests
[i
], drain_tests
[i
], PM_REMOVE
);
2325 ok(!ret
, "Got unexpected message %#x.\n", msg
.message
);
2328 hr
= IVideoWindow_put_MessageDrain(window
, 0);
2329 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2331 hr
= IVideoWindow_put_Owner(window
, (OAHWND
)our_hwnd
);
2332 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2336 hr
= IVideoWindow_NotifyOwnerMessage(window
, (OAHWND
)our_hwnd
, WM_SYSCOLORCHANGE
, 0, 0);
2337 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2339 ret
= GetQueueStatus(QS_SENDMESSAGE
| QS_POSTMESSAGE
);
2340 ok(!ret
, "Got unexpected status %#x.\n", ret
);
2342 hr
= IVideoWindow_NotifyOwnerMessage(window
, (OAHWND
)our_hwnd
, WM_SETCURSOR
,
2343 (WPARAM
)hwnd
, MAKELONG(HTCLIENT
, WM_MOUSEMOVE
));
2344 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2346 ret
= GetQueueStatus(QS_SENDMESSAGE
| QS_POSTMESSAGE
);
2347 ok(!ret
, "Got unexpected status %#x.\n", ret
);
2349 params
.window
= window
;
2350 params
.hwnd
= our_hwnd
;
2351 params
.message
= WM_SYSCOLORCHANGE
;
2352 thread
= CreateThread(NULL
, 0, notify_message_proc
, ¶ms
, 0, NULL
);
2353 ok(WaitForSingleObject(thread
, 100) == WAIT_TIMEOUT
, "Thread should block.\n");
2354 ret
= GetQueueStatus(QS_SENDMESSAGE
| QS_POSTMESSAGE
);
2355 ok(ret
== ((QS_SENDMESSAGE
<< 16) | QS_SENDMESSAGE
), "Got unexpected status %#x.\n", ret
);
2357 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
2358 ok(!WaitForSingleObject(thread
, 1000), "Wait timed out.\n");
2359 CloseHandle(thread
);
2361 params
.message
= WM_SETCURSOR
;
2362 thread
= CreateThread(NULL
, 0, notify_message_proc
, ¶ms
, 0, NULL
);
2363 ok(!WaitForSingleObject(thread
, 1000), "Thread should not block.\n");
2364 CloseHandle(thread
);
2365 ret
= GetQueueStatus(QS_SENDMESSAGE
| QS_POSTMESSAGE
);
2366 ok(!ret
, "Got unexpected status %#x.\n", ret
);
2368 hr
= IVideoWindow_put_Owner(window
, 0);
2369 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2372 static void test_video_window_autoshow(IVideoWindow
*window
, IFilterGraph2
*graph
, HWND hwnd
)
2374 IMediaControl
*control
;
2378 IFilterGraph2_QueryInterface(graph
, &IID_IMediaControl
, (void **)&control
);
2380 hr
= IVideoWindow_get_AutoShow(window
, &l
);
2381 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2382 ok(l
== OATRUE
, "Got %d.\n", l
);
2384 hr
= IVideoWindow_put_Visible(window
, OAFALSE
);
2385 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2387 hr
= IMediaControl_Pause(control
);
2388 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
2390 hr
= IVideoWindow_get_Visible(window
, &l
);
2391 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2392 ok(l
== OATRUE
, "Got %d.\n", l
);
2394 hr
= IMediaControl_Stop(control
);
2395 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2397 hr
= IVideoWindow_get_Visible(window
, &l
);
2398 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2399 ok(l
== OATRUE
, "Got %d.\n", l
);
2401 hr
= IVideoWindow_put_AutoShow(window
, OAFALSE
);
2402 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2404 hr
= IVideoWindow_put_Visible(window
, OAFALSE
);
2405 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2407 hr
= IMediaControl_Pause(control
);
2408 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
2410 hr
= IVideoWindow_get_Visible(window
, &l
);
2411 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2412 ok(l
== OAFALSE
, "Got %d.\n", l
);
2414 hr
= IMediaControl_Stop(control
);
2415 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2417 IMediaControl_Release(control
);
2420 static void test_video_window(void)
2422 ALLOCATOR_PROPERTIES req_props
= {1, 600 * 400 * 4, 1, 0}, ret_props
;
2423 VIDEOINFOHEADER vih
=
2425 .bmiHeader
.biSize
= sizeof(BITMAPINFOHEADER
),
2426 .bmiHeader
.biBitCount
= 32,
2427 .bmiHeader
.biWidth
= 600,
2428 .bmiHeader
.biHeight
= 400,
2429 .bmiHeader
.biPlanes
= 1,
2430 .bmiHeader
.biCompression
= BI_RGB
,
2432 AM_MEDIA_TYPE req_mt
=
2434 .majortype
= MEDIATYPE_Video
,
2435 .subtype
= MEDIASUBTYPE_RGB32
,
2436 .formattype
= FORMAT_VideoInfo
,
2437 .cbFormat
= sizeof(vih
),
2438 .pbFormat
= (BYTE
*)&vih
,
2440 IFilterGraph2
*graph
= create_graph();
2441 WNDCLASSA window_class
= {0};
2442 struct testfilter source
;
2443 IMemAllocator
*allocator
;
2444 MONITORINFO monitorinfo
;
2445 IMediaControl
*control
;
2446 LONG width
, height
, l
;
2447 IVideoWindow
*window
;
2448 IMemInputPin
*input
;
2449 IBaseFilter
*filter
;
2450 HWND hwnd
, our_hwnd
;
2459 window_class
.lpszClassName
= "wine_test_class";
2460 window_class
.lpfnWndProc
= window_proc
;
2461 RegisterClassA(&window_class
);
2462 our_hwnd
= CreateWindowA("wine_test_class", "test window", WS_VISIBLE
| WS_OVERLAPPEDWINDOW
,
2463 100, 200, 300, 400, NULL
, NULL
, NULL
, NULL
);
2466 filter
= create_vmr9(VMR9Mode_Windowed
);
2469 ok(GetActiveWindow() == our_hwnd
, "Got active window %p.\n", GetActiveWindow());
2471 IBaseFilter_FindPin(filter
, L
"VMR Input0", &pin
);
2472 IPin_QueryInterface(pin
, &IID_IMemInputPin
, (void **)&input
);
2474 hr
= IPin_QueryInterface(pin
, &IID_IOverlay
, (void **)&overlay
);
2475 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2477 hr
= IOverlay_GetWindowHandle(overlay
, &hwnd
);
2478 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2479 if (winetest_debug
> 1) trace("ours %p, theirs %p\n", our_hwnd
, hwnd
);
2480 GetWindowRect(hwnd
, &rect
);
2482 tid
= GetWindowThreadProcessId(hwnd
, NULL
);
2483 ok(tid
== GetCurrentThreadId(), "Expected tid %#x, got %#x.\n", GetCurrentThreadId(), tid
);
2485 hr
= IBaseFilter_QueryInterface(filter
, &IID_IVideoWindow
, (void **)&window
);
2486 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2488 hr
= IVideoWindow_get_Caption(window
, &caption
);
2489 todo_wine
ok(hr
== VFW_E_NOT_CONNECTED
, "Got hr %#x.\n", hr
);
2491 hr
= IVideoWindow_get_WindowStyle(window
, &l
);
2492 todo_wine
ok(hr
== VFW_E_NOT_CONNECTED
, "Got hr %#x.\n", hr
);
2494 hr
= IVideoWindow_get_AutoShow(window
, &l
);
2495 todo_wine
ok(hr
== VFW_E_NOT_CONNECTED
, "Got hr %#x.\n", hr
);
2497 testfilter_init(&source
);
2498 IFilterGraph2_AddFilter(graph
, &source
.filter
.IBaseFilter_iface
, NULL
);
2499 IFilterGraph2_AddFilter(graph
, filter
, NULL
);
2500 IFilterGraph2_QueryInterface(graph
, &IID_IMediaControl
, (void **)&control
);
2501 hr
= IFilterGraph2_ConnectDirect(graph
, &source
.source
.pin
.IPin_iface
, pin
, &req_mt
);
2504 skip("Got E_FAIL when connecting.\n");
2507 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2509 hr
= IMemInputPin_GetAllocator(input
, &allocator
);
2510 todo_wine
ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2513 hr
= IMemAllocator_SetProperties(allocator
, &req_props
, &ret_props
);
2514 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2515 ok(!memcmp(&ret_props
, &req_props
, sizeof(req_props
)), "Properties did not match.\n");
2516 hr
= IMemAllocator_Commit(allocator
);
2517 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2518 IMemAllocator_Release(allocator
);
2521 ok(GetActiveWindow() == our_hwnd
, "Got active window %p.\n", GetActiveWindow());
2523 test_video_window_caption(window
, hwnd
);
2524 test_video_window_style(window
, hwnd
, our_hwnd
);
2525 test_video_window_state(window
, hwnd
, our_hwnd
);
2526 test_video_window_position(window
, hwnd
, our_hwnd
);
2527 test_video_window_autoshow(window
, graph
, hwnd
);
2528 test_video_window_owner(window
, hwnd
, our_hwnd
);
2529 test_video_window_messages(window
, hwnd
, our_hwnd
);
2531 hr
= IVideoWindow_put_FullScreenMode(window
, OATRUE
);
2532 ok(hr
== E_NOTIMPL
, "Got hr %#x.\n", hr
);
2533 hr
= IVideoWindow_get_FullScreenMode(window
, &l
);
2534 ok(hr
== E_NOTIMPL
, "Got hr %#x.\n", hr
);
2536 hr
= IVideoWindow_GetMinIdealImageSize(window
, &width
, &height
);
2537 todo_wine
ok(hr
== VFW_E_WRONG_STATE
, "Got hr %#x.\n", hr
);
2538 hr
= IVideoWindow_GetMaxIdealImageSize(window
, &width
, &height
);
2539 todo_wine
ok(hr
== VFW_E_WRONG_STATE
, "Got hr %#x.\n", hr
);
2541 hr
= IMediaControl_Pause(control
);
2542 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
2544 monitorinfo
.cbSize
= sizeof(monitorinfo
);
2545 GetMonitorInfoW(MonitorFromWindow(hwnd
, MONITOR_DEFAULTTOPRIMARY
), &monitorinfo
);
2547 hr
= IVideoWindow_GetMinIdealImageSize(window
, &width
, &height
);
2548 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2549 todo_wine
ok(width
== 1, "Got width %d.\n", width
);
2550 todo_wine
ok(height
== 1, "Got height %d.\n", height
);
2551 hr
= IVideoWindow_GetMaxIdealImageSize(window
, &width
, &height
);
2552 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2553 todo_wine
ok(width
== monitorinfo
.rcMonitor
.right
+ 1, "Expected width %d, got %d.\n",
2554 monitorinfo
.rcMonitor
.right
+ 1, width
);
2555 todo_wine
ok(height
== monitorinfo
.rcMonitor
.bottom
+ 1, "Expected height %d, got %d.\n",
2556 monitorinfo
.rcMonitor
.bottom
+ 1, height
);
2558 hr
= IMediaControl_Stop(control
);
2559 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2562 IMediaControl_Release(control
);
2563 IFilterGraph2_Release(graph
);
2564 IVideoWindow_Release(window
);
2565 IOverlay_Release(overlay
);
2566 IMemInputPin_Release(input
);
2568 ref
= IBaseFilter_Release(filter
);
2569 ok(!ref
, "Got outstanding refcount %d.\n", ref
);
2570 ref
= IBaseFilter_Release(&source
.filter
.IBaseFilter_iface
);
2571 ok(!ref
, "Got outstanding refcount %d.\n", ref
);
2572 DestroyWindow(our_hwnd
);
2575 static IDirect3DDevice9
*create_device(HWND window
)
2577 D3DPRESENT_PARAMETERS present_parameters
=
2580 .hDeviceWindow
= window
,
2581 .SwapEffect
= D3DSWAPEFFECT_DISCARD
,
2582 .BackBufferWidth
= 640,
2583 .BackBufferHeight
= 480,
2584 .BackBufferFormat
= D3DFMT_A8R8G8B8
,
2586 IDirect3DDevice9
*device
;
2590 d3d
= Direct3DCreate9(D3D_SDK_VERSION
);
2591 ok(!!d3d
, "Failed to create a D3D object.\n");
2593 hr
= IDirect3D9_CreateDevice(d3d
, D3DADAPTER_DEFAULT
, D3DDEVTYPE_HAL
, window
,
2594 D3DCREATE_HARDWARE_VERTEXPROCESSING
, &present_parameters
, &device
);
2595 IDirect3D9_Release(d3d
);
2598 skip("Failed to create a 3D device, hr %#x.\n", hr
);
2604 static void test_allocate_surface_helper(void)
2606 VMR9AllocationInfo info
=
2608 .dwFlags
= VMR9AllocFlag_OffscreenSurface
,
2611 .Format
= D3DFMT_X8R8G8B8
,
2612 .Pool
= D3DPOOL_DEFAULT
,
2614 .szAspectRatio
= {32, 16},
2615 .szNativeSize
= {32, 16},
2617 IBaseFilter
*filter
= create_vmr9(VMR9Mode_Renderless
);
2618 IVMRSurfaceAllocatorNotify9
*notify
;
2619 IDirect3DSurface9
*surfaces
[2] = {};
2620 IDirect3DDevice9
*device
, *device2
;
2621 RECT rect
= {0, 0, 640, 480};
2622 IDirect3DTexture9
*container
;
2623 D3DSURFACE_DESC desc
;
2629 AdjustWindowRect(&rect
, WS_OVERLAPPEDWINDOW
, FALSE
);
2630 window
= CreateWindowA("static", "quartz_test", WS_OVERLAPPEDWINDOW
, 0, 0,
2631 rect
.right
- rect
.left
, rect
.bottom
- rect
.top
, NULL
, NULL
, NULL
, NULL
);
2632 if (!(device
= create_device(window
)))
2634 IBaseFilter_Release(filter
);
2635 DestroyWindow(window
);
2639 IBaseFilter_QueryInterface(filter
, &IID_IVMRSurfaceAllocatorNotify9
, (void **)¬ify
);
2642 hr
= IVMRSurfaceAllocatorNotify9_AllocateSurfaceHelper(notify
, &info
, &count
, surfaces
);
2643 todo_wine
ok(hr
== E_FAIL
, "Got hr %#x.\n", hr
);
2645 hr
= IVMRSurfaceAllocatorNotify9_SetD3DDevice(notify
, device
, MonitorFromWindow(window
, MONITOR_DEFAULTTOPRIMARY
));
2646 if (hr
== E_NOINTERFACE
)
2648 win_skip("Direct3D does not support video rendering.\n");
2651 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2653 if (0) /* crashes on Windows */
2655 hr
= IVMRSurfaceAllocatorNotify9_AllocateSurfaceHelper(notify
, NULL
, &count
, surfaces
);
2656 ok(hr
== E_POINTER
, "Got hr %#x.\n", hr
);
2658 hr
= IVMRSurfaceAllocatorNotify9_AllocateSurfaceHelper(notify
, &info
, NULL
, surfaces
);
2659 ok(hr
== E_POINTER
, "Got hr %#x.\n", hr
);
2662 hr
= IVMRSurfaceAllocatorNotify9_AllocateSurfaceHelper(notify
, &info
, &count
, NULL
);
2663 ok(hr
== E_POINTER
, "Got hr %#x.\n", hr
);
2665 hr
= IVMRSurfaceAllocatorNotify9_AllocateSurfaceHelper(notify
, &info
, &count
, surfaces
);
2666 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2667 ok(count
== 2, "Got count %u.\n", count
);
2668 ok(!!surfaces
[0], "Surface 0 was not allocated.\n");
2669 ok(!!surfaces
[1], "Surface 1 was not allocated.\n");
2671 hr
= IDirect3DSurface9_GetDevice(surfaces
[0], &device2
);
2672 ok(hr
== D3D_OK
, "Got hr %#x.\n", hr
);
2673 ok(device2
== device
, "Devices did not match.\n");
2674 IDirect3DDevice9_Release(device2
);
2676 hr
= IDirect3DSurface9_GetContainer(surfaces
[0], &IID_IDirect3DTexture9
, (void **)&container
);
2677 ok(hr
== E_NOINTERFACE
, "Got hr %#x.\n", hr
);
2679 hr
= IDirect3DSurface9_GetDesc(surfaces
[0], &desc
);
2680 ok(hr
== D3D_OK
, "Got hr %#x.\n", hr
);
2681 ok(desc
.Format
== info
.Format
, "Got format %#x.\n", desc
.Format
);
2682 ok(desc
.Type
== D3DRTYPE_SURFACE
, "Got type %u.\n", desc
.Type
);
2683 ok(!desc
.Usage
, "Got usage %#x.\n", desc
.Usage
);
2684 ok(desc
.Pool
== D3DPOOL_DEFAULT
, "Got pool %u.\n", desc
.Pool
);
2685 ok(desc
.MultiSampleType
== D3DMULTISAMPLE_NONE
, "Got multisample type %u.\n", desc
.MultiSampleType
);
2686 ok(!desc
.MultiSampleQuality
, "Got multisample quality %u.\n", desc
.MultiSampleQuality
);
2687 ok(desc
.Width
== 32, "Got width %u.\n", desc
.Width
);
2688 ok(desc
.Height
== 16, "Got height %u.\n", desc
.Height
);
2690 IDirect3DSurface9_Release(surfaces
[0]);
2691 IDirect3DSurface9_Release(surfaces
[1]);
2693 surfaces
[0] = surfaces
[1] = NULL
;
2695 hr
= IVMRSurfaceAllocatorNotify9_AllocateSurfaceHelper(notify
, &info
, &count
, surfaces
);
2696 todo_wine
ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2697 todo_wine
ok(!count
, "Got count %u.\n", count
);
2698 ok(!surfaces
[0], "Surface 0 was allocated.\n");
2699 ok(!surfaces
[1], "Surface 1 was allocated.\n");
2702 info
.MinBuffers
= 1;
2703 hr
= IVMRSurfaceAllocatorNotify9_AllocateSurfaceHelper(notify
, &info
, &count
, surfaces
);
2704 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2705 ok(count
== 2, "Got count %u.\n", count
);
2706 ok(!!surfaces
[0], "Surface 0 was not allocated.\n");
2707 ok(!!surfaces
[1], "Surface 1 was not allocated.\n");
2708 IDirect3DSurface9_Release(surfaces
[0]);
2709 IDirect3DSurface9_Release(surfaces
[1]);
2712 info
.dwFlags
= VMR9AllocFlag_TextureSurface
;
2713 surfaces
[0] = surfaces
[1] = NULL
;
2714 hr
= IVMRSurfaceAllocatorNotify9_AllocateSurfaceHelper(notify
, &info
, &count
, surfaces
);
2715 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2716 ok(count
== 2, "Got count %u.\n", count
);
2717 ok(!!surfaces
[0], "Surface 0 was not allocated.\n");
2718 ok(!!surfaces
[1], "Surface 1 was not allocated.\n");
2720 hr
= IDirect3DSurface9_GetDevice(surfaces
[0], &device2
);
2721 ok(hr
== D3D_OK
, "Got hr %#x.\n", hr
);
2722 ok(device2
== device
, "Devices did not match.\n");
2723 IDirect3DDevice9_Release(device2
);
2725 hr
= IDirect3DSurface9_GetContainer(surfaces
[0], &IID_IDirect3DTexture9
, (void **)&container
);
2726 ok(hr
== D3D_OK
, "Got hr %#x.\n", hr
);
2727 IDirect3DTexture9_Release(container
);
2729 hr
= IDirect3DSurface9_GetDesc(surfaces
[1], &desc
);
2730 ok(hr
== D3D_OK
, "Got hr %#x.\n", hr
);
2731 ok(desc
.Format
== info
.Format
, "Got format %#x.\n", desc
.Format
);
2732 ok(desc
.Type
== D3DRTYPE_SURFACE
, "Got type %u.\n", desc
.Type
);
2733 ok(desc
.Usage
== D3DUSAGE_DYNAMIC
, "Got usage %#x.\n", desc
.Usage
);
2734 ok(desc
.Pool
== D3DPOOL_DEFAULT
, "Got pool %u.\n", desc
.Pool
);
2735 ok(desc
.MultiSampleType
== D3DMULTISAMPLE_NONE
, "Got multisample type %u.\n", desc
.MultiSampleType
);
2736 ok(!desc
.MultiSampleQuality
, "Got multisample quality %u.\n", desc
.MultiSampleQuality
);
2737 ok(desc
.Width
== 32, "Got width %u.\n", desc
.Width
);
2738 ok(desc
.Height
== 16, "Got height %u.\n", desc
.Height
);
2740 IDirect3DSurface9_Release(surfaces
[0]);
2741 IDirect3DSurface9_Release(surfaces
[1]);
2743 info
.Format
= D3DFMT_R8G8B8
;
2744 surfaces
[0] = surfaces
[1] = NULL
;
2745 hr
= IVMRSurfaceAllocatorNotify9_AllocateSurfaceHelper(notify
, &info
, &count
, surfaces
);
2746 ok(hr
== D3DERR_INVALIDCALL
, "Got hr %#x.\n", hr
);
2747 ok(!count
, "Got count %u.\n", count
);
2748 ok(!surfaces
[0], "Surface 0 was allocated.\n");
2749 ok(!surfaces
[1], "Surface 1 was allocated.\n");
2752 info
.dwFlags
= VMR9AllocFlag_3DRenderTarget
;
2754 hr
= IVMRSurfaceAllocatorNotify9_AllocateSurfaceHelper(notify
, &info
, &count
, surfaces
);
2755 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2756 ok(count
== 1, "Got count %u.\n", count
);
2757 ok(!!surfaces
[0], "Surface 0 was not allocated.\n");
2758 ok(info
.Format
!= 0, "Expected a format.\n");
2760 hr
= IDirect3DSurface9_GetDesc(surfaces
[0], &desc
);
2761 ok(hr
== D3D_OK
, "Got hr %#x.\n", hr
);
2762 ok(desc
.Format
== info
.Format
, "Expected format %#x, got %#x.\n", info
.Format
, desc
.Format
);
2763 ok(desc
.Type
== D3DRTYPE_SURFACE
, "Got type %u.\n", desc
.Type
);
2764 ok(desc
.Usage
== D3DUSAGE_RENDERTARGET
, "Got usage %#x.\n", desc
.Usage
);
2765 ok(desc
.Pool
== D3DPOOL_DEFAULT
, "Got pool %u.\n", desc
.Pool
);
2766 ok(desc
.MultiSampleType
== D3DMULTISAMPLE_NONE
, "Got multisample type %u.\n", desc
.MultiSampleType
);
2767 ok(!desc
.MultiSampleQuality
, "Got multisample quality %u.\n", desc
.MultiSampleQuality
);
2768 ok(desc
.Width
== 32, "Got width %u.\n", desc
.Width
);
2769 ok(desc
.Height
== 16, "Got height %u.\n", desc
.Height
);
2771 IDirect3DSurface9_Release(surfaces
[0]);
2773 info
.Format
= D3DFMT_A8R8G8B8
;
2774 info
.dwFlags
= VMR9AllocFlag_OffscreenSurface
| VMR9AllocFlag_TextureSurface
;
2776 hr
= IVMRSurfaceAllocatorNotify9_AllocateSurfaceHelper(notify
, &info
, &count
, surfaces
);
2777 ok(hr
== E_INVALIDARG
, "Got hr %#x.\n", hr
);
2778 ok(count
== 1, "Got count %u.\n", count
);
2781 IVMRSurfaceAllocatorNotify9_Release(notify
);
2782 ref
= IBaseFilter_Release(filter
);
2783 ok(!ref
, "Got outstanding refcount %d.\n", ref
);
2784 ref
= IDirect3DDevice9_Release(device
);
2785 ok(!ref
, "Got outstanding refcount %d.\n", ref
);
2786 DestroyWindow(window
);
2791 IVMRSurfaceAllocator9 IVMRSurfaceAllocator9_iface
;
2792 IVMRImagePresenter9 IVMRImagePresenter9_iface
;
2797 IDirect3DSurface9
*surfaces
[5];
2798 IVMRSurfaceAllocatorNotify9
*notify
;
2799 unsigned int got_PresentImage
, got_TerminateDevice
;
2802 static struct presenter
*impl_from_IVMRImagePresenter9(IVMRImagePresenter9
*iface
)
2804 return CONTAINING_RECORD(iface
, struct presenter
, IVMRImagePresenter9_iface
);
2807 static HRESULT WINAPI
presenter_QueryInterface(IVMRImagePresenter9
*iface
, REFIID iid
, void **out
)
2809 struct presenter
*presenter
= impl_from_IVMRImagePresenter9(iface
);
2810 return IVMRSurfaceAllocator9_QueryInterface(&presenter
->IVMRSurfaceAllocator9_iface
, iid
, out
);
2813 static ULONG WINAPI
presenter_AddRef(IVMRImagePresenter9
*iface
)
2815 struct presenter
*presenter
= impl_from_IVMRImagePresenter9(iface
);
2816 return IVMRSurfaceAllocator9_AddRef(&presenter
->IVMRSurfaceAllocator9_iface
);
2819 static ULONG WINAPI
presenter_Release(IVMRImagePresenter9
*iface
)
2821 struct presenter
*presenter
= impl_from_IVMRImagePresenter9(iface
);
2822 return IVMRSurfaceAllocator9_Release(&presenter
->IVMRSurfaceAllocator9_iface
);
2825 static HRESULT WINAPI
presenter_StartPresenting(IVMRImagePresenter9
*iface
, DWORD_PTR cookie
)
2827 if (winetest_debug
> 1) trace("StartPresenting()\n");
2828 ok(cookie
== 0xabacab, "Got cookie %#lx.\n", cookie
);
2832 static HRESULT WINAPI
presenter_StopPresenting(IVMRImagePresenter9
*iface
, DWORD_PTR cookie
)
2834 if (winetest_debug
> 1) trace("StopPresenting()\n");
2835 ok(cookie
== 0xabacab, "Got cookie %#lx.\n", cookie
);
2839 static HRESULT WINAPI
presenter_PresentImage(IVMRImagePresenter9
*iface
, DWORD_PTR cookie
, VMR9PresentationInfo
*info
)
2841 struct presenter
*presenter
= impl_from_IVMRImagePresenter9(iface
);
2842 static const RECT rect
;
2844 if (winetest_debug
> 1) trace("PresentImage()\n");
2845 ok(cookie
== 0xabacab, "Got cookie %#lx.\n", cookie
);
2846 todo_wine
ok(info
->dwFlags
== VMR9Sample_TimeValid
, "Got flags %#x.\n", info
->dwFlags
);
2847 ok(!info
->rtStart
, "Got start time %s.\n", wine_dbgstr_longlong(info
->rtStart
));
2848 ok(info
->rtEnd
== 10000000, "Got end time %s.\n", wine_dbgstr_longlong(info
->rtEnd
));
2849 todo_wine
ok(info
->szAspectRatio
.cx
== 120, "Got aspect ratio width %d.\n", info
->szAspectRatio
.cx
);
2850 todo_wine
ok(info
->szAspectRatio
.cy
== 60, "Got aspect ratio height %d.\n", info
->szAspectRatio
.cy
);
2851 ok(EqualRect(&info
->rcSrc
, &rect
), "Got source rect %s.\n", wine_dbgstr_rect(&info
->rcSrc
));
2852 ok(EqualRect(&info
->rcDst
, &rect
), "Got dest rect %s.\n", wine_dbgstr_rect(&info
->rcDst
));
2853 ok(!info
->dwReserved1
, "Got dwReserved1 %#x.\n", info
->dwReserved1
);
2854 ok(!info
->dwReserved2
, "Got dwReserved2 %#x.\n", info
->dwReserved2
);
2856 ++presenter
->got_PresentImage
;
2860 static const IVMRImagePresenter9Vtbl presenter_vtbl
=
2862 presenter_QueryInterface
,
2865 presenter_StartPresenting
,
2866 presenter_StopPresenting
,
2867 presenter_PresentImage
,
2870 static struct presenter
*impl_from_IVMRSurfaceAllocator9(IVMRSurfaceAllocator9
*iface
)
2872 return CONTAINING_RECORD(iface
, struct presenter
, IVMRSurfaceAllocator9_iface
);
2875 static HRESULT WINAPI
allocator_QueryInterface(IVMRSurfaceAllocator9
*iface
, REFIID iid
, void **out
)
2877 struct presenter
*presenter
= impl_from_IVMRSurfaceAllocator9(iface
);
2879 if (winetest_debug
> 1) trace("QueryInterface(%s)\n", wine_dbgstr_guid(iid
));
2881 if (IsEqualGUID(iid
, &IID_IVMRImagePresenter9
))
2883 *out
= &presenter
->IVMRImagePresenter9_iface
;
2884 IVMRImagePresenter9_AddRef(&presenter
->IVMRImagePresenter9_iface
);
2887 ok(!IsEqualGUID(iid
, &IID_IVMRSurfaceAllocatorEx9
), "Unexpected query for IVMRSurfaceAllocatorEx9.\n");
2892 static ULONG WINAPI
allocator_AddRef(IVMRSurfaceAllocator9
*iface
)
2894 struct presenter
*presenter
= impl_from_IVMRSurfaceAllocator9(iface
);
2895 return InterlockedIncrement(&presenter
->refcount
);
2898 static ULONG WINAPI
allocator_Release(IVMRSurfaceAllocator9
*iface
)
2900 struct presenter
*presenter
= impl_from_IVMRSurfaceAllocator9(iface
);
2901 return InterlockedDecrement(&presenter
->refcount
);
2904 static HRESULT WINAPI
allocator_InitializeDevice(IVMRSurfaceAllocator9
*iface
,
2905 DWORD_PTR cookie
, VMR9AllocationInfo
*info
, DWORD
*buffer_count
)
2907 struct presenter
*presenter
= impl_from_IVMRSurfaceAllocator9(iface
);
2909 if (winetest_debug
> 1) trace("InitializeDevice(flags %#x, format %u)\n",
2910 info
->dwFlags
, info
->Format
);
2911 ok(cookie
== 0xabacab, "Got cookie %#lx.\n", cookie
);
2912 ok(info
->dwWidth
== 32, "Got width %u.\n", info
->dwWidth
);
2913 ok(info
->dwHeight
== 16, "Got height %u.\n", info
->dwHeight
);
2914 todo_wine
ok(info
->MinBuffers
== 5, "Got buffer count %u.\n", info
->MinBuffers
);
2915 ok(info
->Pool
== D3DPOOL_DEFAULT
, "Got pool %u\n", info
->Pool
);
2916 todo_wine
ok(info
->szAspectRatio
.cx
== 120, "Got aspect ratio width %d.\n", info
->szAspectRatio
.cx
);
2917 todo_wine
ok(info
->szAspectRatio
.cy
== 60, "Got aspect ratio height %d.\n", info
->szAspectRatio
.cy
);
2918 ok(info
->szNativeSize
.cx
== 32, "Got native width %d.\n", info
->szNativeSize
.cx
);
2919 ok(info
->szNativeSize
.cy
== 16, "Got native height %d.\n", info
->szNativeSize
.cy
);
2920 todo_wine
ok(*buffer_count
== 5, "Got buffer count %u.\n", *buffer_count
);
2922 presenter
->format
= info
->Format
;
2924 if (info
->dwFlags
!= presenter
->accept_flags
)
2926 return IVMRSurfaceAllocatorNotify9_AllocateSurfaceHelper(presenter
->notify
,
2927 info
, buffer_count
, presenter
->surfaces
);
2930 static HRESULT WINAPI
allocator_TerminateDevice(IVMRSurfaceAllocator9
*iface
, DWORD_PTR cookie
)
2932 struct presenter
*presenter
= impl_from_IVMRSurfaceAllocator9(iface
);
2934 if (winetest_debug
> 1) trace("TerminateDevice()\n");
2935 ok(cookie
== 0xabacab, "Got cookie %#lx.\n", cookie
);
2936 /* Don't dereference the surfaces here, to mimic How to Survive. */
2937 ++presenter
->got_TerminateDevice
;
2941 static HRESULT WINAPI
allocator_GetSurface(IVMRSurfaceAllocator9
*iface
,
2942 DWORD_PTR cookie
, DWORD index
, DWORD flags
, IDirect3DSurface9
**surface
)
2944 struct presenter
*presenter
= impl_from_IVMRSurfaceAllocator9(iface
);
2946 if (winetest_debug
> 1) trace("GetSurface(index %u)\n", index
);
2947 ok(cookie
== 0xabacab, "Got cookie %#lx.\n", cookie
);
2948 ok(!flags
, "Got flags %#x.\n", flags
);
2949 ok(index
< 5, "Got index %u.\n", index
);
2951 /* Don't reference the surface here, to mimic How to Survive. */
2952 *surface
= presenter
->surfaces
[index
];
2956 static HRESULT WINAPI
allocator_AdviseNotify(IVMRSurfaceAllocator9
*iface
, IVMRSurfaceAllocatorNotify9
*notify
)
2958 ok(0, "Unexpected call.\n");
2962 static const IVMRSurfaceAllocator9Vtbl allocator_vtbl
=
2964 allocator_QueryInterface
,
2967 allocator_InitializeDevice
,
2968 allocator_TerminateDevice
,
2969 allocator_GetSurface
,
2970 allocator_AdviseNotify
,
2973 static void test_renderless_present(struct presenter
*presenter
,
2974 IFilterGraph2
*graph
, IMemInputPin
*input
)
2976 IMediaControl
*control
;
2977 OAFilterState state
;
2981 IFilterGraph2_QueryInterface(graph
, &IID_IMediaControl
, (void **)&control
);
2983 presenter
->got_PresentImage
= 0;
2985 hr
= IMediaControl_Pause(control
);
2986 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
2987 thread
= send_frame(input
);
2988 hr
= IMediaControl_GetState(control
, 1000, &state
);
2989 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2990 /* Atelier Sophie uses the VMR in renderless mode, calls
2991 * IMediaControl::Run() from a stopped state and expects that
2992 * IMediaControl::GetState() returns S_OK only after PresentImage() has
2994 ok(presenter
->got_PresentImage
== 1, "Got %u calls to PresentImage().\n", presenter
->got_PresentImage
);
2996 hr
= IMediaControl_Run(control
);
2997 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2998 hr
= join_thread(thread
);
2999 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
3000 ok(presenter
->got_PresentImage
== 1, "Got %u calls to PresentImage().\n", presenter
->got_PresentImage
);
3002 hr
= IMediaControl_Stop(control
);
3003 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
3005 IMediaControl_Release(control
);
3008 static void test_renderless_formats(void)
3010 VIDEOINFOHEADER vih
=
3012 .rcSource
= {4, 6, 16, 12},
3013 .rcTarget
= {40, 60, 160, 120},
3014 .bmiHeader
.biSize
= sizeof(BITMAPINFOHEADER
),
3015 .bmiHeader
.biWidth
= 32,
3016 .bmiHeader
.biHeight
= 16,
3018 AM_MEDIA_TYPE req_mt
=
3020 .majortype
= MEDIATYPE_Video
,
3021 .formattype
= FORMAT_VideoInfo
,
3022 .cbFormat
= sizeof(vih
),
3023 .pbFormat
= (BYTE
*)&vih
,
3025 ALLOCATOR_PROPERTIES req_props
= {5, 32 * 16 * 4, 1, 0}, ret_props
;
3026 struct presenter presenter
=
3028 .IVMRSurfaceAllocator9_iface
.lpVtbl
= &allocator_vtbl
,
3029 .IVMRImagePresenter9_iface
.lpVtbl
= &presenter_vtbl
,
3032 struct presenter presenter2
= presenter
;
3033 IVMRSurfaceAllocatorNotify9
*notify
;
3034 RECT rect
= {0, 0, 640, 480};
3035 struct testfilter source
;
3036 IDirect3DDevice9
*device
;
3037 IMemAllocator
*allocator
;
3038 IFilterGraph2
*graph
;
3039 IMemInputPin
*input
;
3040 IBaseFilter
*filter
;
3049 const GUID
*subtype
;
3055 {&MEDIASUBTYPE_ARGB1555
, D3DFMT_A1R5G5B5
, VMR9AllocFlag_TextureSurface
},
3056 {&MEDIASUBTYPE_ARGB32
, D3DFMT_A8R8G8B8
, VMR9AllocFlag_TextureSurface
},
3057 {&MEDIASUBTYPE_ARGB4444
, D3DFMT_A4R4G4B4
, VMR9AllocFlag_TextureSurface
},
3059 {&MEDIASUBTYPE_RGB555
, D3DFMT_X1R5G5B5
, VMR9AllocFlag_OffscreenSurface
},
3060 {&MEDIASUBTYPE_RGB555
, D3DFMT_X1R5G5B5
, VMR9AllocFlag_TextureSurface
},
3061 {&MEDIASUBTYPE_RGB565
, D3DFMT_R5G6B5
, VMR9AllocFlag_OffscreenSurface
},
3062 {&MEDIASUBTYPE_RGB565
, D3DFMT_R5G6B5
, VMR9AllocFlag_TextureSurface
},
3063 {&MEDIASUBTYPE_RGB24
, D3DFMT_R8G8B8
, VMR9AllocFlag_OffscreenSurface
},
3064 {&MEDIASUBTYPE_RGB24
, D3DFMT_R8G8B8
, VMR9AllocFlag_TextureSurface
},
3065 {&MEDIASUBTYPE_RGB32
, D3DFMT_X8R8G8B8
, VMR9AllocFlag_OffscreenSurface
},
3066 {&MEDIASUBTYPE_RGB32
, D3DFMT_X8R8G8B8
, VMR9AllocFlag_TextureSurface
},
3068 {&MEDIASUBTYPE_NV12
, MAKEFOURCC('N','V','1','2'), VMR9AllocFlag_OffscreenSurface
},
3069 {&MEDIASUBTYPE_UYVY
, D3DFMT_UYVY
, VMR9AllocFlag_OffscreenSurface
},
3070 {&MEDIASUBTYPE_YUY2
, D3DFMT_YUY2
, VMR9AllocFlag_OffscreenSurface
},
3071 {&MEDIASUBTYPE_YV12
, MAKEFOURCC('Y','V','1','2'), VMR9AllocFlag_OffscreenSurface
},
3074 AdjustWindowRect(&rect
, WS_OVERLAPPEDWINDOW
, FALSE
);
3075 window
= CreateWindowA("static", "quartz_test", WS_OVERLAPPEDWINDOW
, 0, 0,
3076 rect
.right
- rect
.left
, rect
.bottom
- rect
.top
, NULL
, NULL
, NULL
, NULL
);
3077 if (!(device
= create_device(window
)))
3079 DestroyWindow(window
);
3083 filter
= create_vmr9(VMR9Mode_Renderless
);
3084 IBaseFilter_QueryInterface(filter
, &IID_IVMRSurfaceAllocatorNotify9
, (void **)¬ify
);
3086 hr
= IVMRSurfaceAllocatorNotify9_SetD3DDevice(notify
, device
, MonitorFromWindow(window
, MONITOR_DEFAULTTOPRIMARY
));
3087 if (hr
== E_NOINTERFACE
)
3089 win_skip("Direct3D does not support video rendering.\n");
3092 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
3094 hr
= IVMRSurfaceAllocatorNotify9_AdviseSurfaceAllocator(notify
, 0xabacab,
3095 &presenter
.IVMRSurfaceAllocator9_iface
);
3096 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
3098 presenter
.notify
= notify
;
3100 testfilter_init(&source
);
3101 graph
= create_graph();
3102 IFilterGraph2_AddFilter(graph
, &source
.filter
.IBaseFilter_iface
, NULL
);
3103 IFilterGraph2_AddFilter(graph
, filter
, NULL
);
3104 IBaseFilter_FindPin(filter
, L
"VMR Input0", &pin
);
3105 IPin_QueryInterface(pin
, &IID_IMemInputPin
, (void **)&input
);
3107 for (i
= 0; i
< ARRAY_SIZE(tests
); ++i
)
3109 req_mt
.subtype
= *tests
[i
].subtype
;
3110 presenter
.accept_flags
= tests
[i
].flags
;
3112 hr
= IFilterGraph2_ConnectDirect(graph
, &source
.source
.pin
.IPin_iface
, pin
, &req_mt
);
3113 /* Connection never fails on Native, but Wine currently creates D3D
3114 * surfaces during IPin::ReceiveConnection() instead of
3115 * IMemAllocator::SetProperties(), so let that fail here for now. */
3118 skip("Format %u (%#x), flags %#x are not supported, hr %#x.\n",
3119 tests
[i
].format
, tests
[i
].format
, tests
[i
].flags
, hr
);
3122 ok(hr
== S_OK
, "Test %u: Got hr %#x.\n", i
, hr
);
3124 hr
= IMemInputPin_GetAllocator(input
, &allocator
);
3125 todo_wine
ok(hr
== S_OK
, "Test %u: Got hr %#x.\n", i
, hr
);
3128 test_allocator(input
);
3129 hr
= IMemInputPin_GetAllocator(input
, &allocator
);
3132 hr
= IMemAllocator_SetProperties(allocator
, &req_props
, &ret_props
);
3135 skip("Format %u (%#x), flags %#x are not supported, hr %#x.\n",
3136 tests
[i
].format
, tests
[i
].format
, tests
[i
].flags
, hr
);
3137 IMemAllocator_Release(allocator
);
3138 hr
= IFilterGraph2_Disconnect(graph
, &source
.source
.pin
.IPin_iface
);
3139 ok(hr
== S_OK
, "Test %u: Got hr %#x.\n", i
, hr
);
3140 hr
= IFilterGraph2_Disconnect(graph
, pin
);
3141 ok(hr
== S_OK
, "Test %u: Got hr %#x.\n", i
, hr
);
3144 ok(!memcmp(&ret_props
, &req_props
, sizeof(req_props
)), "Properties did not match.\n");
3145 hr
= IMemAllocator_Commit(allocator
);
3146 ok(hr
== S_OK
, "Test %u: Got hr %#x.\n", i
, hr
);
3148 hr
= IVMRSurfaceAllocatorNotify9_AdviseSurfaceAllocator(notify
, 0xabacab,
3149 &presenter2
.IVMRSurfaceAllocator9_iface
);
3150 ok(hr
== VFW_E_WRONG_STATE
, "Got hr %#x.\n", hr
);
3152 ok(presenter
.format
== tests
[i
].format
, "Test %u: Got format %u (%#x).\n",
3153 i
, presenter
.format
, presenter
.format
);
3155 test_renderless_present(&presenter
, graph
, input
);
3157 hr
= IMemAllocator_Decommit(allocator
);
3158 ok(hr
== S_OK
, "Test %u: Got hr %#x.\n", i
, hr
);
3159 IMemAllocator_Release(allocator
);
3161 hr
= IFilterGraph2_Disconnect(graph
, &source
.source
.pin
.IPin_iface
);
3162 ok(hr
== S_OK
, "Test %u: Got hr %#x.\n", i
, hr
);
3163 hr
= IFilterGraph2_Disconnect(graph
, pin
);
3164 ok(hr
== S_OK
, "Test %u: Got hr %#x.\n", i
, hr
);
3167 hr
= IVMRSurfaceAllocatorNotify9_AdviseSurfaceAllocator(notify
, 0xabacab, &presenter2
.IVMRSurfaceAllocator9_iface
);
3168 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
3170 ref
= IFilterGraph2_Release(graph
);
3171 ok(!ref
, "Got outstanding refcount %d.\n", ref
);
3172 IMemInputPin_Release(input
);
3176 IVMRSurfaceAllocatorNotify9_Release(notify
);
3177 ref
= IBaseFilter_Release(filter
);
3178 ok(!ref
, "Got outstanding refcount %d.\n", ref
);
3179 ok(presenter
.refcount
== 1, "Got outstanding refcount %d.\n", presenter
.refcount
);
3180 ok(presenter2
.refcount
== 1, "Got outstanding refcount %d.\n", presenter2
.refcount
);
3181 ref
= IDirect3DDevice9_Release(device
);
3182 ok(!ref
, "Got outstanding refcount %d.\n", ref
);
3183 DestroyWindow(window
);
3186 static void test_mixing_mode(void)
3188 IVMRWindowlessControl9
*windowless_control
;
3189 IVMRMixerControl9
*mixer_control
;
3190 IVMRFilterConfig9
*config
;
3191 DWORD stream_count
= 0;
3192 IBaseFilter
*filter
;
3198 static const VMR9Mode modes
[] =
3202 VMR9Mode_Windowless
,
3203 VMR9Mode_Renderless
,
3206 for (i
= 0; i
< ARRAY_SIZE(modes
); ++i
)
3208 filter
= create_vmr9(modes
[i
]);
3209 IBaseFilter_QueryInterface(filter
, &IID_IVMRFilterConfig9
, (void **)&config
);
3211 hr
= IBaseFilter_QueryInterface(filter
, &IID_IVMRMixerControl9
, (void **)&mixer_control
);
3212 ok(hr
== E_NOINTERFACE
, "Got hr %#x.\n", hr
);
3214 hr
= IVMRFilterConfig9_GetNumberOfStreams(config
, &stream_count
);
3215 ok(hr
== VFW_E_VMR_NOT_IN_MIXER_MODE
, "Got hr %#x.\n", hr
);
3217 hr
= IVMRFilterConfig9_SetNumberOfStreams(config
, 1);
3218 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
3220 hr
= IVMRFilterConfig9_GetNumberOfStreams(config
, &stream_count
);
3221 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
3222 ok(stream_count
== 1, "Got %u streams.\n", stream_count
);
3224 hr
= IBaseFilter_QueryInterface(filter
, &IID_IVMRMixerControl9
, (void **)&mixer_control
);
3225 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
3226 IVMRMixerControl9_Release(mixer_control
);
3228 hr
= IVMRFilterConfig9_SetNumberOfStreams(config
, 2);
3229 ok(hr
== VFW_E_WRONG_STATE
, "Got hr %#x.\n", hr
);
3231 hr
= IVMRFilterConfig9_GetNumberOfStreams(config
, &stream_count
);
3232 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
3233 ok(stream_count
== 1, "Got %u streams.\n", stream_count
);
3235 IVMRFilterConfig9_Release(config
);
3236 ref
= IBaseFilter_Release(filter
);
3237 ok(!ref
, "Got outstanding refcount %d.\n", ref
);
3240 filter
= create_vmr9(VMR9Mode_Windowless
);
3241 IBaseFilter_QueryInterface(filter
, &IID_IVMRFilterConfig9
, (void **)&config
);
3242 IBaseFilter_QueryInterface(filter
, &IID_IVMRWindowlessControl9
, (void **)&windowless_control
);
3244 window
= CreateWindowA("static", "quartz_test", WS_OVERLAPPEDWINDOW
, 0, 0, 640, 480, 0, 0, 0, 0);
3245 ok(!!window
, "Failed to create a window.\n");
3246 hr
= IVMRWindowlessControl9_SetVideoClippingWindow(windowless_control
, window
);
3247 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
3249 hr
= IVMRFilterConfig9_GetNumberOfStreams(config
, &stream_count
);
3250 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
3251 ok(stream_count
== 4, "Got %u streams.\n", stream_count
);
3253 hr
= IBaseFilter_QueryInterface(filter
, &IID_IVMRMixerControl9
, (void **)&mixer_control
);
3254 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
3255 IVMRMixerControl9_Release(mixer_control
);
3257 hr
= IVMRFilterConfig9_SetNumberOfStreams(config
, 2);
3258 ok(hr
== VFW_E_WRONG_STATE
, "Got hr %#x.\n", hr
);
3260 hr
= IVMRFilterConfig9_GetNumberOfStreams(config
, &stream_count
);
3261 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
3262 ok(stream_count
== 4, "Got %u streams.\n", stream_count
);
3264 IVMRWindowlessControl9_Release(windowless_control
);
3265 IVMRFilterConfig9_Release(config
);
3266 ref
= IBaseFilter_Release(filter
);
3267 ok(!ref
, "Got outstanding refcount %d.\n", ref
);
3268 DestroyWindow(window
);
3271 static void test_clipping_window(void)
3273 VIDEOINFOHEADER vih
=
3275 .bmiHeader
.biSize
= sizeof(BITMAPINFOHEADER
),
3276 .bmiHeader
.biWidth
= 32,
3277 .bmiHeader
.biHeight
= 16,
3278 .bmiHeader
.biBitCount
= 32,
3282 .majortype
= MEDIATYPE_Video
,
3283 .subtype
= MEDIASUBTYPE_RGB32
,
3284 .formattype
= FORMAT_VideoInfo
,
3285 .cbFormat
= sizeof(vih
),
3286 .pbFormat
= (BYTE
*)&vih
,
3288 IBaseFilter
*filter
= create_vmr9(VMR9Mode_Windowless
);
3289 IVMRWindowlessControl9
*windowless_control
;
3290 IFilterGraph2
*graph
= create_graph();
3291 struct testfilter source
;
3297 IBaseFilter_QueryInterface(filter
, &IID_IVMRWindowlessControl9
, (void **)&windowless_control
);
3298 IBaseFilter_FindPin(filter
, L
"VMR Input0", &pin
);
3299 testfilter_init(&source
);
3300 IFilterGraph2_AddFilter(graph
, &source
.filter
.IBaseFilter_iface
, L
"source");
3301 IFilterGraph2_AddFilter(graph
, filter
, L
"vmr9");
3302 window
= CreateWindowA("static", "quartz_test", WS_OVERLAPPEDWINDOW
, 0, 0, 640, 480, 0, 0, 0, 0);
3303 ok(!!window
, "Failed to create a window.\n");
3305 hr
= IVMRWindowlessControl9_SetVideoClippingWindow(windowless_control
, NULL
);
3306 ok(hr
== E_INVALIDARG
, "Got hr %#x.\n", hr
);
3307 hr
= IVMRWindowlessControl9_SetVideoClippingWindow(windowless_control
, (HWND
)0xdeadbeef);
3308 ok(hr
== E_INVALIDARG
, "Got hr %#x.\n", hr
);
3310 hr
= IFilterGraph2_ConnectDirect(graph
, &source
.source
.pin
.IPin_iface
, pin
, &mt
);
3311 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
3313 hr
= IVMRWindowlessControl9_SetVideoClippingWindow(windowless_control
, window
);
3314 ok(hr
== VFW_E_WRONG_STATE
, "Got hr %#x.\n", hr
);
3316 hr
= IFilterGraph2_Disconnect(graph
, &source
.source
.pin
.IPin_iface
);
3317 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
3318 hr
= IFilterGraph2_Disconnect(graph
, pin
);
3319 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
3321 hr
= IVMRWindowlessControl9_SetVideoClippingWindow(windowless_control
, window
);
3322 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
3324 ref
= IFilterGraph2_Release(graph
);
3325 ok(!ref
, "Got outstanding refcount %d.\n", ref
);
3327 IVMRWindowlessControl9_Release(windowless_control
);
3328 ref
= IBaseFilter_Release(filter
);
3329 ok(!ref
, "Got outstanding refcount %d.\n", ref
);
3330 DestroyWindow(window
);
3333 static void test_surface_allocator_notify_refcount(void)
3335 struct presenter presenter
=
3337 .IVMRSurfaceAllocator9_iface
.lpVtbl
= &allocator_vtbl
,
3338 .IVMRImagePresenter9_iface
.lpVtbl
= &presenter_vtbl
,
3341 IBaseFilter
*filter
= create_vmr9(VMR9Mode_Renderless
);
3342 IVMRSurfaceAllocatorNotify9
*notify
;
3346 set_mixing_mode(filter
, 2);
3348 IBaseFilter_QueryInterface(filter
, &IID_IVMRSurfaceAllocatorNotify9
, (void **)¬ify
);
3350 hr
= IVMRSurfaceAllocatorNotify9_AdviseSurfaceAllocator(notify
, 0xabacab,
3351 &presenter
.IVMRSurfaceAllocator9_iface
);
3352 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
3354 ref
= IBaseFilter_Release(filter
);
3355 ok(!ref
, "Got outstanding refcount %d.\n", ref
);
3356 ok(presenter
.got_TerminateDevice
== 1, "Got %u calls to TerminateDevice().\n",
3357 presenter
.got_TerminateDevice
);
3358 ok(presenter
.refcount
== 1, "Got outstanding refcount %d.\n", presenter
.refcount
);
3360 ref
= IVMRSurfaceAllocatorNotify9_Release(notify
);
3361 ok(!ref
, "Got outstanding refcount %d.\n", ref
);
3364 static void check_source_position_(int line
, IBasicVideo
*video
,
3365 LONG expect_left
, LONG expect_top
, LONG expect_width
, LONG expect_height
)
3367 LONG left
, top
, width
, height
, l
;
3370 left
= top
= width
= height
= 0xdeadbeef;
3371 hr
= IBasicVideo_GetSourcePosition(video
, &left
, &top
, &width
, &height
);
3372 ok_(__FILE__
,line
)(hr
== S_OK
, "Got hr %#x.\n", hr
);
3373 ok_(__FILE__
,line
)(left
== expect_left
, "Got left %d.\n", left
);
3374 ok_(__FILE__
,line
)(top
== expect_top
, "Got top %d.\n", top
);
3375 ok_(__FILE__
,line
)(width
== expect_width
, "Got width %d.\n", width
);
3376 ok_(__FILE__
,line
)(height
== expect_height
, "Got height %d.\n", height
);
3379 hr
= IBasicVideo_get_SourceLeft(video
, &l
);
3380 ok_(__FILE__
,line
)(hr
== S_OK
, "Failed to get left, hr %#x.\n", hr
);
3381 ok_(__FILE__
,line
)(l
== left
, "Got left %d.\n", l
);
3384 hr
= IBasicVideo_get_SourceTop(video
, &l
);
3385 ok_(__FILE__
,line
)(hr
== S_OK
, "Failed to get top, hr %#x.\n", hr
);
3386 ok_(__FILE__
,line
)(l
== top
, "Got top %d.\n", l
);
3389 hr
= IBasicVideo_get_SourceWidth(video
, &l
);
3390 ok_(__FILE__
,line
)(hr
== S_OK
, "Failed to get width, hr %#x.\n", hr
);
3391 ok_(__FILE__
,line
)(l
== width
, "Got width %d.\n", l
);
3394 hr
= IBasicVideo_get_SourceHeight(video
, &l
);
3395 ok_(__FILE__
,line
)(hr
== S_OK
, "Failed to get height, hr %#x.\n", hr
);
3396 ok_(__FILE__
,line
)(l
== height
, "Got height %d.\n", l
);
3398 #define check_source_position(a,b,c,d,e) check_source_position_(__LINE__,a,b,c,d,e)
3400 static void test_basic_video_source(IBasicVideo
*video
)
3404 check_source_position(video
, 0, 0, 600, 400);
3405 hr
= IBasicVideo_IsUsingDefaultSource(video
);
3406 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
3408 hr
= IBasicVideo_put_SourceLeft(video
, -10);
3409 ok(hr
== E_INVALIDARG
, "Got hr %#x.\n", hr
);
3410 hr
= IBasicVideo_put_SourceLeft(video
, 10);
3411 ok(hr
== E_INVALIDARG
, "Got hr %#x.\n", hr
);
3413 hr
= IBasicVideo_put_SourceTop(video
, -10);
3414 ok(hr
== E_INVALIDARG
, "Got hr %#x.\n", hr
);
3415 hr
= IBasicVideo_put_SourceTop(video
, 10);
3416 ok(hr
== E_INVALIDARG
, "Got hr %#x.\n", hr
);
3418 hr
= IBasicVideo_put_SourceWidth(video
, -500);
3419 ok(hr
== E_INVALIDARG
, "Got hr %#x.\n", hr
);
3420 hr
= IBasicVideo_put_SourceWidth(video
, 0);
3421 ok(hr
== E_INVALIDARG
, "Got hr %#x.\n", hr
);
3422 hr
= IBasicVideo_put_SourceWidth(video
, 700);
3423 ok(hr
== E_INVALIDARG
, "Got hr %#x.\n", hr
);
3424 hr
= IBasicVideo_put_SourceWidth(video
, 500);
3425 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
3426 check_source_position(video
, 0, 0, 500, 400);
3427 hr
= IBasicVideo_IsUsingDefaultSource(video
);
3428 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
3430 hr
= IBasicVideo_put_SourceHeight(video
, -300);
3431 ok(hr
== E_INVALIDARG
, "Got hr %#x.\n", hr
);
3432 hr
= IBasicVideo_put_SourceHeight(video
, 0);
3433 ok(hr
== E_INVALIDARG
, "Got hr %#x.\n", hr
);
3434 hr
= IBasicVideo_put_SourceHeight(video
, 600);
3435 ok(hr
== E_INVALIDARG
, "Got hr %#x.\n", hr
);
3436 hr
= IBasicVideo_put_SourceHeight(video
, 300);
3437 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
3438 check_source_position(video
, 0, 0, 500, 300);
3439 hr
= IBasicVideo_IsUsingDefaultSource(video
);
3440 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
3442 hr
= IBasicVideo_put_SourceLeft(video
, -10);
3443 ok(hr
== E_INVALIDARG
, "Got hr %#x.\n", hr
);
3444 hr
= IBasicVideo_put_SourceLeft(video
, 10);
3445 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
3446 check_source_position(video
, 10, 0, 500, 300);
3447 hr
= IBasicVideo_IsUsingDefaultSource(video
);
3448 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
3450 hr
= IBasicVideo_put_SourceTop(video
, -10);
3451 ok(hr
== E_INVALIDARG
, "Got hr %#x.\n", hr
);
3452 hr
= IBasicVideo_put_SourceTop(video
, 20);
3453 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
3454 check_source_position(video
, 10, 20, 500, 300);
3455 hr
= IBasicVideo_IsUsingDefaultSource(video
);
3456 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
3458 hr
= IBasicVideo_SetSourcePosition(video
, 4, 5, 60, 40);
3459 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
3460 check_source_position(video
, 4, 5, 60, 40);
3461 hr
= IBasicVideo_IsUsingDefaultSource(video
);
3462 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
3464 hr
= IBasicVideo_SetSourcePosition(video
, 0, 0, 600, 400);
3465 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
3466 check_source_position(video
, 0, 0, 600, 400);
3467 hr
= IBasicVideo_IsUsingDefaultSource(video
);
3468 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
3470 hr
= IBasicVideo_SetSourcePosition(video
, 4, 5, 60, 40);
3471 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
3472 hr
= IBasicVideo_SetDefaultSourcePosition(video
);
3473 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
3474 check_source_position(video
, 0, 0, 600, 400);
3475 hr
= IBasicVideo_IsUsingDefaultSource(video
);
3476 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
3479 static void check_destination_position_(int line
, IBasicVideo
*video
,
3480 LONG expect_left
, LONG expect_top
, LONG expect_width
, LONG expect_height
)
3482 LONG left
, top
, width
, height
, l
;
3485 left
= top
= width
= height
= 0xdeadbeef;
3486 hr
= IBasicVideo_GetDestinationPosition(video
, &left
, &top
, &width
, &height
);
3487 ok_(__FILE__
,line
)(hr
== S_OK
, "Failed to get position, hr %#x.\n", hr
);
3488 ok_(__FILE__
,line
)(left
== expect_left
, "Got left %d.\n", left
);
3489 ok_(__FILE__
,line
)(top
== expect_top
, "Got top %d.\n", top
);
3490 ok_(__FILE__
,line
)(width
== expect_width
, "Got width %d.\n", width
);
3491 ok_(__FILE__
,line
)(height
== expect_height
, "Got height %d.\n", height
);
3494 hr
= IBasicVideo_get_DestinationLeft(video
, &l
);
3495 ok_(__FILE__
,line
)(hr
== S_OK
, "Failed to get left, hr %#x.\n", hr
);
3496 ok_(__FILE__
,line
)(l
== left
, "Got left %d.\n", l
);
3499 hr
= IBasicVideo_get_DestinationTop(video
, &l
);
3500 ok_(__FILE__
,line
)(hr
== S_OK
, "Failed to get top, hr %#x.\n", hr
);
3501 ok_(__FILE__
,line
)(l
== top
, "Got top %d.\n", l
);
3504 hr
= IBasicVideo_get_DestinationWidth(video
, &l
);
3505 ok_(__FILE__
,line
)(hr
== S_OK
, "Failed to get width, hr %#x.\n", hr
);
3506 ok_(__FILE__
,line
)(l
== width
, "Got width %d.\n", l
);
3509 hr
= IBasicVideo_get_DestinationHeight(video
, &l
);
3510 ok_(__FILE__
,line
)(hr
== S_OK
, "Failed to get height, hr %#x.\n", hr
);
3511 ok_(__FILE__
,line
)(l
== height
, "Got height %d.\n", l
);
3513 #define check_destination_position(a,b,c,d,e) check_destination_position_(__LINE__,a,b,c,d,e)
3515 static void test_basic_video_destination(IBasicVideo
*video
)
3517 IVideoWindow
*window
;
3521 IBasicVideo_QueryInterface(video
, &IID_IVideoWindow
, (void **)&window
);
3523 check_destination_position(video
, 0, 0, 600, 400);
3524 hr
= IBasicVideo_IsUsingDefaultDestination(video
);
3525 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
3527 hr
= IBasicVideo_put_DestinationLeft(video
, -10);
3528 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
3529 check_destination_position(video
, -10, 0, 600, 400);
3530 hr
= IBasicVideo_IsUsingDefaultDestination(video
);
3531 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
3533 hr
= IBasicVideo_put_DestinationLeft(video
, 10);
3534 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
3535 check_destination_position(video
, 10, 0, 600, 400);
3536 hr
= IBasicVideo_IsUsingDefaultDestination(video
);
3537 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
3539 hr
= IBasicVideo_put_DestinationTop(video
, -20);
3540 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
3541 check_destination_position(video
, 10, -20, 600, 400);
3542 hr
= IBasicVideo_IsUsingDefaultDestination(video
);
3543 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
3545 hr
= IBasicVideo_put_DestinationTop(video
, 20);
3546 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
3547 check_destination_position(video
, 10, 20, 600, 400);
3548 hr
= IBasicVideo_IsUsingDefaultDestination(video
);
3549 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
3551 hr
= IBasicVideo_put_DestinationWidth(video
, -700);
3552 ok(hr
== E_INVALIDARG
, "Got hr %#x.\n", hr
);
3553 hr
= IBasicVideo_put_DestinationWidth(video
, 0);
3554 ok(hr
== E_INVALIDARG
, "Got hr %#x.\n", hr
);
3555 hr
= IBasicVideo_put_DestinationWidth(video
, 700);
3556 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
3557 check_destination_position(video
, 10, 20, 700, 400);
3558 hr
= IBasicVideo_IsUsingDefaultDestination(video
);
3559 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
3561 hr
= IBasicVideo_put_DestinationWidth(video
, 500);
3562 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
3563 check_destination_position(video
, 10, 20, 500, 400);
3564 hr
= IBasicVideo_IsUsingDefaultDestination(video
);
3565 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
3567 hr
= IBasicVideo_put_DestinationHeight(video
, -500);
3568 ok(hr
== E_INVALIDARG
, "Got hr %#x.\n", hr
);
3569 hr
= IBasicVideo_put_DestinationHeight(video
, 0);
3570 ok(hr
== E_INVALIDARG
, "Got hr %#x.\n", hr
);
3571 hr
= IBasicVideo_put_DestinationHeight(video
, 500);
3572 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
3573 check_destination_position(video
, 10, 20, 500, 500);
3574 hr
= IBasicVideo_IsUsingDefaultDestination(video
);
3575 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
3577 hr
= IBasicVideo_put_DestinationHeight(video
, 300);
3578 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
3579 check_destination_position(video
, 10, 20, 500, 300);
3580 hr
= IBasicVideo_IsUsingDefaultDestination(video
);
3581 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
3583 hr
= IBasicVideo_SetDestinationPosition(video
, 4, 5, 60, 40);
3584 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
3585 check_destination_position(video
, 4, 5, 60, 40);
3586 hr
= IBasicVideo_IsUsingDefaultDestination(video
);
3587 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
3589 hr
= IBasicVideo_SetDestinationPosition(video
, 0, 0, 600, 400);
3590 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
3591 check_destination_position(video
, 0, 0, 600, 400);
3592 hr
= IBasicVideo_IsUsingDefaultDestination(video
);
3593 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
3595 hr
= IBasicVideo_SetDestinationPosition(video
, 4, 5, 60, 40);
3596 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
3597 hr
= IBasicVideo_SetDefaultDestinationPosition(video
);
3598 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
3599 check_destination_position(video
, 0, 0, 600, 400);
3600 hr
= IBasicVideo_IsUsingDefaultDestination(video
);
3601 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
3603 SetRect(&rect
, 100, 200, 500, 500);
3604 AdjustWindowRect(&rect
, WS_OVERLAPPEDWINDOW
, FALSE
);
3605 hr
= IVideoWindow_SetWindowPosition(window
, rect
.left
, rect
.top
,
3606 rect
.right
- rect
.left
, rect
.bottom
- rect
.top
);
3607 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
3608 check_destination_position(video
, 0, 0, 400, 300);
3609 hr
= IBasicVideo_IsUsingDefaultDestination(video
);
3610 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
3612 hr
= IBasicVideo_SetDestinationPosition(video
, 0, 0, 400, 300);
3613 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
3614 check_destination_position(video
, 0, 0, 400, 300);
3615 hr
= IBasicVideo_IsUsingDefaultDestination(video
);
3616 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
3618 SetRect(&rect
, 100, 200, 600, 600);
3619 AdjustWindowRect(&rect
, WS_OVERLAPPEDWINDOW
, FALSE
);
3620 hr
= IVideoWindow_SetWindowPosition(window
, rect
.left
, rect
.top
,
3621 rect
.right
- rect
.left
, rect
.bottom
- rect
.top
);
3622 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
3623 check_destination_position(video
, 0, 0, 400, 300);
3624 hr
= IBasicVideo_IsUsingDefaultDestination(video
);
3625 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
3627 IVideoWindow_Release(window
);
3630 static void test_basic_video(void)
3632 ALLOCATOR_PROPERTIES req_props
= {1, 600 * 400 * 4, 1, 0}, ret_props
;
3633 VIDEOINFOHEADER vih
=
3635 .AvgTimePerFrame
= 200000,
3636 .rcSource
= {4, 6, 16, 12},
3637 .rcTarget
= {40, 60, 120, 160},
3638 .bmiHeader
.biSize
= sizeof(BITMAPINFOHEADER
),
3639 .bmiHeader
.biBitCount
= 32,
3640 .bmiHeader
.biWidth
= 600,
3641 .bmiHeader
.biHeight
= 400,
3642 .bmiHeader
.biPlanes
= 1,
3643 .bmiHeader
.biCompression
= BI_RGB
,
3645 AM_MEDIA_TYPE req_mt
=
3647 .majortype
= MEDIATYPE_Video
,
3648 .subtype
= MEDIASUBTYPE_RGB32
,
3649 .formattype
= FORMAT_VideoInfo
,
3650 .cbFormat
= sizeof(vih
),
3651 .pbFormat
= (BYTE
*)&vih
,
3653 IBaseFilter
*filter
= create_vmr9(VMR9Mode_Windowed
);
3654 IFilterGraph2
*graph
= create_graph();
3655 LONG left
, top
, width
, height
, l
;
3656 struct testfilter source
;
3657 IMemAllocator
*allocator
;
3658 IMemInputPin
*input
;
3659 ITypeInfo
*typeinfo
;
3669 IBaseFilter_QueryInterface(filter
, &IID_IBasicVideo
, (void **)&video
);
3670 IBaseFilter_FindPin(filter
, L
"VMR Input0", &pin
);
3671 IPin_QueryInterface(pin
, &IID_IMemInputPin
, (void **)&input
);
3673 hr
= IBasicVideo_GetTypeInfoCount(video
, &count
);
3674 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
3675 ok(count
== 1, "Got count %u.\n", count
);
3677 hr
= IBasicVideo_GetTypeInfo(video
, 0, 0, &typeinfo
);
3678 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
3679 hr
= ITypeInfo_GetTypeAttr(typeinfo
, &typeattr
);
3680 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
3681 ok(typeattr
->typekind
== TKIND_DISPATCH
, "Got kind %u.\n", typeattr
->typekind
);
3682 ok(IsEqualGUID(&typeattr
->guid
, &IID_IBasicVideo
), "Got IID %s.\n", wine_dbgstr_guid(&typeattr
->guid
));
3683 ITypeInfo_ReleaseTypeAttr(typeinfo
, typeattr
);
3684 ITypeInfo_Release(typeinfo
);
3686 hr
= IBasicVideo_get_AvgTimePerFrame(video
, NULL
);
3687 ok(hr
== E_POINTER
, "Got hr %#x.\n", hr
);
3688 hr
= IBasicVideo_get_AvgTimePerFrame(video
, &reftime
);
3689 ok(hr
== VFW_E_NOT_CONNECTED
, "Got hr %#x.\n", hr
);
3691 hr
= IBasicVideo_get_BitRate(video
, NULL
);
3692 ok(hr
== E_POINTER
, "Got hr %#x.\n", hr
);
3693 hr
= IBasicVideo_get_BitRate(video
, &l
);
3694 ok(hr
== VFW_E_NOT_CONNECTED
, "Got hr %#x.\n", hr
);
3696 hr
= IBasicVideo_get_BitErrorRate(video
, NULL
);
3697 ok(hr
== E_POINTER
, "Got hr %#x.\n", hr
);
3698 hr
= IBasicVideo_get_BitErrorRate(video
, &l
);
3699 ok(hr
== VFW_E_NOT_CONNECTED
, "Got hr %#x.\n", hr
);
3701 hr
= IBasicVideo_get_VideoWidth(video
, NULL
);
3702 ok(hr
== E_POINTER
, "Got hr %#x.\n", hr
);
3703 hr
= IBasicVideo_get_VideoHeight(video
, NULL
);
3704 ok(hr
== E_POINTER
, "Got hr %#x.\n", hr
);
3706 hr
= IBasicVideo_get_SourceLeft(video
, NULL
);
3707 ok(hr
== E_POINTER
, "Got hr %#x.\n", hr
);
3708 hr
= IBasicVideo_get_SourceWidth(video
, NULL
);
3709 ok(hr
== E_POINTER
, "Got hr %#x.\n", hr
);
3710 hr
= IBasicVideo_get_SourceTop(video
, NULL
);
3711 ok(hr
== E_POINTER
, "Got hr %#x.\n", hr
);
3712 hr
= IBasicVideo_get_SourceHeight(video
, NULL
);
3713 ok(hr
== E_POINTER
, "Got hr %#x.\n", hr
);
3715 hr
= IBasicVideo_get_DestinationLeft(video
, NULL
);
3716 ok(hr
== E_POINTER
, "Got hr %#x.\n", hr
);
3717 hr
= IBasicVideo_get_DestinationWidth(video
, NULL
);
3718 ok(hr
== E_POINTER
, "Got hr %#x.\n", hr
);
3719 hr
= IBasicVideo_get_DestinationTop(video
, NULL
);
3720 ok(hr
== E_POINTER
, "Got hr %#x.\n", hr
);
3721 hr
= IBasicVideo_get_DestinationHeight(video
, NULL
);
3722 ok(hr
== E_POINTER
, "Got hr %#x.\n", hr
);
3724 hr
= IBasicVideo_GetSourcePosition(video
, NULL
, &top
, &width
, &height
);
3725 ok(hr
== E_POINTER
, "Got hr %#x.\n", hr
);
3726 hr
= IBasicVideo_GetSourcePosition(video
, &left
, NULL
, &width
, &height
);
3727 ok(hr
== E_POINTER
, "Got hr %#x.\n", hr
);
3728 hr
= IBasicVideo_GetSourcePosition(video
, &left
, &top
, NULL
, &height
);
3729 ok(hr
== E_POINTER
, "Got hr %#x.\n", hr
);
3730 hr
= IBasicVideo_GetSourcePosition(video
, &left
, &top
, &width
, NULL
);
3731 ok(hr
== E_POINTER
, "Got hr %#x.\n", hr
);
3733 hr
= IBasicVideo_GetDestinationPosition(video
, NULL
, &top
, &width
, &height
);
3734 ok(hr
== E_POINTER
, "Got hr %#x.\n", hr
);
3735 hr
= IBasicVideo_GetDestinationPosition(video
, &left
, NULL
, &width
, &height
);
3736 ok(hr
== E_POINTER
, "Got hr %#x.\n", hr
);
3737 hr
= IBasicVideo_GetDestinationPosition(video
, &left
, &top
, NULL
, &height
);
3738 ok(hr
== E_POINTER
, "Got hr %#x.\n", hr
);
3739 hr
= IBasicVideo_GetDestinationPosition(video
, &left
, &top
, &width
, NULL
);
3740 ok(hr
== E_POINTER
, "Got hr %#x.\n", hr
);
3742 hr
= IBasicVideo_GetVideoSize(video
, &width
, NULL
);
3743 ok(hr
== E_POINTER
, "Got hr %#x.\n", hr
);
3744 hr
= IBasicVideo_GetVideoSize(video
, NULL
, &height
);
3745 ok(hr
== E_POINTER
, "Got hr %#x.\n", hr
);
3747 hr
= IBasicVideo_GetVideoPaletteEntries(video
, 0, 1, NULL
, &l
);
3748 ok(hr
== E_POINTER
, "Got hr %#x.\n", hr
);
3749 hr
= IBasicVideo_GetVideoPaletteEntries(video
, 0, 1, &l
, NULL
);
3750 todo_wine
ok(hr
== VFW_E_NOT_CONNECTED
, "Got hr %#x.\n", hr
);
3752 testfilter_init(&source
);
3753 IFilterGraph2_AddFilter(graph
, &source
.filter
.IBaseFilter_iface
, L
"vmr9");
3754 IFilterGraph2_AddFilter(graph
, filter
, L
"source");
3755 hr
= IFilterGraph2_ConnectDirect(graph
, &source
.source
.pin
.IPin_iface
, pin
, &req_mt
);
3758 skip("Got E_FAIL when connecting.\n");
3761 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
3763 hr
= IMemInputPin_GetAllocator(input
, &allocator
);
3764 todo_wine
ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
3767 hr
= IMemAllocator_SetProperties(allocator
, &req_props
, &ret_props
);
3768 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
3769 ok(!memcmp(&ret_props
, &req_props
, sizeof(req_props
)), "Properties did not match.\n");
3770 hr
= IMemAllocator_Commit(allocator
);
3771 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
3772 IMemAllocator_Release(allocator
);
3776 hr
= IBasicVideo_get_AvgTimePerFrame(video
, &reftime
);
3777 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
3778 ok(compare_double(reftime
, 0.02, 1 << 28), "Got frame rate %.16e.\n", reftime
);
3781 hr
= IBasicVideo_get_BitRate(video
, &l
);
3782 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
3783 ok(!l
, "Got bit rate %d.\n", l
);
3786 hr
= IBasicVideo_get_BitErrorRate(video
, &l
);
3787 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
3788 ok(!l
, "Got bit rate %d.\n", l
);
3790 hr
= IBasicVideo_GetVideoPaletteEntries(video
, 0, 1, &l
, NULL
);
3791 todo_wine
ok(hr
== VFW_E_NO_PALETTE_AVAILABLE
, "Got hr %#x.\n", hr
);
3793 width
= height
= 0xdeadbeef;
3794 hr
= IBasicVideo_GetVideoSize(video
, &width
, &height
);
3795 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
3796 ok(width
== 600, "Got width %d.\n", width
);
3797 ok(height
== 400, "Got height %d.\n", height
);
3799 test_basic_video_source(video
);
3800 test_basic_video_destination(video
);
3802 hr
= IFilterGraph2_Disconnect(graph
, &source
.source
.pin
.IPin_iface
);
3803 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
3804 hr
= IFilterGraph2_Disconnect(graph
, pin
);
3805 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
3807 vih
.bmiHeader
.biWidth
= 16;
3808 vih
.bmiHeader
.biHeight
= 16;
3809 hr
= IFilterGraph2_ConnectDirect(graph
, &source
.source
.pin
.IPin_iface
, pin
, &req_mt
);
3810 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
3812 hr
= IMemInputPin_GetAllocator(input
, &allocator
);
3813 todo_wine
ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
3816 hr
= IMemAllocator_SetProperties(allocator
, &req_props
, &ret_props
);
3817 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
3818 ok(!memcmp(&ret_props
, &req_props
, sizeof(req_props
)), "Properties did not match.\n");
3819 hr
= IMemAllocator_Commit(allocator
);
3820 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
3821 IMemAllocator_Release(allocator
);
3824 check_source_position(video
, 0, 0, 16, 16);
3826 SetRect(&rect
, 0, 0, 0, 0);
3827 AdjustWindowRectEx(&rect
, WS_CLIPSIBLINGS
| WS_CLIPCHILDREN
| WS_OVERLAPPEDWINDOW
, FALSE
, 0);
3828 check_destination_position(video
, 0, 0, max(16, GetSystemMetrics(SM_CXMIN
) - (rect
.right
- rect
.left
)),
3829 max(16, GetSystemMetrics(SM_CYMIN
) - (rect
.bottom
- rect
.top
)));
3832 ref
= IFilterGraph2_Release(graph
);
3833 ok(!ref
, "Got outstanding refcount %d.\n", ref
);
3834 IBasicVideo_Release(video
);
3835 IMemInputPin_Release(input
);
3837 ref
= IBaseFilter_Release(filter
);
3838 ok(!ref
, "Got outstanding refcount %d.\n", ref
);
3839 ref
= IBaseFilter_Release(&source
.filter
.IBaseFilter_iface
);
3840 ok(!ref
, "Got outstanding refcount %d.\n", ref
);
3843 static void test_windowless_size(void)
3845 ALLOCATOR_PROPERTIES req_props
= {1, 32 * 16 * 4, 1, 0}, ret_props
;
3846 VIDEOINFOHEADER vih
=
3848 .bmiHeader
.biSize
= sizeof(BITMAPINFOHEADER
),
3849 .bmiHeader
.biWidth
= 32,
3850 .bmiHeader
.biHeight
= 16,
3851 .bmiHeader
.biBitCount
= 32,
3852 .bmiHeader
.biPlanes
= 1,
3856 .majortype
= MEDIATYPE_Video
,
3857 .subtype
= MEDIASUBTYPE_RGB32
,
3858 .formattype
= FORMAT_VideoInfo
,
3859 .cbFormat
= sizeof(vih
),
3860 .pbFormat
= (BYTE
*)&vih
,
3862 IBaseFilter
*filter
= create_vmr9(VMR9Mode_Windowless
);
3863 LONG width
, height
, aspect_width
, aspect_height
;
3864 IVMRAspectRatioControl9
*aspect_ratio_control
;
3865 IVMRWindowlessControl9
*windowless_control
;
3866 IFilterGraph2
*graph
= create_graph();
3867 VMR9AspectRatioMode aspect_mode
;
3868 struct testfilter source
;
3869 IMemAllocator
*allocator
;
3870 RECT src
, dst
, expect
;
3871 IMemInputPin
*input
;
3877 IBaseFilter_QueryInterface(filter
, &IID_IVMRWindowlessControl9
, (void **)&windowless_control
);
3878 IBaseFilter_QueryInterface(filter
, &IID_IVMRAspectRatioControl9
, (void **)&aspect_ratio_control
);
3879 IBaseFilter_FindPin(filter
, L
"VMR Input0", &pin
);
3880 IPin_QueryInterface(pin
, &IID_IMemInputPin
, (void **)&input
);
3881 testfilter_init(&source
);
3882 IFilterGraph2_AddFilter(graph
, &source
.filter
.IBaseFilter_iface
, L
"source");
3883 IFilterGraph2_AddFilter(graph
, filter
, L
"vmr9");
3884 window
= CreateWindowA("static", "quartz_test", WS_OVERLAPPEDWINDOW
, 0, 0, 640, 480, 0, 0, 0, 0);
3885 ok(!!window
, "Failed to create a window.\n");
3887 hr
= IVMRWindowlessControl9_SetVideoClippingWindow(windowless_control
, window
);
3888 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
3890 hr
= IFilterGraph2_ConnectDirect(graph
, &source
.source
.pin
.IPin_iface
, pin
, &mt
);
3891 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
3892 hr
= IMemInputPin_GetAllocator(input
, &allocator
);
3893 todo_wine
ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
3896 hr
= IMemAllocator_SetProperties(allocator
, &req_props
, &ret_props
);
3897 IMemAllocator_Release(allocator
);
3900 skip("Got E_FAIL when setting allocator properties.\n");
3903 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
3904 ok(!memcmp(&ret_props
, &req_props
, sizeof(req_props
)), "Properties did not match.\n");
3907 hr
= IVMRWindowlessControl9_GetNativeVideoSize(windowless_control
, NULL
, &height
, &aspect_width
, &aspect_height
);
3908 ok(hr
== E_POINTER
, "Got hr %#x.\n", hr
);
3909 hr
= IVMRWindowlessControl9_GetNativeVideoSize(windowless_control
, &width
, NULL
, &aspect_width
, &aspect_height
);
3910 ok(hr
== E_POINTER
, "Got hr %#x.\n", hr
);
3912 aspect_mode
= 0xdeadbeef;
3913 hr
= IVMRWindowlessControl9_GetAspectRatioMode(windowless_control
, &aspect_mode
);
3914 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
3915 ok(aspect_mode
== VMR9ARMode_None
, "Got mode %u.\n", aspect_mode
);
3917 aspect_mode
= 0xdeadbeef;
3918 hr
= IVMRAspectRatioControl9_GetAspectRatioMode(aspect_ratio_control
, &aspect_mode
);
3919 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
3920 ok(aspect_mode
== VMR9ARMode_None
, "Got mode %u.\n", aspect_mode
);
3922 width
= height
= 0xdeadbeef;
3923 hr
= IVMRWindowlessControl9_GetNativeVideoSize(windowless_control
, &width
, &height
, NULL
, NULL
);
3924 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
3925 ok(width
== 32, "Got width %d.\n", width
);
3926 ok(height
== 16, "Got height %d.\n", height
);
3928 aspect_width
= aspect_height
= 0xdeadbeef;
3929 hr
= IVMRWindowlessControl9_GetNativeVideoSize(windowless_control
, &width
, &height
, &aspect_width
, &aspect_height
);
3930 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
3931 ok(aspect_width
== 32, "Got width %d.\n", aspect_width
);
3932 ok(aspect_height
== 16, "Got height %d.\n", aspect_height
);
3934 memset(&src
, 0xcc, sizeof(src
));
3935 hr
= IVMRWindowlessControl9_GetVideoPosition(windowless_control
, &src
, NULL
);
3936 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
3937 SetRect(&expect
, 0, 0, 32, 16);
3938 ok(EqualRect(&src
, &expect
), "Got source rect %s.\n", wine_dbgstr_rect(&src
));
3940 memset(&dst
, 0xcc, sizeof(dst
));
3941 hr
= IVMRWindowlessControl9_GetVideoPosition(windowless_control
, NULL
, &dst
);
3942 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
3943 SetRect(&expect
, 0, 0, 0, 0);
3944 ok(EqualRect(&dst
, &expect
), "Got dest rect %s.\n", wine_dbgstr_rect(&dst
));
3946 SetRect(&src
, 4, 6, 16, 12);
3947 hr
= IVMRWindowlessControl9_SetVideoPosition(windowless_control
, &src
, NULL
);
3948 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
3950 memset(&src
, 0xcc, sizeof(src
));
3951 memset(&dst
, 0xcc, sizeof(dst
));
3952 hr
= IVMRWindowlessControl9_GetVideoPosition(windowless_control
, &src
, &dst
);
3953 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
3954 SetRect(&expect
, 4, 6, 16, 12);
3955 ok(EqualRect(&src
, &expect
), "Got source rect %s.\n", wine_dbgstr_rect(&src
));
3956 SetRect(&expect
, 0, 0, 0, 0);
3957 ok(EqualRect(&dst
, &expect
), "Got dest rect %s.\n", wine_dbgstr_rect(&dst
));
3959 SetRect(&dst
, 40, 60, 120, 160);
3960 hr
= IVMRWindowlessControl9_SetVideoPosition(windowless_control
, NULL
, &dst
);
3961 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
3963 memset(&src
, 0xcc, sizeof(src
));
3964 memset(&dst
, 0xcc, sizeof(dst
));
3965 hr
= IVMRWindowlessControl9_GetVideoPosition(windowless_control
, &src
, &dst
);
3966 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
3967 SetRect(&expect
, 4, 6, 16, 12);
3968 ok(EqualRect(&src
, &expect
), "Got source rect %s.\n", wine_dbgstr_rect(&src
));
3969 SetRect(&expect
, 40, 60, 120, 160);
3970 ok(EqualRect(&dst
, &expect
), "Got dest rect %s.\n", wine_dbgstr_rect(&dst
));
3972 GetWindowRect(window
, &src
);
3973 SetRect(&expect
, 0, 0, 640, 480);
3974 ok(EqualRect(&src
, &expect
), "Got window rect %s.\n", wine_dbgstr_rect(&src
));
3976 hr
= IVMRAspectRatioControl9_SetAspectRatioMode(aspect_ratio_control
, VMR9ARMode_LetterBox
);
3977 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
3979 aspect_mode
= 0xdeadbeef;
3980 hr
= IVMRWindowlessControl9_GetAspectRatioMode(windowless_control
, &aspect_mode
);
3981 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
3982 ok(aspect_mode
== VMR9ARMode_LetterBox
, "Got mode %u.\n", aspect_mode
);
3984 hr
= IVMRWindowlessControl9_SetAspectRatioMode(windowless_control
, VMR9ARMode_None
);
3985 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
3987 aspect_mode
= 0xdeadbeef;
3988 hr
= IVMRAspectRatioControl9_GetAspectRatioMode(aspect_ratio_control
, &aspect_mode
);
3989 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
3990 ok(aspect_mode
== VMR9ARMode_None
, "Got mode %u.\n", aspect_mode
);
3992 hr
= IVMRWindowlessControl9_SetAspectRatioMode(windowless_control
, VMR9ARMode_LetterBox
);
3993 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
3995 memset(&src
, 0xcc, sizeof(src
));
3996 memset(&dst
, 0xcc, sizeof(dst
));
3997 hr
= IVMRWindowlessControl9_GetVideoPosition(windowless_control
, &src
, &dst
);
3998 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
3999 SetRect(&expect
, 4, 6, 16, 12);
4000 ok(EqualRect(&src
, &expect
), "Got source rect %s.\n", wine_dbgstr_rect(&src
));
4001 SetRect(&expect
, 40, 60, 120, 160);
4002 ok(EqualRect(&dst
, &expect
), "Got dest rect %s.\n", wine_dbgstr_rect(&dst
));
4004 SetRect(&src
, 0, 0, 32, 16);
4005 SetRect(&dst
, 0, 0, 640, 480);
4006 hr
= IVMRWindowlessControl9_SetVideoPosition(windowless_control
, &src
, &dst
);
4007 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
4009 memset(&src
, 0xcc, sizeof(src
));
4010 memset(&dst
, 0xcc, sizeof(dst
));
4011 hr
= IVMRWindowlessControl9_GetVideoPosition(windowless_control
, &src
, &dst
);
4012 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
4013 SetRect(&expect
, 0, 0, 32, 16);
4014 ok(EqualRect(&src
, &expect
), "Got source rect %s.\n", wine_dbgstr_rect(&src
));
4015 SetRect(&expect
, 0, 0, 640, 480);
4016 ok(EqualRect(&dst
, &expect
), "Got dest rect %s.\n", wine_dbgstr_rect(&dst
));
4019 ref
= IFilterGraph2_Release(graph
);
4020 ok(!ref
, "Got outstanding refcount %d.\n", ref
);
4021 IMemInputPin_Release(input
);
4023 IVMRWindowlessControl9_Release(windowless_control
);
4024 IVMRAspectRatioControl9_Release(aspect_ratio_control
);
4025 ref
= IBaseFilter_Release(filter
);
4026 ok(!ref
, "Got outstanding refcount %d.\n", ref
);
4027 DestroyWindow(window
);
4030 static void test_mixing_prefs(void)
4032 IBaseFilter
*filter
= create_vmr9(VMR9Mode_Windowed
);
4033 IVMRMixerControl9
*mixer_control
;
4038 set_mixing_mode(filter
, 1);
4040 hr
= IBaseFilter_QueryInterface(filter
, &IID_IVMRMixerControl9
, (void **)&mixer_control
);
4041 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
4043 hr
= IVMRMixerControl9_GetMixingPrefs(mixer_control
, &flags
);
4044 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
4045 ok(flags
== (MixerPref9_NoDecimation
| MixerPref9_ARAdjustXorY
| MixerPref9_BiLinearFiltering
4046 | MixerPref9_RenderTargetRGB
), "Got flags %#x.\n", flags
);
4048 hr
= IVMRMixerControl9_SetMixingPrefs(mixer_control
, MixerPref9_NoDecimation
4049 | MixerPref9_ARAdjustXorY
| MixerPref9_PointFiltering
| MixerPref9_RenderTargetRGB
);
4050 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
4052 hr
= IVMRMixerControl9_GetMixingPrefs(mixer_control
, &flags
);
4053 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
4054 ok(flags
== (MixerPref9_NoDecimation
| MixerPref9_ARAdjustXorY
| MixerPref9_PointFiltering
4055 | MixerPref9_RenderTargetRGB
), "Got flags %#x.\n", flags
);
4057 IVMRMixerControl9_Release(mixer_control
);
4058 ref
= IBaseFilter_Release(filter
);
4059 ok(!ref
, "Got outstanding refcount %d.\n", ref
);
4064 IBaseFilter
*filter
;
4069 if (FAILED(hr
= CoCreateInstance(&CLSID_VideoMixingRenderer9
, NULL
,
4070 CLSCTX_INPROC_SERVER
, &IID_IBaseFilter
, (void **)&filter
)))
4072 skip("Failed to create VMR9, hr %#x.\n", hr
);
4075 IBaseFilter_Release(filter
);
4077 test_filter_config();
4084 test_enum_media_types();
4085 test_unconnected_filter_state();
4088 test_video_window();
4089 test_allocate_surface_helper();
4090 test_renderless_formats();
4092 test_clipping_window();
4093 test_surface_allocator_notify_refcount();
4095 test_windowless_size();
4096 test_mixing_prefs();