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 IMemAllocator_Release(ret_allocator
);
666 hr
= IMemAllocator_SetProperties(req_allocator
, &req_props
, &ret_props
);
667 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
669 IMemAllocator_Release(req_allocator
);
670 IMemInputPin_Release(input
);
673 static HRESULT WINAPI
testsource_AttemptConnection(struct strmbase_source
*iface
,
674 IPin
*peer
, const AM_MEDIA_TYPE
*mt
)
678 iface
->pin
.peer
= peer
;
680 CopyMediaType(&iface
->pin
.mt
, mt
);
682 if (FAILED(hr
= IPin_ReceiveConnection(peer
, &iface
->pin
.IPin_iface
, mt
)))
684 ok(hr
== VFW_E_TYPE_NOT_ACCEPTED
, "Got hr %#x.\n", hr
);
686 iface
->pin
.peer
= NULL
;
687 FreeMediaType(&iface
->pin
.mt
);
690 test_sink_allocator(peer
);
695 static const struct strmbase_source_ops testsource_ops
=
697 .base
.pin_query_accept
= testsource_query_accept
,
698 .base
.pin_get_media_type
= testsource_get_media_type
,
699 .pfnAttemptConnection
= testsource_AttemptConnection
,
702 static HRESULT
testsink_query_interface(struct strmbase_pin
*iface
, REFIID iid
, void **out
)
704 struct testfilter
*filter
= impl_from_strmbase_filter(iface
->filter
);
706 if (IsEqualGUID(iid
, &IID_IMemInputPin
))
707 *out
= &filter
->sink
.IMemInputPin_iface
;
709 return E_NOINTERFACE
;
711 IUnknown_AddRef((IUnknown
*)*out
);
715 static HRESULT
testsink_query_accept(struct strmbase_pin
*iface
, const AM_MEDIA_TYPE
*mt
)
717 struct testfilter
*filter
= impl_from_strmbase_filter(iface
->filter
);
718 if (filter
->sink_mt
&& !compare_media_types(mt
, filter
->sink_mt
))
723 static HRESULT
testsink_get_media_type(struct strmbase_pin
*iface
, unsigned int index
, AM_MEDIA_TYPE
*mt
)
725 struct testfilter
*filter
= impl_from_strmbase_filter(iface
->filter
);
726 if (!index
&& filter
->sink_mt
)
728 CopyMediaType(mt
, filter
->sink_mt
);
731 return VFW_S_NO_MORE_ITEMS
;
734 static HRESULT WINAPI
testsink_Receive(struct strmbase_sink
*iface
, IMediaSample
*sample
)
736 struct testfilter
*filter
= impl_from_strmbase_filter(iface
->pin
.filter
);
737 REFERENCE_TIME start
, stop
;
738 BYTE
*data
, expect
[200];
742 size
= IMediaSample_GetSize(sample
);
743 ok(size
== 256, "Got size %u.\n", size
);
744 size
= IMediaSample_GetActualDataLength(sample
);
745 ok(size
== 200, "Got valid size %u.\n", size
);
747 hr
= IMediaSample_GetPointer(sample
, &data
);
748 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
749 for (i
= 0; i
< size
; ++i
)
751 ok(!memcmp(data
, expect
, size
), "Data didn't match.\n");
753 hr
= IMediaSample_GetTime(sample
, &start
, &stop
);
754 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
755 ok(start
== 30000, "Got start time %s.\n", wine_dbgstr_longlong(start
));
756 ok(stop
== 40000, "Got stop time %s.\n", wine_dbgstr_longlong(stop
));
758 hr
= IMediaSample_GetMediaTime(sample
, &start
, &stop
);
759 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
760 ok(start
== 10000, "Got start time %s.\n", wine_dbgstr_longlong(start
));
761 ok(stop
== 20000, "Got stop time %s.\n", wine_dbgstr_longlong(stop
));
763 hr
= IMediaSample_IsDiscontinuity(sample
);
764 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
765 hr
= IMediaSample_IsPreroll(sample
);
766 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
767 hr
= IMediaSample_IsSyncPoint(sample
);
768 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
770 ++filter
->got_sample
;
775 static HRESULT
testsink_new_segment(struct strmbase_sink
*iface
,
776 REFERENCE_TIME start
, REFERENCE_TIME stop
, double rate
)
778 struct testfilter
*filter
= impl_from_strmbase_filter(iface
->pin
.filter
);
779 ++filter
->got_new_segment
;
780 ok(start
== 10000, "Got start %s.\n", wine_dbgstr_longlong(start
));
781 ok(stop
== 20000, "Got stop %s.\n", wine_dbgstr_longlong(stop
));
782 ok(rate
== 1.0, "Got rate %.16e.\n", rate
);
786 static HRESULT
testsink_eos(struct strmbase_sink
*iface
)
788 struct testfilter
*filter
= impl_from_strmbase_filter(iface
->pin
.filter
);
793 static HRESULT
testsink_begin_flush(struct strmbase_sink
*iface
)
795 struct testfilter
*filter
= impl_from_strmbase_filter(iface
->pin
.filter
);
796 ++filter
->got_begin_flush
;
800 static HRESULT
testsink_end_flush(struct strmbase_sink
*iface
)
802 struct testfilter
*filter
= impl_from_strmbase_filter(iface
->pin
.filter
);
803 ++filter
->got_end_flush
;
807 static const struct strmbase_sink_ops testsink_ops
=
809 .base
.pin_query_interface
= testsink_query_interface
,
810 .base
.pin_query_accept
= testsink_query_accept
,
811 .base
.pin_get_media_type
= testsink_get_media_type
,
812 .pfnReceive
= testsink_Receive
,
813 .sink_new_segment
= testsink_new_segment
,
814 .sink_eos
= testsink_eos
,
815 .sink_begin_flush
= testsink_begin_flush
,
816 .sink_end_flush
= testsink_end_flush
,
819 static void testfilter_init(struct testfilter
*filter
)
821 static const GUID clsid
= {0xabacab};
822 memset(filter
, 0, sizeof(*filter
));
823 strmbase_filter_init(&filter
->filter
, NULL
, &clsid
, &testfilter_ops
);
824 strmbase_source_init(&filter
->source
, &filter
->filter
, L
"source", &testsource_ops
);
825 strmbase_sink_init(&filter
->sink
, &filter
->filter
, L
"sink", &testsink_ops
, NULL
);
828 static void test_sample_processing(IMediaControl
*control
, IMemInputPin
*input
, struct testfilter
*sink
)
830 REFERENCE_TIME start
, stop
;
831 IMemAllocator
*allocator
;
832 IMediaSample
*sample
;
837 hr
= IMemInputPin_ReceiveCanBlock(input
);
838 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
840 hr
= IMemInputPin_GetAllocator(input
, &allocator
);
841 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
843 hr
= IMemAllocator_GetBuffer(allocator
, &sample
, NULL
, NULL
, 0);
844 ok(hr
== VFW_E_NOT_COMMITTED
, "Got hr %#x.\n", hr
);
846 hr
= IMediaControl_Pause(control
);
847 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
849 hr
= IMemAllocator_GetBuffer(allocator
, &sample
, NULL
, NULL
, 0);
850 todo_wine
ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
853 IMemAllocator_Commit(allocator
);
854 hr
= IMemAllocator_GetBuffer(allocator
, &sample
, NULL
, NULL
, 0);
855 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
858 hr
= IMediaSample_GetPointer(sample
, &data
);
859 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
860 size
= IMediaSample_GetSize(sample
);
861 ok(size
== 256, "Got size %d.\n", size
);
862 for (i
= 0; i
< 200; ++i
)
864 hr
= IMediaSample_SetActualDataLength(sample
, 200);
865 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
869 hr
= IMediaSample_SetMediaTime(sample
, &start
, &stop
);
870 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
873 hr
= IMediaSample_SetTime(sample
, &start
, &stop
);
874 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
875 hr
= IMediaSample_SetDiscontinuity(sample
, TRUE
);
876 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
877 hr
= IMediaSample_SetSyncPoint(sample
, TRUE
);
878 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
880 hr
= IMemInputPin_Receive(input
, sample
);
881 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
882 ok(sink
->got_sample
== 1, "Got %u calls to Receive().\n", sink
->got_sample
);
883 sink
->got_sample
= 0;
885 hr
= IMediaControl_Stop(control
);
886 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
888 hr
= IMemInputPin_Receive(input
, sample
);
889 todo_wine
ok(hr
== VFW_E_WRONG_STATE
, "Got hr %#x.\n", hr
);
891 IMediaSample_Release(sample
);
892 IMemAllocator_Release(allocator
);
895 static void test_streaming_events(IMediaControl
*control
, IPin
*sink
,
896 IMemInputPin
*input
, struct testfilter
*testsink
)
898 REFERENCE_TIME start
, stop
;
899 IMemAllocator
*allocator
;
900 IMediaSample
*sample
;
905 hr
= IMediaControl_Pause(control
);
906 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
908 hr
= IMemInputPin_GetAllocator(input
, &allocator
);
909 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
910 hr
= IMemAllocator_GetBuffer(allocator
, &sample
, NULL
, NULL
, 0);
911 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
912 hr
= IMediaSample_GetPointer(sample
, &data
);
913 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
914 for (i
= 0; i
< 200; ++i
)
916 hr
= IMediaSample_SetActualDataLength(sample
, 200);
917 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
920 hr
= IMediaSample_SetMediaTime(sample
, &start
, &stop
);
921 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
924 hr
= IMediaSample_SetTime(sample
, &start
, &stop
);
925 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
926 hr
= IMediaSample_SetDiscontinuity(sample
, TRUE
);
927 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
928 hr
= IMediaSample_SetSyncPoint(sample
, TRUE
);
929 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
931 ok(!testsink
->got_new_segment
, "Got %u calls to IPin::NewSegment().\n", testsink
->got_new_segment
);
932 hr
= IPin_NewSegment(sink
, 10000, 20000, 1.0);
933 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
934 ok(testsink
->got_new_segment
== 1, "Got %u calls to IPin::NewSegment().\n", testsink
->got_new_segment
);
936 ok(!testsink
->got_eos
, "Got %u calls to IPin::EndOfStream().\n", testsink
->got_eos
);
937 hr
= IPin_EndOfStream(sink
);
938 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
939 todo_wine
ok(!testsink
->got_sample
, "Got %u calls to Receive().\n", testsink
->got_sample
);
940 ok(testsink
->got_eos
== 1, "Got %u calls to IPin::EndOfStream().\n", testsink
->got_eos
);
941 testsink
->got_eos
= 0;
943 hr
= IPin_EndOfStream(sink
);
944 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
945 ok(testsink
->got_eos
== 1, "Got %u calls to IPin::EndOfStream().\n", testsink
->got_eos
);
946 testsink
->got_eos
= 0;
948 hr
= IMemInputPin_Receive(input
, sample
);
949 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
950 todo_wine
ok(testsink
->got_sample
== 1, "Got %u calls to Receive().\n", testsink
->got_sample
);
951 testsink
->got_sample
= 0;
953 ok(!testsink
->got_begin_flush
, "Got %u calls to IPin::BeginFlush().\n", testsink
->got_begin_flush
);
954 hr
= IPin_BeginFlush(sink
);
955 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
956 ok(testsink
->got_begin_flush
== 1, "Got %u calls to IPin::BeginFlush().\n", testsink
->got_begin_flush
);
958 hr
= IMemInputPin_Receive(input
, sample
);
959 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
960 ok(testsink
->got_sample
== 1, "Got %u calls to Receive().\n", testsink
->got_sample
);
961 testsink
->got_sample
= 0;
963 hr
= IPin_EndOfStream(sink
);
964 todo_wine
ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
965 todo_wine
ok(testsink
->got_eos
== 1, "Got %u calls to IPin::EndOfStream().\n", testsink
->got_eos
);
966 testsink
->got_eos
= 0;
968 ok(!testsink
->got_end_flush
, "Got %u calls to IPin::EndFlush().\n", testsink
->got_end_flush
);
969 hr
= IPin_EndFlush(sink
);
970 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
971 ok(testsink
->got_end_flush
== 1, "Got %u calls to IPin::EndFlush().\n", testsink
->got_end_flush
);
973 hr
= IMemInputPin_Receive(input
, sample
);
974 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
975 ok(testsink
->got_sample
== 1, "Got %u calls to Receive().\n", testsink
->got_sample
);
976 testsink
->got_sample
= 0;
978 hr
= IMediaControl_Stop(control
);
979 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
980 IMediaSample_Release(sample
);
981 IMemAllocator_Release(allocator
);
984 static void test_connect_pin(void)
986 AM_MEDIA_TYPE req_mt
=
988 .majortype
= MEDIATYPE_Stream
,
989 .subtype
= MEDIASUBTYPE_Avi
,
990 .formattype
= FORMAT_None
,
992 IBaseFilter
*filter
= create_sample_grabber();
993 struct testfilter testsource
, testsink
;
994 IPin
*sink
, *source
, *peer
;
995 IEnumMediaTypes
*enummt
;
996 ISampleGrabber
*grabber
;
997 IMediaControl
*control
;
998 AM_MEDIA_TYPE mt
, *pmt
;
999 IFilterGraph2
*graph
;
1000 IMemInputPin
*input
;
1004 testfilter_init(&testsource
);
1005 testfilter_init(&testsink
);
1006 CoCreateInstance(&CLSID_FilterGraph
, NULL
, CLSCTX_INPROC_SERVER
,
1007 &IID_IFilterGraph2
, (void **)&graph
);
1008 IFilterGraph2_AddFilter(graph
, &testsource
.filter
.IBaseFilter_iface
, L
"source");
1009 IFilterGraph2_AddFilter(graph
, &testsink
.filter
.IBaseFilter_iface
, L
"sink");
1010 IFilterGraph2_AddFilter(graph
, filter
, L
"sample grabber");
1011 IFilterGraph2_QueryInterface(graph
, &IID_IMediaControl
, (void **)&control
);
1012 IBaseFilter_FindPin(filter
, L
"In", &sink
);
1013 IPin_QueryInterface(sink
, &IID_IMemInputPin
, (void **)&input
);
1014 IBaseFilter_FindPin(filter
, L
"Out", &source
);
1015 IBaseFilter_QueryInterface(filter
, &IID_ISampleGrabber
, (void **)&grabber
);
1017 testsource
.source_mt
.majortype
= MEDIATYPE_Video
;
1018 testsource
.source_mt
.subtype
= MEDIASUBTYPE_RGB8
;
1019 testsource
.source_mt
.formattype
= FORMAT_VideoInfo
;
1021 hr
= ISampleGrabber_GetConnectedMediaType(grabber
, &mt
);
1022 ok(hr
== VFW_E_NOT_CONNECTED
, "Got hr %#x.\n", hr
);
1024 /* Test sink connection. */
1026 peer
= (IPin
*)0xdeadbeef;
1027 hr
= IPin_ConnectedTo(sink
, &peer
);
1028 ok(hr
== VFW_E_NOT_CONNECTED
, "Got hr %#x.\n", hr
);
1029 ok(!peer
, "Got peer %p.\n", peer
);
1031 hr
= IPin_ConnectionMediaType(sink
, &mt
);
1032 ok(hr
== VFW_E_NOT_CONNECTED
, "Got hr %#x.\n", hr
);
1034 hr
= IMediaControl_Pause(control
);
1035 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1036 hr
= IFilterGraph2_ConnectDirect(graph
, &testsource
.source
.pin
.IPin_iface
, sink
, &req_mt
);
1037 ok(hr
== VFW_E_NOT_STOPPED
, "Got hr %#x.\n", hr
);
1038 hr
= IMediaControl_Stop(control
);
1039 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1041 hr
= IFilterGraph2_ConnectDirect(graph
, &testsource
.source
.pin
.IPin_iface
, sink
, &req_mt
);
1042 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1044 hr
= IPin_ConnectedTo(sink
, &peer
);
1045 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1046 ok(peer
== &testsource
.source
.pin
.IPin_iface
, "Got peer %p.\n", peer
);
1049 hr
= IPin_ConnectionMediaType(sink
, &mt
);
1050 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1051 ok(compare_media_types(&mt
, &req_mt
), "Media types didn't match.\n");
1053 hr
= IMediaControl_Pause(control
);
1054 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1055 hr
= IFilterGraph2_Disconnect(graph
, sink
);
1056 ok(hr
== VFW_E_NOT_STOPPED
, "Got hr %#x.\n", hr
);
1057 hr
= IMediaControl_Stop(control
);
1058 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1060 hr
= ISampleGrabber_GetConnectedMediaType(grabber
, NULL
);
1061 ok(hr
== E_POINTER
, "Got hr %#x.\n", hr
);
1063 hr
= ISampleGrabber_GetConnectedMediaType(grabber
, &mt
);
1064 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1065 ok(compare_media_types(&mt
, &req_mt
), "Media types didn't match.\n");
1067 hr
= IPin_EnumMediaTypes(sink
, &enummt
);
1068 ok(hr
== VFW_E_NOT_CONNECTED
, "Got hr %#x.\n", hr
);
1069 hr
= IPin_EnumMediaTypes(source
, &enummt
);
1070 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1071 hr
= IEnumMediaTypes_Next(enummt
, 1, &pmt
, NULL
);
1072 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1073 ok(compare_media_types(pmt
, &testsource
.source_mt
), "Media types didn't match.\n");
1074 IEnumMediaTypes_Release(enummt
);
1076 req_mt
.majortype
= MEDIATYPE_Video
;
1077 req_mt
.subtype
= MEDIASUBTYPE_RGB8
;
1078 req_mt
.formattype
= FORMAT_VideoInfo
;
1079 hr
= IPin_QueryAccept(sink
, &req_mt
);
1080 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1081 hr
= IPin_QueryAccept(source
, &req_mt
);
1082 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
1083 req_mt
.bTemporalCompression
= TRUE
;
1084 hr
= IPin_QueryAccept(source
, &req_mt
);
1085 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1087 memset(&mt
, 0, sizeof(AM_MEDIA_TYPE
));
1088 mt
.majortype
= MEDIATYPE_Midi
;
1089 hr
= ISampleGrabber_SetMediaType(grabber
, &mt
);
1090 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1092 hr
= IPin_QueryAccept(source
, &req_mt
);
1093 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
1095 req_mt
.majortype
= MEDIATYPE_Midi
;
1096 req_mt
.bTemporalCompression
= FALSE
;
1097 hr
= IPin_QueryAccept(source
, &req_mt
);
1098 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
1100 req_mt
.bTemporalCompression
= TRUE
;
1101 hr
= IPin_QueryAccept(source
, &req_mt
);
1102 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1104 memset(&mt
, 0, sizeof(AM_MEDIA_TYPE
));
1105 hr
= ISampleGrabber_SetMediaType(grabber
, &mt
);
1106 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1108 /* Test source connection. */
1110 peer
= (IPin
*)0xdeadbeef;
1111 hr
= IPin_ConnectedTo(source
, &peer
);
1112 ok(hr
== VFW_E_NOT_CONNECTED
, "Got hr %#x.\n", hr
);
1113 ok(!peer
, "Got peer %p.\n", peer
);
1115 hr
= IPin_ConnectionMediaType(source
, &mt
);
1116 ok(hr
== VFW_E_NOT_CONNECTED
, "Got hr %#x.\n", hr
);
1118 /* Exact connection. */
1120 hr
= IMediaControl_Pause(control
);
1121 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1122 hr
= IFilterGraph2_ConnectDirect(graph
, source
, &testsink
.sink
.pin
.IPin_iface
, &req_mt
);
1123 ok(hr
== VFW_E_NOT_STOPPED
, "Got hr %#x.\n", hr
);
1124 hr
= IMediaControl_Stop(control
);
1125 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1127 req_mt
.bTemporalCompression
= FALSE
;
1128 hr
= IFilterGraph2_ConnectDirect(graph
, source
, &testsink
.sink
.pin
.IPin_iface
, &req_mt
);
1129 ok(hr
== VFW_E_TYPE_NOT_ACCEPTED
, "Got hr %#x.\n", hr
);
1131 req_mt
.bTemporalCompression
= TRUE
;
1132 hr
= IFilterGraph2_ConnectDirect(graph
, source
, &testsink
.sink
.pin
.IPin_iface
, &req_mt
);
1133 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1135 hr
= IPin_ConnectedTo(source
, &peer
);
1136 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1137 ok(peer
== &testsink
.sink
.pin
.IPin_iface
, "Got peer %p.\n", peer
);
1140 hr
= IPin_ConnectionMediaType(source
, &mt
);
1141 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1142 ok(compare_media_types(&mt
, &req_mt
), "Media types didn't match.\n");
1143 ok(compare_media_types(&testsink
.sink
.pin
.mt
, &req_mt
), "Media types didn't match.\n");
1144 ok(compare_media_types(&testsource
.source
.pin
.mt
, &testsink
.sink
.pin
.mt
), "Media types didn't match.\n");
1146 test_sample_processing(control
, input
, &testsink
);
1147 test_streaming_events(control
, sink
, input
, &testsink
);
1149 hr
= IMediaControl_Pause(control
);
1150 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1151 hr
= IFilterGraph2_Disconnect(graph
, source
);
1152 ok(hr
== VFW_E_NOT_STOPPED
, "Got hr %#x.\n", hr
);
1153 hr
= IMediaControl_Stop(control
);
1154 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1156 hr
= IFilterGraph2_Disconnect(graph
, source
);
1157 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1158 hr
= IFilterGraph2_Disconnect(graph
, source
);
1159 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
1160 ok(testsink
.sink
.pin
.peer
== source
, "Got peer %p.\n", testsink
.sink
.pin
.peer
);
1161 IFilterGraph2_Disconnect(graph
, &testsink
.sink
.pin
.IPin_iface
);
1163 /* Connection with wildcards. */
1165 hr
= IFilterGraph2_ConnectDirect(graph
, source
, &testsink
.sink
.pin
.IPin_iface
, NULL
);
1166 ok(hr
== VFW_E_NO_ACCEPTABLE_TYPES
, "Got hr %#x.\n", hr
);
1168 testsource
.source_mt
.bTemporalCompression
= TRUE
;
1169 hr
= IFilterGraph2_ConnectDirect(graph
, source
, &testsink
.sink
.pin
.IPin_iface
, NULL
);
1170 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1171 ok(compare_media_types(&testsink
.sink
.pin
.mt
, &testsource
.source_mt
), "Media types didn't match.\n");
1172 ok(compare_media_types(&testsource
.source
.pin
.mt
, &testsink
.sink
.pin
.mt
), "Media types didn't match.\n");
1173 IFilterGraph2_Disconnect(graph
, source
);
1174 IFilterGraph2_Disconnect(graph
, &testsink
.sink
.pin
.IPin_iface
);
1176 req_mt
.majortype
= GUID_NULL
;
1177 req_mt
.bTemporalCompression
= FALSE
;
1178 hr
= IFilterGraph2_ConnectDirect(graph
, source
, &testsink
.sink
.pin
.IPin_iface
, &req_mt
);
1179 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1180 ok(compare_media_types(&testsink
.sink
.pin
.mt
, &testsource
.source_mt
), "Media types didn't match.\n");
1181 ok(compare_media_types(&testsource
.source
.pin
.mt
, &testsink
.sink
.pin
.mt
), "Media types didn't match.\n");
1182 IFilterGraph2_Disconnect(graph
, source
);
1183 IFilterGraph2_Disconnect(graph
, &testsink
.sink
.pin
.IPin_iface
);
1185 req_mt
.subtype
= MEDIASUBTYPE_RGB32
;
1186 hr
= IFilterGraph2_ConnectDirect(graph
, source
, &testsink
.sink
.pin
.IPin_iface
, &req_mt
);
1187 ok(hr
== VFW_E_NO_ACCEPTABLE_TYPES
, "Got hr %#x.\n", hr
);
1189 req_mt
.subtype
= GUID_NULL
;
1190 hr
= IFilterGraph2_ConnectDirect(graph
, source
, &testsink
.sink
.pin
.IPin_iface
, &req_mt
);
1191 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1192 ok(compare_media_types(&testsink
.sink
.pin
.mt
, &testsource
.source_mt
), "Media types didn't match.\n");
1193 ok(compare_media_types(&testsource
.source
.pin
.mt
, &testsink
.sink
.pin
.mt
), "Media types didn't match.\n");
1194 IFilterGraph2_Disconnect(graph
, source
);
1195 IFilterGraph2_Disconnect(graph
, &testsink
.sink
.pin
.IPin_iface
);
1197 req_mt
.formattype
= FORMAT_None
;
1198 hr
= IFilterGraph2_ConnectDirect(graph
, source
, &testsink
.sink
.pin
.IPin_iface
, &req_mt
);
1199 ok(hr
== VFW_E_NO_ACCEPTABLE_TYPES
, "Got hr %#x.\n", hr
);
1201 req_mt
.majortype
= MEDIATYPE_Video
;
1202 req_mt
.subtype
= MEDIASUBTYPE_RGB8
;
1203 req_mt
.formattype
= GUID_NULL
;
1204 hr
= IFilterGraph2_ConnectDirect(graph
, source
, &testsink
.sink
.pin
.IPin_iface
, &req_mt
);
1205 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1206 ok(compare_media_types(&testsink
.sink
.pin
.mt
, &testsource
.source_mt
), "Media types didn't match.\n");
1207 ok(compare_media_types(&testsource
.source
.pin
.mt
, &testsink
.sink
.pin
.mt
), "Media types didn't match.\n");
1208 IFilterGraph2_Disconnect(graph
, source
);
1209 IFilterGraph2_Disconnect(graph
, &testsink
.sink
.pin
.IPin_iface
);
1211 req_mt
.subtype
= MEDIASUBTYPE_RGB32
;
1212 hr
= IFilterGraph2_ConnectDirect(graph
, source
, &testsink
.sink
.pin
.IPin_iface
, &req_mt
);
1213 ok(hr
== VFW_E_NO_ACCEPTABLE_TYPES
, "Got hr %#x.\n", hr
);
1215 req_mt
.subtype
= GUID_NULL
;
1216 hr
= IFilterGraph2_ConnectDirect(graph
, source
, &testsink
.sink
.pin
.IPin_iface
, &req_mt
);
1217 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1218 ok(compare_media_types(&testsink
.sink
.pin
.mt
, &testsource
.source_mt
), "Media types didn't match.\n");
1219 ok(compare_media_types(&testsource
.source
.pin
.mt
, &testsink
.sink
.pin
.mt
), "Media types didn't match.\n");
1220 IFilterGraph2_Disconnect(graph
, source
);
1221 IFilterGraph2_Disconnect(graph
, &testsink
.sink
.pin
.IPin_iface
);
1223 req_mt
.majortype
= MEDIATYPE_Audio
;
1224 hr
= IFilterGraph2_ConnectDirect(graph
, source
, &testsink
.sink
.pin
.IPin_iface
, &req_mt
);
1225 ok(hr
== VFW_E_NO_ACCEPTABLE_TYPES
, "Got hr %#x.\n", hr
);
1227 testsource
.source_mt
.majortype
= testsource
.source_mt
.subtype
= testsource
.source_mt
.formattype
= GUID_NULL
;
1228 req_mt
.majortype
= req_mt
.subtype
= req_mt
.formattype
= GUID_NULL
;
1229 hr
= IFilterGraph2_ConnectDirect(graph
, source
, &testsink
.sink
.pin
.IPin_iface
, &req_mt
);
1230 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1231 ok(compare_media_types(&testsink
.sink
.pin
.mt
, &testsource
.source_mt
), "Media types didn't match.\n");
1232 ok(compare_media_types(&testsource
.source
.pin
.mt
, &testsink
.sink
.pin
.mt
), "Media types didn't match.\n");
1233 IFilterGraph2_Disconnect(graph
, source
);
1234 IFilterGraph2_Disconnect(graph
, &testsink
.sink
.pin
.IPin_iface
);
1236 req_mt
.majortype
= MEDIATYPE_Video
;
1237 hr
= IFilterGraph2_ConnectDirect(graph
, source
, &testsink
.sink
.pin
.IPin_iface
, &req_mt
);
1238 ok(hr
== VFW_E_NO_ACCEPTABLE_TYPES
, "Got hr %#x.\n", hr
);
1239 req_mt
.majortype
= GUID_NULL
;
1241 req_mt
.subtype
= MEDIASUBTYPE_RGB8
;
1242 hr
= IFilterGraph2_ConnectDirect(graph
, source
, &testsink
.sink
.pin
.IPin_iface
, &req_mt
);
1243 ok(hr
== VFW_E_NO_ACCEPTABLE_TYPES
, "Got hr %#x.\n", hr
);
1244 req_mt
.subtype
= GUID_NULL
;
1246 req_mt
.formattype
= FORMAT_None
;
1247 hr
= IFilterGraph2_ConnectDirect(graph
, source
, &testsink
.sink
.pin
.IPin_iface
, &req_mt
);
1248 ok(hr
== VFW_E_NO_ACCEPTABLE_TYPES
, "Got hr %#x.\n", hr
);
1249 req_mt
.formattype
= GUID_NULL
;
1251 testsink
.sink_mt
= &req_mt
;
1252 hr
= IFilterGraph2_ConnectDirect(graph
, source
, &testsink
.sink
.pin
.IPin_iface
, NULL
);
1253 ok(hr
== VFW_E_NO_ACCEPTABLE_TYPES
, "Got hr %#x.\n", hr
);
1255 req_mt
.bTemporalCompression
= TRUE
;
1256 hr
= IFilterGraph2_ConnectDirect(graph
, source
, &testsink
.sink
.pin
.IPin_iface
, NULL
);
1257 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1258 ok(compare_media_types(&testsink
.sink
.pin
.mt
, &req_mt
), "Media types didn't match.\n");
1259 ok(compare_media_types(&testsource
.source
.pin
.mt
, &testsink
.sink
.pin
.mt
), "Media types didn't match.\n");
1261 hr
= IPin_EnumMediaTypes(sink
, &enummt
);
1262 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1263 hr
= IEnumMediaTypes_Next(enummt
, 1, &pmt
, NULL
);
1264 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1265 ok(compare_media_types(pmt
, testsink
.sink_mt
), "Media types didn't match.\n");
1266 IEnumMediaTypes_Release(enummt
);
1268 IFilterGraph2_Disconnect(graph
, source
);
1269 IFilterGraph2_Disconnect(graph
, &testsink
.sink
.pin
.IPin_iface
);
1271 hr
= IFilterGraph2_Disconnect(graph
, sink
);
1272 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1273 hr
= IFilterGraph2_Disconnect(graph
, sink
);
1274 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
1275 ok(testsource
.source
.pin
.peer
== sink
, "Got peer %p.\n", testsource
.source
.pin
.peer
);
1276 IFilterGraph2_Disconnect(graph
, &testsource
.source
.pin
.IPin_iface
);
1278 peer
= (IPin
*)0xdeadbeef;
1279 hr
= IPin_ConnectedTo(sink
, &peer
);
1280 ok(hr
== VFW_E_NOT_CONNECTED
, "Got hr %#x.\n", hr
);
1281 ok(!peer
, "Got peer %p.\n", peer
);
1283 hr
= IPin_ConnectionMediaType(sink
, &mt
);
1284 ok(hr
== VFW_E_NOT_CONNECTED
, "Got hr %#x.\n", hr
);
1286 IMemInputPin_Release(input
);
1288 IPin_Release(source
);
1289 IMediaControl_Release(control
);
1290 ref
= IFilterGraph2_Release(graph
);
1291 ok(!ref
, "Got outstanding refcount %d.\n", ref
);
1292 ISampleGrabber_Release(grabber
);
1293 ref
= IBaseFilter_Release(filter
);
1294 ok(!ref
, "Got outstanding refcount %d.\n", ref
);
1295 ref
= IBaseFilter_Release(&testsource
.filter
.IBaseFilter_iface
);
1296 ok(!ref
, "Got outstanding refcount %d.\n", ref
);
1297 ref
= IBaseFilter_Release(&testsink
.filter
.IBaseFilter_iface
);
1298 ok(!ref
, "Got outstanding refcount %d.\n", ref
);
1301 START_TEST(samplegrabber
)
1303 IBaseFilter
*filter
;
1308 if (FAILED(hr
= CoCreateInstance(&CLSID_SampleGrabber
, NULL
, CLSCTX_INPROC_SERVER
,
1309 &IID_IBaseFilter
, (void **)&filter
)))
1311 /* qedit.dll does not exist on 2003. */
1312 win_skip("Failed to create sample grabber filter, hr %#x.\n", hr
);
1315 IBaseFilter_Release(filter
);