2 * Sample grabber 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
24 #include "wine/strmbase.h"
25 #include "wine/test.h"
27 static IBaseFilter
*create_sample_grabber(void)
29 IBaseFilter
*filter
= NULL
;
30 HRESULT hr
= CoCreateInstance(&CLSID_SampleGrabber
, NULL
, CLSCTX_INPROC_SERVER
,
31 &IID_IBaseFilter
, (void **)&filter
);
32 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
36 static ULONG
get_refcount(void *iface
)
38 IUnknown
*unknown
= iface
;
39 IUnknown_AddRef(unknown
);
40 return IUnknown_Release(unknown
);
43 static inline BOOL
compare_media_types(const AM_MEDIA_TYPE
*a
, const AM_MEDIA_TYPE
*b
)
45 return !memcmp(a
, b
, offsetof(AM_MEDIA_TYPE
, pbFormat
))
46 && !memcmp(a
->pbFormat
, b
->pbFormat
, a
->cbFormat
);
49 #define check_interface(a, b, c) check_interface_(__LINE__, a, b, c)
50 static void check_interface_(unsigned int line
, void *iface_ptr
, REFIID iid
, BOOL supported
)
52 IUnknown
*iface
= iface_ptr
;
53 HRESULT hr
, expected_hr
;
54 ULONG ref
, expect_ref
;
57 expected_hr
= supported
? S_OK
: E_NOINTERFACE
;
59 expect_ref
= get_refcount(iface
);
61 hr
= IUnknown_QueryInterface(iface
, iid
, (void **)&unk
);
62 ok_(__FILE__
, line
)(hr
== expected_hr
, "Got hr %#x, expected %#x.\n", hr
, expected_hr
);
65 ref
= get_refcount(iface
);
66 ok_(__FILE__
, line
)(ref
== expect_ref
+ 1, "Expected %u references, got %u.\n", expect_ref
+ 1, ref
);
67 ref
= get_refcount(unk
);
68 ok_(__FILE__
, line
)(ref
== expect_ref
+ 1, "Expected %u references, got %u.\n", expect_ref
+ 1, ref
);
69 IUnknown_Release(unk
);
73 static void test_interfaces(void)
75 IBaseFilter
*filter
= create_sample_grabber();
81 check_interface(filter
, &IID_IBaseFilter
, TRUE
);
82 check_interface(filter
, &IID_IMediaFilter
, TRUE
);
83 check_interface(filter
, &IID_IPersist
, TRUE
);
84 check_interface(filter
, &IID_ISampleGrabber
, TRUE
);
85 check_interface(filter
, &IID_IUnknown
, TRUE
);
87 check_interface(filter
, &IID_IAMFilterMiscFlags
, FALSE
);
88 check_interface(filter
, &IID_IBasicAudio
, FALSE
);
89 check_interface(filter
, &IID_IBasicVideo
, FALSE
);
90 check_interface(filter
, &IID_IKsPropertySet
, FALSE
);
91 check_interface(filter
, &IID_IMediaPosition
, FALSE
);
92 check_interface(filter
, &IID_IMediaSeeking
, FALSE
);
93 check_interface(filter
, &IID_IMemInputPin
, FALSE
);
94 check_interface(filter
, &IID_IPersistPropertyBag
, FALSE
);
95 check_interface(filter
, &IID_IPin
, FALSE
);
96 check_interface(filter
, &IID_IQualityControl
, FALSE
);
97 check_interface(filter
, &IID_IQualProp
, FALSE
);
98 check_interface(filter
, &IID_IReferenceClock
, FALSE
);
99 check_interface(filter
, &IID_ISeekingPassThru
, FALSE
);
100 check_interface(filter
, &IID_IVideoWindow
, FALSE
);
102 IBaseFilter_FindPin(filter
, L
"In", &pin
);
104 check_interface(pin
, &IID_IMemInputPin
, TRUE
);
105 check_interface(pin
, &IID_IPin
, TRUE
);
106 todo_wine
check_interface(pin
, &IID_IQualityControl
, TRUE
);
107 check_interface(pin
, &IID_IUnknown
, TRUE
);
109 check_interface(pin
, &IID_IKsPropertySet
, FALSE
);
110 check_interface(pin
, &IID_IMediaPosition
, FALSE
);
111 check_interface(pin
, &IID_IMediaSeeking
, FALSE
);
115 IBaseFilter_FindPin(filter
, L
"Out", &pin
);
117 /* Queries for IMediaPosition or IMediaSeeking do not seem to increase the
118 * reference count. */
119 hr
= IPin_QueryInterface(pin
, &IID_IMediaPosition
, (void **)&unk
);
120 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
121 IUnknown_Release(unk
);
122 hr
= IPin_QueryInterface(pin
, &IID_IMediaSeeking
, (void **)&unk
);
123 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
124 IUnknown_Release(unk
);
125 check_interface(pin
, &IID_IPin
, TRUE
);
126 todo_wine
check_interface(pin
, &IID_IQualityControl
, TRUE
);
127 check_interface(pin
, &IID_IUnknown
, TRUE
);
129 check_interface(pin
, &IID_IAsyncReader
, FALSE
);
130 check_interface(pin
, &IID_IKsPropertySet
, FALSE
);
131 check_interface(pin
, &IID_IMemInputPin
, FALSE
);
135 ref
= IBaseFilter_Release(filter
);
136 ok(!ref
, "Got unexpected refcount %d.\n", ref
);
139 static void test_enum_pins(void)
141 IBaseFilter
*filter
= create_sample_grabber();
142 IEnumPins
*enum1
, *enum2
;
147 ref
= get_refcount(filter
);
148 ok(ref
== 1, "Got unexpected refcount %d.\n", ref
);
150 hr
= IBaseFilter_EnumPins(filter
, NULL
);
151 ok(hr
== E_POINTER
, "Got hr %#x.\n", hr
);
153 hr
= IBaseFilter_EnumPins(filter
, &enum1
);
154 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
155 ref
= get_refcount(filter
);
156 ok(ref
== 2, "Got unexpected refcount %d.\n", ref
);
157 ref
= get_refcount(enum1
);
158 ok(ref
== 1, "Got unexpected refcount %d.\n", ref
);
160 hr
= IEnumPins_Next(enum1
, 1, NULL
, NULL
);
161 ok(hr
== E_POINTER
, "Got hr %#x.\n", hr
);
163 hr
= IEnumPins_Next(enum1
, 1, pins
, NULL
);
164 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
165 ref
= get_refcount(filter
);
166 ok(ref
== 3, "Got unexpected refcount %d.\n", ref
);
167 ref
= get_refcount(pins
[0]);
168 ok(ref
== 3, "Got unexpected refcount %d.\n", ref
);
169 ref
= get_refcount(enum1
);
170 ok(ref
== 1, "Got unexpected refcount %d.\n", ref
);
171 IPin_Release(pins
[0]);
172 ref
= get_refcount(filter
);
173 ok(ref
== 2, "Got unexpected refcount %d.\n", ref
);
175 hr
= IEnumPins_Next(enum1
, 1, pins
, NULL
);
176 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
177 ref
= get_refcount(filter
);
178 ok(ref
== 3, "Got unexpected refcount %d.\n", ref
);
179 ref
= get_refcount(pins
[0]);
180 ok(ref
== 3, "Got unexpected refcount %d.\n", ref
);
181 ref
= get_refcount(enum1
);
182 ok(ref
== 1, "Got unexpected refcount %d.\n", ref
);
183 IPin_Release(pins
[0]);
184 ref
= get_refcount(filter
);
185 ok(ref
== 2, "Got unexpected refcount %d.\n", ref
);
187 hr
= IEnumPins_Next(enum1
, 1, pins
, NULL
);
188 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
190 hr
= IEnumPins_Reset(enum1
);
191 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
193 hr
= IEnumPins_Next(enum1
, 1, pins
, &count
);
194 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
195 ok(count
== 1, "Got count %u.\n", count
);
196 IPin_Release(pins
[0]);
198 hr
= IEnumPins_Next(enum1
, 1, pins
, &count
);
199 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
200 ok(count
== 1, "Got count %u.\n", count
);
201 IPin_Release(pins
[0]);
203 hr
= IEnumPins_Next(enum1
, 1, pins
, &count
);
204 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
205 ok(!count
, "Got count %u.\n", count
);
207 hr
= IEnumPins_Reset(enum1
);
208 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
210 hr
= IEnumPins_Next(enum1
, 2, pins
, NULL
);
211 ok(hr
== E_INVALIDARG
, "Got hr %#x.\n", hr
);
213 hr
= IEnumPins_Next(enum1
, 2, pins
, &count
);
214 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
215 ok(count
== 2, "Got count %u.\n", count
);
216 IPin_Release(pins
[0]);
217 IPin_Release(pins
[1]);
219 hr
= IEnumPins_Next(enum1
, 2, pins
, &count
);
220 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
221 ok(!count
, "Got count %u.\n", count
);
223 hr
= IEnumPins_Reset(enum1
);
224 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
226 hr
= IEnumPins_Next(enum1
, 3, pins
, &count
);
227 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
228 ok(count
== 2, "Got count %u.\n", count
);
229 IPin_Release(pins
[0]);
230 IPin_Release(pins
[1]);
232 hr
= IEnumPins_Reset(enum1
);
233 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
235 hr
= IEnumPins_Clone(enum1
, &enum2
);
236 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
238 hr
= IEnumPins_Skip(enum1
, 3);
239 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
241 hr
= IEnumPins_Skip(enum1
, 2);
242 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
244 hr
= IEnumPins_Skip(enum1
, 1);
245 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
247 hr
= IEnumPins_Next(enum1
, 1, pins
, NULL
);
248 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
250 hr
= IEnumPins_Next(enum2
, 1, pins
, NULL
);
251 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
252 IPin_Release(pins
[0]);
254 IEnumPins_Release(enum2
);
255 IEnumPins_Release(enum1
);
256 ref
= IBaseFilter_Release(filter
);
257 ok(!ref
, "Got outstanding refcount %d.\n", ref
);
260 static void test_find_pin(void)
262 IBaseFilter
*filter
= create_sample_grabber();
263 IEnumPins
*enum_pins
;
268 hr
= IBaseFilter_FindPin(filter
, L
"Input", &pin
);
269 ok(hr
== VFW_E_NOT_FOUND
, "Got hr %#x.\n", hr
);
270 hr
= IBaseFilter_FindPin(filter
, L
"Output", &pin
);
271 ok(hr
== VFW_E_NOT_FOUND
, "Got hr %#x.\n", hr
);
273 hr
= IBaseFilter_EnumPins(filter
, &enum_pins
);
274 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
276 hr
= IBaseFilter_FindPin(filter
, L
"In", &pin
);
277 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
278 hr
= IEnumPins_Next(enum_pins
, 1, &pin2
, NULL
);
279 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
280 ok(pin2
== pin
, "Expected pin %p, got %p.\n", pin
, pin2
);
284 hr
= IBaseFilter_FindPin(filter
, L
"Out", &pin
);
285 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
286 hr
= IEnumPins_Next(enum_pins
, 1, &pin2
, NULL
);
287 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
288 ok(pin2
== pin
, "Expected pin %p, got %p.\n", pin
, pin2
);
292 IEnumPins_Release(enum_pins
);
293 ref
= IBaseFilter_Release(filter
);
294 ok(!ref
, "Got outstanding refcount %d.\n", ref
);
297 static void test_pin_info(void)
299 IBaseFilter
*filter
= create_sample_grabber();
308 hr
= IBaseFilter_FindPin(filter
, L
"In", &pin
);
309 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
311 hr
= IPin_QueryPinInfo(pin
, &info
);
312 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
313 ok(info
.pFilter
== filter
, "Expected filter %p, got %p.\n", filter
, info
.pFilter
);
314 ok(info
.dir
== PINDIR_INPUT
, "Got direction %d.\n", info
.dir
);
315 todo_wine
ok(!wcscmp(info
.achName
, L
"Input"), "Got name %s.\n", wine_dbgstr_w(info
.achName
));
316 IBaseFilter_Release(info
.pFilter
);
318 hr
= IPin_QueryDirection(pin
, &dir
);
319 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
320 ok(dir
== PINDIR_INPUT
, "Got direction %d.\n", dir
);
322 hr
= IPin_QueryId(pin
, &id
);
323 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
324 ok(!wcscmp(id
, L
"In"), "Got id %s.\n", wine_dbgstr_w(id
));
327 hr
= IPin_QueryInternalConnections(pin
, NULL
, &count
);
328 ok(hr
== E_NOTIMPL
, "Got hr %#x.\n", hr
);
332 hr
= IBaseFilter_FindPin(filter
, L
"Out", &pin
);
333 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
335 hr
= IPin_QueryPinInfo(pin
, &info
);
336 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
337 ok(info
.pFilter
== filter
, "Expected filter %p, got %p.\n", filter
, info
.pFilter
);
338 ok(info
.dir
== PINDIR_OUTPUT
, "Got direction %d.\n", info
.dir
);
339 todo_wine
ok(!wcscmp(info
.achName
, L
"Output"), "Got name %s.\n", wine_dbgstr_w(info
.achName
));
340 IBaseFilter_Release(info
.pFilter
);
342 hr
= IPin_QueryDirection(pin
, &dir
);
343 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
344 ok(dir
== PINDIR_OUTPUT
, "Got direction %d.\n", dir
);
346 hr
= IPin_QueryId(pin
, &id
);
347 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
348 ok(!wcscmp(id
, L
"Out"), "Got id %s.\n", wine_dbgstr_w(id
));
351 hr
= IPin_QueryInternalConnections(pin
, NULL
, &count
);
352 ok(hr
== E_NOTIMPL
, "Got hr %#x.\n", hr
);
356 ref
= IBaseFilter_Release(filter
);
357 ok(!ref
, "Got outstanding refcount %d.\n", ref
);
360 static const GUID test_iid
= {0x33333333};
361 static LONG outer_ref
= 1;
363 static HRESULT WINAPI
outer_QueryInterface(IUnknown
*iface
, REFIID iid
, void **out
)
365 if (IsEqualGUID(iid
, &IID_IUnknown
)
366 || IsEqualGUID(iid
, &IID_IBaseFilter
)
367 || IsEqualGUID(iid
, &test_iid
))
369 *out
= (IUnknown
*)0xdeadbeef;
372 ok(0, "unexpected call %s\n", wine_dbgstr_guid(iid
));
373 return E_NOINTERFACE
;
376 static ULONG WINAPI
outer_AddRef(IUnknown
*iface
)
378 return InterlockedIncrement(&outer_ref
);
381 static ULONG WINAPI
outer_Release(IUnknown
*iface
)
383 return InterlockedDecrement(&outer_ref
);
386 static const IUnknownVtbl outer_vtbl
=
388 outer_QueryInterface
,
393 static IUnknown test_outer
= {&outer_vtbl
};
395 static void test_aggregation(void)
397 IBaseFilter
*filter
, *filter2
;
398 IUnknown
*unk
, *unk2
;
402 filter
= (IBaseFilter
*)0xdeadbeef;
403 hr
= CoCreateInstance(&CLSID_SampleGrabber
, &test_outer
, CLSCTX_INPROC_SERVER
,
404 &IID_IBaseFilter
, (void **)&filter
);
405 ok(hr
== E_NOINTERFACE
, "Got hr %#x.\n", hr
);
406 ok(!filter
, "Got interface %p.\n", filter
);
408 hr
= CoCreateInstance(&CLSID_SampleGrabber
, &test_outer
, CLSCTX_INPROC_SERVER
,
409 &IID_IUnknown
, (void **)&unk
);
410 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
411 ok(outer_ref
== 1, "Got unexpected refcount %d.\n", outer_ref
);
412 ok(unk
!= &test_outer
, "Returned IUnknown should not be outer IUnknown.\n");
413 ref
= get_refcount(unk
);
414 ok(ref
== 1, "Got unexpected refcount %d.\n", ref
);
416 ref
= IUnknown_AddRef(unk
);
417 ok(ref
== 2, "Got unexpected refcount %d.\n", ref
);
418 ok(outer_ref
== 1, "Got unexpected refcount %d.\n", outer_ref
);
420 ref
= IUnknown_Release(unk
);
421 ok(ref
== 1, "Got unexpected refcount %d.\n", ref
);
422 ok(outer_ref
== 1, "Got unexpected refcount %d.\n", outer_ref
);
424 hr
= IUnknown_QueryInterface(unk
, &IID_IUnknown
, (void **)&unk2
);
425 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
426 ok(unk2
== unk
, "Got unexpected IUnknown %p.\n", unk2
);
427 IUnknown_Release(unk2
);
429 hr
= IUnknown_QueryInterface(unk
, &IID_IBaseFilter
, (void **)&filter
);
430 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
432 hr
= IBaseFilter_QueryInterface(filter
, &IID_IUnknown
, (void **)&unk2
);
433 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
434 ok(unk2
== (IUnknown
*)0xdeadbeef, "Got unexpected IUnknown %p.\n", unk2
);
436 hr
= IBaseFilter_QueryInterface(filter
, &IID_IBaseFilter
, (void **)&filter2
);
437 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
438 ok(filter2
== (IBaseFilter
*)0xdeadbeef, "Got unexpected IBaseFilter %p.\n", filter2
);
440 hr
= IUnknown_QueryInterface(unk
, &test_iid
, (void **)&unk2
);
441 ok(hr
== E_NOINTERFACE
, "Got hr %#x.\n", hr
);
442 ok(!unk2
, "Got unexpected IUnknown %p.\n", unk2
);
444 hr
= IBaseFilter_QueryInterface(filter
, &test_iid
, (void **)&unk2
);
445 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
446 ok(unk2
== (IUnknown
*)0xdeadbeef, "Got unexpected IUnknown %p.\n", unk2
);
448 IBaseFilter_Release(filter
);
449 ref
= IUnknown_Release(unk
);
450 ok(!ref
, "Got unexpected refcount %d.\n", ref
);
451 ok(outer_ref
== 1, "Got unexpected refcount %d.\n", outer_ref
);
454 static void test_media_types(void)
459 .majortype
= {0x111},
461 .formattype
= {0x333},
463 AM_MEDIA_TYPE match_mt
=
466 .bFixedSizeSamples
= TRUE
,
467 .bTemporalCompression
= TRUE
,
469 .formattype
= {0x789},
470 .cbFormat
= sizeof(format
),
473 IBaseFilter
*filter
= create_sample_grabber();
474 IEnumMediaTypes
*enummt
;
475 ISampleGrabber
*grabber
;
480 IBaseFilter_QueryInterface(filter
, &IID_ISampleGrabber
, (void **)&grabber
);
481 IBaseFilter_FindPin(filter
, L
"In", &sink
);
482 IBaseFilter_FindPin(filter
, L
"Out", &source
);
484 hr
= IPin_EnumMediaTypes(sink
, &enummt
);
485 ok(hr
== VFW_E_NOT_CONNECTED
, "Got hr %#x.\n", hr
);
487 hr
= IPin_EnumMediaTypes(source
, &enummt
);
488 ok(hr
== VFW_E_NOT_CONNECTED
, "Got hr %#x.\n", hr
);
490 hr
= IPin_QueryAccept(sink
, &mt
);
491 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
492 hr
= IPin_QueryAccept(source
, &mt
);
493 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
495 hr
= ISampleGrabber_SetMediaType(grabber
, &match_mt
);
496 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
498 hr
= IPin_EnumMediaTypes(sink
, &enummt
);
499 ok(hr
== VFW_E_NOT_CONNECTED
, "Got hr %#x.\n", hr
);
501 hr
= IPin_EnumMediaTypes(source
, &enummt
);
502 ok(hr
== VFW_E_NOT_CONNECTED
, "Got hr %#x.\n", hr
);
504 hr
= IPin_QueryAccept(sink
, &mt
);
505 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
506 hr
= IPin_QueryAccept(source
, &mt
);
507 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
509 match_mt
.majortype
= MEDIATYPE_Video
;
510 match_mt
.subtype
= GUID_NULL
;
511 hr
= ISampleGrabber_SetMediaType(grabber
, &match_mt
);
512 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
513 hr
= IPin_QueryAccept(sink
, &mt
);
514 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
515 hr
= IPin_QueryAccept(source
, &mt
);
516 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
518 mt
.majortype
= GUID_NULL
;
519 hr
= IPin_QueryAccept(sink
, &mt
);
520 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
521 hr
= IPin_QueryAccept(source
, &mt
);
522 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
523 mt
.majortype
= match_mt
.majortype
;
524 hr
= IPin_QueryAccept(sink
, &mt
);
525 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
526 hr
= IPin_QueryAccept(source
, &mt
);
527 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
529 match_mt
.subtype
= MEDIASUBTYPE_RGB8
;
530 match_mt
.formattype
= GUID_NULL
;
531 hr
= ISampleGrabber_SetMediaType(grabber
, &match_mt
);
532 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
533 hr
= IPin_QueryAccept(sink
, &mt
);
534 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
535 hr
= IPin_QueryAccept(source
, &mt
);
536 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
538 mt
.subtype
= GUID_NULL
;
539 hr
= IPin_QueryAccept(sink
, &mt
);
540 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
541 hr
= IPin_QueryAccept(source
, &mt
);
542 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
543 mt
.subtype
= match_mt
.subtype
;
544 hr
= IPin_QueryAccept(sink
, &mt
);
545 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
546 hr
= IPin_QueryAccept(source
, &mt
);
547 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
549 match_mt
.formattype
= FORMAT_None
;
550 hr
= ISampleGrabber_SetMediaType(grabber
, &match_mt
);
551 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
552 hr
= IPin_QueryAccept(sink
, &mt
);
553 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
554 hr
= IPin_QueryAccept(source
, &mt
);
555 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
557 mt
.formattype
= GUID_NULL
;
558 hr
= IPin_QueryAccept(sink
, &mt
);
559 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
560 hr
= IPin_QueryAccept(source
, &mt
);
561 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
562 mt
.formattype
= match_mt
.formattype
;
563 hr
= IPin_QueryAccept(sink
, &mt
);
564 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
565 hr
= IPin_QueryAccept(source
, &mt
);
566 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
569 IPin_Release(source
);
570 ISampleGrabber_Release(grabber
);
571 ref
= IBaseFilter_Release(filter
);
572 ok(!ref
, "Got outstanding refcount %d.\n", ref
);
577 struct strmbase_filter filter
;
578 struct strmbase_source source
;
579 struct strmbase_sink sink
;
580 const AM_MEDIA_TYPE
*sink_mt
;
581 AM_MEDIA_TYPE source_mt
;
582 unsigned int got_sample
, got_new_segment
, got_eos
, got_begin_flush
, got_end_flush
;
585 static inline struct testfilter
*impl_from_strmbase_filter(struct strmbase_filter
*iface
)
587 return CONTAINING_RECORD(iface
, struct testfilter
, filter
);
590 static struct strmbase_pin
*testfilter_get_pin(struct strmbase_filter
*iface
, unsigned int index
)
592 struct testfilter
*filter
= impl_from_strmbase_filter(iface
);
594 return &filter
->source
.pin
;
596 return &filter
->sink
.pin
;
600 static void testfilter_destroy(struct strmbase_filter
*iface
)
602 struct testfilter
*filter
= impl_from_strmbase_filter(iface
);
603 strmbase_source_cleanup(&filter
->source
);
604 strmbase_sink_cleanup(&filter
->sink
);
605 strmbase_filter_cleanup(&filter
->filter
);
608 static const struct strmbase_filter_ops testfilter_ops
=
610 .filter_get_pin
= testfilter_get_pin
,
611 .filter_destroy
= testfilter_destroy
,
614 static HRESULT
testsource_query_accept(struct strmbase_pin
*iface
, const AM_MEDIA_TYPE
*mt
)
616 return mt
->bTemporalCompression
? S_OK
: S_FALSE
;
619 static HRESULT
testsource_get_media_type(struct strmbase_pin
*iface
, unsigned int index
, AM_MEDIA_TYPE
*mt
)
621 struct testfilter
*filter
= impl_from_strmbase_filter(iface
->filter
);
624 CopyMediaType(mt
, &filter
->source_mt
);
627 return VFW_S_NO_MORE_ITEMS
;
630 static void test_sink_allocator(IPin
*pin
)
632 ALLOCATOR_PROPERTIES req_props
= {1, 256, 1, 0}, ret_props
;
633 IMemAllocator
*req_allocator
, *ret_allocator
;
637 IPin_QueryInterface(pin
, &IID_IMemInputPin
, (void **)&input
);
639 hr
= IMemInputPin_NotifyAllocator(input
, NULL
, TRUE
);
640 todo_wine
ok(hr
== E_POINTER
, "Got hr %#x.\n", hr
);
642 hr
= IMemInputPin_GetAllocatorRequirements(input
, &ret_props
);
643 ok(hr
== E_NOTIMPL
, "Got hr %#x.\n", hr
);
645 hr
= IMemInputPin_GetAllocator(input
, &ret_allocator
);
646 todo_wine
ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
650 hr
= IMemInputPin_NotifyAllocator(input
, ret_allocator
, TRUE
);
651 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
652 IMemAllocator_Release(ret_allocator
);
655 CoCreateInstance(&CLSID_MemoryAllocator
, NULL
, CLSCTX_INPROC_SERVER
,
656 &IID_IMemAllocator
, (void **)&req_allocator
);
658 hr
= IMemInputPin_NotifyAllocator(input
, req_allocator
, TRUE
);
659 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
661 hr
= IMemInputPin_GetAllocator(input
, &ret_allocator
);
662 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
663 ok(ret_allocator
== req_allocator
, "Allocators didn't match.\n");
664 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
665 IMemAllocator_Release(ret_allocator
);
667 hr
= IMemAllocator_SetProperties(req_allocator
, &req_props
, &ret_props
);
668 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
670 IMemAllocator_Release(req_allocator
);
671 IMemInputPin_Release(input
);
674 static HRESULT WINAPI
testsource_AttemptConnection(struct strmbase_source
*iface
,
675 IPin
*peer
, const AM_MEDIA_TYPE
*mt
)
679 iface
->pin
.peer
= peer
;
681 CopyMediaType(&iface
->pin
.mt
, mt
);
683 if (FAILED(hr
= IPin_ReceiveConnection(peer
, &iface
->pin
.IPin_iface
, mt
)))
685 ok(hr
== VFW_E_TYPE_NOT_ACCEPTED
, "Got hr %#x.\n", hr
);
687 iface
->pin
.peer
= NULL
;
688 FreeMediaType(&iface
->pin
.mt
);
691 test_sink_allocator(peer
);
696 static const struct strmbase_source_ops testsource_ops
=
698 .base
.pin_query_accept
= testsource_query_accept
,
699 .base
.pin_get_media_type
= testsource_get_media_type
,
700 .pfnAttemptConnection
= testsource_AttemptConnection
,
703 static HRESULT
testsink_query_interface(struct strmbase_pin
*iface
, REFIID iid
, void **out
)
705 struct testfilter
*filter
= impl_from_strmbase_filter(iface
->filter
);
707 if (IsEqualGUID(iid
, &IID_IMemInputPin
))
708 *out
= &filter
->sink
.IMemInputPin_iface
;
710 return E_NOINTERFACE
;
712 IUnknown_AddRef((IUnknown
*)*out
);
716 static HRESULT
testsink_query_accept(struct strmbase_pin
*iface
, const AM_MEDIA_TYPE
*mt
)
718 struct testfilter
*filter
= impl_from_strmbase_filter(iface
->filter
);
719 if (filter
->sink_mt
&& !compare_media_types(mt
, filter
->sink_mt
))
724 static HRESULT
testsink_get_media_type(struct strmbase_pin
*iface
, unsigned int index
, AM_MEDIA_TYPE
*mt
)
726 struct testfilter
*filter
= impl_from_strmbase_filter(iface
->filter
);
727 if (!index
&& filter
->sink_mt
)
729 CopyMediaType(mt
, filter
->sink_mt
);
732 return VFW_S_NO_MORE_ITEMS
;
735 static HRESULT WINAPI
testsink_Receive(struct strmbase_sink
*iface
, IMediaSample
*sample
)
737 struct testfilter
*filter
= impl_from_strmbase_filter(iface
->pin
.filter
);
738 REFERENCE_TIME start
, stop
;
739 BYTE
*data
, expect
[200];
743 size
= IMediaSample_GetSize(sample
);
744 ok(size
== 256, "Got size %u.\n", size
);
745 size
= IMediaSample_GetActualDataLength(sample
);
746 ok(size
== 200, "Got valid size %u.\n", size
);
748 hr
= IMediaSample_GetPointer(sample
, &data
);
749 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
750 for (i
= 0; i
< size
; ++i
)
752 ok(!memcmp(data
, expect
, size
), "Data didn't match.\n");
754 hr
= IMediaSample_GetTime(sample
, &start
, &stop
);
755 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
756 ok(start
== 30000, "Got start time %s.\n", wine_dbgstr_longlong(start
));
757 ok(stop
== 40000, "Got stop time %s.\n", wine_dbgstr_longlong(stop
));
759 hr
= IMediaSample_GetMediaTime(sample
, &start
, &stop
);
760 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
761 ok(start
== 10000, "Got start time %s.\n", wine_dbgstr_longlong(start
));
762 ok(stop
== 20000, "Got stop time %s.\n", wine_dbgstr_longlong(stop
));
764 hr
= IMediaSample_IsDiscontinuity(sample
);
765 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
766 hr
= IMediaSample_IsPreroll(sample
);
767 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
768 hr
= IMediaSample_IsSyncPoint(sample
);
769 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
771 ++filter
->got_sample
;
776 static HRESULT
testsink_new_segment(struct strmbase_sink
*iface
,
777 REFERENCE_TIME start
, REFERENCE_TIME stop
, double rate
)
779 struct testfilter
*filter
= impl_from_strmbase_filter(iface
->pin
.filter
);
780 ++filter
->got_new_segment
;
781 ok(start
== 10000, "Got start %s.\n", wine_dbgstr_longlong(start
));
782 ok(stop
== 20000, "Got stop %s.\n", wine_dbgstr_longlong(stop
));
783 ok(rate
== 1.0, "Got rate %.16e.\n", rate
);
787 static HRESULT
testsink_eos(struct strmbase_sink
*iface
)
789 struct testfilter
*filter
= impl_from_strmbase_filter(iface
->pin
.filter
);
794 static HRESULT
testsink_begin_flush(struct strmbase_sink
*iface
)
796 struct testfilter
*filter
= impl_from_strmbase_filter(iface
->pin
.filter
);
797 ++filter
->got_begin_flush
;
801 static HRESULT
testsink_end_flush(struct strmbase_sink
*iface
)
803 struct testfilter
*filter
= impl_from_strmbase_filter(iface
->pin
.filter
);
804 ++filter
->got_end_flush
;
808 static const struct strmbase_sink_ops testsink_ops
=
810 .base
.pin_query_interface
= testsink_query_interface
,
811 .base
.pin_query_accept
= testsink_query_accept
,
812 .base
.pin_get_media_type
= testsink_get_media_type
,
813 .pfnReceive
= testsink_Receive
,
814 .sink_new_segment
= testsink_new_segment
,
815 .sink_eos
= testsink_eos
,
816 .sink_begin_flush
= testsink_begin_flush
,
817 .sink_end_flush
= testsink_end_flush
,
820 static void testfilter_init(struct testfilter
*filter
)
822 static const GUID clsid
= {0xabacab};
823 memset(filter
, 0, sizeof(*filter
));
824 strmbase_filter_init(&filter
->filter
, NULL
, &clsid
, &testfilter_ops
);
825 strmbase_source_init(&filter
->source
, &filter
->filter
, L
"source", &testsource_ops
);
826 strmbase_sink_init(&filter
->sink
, &filter
->filter
, L
"sink", &testsink_ops
, NULL
);
829 static void test_sample_processing(IMediaControl
*control
, IMemInputPin
*input
, struct testfilter
*sink
)
831 REFERENCE_TIME start
, stop
;
832 IMemAllocator
*allocator
;
833 IMediaSample
*sample
;
838 hr
= IMemInputPin_ReceiveCanBlock(input
);
839 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
841 hr
= IMemInputPin_GetAllocator(input
, &allocator
);
842 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
844 hr
= IMemAllocator_GetBuffer(allocator
, &sample
, NULL
, NULL
, 0);
845 ok(hr
== VFW_E_NOT_COMMITTED
, "Got hr %#x.\n", hr
);
847 hr
= IMediaControl_Pause(control
);
848 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
850 hr
= IMemAllocator_GetBuffer(allocator
, &sample
, NULL
, NULL
, 0);
851 todo_wine
ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
854 IMemAllocator_Commit(allocator
);
855 hr
= IMemAllocator_GetBuffer(allocator
, &sample
, NULL
, NULL
, 0);
856 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
859 hr
= IMediaSample_GetPointer(sample
, &data
);
860 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
861 size
= IMediaSample_GetSize(sample
);
862 ok(size
== 256, "Got size %d.\n", size
);
863 for (i
= 0; i
< 200; ++i
)
865 hr
= IMediaSample_SetActualDataLength(sample
, 200);
866 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
870 hr
= IMediaSample_SetMediaTime(sample
, &start
, &stop
);
871 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
874 hr
= IMediaSample_SetTime(sample
, &start
, &stop
);
875 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
876 hr
= IMediaSample_SetDiscontinuity(sample
, TRUE
);
877 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
878 hr
= IMediaSample_SetSyncPoint(sample
, TRUE
);
879 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
881 hr
= IMemInputPin_Receive(input
, sample
);
882 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
883 ok(sink
->got_sample
== 1, "Got %u calls to Receive().\n", sink
->got_sample
);
884 sink
->got_sample
= 0;
886 hr
= IMediaControl_Stop(control
);
887 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
889 hr
= IMemInputPin_Receive(input
, sample
);
890 todo_wine
ok(hr
== VFW_E_WRONG_STATE
, "Got hr %#x.\n", hr
);
892 IMediaSample_Release(sample
);
893 IMemAllocator_Release(allocator
);
896 static void test_streaming_events(IMediaControl
*control
, IPin
*sink
,
897 IMemInputPin
*input
, struct testfilter
*testsink
)
899 REFERENCE_TIME start
, stop
;
900 IMemAllocator
*allocator
;
901 IMediaSample
*sample
;
906 hr
= IMediaControl_Pause(control
);
907 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
909 hr
= IMemInputPin_GetAllocator(input
, &allocator
);
910 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
911 hr
= IMemAllocator_GetBuffer(allocator
, &sample
, NULL
, NULL
, 0);
912 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
913 hr
= IMediaSample_GetPointer(sample
, &data
);
914 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
915 for (i
= 0; i
< 200; ++i
)
917 hr
= IMediaSample_SetActualDataLength(sample
, 200);
918 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
921 hr
= IMediaSample_SetMediaTime(sample
, &start
, &stop
);
922 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
925 hr
= IMediaSample_SetTime(sample
, &start
, &stop
);
926 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
927 hr
= IMediaSample_SetDiscontinuity(sample
, TRUE
);
928 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
929 hr
= IMediaSample_SetSyncPoint(sample
, TRUE
);
930 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
932 ok(!testsink
->got_new_segment
, "Got %u calls to IPin::NewSegment().\n", testsink
->got_new_segment
);
933 hr
= IPin_NewSegment(sink
, 10000, 20000, 1.0);
934 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
935 ok(testsink
->got_new_segment
== 1, "Got %u calls to IPin::NewSegment().\n", testsink
->got_new_segment
);
937 ok(!testsink
->got_eos
, "Got %u calls to IPin::EndOfStream().\n", testsink
->got_eos
);
938 hr
= IPin_EndOfStream(sink
);
939 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
940 todo_wine
ok(!testsink
->got_sample
, "Got %u calls to Receive().\n", testsink
->got_sample
);
941 ok(testsink
->got_eos
== 1, "Got %u calls to IPin::EndOfStream().\n", testsink
->got_eos
);
942 testsink
->got_eos
= 0;
944 hr
= IPin_EndOfStream(sink
);
945 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
946 ok(testsink
->got_eos
== 1, "Got %u calls to IPin::EndOfStream().\n", testsink
->got_eos
);
947 testsink
->got_eos
= 0;
949 hr
= IMemInputPin_Receive(input
, sample
);
950 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
951 todo_wine
ok(testsink
->got_sample
== 1, "Got %u calls to Receive().\n", testsink
->got_sample
);
952 testsink
->got_sample
= 0;
954 ok(!testsink
->got_begin_flush
, "Got %u calls to IPin::BeginFlush().\n", testsink
->got_begin_flush
);
955 hr
= IPin_BeginFlush(sink
);
956 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
957 ok(testsink
->got_begin_flush
== 1, "Got %u calls to IPin::BeginFlush().\n", testsink
->got_begin_flush
);
959 hr
= IMemInputPin_Receive(input
, sample
);
960 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
961 ok(testsink
->got_sample
== 1, "Got %u calls to Receive().\n", testsink
->got_sample
);
962 testsink
->got_sample
= 0;
964 hr
= IPin_EndOfStream(sink
);
965 todo_wine
ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
966 todo_wine
ok(testsink
->got_eos
== 1, "Got %u calls to IPin::EndOfStream().\n", testsink
->got_eos
);
967 testsink
->got_eos
= 0;
969 ok(!testsink
->got_end_flush
, "Got %u calls to IPin::EndFlush().\n", testsink
->got_end_flush
);
970 hr
= IPin_EndFlush(sink
);
971 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
972 ok(testsink
->got_end_flush
== 1, "Got %u calls to IPin::EndFlush().\n", testsink
->got_end_flush
);
974 hr
= IMemInputPin_Receive(input
, sample
);
975 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
976 ok(testsink
->got_sample
== 1, "Got %u calls to Receive().\n", testsink
->got_sample
);
977 testsink
->got_sample
= 0;
979 hr
= IMediaControl_Stop(control
);
980 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
981 IMediaSample_Release(sample
);
982 IMemAllocator_Release(allocator
);
985 static void test_connect_pin(void)
987 AM_MEDIA_TYPE req_mt
=
989 .majortype
= MEDIATYPE_Stream
,
990 .subtype
= MEDIASUBTYPE_Avi
,
991 .formattype
= FORMAT_None
,
993 IBaseFilter
*filter
= create_sample_grabber();
994 struct testfilter testsource
, testsink
;
995 IPin
*sink
, *source
, *peer
;
996 IEnumMediaTypes
*enummt
;
997 ISampleGrabber
*grabber
;
998 IMediaControl
*control
;
999 AM_MEDIA_TYPE mt
, *pmt
;
1000 IFilterGraph2
*graph
;
1001 IMemInputPin
*input
;
1005 testfilter_init(&testsource
);
1006 testfilter_init(&testsink
);
1007 CoCreateInstance(&CLSID_FilterGraph
, NULL
, CLSCTX_INPROC_SERVER
,
1008 &IID_IFilterGraph2
, (void **)&graph
);
1009 IFilterGraph2_AddFilter(graph
, &testsource
.filter
.IBaseFilter_iface
, L
"source");
1010 IFilterGraph2_AddFilter(graph
, &testsink
.filter
.IBaseFilter_iface
, L
"sink");
1011 IFilterGraph2_AddFilter(graph
, filter
, L
"sample grabber");
1012 IFilterGraph2_QueryInterface(graph
, &IID_IMediaControl
, (void **)&control
);
1013 IBaseFilter_FindPin(filter
, L
"In", &sink
);
1014 IPin_QueryInterface(sink
, &IID_IMemInputPin
, (void **)&input
);
1015 IBaseFilter_FindPin(filter
, L
"Out", &source
);
1016 IBaseFilter_QueryInterface(filter
, &IID_ISampleGrabber
, (void **)&grabber
);
1018 testsource
.source_mt
.majortype
= MEDIATYPE_Video
;
1019 testsource
.source_mt
.subtype
= MEDIASUBTYPE_RGB8
;
1020 testsource
.source_mt
.formattype
= FORMAT_VideoInfo
;
1022 hr
= ISampleGrabber_GetConnectedMediaType(grabber
, &mt
);
1023 ok(hr
== VFW_E_NOT_CONNECTED
, "Got hr %#x.\n", hr
);
1025 /* Test sink connection. */
1027 peer
= (IPin
*)0xdeadbeef;
1028 hr
= IPin_ConnectedTo(sink
, &peer
);
1029 ok(hr
== VFW_E_NOT_CONNECTED
, "Got hr %#x.\n", hr
);
1030 ok(!peer
, "Got peer %p.\n", peer
);
1032 hr
= IPin_ConnectionMediaType(sink
, &mt
);
1033 ok(hr
== VFW_E_NOT_CONNECTED
, "Got hr %#x.\n", hr
);
1035 hr
= IMediaControl_Pause(control
);
1036 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1037 hr
= IFilterGraph2_ConnectDirect(graph
, &testsource
.source
.pin
.IPin_iface
, sink
, &req_mt
);
1038 ok(hr
== VFW_E_NOT_STOPPED
, "Got hr %#x.\n", hr
);
1039 hr
= IMediaControl_Stop(control
);
1040 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1042 hr
= IFilterGraph2_ConnectDirect(graph
, &testsource
.source
.pin
.IPin_iface
, sink
, &req_mt
);
1043 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1045 hr
= IPin_ConnectedTo(sink
, &peer
);
1046 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1047 ok(peer
== &testsource
.source
.pin
.IPin_iface
, "Got peer %p.\n", peer
);
1050 hr
= IPin_ConnectionMediaType(sink
, &mt
);
1051 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1052 ok(compare_media_types(&mt
, &req_mt
), "Media types didn't match.\n");
1054 hr
= IMediaControl_Pause(control
);
1055 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1056 hr
= IFilterGraph2_Disconnect(graph
, sink
);
1057 ok(hr
== VFW_E_NOT_STOPPED
, "Got hr %#x.\n", hr
);
1058 hr
= IMediaControl_Stop(control
);
1059 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1061 hr
= ISampleGrabber_GetConnectedMediaType(grabber
, NULL
);
1062 ok(hr
== E_POINTER
, "Got hr %#x.\n", hr
);
1064 hr
= ISampleGrabber_GetConnectedMediaType(grabber
, &mt
);
1065 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1066 ok(compare_media_types(&mt
, &req_mt
), "Media types didn't match.\n");
1068 hr
= IPin_EnumMediaTypes(sink
, &enummt
);
1069 ok(hr
== VFW_E_NOT_CONNECTED
, "Got hr %#x.\n", hr
);
1070 hr
= IPin_EnumMediaTypes(source
, &enummt
);
1071 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1072 hr
= IEnumMediaTypes_Next(enummt
, 1, &pmt
, NULL
);
1073 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1074 ok(compare_media_types(pmt
, &testsource
.source_mt
), "Media types didn't match.\n");
1075 IEnumMediaTypes_Release(enummt
);
1077 req_mt
.majortype
= MEDIATYPE_Video
;
1078 req_mt
.subtype
= MEDIASUBTYPE_RGB8
;
1079 req_mt
.formattype
= FORMAT_VideoInfo
;
1080 hr
= IPin_QueryAccept(sink
, &req_mt
);
1081 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1082 hr
= IPin_QueryAccept(source
, &req_mt
);
1083 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
1084 req_mt
.bTemporalCompression
= TRUE
;
1085 hr
= IPin_QueryAccept(source
, &req_mt
);
1086 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1088 memset(&mt
, 0, sizeof(AM_MEDIA_TYPE
));
1089 mt
.majortype
= MEDIATYPE_Midi
;
1090 hr
= ISampleGrabber_SetMediaType(grabber
, &mt
);
1091 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1093 hr
= IPin_QueryAccept(source
, &req_mt
);
1094 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
1096 req_mt
.majortype
= MEDIATYPE_Midi
;
1097 req_mt
.bTemporalCompression
= FALSE
;
1098 hr
= IPin_QueryAccept(source
, &req_mt
);
1099 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
1101 req_mt
.bTemporalCompression
= TRUE
;
1102 hr
= IPin_QueryAccept(source
, &req_mt
);
1103 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1105 memset(&mt
, 0, sizeof(AM_MEDIA_TYPE
));
1106 hr
= ISampleGrabber_SetMediaType(grabber
, &mt
);
1107 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1109 /* Test source connection. */
1111 peer
= (IPin
*)0xdeadbeef;
1112 hr
= IPin_ConnectedTo(source
, &peer
);
1113 ok(hr
== VFW_E_NOT_CONNECTED
, "Got hr %#x.\n", hr
);
1114 ok(!peer
, "Got peer %p.\n", peer
);
1116 hr
= IPin_ConnectionMediaType(source
, &mt
);
1117 ok(hr
== VFW_E_NOT_CONNECTED
, "Got hr %#x.\n", hr
);
1119 /* Exact connection. */
1121 hr
= IMediaControl_Pause(control
);
1122 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1123 hr
= IFilterGraph2_ConnectDirect(graph
, source
, &testsink
.sink
.pin
.IPin_iface
, &req_mt
);
1124 ok(hr
== VFW_E_NOT_STOPPED
, "Got hr %#x.\n", hr
);
1125 hr
= IMediaControl_Stop(control
);
1126 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1128 req_mt
.bTemporalCompression
= FALSE
;
1129 hr
= IFilterGraph2_ConnectDirect(graph
, source
, &testsink
.sink
.pin
.IPin_iface
, &req_mt
);
1130 ok(hr
== VFW_E_TYPE_NOT_ACCEPTED
, "Got hr %#x.\n", hr
);
1132 req_mt
.bTemporalCompression
= TRUE
;
1133 hr
= IFilterGraph2_ConnectDirect(graph
, source
, &testsink
.sink
.pin
.IPin_iface
, &req_mt
);
1134 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1136 hr
= IPin_ConnectedTo(source
, &peer
);
1137 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1138 ok(peer
== &testsink
.sink
.pin
.IPin_iface
, "Got peer %p.\n", peer
);
1141 hr
= IPin_ConnectionMediaType(source
, &mt
);
1142 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1143 ok(compare_media_types(&mt
, &req_mt
), "Media types didn't match.\n");
1144 ok(compare_media_types(&testsink
.sink
.pin
.mt
, &req_mt
), "Media types didn't match.\n");
1145 ok(compare_media_types(&testsource
.source
.pin
.mt
, &testsink
.sink
.pin
.mt
), "Media types didn't match.\n");
1147 test_sample_processing(control
, input
, &testsink
);
1148 test_streaming_events(control
, sink
, input
, &testsink
);
1150 hr
= IMediaControl_Pause(control
);
1151 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1152 hr
= IFilterGraph2_Disconnect(graph
, source
);
1153 ok(hr
== VFW_E_NOT_STOPPED
, "Got hr %#x.\n", hr
);
1154 hr
= IMediaControl_Stop(control
);
1155 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1157 hr
= IFilterGraph2_Disconnect(graph
, source
);
1158 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1159 hr
= IFilterGraph2_Disconnect(graph
, source
);
1160 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
1161 ok(testsink
.sink
.pin
.peer
== source
, "Got peer %p.\n", testsink
.sink
.pin
.peer
);
1162 IFilterGraph2_Disconnect(graph
, &testsink
.sink
.pin
.IPin_iface
);
1164 /* Connection with wildcards. */
1166 hr
= IFilterGraph2_ConnectDirect(graph
, source
, &testsink
.sink
.pin
.IPin_iface
, NULL
);
1167 ok(hr
== VFW_E_NO_ACCEPTABLE_TYPES
, "Got hr %#x.\n", hr
);
1169 testsource
.source_mt
.bTemporalCompression
= TRUE
;
1170 hr
= IFilterGraph2_ConnectDirect(graph
, source
, &testsink
.sink
.pin
.IPin_iface
, NULL
);
1171 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1172 ok(compare_media_types(&testsink
.sink
.pin
.mt
, &testsource
.source_mt
), "Media types didn't match.\n");
1173 ok(compare_media_types(&testsource
.source
.pin
.mt
, &testsink
.sink
.pin
.mt
), "Media types didn't match.\n");
1174 IFilterGraph2_Disconnect(graph
, source
);
1175 IFilterGraph2_Disconnect(graph
, &testsink
.sink
.pin
.IPin_iface
);
1177 req_mt
.majortype
= GUID_NULL
;
1178 req_mt
.bTemporalCompression
= FALSE
;
1179 hr
= IFilterGraph2_ConnectDirect(graph
, source
, &testsink
.sink
.pin
.IPin_iface
, &req_mt
);
1180 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1181 ok(compare_media_types(&testsink
.sink
.pin
.mt
, &testsource
.source_mt
), "Media types didn't match.\n");
1182 ok(compare_media_types(&testsource
.source
.pin
.mt
, &testsink
.sink
.pin
.mt
), "Media types didn't match.\n");
1183 IFilterGraph2_Disconnect(graph
, source
);
1184 IFilterGraph2_Disconnect(graph
, &testsink
.sink
.pin
.IPin_iface
);
1186 req_mt
.subtype
= MEDIASUBTYPE_RGB32
;
1187 hr
= IFilterGraph2_ConnectDirect(graph
, source
, &testsink
.sink
.pin
.IPin_iface
, &req_mt
);
1188 ok(hr
== VFW_E_NO_ACCEPTABLE_TYPES
, "Got hr %#x.\n", hr
);
1190 req_mt
.subtype
= GUID_NULL
;
1191 hr
= IFilterGraph2_ConnectDirect(graph
, source
, &testsink
.sink
.pin
.IPin_iface
, &req_mt
);
1192 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1193 ok(compare_media_types(&testsink
.sink
.pin
.mt
, &testsource
.source_mt
), "Media types didn't match.\n");
1194 ok(compare_media_types(&testsource
.source
.pin
.mt
, &testsink
.sink
.pin
.mt
), "Media types didn't match.\n");
1195 IFilterGraph2_Disconnect(graph
, source
);
1196 IFilterGraph2_Disconnect(graph
, &testsink
.sink
.pin
.IPin_iface
);
1198 req_mt
.formattype
= FORMAT_None
;
1199 hr
= IFilterGraph2_ConnectDirect(graph
, source
, &testsink
.sink
.pin
.IPin_iface
, &req_mt
);
1200 ok(hr
== VFW_E_NO_ACCEPTABLE_TYPES
, "Got hr %#x.\n", hr
);
1202 req_mt
.majortype
= MEDIATYPE_Video
;
1203 req_mt
.subtype
= MEDIASUBTYPE_RGB8
;
1204 req_mt
.formattype
= GUID_NULL
;
1205 hr
= IFilterGraph2_ConnectDirect(graph
, source
, &testsink
.sink
.pin
.IPin_iface
, &req_mt
);
1206 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1207 ok(compare_media_types(&testsink
.sink
.pin
.mt
, &testsource
.source_mt
), "Media types didn't match.\n");
1208 ok(compare_media_types(&testsource
.source
.pin
.mt
, &testsink
.sink
.pin
.mt
), "Media types didn't match.\n");
1209 IFilterGraph2_Disconnect(graph
, source
);
1210 IFilterGraph2_Disconnect(graph
, &testsink
.sink
.pin
.IPin_iface
);
1212 req_mt
.subtype
= MEDIASUBTYPE_RGB32
;
1213 hr
= IFilterGraph2_ConnectDirect(graph
, source
, &testsink
.sink
.pin
.IPin_iface
, &req_mt
);
1214 ok(hr
== VFW_E_NO_ACCEPTABLE_TYPES
, "Got hr %#x.\n", hr
);
1216 req_mt
.subtype
= GUID_NULL
;
1217 hr
= IFilterGraph2_ConnectDirect(graph
, source
, &testsink
.sink
.pin
.IPin_iface
, &req_mt
);
1218 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1219 ok(compare_media_types(&testsink
.sink
.pin
.mt
, &testsource
.source_mt
), "Media types didn't match.\n");
1220 ok(compare_media_types(&testsource
.source
.pin
.mt
, &testsink
.sink
.pin
.mt
), "Media types didn't match.\n");
1221 IFilterGraph2_Disconnect(graph
, source
);
1222 IFilterGraph2_Disconnect(graph
, &testsink
.sink
.pin
.IPin_iface
);
1224 req_mt
.majortype
= MEDIATYPE_Audio
;
1225 hr
= IFilterGraph2_ConnectDirect(graph
, source
, &testsink
.sink
.pin
.IPin_iface
, &req_mt
);
1226 ok(hr
== VFW_E_NO_ACCEPTABLE_TYPES
, "Got hr %#x.\n", hr
);
1228 testsource
.source_mt
.majortype
= testsource
.source_mt
.subtype
= testsource
.source_mt
.formattype
= GUID_NULL
;
1229 req_mt
.majortype
= req_mt
.subtype
= req_mt
.formattype
= GUID_NULL
;
1230 hr
= IFilterGraph2_ConnectDirect(graph
, source
, &testsink
.sink
.pin
.IPin_iface
, &req_mt
);
1231 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1232 ok(compare_media_types(&testsink
.sink
.pin
.mt
, &testsource
.source_mt
), "Media types didn't match.\n");
1233 ok(compare_media_types(&testsource
.source
.pin
.mt
, &testsink
.sink
.pin
.mt
), "Media types didn't match.\n");
1234 IFilterGraph2_Disconnect(graph
, source
);
1235 IFilterGraph2_Disconnect(graph
, &testsink
.sink
.pin
.IPin_iface
);
1237 req_mt
.majortype
= MEDIATYPE_Video
;
1238 hr
= IFilterGraph2_ConnectDirect(graph
, source
, &testsink
.sink
.pin
.IPin_iface
, &req_mt
);
1239 ok(hr
== VFW_E_NO_ACCEPTABLE_TYPES
, "Got hr %#x.\n", hr
);
1240 req_mt
.majortype
= GUID_NULL
;
1242 req_mt
.subtype
= MEDIASUBTYPE_RGB8
;
1243 hr
= IFilterGraph2_ConnectDirect(graph
, source
, &testsink
.sink
.pin
.IPin_iface
, &req_mt
);
1244 ok(hr
== VFW_E_NO_ACCEPTABLE_TYPES
, "Got hr %#x.\n", hr
);
1245 req_mt
.subtype
= GUID_NULL
;
1247 req_mt
.formattype
= FORMAT_None
;
1248 hr
= IFilterGraph2_ConnectDirect(graph
, source
, &testsink
.sink
.pin
.IPin_iface
, &req_mt
);
1249 ok(hr
== VFW_E_NO_ACCEPTABLE_TYPES
, "Got hr %#x.\n", hr
);
1250 req_mt
.formattype
= GUID_NULL
;
1252 testsink
.sink_mt
= &req_mt
;
1253 hr
= IFilterGraph2_ConnectDirect(graph
, source
, &testsink
.sink
.pin
.IPin_iface
, NULL
);
1254 ok(hr
== VFW_E_NO_ACCEPTABLE_TYPES
, "Got hr %#x.\n", hr
);
1256 req_mt
.bTemporalCompression
= TRUE
;
1257 hr
= IFilterGraph2_ConnectDirect(graph
, source
, &testsink
.sink
.pin
.IPin_iface
, NULL
);
1258 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1259 ok(compare_media_types(&testsink
.sink
.pin
.mt
, &req_mt
), "Media types didn't match.\n");
1260 ok(compare_media_types(&testsource
.source
.pin
.mt
, &testsink
.sink
.pin
.mt
), "Media types didn't match.\n");
1262 hr
= IPin_EnumMediaTypes(sink
, &enummt
);
1263 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1264 hr
= IEnumMediaTypes_Next(enummt
, 1, &pmt
, NULL
);
1265 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1266 ok(compare_media_types(pmt
, testsink
.sink_mt
), "Media types didn't match.\n");
1267 IEnumMediaTypes_Release(enummt
);
1269 IFilterGraph2_Disconnect(graph
, source
);
1270 IFilterGraph2_Disconnect(graph
, &testsink
.sink
.pin
.IPin_iface
);
1272 hr
= IFilterGraph2_Disconnect(graph
, sink
);
1273 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1274 hr
= IFilterGraph2_Disconnect(graph
, sink
);
1275 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
1276 ok(testsource
.source
.pin
.peer
== sink
, "Got peer %p.\n", testsource
.source
.pin
.peer
);
1277 IFilterGraph2_Disconnect(graph
, &testsource
.source
.pin
.IPin_iface
);
1279 peer
= (IPin
*)0xdeadbeef;
1280 hr
= IPin_ConnectedTo(sink
, &peer
);
1281 ok(hr
== VFW_E_NOT_CONNECTED
, "Got hr %#x.\n", hr
);
1282 ok(!peer
, "Got peer %p.\n", peer
);
1284 hr
= IPin_ConnectionMediaType(sink
, &mt
);
1285 ok(hr
== VFW_E_NOT_CONNECTED
, "Got hr %#x.\n", hr
);
1287 IMemInputPin_Release(input
);
1289 IPin_Release(source
);
1290 IMediaControl_Release(control
);
1291 ref
= IFilterGraph2_Release(graph
);
1292 ok(!ref
, "Got outstanding refcount %d.\n", ref
);
1293 ISampleGrabber_Release(grabber
);
1294 ref
= IBaseFilter_Release(filter
);
1295 ok(!ref
, "Got outstanding refcount %d.\n", ref
);
1296 ref
= IBaseFilter_Release(&testsource
.filter
.IBaseFilter_iface
);
1297 ok(!ref
, "Got outstanding refcount %d.\n", ref
);
1298 ref
= IBaseFilter_Release(&testsink
.filter
.IBaseFilter_iface
);
1299 ok(!ref
, "Got outstanding refcount %d.\n", ref
);
1302 START_TEST(samplegrabber
)
1304 IBaseFilter
*filter
;
1309 if (FAILED(hr
= CoCreateInstance(&CLSID_SampleGrabber
, NULL
, CLSCTX_INPROC_SERVER
,
1310 &IID_IBaseFilter
, (void **)&filter
)))
1312 /* qedit.dll does not exist on 2003. */
1313 win_skip("Failed to create sample grabber filter, hr %#x.\n", hr
);
1316 IBaseFilter_Release(filter
);