2 * ACM wrapper filter 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
23 #include "wine/test.h"
25 static IBaseFilter
*create_acm_wrapper(void)
27 IBaseFilter
*filter
= NULL
;
28 HRESULT hr
= CoCreateInstance(&CLSID_ACMWrapper
, NULL
, CLSCTX_INPROC_SERVER
,
29 &IID_IBaseFilter
, (void **)&filter
);
30 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
34 static ULONG
get_refcount(void *iface
)
36 IUnknown
*unknown
= iface
;
37 IUnknown_AddRef(unknown
);
38 return IUnknown_Release(unknown
);
41 #define check_interface(a, b, c) check_interface_(__LINE__, a, b, c)
42 static void check_interface_(unsigned int line
, void *iface_ptr
, REFIID iid
, BOOL supported
)
44 IUnknown
*iface
= iface_ptr
;
45 HRESULT hr
, expected_hr
;
48 expected_hr
= supported
? S_OK
: E_NOINTERFACE
;
50 hr
= IUnknown_QueryInterface(iface
, iid
, (void **)&unk
);
51 ok_(__FILE__
, line
)(hr
== expected_hr
, "Got hr %#lx, expected %#lx.\n", hr
, expected_hr
);
53 IUnknown_Release(unk
);
56 static void test_interfaces(void)
58 IBaseFilter
*filter
= create_acm_wrapper();
61 check_interface(filter
, &IID_IBaseFilter
, TRUE
);
62 check_interface(filter
, &IID_IMediaFilter
, TRUE
);
63 check_interface(filter
, &IID_IPersist
, TRUE
);
64 todo_wine
check_interface(filter
, &IID_IPersistPropertyBag
, TRUE
);
65 check_interface(filter
, &IID_IUnknown
, TRUE
);
67 check_interface(filter
, &IID_IAMFilterMiscFlags
, FALSE
);
68 check_interface(filter
, &IID_IBasicAudio
, FALSE
);
69 check_interface(filter
, &IID_IBasicVideo
, FALSE
);
70 check_interface(filter
, &IID_IKsPropertySet
, FALSE
);
71 check_interface(filter
, &IID_IMediaPosition
, FALSE
);
72 check_interface(filter
, &IID_IMediaSeeking
, FALSE
);
73 check_interface(filter
, &IID_IPin
, FALSE
);
74 check_interface(filter
, &IID_IQualityControl
, FALSE
);
75 check_interface(filter
, &IID_IQualProp
, FALSE
);
76 check_interface(filter
, &IID_IReferenceClock
, FALSE
);
77 check_interface(filter
, &IID_IVideoWindow
, FALSE
);
79 IBaseFilter_FindPin(filter
, L
"In", &pin
);
81 check_interface(pin
, &IID_IMemInputPin
, TRUE
);
82 check_interface(pin
, &IID_IPin
, TRUE
);
83 todo_wine
check_interface(pin
, &IID_IQualityControl
, TRUE
);
84 check_interface(pin
, &IID_IUnknown
, TRUE
);
86 check_interface(pin
, &IID_IMediaPosition
, FALSE
);
87 check_interface(pin
, &IID_IMediaSeeking
, FALSE
);
91 IBaseFilter_FindPin(filter
, L
"Out", &pin
);
93 check_interface(pin
, &IID_IPin
, TRUE
);
94 todo_wine
check_interface(pin
, &IID_IMediaPosition
, TRUE
);
95 check_interface(pin
, &IID_IMediaSeeking
, TRUE
);
96 check_interface(pin
, &IID_IQualityControl
, TRUE
);
97 check_interface(pin
, &IID_IUnknown
, TRUE
);
99 check_interface(pin
, &IID_IAsyncReader
, FALSE
);
103 IBaseFilter_Release(filter
);
106 static const GUID test_iid
= {0x33333333};
107 static LONG outer_ref
= 1;
109 static HRESULT WINAPI
outer_QueryInterface(IUnknown
*iface
, REFIID iid
, void **out
)
111 if (IsEqualGUID(iid
, &IID_IUnknown
)
112 || IsEqualGUID(iid
, &IID_IBaseFilter
)
113 || IsEqualGUID(iid
, &test_iid
))
115 *out
= (IUnknown
*)0xdeadbeef;
118 ok(0, "unexpected call %s\n", wine_dbgstr_guid(iid
));
119 return E_NOINTERFACE
;
122 static ULONG WINAPI
outer_AddRef(IUnknown
*iface
)
124 return InterlockedIncrement(&outer_ref
);
127 static ULONG WINAPI
outer_Release(IUnknown
*iface
)
129 return InterlockedDecrement(&outer_ref
);
132 static const IUnknownVtbl outer_vtbl
=
134 outer_QueryInterface
,
139 static IUnknown test_outer
= {&outer_vtbl
};
141 static void test_aggregation(void)
143 IBaseFilter
*filter
, *filter2
;
144 IUnknown
*unk
, *unk2
;
148 filter
= (IBaseFilter
*)0xdeadbeef;
149 hr
= CoCreateInstance(&CLSID_ACMWrapper
, &test_outer
, CLSCTX_INPROC_SERVER
,
150 &IID_IBaseFilter
, (void **)&filter
);
151 ok(hr
== E_NOINTERFACE
, "Got hr %#lx.\n", hr
);
152 ok(!filter
, "Got interface %p.\n", filter
);
154 hr
= CoCreateInstance(&CLSID_ACMWrapper
, &test_outer
, CLSCTX_INPROC_SERVER
,
155 &IID_IUnknown
, (void **)&unk
);
156 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
157 ok(outer_ref
== 1, "Got unexpected refcount %ld.\n", outer_ref
);
158 ok(unk
!= &test_outer
, "Returned IUnknown should not be outer IUnknown.\n");
159 ref
= get_refcount(unk
);
160 ok(ref
== 1, "Got unexpected refcount %ld.\n", ref
);
162 ref
= IUnknown_AddRef(unk
);
163 ok(ref
== 2, "Got unexpected refcount %ld.\n", ref
);
164 ok(outer_ref
== 1, "Got unexpected refcount %ld.\n", outer_ref
);
166 ref
= IUnknown_Release(unk
);
167 ok(ref
== 1, "Got unexpected refcount %ld.\n", ref
);
168 ok(outer_ref
== 1, "Got unexpected refcount %ld.\n", outer_ref
);
170 hr
= IUnknown_QueryInterface(unk
, &IID_IUnknown
, (void **)&unk2
);
171 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
172 ok(unk2
== unk
, "Got unexpected IUnknown %p.\n", unk2
);
173 IUnknown_Release(unk2
);
175 hr
= IUnknown_QueryInterface(unk
, &IID_IBaseFilter
, (void **)&filter
);
176 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
178 hr
= IBaseFilter_QueryInterface(filter
, &IID_IUnknown
, (void **)&unk2
);
179 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
180 ok(unk2
== (IUnknown
*)0xdeadbeef, "Got unexpected IUnknown %p.\n", unk2
);
182 hr
= IBaseFilter_QueryInterface(filter
, &IID_IBaseFilter
, (void **)&filter2
);
183 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
184 ok(filter2
== (IBaseFilter
*)0xdeadbeef, "Got unexpected IBaseFilter %p.\n", filter2
);
186 hr
= IUnknown_QueryInterface(unk
, &test_iid
, (void **)&unk2
);
187 ok(hr
== E_NOINTERFACE
, "Got hr %#lx.\n", hr
);
188 ok(!unk2
, "Got unexpected IUnknown %p.\n", unk2
);
190 hr
= IBaseFilter_QueryInterface(filter
, &test_iid
, (void **)&unk2
);
191 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
192 ok(unk2
== (IUnknown
*)0xdeadbeef, "Got unexpected IUnknown %p.\n", unk2
);
194 IBaseFilter_Release(filter
);
195 ref
= IUnknown_Release(unk
);
196 ok(!ref
, "Got unexpected refcount %ld.\n", ref
);
197 ok(outer_ref
== 1, "Got unexpected refcount %ld.\n", outer_ref
);
200 static void test_enum_pins(void)
202 IBaseFilter
*filter
= create_acm_wrapper();
203 IEnumPins
*enum1
, *enum2
;
208 ref
= get_refcount(filter
);
209 ok(ref
== 1, "Got unexpected refcount %ld.\n", ref
);
211 hr
= IBaseFilter_EnumPins(filter
, NULL
);
212 ok(hr
== E_POINTER
, "Got hr %#lx.\n", hr
);
214 hr
= IBaseFilter_EnumPins(filter
, &enum1
);
215 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
216 ref
= get_refcount(filter
);
217 ok(ref
== 2, "Got unexpected refcount %ld.\n", ref
);
218 ref
= get_refcount(enum1
);
219 ok(ref
== 1, "Got unexpected refcount %ld.\n", ref
);
221 hr
= IEnumPins_Next(enum1
, 1, NULL
, NULL
);
222 ok(hr
== E_POINTER
, "Got hr %#lx.\n", hr
);
224 hr
= IEnumPins_Next(enum1
, 1, pins
, NULL
);
225 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
226 ref
= get_refcount(filter
);
227 ok(ref
== 3, "Got unexpected refcount %ld.\n", ref
);
228 ref
= get_refcount(pins
[0]);
229 ok(ref
== 3, "Got unexpected refcount %ld.\n", ref
);
230 ref
= get_refcount(enum1
);
231 ok(ref
== 1, "Got unexpected refcount %ld.\n", ref
);
232 IPin_Release(pins
[0]);
233 ref
= get_refcount(filter
);
234 ok(ref
== 2, "Got unexpected refcount %ld.\n", ref
);
236 hr
= IEnumPins_Next(enum1
, 1, pins
, NULL
);
237 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
238 ref
= get_refcount(filter
);
239 ok(ref
== 3, "Got unexpected refcount %ld.\n", ref
);
240 ref
= get_refcount(pins
[0]);
241 ok(ref
== 3, "Got unexpected refcount %ld.\n", ref
);
242 ref
= get_refcount(enum1
);
243 ok(ref
== 1, "Got unexpected refcount %ld.\n", ref
);
244 IPin_Release(pins
[0]);
245 ref
= get_refcount(filter
);
246 ok(ref
== 2, "Got unexpected refcount %ld.\n", ref
);
248 hr
= IEnumPins_Next(enum1
, 1, pins
, NULL
);
249 ok(hr
== S_FALSE
, "Got hr %#lx.\n", hr
);
251 hr
= IEnumPins_Reset(enum1
);
252 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
254 hr
= IEnumPins_Next(enum1
, 1, pins
, &count
);
255 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
256 ok(count
== 1, "Got count %lu.\n", count
);
257 IPin_Release(pins
[0]);
259 hr
= IEnumPins_Next(enum1
, 1, pins
, &count
);
260 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
261 ok(count
== 1, "Got count %lu.\n", count
);
262 IPin_Release(pins
[0]);
264 hr
= IEnumPins_Next(enum1
, 1, pins
, &count
);
265 ok(hr
== S_FALSE
, "Got hr %#lx.\n", hr
);
266 ok(!count
, "Got count %lu.\n", count
);
268 hr
= IEnumPins_Reset(enum1
);
269 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
271 hr
= IEnumPins_Next(enum1
, 2, pins
, NULL
);
272 ok(hr
== E_INVALIDARG
, "Got hr %#lx.\n", hr
);
274 hr
= IEnumPins_Next(enum1
, 2, pins
, &count
);
275 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
276 ok(count
== 2, "Got count %lu.\n", count
);
277 IPin_Release(pins
[0]);
278 IPin_Release(pins
[1]);
280 hr
= IEnumPins_Next(enum1
, 2, pins
, &count
);
281 ok(hr
== S_FALSE
, "Got hr %#lx.\n", hr
);
282 ok(!count
, "Got count %lu.\n", count
);
284 hr
= IEnumPins_Reset(enum1
);
285 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
287 hr
= IEnumPins_Next(enum1
, 3, pins
, &count
);
288 ok(hr
== S_FALSE
, "Got hr %#lx.\n", hr
);
289 ok(count
== 2, "Got count %lu.\n", count
);
290 IPin_Release(pins
[0]);
291 IPin_Release(pins
[1]);
293 hr
= IEnumPins_Reset(enum1
);
294 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
296 hr
= IEnumPins_Clone(enum1
, &enum2
);
297 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
299 hr
= IEnumPins_Skip(enum1
, 3);
300 ok(hr
== S_FALSE
, "Got hr %#lx.\n", hr
);
302 hr
= IEnumPins_Skip(enum1
, 2);
303 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
305 hr
= IEnumPins_Skip(enum1
, 1);
306 ok(hr
== S_FALSE
, "Got hr %#lx.\n", hr
);
308 hr
= IEnumPins_Next(enum1
, 1, pins
, NULL
);
309 ok(hr
== S_FALSE
, "Got hr %#lx.\n", hr
);
311 hr
= IEnumPins_Next(enum2
, 1, pins
, NULL
);
312 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
313 IPin_Release(pins
[0]);
315 IEnumPins_Release(enum2
);
316 IEnumPins_Release(enum1
);
317 ref
= IBaseFilter_Release(filter
);
318 ok(!ref
, "Got outstanding refcount %ld.\n", ref
);
321 static void test_find_pin(void)
323 IBaseFilter
*filter
= create_acm_wrapper();
324 IEnumPins
*enum_pins
;
329 hr
= IBaseFilter_EnumPins(filter
, &enum_pins
);
330 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
332 hr
= IBaseFilter_FindPin(filter
, L
"In", &pin
);
333 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
334 hr
= IEnumPins_Next(enum_pins
, 1, &pin2
, NULL
);
335 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
336 ok(pin
== pin2
, "Pins didn't match.\n");
340 hr
= IBaseFilter_FindPin(filter
, L
"Out", &pin
);
341 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
342 hr
= IEnumPins_Next(enum_pins
, 1, &pin2
, NULL
);
343 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
344 ok(pin
== pin2
, "Pins didn't match.\n");
348 hr
= IBaseFilter_FindPin(filter
, L
"Input", &pin
);
349 ok(hr
== VFW_E_NOT_FOUND
, "Got hr %#lx.\n", hr
);
350 hr
= IBaseFilter_FindPin(filter
, L
"Output", &pin
);
351 ok(hr
== VFW_E_NOT_FOUND
, "Got hr %#lx.\n", hr
);
352 hr
= IBaseFilter_FindPin(filter
, L
"input pin", &pin
);
353 ok(hr
== VFW_E_NOT_FOUND
, "Got hr %#lx.\n", hr
);
354 hr
= IBaseFilter_FindPin(filter
, L
"output pin", &pin
);
355 ok(hr
== VFW_E_NOT_FOUND
, "Got hr %#lx.\n", hr
);
357 IEnumPins_Release(enum_pins
);
358 ref
= IBaseFilter_Release(filter
);
359 ok(!ref
, "Got outstanding refcount %ld.\n", ref
);
362 static void test_pin_info(void)
364 IBaseFilter
*filter
= create_acm_wrapper();
372 hr
= IBaseFilter_FindPin(filter
, L
"In", &pin
);
373 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
374 ref
= get_refcount(filter
);
375 ok(ref
== 2, "Got unexpected refcount %ld.\n", ref
);
376 ref
= get_refcount(pin
);
377 ok(ref
== 2, "Got unexpected refcount %ld.\n", ref
);
379 hr
= IPin_QueryPinInfo(pin
, &info
);
380 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
381 ok(info
.pFilter
== filter
, "Expected filter %p, got %p.\n", filter
, info
.pFilter
);
382 ok(info
.dir
== PINDIR_INPUT
, "Got direction %d.\n", info
.dir
);
383 ok(!wcscmp(info
.achName
, L
"Input"), "Got name %s.\n", debugstr_w(info
.achName
));
384 ref
= get_refcount(filter
);
385 ok(ref
== 3, "Got unexpected refcount %ld.\n", ref
);
386 ref
= get_refcount(pin
);
387 ok(ref
== 3, "Got unexpected refcount %ld.\n", ref
);
388 IBaseFilter_Release(info
.pFilter
);
390 hr
= IPin_QueryDirection(pin
, &dir
);
391 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
392 ok(dir
== PINDIR_INPUT
, "Got direction %d.\n", dir
);
394 hr
= IPin_QueryId(pin
, &id
);
395 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
396 ok(!wcscmp(id
, L
"In"), "Got id %s.\n", wine_dbgstr_w(id
));
399 hr
= IPin_QueryInternalConnections(pin
, NULL
, NULL
);
400 ok(hr
== E_NOTIMPL
, "Got hr %#lx.\n", hr
);
404 hr
= IBaseFilter_FindPin(filter
, L
"Out", &pin
);
405 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
407 check_interface(pin
, &IID_IPin
, TRUE
);
408 check_interface(pin
, &IID_IMediaSeeking
, TRUE
);
410 hr
= IPin_QueryPinInfo(pin
, &info
);
411 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
412 ok(info
.pFilter
== filter
, "Expected filter %p, got %p.\n", filter
, info
.pFilter
);
413 ok(info
.dir
== PINDIR_OUTPUT
, "Got direction %d.\n", info
.dir
);
414 ok(!wcscmp(info
.achName
, L
"Output"), "Got name %s.\n", debugstr_w(info
.achName
));
415 IBaseFilter_Release(info
.pFilter
);
417 hr
= IPin_QueryDirection(pin
, &dir
);
418 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
419 ok(dir
== PINDIR_OUTPUT
, "Got direction %d.\n", dir
);
421 hr
= IPin_QueryId(pin
, &id
);
422 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
423 ok(!wcscmp(id
, L
"Out"), "Got id %s.\n", wine_dbgstr_w(id
));
426 hr
= IPin_QueryInternalConnections(pin
, NULL
, NULL
);
427 ok(hr
== E_NOTIMPL
, "Got hr %#lx.\n", hr
);
431 ref
= IBaseFilter_Release(filter
);
432 ok(!ref
, "Got outstanding refcount %ld.\n", ref
);
435 static void test_unconnected_filter_state(void)
437 IBaseFilter
*filter
= create_acm_wrapper();
442 hr
= IBaseFilter_GetState(filter
, 0, &state
);
443 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
444 ok(state
== State_Stopped
, "Got state %u.\n", state
);
446 hr
= IBaseFilter_Pause(filter
);
447 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
449 hr
= IBaseFilter_GetState(filter
, 0, &state
);
450 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
451 ok(state
== State_Paused
, "Got state %u.\n", state
);
453 hr
= IBaseFilter_Run(filter
, 0);
454 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
456 hr
= IBaseFilter_GetState(filter
, 0, &state
);
457 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
458 ok(state
== State_Running
, "Got state %u.\n", state
);
460 hr
= IBaseFilter_Pause(filter
);
461 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
463 hr
= IBaseFilter_GetState(filter
, 0, &state
);
464 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
465 ok(state
== State_Paused
, "Got state %u.\n", state
);
467 hr
= IBaseFilter_Stop(filter
);
468 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
470 hr
= IBaseFilter_GetState(filter
, 0, &state
);
471 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
472 ok(state
== State_Stopped
, "Got state %u.\n", state
);
474 hr
= IBaseFilter_Run(filter
, 0);
475 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
477 hr
= IBaseFilter_GetState(filter
, 0, &state
);
478 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
479 ok(state
== State_Running
, "Got state %u.\n", state
);
481 hr
= IBaseFilter_Stop(filter
);
482 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
484 hr
= IBaseFilter_GetState(filter
, 0, &state
);
485 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
486 ok(state
== State_Stopped
, "Got state %u.\n", state
);
488 ref
= IBaseFilter_Release(filter
);
489 ok(!ref
, "Got outstanding refcount %ld.\n", ref
);
492 START_TEST(acmwrapper
)
501 test_unconnected_filter_state();