tools: Move target CPU and platform handling to the common tools.h header.
[wine.git] / dlls / qedit / tests / samplegrabber.c
blob6a58d5ea7e61f6db00ab457b750113c4a2925c83
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 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)
676 HRESULT hr;
678 iface->pin.peer = peer;
679 IPin_AddRef(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);
685 IPin_Release(peer);
686 iface->pin.peer = NULL;
687 FreeMediaType(&iface->pin.mt);
690 test_sink_allocator(peer);
692 return hr;
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;
708 else
709 return E_NOINTERFACE;
711 IUnknown_AddRef((IUnknown *)*out);
712 return S_OK;
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))
719 return S_FALSE;
720 return S_OK;
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);
729 return S_OK;
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];
739 LONG size, i;
740 HRESULT hr;
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)
750 expect[i] = 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;
772 return S_OK;
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);
783 return S_OK;
786 static HRESULT testsink_eos(struct strmbase_sink *iface)
788 struct testfilter *filter = impl_from_strmbase_filter(iface->pin.filter);
789 ++filter->got_eos;
790 return S_OK;
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;
797 return S_OK;
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;
804 return S_OK;
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;
833 LONG size, i;
834 HRESULT hr;
835 BYTE *data;
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);
851 if (hr != S_OK)
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)
863 data[i] = i;
864 hr = IMediaSample_SetActualDataLength(sample, 200);
865 ok(hr == S_OK, "Got hr %#x.\n", hr);
867 start = 10000;
868 stop = 20000;
869 hr = IMediaSample_SetMediaTime(sample, &start, &stop);
870 ok(hr == S_OK, "Got hr %#x.\n", hr);
871 start = 30000;
872 stop = 40000;
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;
901 HRESULT hr;
902 BYTE *data;
903 LONG i;
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)
915 data[i] = i;
916 hr = IMediaSample_SetActualDataLength(sample, 200);
917 ok(hr == S_OK, "Got hr %#x.\n", hr);
918 start = 10000;
919 stop = 20000;
920 hr = IMediaSample_SetMediaTime(sample, &start, &stop);
921 ok(hr == S_OK, "Got hr %#x.\n", hr);
922 start = 30000;
923 stop = 40000;
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;
1001 HRESULT hr;
1002 ULONG ref;
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);
1047 IPin_Release(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);
1138 IPin_Release(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);
1287 IPin_Release(sink);
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;
1304 HRESULT hr;
1306 CoInitialize(NULL);
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);
1313 return;
1315 IBaseFilter_Release(filter);
1317 test_interfaces();
1318 test_enum_pins();
1319 test_find_pin();
1320 test_pin_info();
1321 test_aggregation();
1322 test_media_types();
1323 test_connect_pin();
1325 CoUninitialize();