quartz/tests: Test the close button of the video window.
[wine.git] / dlls / quartz / tests / vmr7.c
blob4673601a40b338731ace78650f6dd467d743aed6
1 /*
2 * Video Mixing Renderer 7 unit tests
4 * Copyright 2018 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
21 #include <stdint.h>
22 #define COBJMACROS
23 #include "dshow.h"
24 #include "d3d9.h"
25 #include "vmr9.h"
26 #include "wine/strmbase.h"
27 #include "wine/test.h"
29 static IBaseFilter *create_vmr7(DWORD mode)
31 IBaseFilter *filter = NULL;
32 IVMRFilterConfig *config;
33 HRESULT hr = CoCreateInstance(&CLSID_VideoMixingRenderer, NULL, CLSCTX_INPROC_SERVER,
34 &IID_IBaseFilter, (void **)&filter);
35 ok(hr == S_OK, "Got hr %#x.\n", hr);
36 if (mode)
38 hr = IBaseFilter_QueryInterface(filter, &IID_IVMRFilterConfig, (void **)&config);
39 ok(hr == S_OK, "Got hr %#x.\n", hr);
40 hr = IVMRFilterConfig_SetRenderingMode(config, mode);
41 ok(hr == S_OK, "Got hr %#x.\n", hr);
42 IVMRFilterConfig_Release(config);
44 return filter;
47 static HRESULT set_mixing_mode(IBaseFilter *filter)
49 IVMRFilterConfig *config;
50 HRESULT hr;
52 hr = IBaseFilter_QueryInterface(filter, &IID_IVMRFilterConfig, (void **)&config);
53 ok(hr == S_OK, "Got hr %#x.\n", hr);
55 hr = IVMRFilterConfig_SetNumberOfStreams(config, 2);
56 todo_wine ok(hr == VFW_E_DDRAW_CAPS_NOT_SUITABLE || hr == S_OK, "Got hr %#x.\n", hr);
58 IVMRFilterConfig_Release(config);
59 return hr;
62 static inline BOOL compare_media_types(const AM_MEDIA_TYPE *a, const AM_MEDIA_TYPE *b)
64 return !memcmp(a, b, offsetof(AM_MEDIA_TYPE, pbFormat))
65 && !memcmp(a->pbFormat, b->pbFormat, a->cbFormat);
68 static BOOL compare_double(double f, double g, unsigned int ulps)
70 uint64_t x = *(ULONGLONG *)&f;
71 uint64_t y = *(ULONGLONG *)&g;
73 if (f < 0)
74 x = ~x + 1;
75 else
76 x |= ((ULONGLONG)1)<<63;
77 if (g < 0)
78 y = ~y + 1;
79 else
80 y |= ((ULONGLONG)1)<<63;
82 return (x>y ? x-y : y-x) <= ulps;
85 static IFilterGraph2 *create_graph(void)
87 IFilterGraph2 *ret;
88 HRESULT hr;
89 hr = CoCreateInstance(&CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, &IID_IFilterGraph2, (void **)&ret);
90 ok(hr == S_OK, "Failed to create FilterGraph: %#x\n", hr);
91 return ret;
94 static ULONG get_refcount(void *iface)
96 IUnknown *unknown = iface;
97 IUnknown_AddRef(unknown);
98 return IUnknown_Release(unknown);
101 static void test_filter_config(void)
103 IVMRFilterConfig *config;
104 DWORD count, mode;
105 HRESULT hr;
106 ULONG ref;
108 hr = CoCreateInstance(&CLSID_VideoMixingRenderer, NULL, CLSCTX_INPROC_SERVER,
109 &IID_IVMRFilterConfig, (void **)&config);
110 ok(hr == S_OK, "Got hr %#x.\n", hr);
112 hr = IVMRFilterConfig_GetRenderingMode(config, &mode);
113 ok(hr == S_OK, "Got hr %#x.\n", hr);
114 ok(mode == VMRMode_Windowed, "Got mode %#x.\n", mode);
116 hr = IVMRFilterConfig_SetRenderingMode(config, VMRMode_Windowed);
117 ok(hr == S_OK, "Got hr %#x.\n", hr);
119 hr = IVMRFilterConfig_GetRenderingMode(config, &mode);
120 ok(hr == S_OK, "Got hr %#x.\n", hr);
121 ok(mode == VMRMode_Windowed, "Got mode %#x.\n", mode);
123 hr = IVMRFilterConfig_SetRenderingMode(config, VMRMode_Windowed);
124 ok(hr == VFW_E_WRONG_STATE, "Got hr %#x.\n", hr);
126 ref = IVMRFilterConfig_Release(config);
127 ok(!ref, "Got outstanding refcount %d.\n", ref);
129 hr = CoCreateInstance(&CLSID_VideoMixingRenderer, NULL, CLSCTX_INPROC_SERVER,
130 &IID_IVMRFilterConfig, (void **)&config);
131 ok(hr == S_OK, "Got hr %#x.\n", hr);
133 hr = IVMRFilterConfig_SetRenderingMode(config, VMRMode_Windowless);
134 ok(hr == S_OK, "Got hr %#x.\n", hr);
136 hr = IVMRFilterConfig_GetRenderingMode(config, &mode);
137 ok(hr == S_OK, "Got hr %#x.\n", hr);
138 ok(mode == VMRMode_Windowless, "Got mode %#x.\n", mode);
140 hr = IVMRFilterConfig_SetRenderingMode(config, VMRMode_Windowed);
141 ok(hr == VFW_E_WRONG_STATE, "Got hr %#x.\n", hr);
143 ref = IVMRFilterConfig_Release(config);
144 ok(!ref, "Got outstanding refcount %d.\n", ref);
146 hr = CoCreateInstance(&CLSID_VideoMixingRenderer, NULL, CLSCTX_INPROC_SERVER,
147 &IID_IVMRFilterConfig, (void **)&config);
148 ok(hr == S_OK, "Got hr %#x.\n", hr);
150 hr = IVMRFilterConfig_SetRenderingMode(config, VMRMode_Renderless);
151 ok(hr == S_OK, "Got hr %#x.\n", hr);
153 hr = IVMRFilterConfig_GetRenderingMode(config, &mode);
154 ok(hr == S_OK, "Got hr %#x.\n", hr);
155 ok(mode == VMRMode_Renderless, "Got mode %#x.\n", mode);
157 hr = IVMRFilterConfig_SetRenderingMode(config, VMRMode_Windowless);
158 ok(hr == VFW_E_WRONG_STATE, "Got hr %#x.\n", hr);
160 ref = IVMRFilterConfig_Release(config);
161 ok(!ref, "Got outstanding refcount %d.\n", ref);
163 hr = CoCreateInstance(&CLSID_VideoMixingRenderer, NULL, CLSCTX_INPROC_SERVER,
164 &IID_IVMRFilterConfig, (void **)&config);
165 ok(hr == S_OK, "Got hr %#x.\n", hr);
167 hr = IVMRFilterConfig_GetNumberOfStreams(config, &count);
168 todo_wine ok(hr == VFW_E_VMR_NOT_IN_MIXER_MODE, "Got hr %#x.\n", hr);
170 hr = IVMRFilterConfig_SetNumberOfStreams(config, 3);
171 if (hr != VFW_E_DDRAW_CAPS_NOT_SUITABLE)
173 todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr);
175 hr = IVMRFilterConfig_GetNumberOfStreams(config, &count);
176 todo_wine {
177 ok(hr == S_OK, "Got hr %#x.\n", hr);
178 ok(count == 3, "Got count %u.\n", count);
181 hr = IVMRFilterConfig_GetRenderingMode(config, &mode);
182 ok(hr == S_OK, "Got hr %#x.\n", hr);
183 ok(mode == VMRMode_Windowed, "Got mode %#x.\n", mode);
185 /* Despite MSDN, you can still change the rendering mode after setting the
186 * stream count. */
187 hr = IVMRFilterConfig_SetRenderingMode(config, VMRMode_Windowless);
188 ok(hr == S_OK, "Got hr %#x.\n", hr);
190 hr = IVMRFilterConfig_GetRenderingMode(config, &mode);
191 ok(hr == S_OK, "Got hr %#x.\n", hr);
192 ok(mode == VMRMode_Windowless, "Got mode %#x.\n", mode);
194 hr = IVMRFilterConfig_GetNumberOfStreams(config, &count);
195 todo_wine {
196 ok(hr == S_OK, "Got hr %#x.\n", hr);
197 ok(count == 3, "Got count %u.\n", count);
200 else
201 skip("Mixing mode is not supported.\n");
203 ref = IVMRFilterConfig_Release(config);
204 ok(!ref, "Got outstanding refcount %d.\n", ref);
207 #define check_interface(a, b, c) check_interface_(__LINE__, a, b, c)
208 static void check_interface_(unsigned int line, void *iface_ptr, REFIID iid, BOOL supported)
210 IUnknown *iface = iface_ptr;
211 HRESULT hr, expected_hr;
212 IUnknown *unk;
214 expected_hr = supported ? S_OK : E_NOINTERFACE;
216 hr = IUnknown_QueryInterface(iface, iid, (void **)&unk);
217 ok_(__FILE__, line)(hr == expected_hr, "Got hr %#x, expected %#x.\n", hr, expected_hr);
218 if (SUCCEEDED(hr))
219 IUnknown_Release(unk);
222 static void test_interfaces(void)
224 IBaseFilter *filter = create_vmr7(0);
225 ULONG ref;
226 IPin *pin;
228 check_interface(filter, &IID_IAMCertifiedOutputProtection, TRUE);
229 check_interface(filter, &IID_IAMFilterMiscFlags, TRUE);
230 check_interface(filter, &IID_IBaseFilter, TRUE);
231 check_interface(filter, &IID_IBasicVideo, TRUE);
232 todo_wine check_interface(filter, &IID_IBasicVideo2, TRUE);
233 todo_wine check_interface(filter, &IID_IKsPropertySet, TRUE);
234 check_interface(filter, &IID_IMediaFilter, TRUE);
235 check_interface(filter, &IID_IMediaPosition, TRUE);
236 check_interface(filter, &IID_IMediaSeeking, TRUE);
237 check_interface(filter, &IID_IPersist, TRUE);
238 check_interface(filter, &IID_IQualityControl, TRUE);
239 todo_wine check_interface(filter, &IID_IQualProp, TRUE);
240 check_interface(filter, &IID_IUnknown, TRUE);
241 check_interface(filter, &IID_IVideoWindow, TRUE);
242 todo_wine check_interface(filter, &IID_IVMRAspectRatioControl, TRUE);
243 todo_wine check_interface(filter, &IID_IVMRDeinterlaceControl, TRUE);
244 check_interface(filter, &IID_IVMRFilterConfig, TRUE);
245 todo_wine check_interface(filter, &IID_IVMRMixerBitmap, TRUE);
246 check_interface(filter, &IID_IVMRMonitorConfig, TRUE);
248 check_interface(filter, &IID_IBasicAudio, FALSE);
249 check_interface(filter, &IID_IDirectDrawVideo, FALSE);
250 check_interface(filter, &IID_IPersistPropertyBag, FALSE);
251 check_interface(filter, &IID_IPin, FALSE);
252 check_interface(filter, &IID_IReferenceClock, FALSE);
253 check_interface(filter, &IID_IVMRAspectRatioControl9, FALSE);
254 check_interface(filter, &IID_IVMRDeinterlaceControl9, FALSE);
255 check_interface(filter, &IID_IVMRFilterConfig9, FALSE);
256 check_interface(filter, &IID_IVMRMixerBitmap9, FALSE);
257 check_interface(filter, &IID_IVMRMixerControl, FALSE);
258 check_interface(filter, &IID_IVMRMixerControl9, FALSE);
259 check_interface(filter, &IID_IVMRMonitorConfig9, FALSE);
260 check_interface(filter, &IID_IVMRSurfaceAllocatorNotify, FALSE);
261 check_interface(filter, &IID_IVMRSurfaceAllocatorNotify9, FALSE);
262 check_interface(filter, &IID_IVMRWindowlessControl, FALSE);
263 check_interface(filter, &IID_IVMRWindowlessControl9, FALSE);
265 IBaseFilter_FindPin(filter, L"VMR Input0", &pin);
267 check_interface(pin, &IID_IMemInputPin, TRUE);
268 check_interface(pin, &IID_IOverlay, TRUE);
269 check_interface(pin, &IID_IPin, TRUE);
270 todo_wine check_interface(pin, &IID_IQualityControl, TRUE);
271 check_interface(pin, &IID_IUnknown, TRUE);
273 check_interface(pin, &IID_IKsPropertySet, FALSE);
274 check_interface(pin, &IID_IMediaPosition, FALSE);
275 check_interface(pin, &IID_IMediaSeeking, FALSE);
277 IPin_Release(pin);
279 IBaseFilter_Release(filter);
280 filter = create_vmr7(VMRMode_Windowless);
282 check_interface(filter, &IID_IVMRMonitorConfig, TRUE);
283 check_interface(filter, &IID_IVMRWindowlessControl, TRUE);
285 todo_wine check_interface(filter, &IID_IBasicVideo, FALSE);
286 check_interface(filter, &IID_IBasicVideo2, FALSE);
287 todo_wine check_interface(filter, &IID_IVideoWindow, FALSE);
288 check_interface(filter, &IID_IVMRSurfaceAllocatorNotify, FALSE);
289 check_interface(filter, &IID_IVMRSurfaceAllocatorNotify9, FALSE);
290 check_interface(filter, &IID_IVMRMixerControl, FALSE);
291 check_interface(filter, &IID_IVMRMixerControl9, FALSE);
292 check_interface(filter, &IID_IVMRMonitorConfig9, FALSE);
293 check_interface(filter, &IID_IVMRWindowlessControl9, FALSE);
295 IBaseFilter_FindPin(filter, L"VMR Input0", &pin);
297 check_interface(pin, &IID_IMemInputPin, TRUE);
298 check_interface(pin, &IID_IOverlay, TRUE);
299 check_interface(pin, &IID_IPin, TRUE);
300 todo_wine check_interface(pin, &IID_IQualityControl, TRUE);
301 check_interface(pin, &IID_IUnknown, TRUE);
303 check_interface(pin, &IID_IKsPropertySet, FALSE);
304 check_interface(pin, &IID_IMediaPosition, FALSE);
305 check_interface(pin, &IID_IMediaSeeking, FALSE);
307 IPin_Release(pin);
309 IBaseFilter_Release(filter);
310 filter = create_vmr7(VMRMode_Renderless);
312 check_interface(filter, &IID_IVMRSurfaceAllocatorNotify, TRUE);
314 todo_wine check_interface(filter, &IID_IBasicVideo, FALSE);
315 check_interface(filter, &IID_IBasicVideo2, FALSE);
316 todo_wine check_interface(filter, &IID_IVideoWindow, FALSE);
317 check_interface(filter, &IID_IVMRMixerControl, FALSE);
318 todo_wine check_interface(filter, &IID_IVMRMonitorConfig, FALSE);
319 check_interface(filter, &IID_IVMRMonitorConfig9, FALSE);
320 check_interface(filter, &IID_IVMRSurfaceAllocatorNotify9, FALSE);
321 check_interface(filter, &IID_IVMRWindowlessControl, FALSE);
322 check_interface(filter, &IID_IVMRWindowlessControl9, FALSE);
324 IBaseFilter_FindPin(filter, L"VMR Input0", &pin);
326 check_interface(pin, &IID_IMemInputPin, TRUE);
327 check_interface(pin, &IID_IOverlay, TRUE);
328 check_interface(pin, &IID_IPin, TRUE);
329 todo_wine check_interface(pin, &IID_IQualityControl, TRUE);
330 check_interface(pin, &IID_IUnknown, TRUE);
332 check_interface(pin, &IID_IKsPropertySet, FALSE);
333 check_interface(pin, &IID_IMediaPosition, FALSE);
334 check_interface(pin, &IID_IMediaSeeking, FALSE);
336 IPin_Release(pin);
338 ref = IBaseFilter_Release(filter);
339 ok(!ref, "Got outstanding refcount %d.\n", ref);
342 static const GUID test_iid = {0x33333333};
343 static LONG outer_ref = 1;
345 static HRESULT WINAPI outer_QueryInterface(IUnknown *iface, REFIID iid, void **out)
347 if (IsEqualGUID(iid, &IID_IUnknown)
348 || IsEqualGUID(iid, &IID_IBaseFilter)
349 || IsEqualGUID(iid, &test_iid))
351 *out = (IUnknown *)0xdeadbeef;
352 return S_OK;
354 ok(0, "unexpected call %s\n", wine_dbgstr_guid(iid));
355 return E_NOINTERFACE;
358 static ULONG WINAPI outer_AddRef(IUnknown *iface)
360 return InterlockedIncrement(&outer_ref);
363 static ULONG WINAPI outer_Release(IUnknown *iface)
365 return InterlockedDecrement(&outer_ref);
368 static const IUnknownVtbl outer_vtbl =
370 outer_QueryInterface,
371 outer_AddRef,
372 outer_Release,
375 static IUnknown test_outer = {&outer_vtbl};
377 static void test_aggregation(void)
379 IBaseFilter *filter, *filter2;
380 IUnknown *unk, *unk2;
381 HRESULT hr;
382 ULONG ref;
384 filter = (IBaseFilter *)0xdeadbeef;
385 hr = CoCreateInstance(&CLSID_VideoMixingRenderer, &test_outer, CLSCTX_INPROC_SERVER,
386 &IID_IBaseFilter, (void **)&filter);
387 ok(hr == E_NOINTERFACE, "Got hr %#x.\n", hr);
388 ok(!filter, "Got interface %p.\n", filter);
390 hr = CoCreateInstance(&CLSID_VideoMixingRenderer, &test_outer, CLSCTX_INPROC_SERVER,
391 &IID_IUnknown, (void **)&unk);
392 ok(hr == S_OK, "Got hr %#x.\n", hr);
393 ok(outer_ref == 1, "Got unexpected refcount %d.\n", outer_ref);
394 ok(unk != &test_outer, "Returned IUnknown should not be outer IUnknown.\n");
395 ref = get_refcount(unk);
396 ok(ref == 1, "Got unexpected refcount %d.\n", ref);
398 ref = IUnknown_AddRef(unk);
399 ok(ref == 2, "Got unexpected refcount %d.\n", ref);
400 ok(outer_ref == 1, "Got unexpected refcount %d.\n", outer_ref);
402 ref = IUnknown_Release(unk);
403 ok(ref == 1, "Got unexpected refcount %d.\n", ref);
404 ok(outer_ref == 1, "Got unexpected refcount %d.\n", outer_ref);
406 hr = IUnknown_QueryInterface(unk, &IID_IUnknown, (void **)&unk2);
407 ok(hr == S_OK, "Got hr %#x.\n", hr);
408 ok(unk2 == unk, "Got unexpected IUnknown %p.\n", unk2);
409 IUnknown_Release(unk2);
411 hr = IUnknown_QueryInterface(unk, &IID_IBaseFilter, (void **)&filter);
412 ok(hr == S_OK, "Got hr %#x.\n", hr);
414 hr = IBaseFilter_QueryInterface(filter, &IID_IUnknown, (void **)&unk2);
415 ok(hr == S_OK, "Got hr %#x.\n", hr);
416 ok(unk2 == (IUnknown *)0xdeadbeef, "Got unexpected IUnknown %p.\n", unk2);
418 hr = IBaseFilter_QueryInterface(filter, &IID_IBaseFilter, (void **)&filter2);
419 ok(hr == S_OK, "Got hr %#x.\n", hr);
420 ok(filter2 == (IBaseFilter *)0xdeadbeef, "Got unexpected IBaseFilter %p.\n", filter2);
422 hr = IUnknown_QueryInterface(unk, &test_iid, (void **)&unk2);
423 ok(hr == E_NOINTERFACE, "Got hr %#x.\n", hr);
424 ok(!unk2, "Got unexpected IUnknown %p.\n", unk2);
426 hr = IBaseFilter_QueryInterface(filter, &test_iid, (void **)&unk2);
427 ok(hr == S_OK, "Got hr %#x.\n", hr);
428 ok(unk2 == (IUnknown *)0xdeadbeef, "Got unexpected IUnknown %p.\n", unk2);
430 IBaseFilter_Release(filter);
431 ref = IUnknown_Release(unk);
432 ok(!ref, "Got unexpected refcount %d.\n", ref);
433 ok(outer_ref == 1, "Got unexpected refcount %d.\n", outer_ref);
436 static void test_enum_pins(void)
438 IBaseFilter *filter = create_vmr7(0);
439 IEnumPins *enum1, *enum2;
440 ULONG count, ref;
441 IPin *pins[3];
442 HRESULT hr;
444 ref = get_refcount(filter);
445 ok(ref == 1, "Got unexpected refcount %d.\n", ref);
447 hr = IBaseFilter_EnumPins(filter, NULL);
448 ok(hr == E_POINTER, "Got hr %#x.\n", hr);
450 hr = IBaseFilter_EnumPins(filter, &enum1);
451 ok(hr == S_OK, "Got hr %#x.\n", hr);
452 ref = get_refcount(filter);
453 ok(ref == 2, "Got unexpected refcount %d.\n", ref);
454 ref = get_refcount(enum1);
455 ok(ref == 1, "Got unexpected refcount %d.\n", ref);
457 hr = IEnumPins_Next(enum1, 1, NULL, NULL);
458 ok(hr == E_POINTER, "Got hr %#x.\n", hr);
460 hr = IEnumPins_Next(enum1, 1, pins, NULL);
461 ok(hr == S_OK, "Got hr %#x.\n", hr);
462 ref = get_refcount(filter);
463 ok(ref == 3, "Got unexpected refcount %d.\n", ref);
464 ref = get_refcount(pins[0]);
465 ok(ref == 3, "Got unexpected refcount %d.\n", ref);
466 ref = get_refcount(enum1);
467 ok(ref == 1, "Got unexpected refcount %d.\n", ref);
468 IPin_Release(pins[0]);
469 ref = get_refcount(filter);
470 ok(ref == 2, "Got unexpected refcount %d.\n", ref);
472 hr = IEnumPins_Next(enum1, 1, pins, NULL);
473 ok(hr == S_FALSE, "Got hr %#x.\n", hr);
475 hr = IEnumPins_Reset(enum1);
476 ok(hr == S_OK, "Got hr %#x.\n", hr);
478 hr = IEnumPins_Next(enum1, 1, pins, &count);
479 ok(hr == S_OK, "Got hr %#x.\n", hr);
480 ok(count == 1, "Got count %u.\n", count);
481 IPin_Release(pins[0]);
483 hr = IEnumPins_Next(enum1, 1, pins, &count);
484 ok(hr == S_FALSE, "Got hr %#x.\n", hr);
485 ok(!count, "Got count %u.\n", count);
487 hr = IEnumPins_Reset(enum1);
488 ok(hr == S_OK, "Got hr %#x.\n", hr);
490 hr = IEnumPins_Next(enum1, 2, pins, NULL);
491 ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr);
493 hr = IEnumPins_Next(enum1, 2, pins, &count);
494 ok(hr == S_FALSE, "Got hr %#x.\n", hr);
495 ok(count == 1, "Got count %u.\n", count);
496 IPin_Release(pins[0]);
498 hr = IEnumPins_Reset(enum1);
499 ok(hr == S_OK, "Got hr %#x.\n", hr);
501 hr = IEnumPins_Clone(enum1, &enum2);
502 ok(hr == S_OK, "Got hr %#x.\n", hr);
504 hr = IEnumPins_Skip(enum1, 2);
505 ok(hr == S_FALSE, "Got hr %#x.\n", hr);
507 hr = IEnumPins_Skip(enum1, 1);
508 ok(hr == S_OK, "Got hr %#x.\n", hr);
510 hr = IEnumPins_Skip(enum1, 1);
511 ok(hr == S_FALSE, "Got hr %#x.\n", hr);
513 hr = IEnumPins_Next(enum1, 1, pins, NULL);
514 ok(hr == S_FALSE, "Got hr %#x.\n", hr);
516 hr = IEnumPins_Next(enum2, 1, pins, NULL);
517 ok(hr == S_OK, "Got hr %#x.\n", hr);
518 IPin_Release(pins[0]);
520 IEnumPins_Release(enum2);
522 if (SUCCEEDED(set_mixing_mode(filter)))
524 hr = IEnumPins_Next(enum1, 1, pins, NULL);
525 todo_wine ok(hr == S_FALSE, "Got hr %#x.\n", hr);
527 hr = IEnumPins_Reset(enum1);
528 ok(hr == S_OK, "Got hr %#x.\n", hr);
530 hr = IEnumPins_Next(enum1, 1, pins, NULL);
531 ok(hr == S_OK, "Got hr %#x.\n", hr);
532 IPin_Release(pins[0]);
534 hr = IEnumPins_Next(enum1, 1, pins, NULL);
535 ok(hr == S_OK, "Got hr %#x.\n", hr);
536 IPin_Release(pins[0]);
538 hr = IEnumPins_Next(enum1, 1, pins, NULL);
539 ok(hr == S_FALSE, "Got hr %#x.\n", hr);
541 hr = IEnumPins_Reset(enum1);
542 ok(hr == S_OK, "Got hr %#x.\n", hr);
544 hr = IEnumPins_Next(enum1, 2, pins, &count);
545 ok(hr == S_OK, "Got hr %#x.\n", hr);
546 ok(count == 2, "Got count %u.\n", count);
547 IPin_Release(pins[0]);
548 IPin_Release(pins[1]);
550 hr = IEnumPins_Reset(enum1);
551 ok(hr == S_OK, "Got hr %#x.\n", hr);
553 hr = IEnumPins_Next(enum1, 3, pins, &count);
554 ok(hr == S_FALSE, "Got hr %#x.\n", hr);
555 ok(count == 2, "Got count %u.\n", count);
556 IPin_Release(pins[0]);
557 IPin_Release(pins[1]);
559 else
560 skip("Mixing mode is not supported.\n");
562 IEnumPins_Release(enum1);
563 ref = IBaseFilter_Release(filter);
564 ok(!ref, "Got outstanding refcount %d.\n", ref);
567 static void test_find_pin(void)
569 IBaseFilter *filter = create_vmr7(0);
570 IEnumPins *enum_pins;
571 IPin *pin, *pin2;
572 HRESULT hr;
573 ULONG ref;
575 IBaseFilter_EnumPins(filter, &enum_pins);
577 hr = IBaseFilter_FindPin(filter, L"input pin", &pin);
578 ok(hr == VFW_E_NOT_FOUND, "Got hr %#x.\n", hr);
580 hr = IBaseFilter_FindPin(filter, L"In", &pin);
581 ok(hr == VFW_E_NOT_FOUND, "Got hr %#x.\n", hr);
583 hr = IBaseFilter_FindPin(filter, L"VMR Input0", &pin);
584 ok(hr == S_OK, "Got hr %#x.\n", hr);
585 hr = IEnumPins_Next(enum_pins, 1, &pin2, NULL);
586 ok(hr == S_OK, "Got hr %#x.\n", hr);
587 ok(pin == pin2, "Pins did not match.\n");
588 IPin_Release(pin);
589 IPin_Release(pin2);
591 hr = IBaseFilter_FindPin(filter, L"VMR input1", &pin);
592 ok(hr == VFW_E_NOT_FOUND, "Got hr %#x.\n", hr);
594 if (SUCCEEDED(set_mixing_mode(filter)))
596 IEnumPins_Reset(enum_pins);
598 hr = IBaseFilter_FindPin(filter, L"VMR Input0", &pin);
599 ok(hr == S_OK, "Got hr %#x.\n", hr);
600 hr = IEnumPins_Next(enum_pins, 1, &pin2, NULL);
601 ok(hr == S_OK, "Got hr %#x.\n", hr);
602 ok(pin == pin2, "Pins did not match.\n");
603 IPin_Release(pin);
604 IPin_Release(pin2);
606 hr = IBaseFilter_FindPin(filter, L"VMR Input1", &pin);
607 ok(hr == S_OK, "Got hr %#x.\n", hr);
608 hr = IEnumPins_Next(enum_pins, 1, &pin2, NULL);
609 ok(hr == S_OK, "Got hr %#x.\n", hr);
610 ok(pin == pin2, "Pins did not match.\n");
611 IPin_Release(pin);
612 IPin_Release(pin2);
614 hr = IBaseFilter_FindPin(filter, L"VMR Input2", &pin);
615 ok(hr == VFW_E_NOT_FOUND, "Got hr %#x.\n", hr);
617 else
618 skip("Mixing mode is not supported.\n");
620 IEnumPins_Release(enum_pins);
621 ref = IBaseFilter_Release(filter);
622 ok(!ref, "Got outstanding refcount %d.\n", ref);
625 static void test_pin_info(void)
627 IBaseFilter *filter = create_vmr7(0);
628 PIN_DIRECTION dir;
629 ULONG count, ref;
630 PIN_INFO info;
631 HRESULT hr;
632 WCHAR *id;
633 IPin *pin;
635 IBaseFilter_FindPin(filter, L"VMR Input0", &pin);
636 hr = IPin_QueryPinInfo(pin, &info);
637 ok(info.pFilter == filter, "Expected filter %p, got %p.\n", filter, info.pFilter);
638 ok(info.dir == PINDIR_INPUT, "Got direction %d.\n", info.dir);
639 ok(!wcscmp(info.achName, L"VMR Input0"), "Got name %s.\n", wine_dbgstr_w(info.achName));
640 IBaseFilter_Release(info.pFilter);
642 hr = IPin_QueryDirection(pin, &dir);
643 ok(hr == S_OK, "Got hr %#x.\n", hr);
644 ok(dir == PINDIR_INPUT, "Got direction %d.\n", dir);
646 hr = IPin_QueryId(pin, &id);
647 ok(hr == S_OK, "Got hr %#x.\n", hr);
648 ok(!wcscmp(id, L"VMR Input0"), "Got id %s.\n", wine_dbgstr_w(id));
649 CoTaskMemFree(id);
651 hr = IPin_QueryInternalConnections(pin, NULL, &count);
652 ok(hr == E_NOTIMPL, "Got hr %#x.\n", hr);
654 IPin_Release(pin);
656 if (SUCCEEDED(set_mixing_mode(filter)))
658 IBaseFilter_FindPin(filter, L"VMR Input1", &pin);
659 hr = IPin_QueryPinInfo(pin, &info);
660 ok(info.pFilter == filter, "Expected filter %p, got %p.\n", filter, info.pFilter);
661 ok(info.dir == PINDIR_INPUT, "Got direction %d.\n", info.dir);
662 ok(!wcscmp(info.achName, L"VMR Input1"), "Got name %s.\n", wine_dbgstr_w(info.achName));
663 IBaseFilter_Release(info.pFilter);
665 hr = IPin_QueryDirection(pin, &dir);
666 ok(hr == S_OK, "Got hr %#x.\n", hr);
667 ok(dir == PINDIR_INPUT, "Got direction %d.\n", dir);
669 hr = IPin_QueryId(pin, &id);
670 ok(hr == S_OK, "Got hr %#x.\n", hr);
671 ok(!wcscmp(id, L"VMR Input1"), "Got id %s.\n", wine_dbgstr_w(id));
672 CoTaskMemFree(id);
674 hr = IPin_QueryInternalConnections(pin, NULL, &count);
675 ok(hr == E_NOTIMPL, "Got hr %#x.\n", hr);
677 IPin_Release(pin);
679 else
680 skip("Mixing mode is not supported.\n");
682 ref = IBaseFilter_Release(filter);
683 ok(!ref, "Got outstanding refcount %d.\n", ref);
686 static void test_media_types(void)
688 IBaseFilter *filter = create_vmr7(0);
689 AM_MEDIA_TYPE *mt, req_mt = {{0}};
690 VIDEOINFOHEADER vih =
692 {0}, {0}, 0, 0, 0,
693 {sizeof(BITMAPINFOHEADER), 32, 24, 1, 0, BI_RGB}
695 IEnumMediaTypes *enummt;
696 unsigned int i;
697 HRESULT hr;
698 ULONG ref;
699 IPin *pin;
701 static const GUID *subtype_tests[] =
703 &MEDIASUBTYPE_NULL,
704 &MEDIASUBTYPE_RGB565,
705 &MEDIASUBTYPE_RGB24,
706 &MEDIASUBTYPE_RGB32,
709 IBaseFilter_FindPin(filter, L"VMR Input0", &pin);
711 hr = IPin_EnumMediaTypes(pin, &enummt);
712 ok(hr == S_OK, "Got hr %#x.\n", hr);
714 hr = IEnumMediaTypes_Next(enummt, 1, &mt, NULL);
715 ok(hr == S_FALSE, "Got hr %#x.\n", hr);
717 IEnumMediaTypes_Release(enummt);
719 req_mt.majortype = MEDIATYPE_Video;
720 req_mt.formattype = FORMAT_VideoInfo;
721 req_mt.cbFormat = sizeof(VIDEOINFOHEADER);
722 req_mt.pbFormat = (BYTE *)&vih;
724 for (i = 0; i < ARRAY_SIZE(subtype_tests); ++i)
726 req_mt.subtype = *subtype_tests[i];
727 hr = IPin_QueryAccept(pin, &req_mt);
728 ok(hr == S_OK, "Got hr %#x for subtype %s.\n", hr, wine_dbgstr_guid(subtype_tests[i]));
731 req_mt.subtype = MEDIASUBTYPE_RGB8;
732 hr = IPin_QueryAccept(pin, &req_mt);
733 todo_wine ok(hr == S_FALSE, "Got hr %#x.\n", hr);
734 req_mt.subtype = MEDIASUBTYPE_RGB24;
736 req_mt.majortype = MEDIATYPE_NULL;
737 hr = IPin_QueryAccept(pin, &req_mt);
738 ok(hr == S_FALSE, "Got hr %#x.\n", hr);
739 req_mt.majortype = MEDIATYPE_Video;
741 req_mt.formattype = FORMAT_None;
742 hr = IPin_QueryAccept(pin, &req_mt);
743 ok(hr == S_FALSE, "Got hr %#x.\n", hr);
745 req_mt.formattype = GUID_NULL;
746 hr = IPin_QueryAccept(pin, &req_mt);
747 ok(hr == S_FALSE, "Got hr %#x.\n", hr);
749 IPin_Release(pin);
750 ref = IBaseFilter_Release(filter);
751 ok(!ref, "Got outstanding refcount %d.\n", ref);
754 static void test_enum_media_types(void)
756 IBaseFilter *filter = create_vmr7(0);
757 IEnumMediaTypes *enum1, *enum2;
758 AM_MEDIA_TYPE *mts[2];
759 ULONG ref, count;
760 HRESULT hr;
761 IPin *pin;
763 IBaseFilter_FindPin(filter, L"VMR Input0", &pin);
765 hr = IPin_EnumMediaTypes(pin, &enum1);
766 ok(hr == S_OK, "Got hr %#x.\n", hr);
768 hr = IEnumMediaTypes_Next(enum1, 1, mts, NULL);
769 ok(hr == S_FALSE, "Got hr %#x.\n", hr);
771 hr = IEnumMediaTypes_Next(enum1, 1, mts, &count);
772 ok(hr == S_FALSE, "Got hr %#x.\n", hr);
773 ok(!count, "Got count %u.\n", count);
775 hr = IEnumMediaTypes_Reset(enum1);
776 ok(hr == S_OK, "Got hr %#x.\n", hr);
778 hr = IEnumMediaTypes_Next(enum1, 1, mts, NULL);
779 ok(hr == S_FALSE, "Got hr %#x.\n", hr);
781 hr = IEnumMediaTypes_Clone(enum1, &enum2);
782 ok(hr == S_OK, "Got hr %#x.\n", hr);
784 hr = IEnumMediaTypes_Skip(enum1, 1);
785 ok(hr == S_FALSE, "Got hr %#x.\n", hr);
787 hr = IEnumMediaTypes_Next(enum2, 1, mts, NULL);
788 ok(hr == S_FALSE, "Got hr %#x.\n", hr);
790 IEnumMediaTypes_Release(enum1);
791 IEnumMediaTypes_Release(enum2);
792 IPin_Release(pin);
794 ref = IBaseFilter_Release(filter);
795 ok(!ref, "Got outstanding refcount %d.\n", ref);
798 static void test_unconnected_filter_state(void)
800 IBaseFilter *filter = create_vmr7(0);
801 FILTER_STATE state;
802 HRESULT hr;
803 ULONG ref;
805 hr = IBaseFilter_GetState(filter, 0, &state);
806 ok(hr == S_OK, "Got hr %#x.\n", hr);
807 ok(state == State_Stopped, "Got state %u.\n", state);
809 hr = IBaseFilter_Pause(filter);
810 ok(hr == S_OK, "Got hr %#x.\n", hr);
812 hr = IBaseFilter_GetState(filter, 0, &state);
813 ok(hr == S_OK, "Got hr %#x.\n", hr);
814 ok(state == State_Paused, "Got state %u.\n", state);
816 hr = IBaseFilter_Run(filter, 0);
817 ok(hr == S_OK, "Got hr %#x.\n", hr);
819 hr = IBaseFilter_GetState(filter, 0, &state);
820 ok(hr == S_OK, "Got hr %#x.\n", hr);
821 ok(state == State_Running, "Got state %u.\n", state);
823 hr = IBaseFilter_Pause(filter);
824 ok(hr == S_OK, "Got hr %#x.\n", hr);
826 hr = IBaseFilter_GetState(filter, 0, &state);
827 ok(hr == S_OK, "Got hr %#x.\n", hr);
828 ok(state == State_Paused, "Got state %u.\n", state);
830 hr = IBaseFilter_Stop(filter);
831 ok(hr == S_OK, "Got hr %#x.\n", hr);
833 hr = IBaseFilter_GetState(filter, 0, &state);
834 ok(hr == S_OK, "Got hr %#x.\n", hr);
835 ok(state == State_Stopped, "Got state %u.\n", state);
837 hr = IBaseFilter_Run(filter, 0);
838 ok(hr == S_OK, "Got hr %#x.\n", hr);
840 hr = IBaseFilter_GetState(filter, 0, &state);
841 ok(hr == S_OK, "Got hr %#x.\n", hr);
842 ok(state == State_Running, "Got state %u.\n", state);
844 hr = IBaseFilter_Stop(filter);
845 ok(hr == S_OK, "Got hr %#x.\n", hr);
847 hr = IBaseFilter_GetState(filter, 0, &state);
848 ok(hr == S_OK, "Got hr %#x.\n", hr);
849 ok(state == State_Stopped, "Got state %u.\n", state);
851 ref = IBaseFilter_Release(filter);
852 ok(!ref, "Got outstanding refcount %d.\n", ref);
855 struct testfilter
857 struct strmbase_filter filter;
858 struct strmbase_source source;
861 static inline struct testfilter *impl_from_strmbase_filter(struct strmbase_filter *iface)
863 return CONTAINING_RECORD(iface, struct testfilter, filter);
866 static struct strmbase_pin *testfilter_get_pin(struct strmbase_filter *iface, unsigned int index)
868 struct testfilter *filter = impl_from_strmbase_filter(iface);
869 if (!index)
870 return &filter->source.pin;
871 return NULL;
874 static void testfilter_destroy(struct strmbase_filter *iface)
876 struct testfilter *filter = impl_from_strmbase_filter(iface);
877 strmbase_source_cleanup(&filter->source);
878 strmbase_filter_cleanup(&filter->filter);
881 static const struct strmbase_filter_ops testfilter_ops =
883 .filter_get_pin = testfilter_get_pin,
884 .filter_destroy = testfilter_destroy,
887 static HRESULT WINAPI testsource_DecideAllocator(struct strmbase_source *iface,
888 IMemInputPin *peer, IMemAllocator **allocator)
890 return S_OK;
893 static const struct strmbase_source_ops testsource_ops =
895 .pfnAttemptConnection = BaseOutputPinImpl_AttemptConnection,
896 .pfnDecideAllocator = testsource_DecideAllocator,
899 static void testfilter_init(struct testfilter *filter)
901 static const GUID clsid = {0xabacab};
902 strmbase_filter_init(&filter->filter, NULL, &clsid, &testfilter_ops);
903 strmbase_source_init(&filter->source, &filter->filter, L"", &testsource_ops);
906 static void test_allocator(IMemInputPin *input)
908 IMemAllocator *req_allocator, *ret_allocator;
909 ALLOCATOR_PROPERTIES props, req_props;
910 HRESULT hr;
912 hr = IMemInputPin_GetAllocatorRequirements(input, &props);
913 ok(hr == E_NOTIMPL, "Got hr %#x.\n", hr);
915 hr = IMemInputPin_GetAllocator(input, &ret_allocator);
916 todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr);
918 if (hr == S_OK)
920 hr = IMemAllocator_GetProperties(ret_allocator, &props);
921 ok(hr == S_OK, "Got hr %#x.\n", hr);
922 ok(!props.cBuffers, "Got %d buffers.\n", props.cBuffers);
923 ok(!props.cbBuffer, "Got size %d.\n", props.cbBuffer);
924 ok(!props.cbAlign, "Got alignment %d.\n", props.cbAlign);
925 ok(!props.cbPrefix, "Got prefix %d.\n", props.cbPrefix);
927 hr = IMemInputPin_NotifyAllocator(input, ret_allocator, TRUE);
928 ok(hr == S_OK, "Got hr %#x.\n", hr);
930 req_props.cBuffers = 1;
931 req_props.cbBuffer = 32 * 16 * 4;
932 req_props.cbAlign = 1;
933 req_props.cbPrefix = 0;
934 hr = IMemAllocator_SetProperties(ret_allocator, &req_props, &props);
935 ok(hr == S_OK, "Got hr %#x.\n", hr);
936 ok(props.cBuffers == 1, "Got %d buffers.\n", props.cBuffers);
937 ok(props.cbBuffer == 32 * 16 * 4, "Got size %d.\n", props.cbBuffer);
938 ok(props.cbAlign == 1, "Got alignment %d.\n", props.cbAlign);
939 ok(!props.cbPrefix, "Got prefix %d.\n", props.cbPrefix);
941 IMemAllocator_Release(ret_allocator);
944 hr = IMemInputPin_NotifyAllocator(input, NULL, TRUE);
945 todo_wine ok(hr == E_FAIL, "Got hr %#x.\n", hr);
947 CoCreateInstance(&CLSID_MemoryAllocator, NULL, CLSCTX_INPROC_SERVER,
948 &IID_IMemAllocator, (void **)&req_allocator);
950 hr = IMemInputPin_NotifyAllocator(input, req_allocator, TRUE);
951 todo_wine ok(hr == E_FAIL, "Got hr %#x.\n", hr);
953 IMemAllocator_Release(req_allocator);
956 struct frame_thread_params
958 IMemInputPin *sink;
959 IMediaSample *sample;
962 static DWORD WINAPI frame_thread(void *arg)
964 struct frame_thread_params *params = arg;
965 HRESULT hr;
967 if (winetest_debug > 1) trace("%04x: Sending frame.\n", GetCurrentThreadId());
968 hr = IMemInputPin_Receive(params->sink, params->sample);
969 if (winetest_debug > 1) trace("%04x: Returned %#x.\n", GetCurrentThreadId(), hr);
970 IMediaSample_Release(params->sample);
971 free(params);
972 return hr;
975 static HANDLE send_frame(IMemInputPin *sink)
977 struct frame_thread_params *params = malloc(sizeof(*params));
978 REFERENCE_TIME start_time, end_time;
979 IMemAllocator *allocator;
980 IMediaSample *sample;
981 HANDLE thread;
982 HRESULT hr;
983 BYTE *data;
985 hr = IMemInputPin_GetAllocator(sink, &allocator);
986 ok(hr == S_OK, "Got hr %#x.\n", hr);
988 hr = IMemAllocator_GetBuffer(allocator, &sample, NULL, NULL, 0);
989 ok(hr == S_OK, "Got hr %#x.\n", hr);
991 hr = IMediaSample_GetPointer(sample, &data);
992 ok(hr == S_OK, "Got hr %#x.\n", hr);
993 memset(data, 0x55, IMediaSample_GetSize(sample));
995 hr = IMediaSample_SetActualDataLength(sample, IMediaSample_GetSize(sample));
996 ok(hr == S_OK, "Got hr %#x.\n", hr);
998 start_time = 0;
999 end_time = start_time + 10000000;
1000 hr = IMediaSample_SetTime(sample, &start_time, &end_time);
1001 ok(hr == S_OK, "Got hr %#x.\n", hr);
1003 hr = IMediaSample_SetPreroll(sample, TRUE);
1004 ok(hr == S_OK, "Got hr %#x.\n", hr);
1006 params->sink = sink;
1007 params->sample = sample;
1008 thread = CreateThread(NULL, 0, frame_thread, params, 0, NULL);
1010 IMemAllocator_Release(allocator);
1011 return thread;
1014 static HRESULT join_thread_(int line, HANDLE thread)
1016 DWORD ret;
1017 ok_(__FILE__, line)(!WaitForSingleObject(thread, 1000), "Wait failed.\n");
1018 GetExitCodeThread(thread, &ret);
1019 CloseHandle(thread);
1020 return ret;
1022 #define join_thread(a) join_thread_(__LINE__, a)
1024 static void commit_allocator(IMemInputPin *input)
1026 IMemAllocator *allocator;
1027 HRESULT hr;
1029 hr = IMemInputPin_GetAllocator(input, &allocator);
1030 ok(hr == S_OK, "Got hr %#x.\n", hr);
1031 hr = IMemAllocator_Commit(allocator);
1032 ok(hr == S_OK, "Got hr %#x.\n", hr);
1033 IMemAllocator_Release(allocator);
1036 static void test_filter_state(IMemInputPin *input, IMediaControl *control)
1038 IMemAllocator *allocator;
1039 IMediaSample *sample;
1040 OAFilterState state;
1041 HANDLE thread;
1042 HRESULT hr;
1044 thread = send_frame(input);
1045 hr = join_thread(thread);
1046 ok(hr == VFW_E_WRONG_STATE, "Got hr %#x.\n", hr);
1048 /* The renderer is not fully paused until it receives a sample. The thread
1049 * sending the sample blocks in IMemInputPin_Receive() until the filter is
1050 * stopped or run. */
1052 hr = IMediaControl_Pause(control);
1053 ok(hr == S_FALSE, "Got hr %#x.\n", hr);
1055 hr = IMediaControl_GetState(control, 0, &state);
1056 ok(hr == VFW_S_STATE_INTERMEDIATE, "Got hr %#x.\n", hr);
1058 thread = send_frame(input);
1060 hr = IMediaControl_GetState(control, 1000, &state);
1061 ok(hr == S_OK, "Got hr %#x.\n", hr);
1063 ok(WaitForSingleObject(thread, 100) == WAIT_TIMEOUT, "Thread should block in Receive().\n");
1065 hr = IMediaControl_Stop(control);
1066 ok(hr == S_OK, "Got hr %#x.\n", hr);
1068 hr = join_thread(thread);
1069 ok(hr == S_OK, "Got hr %#x.\n", hr);
1071 /* The sink will decommit our allocator for us when stopping, however it
1072 * will not recommit it when pausing. */
1073 hr = IMemInputPin_GetAllocator(input, &allocator);
1074 ok(hr == S_OK, "Got hr %#x.\n", hr);
1075 hr = IMemAllocator_GetBuffer(allocator, &sample, NULL, NULL, 0);
1076 todo_wine ok(hr == VFW_E_NOT_COMMITTED, "Got hr %#x.\n", hr);
1077 if (hr == S_OK) IMediaSample_Release(sample);
1079 hr = IMemAllocator_Commit(allocator);
1080 ok(hr == S_OK, "Got hr %#x.\n", hr);
1081 thread = send_frame(input);
1082 hr = join_thread(thread);
1083 ok(hr == VFW_E_WRONG_STATE, "Got hr %#x.\n", hr);
1085 hr = IMediaControl_Pause(control);
1086 ok(hr == S_FALSE, "Got hr %#x.\n", hr);
1088 hr = IMediaControl_GetState(control, 0, &state);
1089 ok(hr == VFW_S_STATE_INTERMEDIATE, "Got hr %#x.\n", hr);
1091 thread = send_frame(input);
1093 hr = IMediaControl_GetState(control, 1000, &state);
1094 ok(hr == S_OK, "Got hr %#x.\n", hr);
1096 ok(WaitForSingleObject(thread, 100) == WAIT_TIMEOUT, "Thread should block in Receive().\n");
1098 hr = IMediaControl_Run(control);
1099 ok(hr == S_OK, "Got hr %#x.\n", hr);
1101 hr = IMediaControl_GetState(control, 0, &state);
1102 ok(hr == S_OK, "Got hr %#x.\n", hr);
1104 hr = join_thread(thread);
1105 ok(hr == S_OK, "Got hr %#x.\n", hr);
1107 thread = send_frame(input);
1108 hr = join_thread(thread);
1109 ok(hr == S_OK, "Got hr %#x.\n", hr);
1111 hr = IMediaControl_Pause(control);
1112 todo_wine ok(hr == S_FALSE, "Got hr %#x.\n", hr);
1114 hr = IMediaControl_GetState(control, 0, &state);
1115 todo_wine ok(hr == VFW_S_STATE_INTERMEDIATE, "Got hr %#x.\n", hr);
1117 thread = send_frame(input);
1119 hr = IMediaControl_GetState(control, 1000, &state);
1120 ok(hr == S_OK, "Got hr %#x.\n", hr);
1122 ok(WaitForSingleObject(thread, 100) == WAIT_TIMEOUT, "Thread should block in Receive().\n");
1124 hr = IMediaControl_Run(control);
1125 ok(hr == S_OK, "Got hr %#x.\n", hr);
1127 hr = IMediaControl_GetState(control, 0, &state);
1128 ok(hr == S_OK, "Got hr %#x.\n", hr);
1130 hr = join_thread(thread);
1131 ok(hr == S_OK, "Got hr %#x.\n", hr);
1133 hr = IMediaControl_Pause(control);
1134 todo_wine ok(hr == S_FALSE, "Got hr %#x.\n", hr);
1136 hr = IMediaControl_GetState(control, 0, &state);
1137 todo_wine ok(hr == VFW_S_STATE_INTERMEDIATE, "Got hr %#x.\n", hr);
1139 hr = IMediaControl_Stop(control);
1140 ok(hr == S_OK, "Got hr %#x.\n", hr);
1142 hr = IMediaControl_GetState(control, 0, &state);
1143 ok(hr == S_OK, "Got hr %#x.\n", hr);
1145 commit_allocator(input);
1146 hr = IMediaControl_Pause(control);
1147 ok(hr == S_FALSE, "Got hr %#x.\n", hr);
1149 hr = IMediaControl_GetState(control, 0, &state);
1150 ok(hr == VFW_S_STATE_INTERMEDIATE, "Got hr %#x.\n", hr);
1152 hr = IMediaControl_Run(control);
1153 todo_wine ok(hr == S_FALSE, "Got hr %#x.\n", hr);
1155 hr = IMediaControl_GetState(control, 0, &state);
1156 todo_wine ok(hr == VFW_S_STATE_INTERMEDIATE, "Got hr %#x.\n", hr);
1158 thread = send_frame(input);
1159 hr = join_thread(thread);
1160 ok(hr == S_OK, "Got hr %#x.\n", hr);
1162 hr = IMediaControl_GetState(control, 0, &state);
1163 ok(hr == S_OK, "Got hr %#x.\n", hr);
1165 hr = IMediaControl_Stop(control);
1166 ok(hr == S_OK, "Got hr %#x.\n", hr);
1168 hr = IMediaControl_GetState(control, 0, &state);
1169 ok(hr == S_OK, "Got hr %#x.\n", hr);
1171 IMemAllocator_Release(allocator);
1174 static void test_flushing(IPin *pin, IMemInputPin *input, IMediaControl *control)
1176 OAFilterState state;
1177 HANDLE thread;
1178 HRESULT hr;
1180 commit_allocator(input);
1181 hr = IMediaControl_Pause(control);
1182 ok(hr == S_FALSE, "Got hr %#x.\n", hr);
1184 thread = send_frame(input);
1185 ok(WaitForSingleObject(thread, 100) == WAIT_TIMEOUT, "Thread should block in Receive().\n");
1187 hr = IMediaControl_GetState(control, 1000, &state);
1188 ok(hr == S_OK, "Got hr %#x.\n", hr);
1190 hr = IPin_BeginFlush(pin);
1191 ok(hr == S_OK, "Got hr %#x.\n", hr);
1193 hr = join_thread(thread);
1194 ok(hr == S_OK, "Got hr %#x.\n", hr);
1196 thread = send_frame(input);
1197 hr = join_thread(thread);
1198 ok(hr == S_FALSE, "Got hr %#x.\n", hr);
1200 hr = IPin_EndFlush(pin);
1201 ok(hr == S_OK, "Got hr %#x.\n", hr);
1203 /* We dropped the sample we were holding, so now we need a new one... */
1205 hr = IMediaControl_GetState(control, 0, &state);
1206 todo_wine ok(hr == VFW_S_STATE_INTERMEDIATE, "Got hr %#x.\n", hr);
1207 ok(state == State_Paused, "Got state %#x.\n", state);
1209 thread = send_frame(input);
1210 ok(WaitForSingleObject(thread, 100) == WAIT_TIMEOUT, "Thread should block in Receive().\n");
1212 hr = IMediaControl_GetState(control, 1000, &state);
1213 ok(hr == S_OK, "Got hr %#x.\n", hr);
1214 ok(state == State_Paused, "Got state %#x.\n", state);
1216 hr = IMediaControl_Run(control);
1217 ok(hr == S_OK, "Got hr %#x.\n", hr);
1218 hr = join_thread(thread);
1219 ok(hr == S_OK, "Got hr %#x.\n", hr);
1221 hr = IPin_BeginFlush(pin);
1222 ok(hr == S_OK, "Got hr %#x.\n", hr);
1224 thread = send_frame(input);
1225 hr = join_thread(thread);
1226 ok(hr == S_FALSE, "Got hr %#x.\n", hr);
1228 hr = IPin_EndFlush(pin);
1229 ok(hr == S_OK, "Got hr %#x.\n", hr);
1231 thread = send_frame(input);
1232 hr = join_thread(thread);
1233 ok(hr == S_OK, "Got hr %#x.\n", hr);
1235 hr = IMediaControl_Stop(control);
1236 ok(hr == S_OK, "Got hr %#x.\n", hr);
1239 static void test_current_image(IBaseFilter *filter, IMemInputPin *input,
1240 IMediaControl *control, const BITMAPINFOHEADER *req_bih)
1242 LONG buffer[(sizeof(BITMAPINFOHEADER) + 32 * 16 * 4) / 4];
1243 const BITMAPINFOHEADER *bih = (BITMAPINFOHEADER *)buffer;
1244 const DWORD *data = (DWORD *)((char *)buffer + sizeof(BITMAPINFOHEADER));
1245 BITMAPINFOHEADER expect_bih = *req_bih;
1246 OAFilterState state;
1247 IBasicVideo *video;
1248 unsigned int i;
1249 HANDLE thread;
1250 HRESULT hr;
1251 LONG size;
1253 /* Note that the bitmap returned by GetCurrentImage() has a bit depth of
1254 * 32 regardless of the format used for pin connection. */
1255 expect_bih.biBitCount = 32;
1256 expect_bih.biSizeImage = 32 * 16 * 4;
1258 IBaseFilter_QueryInterface(filter, &IID_IBasicVideo, (void **)&video);
1260 hr = IBasicVideo_GetCurrentImage(video, NULL, NULL);
1261 ok(hr == E_POINTER, "Got hr %#x.\n", hr);
1263 hr = IBasicVideo_GetCurrentImage(video, NULL, buffer);
1264 ok(hr == E_POINTER, "Got hr %#x.\n", hr);
1266 size = 0xdeadbeef;
1267 hr = IBasicVideo_GetCurrentImage(video, &size, NULL);
1268 todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr);
1269 todo_wine ok(size == sizeof(BITMAPINFOHEADER) + 32 * 16 * 4, "Got size %d.\n", size);
1271 size = sizeof(buffer);
1272 hr = IBasicVideo_GetCurrentImage(video, &size, buffer);
1273 ok(hr == S_OK, "Got hr %#x.\n", hr);
1274 ok(size == sizeof(buffer), "Got size %d.\n", size);
1275 ok(!memcmp(bih, &expect_bih, sizeof(BITMAPINFOHEADER)), "Bitmap headers didn't match.\n");
1276 /* The contents seem to reflect the last frame rendered. */
1278 commit_allocator(input);
1279 hr = IMediaControl_Pause(control);
1280 ok(hr == S_FALSE, "Got hr %#x.\n", hr);
1282 size = sizeof(buffer);
1283 hr = IBasicVideo_GetCurrentImage(video, &size, buffer);
1284 ok(hr == S_OK, "Got hr %#x.\n", hr);
1285 ok(size == sizeof(buffer), "Got size %d.\n", size);
1286 ok(!memcmp(bih, &expect_bih, sizeof(BITMAPINFOHEADER)), "Bitmap headers didn't match.\n");
1287 /* The contents seem to reflect the last frame rendered. */
1289 thread = send_frame(input);
1290 hr = IMediaControl_GetState(control, 1000, &state);
1291 ok(hr == S_OK, "Got hr %#x.\n", hr);
1293 size = 1;
1294 memset(buffer, 0xcc, sizeof(buffer));
1295 hr = IBasicVideo_GetCurrentImage(video, &size, buffer);
1296 ok(hr == S_OK, "Got hr %#x.\n", hr);
1297 ok(size == 1, "Got size %d.\n", size);
1299 size = sizeof(buffer);
1300 memset(buffer, 0xcc, sizeof(buffer));
1301 hr = IBasicVideo_GetCurrentImage(video, &size, buffer);
1302 ok(hr == S_OK, "Got hr %#x.\n", hr);
1303 ok(size == sizeof(buffer), "Got size %d.\n", size);
1304 ok(!memcmp(bih, &expect_bih, sizeof(BITMAPINFOHEADER)), "Bitmap headers didn't match.\n");
1305 for (i = 0; i < 32 * 16; ++i)
1306 ok((data[i] & 0xffffff) == 0x555555, "Got unexpected color %08x at %u.\n", data[i], i);
1308 hr = IMediaControl_Run(control);
1309 ok(hr == S_OK, "Got hr %#x.\n", hr);
1310 join_thread(thread);
1312 size = sizeof(buffer);
1313 memset(buffer, 0xcc, sizeof(buffer));
1314 hr = IBasicVideo_GetCurrentImage(video, &size, buffer);
1315 ok(hr == S_OK, "Got hr %#x.\n", hr);
1316 ok(size == sizeof(buffer), "Got size %d.\n", size);
1317 ok(!memcmp(bih, &expect_bih, sizeof(BITMAPINFOHEADER)), "Bitmap headers didn't match.\n");
1318 for (i = 0; i < 32 * 16; ++i)
1319 ok((data[i] & 0xffffff) == 0x555555, "Got unexpected color %08x at %u.\n", data[i], i);
1321 hr = IMediaControl_Stop(control);
1322 ok(hr == S_OK, "Got hr %#x.\n", hr);
1324 IBasicVideo_Release(video);
1327 static unsigned int check_ec_userabort(IMediaEvent *eventsrc, DWORD timeout)
1329 LONG_PTR param1, param2;
1330 unsigned int ret = 0;
1331 HRESULT hr;
1332 LONG code;
1334 while ((hr = IMediaEvent_GetEvent(eventsrc, &code, &param1, &param2, timeout)) == S_OK)
1336 if (code == EC_USERABORT)
1338 ok(!param1, "Got param1 %#lx.\n", param1);
1339 ok(!param2, "Got param2 %#lx.\n", param2);
1340 ret++;
1342 IMediaEvent_FreeEventParams(eventsrc, code, param1, param2);
1343 timeout = 0;
1345 ok(hr == E_ABORT, "Got hr %#x.\n", hr);
1347 return ret;
1350 static void test_window_close(IPin *pin, IMemInputPin *input, IMediaControl *control)
1352 IMediaEvent *eventsrc;
1353 OAFilterState state;
1354 IOverlay *overlay;
1355 HANDLE thread;
1356 HRESULT hr;
1357 HWND hwnd;
1358 BOOL ret;
1360 IMediaControl_QueryInterface(control, &IID_IMediaEvent, (void **)&eventsrc);
1361 IPin_QueryInterface(pin, &IID_IOverlay, (void **)&overlay);
1363 hr = IOverlay_GetWindowHandle(overlay, &hwnd);
1364 ok(hr == S_OK, "Got hr %#x.\n", hr);
1365 IOverlay_Release(overlay);
1367 commit_allocator(input);
1368 hr = IMediaControl_Pause(control);
1369 ok(hr == S_FALSE, "Got hr %#x.\n", hr);
1370 ret = check_ec_userabort(eventsrc, 0);
1371 ok(!ret, "Got unexpected EC_USERABORT.\n");
1373 SendMessageW(hwnd, WM_CLOSE, 0, 0);
1375 hr = IMediaControl_GetState(control, 1000, &state);
1376 ok(hr == VFW_S_STATE_INTERMEDIATE, "Got hr %#x.\n", hr);
1377 ret = check_ec_userabort(eventsrc, 0);
1378 todo_wine ok(ret == 1, "Expected EC_USERABORT.\n");
1380 todo_wine ok(IsWindow(hwnd), "Window should exist.\n");
1381 ok(!IsWindowVisible(hwnd), "Window should be visible.\n");
1383 thread = send_frame(input);
1384 ret = WaitForSingleObject(thread, 1000);
1385 todo_wine ok(ret == WAIT_OBJECT_0, "Wait failed\n");
1386 if (ret == WAIT_OBJECT_0)
1388 GetExitCodeThread(thread, (DWORD *)&hr);
1389 ok(hr == E_UNEXPECTED, "Got hr %#x.\n", hr);
1391 CloseHandle(thread);
1393 hr = IMediaControl_Run(control);
1394 ok(hr == S_OK, "Got hr %#x.\n", hr);
1395 ret = check_ec_userabort(eventsrc, 0);
1396 ok(!ret, "Got unexpected EC_USERABORT.\n");
1398 hr = IMediaControl_Stop(control);
1399 ok(hr == S_OK, "Got hr %#x.\n", hr);
1400 ret = check_ec_userabort(eventsrc, 0);
1401 ok(!ret, "Got unexpected EC_USERABORT.\n");
1403 /* We receive an EC_USERABORT notification immediately. */
1405 commit_allocator(input);
1406 hr = IMediaControl_Run(control);
1407 ok(hr == S_FALSE, "Got hr %#x.\n", hr);
1408 hr = join_thread(send_frame(input));
1409 ok(hr == S_OK, "Got hr %#x.\n", hr);
1410 hr = IMediaControl_GetState(control, 1000, &state);
1411 ok(hr == S_OK, "Got hr %#x.\n", hr);
1412 ret = check_ec_userabort(eventsrc, 0);
1413 ok(!ret, "Got unexpected EC_USERABORT.\n");
1415 SendMessageW(hwnd, WM_CLOSE, 0, 0);
1417 ret = check_ec_userabort(eventsrc, 0);
1418 todo_wine ok(ret == 1, "Expected EC_USERABORT.\n");
1420 todo_wine ok(IsWindow(hwnd), "Window should exist.\n");
1421 ok(!IsWindowVisible(hwnd), "Window should be visible.\n");
1423 hr = IMediaControl_Stop(control);
1424 ok(hr == S_OK, "Got hr %#x.\n", hr);
1425 ret = check_ec_userabort(eventsrc, 0);
1426 ok(!ret, "Got unexpected EC_USERABORT.\n");
1428 IMediaEvent_Release(eventsrc);
1431 static void test_connect_pin(void)
1433 VIDEOINFOHEADER vih =
1435 .bmiHeader.biSize = sizeof(BITMAPINFOHEADER),
1436 .bmiHeader.biWidth = 32,
1437 .bmiHeader.biHeight = 16,
1438 .bmiHeader.biPlanes = 1,
1439 .bmiHeader.biCompression = BI_RGB,
1441 AM_MEDIA_TYPE req_mt =
1443 .majortype = MEDIATYPE_Video,
1444 .subtype = MEDIASUBTYPE_WAVE,
1445 .formattype = FORMAT_VideoInfo,
1446 .cbFormat = sizeof(vih),
1447 .pbFormat = (BYTE *)&vih,
1449 ALLOCATOR_PROPERTIES req_props = {1, 32 * 16 * 4, 1, 0}, ret_props;
1450 IBaseFilter *filter = create_vmr7(VMRMode_Windowed);
1451 IFilterGraph2 *graph = create_graph();
1452 struct testfilter source;
1453 IMemAllocator *allocator;
1454 IMediaControl *control;
1455 IMemInputPin *input;
1456 AM_MEDIA_TYPE mt;
1457 IPin *pin, *peer;
1458 unsigned int i;
1459 HRESULT hr;
1460 ULONG ref;
1462 static const GUID *subtype_tests[] =
1464 &MEDIASUBTYPE_RGB565,
1465 &MEDIASUBTYPE_RGB24,
1466 &MEDIASUBTYPE_RGB32,
1467 &MEDIASUBTYPE_WAVE,
1470 testfilter_init(&source);
1472 IFilterGraph2_AddFilter(graph, &source.filter.IBaseFilter_iface, NULL);
1473 IFilterGraph2_AddFilter(graph, filter, NULL);
1474 IFilterGraph2_QueryInterface(graph, &IID_IMediaControl, (void **)&control);
1476 IBaseFilter_FindPin(filter, L"VMR Input0", &pin);
1478 vih.bmiHeader.biBitCount = 16;
1479 hr = IFilterGraph2_ConnectDirect(graph, &source.source.pin.IPin_iface, pin, &req_mt);
1480 ok(hr == VFW_E_TYPE_NOT_ACCEPTED, "Got hr %#x.\n", hr);
1482 vih.bmiHeader.biBitCount = 32;
1483 hr = IFilterGraph2_ConnectDirect(graph, &source.source.pin.IPin_iface, pin, &req_mt);
1484 if (hr == VFW_E_TYPE_NOT_ACCEPTED) /* w7u */
1486 vih.bmiHeader.biBitCount = 24;
1487 hr = IFilterGraph2_ConnectDirect(graph, &source.source.pin.IPin_iface, pin, &req_mt);
1488 /* w7u is also rather buggy with its allocator. Requesting a size of
1489 * 32 * 16 * 4 succeeds and returns that size from SetProperties(), but
1490 * the actual samples only have a size of 32 * 16 * 3. */
1491 req_props.cbBuffer = 32 * 16 * 3;
1493 ok(hr == S_OK, "Got hr %#x.\n", hr);
1494 hr = IFilterGraph2_Disconnect(graph, &source.source.pin.IPin_iface);
1495 ok(hr == S_OK, "Got hr %#x.\n", hr);
1496 hr = IFilterGraph2_Disconnect(graph, pin);
1497 ok(hr == S_OK, "Got hr %#x.\n", hr);
1499 for (i = 0; i < ARRAY_SIZE(subtype_tests); ++i)
1501 req_mt.subtype = *subtype_tests[i];
1502 hr = IFilterGraph2_ConnectDirect(graph, &source.source.pin.IPin_iface, pin, &req_mt);
1503 ok(hr == S_OK, "Got hr %#x for subtype %s.\n", hr, wine_dbgstr_guid(subtype_tests[i]));
1505 hr = IFilterGraph2_Disconnect(graph, &source.source.pin.IPin_iface);
1506 ok(hr == S_OK, "Got hr %#x.\n", hr);
1507 hr = IFilterGraph2_Disconnect(graph, pin);
1508 ok(hr == S_OK, "Got hr %#x.\n", hr);
1511 req_mt.formattype = FORMAT_None;
1512 hr = IFilterGraph2_ConnectDirect(graph, &source.source.pin.IPin_iface, pin, &req_mt);
1513 ok(hr == VFW_E_TYPE_NOT_ACCEPTED, "Got hr %#x.\n", hr);
1514 req_mt.formattype = FORMAT_VideoInfo;
1516 req_mt.subtype = MEDIASUBTYPE_RGB8;
1517 hr = IFilterGraph2_ConnectDirect(graph, &source.source.pin.IPin_iface, pin, &req_mt);
1518 todo_wine ok(hr == VFW_E_TYPE_NOT_ACCEPTED, "Got hr %#x.\n", hr);
1519 if (hr == S_OK)
1521 IFilterGraph2_Disconnect(graph, &source.source.pin.IPin_iface);
1522 IFilterGraph2_Disconnect(graph, pin);
1524 req_mt.subtype = MEDIASUBTYPE_RGB32;
1526 peer = (IPin *)0xdeadbeef;
1527 hr = IPin_ConnectedTo(pin, &peer);
1528 ok(hr == VFW_E_NOT_CONNECTED, "Got hr %#x.\n", hr);
1529 ok(!peer, "Got peer %p.\n", peer);
1531 hr = IPin_ConnectionMediaType(pin, &mt);
1532 ok(hr == VFW_E_NOT_CONNECTED, "Got hr %#x.\n", hr);
1534 hr = IMediaControl_Pause(control);
1535 ok(hr == S_OK, "Got hr %#x.\n", hr);
1536 hr = IFilterGraph2_ConnectDirect(graph, &source.source.pin.IPin_iface, pin, &req_mt);
1537 ok(hr == VFW_E_NOT_STOPPED, "Got hr %#x.\n", hr);
1538 hr = IMediaControl_Stop(control);
1539 ok(hr == S_OK, "Got hr %#x.\n", hr);
1541 hr = IFilterGraph2_ConnectDirect(graph, &source.source.pin.IPin_iface, pin, &req_mt);
1542 ok(hr == S_OK, "Got hr %#x.\n", hr);
1544 hr = IPin_ConnectedTo(pin, &peer);
1545 ok(hr == S_OK, "Got hr %#x.\n", hr);
1546 ok(peer == &source.source.pin.IPin_iface, "Got peer %p.\n", peer);
1547 IPin_Release(peer);
1549 hr = IPin_ConnectionMediaType(pin, &mt);
1550 ok(hr == S_OK, "Got hr %#x.\n", hr);
1551 ok(compare_media_types(&mt, &req_mt), "Media types didn't match.\n");
1553 /* Disconnecting while not stopped is broken: it returns S_OK, but
1554 * subsequent attempts to connect return VFW_E_ALREADY_CONNECTED. */
1556 IPin_QueryInterface(pin, &IID_IMemInputPin, (void **)&input);
1558 test_allocator(input);
1560 hr = IMemInputPin_GetAllocator(input, &allocator);
1561 ok(hr == S_OK, "Got hr %#x.\n", hr);
1562 hr = IMemAllocator_SetProperties(allocator, &req_props, &ret_props);
1563 ok(hr == S_OK, "Got hr %#x.\n", hr);
1564 ok(!memcmp(&ret_props, &req_props, sizeof(req_props)), "Properties did not match.\n");
1565 hr = IMemAllocator_Commit(allocator);
1566 ok(hr == S_OK, "Got hr %#x.\n", hr);
1567 IMemAllocator_Release(allocator);
1569 hr = IMemInputPin_ReceiveCanBlock(input);
1570 ok(hr == S_OK, "Got hr %#x.\n", hr);
1572 test_filter_state(input, control);
1573 test_flushing(pin, input, control);
1574 test_current_image(filter, input, control, &vih.bmiHeader);
1575 test_window_close(pin, input, control);
1577 hr = IFilterGraph2_Disconnect(graph, pin);
1578 ok(hr == S_OK, "Got hr %#x.\n", hr);
1579 hr = IFilterGraph2_Disconnect(graph, pin);
1580 ok(hr == S_FALSE, "Got hr %#x.\n", hr);
1581 ok(source.source.pin.peer == pin, "Got peer %p.\n", peer);
1582 IFilterGraph2_Disconnect(graph, &source.source.pin.IPin_iface);
1584 peer = (IPin *)0xdeadbeef;
1585 hr = IPin_ConnectedTo(pin, &peer);
1586 ok(hr == VFW_E_NOT_CONNECTED, "Got hr %#x.\n", hr);
1587 ok(!peer, "Got peer %p.\n", peer);
1589 hr = IPin_ConnectionMediaType(pin, &mt);
1590 ok(hr == VFW_E_NOT_CONNECTED, "Got hr %#x.\n", hr);
1592 IMemInputPin_Release(input);
1593 IPin_Release(pin);
1594 IMediaControl_Release(control);
1595 ref = IFilterGraph2_Release(graph);
1596 ok(!ref, "Got outstanding refcount %d.\n", ref);
1597 ref = IBaseFilter_Release(filter);
1598 ok(!ref, "Got outstanding refcount %d.\n", ref);
1599 ref = IBaseFilter_Release(&source.filter.IBaseFilter_iface);
1600 ok(!ref, "Got outstanding refcount %d.\n", ref);
1603 static void test_overlay(void)
1605 IBaseFilter *filter = create_vmr7(0);
1606 IOverlay *overlay;
1607 HRESULT hr;
1608 ULONG ref;
1609 IPin *pin;
1610 HWND hwnd;
1612 IBaseFilter_FindPin(filter, L"VMR Input0", &pin);
1614 hr = IPin_QueryInterface(pin, &IID_IOverlay, (void **)&overlay);
1615 ok(hr == S_OK, "Got hr %#x.\n", hr);
1617 hwnd = (HWND)0xdeadbeef;
1618 hr = IOverlay_GetWindowHandle(overlay, &hwnd);
1619 ok(hr == S_OK, "Got hr %#x.\n", hr);
1620 ok(hwnd && hwnd != (HWND)0xdeadbeef, "Got invalid window %p.\n", hwnd);
1622 IOverlay_Release(overlay);
1623 IPin_Release(pin);
1624 ref = IBaseFilter_Release(filter);
1625 ok(!ref, "Got outstanding refcount %d.\n", ref);
1628 /* try to make sure pending X events have been processed before continuing */
1629 static void flush_events(void)
1631 int diff = 200;
1632 DWORD time;
1633 MSG msg;
1635 time = GetTickCount() + diff;
1636 while (diff > 0)
1638 if (MsgWaitForMultipleObjects(0, NULL, FALSE, 100, QS_ALLINPUT) == WAIT_TIMEOUT)
1639 break;
1640 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE))
1641 DispatchMessageA(&msg);
1642 diff = time - GetTickCount();
1646 static LRESULT CALLBACK window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
1648 if (winetest_debug > 1)
1649 trace("hwnd %p, msg %#x, wparam %#lx, lparam %#lx.\n", hwnd, msg, wparam, lparam);
1651 if (wparam == 0xdeadbeef)
1652 return 0;
1654 return DefWindowProcA(hwnd, msg, wparam, lparam);
1657 static void test_video_window_caption(IVideoWindow *window, HWND hwnd)
1659 WCHAR text[50];
1660 BSTR caption;
1661 HRESULT hr;
1663 hr = IVideoWindow_get_Caption(window, &caption);
1664 ok(hr == S_OK, "Got hr %#x.\n", hr);
1665 ok(!wcscmp(caption, L"ActiveMovie Window"), "Got caption %s.\n", wine_dbgstr_w(caption));
1666 SysFreeString(caption);
1668 GetWindowTextW(hwnd, text, ARRAY_SIZE(text));
1669 ok(!wcscmp(text, L"ActiveMovie Window"), "Got caption %s.\n", wine_dbgstr_w(text));
1671 caption = SysAllocString(L"foo");
1672 hr = IVideoWindow_put_Caption(window, caption);
1673 ok(hr == S_OK, "Got hr %#x.\n", hr);
1674 SysFreeString(caption);
1676 hr = IVideoWindow_get_Caption(window, &caption);
1677 ok(hr == S_OK, "Got hr %#x.\n", hr);
1678 ok(!wcscmp(caption, L"foo"), "Got caption %s.\n", wine_dbgstr_w(caption));
1679 SysFreeString(caption);
1681 GetWindowTextW(hwnd, text, ARRAY_SIZE(text));
1682 ok(!wcscmp(text, L"foo"), "Got caption %s.\n", wine_dbgstr_w(text));
1685 static void test_video_window_style(IVideoWindow *window, HWND hwnd, HWND our_hwnd)
1687 HRESULT hr;
1688 LONG style;
1690 hr = IVideoWindow_get_WindowStyle(window, &style);
1691 ok(hr == S_OK, "Got hr %#x.\n", hr);
1692 ok(style == (WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_OVERLAPPEDWINDOW),
1693 "Got style %#x.\n", style);
1695 style = GetWindowLongA(hwnd, GWL_STYLE);
1696 ok(style == (WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_OVERLAPPEDWINDOW),
1697 "Got style %#x.\n", style);
1699 hr = IVideoWindow_put_WindowStyle(window, style | WS_DISABLED);
1700 ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr);
1701 hr = IVideoWindow_put_WindowStyle(window, style | WS_HSCROLL);
1702 ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr);
1703 hr = IVideoWindow_put_WindowStyle(window, style | WS_VSCROLL);
1704 ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr);
1705 hr = IVideoWindow_put_WindowStyle(window, style | WS_MAXIMIZE);
1706 ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr);
1707 hr = IVideoWindow_put_WindowStyle(window, style | WS_MINIMIZE);
1708 ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr);
1710 hr = IVideoWindow_put_WindowStyle(window, style & ~WS_CLIPCHILDREN);
1711 ok(hr == S_OK, "Got hr %#x.\n", hr);
1713 hr = IVideoWindow_get_WindowStyle(window, &style);
1714 ok(hr == S_OK, "Got hr %#x.\n", hr);
1715 ok(style == (WS_CLIPSIBLINGS | WS_OVERLAPPEDWINDOW), "Got style %#x.\n", style);
1717 style = GetWindowLongA(hwnd, GWL_STYLE);
1718 ok(style == (WS_CLIPSIBLINGS | WS_OVERLAPPEDWINDOW), "Got style %#x.\n", style);
1720 ok(GetActiveWindow() == our_hwnd, "Got active window %p.\n", GetActiveWindow());
1722 hr = IVideoWindow_get_WindowStyleEx(window, &style);
1723 ok(hr == S_OK, "Got hr %#x.\n", hr);
1724 ok(style == WS_EX_WINDOWEDGE, "Got style %#x.\n", style);
1726 style = GetWindowLongA(hwnd, GWL_EXSTYLE);
1727 ok(style == WS_EX_WINDOWEDGE, "Got style %#x.\n", style);
1729 hr = IVideoWindow_put_WindowStyleEx(window, style | WS_EX_TRANSPARENT);
1730 ok(hr == S_OK, "Got hr %#x.\n", hr);
1732 hr = IVideoWindow_get_WindowStyleEx(window, &style);
1733 ok(hr == S_OK, "Got hr %#x.\n", hr);
1734 ok(style == (WS_EX_WINDOWEDGE | WS_EX_TRANSPARENT), "Got style %#x.\n", style);
1736 style = GetWindowLongA(hwnd, GWL_EXSTYLE);
1737 ok(style == (WS_EX_WINDOWEDGE | WS_EX_TRANSPARENT), "Got style %#x.\n", style);
1740 static BOOL CALLBACK top_window_cb(HWND hwnd, LPARAM ctx)
1742 DWORD pid;
1743 GetWindowThreadProcessId(hwnd, &pid);
1744 if (pid == GetCurrentProcessId() && (GetWindowLongW(hwnd, GWL_STYLE) & WS_VISIBLE))
1746 *(HWND *)ctx = hwnd;
1747 return FALSE;
1749 return TRUE;
1752 static HWND get_top_window(void)
1754 HWND hwnd;
1755 EnumWindows(top_window_cb, (LPARAM)&hwnd);
1756 return hwnd;
1759 static void test_video_window_state(IVideoWindow *window, HWND hwnd, HWND our_hwnd)
1761 HRESULT hr;
1762 LONG state;
1763 HWND top;
1765 SetWindowPos(our_hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
1767 hr = IVideoWindow_get_WindowState(window, &state);
1768 ok(hr == S_OK, "Got hr %#x.\n", hr);
1769 ok(state == SW_HIDE, "Got state %d.\n", state);
1771 hr = IVideoWindow_get_Visible(window, &state);
1772 ok(state == OAFALSE, "Got state %d.\n", state);
1774 ok(!IsWindowVisible(hwnd), "Window should not be visible.\n");
1775 ok(!IsIconic(hwnd), "Window should not be minimized.\n");
1776 ok(!IsZoomed(hwnd), "Window should not be maximized.\n");
1778 hr = IVideoWindow_put_WindowState(window, SW_SHOWNA);
1779 ok(hr == S_OK, "Got hr %#x.\n", hr);
1781 hr = IVideoWindow_get_WindowState(window, &state);
1782 ok(hr == S_OK, "Got hr %#x.\n", hr);
1783 ok(state == SW_SHOW, "Got state %d.\n", state);
1785 hr = IVideoWindow_get_Visible(window, &state);
1786 ok(state == OATRUE, "Got state %d.\n", state);
1788 ok(IsWindowVisible(hwnd), "Window should be visible.\n");
1789 ok(!IsIconic(hwnd), "Window should not be minimized.\n");
1790 ok(!IsZoomed(hwnd), "Window should not be maximized.\n");
1791 ok(GetActiveWindow() == our_hwnd, "Got active window %p.\n", GetActiveWindow());
1792 top = get_top_window();
1793 ok(top == hwnd, "Got top window %p.\n", top);
1795 hr = IVideoWindow_put_WindowState(window, SW_MINIMIZE);
1796 ok(hr == S_OK, "Got hr %#x.\n", hr);
1798 hr = IVideoWindow_get_WindowState(window, &state);
1799 ok(hr == S_OK, "Got hr %#x.\n", hr);
1800 ok(state == SW_MINIMIZE, "Got state %d.\n", state);
1802 hr = IVideoWindow_get_Visible(window, &state);
1803 ok(state == OATRUE, "Got state %d.\n", state);
1805 ok(IsWindowVisible(hwnd), "Window should be visible.\n");
1806 ok(IsIconic(hwnd), "Window should be minimized.\n");
1807 ok(!IsZoomed(hwnd), "Window should not be maximized.\n");
1808 ok(GetActiveWindow() == our_hwnd, "Got active window %p.\n", GetActiveWindow());
1810 hr = IVideoWindow_put_WindowState(window, SW_RESTORE);
1811 ok(hr == S_OK, "Got hr %#x.\n", hr);
1813 hr = IVideoWindow_get_WindowState(window, &state);
1814 ok(hr == S_OK, "Got hr %#x.\n", hr);
1815 ok(state == SW_SHOW, "Got state %d.\n", state);
1817 hr = IVideoWindow_get_Visible(window, &state);
1818 ok(state == OATRUE, "Got state %d.\n", state);
1820 ok(IsWindowVisible(hwnd), "Window should be visible.\n");
1821 ok(!IsIconic(hwnd), "Window should not be minimized.\n");
1822 ok(!IsZoomed(hwnd), "Window should not be maximized.\n");
1823 ok(GetActiveWindow() == hwnd, "Got active window %p.\n", GetActiveWindow());
1825 hr = IVideoWindow_put_WindowState(window, SW_MAXIMIZE);
1826 ok(hr == S_OK, "Got hr %#x.\n", hr);
1828 hr = IVideoWindow_get_WindowState(window, &state);
1829 ok(hr == S_OK, "Got hr %#x.\n", hr);
1830 ok(state == SW_MAXIMIZE, "Got state %d.\n", state);
1832 hr = IVideoWindow_get_Visible(window, &state);
1833 ok(state == OATRUE, "Got state %d.\n", state);
1835 ok(IsWindowVisible(hwnd), "Window should be visible.\n");
1836 ok(!IsIconic(hwnd), "Window should be minimized.\n");
1837 ok(IsZoomed(hwnd), "Window should not be maximized.\n");
1838 ok(GetActiveWindow() == hwnd, "Got active window %p.\n", GetActiveWindow());
1840 hr = IVideoWindow_put_WindowState(window, SW_RESTORE);
1841 ok(hr == S_OK, "Got hr %#x.\n", hr);
1843 hr = IVideoWindow_put_WindowState(window, SW_HIDE);
1844 ok(hr == S_OK, "Got hr %#x.\n", hr);
1846 hr = IVideoWindow_get_WindowState(window, &state);
1847 ok(hr == S_OK, "Got hr %#x.\n", hr);
1848 ok(state == SW_HIDE, "Got state %d.\n", state);
1850 hr = IVideoWindow_get_Visible(window, &state);
1851 ok(state == OAFALSE, "Got state %d.\n", state);
1853 ok(!IsWindowVisible(hwnd), "Window should not be visible.\n");
1854 ok(!IsIconic(hwnd), "Window should not be minimized.\n");
1855 ok(!IsZoomed(hwnd), "Window should not be maximized.\n");
1856 ok(GetActiveWindow() == our_hwnd, "Got active window %p.\n", GetActiveWindow());
1858 hr = IVideoWindow_put_Visible(window, OATRUE);
1859 ok(hr == S_OK, "Got hr %#x.\n", hr);
1861 hr = IVideoWindow_get_WindowState(window, &state);
1862 ok(hr == S_OK, "Got hr %#x.\n", hr);
1863 ok(state == SW_SHOW, "Got state %d.\n", state);
1865 hr = IVideoWindow_get_Visible(window, &state);
1866 ok(state == OATRUE, "Got state %d.\n", state);
1868 ok(IsWindowVisible(hwnd), "Window should be visible.\n");
1869 ok(!IsIconic(hwnd), "Window should not be minimized.\n");
1870 ok(!IsZoomed(hwnd), "Window should not be maximized.\n");
1871 ok(GetActiveWindow() == hwnd, "Got active window %p.\n", GetActiveWindow());
1873 hr = IVideoWindow_put_Visible(window, OAFALSE);
1874 ok(hr == S_OK, "Got hr %#x.\n", hr);
1876 hr = IVideoWindow_get_WindowState(window, &state);
1877 ok(hr == S_OK, "Got hr %#x.\n", hr);
1878 ok(state == SW_HIDE, "Got state %d.\n", state);
1880 hr = IVideoWindow_get_Visible(window, &state);
1881 ok(state == OAFALSE, "Got state %d.\n", state);
1883 ok(!IsWindowVisible(hwnd), "Window should not be visible.\n");
1884 ok(!IsIconic(hwnd), "Window should not be minimized.\n");
1885 ok(!IsZoomed(hwnd), "Window should not be maximized.\n");
1886 ok(GetActiveWindow() == our_hwnd, "Got active window %p.\n", GetActiveWindow());
1888 hr = IVideoWindow_put_WindowState(window, SW_SHOWNA);
1889 ok(hr == S_OK, "Got hr %#x.\n", hr);
1891 hr = IVideoWindow_SetWindowForeground(window, TRUE);
1892 ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr);
1894 SetWindowPos(our_hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
1895 hr = IVideoWindow_SetWindowForeground(window, OATRUE);
1896 ok(hr == S_OK, "Got hr %#x.\n", hr);
1897 ok(GetActiveWindow() == hwnd, "Got active window %p.\n", GetActiveWindow());
1898 ok(GetFocus() == hwnd, "Got focus window %p.\n", GetFocus());
1899 ok(GetForegroundWindow() == hwnd, "Got foreground window %p.\n", GetForegroundWindow());
1900 top = get_top_window();
1901 ok(top == hwnd, "Got top window %p.\n", top);
1903 hr = IVideoWindow_SetWindowForeground(window, OAFALSE);
1904 ok(hr == S_OK, "Got hr %#x.\n", hr);
1905 ok(GetActiveWindow() == hwnd, "Got active window %p.\n", GetActiveWindow());
1906 ok(GetFocus() == hwnd, "Got focus window %p.\n", GetFocus());
1907 ok(GetForegroundWindow() == hwnd, "Got foreground window %p.\n", GetForegroundWindow());
1908 top = get_top_window();
1909 ok(top == hwnd, "Got top window %p.\n", top);
1911 SetWindowPos(our_hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
1912 hr = IVideoWindow_SetWindowForeground(window, OAFALSE);
1913 ok(hr == S_OK, "Got hr %#x.\n", hr);
1914 ok(GetActiveWindow() == our_hwnd, "Got active window %p.\n", GetActiveWindow());
1915 ok(GetFocus() == our_hwnd, "Got focus window %p.\n", GetFocus());
1916 ok(GetForegroundWindow() == our_hwnd, "Got foreground window %p.\n", GetForegroundWindow());
1917 top = get_top_window();
1918 ok(top == hwnd, "Got top window %p.\n", top);
1921 static void test_video_window_position(IVideoWindow *window, HWND hwnd, HWND our_hwnd)
1923 LONG left, width, top, height, expect_width, expect_height;
1924 RECT rect = {0, 0, 600, 400};
1925 HWND top_hwnd;
1926 HRESULT hr;
1928 SetWindowPos(our_hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
1930 AdjustWindowRect(&rect, GetWindowLongA(hwnd, GWL_STYLE), FALSE);
1931 expect_width = rect.right - rect.left;
1932 expect_height = rect.bottom - rect.top;
1934 hr = IVideoWindow_put_Left(window, 0);
1935 ok(hr == S_OK, "Got hr %#x.\n", hr);
1936 hr = IVideoWindow_put_Top(window, 0);
1937 ok(hr == S_OK, "Got hr %#x.\n", hr);
1939 hr = IVideoWindow_get_Left(window, &left);
1940 ok(hr == S_OK, "Got hr %#x.\n", hr);
1941 ok(left == 0, "Got left %d.\n", left);
1942 hr = IVideoWindow_get_Top(window, &top);
1943 ok(hr == S_OK, "Got hr %#x.\n", hr);
1944 ok(top == 0, "Got top %d.\n", top);
1945 hr = IVideoWindow_get_Width(window, &width);
1946 ok(hr == S_OK, "Got hr %#x.\n", hr);
1947 ok(width == expect_width, "Got width %d.\n", width);
1948 hr = IVideoWindow_get_Height(window, &height);
1949 ok(hr == S_OK, "Got hr %#x.\n", hr);
1950 ok(height == expect_height, "Got height %d.\n", height);
1951 hr = IVideoWindow_GetWindowPosition(window, &left, &top, &width, &height);
1952 ok(hr == S_OK, "Got hr %#x.\n", hr);
1953 ok(left == 0, "Got left %d.\n", left);
1954 ok(top == 0, "Got top %d.\n", top);
1955 ok(width == expect_width, "Got width %d.\n", width);
1956 ok(height == expect_height, "Got height %d.\n", height);
1957 GetWindowRect(hwnd, &rect);
1958 ok(rect.left == 0, "Got window left %d.\n", rect.left);
1959 ok(rect.top == 0, "Got window top %d.\n", rect.top);
1960 ok(rect.right == expect_width, "Got window right %d.\n", rect.right);
1961 ok(rect.bottom == expect_height, "Got window bottom %d.\n", rect.bottom);
1963 hr = IVideoWindow_put_Left(window, 10);
1964 ok(hr == S_OK, "Got hr %#x.\n", hr);
1966 hr = IVideoWindow_get_Left(window, &left);
1967 ok(hr == S_OK, "Got hr %#x.\n", hr);
1968 ok(left == 10, "Got left %d.\n", left);
1969 hr = IVideoWindow_get_Top(window, &top);
1970 ok(hr == S_OK, "Got hr %#x.\n", hr);
1971 ok(top == 0, "Got top %d.\n", top);
1972 hr = IVideoWindow_get_Width(window, &width);
1973 ok(hr == S_OK, "Got hr %#x.\n", hr);
1974 ok(width == expect_width, "Got width %d.\n", width);
1975 hr = IVideoWindow_get_Height(window, &height);
1976 ok(hr == S_OK, "Got hr %#x.\n", hr);
1977 ok(height == expect_height, "Got height %d.\n", height);
1978 hr = IVideoWindow_GetWindowPosition(window, &left, &top, &width, &height);
1979 ok(hr == S_OK, "Got hr %#x.\n", hr);
1980 ok(left == 10, "Got left %d.\n", left);
1981 ok(top == 0, "Got top %d.\n", top);
1982 ok(width == expect_width, "Got width %d.\n", width);
1983 ok(height == expect_height, "Got height %d.\n", height);
1984 GetWindowRect(hwnd, &rect);
1985 ok(rect.left == 10, "Got window left %d.\n", rect.left);
1986 ok(rect.top == 0, "Got window top %d.\n", rect.top);
1987 ok(rect.right == 10 + expect_width, "Got window right %d.\n", rect.right);
1988 ok(rect.bottom == expect_height, "Got window bottom %d.\n", rect.bottom);
1990 hr = IVideoWindow_put_Height(window, 200);
1991 ok(hr == S_OK, "Got hr %#x.\n", hr);
1993 hr = IVideoWindow_get_Left(window, &left);
1994 ok(hr == S_OK, "Got hr %#x.\n", hr);
1995 ok(left == 10, "Got left %d.\n", left);
1996 hr = IVideoWindow_get_Top(window, &top);
1997 ok(hr == S_OK, "Got hr %#x.\n", hr);
1998 ok(top == 0, "Got top %d.\n", top);
1999 hr = IVideoWindow_get_Width(window, &width);
2000 ok(hr == S_OK, "Got hr %#x.\n", hr);
2001 ok(width == expect_width, "Got width %d.\n", width);
2002 hr = IVideoWindow_get_Height(window, &height);
2003 ok(hr == S_OK, "Got hr %#x.\n", hr);
2004 ok(height == 200, "Got height %d.\n", height);
2005 hr = IVideoWindow_GetWindowPosition(window, &left, &top, &width, &height);
2006 ok(hr == S_OK, "Got hr %#x.\n", hr);
2007 ok(left == 10, "Got left %d.\n", left);
2008 ok(top == 0, "Got top %d.\n", top);
2009 ok(width == expect_width, "Got width %d.\n", width);
2010 ok(height == 200, "Got height %d.\n", height);
2011 GetWindowRect(hwnd, &rect);
2012 ok(rect.left == 10, "Got window left %d.\n", rect.left);
2013 ok(rect.top == 0, "Got window top %d.\n", rect.top);
2014 ok(rect.right == 10 + expect_width, "Got window right %d.\n", rect.right);
2015 ok(rect.bottom == 200, "Got window bottom %d.\n", rect.bottom);
2017 hr = IVideoWindow_SetWindowPosition(window, 100, 200, 300, 400);
2018 ok(hr == S_OK, "Got hr %#x.\n", hr);
2020 hr = IVideoWindow_get_Left(window, &left);
2021 ok(hr == S_OK, "Got hr %#x.\n", hr);
2022 ok(left == 100, "Got left %d.\n", left);
2023 hr = IVideoWindow_get_Top(window, &top);
2024 ok(hr == S_OK, "Got hr %#x.\n", hr);
2025 ok(top == 200, "Got top %d.\n", top);
2026 hr = IVideoWindow_get_Width(window, &width);
2027 ok(hr == S_OK, "Got hr %#x.\n", hr);
2028 ok(width == 300, "Got width %d.\n", width);
2029 hr = IVideoWindow_get_Height(window, &height);
2030 ok(hr == S_OK, "Got hr %#x.\n", hr);
2031 ok(height == 400, "Got height %d.\n", height);
2032 hr = IVideoWindow_GetWindowPosition(window, &left, &top, &width, &height);
2033 ok(hr == S_OK, "Got hr %#x.\n", hr);
2034 ok(left == 100, "Got left %d.\n", left);
2035 ok(top == 200, "Got top %d.\n", top);
2036 ok(width == 300, "Got width %d.\n", width);
2037 ok(height == 400, "Got height %d.\n", height);
2038 GetWindowRect(hwnd, &rect);
2039 ok(rect.left == 100, "Got window left %d.\n", rect.left);
2040 ok(rect.top == 200, "Got window top %d.\n", rect.top);
2041 ok(rect.right == 400, "Got window right %d.\n", rect.right);
2042 ok(rect.bottom == 600, "Got window bottom %d.\n", rect.bottom);
2044 ok(GetActiveWindow() == our_hwnd, "Got active window %p.\n", GetActiveWindow());
2045 top_hwnd = get_top_window();
2046 ok(top_hwnd == our_hwnd, "Got top window %p.\n", top_hwnd);
2049 static void test_video_window_owner(IVideoWindow *window, HWND hwnd, HWND our_hwnd)
2051 HWND parent, top_hwnd;
2052 LONG style, state;
2053 OAHWND oahwnd;
2054 HRESULT hr;
2056 SetWindowPos(our_hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
2058 hr = IVideoWindow_get_Owner(window, &oahwnd);
2059 ok(hr == S_OK, "Got hr %#x.\n", hr);
2060 ok(!oahwnd, "Got owner %#lx.\n", oahwnd);
2062 parent = GetAncestor(hwnd, GA_PARENT);
2063 ok(parent == GetDesktopWindow(), "Got parent %p.\n", parent);
2064 style = GetWindowLongA(hwnd, GWL_STYLE);
2065 ok(!(style & WS_CHILD), "Got style %#x.\n", style);
2067 hr = IVideoWindow_put_Owner(window, (OAHWND)our_hwnd);
2068 ok(hr == S_OK, "Got hr %#x.\n", hr);
2070 hr = IVideoWindow_get_Owner(window, &oahwnd);
2071 ok(hr == S_OK, "Got hr %#x.\n", hr);
2072 ok(oahwnd == (OAHWND)our_hwnd, "Got owner %#lx.\n", oahwnd);
2074 parent = GetAncestor(hwnd, GA_PARENT);
2075 ok(parent == our_hwnd, "Got parent %p.\n", parent);
2076 style = GetWindowLongA(hwnd, GWL_STYLE);
2077 ok((style & WS_CHILD), "Got style %#x.\n", style);
2079 ok(GetActiveWindow() == our_hwnd, "Got active window %p.\n", GetActiveWindow());
2080 top_hwnd = get_top_window();
2081 ok(top_hwnd == our_hwnd, "Got top window %p.\n", top_hwnd);
2083 ShowWindow(our_hwnd, SW_HIDE);
2085 hr = IVideoWindow_put_Visible(window, OATRUE);
2086 ok(hr == S_OK, "Got hr %#x.\n", hr);
2088 hr = IVideoWindow_get_Visible(window, &state);
2089 ok(hr == S_OK, "Got hr %#x.\n", hr);
2090 ok(state == OAFALSE, "Got state %d.\n", state);
2092 hr = IVideoWindow_put_Owner(window, 0);
2093 ok(hr == S_OK, "Got hr %#x.\n", hr);
2095 hr = IVideoWindow_get_Owner(window, &oahwnd);
2096 ok(hr == S_OK, "Got hr %#x.\n", hr);
2097 ok(!oahwnd, "Got owner %#lx.\n", oahwnd);
2099 parent = GetAncestor(hwnd, GA_PARENT);
2100 ok(parent == GetDesktopWindow(), "Got parent %p.\n", parent);
2101 style = GetWindowLongA(hwnd, GWL_STYLE);
2102 ok(!(style & WS_CHILD), "Got style %#x.\n", style);
2104 ok(GetActiveWindow() == hwnd, "Got active window %p.\n", GetActiveWindow());
2105 top_hwnd = get_top_window();
2106 ok(top_hwnd == hwnd, "Got top window %p.\n", top_hwnd);
2108 hr = IVideoWindow_get_Visible(window, &state);
2109 ok(hr == S_OK, "Got hr %#x.\n", hr);
2110 ok(state == OATRUE, "Got state %d.\n", state);
2113 struct notify_message_params
2115 IVideoWindow *window;
2116 HWND hwnd;
2117 UINT message;
2120 static DWORD CALLBACK notify_message_proc(void *arg)
2122 const struct notify_message_params *params = arg;
2123 HRESULT hr = IVideoWindow_NotifyOwnerMessage(params->window, (OAHWND)params->hwnd, params->message, 0, 0);
2124 ok(hr == S_OK, "Got hr %#x.\n", hr);
2125 return 0;
2128 static void test_video_window_messages(IVideoWindow *window, HWND hwnd, HWND our_hwnd)
2130 struct notify_message_params params;
2131 unsigned int i;
2132 OAHWND oahwnd;
2133 HANDLE thread;
2134 HRESULT hr;
2135 BOOL ret;
2136 MSG msg;
2138 static UINT drain_tests[] =
2140 WM_MOUSEACTIVATE,
2141 WM_NCLBUTTONDOWN,
2142 WM_NCLBUTTONUP,
2143 WM_NCLBUTTONDBLCLK,
2144 WM_NCRBUTTONDOWN,
2145 WM_NCRBUTTONUP,
2146 WM_NCRBUTTONDBLCLK,
2147 WM_NCMBUTTONDOWN,
2148 WM_NCMBUTTONUP,
2149 WM_NCMBUTTONDBLCLK,
2150 WM_KEYDOWN,
2151 WM_KEYUP,
2152 WM_MOUSEMOVE,
2153 WM_LBUTTONDOWN,
2154 WM_LBUTTONUP,
2155 WM_LBUTTONDBLCLK,
2156 WM_RBUTTONDOWN,
2157 WM_RBUTTONUP,
2158 WM_RBUTTONDBLCLK,
2159 WM_MBUTTONDOWN,
2160 WM_MBUTTONUP,
2161 WM_MBUTTONDBLCLK,
2164 flush_events();
2166 hr = IVideoWindow_get_MessageDrain(window, &oahwnd);
2167 ok(hr == S_OK, "Got hr %#x.\n", hr);
2168 ok(!oahwnd, "Got window %#lx.\n", oahwnd);
2170 hr = IVideoWindow_put_MessageDrain(window, (OAHWND)our_hwnd);
2171 ok(hr == S_OK, "Got hr %#x.\n", hr);
2173 hr = IVideoWindow_get_MessageDrain(window, &oahwnd);
2174 ok(hr == S_OK, "Got hr %#x.\n", hr);
2175 ok(oahwnd == (OAHWND)our_hwnd, "Got window %#lx.\n", oahwnd);
2177 for (i = 0; i < ARRAY_SIZE(drain_tests); ++i)
2179 SendMessageA(hwnd, drain_tests[i], 0xdeadbeef, 0);
2180 ret = PeekMessageA(&msg, 0, drain_tests[i], drain_tests[i], PM_REMOVE);
2181 ok(ret, "Expected a message.\n");
2182 ok(msg.hwnd == our_hwnd, "Got hwnd %p.\n", msg.hwnd);
2183 ok(msg.message == drain_tests[i], "Got message %#x.\n", msg.message);
2184 ok(msg.wParam == 0xdeadbeef, "Got wparam %#lx.\n", msg.wParam);
2185 ok(!msg.lParam, "Got lparam %#lx.\n", msg.lParam);
2186 DispatchMessageA(&msg);
2188 ret = PeekMessageA(&msg, 0, drain_tests[i], drain_tests[i], PM_REMOVE);
2189 ok(!ret, "Got unexpected message %#x.\n", msg.message);
2192 hr = IVideoWindow_put_MessageDrain(window, 0);
2193 ok(hr == S_OK, "Got hr %#x.\n", hr);
2195 hr = IVideoWindow_put_Owner(window, (OAHWND)our_hwnd);
2196 ok(hr == S_OK, "Got hr %#x.\n", hr);
2198 flush_events();
2200 /* Demonstrate that messages should be sent, not posted, and that only some
2201 * messages should be forwarded. A previous implementation unconditionally
2202 * posted all messages. */
2204 hr = IVideoWindow_NotifyOwnerMessage(window, (OAHWND)our_hwnd, WM_SYSCOLORCHANGE, 0, 0);
2205 ok(hr == S_OK, "Got hr %#x.\n", hr);
2207 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE))
2209 ok(msg.message != WM_SYSCOLORCHANGE, "WM_SYSCOLORCHANGE should not be posted.\n");
2210 DispatchMessageA(&msg);
2213 hr = IVideoWindow_NotifyOwnerMessage(window, (OAHWND)our_hwnd, WM_FONTCHANGE, 0, 0);
2214 ok(hr == S_OK, "Got hr %#x.\n", hr);
2216 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE))
2218 ok(msg.message != WM_FONTCHANGE, "WM_FONTCHANGE should not be posted.\n");
2219 DispatchMessageA(&msg);
2222 params.window = window;
2223 params.hwnd = our_hwnd;
2224 params.message = WM_SYSCOLORCHANGE;
2225 thread = CreateThread(NULL, 0, notify_message_proc, &params, 0, NULL);
2226 ok(WaitForSingleObject(thread, 100) == WAIT_TIMEOUT, "Thread should block.\n");
2228 while ((ret = MsgWaitForMultipleObjects(1, &thread, FALSE, 1000, QS_ALLINPUT)) == 1)
2230 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE))
2232 ok(msg.message != WM_SYSCOLORCHANGE, "WM_SYSCOLORCHANGE should not be posted.\n");
2233 DispatchMessageA(&msg);
2236 ok(!ret, "Wait timed out.\n");
2237 CloseHandle(thread);
2239 params.message = WM_FONTCHANGE;
2240 thread = CreateThread(NULL, 0, notify_message_proc, &params, 0, NULL);
2241 ok(!WaitForSingleObject(thread, 1000), "Thread should not block.\n");
2242 CloseHandle(thread);
2244 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE))
2246 ok(msg.message != WM_FONTCHANGE, "WM_FONTCHANGE should not be posted.\n");
2247 DispatchMessageA(&msg);
2250 hr = IVideoWindow_put_Owner(window, 0);
2251 ok(hr == S_OK, "Got hr %#x.\n", hr);
2254 static void test_video_window_autoshow(IVideoWindow *window, IFilterGraph2 *graph, HWND hwnd)
2256 IMediaControl *control;
2257 HRESULT hr;
2258 LONG l;
2260 IFilterGraph2_QueryInterface(graph, &IID_IMediaControl, (void **)&control);
2262 hr = IVideoWindow_get_AutoShow(window, &l);
2263 ok(hr == S_OK, "Got hr %#x.\n", hr);
2264 ok(l == OATRUE, "Got %d.\n", l);
2266 hr = IVideoWindow_put_Visible(window, OAFALSE);
2267 ok(hr == S_OK, "Got hr %#x.\n", hr);
2269 hr = IMediaControl_Pause(control);
2270 ok(hr == S_FALSE, "Got hr %#x.\n", hr);
2272 hr = IVideoWindow_get_Visible(window, &l);
2273 ok(hr == S_OK, "Got hr %#x.\n", hr);
2274 ok(l == OATRUE, "Got %d.\n", l);
2276 hr = IMediaControl_Stop(control);
2277 ok(hr == S_OK, "Got hr %#x.\n", hr);
2279 hr = IVideoWindow_get_Visible(window, &l);
2280 ok(hr == S_OK, "Got hr %#x.\n", hr);
2281 ok(l == OATRUE, "Got %d.\n", l);
2283 hr = IVideoWindow_put_AutoShow(window, OAFALSE);
2284 ok(hr == S_OK, "Got hr %#x.\n", hr);
2286 hr = IVideoWindow_put_Visible(window, OAFALSE);
2287 ok(hr == S_OK, "Got hr %#x.\n", hr);
2289 hr = IMediaControl_Pause(control);
2290 ok(hr == S_FALSE, "Got hr %#x.\n", hr);
2292 hr = IVideoWindow_get_Visible(window, &l);
2293 ok(hr == S_OK, "Got hr %#x.\n", hr);
2294 ok(l == OAFALSE, "Got %d.\n", l);
2296 hr = IMediaControl_Stop(control);
2297 ok(hr == S_OK, "Got hr %#x.\n", hr);
2299 IMediaControl_Release(control);
2302 static void test_video_window(void)
2304 ALLOCATOR_PROPERTIES req_props = {1, 600 * 400 * 4, 1, 0}, ret_props;
2305 VIDEOINFOHEADER vih =
2307 .bmiHeader.biSize = sizeof(BITMAPINFOHEADER),
2308 .bmiHeader.biBitCount = 32,
2309 .bmiHeader.biWidth = 600,
2310 .bmiHeader.biHeight = 400,
2311 .bmiHeader.biPlanes = 1,
2312 .bmiHeader.biCompression = BI_RGB,
2314 AM_MEDIA_TYPE req_mt =
2316 .majortype = MEDIATYPE_Video,
2317 .subtype = MEDIASUBTYPE_RGB32,
2318 .formattype = FORMAT_VideoInfo,
2319 .cbFormat = sizeof(vih),
2320 .pbFormat = (BYTE *)&vih,
2322 IFilterGraph2 *graph = create_graph();
2323 WNDCLASSA window_class = {0};
2324 struct testfilter source;
2325 IMemAllocator *allocator;
2326 LONG width, height, l;
2327 IVideoWindow *window;
2328 IMemInputPin *input;
2329 IBaseFilter *filter;
2330 HWND hwnd, our_hwnd;
2331 IOverlay *overlay;
2332 BSTR caption;
2333 HRESULT hr;
2334 DWORD tid;
2335 ULONG ref;
2336 IPin *pin;
2337 RECT rect;
2339 window_class.lpszClassName = "wine_test_class";
2340 window_class.lpfnWndProc = window_proc;
2341 RegisterClassA(&window_class);
2342 our_hwnd = CreateWindowA("wine_test_class", "test window", WS_VISIBLE | WS_OVERLAPPEDWINDOW,
2343 100, 200, 300, 400, NULL, NULL, NULL, NULL);
2344 flush_events();
2346 filter = create_vmr7(0);
2347 flush_events();
2349 ok(GetActiveWindow() == our_hwnd, "Got active window %p.\n", GetActiveWindow());
2351 IBaseFilter_FindPin(filter, L"VMR Input0", &pin);
2352 IPin_QueryInterface(pin, &IID_IMemInputPin, (void **)&input);
2354 hr = IPin_QueryInterface(pin, &IID_IOverlay, (void **)&overlay);
2355 ok(hr == S_OK, "Got hr %#x.\n", hr);
2357 hr = IOverlay_GetWindowHandle(overlay, &hwnd);
2358 ok(hr == S_OK, "Got hr %#x.\n", hr);
2359 if (winetest_debug > 1) trace("ours %p, theirs %p\n", our_hwnd, hwnd);
2360 GetWindowRect(hwnd, &rect);
2362 tid = GetWindowThreadProcessId(hwnd, NULL);
2363 ok(tid == GetCurrentThreadId(), "Expected tid %#x, got %#x.\n", GetCurrentThreadId(), tid);
2365 hr = IBaseFilter_QueryInterface(filter, &IID_IVideoWindow, (void **)&window);
2366 ok(hr == S_OK, "Got hr %#x.\n", hr);
2368 hr = IVideoWindow_get_Caption(window, &caption);
2369 todo_wine ok(hr == VFW_E_NOT_CONNECTED, "Got hr %#x.\n", hr);
2371 hr = IVideoWindow_get_WindowStyle(window, &l);
2372 todo_wine ok(hr == VFW_E_NOT_CONNECTED, "Got hr %#x.\n", hr);
2374 hr = IVideoWindow_get_AutoShow(window, &l);
2375 todo_wine ok(hr == VFW_E_NOT_CONNECTED, "Got hr %#x.\n", hr);
2377 testfilter_init(&source);
2378 IFilterGraph2_AddFilter(graph, &source.filter.IBaseFilter_iface, NULL);
2379 IFilterGraph2_AddFilter(graph, filter, NULL);
2380 hr = IFilterGraph2_ConnectDirect(graph, &source.source.pin.IPin_iface, pin, &req_mt);
2381 if (hr == VFW_E_TYPE_NOT_ACCEPTED) /* w7u */
2383 req_mt.subtype = MEDIASUBTYPE_RGB24;
2384 vih.bmiHeader.biBitCount = 24;
2385 req_props.cbBuffer = 32 * 16 * 3;
2386 hr = IFilterGraph2_ConnectDirect(graph, &source.source.pin.IPin_iface, pin, &req_mt);
2388 ok(hr == S_OK, "Got hr %#x.\n", hr);
2390 hr = IMemInputPin_GetAllocator(input, &allocator);
2391 todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr);
2392 if (hr == S_OK)
2394 hr = IMemAllocator_SetProperties(allocator, &req_props, &ret_props);
2395 ok(hr == S_OK, "Got hr %#x.\n", hr);
2396 ok(!memcmp(&ret_props, &req_props, sizeof(req_props)), "Properties did not match.\n");
2397 hr = IMemAllocator_Commit(allocator);
2398 ok(hr == S_OK, "Got hr %#x.\n", hr);
2399 IMemAllocator_Release(allocator);
2402 ok(GetActiveWindow() == our_hwnd, "Got active window %p.\n", GetActiveWindow());
2404 test_video_window_caption(window, hwnd);
2405 test_video_window_style(window, hwnd, our_hwnd);
2406 test_video_window_state(window, hwnd, our_hwnd);
2407 test_video_window_position(window, hwnd, our_hwnd);
2408 test_video_window_autoshow(window, graph, hwnd);
2409 test_video_window_owner(window, hwnd, our_hwnd);
2410 test_video_window_messages(window, hwnd, our_hwnd);
2412 hr = IVideoWindow_put_FullScreenMode(window, OATRUE);
2413 ok(hr == E_NOTIMPL, "Got hr %#x.\n", hr);
2414 hr = IVideoWindow_get_FullScreenMode(window, &l);
2415 ok(hr == E_NOTIMPL, "Got hr %#x.\n", hr);
2417 hr = IVideoWindow_GetMinIdealImageSize(window, &width, &height);
2418 todo_wine ok(hr == VFW_E_WRONG_STATE, "Got hr %#x.\n", hr);
2419 hr = IVideoWindow_GetMaxIdealImageSize(window, &width, &height);
2420 todo_wine ok(hr == VFW_E_WRONG_STATE, "Got hr %#x.\n", hr);
2422 IFilterGraph2_Release(graph);
2423 IVideoWindow_Release(window);
2424 IOverlay_Release(overlay);
2425 IMemInputPin_Release(input);
2426 IPin_Release(pin);
2427 ref = IBaseFilter_Release(filter);
2428 ok(!ref, "Got outstanding refcount %d.\n", ref);
2429 ref = IBaseFilter_Release(&source.filter.IBaseFilter_iface);
2430 ok(!ref, "Got outstanding refcount %d.\n", ref);
2431 DestroyWindow(our_hwnd);
2434 static void check_source_position_(int line, IBasicVideo *video,
2435 LONG expect_left, LONG expect_top, LONG expect_width, LONG expect_height)
2437 LONG left, top, width, height, l;
2438 HRESULT hr;
2440 left = top = width = height = 0xdeadbeef;
2441 hr = IBasicVideo_GetSourcePosition(video, &left, &top, &width, &height);
2442 ok_(__FILE__,line)(hr == S_OK, "Got hr %#x.\n", hr);
2443 ok_(__FILE__,line)(left == expect_left, "Got left %d.\n", left);
2444 ok_(__FILE__,line)(top == expect_top, "Got top %d.\n", top);
2445 ok_(__FILE__,line)(width == expect_width, "Got width %d.\n", width);
2446 ok_(__FILE__,line)(height == expect_height, "Got height %d.\n", height);
2448 l = 0xdeadbeef;
2449 hr = IBasicVideo_get_SourceLeft(video, &l);
2450 ok_(__FILE__,line)(hr == S_OK, "Failed to get left, hr %#x.\n", hr);
2451 ok_(__FILE__,line)(l == left, "Got left %d.\n", l);
2453 l = 0xdeadbeef;
2454 hr = IBasicVideo_get_SourceTop(video, &l);
2455 ok_(__FILE__,line)(hr == S_OK, "Failed to get top, hr %#x.\n", hr);
2456 ok_(__FILE__,line)(l == top, "Got top %d.\n", l);
2458 l = 0xdeadbeef;
2459 hr = IBasicVideo_get_SourceWidth(video, &l);
2460 ok_(__FILE__,line)(hr == S_OK, "Failed to get width, hr %#x.\n", hr);
2461 ok_(__FILE__,line)(l == width, "Got width %d.\n", l);
2463 l = 0xdeadbeef;
2464 hr = IBasicVideo_get_SourceHeight(video, &l);
2465 ok_(__FILE__,line)(hr == S_OK, "Failed to get height, hr %#x.\n", hr);
2466 ok_(__FILE__,line)(l == height, "Got height %d.\n", l);
2468 #define check_source_position(a,b,c,d,e) check_source_position_(__LINE__,a,b,c,d,e)
2470 static void test_basic_video_source(IBasicVideo *video)
2472 HRESULT hr;
2474 check_source_position(video, 0, 0, 600, 400);
2475 hr = IBasicVideo_IsUsingDefaultSource(video);
2476 ok(hr == S_OK, "Got hr %#x.\n", hr);
2478 hr = IBasicVideo_put_SourceLeft(video, -10);
2479 ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr);
2480 hr = IBasicVideo_put_SourceLeft(video, 10);
2481 ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr);
2483 hr = IBasicVideo_put_SourceTop(video, -10);
2484 ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr);
2485 hr = IBasicVideo_put_SourceTop(video, 10);
2486 ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr);
2488 hr = IBasicVideo_put_SourceWidth(video, -500);
2489 ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr);
2490 hr = IBasicVideo_put_SourceWidth(video, 0);
2491 ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr);
2492 hr = IBasicVideo_put_SourceWidth(video, 700);
2493 ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr);
2494 hr = IBasicVideo_put_SourceWidth(video, 500);
2495 ok(hr == S_OK, "Got hr %#x.\n", hr);
2496 check_source_position(video, 0, 0, 500, 400);
2497 hr = IBasicVideo_IsUsingDefaultSource(video);
2498 ok(hr == S_FALSE, "Got hr %#x.\n", hr);
2500 hr = IBasicVideo_put_SourceHeight(video, -300);
2501 ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr);
2502 hr = IBasicVideo_put_SourceHeight(video, 0);
2503 ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr);
2504 hr = IBasicVideo_put_SourceHeight(video, 600);
2505 ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr);
2506 hr = IBasicVideo_put_SourceHeight(video, 300);
2507 ok(hr == S_OK, "Got hr %#x.\n", hr);
2508 check_source_position(video, 0, 0, 500, 300);
2509 hr = IBasicVideo_IsUsingDefaultSource(video);
2510 ok(hr == S_FALSE, "Got hr %#x.\n", hr);
2512 hr = IBasicVideo_put_SourceLeft(video, -10);
2513 ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr);
2514 hr = IBasicVideo_put_SourceLeft(video, 10);
2515 ok(hr == S_OK, "Got hr %#x.\n", hr);
2516 check_source_position(video, 10, 0, 500, 300);
2517 hr = IBasicVideo_IsUsingDefaultSource(video);
2518 ok(hr == S_FALSE, "Got hr %#x.\n", hr);
2520 hr = IBasicVideo_put_SourceTop(video, -10);
2521 ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr);
2522 hr = IBasicVideo_put_SourceTop(video, 20);
2523 ok(hr == S_OK, "Got hr %#x.\n", hr);
2524 check_source_position(video, 10, 20, 500, 300);
2525 hr = IBasicVideo_IsUsingDefaultSource(video);
2526 ok(hr == S_FALSE, "Got hr %#x.\n", hr);
2528 hr = IBasicVideo_SetSourcePosition(video, 4, 5, 60, 40);
2529 ok(hr == S_OK, "Got hr %#x.\n", hr);
2530 check_source_position(video, 4, 5, 60, 40);
2531 hr = IBasicVideo_IsUsingDefaultSource(video);
2532 ok(hr == S_FALSE, "Got hr %#x.\n", hr);
2534 hr = IBasicVideo_SetSourcePosition(video, 0, 0, 600, 400);
2535 ok(hr == S_OK, "Got hr %#x.\n", hr);
2536 check_source_position(video, 0, 0, 600, 400);
2537 hr = IBasicVideo_IsUsingDefaultSource(video);
2538 ok(hr == S_OK, "Got hr %#x.\n", hr);
2540 hr = IBasicVideo_SetSourcePosition(video, 4, 5, 60, 40);
2541 ok(hr == S_OK, "Got hr %#x.\n", hr);
2542 hr = IBasicVideo_SetDefaultSourcePosition(video);
2543 ok(hr == S_OK, "Got hr %#x.\n", hr);
2544 check_source_position(video, 0, 0, 600, 400);
2545 hr = IBasicVideo_IsUsingDefaultSource(video);
2546 ok(hr == S_OK, "Got hr %#x.\n", hr);
2549 static void check_destination_position_(int line, IBasicVideo *video,
2550 LONG expect_left, LONG expect_top, LONG expect_width, LONG expect_height)
2552 LONG left, top, width, height, l;
2553 HRESULT hr;
2555 left = top = width = height = 0xdeadbeef;
2556 hr = IBasicVideo_GetDestinationPosition(video, &left, &top, &width, &height);
2557 ok_(__FILE__,line)(hr == S_OK, "Failed to get position, hr %#x.\n", hr);
2558 ok_(__FILE__,line)(left == expect_left, "Got left %d.\n", left);
2559 ok_(__FILE__,line)(top == expect_top, "Got top %d.\n", top);
2560 ok_(__FILE__,line)(width == expect_width, "Got width %d.\n", width);
2561 ok_(__FILE__,line)(height == expect_height, "Got height %d.\n", height);
2563 l = 0xdeadbeef;
2564 hr = IBasicVideo_get_DestinationLeft(video, &l);
2565 ok_(__FILE__,line)(hr == S_OK, "Failed to get left, hr %#x.\n", hr);
2566 ok_(__FILE__,line)(l == left, "Got left %d.\n", l);
2568 l = 0xdeadbeef;
2569 hr = IBasicVideo_get_DestinationTop(video, &l);
2570 ok_(__FILE__,line)(hr == S_OK, "Failed to get top, hr %#x.\n", hr);
2571 ok_(__FILE__,line)(l == top, "Got top %d.\n", l);
2573 l = 0xdeadbeef;
2574 hr = IBasicVideo_get_DestinationWidth(video, &l);
2575 ok_(__FILE__,line)(hr == S_OK, "Failed to get width, hr %#x.\n", hr);
2576 ok_(__FILE__,line)(l == width, "Got width %d.\n", l);
2578 l = 0xdeadbeef;
2579 hr = IBasicVideo_get_DestinationHeight(video, &l);
2580 ok_(__FILE__,line)(hr == S_OK, "Failed to get height, hr %#x.\n", hr);
2581 ok_(__FILE__,line)(l == height, "Got height %d.\n", l);
2583 #define check_destination_position(a,b,c,d,e) check_destination_position_(__LINE__,a,b,c,d,e)
2585 static void test_basic_video_destination(IBasicVideo *video)
2587 IVideoWindow *window;
2588 HRESULT hr;
2589 RECT rect;
2591 IBasicVideo_QueryInterface(video, &IID_IVideoWindow, (void **)&window);
2593 check_destination_position(video, 0, 0, 600, 400);
2594 hr = IBasicVideo_IsUsingDefaultDestination(video);
2595 ok(hr == S_OK, "Got hr %#x.\n", hr);
2597 hr = IBasicVideo_put_DestinationLeft(video, -10);
2598 ok(hr == S_OK, "Got hr %#x.\n", hr);
2599 check_destination_position(video, -10, 0, 600, 400);
2600 hr = IBasicVideo_IsUsingDefaultDestination(video);
2601 ok(hr == S_FALSE, "Got hr %#x.\n", hr);
2603 hr = IBasicVideo_put_DestinationLeft(video, 10);
2604 ok(hr == S_OK, "Got hr %#x.\n", hr);
2605 check_destination_position(video, 10, 0, 600, 400);
2606 hr = IBasicVideo_IsUsingDefaultDestination(video);
2607 ok(hr == S_FALSE, "Got hr %#x.\n", hr);
2609 hr = IBasicVideo_put_DestinationTop(video, -20);
2610 ok(hr == S_OK, "Got hr %#x.\n", hr);
2611 check_destination_position(video, 10, -20, 600, 400);
2612 hr = IBasicVideo_IsUsingDefaultDestination(video);
2613 ok(hr == S_FALSE, "Got hr %#x.\n", hr);
2615 hr = IBasicVideo_put_DestinationTop(video, 20);
2616 ok(hr == S_OK, "Got hr %#x.\n", hr);
2617 check_destination_position(video, 10, 20, 600, 400);
2618 hr = IBasicVideo_IsUsingDefaultDestination(video);
2619 ok(hr == S_FALSE, "Got hr %#x.\n", hr);
2621 hr = IBasicVideo_put_DestinationWidth(video, -700);
2622 ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr);
2623 hr = IBasicVideo_put_DestinationWidth(video, 0);
2624 ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr);
2625 hr = IBasicVideo_put_DestinationWidth(video, 700);
2626 ok(hr == S_OK, "Got hr %#x.\n", hr);
2627 check_destination_position(video, 10, 20, 700, 400);
2628 hr = IBasicVideo_IsUsingDefaultDestination(video);
2629 ok(hr == S_FALSE, "Got hr %#x.\n", hr);
2631 hr = IBasicVideo_put_DestinationWidth(video, 500);
2632 ok(hr == S_OK, "Got hr %#x.\n", hr);
2633 check_destination_position(video, 10, 20, 500, 400);
2634 hr = IBasicVideo_IsUsingDefaultDestination(video);
2635 ok(hr == S_FALSE, "Got hr %#x.\n", hr);
2637 hr = IBasicVideo_put_DestinationHeight(video, -500);
2638 ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr);
2639 hr = IBasicVideo_put_DestinationHeight(video, 0);
2640 ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr);
2641 hr = IBasicVideo_put_DestinationHeight(video, 500);
2642 ok(hr == S_OK, "Got hr %#x.\n", hr);
2643 check_destination_position(video, 10, 20, 500, 500);
2644 hr = IBasicVideo_IsUsingDefaultDestination(video);
2645 ok(hr == S_FALSE, "Got hr %#x.\n", hr);
2647 hr = IBasicVideo_put_DestinationHeight(video, 300);
2648 ok(hr == S_OK, "Got hr %#x.\n", hr);
2649 check_destination_position(video, 10, 20, 500, 300);
2650 hr = IBasicVideo_IsUsingDefaultDestination(video);
2651 ok(hr == S_FALSE, "Got hr %#x.\n", hr);
2653 hr = IBasicVideo_SetDestinationPosition(video, 4, 5, 60, 40);
2654 ok(hr == S_OK, "Got hr %#x.\n", hr);
2655 check_destination_position(video, 4, 5, 60, 40);
2656 hr = IBasicVideo_IsUsingDefaultDestination(video);
2657 ok(hr == S_FALSE, "Got hr %#x.\n", hr);
2659 hr = IBasicVideo_SetDestinationPosition(video, 0, 0, 600, 400);
2660 ok(hr == S_OK, "Got hr %#x.\n", hr);
2661 check_destination_position(video, 0, 0, 600, 400);
2662 hr = IBasicVideo_IsUsingDefaultDestination(video);
2663 ok(hr == S_FALSE, "Got hr %#x.\n", hr);
2665 hr = IBasicVideo_SetDestinationPosition(video, 4, 5, 60, 40);
2666 ok(hr == S_OK, "Got hr %#x.\n", hr);
2667 hr = IBasicVideo_SetDefaultDestinationPosition(video);
2668 ok(hr == S_OK, "Got hr %#x.\n", hr);
2669 check_destination_position(video, 0, 0, 600, 400);
2670 hr = IBasicVideo_IsUsingDefaultDestination(video);
2671 ok(hr == S_OK, "Got hr %#x.\n", hr);
2673 SetRect(&rect, 100, 200, 500, 500);
2674 AdjustWindowRect(&rect, WS_OVERLAPPEDWINDOW, FALSE);
2675 hr = IVideoWindow_SetWindowPosition(window, rect.left, rect.top,
2676 rect.right - rect.left, rect.bottom - rect.top);
2677 ok(hr == S_OK, "Got hr %#x.\n", hr);
2678 check_destination_position(video, 0, 0, 400, 300);
2679 hr = IBasicVideo_IsUsingDefaultDestination(video);
2680 ok(hr == S_OK, "Got hr %#x.\n", hr);
2682 hr = IBasicVideo_SetDestinationPosition(video, 0, 0, 400, 300);
2683 ok(hr == S_OK, "Got hr %#x.\n", hr);
2684 check_destination_position(video, 0, 0, 400, 300);
2685 hr = IBasicVideo_IsUsingDefaultDestination(video);
2686 ok(hr == S_FALSE, "Got hr %#x.\n", hr);
2688 SetRect(&rect, 100, 200, 600, 600);
2689 AdjustWindowRect(&rect, WS_OVERLAPPEDWINDOW, FALSE);
2690 hr = IVideoWindow_SetWindowPosition(window, rect.left, rect.top,
2691 rect.right - rect.left, rect.bottom - rect.top);
2692 ok(hr == S_OK, "Got hr %#x.\n", hr);
2693 check_destination_position(video, 0, 0, 400, 300);
2694 hr = IBasicVideo_IsUsingDefaultDestination(video);
2695 ok(hr == S_FALSE, "Got hr %#x.\n", hr);
2697 IVideoWindow_Release(window);
2700 static void test_basic_video(void)
2702 ALLOCATOR_PROPERTIES req_props = {1, 600 * 400 * 4, 1, 0}, ret_props;
2703 VIDEOINFOHEADER vih =
2705 .AvgTimePerFrame = 200000,
2706 .rcSource = {4, 6, 16, 12},
2707 .rcTarget = {40, 60, 120, 160},
2708 .bmiHeader.biSize = sizeof(BITMAPINFOHEADER),
2709 .bmiHeader.biBitCount = 32,
2710 .bmiHeader.biWidth = 600,
2711 .bmiHeader.biHeight = 400,
2712 .bmiHeader.biPlanes = 1,
2713 .bmiHeader.biCompression = BI_RGB,
2715 AM_MEDIA_TYPE req_mt =
2717 .majortype = MEDIATYPE_Video,
2718 .subtype = MEDIASUBTYPE_RGB32,
2719 .formattype = FORMAT_VideoInfo,
2720 .cbFormat = sizeof(vih),
2721 .pbFormat = (BYTE *)&vih,
2723 IBaseFilter *filter = create_vmr7(VMRMode_Windowed);
2724 IFilterGraph2 *graph = create_graph();
2725 LONG left, top, width, height, l;
2726 struct testfilter source;
2727 IMemAllocator *allocator;
2728 IMemInputPin *input;
2729 ITypeInfo *typeinfo;
2730 IBasicVideo *video;
2731 TYPEATTR *typeattr;
2732 REFTIME reftime;
2733 HRESULT hr;
2734 UINT count;
2735 ULONG ref;
2736 IPin *pin;
2737 RECT rect;
2739 IBaseFilter_QueryInterface(filter, &IID_IBasicVideo, (void **)&video);
2740 IBaseFilter_FindPin(filter, L"VMR Input0", &pin);
2741 IPin_QueryInterface(pin, &IID_IMemInputPin, (void **)&input);
2743 hr = IBasicVideo_GetTypeInfoCount(video, &count);
2744 ok(hr == S_OK, "Got hr %#x.\n", hr);
2745 ok(count == 1, "Got count %u.\n", count);
2747 hr = IBasicVideo_GetTypeInfo(video, 0, 0, &typeinfo);
2748 ok(hr == S_OK, "Got hr %#x.\n", hr);
2749 hr = ITypeInfo_GetTypeAttr(typeinfo, &typeattr);
2750 ok(hr == S_OK, "Got hr %#x.\n", hr);
2751 ok(typeattr->typekind == TKIND_DISPATCH, "Got kind %u.\n", typeattr->typekind);
2752 ok(IsEqualGUID(&typeattr->guid, &IID_IBasicVideo), "Got IID %s.\n", wine_dbgstr_guid(&typeattr->guid));
2753 ITypeInfo_ReleaseTypeAttr(typeinfo, typeattr);
2754 ITypeInfo_Release(typeinfo);
2756 hr = IBasicVideo_get_AvgTimePerFrame(video, NULL);
2757 ok(hr == E_POINTER, "Got hr %#x.\n", hr);
2758 hr = IBasicVideo_get_AvgTimePerFrame(video, &reftime);
2759 ok(hr == VFW_E_NOT_CONNECTED, "Got hr %#x.\n", hr);
2761 hr = IBasicVideo_get_BitRate(video, NULL);
2762 ok(hr == E_POINTER, "Got hr %#x.\n", hr);
2763 hr = IBasicVideo_get_BitRate(video, &l);
2764 ok(hr == VFW_E_NOT_CONNECTED, "Got hr %#x.\n", hr);
2766 hr = IBasicVideo_get_BitErrorRate(video, NULL);
2767 ok(hr == E_POINTER, "Got hr %#x.\n", hr);
2768 hr = IBasicVideo_get_BitErrorRate(video, &l);
2769 ok(hr == VFW_E_NOT_CONNECTED, "Got hr %#x.\n", hr);
2771 hr = IBasicVideo_get_VideoWidth(video, NULL);
2772 ok(hr == E_POINTER, "Got hr %#x.\n", hr);
2773 hr = IBasicVideo_get_VideoHeight(video, NULL);
2774 ok(hr == E_POINTER, "Got hr %#x.\n", hr);
2776 hr = IBasicVideo_get_SourceLeft(video, NULL);
2777 ok(hr == E_POINTER, "Got hr %#x.\n", hr);
2778 hr = IBasicVideo_get_SourceWidth(video, NULL);
2779 ok(hr == E_POINTER, "Got hr %#x.\n", hr);
2780 hr = IBasicVideo_get_SourceTop(video, NULL);
2781 ok(hr == E_POINTER, "Got hr %#x.\n", hr);
2782 hr = IBasicVideo_get_SourceHeight(video, NULL);
2783 ok(hr == E_POINTER, "Got hr %#x.\n", hr);
2785 hr = IBasicVideo_get_DestinationLeft(video, NULL);
2786 ok(hr == E_POINTER, "Got hr %#x.\n", hr);
2787 hr = IBasicVideo_get_DestinationWidth(video, NULL);
2788 ok(hr == E_POINTER, "Got hr %#x.\n", hr);
2789 hr = IBasicVideo_get_DestinationTop(video, NULL);
2790 ok(hr == E_POINTER, "Got hr %#x.\n", hr);
2791 hr = IBasicVideo_get_DestinationHeight(video, NULL);
2792 ok(hr == E_POINTER, "Got hr %#x.\n", hr);
2794 hr = IBasicVideo_GetSourcePosition(video, NULL, &top, &width, &height);
2795 ok(hr == E_POINTER, "Got hr %#x.\n", hr);
2796 hr = IBasicVideo_GetSourcePosition(video, &left, NULL, &width, &height);
2797 ok(hr == E_POINTER, "Got hr %#x.\n", hr);
2798 hr = IBasicVideo_GetSourcePosition(video, &left, &top, NULL, &height);
2799 ok(hr == E_POINTER, "Got hr %#x.\n", hr);
2800 hr = IBasicVideo_GetSourcePosition(video, &left, &top, &width, NULL);
2801 ok(hr == E_POINTER, "Got hr %#x.\n", hr);
2803 hr = IBasicVideo_GetDestinationPosition(video, NULL, &top, &width, &height);
2804 ok(hr == E_POINTER, "Got hr %#x.\n", hr);
2805 hr = IBasicVideo_GetDestinationPosition(video, &left, NULL, &width, &height);
2806 ok(hr == E_POINTER, "Got hr %#x.\n", hr);
2807 hr = IBasicVideo_GetDestinationPosition(video, &left, &top, NULL, &height);
2808 ok(hr == E_POINTER, "Got hr %#x.\n", hr);
2809 hr = IBasicVideo_GetDestinationPosition(video, &left, &top, &width, NULL);
2810 ok(hr == E_POINTER, "Got hr %#x.\n", hr);
2812 hr = IBasicVideo_GetVideoSize(video, &width, NULL);
2813 ok(hr == E_POINTER, "Got hr %#x.\n", hr);
2814 hr = IBasicVideo_GetVideoSize(video, NULL, &height);
2815 ok(hr == E_POINTER, "Got hr %#x.\n", hr);
2817 hr = IBasicVideo_GetVideoPaletteEntries(video, 0, 1, NULL, &l);
2818 ok(hr == E_POINTER, "Got hr %#x.\n", hr);
2819 hr = IBasicVideo_GetVideoPaletteEntries(video, 0, 1, &l, NULL);
2820 todo_wine ok(hr == VFW_E_NOT_CONNECTED, "Got hr %#x.\n", hr);
2822 testfilter_init(&source);
2823 IFilterGraph2_AddFilter(graph, &source.filter.IBaseFilter_iface, L"vmr9");
2824 IFilterGraph2_AddFilter(graph, filter, L"source");
2825 hr = IFilterGraph2_ConnectDirect(graph, &source.source.pin.IPin_iface, pin, &req_mt);
2826 if (hr == E_FAIL)
2828 skip("Got E_FAIL when connecting.\n");
2829 goto out;
2831 ok(hr == S_OK, "Got hr %#x.\n", hr);
2833 hr = IMemInputPin_GetAllocator(input, &allocator);
2834 todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr);
2835 if (hr == S_OK)
2837 hr = IMemAllocator_SetProperties(allocator, &req_props, &ret_props);
2838 ok(hr == S_OK, "Got hr %#x.\n", hr);
2839 ok(!memcmp(&ret_props, &req_props, sizeof(req_props)), "Properties did not match.\n");
2840 hr = IMemAllocator_Commit(allocator);
2841 ok(hr == S_OK, "Got hr %#x.\n", hr);
2842 IMemAllocator_Release(allocator);
2845 reftime = 0.0;
2846 hr = IBasicVideo_get_AvgTimePerFrame(video, &reftime);
2847 ok(hr == S_OK, "Got hr %#x.\n", hr);
2848 ok(compare_double(reftime, 0.02, 1 << 28), "Got frame rate %.16e.\n", reftime);
2850 l = 0xdeadbeef;
2851 hr = IBasicVideo_get_BitRate(video, &l);
2852 ok(hr == S_OK, "Got hr %#x.\n", hr);
2853 ok(!l, "Got bit rate %d.\n", l);
2855 l = 0xdeadbeef;
2856 hr = IBasicVideo_get_BitErrorRate(video, &l);
2857 ok(hr == S_OK, "Got hr %#x.\n", hr);
2858 ok(!l, "Got bit rate %d.\n", l);
2860 hr = IBasicVideo_GetVideoPaletteEntries(video, 0, 1, &l, NULL);
2861 todo_wine ok(hr == VFW_E_NO_PALETTE_AVAILABLE, "Got hr %#x.\n", hr);
2863 width = height = 0xdeadbeef;
2864 hr = IBasicVideo_GetVideoSize(video, &width, &height);
2865 ok(hr == S_OK, "Got hr %#x.\n", hr);
2866 ok(width == 600, "Got width %d.\n", width);
2867 ok(height == 400, "Got height %d.\n", height);
2869 test_basic_video_source(video);
2870 test_basic_video_destination(video);
2872 hr = IFilterGraph2_Disconnect(graph, &source.source.pin.IPin_iface);
2873 ok(hr == S_OK, "Got hr %#x.\n", hr);
2874 hr = IFilterGraph2_Disconnect(graph, pin);
2875 ok(hr == S_OK, "Got hr %#x.\n", hr);
2877 vih.bmiHeader.biWidth = 16;
2878 vih.bmiHeader.biHeight = 16;
2879 hr = IFilterGraph2_ConnectDirect(graph, &source.source.pin.IPin_iface, pin, &req_mt);
2880 ok(hr == S_OK, "Got hr %#x.\n", hr);
2882 hr = IMemInputPin_GetAllocator(input, &allocator);
2883 todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr);
2884 if (hr == S_OK)
2886 hr = IMemAllocator_SetProperties(allocator, &req_props, &ret_props);
2887 ok(hr == S_OK, "Got hr %#x.\n", hr);
2888 ok(!memcmp(&ret_props, &req_props, sizeof(req_props)), "Properties did not match.\n");
2889 hr = IMemAllocator_Commit(allocator);
2890 ok(hr == S_OK, "Got hr %#x.\n", hr);
2891 IMemAllocator_Release(allocator);
2894 check_source_position(video, 0, 0, 16, 16);
2896 SetRect(&rect, 0, 0, 0, 0);
2897 AdjustWindowRectEx(&rect, WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_OVERLAPPEDWINDOW, FALSE, 0);
2898 check_destination_position(video, 0, 0, max(16, GetSystemMetrics(SM_CXMIN) - (rect.right - rect.left)),
2899 max(16, GetSystemMetrics(SM_CYMIN) - (rect.bottom - rect.top)));
2901 out:
2902 ref = IFilterGraph2_Release(graph);
2903 ok(!ref, "Got outstanding refcount %d.\n", ref);
2904 IBasicVideo_Release(video);
2905 IMemInputPin_Release(input);
2906 IPin_Release(pin);
2907 ref = IBaseFilter_Release(filter);
2908 ok(!ref, "Got outstanding refcount %d.\n", ref);
2909 ref = IBaseFilter_Release(&source.filter.IBaseFilter_iface);
2910 ok(!ref, "Got outstanding refcount %d.\n", ref);
2913 static void test_windowless_size(void)
2915 ALLOCATOR_PROPERTIES req_props = {1, 32 * 16 * 4, 1, 0}, ret_props;
2916 VIDEOINFOHEADER vih =
2918 .bmiHeader.biSize = sizeof(BITMAPINFOHEADER),
2919 .bmiHeader.biWidth = 32,
2920 .bmiHeader.biHeight = 16,
2921 .bmiHeader.biBitCount = 32,
2922 .bmiHeader.biPlanes = 1,
2924 AM_MEDIA_TYPE mt =
2926 .majortype = MEDIATYPE_Video,
2927 .subtype = MEDIASUBTYPE_RGB32,
2928 .formattype = FORMAT_VideoInfo,
2929 .cbFormat = sizeof(vih),
2930 .pbFormat = (BYTE *)&vih,
2932 IBaseFilter *filter = create_vmr7(VMRMode_Windowless);
2933 LONG width, height, aspect_width, aspect_height;
2934 IVMRWindowlessControl *windowless_control;
2935 IFilterGraph2 *graph = create_graph();
2936 struct testfilter source;
2937 IMemAllocator *allocator;
2938 RECT src, dst, expect;
2939 IMemInputPin *input;
2940 HWND window;
2941 HRESULT hr;
2942 ULONG ref;
2943 IPin *pin;
2945 IBaseFilter_QueryInterface(filter, &IID_IVMRWindowlessControl, (void **)&windowless_control);
2946 IBaseFilter_FindPin(filter, L"VMR Input0", &pin);
2947 IPin_QueryInterface(pin, &IID_IMemInputPin, (void **)&input);
2948 testfilter_init(&source);
2949 IFilterGraph2_AddFilter(graph, &source.filter.IBaseFilter_iface, L"source");
2950 IFilterGraph2_AddFilter(graph, filter, L"vmr7");
2951 window = CreateWindowA("static", "quartz_test", WS_OVERLAPPEDWINDOW, 0, 0, 640, 480, 0, 0, 0, 0);
2952 ok(!!window, "Failed to create a window.\n");
2954 hr = IVMRWindowlessControl_SetVideoClippingWindow(windowless_control, window);
2955 ok(hr == S_OK, "Got hr %#x.\n", hr);
2957 hr = IFilterGraph2_ConnectDirect(graph, &source.source.pin.IPin_iface, pin, &mt);
2958 ok(hr == S_OK, "Got hr %#x.\n", hr);
2959 hr = IMemInputPin_GetAllocator(input, &allocator);
2960 todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr);
2961 if (hr == S_OK)
2963 hr = IMemAllocator_SetProperties(allocator, &req_props, &ret_props);
2964 IMemAllocator_Release(allocator);
2965 if (hr == E_FAIL)
2967 skip("Got E_FAIL when setting allocator properties.\n");
2968 goto out;
2970 ok(hr == S_OK, "Got hr %#x.\n", hr);
2971 ok(!memcmp(&ret_props, &req_props, sizeof(req_props)), "Properties did not match.\n");
2974 hr = IVMRWindowlessControl_GetNativeVideoSize(windowless_control, NULL, &height, &aspect_width, &aspect_height);
2975 ok(hr == E_POINTER, "Got hr %#x.\n", hr);
2976 hr = IVMRWindowlessControl_GetNativeVideoSize(windowless_control, &width, NULL, &aspect_width, &aspect_height);
2977 ok(hr == E_POINTER, "Got hr %#x.\n", hr);
2979 width = height = 0xdeadbeef;
2980 hr = IVMRWindowlessControl_GetNativeVideoSize(windowless_control, &width, &height, NULL, NULL);
2981 ok(hr == S_OK, "Got hr %#x.\n", hr);
2982 ok(width == 32, "Got width %d.\n", width);
2983 ok(height == 16, "Got height %d.\n", height);
2985 aspect_width = aspect_height = 0xdeadbeef;
2986 hr = IVMRWindowlessControl_GetNativeVideoSize(windowless_control, &width, &height, &aspect_width, &aspect_height);
2987 ok(hr == S_OK, "Got hr %#x.\n", hr);
2988 ok(aspect_width == 32, "Got width %d.\n", aspect_width);
2989 ok(aspect_height == 16, "Got height %d.\n", aspect_height);
2991 memset(&src, 0xcc, sizeof(src));
2992 hr = IVMRWindowlessControl_GetVideoPosition(windowless_control, &src, NULL);
2993 ok(hr == S_OK, "Got hr %#x.\n", hr);
2994 SetRect(&expect, 0, 0, 32, 16);
2995 ok(EqualRect(&src, &expect), "Got source rect %s.\n", wine_dbgstr_rect(&src));
2997 memset(&dst, 0xcc, sizeof(dst));
2998 hr = IVMRWindowlessControl_GetVideoPosition(windowless_control, NULL, &dst);
2999 ok(hr == S_OK, "Got hr %#x.\n", hr);
3000 SetRect(&expect, 0, 0, 0, 0);
3001 ok(EqualRect(&dst, &expect), "Got dest rect %s.\n", wine_dbgstr_rect(&dst));
3003 SetRect(&src, 4, 6, 16, 12);
3004 hr = IVMRWindowlessControl_SetVideoPosition(windowless_control, &src, NULL);
3005 ok(hr == S_OK, "Got hr %#x.\n", hr);
3007 memset(&src, 0xcc, sizeof(src));
3008 memset(&dst, 0xcc, sizeof(dst));
3009 hr = IVMRWindowlessControl_GetVideoPosition(windowless_control, &src, &dst);
3010 ok(hr == S_OK, "Got hr %#x.\n", hr);
3011 SetRect(&expect, 4, 6, 16, 12);
3012 ok(EqualRect(&src, &expect), "Got source rect %s.\n", wine_dbgstr_rect(&src));
3013 SetRect(&expect, 0, 0, 0, 0);
3014 ok(EqualRect(&dst, &expect), "Got dest rect %s.\n", wine_dbgstr_rect(&dst));
3016 SetRect(&dst, 40, 60, 120, 160);
3017 hr = IVMRWindowlessControl_SetVideoPosition(windowless_control, NULL, &dst);
3018 ok(hr == S_OK, "Got hr %#x.\n", hr);
3020 memset(&src, 0xcc, sizeof(src));
3021 memset(&dst, 0xcc, sizeof(dst));
3022 hr = IVMRWindowlessControl_GetVideoPosition(windowless_control, &src, &dst);
3023 ok(hr == S_OK, "Got hr %#x.\n", hr);
3024 SetRect(&expect, 4, 6, 16, 12);
3025 ok(EqualRect(&src, &expect), "Got source rect %s.\n", wine_dbgstr_rect(&src));
3026 SetRect(&expect, 40, 60, 120, 160);
3027 ok(EqualRect(&dst, &expect), "Got dest rect %s.\n", wine_dbgstr_rect(&dst));
3029 GetWindowRect(window, &src);
3030 SetRect(&expect, 0, 0, 640, 480);
3031 ok(EqualRect(&src, &expect), "Got window rect %s.\n", wine_dbgstr_rect(&src));
3033 out:
3034 ref = IFilterGraph2_Release(graph);
3035 ok(!ref, "Got outstanding refcount %d.\n", ref);
3036 IMemInputPin_Release(input);
3037 IPin_Release(pin);
3038 IVMRWindowlessControl_Release(windowless_control);
3039 ref = IBaseFilter_Release(filter);
3040 ok(!ref, "Got outstanding refcount %d.\n", ref);
3041 DestroyWindow(window);
3044 START_TEST(vmr7)
3046 CoInitialize(NULL);
3048 test_filter_config();
3049 test_interfaces();
3050 test_aggregation();
3051 test_enum_pins();
3052 test_find_pin();
3053 test_pin_info();
3054 test_media_types();
3055 test_enum_media_types();
3056 test_unconnected_filter_state();
3057 test_connect_pin();
3058 test_overlay();
3059 test_video_window();
3060 test_basic_video();
3061 test_windowless_size();
3063 CoUninitialize();