mfplat: Read queue subscriber within the critical section.
[wine/zf.git] / dlls / qedit / tests / samplegrabber.c
blobf82c375b76f7d62232b70dfc814f59442a96db0f
1 /*
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
21 #define COBJMACROS
22 #include "dshow.h"
23 #include "qedit.h"
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);
33 return filter;
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;
55 IUnknown *unk;
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);
63 if (SUCCEEDED(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();
76 IUnknown *unk;
77 HRESULT hr;
78 ULONG ref;
79 IPin *pin;
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);
113 IPin_Release(pin);
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);
133 IPin_Release(pin);
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;
143 ULONG count, ref;
144 IPin *pins[3];
145 HRESULT hr;
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;
264 IPin *pin, *pin2;
265 HRESULT hr;
266 ULONG ref;
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);
281 IPin_Release(pin2);
282 IPin_Release(pin);
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);
289 IPin_Release(pin2);
290 IPin_Release(pin);
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();
300 PIN_DIRECTION dir;
301 PIN_INFO info;
302 ULONG count;
303 HRESULT hr;
304 WCHAR *id;
305 ULONG ref;
306 IPin *pin;
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));
325 CoTaskMemFree(id);
327 hr = IPin_QueryInternalConnections(pin, NULL, &count);
328 ok(hr == E_NOTIMPL, "Got hr %#x.\n", hr);
330 IPin_Release(pin);
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));
349 CoTaskMemFree(id);
351 hr = IPin_QueryInternalConnections(pin, NULL, &count);
352 ok(hr == E_NOTIMPL, "Got hr %#x.\n", hr);
354 IPin_Release(pin);
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;
370 return S_OK;
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,
389 outer_AddRef,
390 outer_Release,
393 static IUnknown test_outer = {&outer_vtbl};
395 static void test_aggregation(void)
397 IBaseFilter *filter, *filter2;
398 IUnknown *unk, *unk2;
399 HRESULT hr;
400 ULONG ref;
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)
456 BYTE format = 1;
457 AM_MEDIA_TYPE mt =
459 .majortype = {0x111},
460 .subtype = {0x222},
461 .formattype = {0x333},
463 AM_MEDIA_TYPE match_mt =
465 .subtype = {0x123},
466 .bFixedSizeSamples = TRUE,
467 .bTemporalCompression = TRUE,
468 .lSampleSize = 456,
469 .formattype = {0x789},
470 .cbFormat = sizeof(format),
471 .pbFormat = &format,
473 IBaseFilter *filter = create_sample_grabber();
474 IEnumMediaTypes *enummt;
475 ISampleGrabber *grabber;
476 IPin *sink, *source;
477 HRESULT hr;
478 ULONG ref;
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);
568 IPin_Release(sink);
569 IPin_Release(source);
570 ISampleGrabber_Release(grabber);
571 ref = IBaseFilter_Release(filter);
572 ok(!ref, "Got outstanding refcount %d.\n", ref);
575 struct testfilter
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);
593 if (!index)
594 return &filter->source.pin;
595 else if (index == 1)
596 return &filter->sink.pin;
597 return NULL;
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);
622 if (!index)
624 CopyMediaType(mt, &filter->source_mt);
625 return S_OK;
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;
634 IMemInputPin *input;
635 HRESULT hr;
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);
648 if (hr == S_OK)
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)
677 HRESULT hr;
679 iface->pin.peer = peer;
680 IPin_AddRef(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);
686 IPin_Release(peer);
687 iface->pin.peer = NULL;
688 FreeMediaType(&iface->pin.mt);
691 test_sink_allocator(peer);
693 return hr;
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;
709 else
710 return E_NOINTERFACE;
712 IUnknown_AddRef((IUnknown *)*out);
713 return S_OK;
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))
720 return S_FALSE;
721 return S_OK;
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);
730 return S_OK;
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];
740 LONG size, i;
741 HRESULT hr;
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)
751 expect[i] = 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;
773 return S_OK;
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);
784 return S_OK;
787 static HRESULT testsink_eos(struct strmbase_sink *iface)
789 struct testfilter *filter = impl_from_strmbase_filter(iface->pin.filter);
790 ++filter->got_eos;
791 return S_OK;
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;
798 return S_OK;
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;
805 return S_OK;
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;
834 LONG size, i;
835 HRESULT hr;
836 BYTE *data;
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);
852 if (hr != S_OK)
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)
864 data[i] = i;
865 hr = IMediaSample_SetActualDataLength(sample, 200);
866 ok(hr == S_OK, "Got hr %#x.\n", hr);
868 start = 10000;
869 stop = 20000;
870 hr = IMediaSample_SetMediaTime(sample, &start, &stop);
871 ok(hr == S_OK, "Got hr %#x.\n", hr);
872 start = 30000;
873 stop = 40000;
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;
902 HRESULT hr;
903 BYTE *data;
904 LONG i;
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)
916 data[i] = i;
917 hr = IMediaSample_SetActualDataLength(sample, 200);
918 ok(hr == S_OK, "Got hr %#x.\n", hr);
919 start = 10000;
920 stop = 20000;
921 hr = IMediaSample_SetMediaTime(sample, &start, &stop);
922 ok(hr == S_OK, "Got hr %#x.\n", hr);
923 start = 30000;
924 stop = 40000;
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;
1002 HRESULT hr;
1003 ULONG ref;
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);
1048 IPin_Release(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);
1139 IPin_Release(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);
1288 IPin_Release(sink);
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;
1305 HRESULT hr;
1307 CoInitialize(NULL);
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);
1314 return;
1316 IBaseFilter_Release(filter);
1318 test_interfaces();
1319 test_enum_pins();
1320 test_find_pin();
1321 test_pin_info();
1322 test_aggregation();
1323 test_media_types();
1324 test_connect_pin();
1326 CoUninitialize();