d3d11: Remove null dxgi object checks.
[wine.git] / dlls / quartz / tests / filesource.c
blobc383d9f65791cd13e4599a5fddfd34ae31b81f90
1 /*
2 * File source filter unit tests
4 * Copyright 2016 Sebastian Lackner
5 * Copyright 2018 Zebediah Figura
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 #define COBJMACROS
23 #include "dshow.h"
24 #include "wine/strmbase.h"
25 #include "wine/test.h"
27 static IBaseFilter *create_file_source(void)
29 IBaseFilter *filter = NULL;
30 HRESULT hr = CoCreateInstance(&CLSID_AsyncReader, NULL, CLSCTX_INPROC_SERVER,
31 &IID_IBaseFilter, (void **)&filter);
32 ok(hr == S_OK, "Got hr %#lx.\n", hr);
33 return filter;
36 static BOOL compare_media_types(const AM_MEDIA_TYPE *a, const AM_MEDIA_TYPE *b)
38 return !memcmp(a, b, offsetof(AM_MEDIA_TYPE, pbFormat))
39 && !memcmp(a->pbFormat, b->pbFormat, a->cbFormat);
42 static WCHAR *load_resource(const WCHAR *name)
44 static WCHAR pathW[MAX_PATH];
45 DWORD written;
46 HANDLE file;
47 HRSRC res;
48 void *ptr;
50 GetTempPathW(ARRAY_SIZE(pathW), pathW);
51 wcscat(pathW, name);
53 file = CreateFileW(pathW, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0);
54 ok(file != INVALID_HANDLE_VALUE, "Failed to create file %s, error %lu.\n",
55 wine_dbgstr_w(pathW), GetLastError());
57 res = FindResourceW(NULL, name, (LPCWSTR)RT_RCDATA);
58 ok(!!res, "Failed to load resource, error %lu.\n", GetLastError());
59 ptr = LockResource(LoadResource(GetModuleHandleA(NULL), res));
60 WriteFile(file, ptr, SizeofResource( GetModuleHandleA(NULL), res), &written, NULL);
61 ok(written == SizeofResource(GetModuleHandleA(NULL), res), "Failed to write resource.\n");
62 CloseHandle(file);
64 return pathW;
67 static void load_file(IBaseFilter *filter, const WCHAR *filename)
69 IFileSourceFilter *filesource;
70 HRESULT hr;
72 hr = IBaseFilter_QueryInterface(filter, &IID_IFileSourceFilter, (void **)&filesource);
73 ok(hr == S_OK, "Got hr %#lx.\n", hr);
74 hr = IFileSourceFilter_Load(filesource, filename, NULL);
75 ok(hr == S_OK, "Got hr %#lx.\n", hr);
76 IFileSourceFilter_Release(filesource);
79 static ULONG get_refcount(void *iface)
81 IUnknown *unknown = iface;
82 IUnknown_AddRef(unknown);
83 return IUnknown_Release(unknown);
86 #define check_interface(a, b, c) check_interface_(__LINE__, a, b, c)
87 static void check_interface_(unsigned int line, void *iface_ptr, REFIID iid, BOOL supported)
89 IUnknown *iface = iface_ptr;
90 HRESULT hr, expected_hr;
91 IUnknown *unk;
93 expected_hr = supported ? S_OK : E_NOINTERFACE;
95 hr = IUnknown_QueryInterface(iface, iid, (void **)&unk);
96 ok_(__FILE__, line)(hr == expected_hr, "Got hr %#lx, expected %#lx.\n", hr, expected_hr);
97 if (SUCCEEDED(hr))
98 IUnknown_Release(unk);
101 static void test_interfaces(void)
103 const WCHAR *filename = load_resource(L"test.avi");
104 IBaseFilter *filter = create_file_source();
105 IPin *pin;
107 check_interface(filter, &IID_IBaseFilter, TRUE);
108 check_interface(filter, &IID_IFileSourceFilter, TRUE);
110 check_interface(filter, &IID_IAMFilterMiscFlags, FALSE);
111 check_interface(filter, &IID_IBasicAudio, FALSE);
112 check_interface(filter, &IID_IBasicVideo, FALSE);
113 check_interface(filter, &IID_IKsPropertySet, FALSE);
114 check_interface(filter, &IID_IMediaPosition, FALSE);
115 check_interface(filter, &IID_IMediaSeeking, FALSE);
116 check_interface(filter, &IID_IPersistPropertyBag, FALSE);
117 check_interface(filter, &IID_IPin, FALSE);
118 check_interface(filter, &IID_IQualityControl, FALSE);
119 check_interface(filter, &IID_IQualProp, FALSE);
120 check_interface(filter, &IID_IReferenceClock, FALSE);
121 check_interface(filter, &IID_IVideoWindow, FALSE);
123 load_file(filter, filename);
124 IBaseFilter_FindPin(filter, L"Output", &pin);
126 check_interface(pin, &IID_IAsyncReader, TRUE);
127 check_interface(pin, &IID_IPin, TRUE);
128 todo_wine check_interface(pin, &IID_IQualityControl, TRUE);
129 check_interface(pin, &IID_IUnknown, TRUE);
131 check_interface(pin, &IID_IKsPropertySet, FALSE);
132 check_interface(pin, &IID_IMediaPosition, FALSE);
133 check_interface(pin, &IID_IMediaSeeking, FALSE);
135 IPin_Release(pin);
136 IBaseFilter_Release(filter);
139 static const GUID test_iid = {0x33333333};
140 static LONG outer_ref = 1;
142 static HRESULT WINAPI outer_QueryInterface(IUnknown *iface, REFIID iid, void **out)
144 if (IsEqualGUID(iid, &IID_IUnknown)
145 || IsEqualGUID(iid, &IID_IBaseFilter)
146 || IsEqualGUID(iid, &test_iid))
148 *out = (IUnknown *)0xdeadbeef;
149 return S_OK;
151 ok(0, "unexpected call %s\n", wine_dbgstr_guid(iid));
152 return E_NOINTERFACE;
155 static ULONG WINAPI outer_AddRef(IUnknown *iface)
157 return InterlockedIncrement(&outer_ref);
160 static ULONG WINAPI outer_Release(IUnknown *iface)
162 return InterlockedDecrement(&outer_ref);
165 static const IUnknownVtbl outer_vtbl =
167 outer_QueryInterface,
168 outer_AddRef,
169 outer_Release,
172 static IUnknown test_outer = {&outer_vtbl};
174 static void test_aggregation(void)
176 IBaseFilter *filter, *filter2;
177 IUnknown *unk, *unk2;
178 HRESULT hr;
179 ULONG ref;
181 filter = (IBaseFilter *)0xdeadbeef;
182 hr = CoCreateInstance(&CLSID_AsyncReader, &test_outer, CLSCTX_INPROC_SERVER,
183 &IID_IBaseFilter, (void **)&filter);
184 ok(hr == E_NOINTERFACE, "Got hr %#lx.\n", hr);
185 ok(!filter, "Got interface %p.\n", filter);
187 hr = CoCreateInstance(&CLSID_AsyncReader, &test_outer, CLSCTX_INPROC_SERVER,
188 &IID_IUnknown, (void **)&unk);
189 ok(hr == S_OK, "Got hr %#lx.\n", hr);
190 ok(outer_ref == 1, "Got unexpected refcount %ld.\n", outer_ref);
191 ok(unk != &test_outer, "Returned IUnknown should not be outer IUnknown.\n");
192 ref = get_refcount(unk);
193 ok(ref == 1, "Got unexpected refcount %ld.\n", ref);
195 ref = IUnknown_AddRef(unk);
196 ok(ref == 2, "Got unexpected refcount %ld.\n", ref);
197 ok(outer_ref == 1, "Got unexpected refcount %ld.\n", outer_ref);
199 ref = IUnknown_Release(unk);
200 ok(ref == 1, "Got unexpected refcount %ld.\n", ref);
201 ok(outer_ref == 1, "Got unexpected refcount %ld.\n", outer_ref);
203 hr = IUnknown_QueryInterface(unk, &IID_IUnknown, (void **)&unk2);
204 ok(hr == S_OK, "Got hr %#lx.\n", hr);
205 ok(unk2 == unk, "Got unexpected IUnknown %p.\n", unk2);
206 IUnknown_Release(unk2);
208 hr = IUnknown_QueryInterface(unk, &IID_IBaseFilter, (void **)&filter);
209 ok(hr == S_OK, "Got hr %#lx.\n", hr);
211 hr = IBaseFilter_QueryInterface(filter, &IID_IUnknown, (void **)&unk2);
212 ok(hr == S_OK, "Got hr %#lx.\n", hr);
213 ok(unk2 == (IUnknown *)0xdeadbeef, "Got unexpected IUnknown %p.\n", unk2);
215 hr = IBaseFilter_QueryInterface(filter, &IID_IBaseFilter, (void **)&filter2);
216 ok(hr == S_OK, "Got hr %#lx.\n", hr);
217 ok(filter2 == (IBaseFilter *)0xdeadbeef, "Got unexpected IBaseFilter %p.\n", filter2);
219 hr = IUnknown_QueryInterface(unk, &test_iid, (void **)&unk2);
220 ok(hr == E_NOINTERFACE, "Got hr %#lx.\n", hr);
221 ok(!unk2, "Got unexpected IUnknown %p.\n", unk2);
223 hr = IBaseFilter_QueryInterface(filter, &test_iid, (void **)&unk2);
224 ok(hr == S_OK, "Got hr %#lx.\n", hr);
225 ok(unk2 == (IUnknown *)0xdeadbeef, "Got unexpected IUnknown %p.\n", unk2);
227 IBaseFilter_Release(filter);
228 ref = IUnknown_Release(unk);
229 ok(!ref, "Got unexpected refcount %ld.\n", ref);
230 ok(outer_ref == 1, "Got unexpected refcount %ld.\n", outer_ref);
233 static void test_file_source_filter(void)
235 static const struct
237 const char *label;
238 const char *data;
239 DWORD size;
240 const GUID *subtype;
242 tests[] =
245 "AVI",
246 "\x52\x49\x46\x46xxxx\x41\x56\x49\x20",
248 &MEDIASUBTYPE_Avi,
251 "MPEG1 System",
252 "\x00\x00\x01\xBA\x21\x00\x01\x00\x01\x80\x00\x01\x00\x00\x01\xBB",
254 &MEDIASUBTYPE_MPEG1System,
257 "MPEG1 Video",
258 "\x00\x00\x01\xB3",
260 &MEDIASUBTYPE_MPEG1Video,
263 "MPEG1 Audio",
264 "\xFF\xE0",
266 &MEDIASUBTYPE_MPEG1Audio,
269 "MPEG2 Program",
270 "\x00\x00\x01\xBA\x40",
272 &MEDIASUBTYPE_MPEG2_PROGRAM,
275 "WAVE",
276 "\x52\x49\x46\x46xxxx\x57\x41\x56\x45",
278 &MEDIASUBTYPE_WAVE,
281 "unknown format",
282 "Hello World",
284 &MEDIASUBTYPE_NULL,
287 WCHAR path[MAX_PATH], temp[MAX_PATH], *filename;
288 AM_MEDIA_TYPE mt, file_mt, *pmt;
289 IFileSourceFilter *filesource;
290 IEnumMediaTypes *enum_mt;
291 IBaseFilter *filter;
292 OLECHAR *olepath;
293 DWORD written;
294 HANDLE file;
295 HRESULT hr;
296 ULONG ref;
297 IPin *pin;
298 BOOL ret;
299 int i;
301 GetTempPathW(MAX_PATH, temp);
302 GetTempFileNameW(temp, L"win", 0, path);
304 for (i = 0; i < ARRAY_SIZE(tests); i++)
306 trace("Running test for %s.\n", tests[i].label);
308 file = CreateFileW(path, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
309 ok(file != INVALID_HANDLE_VALUE, "Failed to create file, error %lu.\n", GetLastError());
310 ret = WriteFile(file, tests[i].data, tests[i].size, &written, NULL);
311 ok(ret, "Failed to write file, error %lu.\n", GetLastError());
312 CloseHandle(file);
314 filter = create_file_source();
315 IBaseFilter_QueryInterface(filter, &IID_IFileSourceFilter, (void **)&filesource);
317 olepath = (void *)0xdeadbeef;
318 hr = IFileSourceFilter_GetCurFile(filesource, &olepath, NULL);
319 ok(hr == S_OK, "Got hr %#lx.\n", hr);
320 ok(!olepath, "Got path %s.\n", wine_dbgstr_w(olepath));
322 hr = IFileSourceFilter_Load(filesource, NULL, NULL);
323 ok(hr == E_POINTER, "Got hr %#lx.\n", hr);
325 hr = IFileSourceFilter_Load(filesource, path, NULL);
326 ok(hr == S_OK, "Got hr %#lx.\n", hr);
328 hr = IFileSourceFilter_GetCurFile(filesource, NULL, &mt);
329 ok(hr == E_POINTER, "Got hr %#lx.\n", hr);
331 olepath = NULL;
332 hr = IFileSourceFilter_GetCurFile(filesource, &olepath, NULL);
333 ok(hr == S_OK, "Got hr %#lx.\n", hr);
334 CoTaskMemFree(olepath);
336 olepath = NULL;
337 memset(&file_mt, 0x11, sizeof(file_mt));
338 hr = IFileSourceFilter_GetCurFile(filesource, &olepath, &file_mt);
339 ok(hr == S_OK, "Got hr %#lx.\n", hr);
340 ok(!wcscmp(olepath, path), "Expected path %s, got %s.\n",
341 wine_dbgstr_w(path), wine_dbgstr_w(olepath));
342 ok(IsEqualGUID(&file_mt.majortype, &MEDIATYPE_Stream), "Got major type %s.\n",
343 wine_dbgstr_guid(&file_mt.majortype));
344 /* winegstreamer hijacks format type detection. */
345 if (!IsEqualGUID(tests[i].subtype, &MEDIASUBTYPE_NULL))
346 ok(IsEqualGUID(&file_mt.subtype, tests[i].subtype), "Expected subtype %s, got %s.\n",
347 wine_dbgstr_guid(tests[i].subtype), wine_dbgstr_guid(&file_mt.subtype));
348 ok(file_mt.bFixedSizeSamples == TRUE, "Got fixed size %d.\n", file_mt.bFixedSizeSamples);
349 ok(file_mt.bTemporalCompression == FALSE, "Got temporal compression %d.\n",
350 file_mt.bTemporalCompression);
351 ok(file_mt.lSampleSize == 1, "Got sample size %lu.\n", file_mt.lSampleSize);
352 ok(IsEqualGUID(&file_mt.formattype, &GUID_NULL), "Got format type %s.\n",
353 wine_dbgstr_guid(&file_mt.formattype));
354 ok(!file_mt.pUnk, "Got pUnk %p.\n", file_mt.pUnk);
355 ok(!file_mt.cbFormat, "Got format size %#lx.\n", file_mt.cbFormat);
356 ok(!file_mt.pbFormat, "Got format %p.\n", file_mt.pbFormat);
357 CoTaskMemFree(olepath);
359 hr = IBaseFilter_FindPin(filter, L"Output", &pin);
360 ok(hr == S_OK, "Got hr %#lx.\n", hr);
362 hr = IPin_EnumMediaTypes(pin, &enum_mt);
363 ok(hr == S_OK, "Got hr %#lx.\n", hr);
365 hr = IEnumMediaTypes_Next(enum_mt, 1, &pmt, NULL);
366 ok(hr == S_OK, "Got hr %#lx.\n", hr);
367 ok(!memcmp(pmt, &file_mt, sizeof(*pmt)), "Media types did not match.\n");
368 CoTaskMemFree(pmt);
370 hr = IEnumMediaTypes_Next(enum_mt, 1, &pmt, NULL);
371 ok(hr == S_OK, "Got hr %#lx.\n", hr);
372 mt = file_mt;
373 mt.subtype = GUID_NULL;
374 ok(!memcmp(pmt, &mt, sizeof(*pmt)), "Media types did not match.\n");
375 CoTaskMemFree(pmt);
377 hr = IEnumMediaTypes_Next(enum_mt, 1, &pmt, NULL);
378 ok(hr == S_FALSE, "Got hr %#lx.\n", hr);
380 IEnumMediaTypes_Release(enum_mt);
382 mt = file_mt;
383 hr = IPin_QueryAccept(pin, &mt);
384 ok(hr == S_OK, "Got hr %#lx.\n", hr);
386 mt.bFixedSizeSamples = FALSE;
387 mt.bTemporalCompression = TRUE;
388 mt.lSampleSize = 123;
389 mt.formattype = FORMAT_VideoInfo;
390 mt.subtype = MEDIASUBTYPE_RGB32;
391 hr = IPin_QueryAccept(pin, &mt);
392 ok(hr == S_OK, "Got hr %#lx.\n", hr);
394 mt.majortype = MEDIATYPE_Video;
395 hr = IPin_QueryAccept(pin, &mt);
396 ok(hr == S_FALSE, "Got hr %#lx.\n", hr);
397 mt.majortype = MEDIATYPE_Stream;
399 if (!IsEqualGUID(tests[i].subtype, &GUID_NULL))
401 mt.subtype = GUID_NULL;
402 hr = IPin_QueryAccept(pin, &mt);
403 ok(hr == S_FALSE, "Got hr %#lx.\n", hr);
406 IPin_Release(pin);
407 IFileSourceFilter_Release(filesource);
408 ref = IBaseFilter_Release(filter);
409 ok(!ref, "Got outstanding refcount %ld.\n", ref);
411 ret = DeleteFileW(path);
412 ok(ret, "Failed to delete file, error %lu\n", GetLastError());
415 /* test prescribed format */
416 filter = create_file_source();
417 hr = IBaseFilter_QueryInterface(filter, &IID_IFileSourceFilter, (void **)&filesource);
418 ok(hr == S_OK, "Got hr %#lx.\n", hr);
420 mt.majortype = MEDIATYPE_Video;
421 mt.subtype = MEDIASUBTYPE_RGB8;
422 mt.bFixedSizeSamples = FALSE;
423 mt.bTemporalCompression = TRUE;
424 mt.lSampleSize = 123;
425 mt.formattype = FORMAT_None;
426 mt.pUnk = NULL;
427 mt.cbFormat = 0;
428 mt.pbFormat = NULL;
429 filename = load_resource(L"test.avi");
430 hr = IFileSourceFilter_Load(filesource, filename, &mt);
431 ok(hr == S_OK, "Got hr %#lx.\n", hr);
433 hr = IFileSourceFilter_GetCurFile(filesource, &olepath, &file_mt);
434 ok(hr == S_OK, "Got hr %#lx.\n", hr);
435 ok(!memcmp(&file_mt, &mt, sizeof(mt)), "Media types did not match.\n");
436 CoTaskMemFree(olepath);
438 hr = IBaseFilter_FindPin(filter, L"Output", &pin);
439 ok(hr == S_OK, "Got hr %#lx.\n", hr);
441 hr = IPin_EnumMediaTypes(pin, &enum_mt);
442 ok(hr == S_OK, "Got hr %#lx.\n", hr);
444 hr = IEnumMediaTypes_Next(enum_mt, 1, &pmt, NULL);
445 ok(hr == S_OK, "Got hr %#lx.\n", hr);
446 ok(!memcmp(pmt, &file_mt, sizeof(*pmt)), "Media types did not match.\n");
447 CoTaskMemFree(pmt);
449 hr = IEnumMediaTypes_Next(enum_mt, 1, &pmt, NULL);
450 ok(hr == S_OK, "Got hr %#lx.\n", hr);
451 ok(IsEqualGUID(&pmt->majortype, &MEDIATYPE_Stream), "Got major type %s.\n",
452 wine_dbgstr_guid(&pmt->majortype));
453 ok(IsEqualGUID(&pmt->subtype, &GUID_NULL), "Got subtype %s.\n",
454 wine_dbgstr_guid(&pmt->subtype));
455 ok(pmt->bFixedSizeSamples == TRUE, "Got fixed size %d.\n", pmt->bFixedSizeSamples);
456 ok(!pmt->bTemporalCompression, "Got temporal compression %d.\n", pmt->bTemporalCompression);
457 ok(pmt->lSampleSize == 1, "Got sample size %lu.\n", pmt->lSampleSize);
458 ok(IsEqualGUID(&pmt->formattype, &GUID_NULL), "Got format type %s.\n",
459 wine_dbgstr_guid(&pmt->formattype));
460 ok(!pmt->pUnk, "Got pUnk %p.\n", pmt->pUnk);
461 ok(!pmt->cbFormat, "Got format size %#lx.\n", pmt->cbFormat);
462 ok(!pmt->pbFormat, "Got format %p.\n", pmt->pbFormat);
464 hr = IPin_QueryAccept(pin, pmt);
465 ok(hr == S_FALSE, "Got hr %#lx.\n", hr);
466 CoTaskMemFree(pmt);
468 hr = IEnumMediaTypes_Next(enum_mt, 1, &pmt, NULL);
469 ok(hr == S_FALSE, "Got hr %#lx.\n", hr);
471 IEnumMediaTypes_Release(enum_mt);
473 hr = IPin_QueryAccept(pin, &mt);
474 ok(hr == S_OK, "Got hr %#lx.\n", hr);
476 mt.bFixedSizeSamples = TRUE;
477 mt.bTemporalCompression = FALSE;
478 mt.lSampleSize = 456;
479 mt.formattype = FORMAT_VideoInfo;
480 hr = IPin_QueryAccept(pin, &mt);
481 ok(hr == S_OK, "Got hr %#lx.\n", hr);
483 mt.majortype = MEDIATYPE_Stream;
484 hr = IPin_QueryAccept(pin, &mt);
485 ok(hr == S_FALSE, "Got hr %#lx.\n", hr);
486 mt.majortype = MEDIATYPE_Video;
488 mt.subtype = MEDIASUBTYPE_NULL;
489 hr = IPin_QueryAccept(pin, &mt);
490 ok(hr == S_FALSE, "Got hr %#lx.\n", hr);
492 IPin_Release(pin);
493 IFileSourceFilter_Release(filesource);
494 ref = IBaseFilter_Release(filter);
495 ok(!ref, "Got outstanding refcount %ld.\n", ref);
496 ret = DeleteFileW(filename);
497 ok(ret, "Failed to delete file, error %lu.\n", GetLastError());
500 static void test_enum_pins(void)
502 const WCHAR *filename = load_resource(L"test.avi");
503 IBaseFilter *filter = create_file_source();
504 IEnumPins *enum1, *enum2;
505 IPin *pins[2];
506 ULONG count;
507 HRESULT hr;
508 ULONG ref;
509 BOOL ret;
511 ref = get_refcount(filter);
512 ok(ref == 1, "Got unexpected refcount %ld.\n", ref);
514 hr = IBaseFilter_EnumPins(filter, NULL);
515 ok(hr == E_POINTER, "Got hr %#lx.\n", hr);
517 hr = IBaseFilter_EnumPins(filter, &enum1);
518 ok(hr == S_OK, "Got hr %#lx.\n", hr);
520 ref = get_refcount(filter);
521 ok(ref == 2, "Got unexpected refcount %ld.\n", ref);
522 ref = get_refcount(enum1);
523 ok(ref == 1, "Got unexpected refcount %ld.\n", ref);
525 hr = IEnumPins_Next(enum1, 1, NULL, NULL);
526 ok(hr == E_POINTER, "Got hr %#lx.\n", hr);
528 hr = IEnumPins_Next(enum1, 1, pins, NULL);
529 ok(hr == S_FALSE, "Got hr %#lx.\n", hr);
531 hr = IEnumPins_Skip(enum1, 1);
532 ok(hr == S_FALSE, "Got hr %#lx.\n", hr);
534 load_file(filter, filename);
536 hr = IEnumPins_Next(enum1, 1, pins, NULL);
537 ok(hr == S_FALSE, "Got hr %#lx.\n", hr);
539 hr = IEnumPins_Reset(enum1);
540 ok(hr == S_OK, "Got hr %#lx.\n", hr);
542 hr = IEnumPins_Next(enum1, 1, pins, NULL);
543 ok(hr == S_OK, "Got hr %#lx.\n", hr);
544 ref = get_refcount(filter);
545 ok(ref == 3, "Got unexpected refcount %ld.\n", ref);
546 ref = get_refcount(pins[0]);
547 ok(ref == 3, "Got unexpected refcount %ld.\n", ref);
548 ref = get_refcount(enum1);
549 ok(ref == 1, "Got unexpected refcount %ld.\n", ref);
550 IPin_Release(pins[0]);
551 ref = get_refcount(filter);
552 ok(ref == 2, "Got unexpected refcount %ld.\n", ref);
554 hr = IEnumPins_Next(enum1, 1, pins, NULL);
555 ok(hr == S_FALSE, "Got hr %#lx.\n", hr);
557 hr = IEnumPins_Reset(enum1);
558 ok(hr == S_OK, "Got hr %#lx.\n", hr);
560 hr = IEnumPins_Next(enum1, 1, pins, &count);
561 ok(hr == S_OK, "Got hr %#lx.\n", hr);
562 ok(count == 1, "Got count %lu.\n", count);
563 IPin_Release(pins[0]);
565 hr = IEnumPins_Next(enum1, 1, pins, &count);
566 ok(hr == S_FALSE, "Got hr %#lx.\n", hr);
567 ok(!count, "Got count %lu.\n", count);
569 hr = IEnumPins_Reset(enum1);
570 ok(hr == S_OK, "Got hr %#lx.\n", hr);
572 hr = IEnumPins_Next(enum1, 2, pins, NULL);
573 ok(hr == E_INVALIDARG, "Got hr %#lx.\n", hr);
575 hr = IEnumPins_Next(enum1, 2, pins, &count);
576 ok(hr == S_FALSE, "Got hr %#lx.\n", hr);
577 ok(count == 1, "Got count %lu.\n", count);
578 IPin_Release(pins[0]);
580 hr = IEnumPins_Reset(enum1);
581 ok(hr == S_OK, "Got hr %#lx.\n", hr);
583 hr = IEnumPins_Clone(enum1, &enum2);
584 ok(hr == S_OK, "Got hr %#lx.\n", hr);
586 hr = IEnumPins_Skip(enum1, 2);
587 ok(hr == S_FALSE, "Got hr %#lx.\n", hr);
589 hr = IEnumPins_Skip(enum1, 1);
590 ok(hr == S_OK, "Got hr %#lx.\n", hr);
592 hr = IEnumPins_Skip(enum1, 1);
593 ok(hr == S_FALSE, "Got hr %#lx.\n", hr);
595 hr = IEnumPins_Next(enum1, 1, pins, NULL);
596 ok(hr == S_FALSE, "Got hr %#lx.\n", hr);
598 hr = IEnumPins_Next(enum2, 1, pins, NULL);
599 ok(hr == S_OK, "Got hr %#lx.\n", hr);
600 IPin_Release(pins[0]);
602 IEnumPins_Release(enum2);
603 IEnumPins_Release(enum1);
604 ref = IBaseFilter_Release(filter);
605 ok(!ref, "Got outstanding refcount %ld.\n", ref);
606 ret = DeleteFileW(filename);
607 ok(ret, "Failed to delete file, error %lu.\n", GetLastError());
610 static void test_find_pin(void)
612 const WCHAR *filename = load_resource(L"test.avi");
613 IBaseFilter *filter = create_file_source();
614 IEnumPins *enumpins;
615 IPin *pin, *pin2;
616 HRESULT hr;
617 ULONG ref;
618 BOOL ret;
620 hr = IBaseFilter_FindPin(filter, L"Output", &pin);
621 ok(hr == VFW_E_NOT_FOUND, "Got hr %#lx.\n", hr);
623 load_file(filter, filename);
625 hr = IBaseFilter_FindPin(filter, L"Output", &pin);
626 ok(hr == S_OK, "Got hr %#lx.\n", hr);
627 ref = get_refcount(filter);
628 ok(ref == 2, "Got unexpected refcount %ld.\n", ref);
629 ref = get_refcount(pin);
630 ok(ref == 2, "Got unexpected refcount %ld.\n", ref);
632 hr = IBaseFilter_EnumPins(filter, &enumpins);
633 ok(hr == S_OK, "Got hr %#lx.\n", hr);
635 hr = IEnumPins_Next(enumpins, 1, &pin2, NULL);
636 ok(hr == S_OK, "Got hr %#lx.\n", hr);
637 ok(pin == pin2, "Expected pin %p, got %p.\n", pin, pin2);
639 IPin_Release(pin2);
640 IPin_Release(pin);
641 IEnumPins_Release(enumpins);
642 ref = IBaseFilter_Release(filter);
643 ok(!ref, "Got outstanding refcount %ld.\n", ref);
644 ret = DeleteFileW(filename);
645 ok(ret, "Failed to delete file, error %lu.\n", GetLastError());
648 static void test_pin_info(void)
650 const WCHAR *filename = load_resource(L"test.avi");
651 IBaseFilter *filter = create_file_source();
652 PIN_DIRECTION dir;
653 PIN_INFO info;
654 HRESULT hr;
655 WCHAR *id;
656 ULONG ref;
657 IPin *pin;
658 BOOL ret;
660 load_file(filter, filename);
662 hr = IBaseFilter_FindPin(filter, L"Output", &pin);
663 ok(hr == S_OK, "Got hr %#lx.\n", hr);
664 ref = get_refcount(filter);
665 ok(ref == 2, "Got unexpected refcount %ld.\n", ref);
666 ref = get_refcount(pin);
667 ok(ref == 2, "Got unexpected refcount %ld.\n", ref);
669 hr = IPin_QueryPinInfo(pin, &info);
670 ok(hr == S_OK, "Got hr %#lx.\n", hr);
671 ok(info.pFilter == filter, "Expected filter %p, got %p.\n", filter, info.pFilter);
672 ok(info.dir == PINDIR_OUTPUT, "Got direction %d.\n", info.dir);
673 ok(!wcscmp(info.achName, L"Output"), "Got name %s.\n", wine_dbgstr_w(info.achName));
674 ref = get_refcount(filter);
675 ok(ref == 3, "Got unexpected refcount %ld.\n", ref);
676 ref = get_refcount(pin);
677 ok(ref == 3, "Got unexpected refcount %ld.\n", ref);
678 IBaseFilter_Release(info.pFilter);
680 hr = IPin_QueryDirection(pin, &dir);
681 ok(hr == S_OK, "Got hr %#lx.\n", hr);
682 ok(dir == PINDIR_OUTPUT, "Got direction %d.\n", dir);
684 hr = IPin_QueryId(pin, &id);
685 ok(hr == S_OK, "Got hr %#lx.\n", hr);
686 ok(!wcscmp(id, L"Output"), "Got id %s.\n", wine_dbgstr_w(id));
687 CoTaskMemFree(id);
689 IPin_Release(pin);
690 ref = IBaseFilter_Release(filter);
691 ok(!ref, "Got outstanding refcount %ld.\n", ref);
692 ret = DeleteFileW(filename);
693 ok(ret, "Failed to delete file, error %lu.\n", GetLastError());
696 static void test_unconnected_filter_state(void)
698 IBaseFilter *filter = create_file_source();
699 FILTER_STATE state;
700 HRESULT hr;
701 ULONG ref;
703 hr = IBaseFilter_GetState(filter, 0, &state);
704 ok(hr == S_OK, "Got hr %#lx.\n", hr);
705 ok(state == State_Stopped, "Got state %u.\n", state);
707 hr = IBaseFilter_Pause(filter);
708 ok(hr == S_OK, "Got hr %#lx.\n", hr);
710 hr = IBaseFilter_GetState(filter, 0, &state);
711 ok(hr == S_OK, "Got hr %#lx.\n", hr);
712 ok(state == State_Paused, "Got state %u.\n", state);
714 hr = IBaseFilter_Run(filter, 0);
715 ok(hr == S_OK, "Got hr %#lx.\n", hr);
717 hr = IBaseFilter_GetState(filter, 0, &state);
718 ok(hr == S_OK, "Got hr %#lx.\n", hr);
719 ok(state == State_Running, "Got state %u.\n", state);
721 hr = IBaseFilter_Pause(filter);
722 ok(hr == S_OK, "Got hr %#lx.\n", hr);
724 hr = IBaseFilter_GetState(filter, 0, &state);
725 ok(hr == S_OK, "Got hr %#lx.\n", hr);
726 ok(state == State_Paused, "Got state %u.\n", state);
728 hr = IBaseFilter_Stop(filter);
729 ok(hr == S_OK, "Got hr %#lx.\n", hr);
731 hr = IBaseFilter_GetState(filter, 0, &state);
732 ok(hr == S_OK, "Got hr %#lx.\n", hr);
733 ok(state == State_Stopped, "Got state %u.\n", state);
735 hr = IBaseFilter_Run(filter, 0);
736 ok(hr == S_OK, "Got hr %#lx.\n", hr);
738 hr = IBaseFilter_GetState(filter, 0, &state);
739 ok(hr == S_OK, "Got hr %#lx.\n", hr);
740 ok(state == State_Running, "Got state %u.\n", state);
742 hr = IBaseFilter_Stop(filter);
743 ok(hr == S_OK, "Got hr %#lx.\n", hr);
745 hr = IBaseFilter_GetState(filter, 0, &state);
746 ok(hr == S_OK, "Got hr %#lx.\n", hr);
747 ok(state == State_Stopped, "Got state %u.\n", state);
749 ref = IBaseFilter_Release(filter);
750 ok(!ref, "Got outstanding refcount %ld.\n", ref);
753 static void test_sync_read_aligned(IAsyncReader *reader, IMemAllocator *allocator)
755 REFERENCE_TIME start_time, end_time;
756 IMediaSample *sample;
757 HRESULT hr;
758 BYTE *data;
759 LONG len;
760 int i;
762 IMemAllocator_GetBuffer(allocator, &sample, NULL, NULL, 0);
763 IMediaSample_GetPointer(sample, &data);
765 start_time = 0;
766 end_time = 512 * (LONGLONG)10000000;
767 hr = IMediaSample_SetTime(sample, &start_time, &end_time);
768 ok(hr == S_OK, "Got hr %#lx.\n", hr);
770 hr = IAsyncReader_SyncReadAligned(reader, sample);
771 ok(hr == S_OK, "Got hr %#lx.\n", hr);
773 len = IMediaSample_GetActualDataLength(sample);
774 ok(len == 512, "Got length %ld.\n", len);
776 for (i = 0; i < 512; i++)
777 ok(data[i] == i % 111, "Got wrong byte %02x at %u.\n", data[i], i);
779 start_time = 512 * (LONGLONG)10000000;
780 end_time = 1024 * (LONGLONG)10000000;
781 hr = IMediaSample_SetTime(sample, &start_time, &end_time);
782 ok(hr == S_OK, "Got hr %#lx.\n", hr);
784 hr = IAsyncReader_SyncReadAligned(reader, sample);
785 ok(hr == S_FALSE, "Got hr %#lx.\n", hr);
787 len = IMediaSample_GetActualDataLength(sample);
788 ok(len == 88, "Got length %ld.\n", len);
790 for (i = 0; i < 88; i++)
791 ok(data[i] == (512 + i) % 111, "Got wrong byte %02x at %u.\n", data[i], i);
793 start_time = 1024 * (LONGLONG)10000000;
794 end_time = 1536 * (LONGLONG)10000000;
795 hr = IMediaSample_SetTime(sample, &start_time, &end_time);
796 ok(hr == S_OK, "Got hr %#lx.\n", hr);
798 hr = IAsyncReader_SyncReadAligned(reader, sample);
799 ok(hr == S_OK, "Got hr %#lx.\n", hr);
801 len = IMediaSample_GetActualDataLength(sample);
802 ok(len == 0, "Got length %ld.\n", len);
804 IMediaSample_Release(sample);
807 struct request_thread_params
809 IAsyncReader *reader;
810 IMediaSample *sample;
813 static DWORD CALLBACK request_thread(void *arg)
815 struct request_thread_params *params = arg;
816 HRESULT hr = IAsyncReader_Request(params->reader, params->sample, 123);
817 ok(hr == S_OK, "Got hr %#lx.\n", hr);
818 return 0;
821 static void test_request(IAsyncReader *reader, IMemAllocator *allocator)
823 IMediaSample *sample, *sample2, *ret_sample;
824 struct request_thread_params params;
825 REFERENCE_TIME start_time, end_time;
826 BYTE *data, *data2;
827 DWORD_PTR cookie;
828 HANDLE thread;
829 HRESULT hr;
830 LONG len;
831 int i;
833 IMemAllocator_GetBuffer(allocator, &sample, NULL, NULL, 0);
834 IMediaSample_GetPointer(sample, &data);
835 IMemAllocator_GetBuffer(allocator, &sample2, NULL, NULL, 0);
836 IMediaSample_GetPointer(sample2, &data2);
838 hr = IAsyncReader_WaitForNext(reader, 0, &ret_sample, &cookie);
839 ok(hr == VFW_E_TIMEOUT, "Got hr %#lx.\n", hr);
841 start_time = 0;
842 end_time = 512 * (LONGLONG)10000000;
843 hr = IMediaSample_SetTime(sample, &start_time, &end_time);
844 ok(hr == S_OK, "Got hr %#lx.\n", hr);
846 hr = IAsyncReader_Request(reader, sample, 123);
847 ok(hr == S_OK, "Got hr %#lx.\n", hr);
849 hr = IAsyncReader_WaitForNext(reader, 1000, &ret_sample, &cookie);
850 ok(hr == S_OK, "Got hr %#lx.\n", hr);
851 ok(ret_sample == sample, "Expected sample %p, got %p.\n", sample, ret_sample);
852 ok(cookie == 123, "Got cookie %Iu.\n", cookie);
854 len = IMediaSample_GetActualDataLength(sample);
855 ok(len == 512, "Got length %ld.\n", len);
857 for (i = 0; i < 512; i++)
858 ok(data[i] == i % 111, "Got wrong byte %02x at %u.\n", data[i], i);
860 start_time = 1024 * (LONGLONG)10000000;
861 end_time = 1536 * (LONGLONG)10000000;
862 hr = IMediaSample_SetTime(sample, &start_time, &end_time);
863 ok(hr == S_OK, "Got hr %#lx.\n", hr);
865 hr = IAsyncReader_Request(reader, sample, 123);
866 ok(hr == HRESULT_FROM_WIN32(ERROR_HANDLE_EOF), "Got hr %#lx.\n", hr);
868 start_time = 0;
869 end_time = 512 * (LONGLONG)10000000;
870 hr = IMediaSample_SetTime(sample, &start_time, &end_time);
871 ok(hr == S_OK, "Got hr %#lx.\n", hr);
873 hr = IAsyncReader_Request(reader, sample, 123);
874 ok(hr == S_OK, "Got hr %#lx.\n", hr);
876 start_time = 512 * (LONGLONG)10000000;
877 end_time = 1024 * (LONGLONG)10000000;
878 hr = IMediaSample_SetTime(sample2, &start_time, &end_time);
879 ok(hr == S_OK, "Got hr %#lx.\n", hr);
881 hr = IAsyncReader_Request(reader, sample2, 456);
882 ok(hr == S_OK, "Got hr %#lx.\n", hr);
884 hr = IAsyncReader_WaitForNext(reader, 1000, &ret_sample, &cookie);
885 ok(hr == S_OK, "Got hr %#lx.\n", hr);
886 if (cookie == 123)
888 ok(ret_sample == sample, "Expected sample %p, got %p.\n", sample, ret_sample);
890 hr = IAsyncReader_WaitForNext(reader, 1000, &ret_sample, &cookie);
891 ok(hr == S_OK, "Got hr %#lx.\n", hr);
892 ok(ret_sample == sample2, "Expected sample %p, got %p.\n", sample2, ret_sample);
893 ok(cookie == 456, "Got cookie %Iu.\n", cookie);
895 else
897 ok(cookie == 456, "Got cookie %Iu.\n", cookie);
898 ok(ret_sample == sample2, "Expected sample %p, got %p.\n", sample2, ret_sample);
900 hr = IAsyncReader_WaitForNext(reader, 1000, &ret_sample, &cookie);
901 ok(hr == S_OK, "Got hr %#lx.\n", hr);
902 ok(ret_sample == sample, "Expected sample %p, got %p.\n", sample, ret_sample);
903 ok(cookie == 123, "Got cookie %Iu.\n", cookie);
906 for (i = 0; i < 512; i++)
907 ok(data[i] == i % 111, "Got wrong byte %02x at %u.\n", data[i], i);
909 for (i = 0; i < 88; i++)
910 ok(data2[i] == (512 + i) % 111, "Got wrong byte %02x at %u.\n", data2[i], i);
912 params.reader = reader;
913 params.sample = sample;
914 thread = CreateThread(NULL, 0, request_thread, &params, 0, NULL);
915 ok(!WaitForSingleObject(thread, 1000), "Wait timed out.\n");
916 CloseHandle(thread);
918 hr = IAsyncReader_WaitForNext(reader, 1000, &ret_sample, &cookie);
919 ok(hr == S_OK, "Got hr %#lx.\n", hr);
920 ok(ret_sample == sample, "Samples didn't match.\n");
921 ok(cookie == 123, "Got cookie %Iu.\n", cookie);
923 IMediaSample_Release(sample);
924 IMediaSample_Release(sample2);
927 static DWORD CALLBACK wait_thread(void *arg)
929 IAsyncReader *reader = arg;
930 IMediaSample *sample;
931 DWORD_PTR cookie;
932 HRESULT hr = IAsyncReader_WaitForNext(reader, 2000, &sample, &cookie);
933 ok(hr == VFW_E_WRONG_STATE, "Got hr %#lx.\n", hr);
934 return 0;
937 static void test_flush(IAsyncReader *reader, IMemAllocator *allocator)
939 REFERENCE_TIME start_time, end_time;
940 IMediaSample *sample, *ret_sample;
941 BYTE buffer[20], *data;
942 DWORD_PTR cookie;
943 HANDLE thread;
944 HRESULT hr;
945 int i;
947 IMemAllocator_GetBuffer(allocator, &sample, NULL, NULL, 0);
948 IMediaSample_GetPointer(sample, &data);
950 start_time = 0;
951 end_time = 512 * (LONGLONG)10000000;
952 hr = IMediaSample_SetTime(sample, &start_time, &end_time);
953 ok(hr == S_OK, "Got hr %#lx.\n", hr);
955 hr = IAsyncReader_BeginFlush(reader);
956 ok(hr == S_OK, "Got hr %#lx.\n", hr);
958 hr = IAsyncReader_SyncRead(reader, 0, 20, buffer);
959 ok(hr == S_OK, "Got hr %#lx.\n", hr);
960 for (i = 0; i < 20; i++)
961 ok(buffer[i] == i % 111, "Got wrong byte %02x at %u.\n", buffer[i], i);
963 start_time = 0;
964 end_time = 512 * (LONGLONG)10000000;
965 hr = IMediaSample_SetTime(sample, &start_time, &end_time);
966 ok(hr == S_OK, "Got hr %#lx.\n", hr);
968 hr = IAsyncReader_SyncReadAligned(reader, sample);
969 ok(hr == S_OK, "Got hr %#lx.\n", hr);
970 for (i = 0; i < 512; i++)
971 ok(data[i] == i % 111, "Got wrong byte %02x at %u.\n", data[i], i);
973 hr = IAsyncReader_Request(reader, sample, 456);
974 ok(hr == VFW_E_WRONG_STATE, "Got hr %#lx.\n", hr);
976 hr = IAsyncReader_EndFlush(reader);
977 ok(hr == S_OK, "Got hr %#lx.\n", hr);
979 hr = IAsyncReader_WaitForNext(reader, 0, &ret_sample, &cookie);
980 ok(hr == VFW_E_TIMEOUT, "Got hr %#lx.\n", hr);
982 start_time = 0;
983 end_time = 512 * (LONGLONG)10000000;
984 hr = IAsyncReader_Request(reader, sample, 123);
985 ok(hr == S_OK, "Got hr %#lx.\n", hr);
987 hr = IAsyncReader_WaitForNext(reader, 1000, &ret_sample, &cookie);
988 ok(hr == S_OK, "Got hr %#lx.\n", hr);
989 ok(ret_sample == sample, "Expected sample %p, got %p.\n", sample, ret_sample);
990 ok(cookie == 123, "Got cookie %Iu.\n", cookie);
992 for (i = 0; i < 512; i++)
993 ok(data[i] == i % 111, "Got wrong byte %02x at %u.\n", data[i], i);
995 thread = CreateThread(NULL, 0, wait_thread, reader, 0, NULL);
996 ok(WaitForSingleObject(thread, 100) == WAIT_TIMEOUT, "Expected timeout.\n");
998 hr = IAsyncReader_BeginFlush(reader);
999 ok(hr == S_OK, "Got hr %#lx.\n", hr);
1000 ok(!WaitForSingleObject(thread, 1000), "Wait timed out.\n");
1001 CloseHandle(thread);
1003 hr = IAsyncReader_EndFlush(reader);
1004 ok(hr == S_OK, "Got hr %#lx.\n", hr);
1006 IMediaSample_Release(sample);
1009 static void test_async_reader(void)
1011 ALLOCATOR_PROPERTIES req_props = {100, 1024, 512, 0}, ret_props;
1012 IBaseFilter *filter = create_file_source();
1013 IFileSourceFilter *filesource;
1014 LONGLONG length, available;
1015 IMemAllocator *allocator;
1016 WCHAR filename[MAX_PATH];
1017 IAsyncReader *reader;
1018 BYTE buffer[20];
1019 DWORD written;
1020 HANDLE file;
1021 HRESULT hr;
1022 ULONG ref;
1023 IPin *pin;
1024 BOOL ret;
1025 int i;
1027 GetTempPathW(ARRAY_SIZE(filename), filename);
1028 wcscat(filename, L"test.avi");
1029 file = CreateFileW(filename, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0);
1030 ok(file != INVALID_HANDLE_VALUE, "Failed to create file, error %lu.\n", GetLastError());
1031 for (i = 0; i < 600; i++)
1033 BYTE b = i % 111;
1034 WriteFile(file, &b, 1, &written, NULL);
1036 CloseHandle(file);
1038 IBaseFilter_QueryInterface(filter, &IID_IFileSourceFilter, (void **)&filesource);
1039 IFileSourceFilter_Load(filesource, filename, NULL);
1040 IBaseFilter_FindPin(filter, L"Output", &pin);
1042 hr = IPin_QueryInterface(pin, &IID_IAsyncReader, (void **)&reader);
1043 ok(hr == S_OK, "Got hr %#lx.\n", hr);
1045 hr = IAsyncReader_Length(reader, &length, &available);
1046 ok(hr == S_OK, "Got hr %#lx.\n", hr);
1047 ok(length == 600, "Got length %s.\n", wine_dbgstr_longlong(length));
1048 ok(available == 600, "Got available length %s.\n", wine_dbgstr_longlong(available));
1050 memset(buffer, 0xcc, sizeof(buffer));
1051 hr = IAsyncReader_SyncRead(reader, 0, 10, buffer);
1052 ok(hr == S_OK, "Got hr %#lx.\n", hr);
1053 for (i = 0; i < 10; i++)
1054 ok(buffer[i] == i % 111, "Got wrong byte %02x at %u.\n", buffer[i], i);
1056 hr = IAsyncReader_SyncRead(reader, 0, 10, buffer);
1057 ok(hr == S_OK, "Got hr %#lx.\n", hr);
1058 for (i = 0; i < 10; i++)
1059 ok(buffer[i] == i % 111, "Got wrong byte %02x at %u.\n", buffer[i], i);
1061 hr = IAsyncReader_SyncRead(reader, 10, 10, buffer);
1062 ok(hr == S_OK, "Got hr %#lx.\n", hr);
1063 for (i = 0; i < 10; i++)
1064 ok(buffer[i] == (10 + i) % 111, "Got wrong byte %02x at %u.\n", buffer[i], i);
1066 hr = IAsyncReader_SyncRead(reader, 590, 20, buffer);
1067 ok(hr == S_FALSE, "Got hr %#lx.\n", hr);
1068 for (i = 0; i < 10; i++)
1069 ok(buffer[i] == (590 + i) % 111, "Got wrong byte %02x at %u.\n", buffer[i], i);
1070 for (; i < 20; i++)
1071 ok(buffer[i] == 0xcc, "Got wrong byte %02x at %u.\n", buffer[i], i);
1073 memset(buffer, 0xcc, sizeof(buffer));
1074 hr = IAsyncReader_SyncRead(reader, 600, 10, buffer);
1075 ok(hr == S_FALSE, "Got hr %#lx.\n", hr);
1076 ok(buffer[0] == 0xcc, "Got wrong byte %02x.\n", buffer[0]);
1078 ret_props = req_props;
1079 hr = IAsyncReader_RequestAllocator(reader, NULL, &ret_props, &allocator);
1080 ok(hr == S_OK, "Got hr %#lx.\n", hr);
1081 ok(ret_props.cBuffers == 100, "Got %ld buffers.\n", ret_props.cBuffers);
1082 ok(ret_props.cbBuffer == 1024, "Got size %ld.\n", ret_props.cbBuffer);
1083 ok(ret_props.cbAlign == 512, "Got alignment %ld.\n", ret_props.cbAlign);
1084 ok(ret_props.cbPrefix == 0, "Got prefix %ld.\n", ret_props.cbPrefix);
1086 IMemAllocator_Commit(allocator);
1088 test_sync_read_aligned(reader, allocator);
1089 test_request(reader, allocator);
1090 test_flush(reader, allocator);
1092 IMemAllocator_Release(allocator);
1093 IAsyncReader_Release(reader);
1094 IPin_Release(pin);
1095 IFileSourceFilter_Release(filesource);
1096 ref = IBaseFilter_Release(filter);
1097 ok(!ref, "Got outstanding refcount %ld.\n", ref);
1098 ret = DeleteFileW(filename);
1099 ok(ret, "Failed to delete file, error %lu.\n", GetLastError());
1102 static void test_enum_media_types(void)
1104 const WCHAR *filename = load_resource(L"test.avi");
1105 IBaseFilter *filter = create_file_source();
1106 IEnumMediaTypes *enum1, *enum2;
1107 AM_MEDIA_TYPE *mts[3];
1108 ULONG ref, count;
1109 HRESULT hr;
1110 IPin *pin;
1111 BOOL ret;
1113 load_file(filter, filename);
1115 IBaseFilter_FindPin(filter, L"Output", &pin);
1117 hr = IPin_EnumMediaTypes(pin, &enum1);
1118 ok(hr == S_OK, "Got hr %#lx.\n", hr);
1120 hr = IEnumMediaTypes_Next(enum1, 1, mts, NULL);
1121 ok(hr == S_OK, "Got hr %#lx.\n", hr);
1122 CoTaskMemFree(mts[0]);
1124 hr = IEnumMediaTypes_Next(enum1, 1, mts, NULL);
1125 ok(hr == S_OK, "Got hr %#lx.\n", hr);
1126 CoTaskMemFree(mts[0]);
1128 hr = IEnumMediaTypes_Next(enum1, 1, mts, NULL);
1129 ok(hr == S_FALSE, "Got hr %#lx.\n", hr);
1131 hr = IEnumMediaTypes_Reset(enum1);
1132 ok(hr == S_OK, "Got hr %#lx.\n", hr);
1134 hr = IEnumMediaTypes_Next(enum1, 1, mts, &count);
1135 ok(hr == S_OK, "Got hr %#lx.\n", hr);
1136 ok(count == 1, "Got count %lu.\n", count);
1137 CoTaskMemFree(mts[0]);
1139 hr = IEnumMediaTypes_Next(enum1, 1, mts, &count);
1140 ok(hr == S_OK, "Got hr %#lx.\n", hr);
1141 ok(count == 1, "Got count %lu.\n", count);
1142 CoTaskMemFree(mts[0]);
1144 hr = IEnumMediaTypes_Next(enum1, 1, mts, &count);
1145 ok(hr == S_FALSE, "Got hr %#lx.\n", hr);
1146 ok(!count, "Got count %lu.\n", count);
1148 hr = IEnumMediaTypes_Reset(enum1);
1149 ok(hr == S_OK, "Got hr %#lx.\n", hr);
1151 hr = IEnumMediaTypes_Next(enum1, 2, mts, &count);
1152 ok(hr == S_OK, "Got hr %#lx.\n", hr);
1153 ok(count == 2, "Got count %lu.\n", count);
1154 CoTaskMemFree(mts[0]);
1155 CoTaskMemFree(mts[1]);
1157 hr = IEnumMediaTypes_Next(enum1, 2, mts, &count);
1158 ok(hr == S_FALSE, "Got hr %#lx.\n", hr);
1159 ok(!count, "Got count %lu.\n", count);
1161 hr = IEnumMediaTypes_Reset(enum1);
1162 ok(hr == S_OK, "Got hr %#lx.\n", hr);
1164 hr = IEnumMediaTypes_Next(enum1, 3, mts, &count);
1165 ok(hr == S_FALSE, "Got hr %#lx.\n", hr);
1166 ok(count == 2, "Got count %lu.\n", count);
1167 CoTaskMemFree(mts[0]);
1168 CoTaskMemFree(mts[1]);
1170 hr = IEnumMediaTypes_Reset(enum1);
1171 ok(hr == S_OK, "Got hr %#lx.\n", hr);
1173 hr = IEnumMediaTypes_Clone(enum1, &enum2);
1174 ok(hr == S_OK, "Got hr %#lx.\n", hr);
1176 hr = IEnumMediaTypes_Skip(enum1, 3);
1177 ok(hr == S_FALSE, "Got hr %#lx.\n", hr);
1179 hr = IEnumMediaTypes_Skip(enum1, 1);
1180 ok(hr == S_FALSE, "Got hr %#lx.\n", hr);
1182 hr = IEnumMediaTypes_Reset(enum1);
1183 ok(hr == S_OK, "Got hr %#lx.\n", hr);
1185 hr = IEnumMediaTypes_Skip(enum1, 2);
1186 ok(hr == S_OK, "Got hr %#lx.\n", hr);
1188 hr = IEnumMediaTypes_Skip(enum1, 1);
1189 ok(hr == S_FALSE, "Got hr %#lx.\n", hr);
1191 hr = IEnumMediaTypes_Next(enum1, 1, mts, NULL);
1192 ok(hr == S_FALSE, "Got hr %#lx.\n", hr);
1194 hr = IEnumMediaTypes_Next(enum2, 1, mts, NULL);
1195 ok(hr == S_OK, "Got hr %#lx.\n", hr);
1196 CoTaskMemFree(mts[0]);
1198 IEnumMediaTypes_Release(enum1);
1199 IEnumMediaTypes_Release(enum2);
1200 IPin_Release(pin);
1202 ref = IBaseFilter_Release(filter);
1203 ok(!ref, "Got outstanding refcount %ld.\n", ref);
1204 ret = DeleteFileW(filename);
1205 ok(ret, "Failed to delete file, error %lu.\n", GetLastError());
1208 struct testsink
1210 struct strmbase_filter filter;
1211 struct strmbase_sink pin;
1212 IAsyncReader *reader;
1213 BOOL reject_avi;
1214 const AM_MEDIA_TYPE *mt;
1217 static inline struct testsink *impl_sink_from_strmbase_filter(struct strmbase_filter *iface)
1219 return CONTAINING_RECORD(iface, struct testsink, filter);
1222 static struct strmbase_pin *testsink_get_pin(struct strmbase_filter *iface, unsigned int index)
1224 struct testsink *filter = impl_sink_from_strmbase_filter(iface);
1225 if (!index)
1226 return &filter->pin.pin;
1227 return NULL;
1230 static void testsink_destroy(struct strmbase_filter *iface)
1232 struct testsink *filter = impl_sink_from_strmbase_filter(iface);
1233 strmbase_sink_cleanup(&filter->pin);
1234 strmbase_filter_cleanup(&filter->filter);
1237 static const struct strmbase_filter_ops testsink_ops =
1239 .filter_get_pin = testsink_get_pin,
1240 .filter_destroy = testsink_destroy,
1243 static HRESULT testsink_get_media_type(struct strmbase_pin *iface, unsigned int index, AM_MEDIA_TYPE *mt)
1245 struct testsink *filter = impl_sink_from_strmbase_filter(iface->filter);
1246 if (!index && filter->mt)
1248 CopyMediaType(mt, filter->mt);
1249 return S_OK;
1251 return VFW_S_NO_MORE_ITEMS;
1254 static HRESULT testsink_connect(struct strmbase_sink *iface, IPin *peer, const AM_MEDIA_TYPE *mt)
1256 struct testsink *filter = impl_sink_from_strmbase_filter(iface->pin.filter);
1257 if (filter->reject_avi && IsEqualGUID(&mt->subtype, &MEDIASUBTYPE_Avi))
1258 return VFW_E_TYPE_NOT_ACCEPTED;
1259 IPin_QueryInterface(peer, &IID_IAsyncReader, (void **)&filter->reader);
1260 return S_OK;
1263 static void testsink_disconnect(struct strmbase_sink *iface)
1265 struct testsink *filter = impl_sink_from_strmbase_filter(iface->pin.filter);
1266 IAsyncReader_Release(filter->reader);
1267 filter->reader = NULL;
1270 static const struct strmbase_sink_ops testsink_pin_ops =
1272 .base.pin_get_media_type = testsink_get_media_type,
1273 .sink_connect = testsink_connect,
1274 .sink_disconnect = testsink_disconnect,
1277 static void testsink_init(struct testsink *filter)
1279 static const GUID clsid = {0xabacab};
1280 memset(filter, 0, sizeof(*filter));
1281 strmbase_filter_init(&filter->filter, NULL, &clsid, &testsink_ops);
1282 strmbase_sink_init(&filter->pin, &filter->filter, L"", &testsink_pin_ops, NULL);
1285 static void test_connect_pin(void)
1287 AM_MEDIA_TYPE req_mt =
1289 .majortype = MEDIATYPE_Stream,
1290 .subtype = MEDIASUBTYPE_Avi,
1291 .formattype = FORMAT_None,
1292 .lSampleSize = 888,
1294 const WCHAR *filename = load_resource(L"test.avi");
1295 IBaseFilter *filter = create_file_source();
1296 AM_MEDIA_TYPE mt, *source_mt;
1297 struct testsink testsink;
1298 IEnumMediaTypes *enummt;
1299 IMediaControl *control;
1300 IFilterGraph2 *graph;
1301 IPin *source, *peer;
1302 BYTE my_format = 1;
1303 HRESULT hr;
1304 ULONG ref;
1305 BOOL ret;
1307 testsink_init(&testsink);
1308 CoCreateInstance(&CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER,
1309 &IID_IFilterGraph2, (void **)&graph);
1310 IFilterGraph2_AddFilter(graph, &testsink.filter.IBaseFilter_iface, L"sink");
1311 IFilterGraph2_AddFilter(graph, filter, L"file source");
1312 IFilterGraph2_QueryInterface(graph, &IID_IMediaControl, (void **)&control);
1313 load_file(filter, filename);
1314 IBaseFilter_FindPin(filter, L"Output", &source);
1316 IPin_EnumMediaTypes(source, &enummt);
1317 IEnumMediaTypes_Next(enummt, 1, &source_mt, NULL);
1318 IEnumMediaTypes_Release(enummt);
1320 peer = (IPin *)0xdeadbeef;
1321 hr = IPin_ConnectedTo(source, &peer);
1322 ok(hr == VFW_E_NOT_CONNECTED, "Got hr %#lx.\n", hr);
1323 ok(!peer, "Got peer %p.\n", peer);
1325 hr = IPin_ConnectionMediaType(source, &mt);
1326 ok(hr == VFW_E_NOT_CONNECTED, "Got hr %#lx.\n", hr);
1328 /* Test exact connection. */
1330 hr = IMediaControl_Pause(control);
1331 ok(hr == S_OK, "Got hr %#lx.\n", hr);
1332 hr = IFilterGraph2_ConnectDirect(graph, source, &testsink.pin.pin.IPin_iface, &req_mt);
1333 ok(hr == VFW_E_NOT_STOPPED, "Got hr %#lx.\n", hr);
1334 hr = IMediaControl_Stop(control);
1335 ok(hr == S_OK, "Got hr %#lx.\n", hr);
1337 hr = IFilterGraph2_ConnectDirect(graph, source, &testsink.pin.pin.IPin_iface, &req_mt);
1338 ok(hr == S_OK, "Got hr %#lx.\n", hr);
1340 hr = IPin_ConnectedTo(source, &peer);
1341 ok(hr == S_OK, "Got hr %#lx.\n", hr);
1342 ok(peer == &testsink.pin.pin.IPin_iface, "Got peer %p.\n", peer);
1343 IPin_Release(peer);
1345 hr = IPin_ConnectionMediaType(source, &mt);
1346 ok(hr == S_OK, "Got hr %#lx.\n", hr);
1347 ok(compare_media_types(&mt, &req_mt), "Media types didn't match.\n");
1348 ok(compare_media_types(&testsink.pin.pin.mt, &req_mt), "Media types didn't match.\n");
1350 hr = IMediaControl_Pause(control);
1351 ok(hr == S_OK, "Got hr %#lx.\n", hr);
1352 hr = IFilterGraph2_Disconnect(graph, source);
1353 ok(hr == VFW_E_NOT_STOPPED, "Got hr %#lx.\n", hr);
1354 hr = IMediaControl_Stop(control);
1355 ok(hr == S_OK, "Got hr %#lx.\n", hr);
1357 hr = IFilterGraph2_Disconnect(graph, source);
1358 ok(hr == S_OK, "Got hr %#lx.\n", hr);
1359 hr = IFilterGraph2_Disconnect(graph, source);
1360 ok(hr == S_FALSE, "Got hr %#lx.\n", hr);
1361 ok(testsink.pin.pin.peer == source, "Got peer %p.\n", testsink.pin.pin.peer);
1362 IFilterGraph2_Disconnect(graph, &testsink.pin.pin.IPin_iface);
1364 req_mt.pbFormat = &my_format;
1365 req_mt.cbFormat = sizeof(my_format);
1366 hr = IFilterGraph2_ConnectDirect(graph, source, &testsink.pin.pin.IPin_iface, &req_mt);
1367 ok(hr == S_OK, "Got hr %#lx.\n", hr);
1368 ok(compare_media_types(&testsink.pin.pin.mt, &req_mt), "Media types didn't match.\n");
1369 IFilterGraph2_Disconnect(graph, source);
1370 IFilterGraph2_Disconnect(graph, &testsink.pin.pin.IPin_iface);
1371 req_mt.pbFormat = NULL;
1372 req_mt.cbFormat = 0;
1374 req_mt.majortype = MEDIATYPE_Video;
1375 hr = IFilterGraph2_ConnectDirect(graph, source, &testsink.pin.pin.IPin_iface, &req_mt);
1376 ok(hr == VFW_E_TYPE_NOT_ACCEPTED, "Got hr %#lx.\n", hr);
1377 req_mt.majortype = MEDIATYPE_Stream;
1379 req_mt.subtype = MEDIASUBTYPE_RGB8;
1380 hr = IFilterGraph2_ConnectDirect(graph, source, &testsink.pin.pin.IPin_iface, &req_mt);
1381 ok(hr == S_OK, "Got hr %#lx.\n", hr);
1382 ok(compare_media_types(&testsink.pin.pin.mt, &req_mt), "Media types didn't match.\n");
1383 IFilterGraph2_Disconnect(graph, source);
1384 IFilterGraph2_Disconnect(graph, &testsink.pin.pin.IPin_iface);
1385 req_mt.subtype = GUID_NULL;
1386 hr = IFilterGraph2_ConnectDirect(graph, source, &testsink.pin.pin.IPin_iface, &req_mt);
1387 ok(hr == VFW_E_TYPE_NOT_ACCEPTED, "Got hr %#lx.\n", hr);
1388 req_mt.subtype = MEDIASUBTYPE_Avi;
1390 /* Test connection with wildcards. */
1392 hr = IFilterGraph2_ConnectDirect(graph, source, &testsink.pin.pin.IPin_iface, NULL);
1393 ok(hr == S_OK, "Got hr %#lx.\n", hr);
1394 ok(compare_media_types(&testsink.pin.pin.mt, source_mt), "Media types didn't match.\n");
1395 IFilterGraph2_Disconnect(graph, source);
1396 IFilterGraph2_Disconnect(graph, &testsink.pin.pin.IPin_iface);
1398 req_mt.formattype = GUID_NULL;
1399 hr = IFilterGraph2_ConnectDirect(graph, source, &testsink.pin.pin.IPin_iface, &req_mt);
1400 ok(hr == S_OK, "Got hr %#lx.\n", hr);
1401 ok(compare_media_types(&testsink.pin.pin.mt, source_mt), "Media types didn't match.\n");
1402 IFilterGraph2_Disconnect(graph, source);
1403 IFilterGraph2_Disconnect(graph, &testsink.pin.pin.IPin_iface);
1405 req_mt.formattype = FORMAT_None;
1406 req_mt.majortype = GUID_NULL;
1407 hr = IFilterGraph2_ConnectDirect(graph, source, &testsink.pin.pin.IPin_iface, &req_mt);
1408 ok(hr == VFW_E_NO_ACCEPTABLE_TYPES, "Got hr %#lx.\n", hr);
1410 req_mt.formattype = GUID_NULL;
1411 hr = IFilterGraph2_ConnectDirect(graph, source, &testsink.pin.pin.IPin_iface, &req_mt);
1412 ok(hr == S_OK, "Got hr %#lx.\n", hr);
1413 ok(compare_media_types(&testsink.pin.pin.mt, source_mt), "Media types didn't match.\n");
1414 IFilterGraph2_Disconnect(graph, source);
1415 IFilterGraph2_Disconnect(graph, &testsink.pin.pin.IPin_iface);
1417 req_mt.subtype = MEDIASUBTYPE_RGB8;
1418 hr = IFilterGraph2_ConnectDirect(graph, source, &testsink.pin.pin.IPin_iface, &req_mt);
1419 ok(hr == VFW_E_NO_ACCEPTABLE_TYPES, "Got hr %#lx.\n", hr);
1421 req_mt.subtype = GUID_NULL;
1422 hr = IFilterGraph2_ConnectDirect(graph, source, &testsink.pin.pin.IPin_iface, &req_mt);
1423 ok(hr == S_OK, "Got hr %#lx.\n", hr);
1424 ok(compare_media_types(&testsink.pin.pin.mt, source_mt), "Media types didn't match.\n");
1425 IFilterGraph2_Disconnect(graph, source);
1426 IFilterGraph2_Disconnect(graph, &testsink.pin.pin.IPin_iface);
1428 req_mt.majortype = MEDIATYPE_Stream;
1429 req_mt.subtype = MEDIASUBTYPE_RGB8;
1430 hr = IFilterGraph2_ConnectDirect(graph, source, &testsink.pin.pin.IPin_iface, &req_mt);
1431 ok(hr == VFW_E_NO_ACCEPTABLE_TYPES, "Got hr %#lx.\n", hr);
1433 req_mt.subtype = GUID_NULL;
1434 hr = IFilterGraph2_ConnectDirect(graph, source, &testsink.pin.pin.IPin_iface, &req_mt);
1435 ok(hr == S_OK, "Got hr %#lx.\n", hr);
1436 ok(compare_media_types(&testsink.pin.pin.mt, source_mt), "Media types didn't match.\n");
1437 IFilterGraph2_Disconnect(graph, source);
1438 IFilterGraph2_Disconnect(graph, &testsink.pin.pin.IPin_iface);
1440 req_mt.majortype = MEDIATYPE_Video;
1441 hr = IFilterGraph2_ConnectDirect(graph, source, &testsink.pin.pin.IPin_iface, &req_mt);
1442 ok(hr == VFW_E_NO_ACCEPTABLE_TYPES, "Got hr %#lx.\n", hr);
1444 /* The second type (i.e. whose subtype is GUID_NULL) is not tried. This is
1445 * consistent with its being rejected by IPin::QueryAccept(). */
1446 testsink.reject_avi = TRUE;
1447 hr = IFilterGraph2_ConnectDirect(graph, source, &testsink.pin.pin.IPin_iface, NULL);
1448 ok(hr == VFW_E_NO_ACCEPTABLE_TYPES, "Got hr %#lx.\n", hr);
1450 /* But any types we expose are tried. */
1451 testsink.mt = &mt;
1452 memset(&mt, 0, sizeof(mt));
1453 mt.majortype = MEDIATYPE_Video;
1454 mt.subtype = MEDIASUBTYPE_RGB8;
1455 mt.formattype = FORMAT_None;
1456 hr = IFilterGraph2_ConnectDirect(graph, source, &testsink.pin.pin.IPin_iface, NULL);
1457 ok(hr == VFW_E_NO_ACCEPTABLE_TYPES, "Got hr %#lx.\n", hr);
1459 mt.majortype = MEDIATYPE_Stream;
1460 hr = IFilterGraph2_ConnectDirect(graph, source, &testsink.pin.pin.IPin_iface, NULL);
1461 ok(hr == S_OK, "Got hr %#lx.\n", hr);
1462 ok(compare_media_types(&testsink.pin.pin.mt, &mt), "Media types didn't match.\n");
1463 IFilterGraph2_Disconnect(graph, source);
1464 IFilterGraph2_Disconnect(graph, &testsink.pin.pin.IPin_iface);
1466 CoTaskMemFree(source_mt);
1467 IPin_Release(source);
1468 IMediaControl_Release(control);
1469 ref = IFilterGraph2_Release(graph);
1470 ok(!ref, "Got outstanding refcount %ld.\n", ref);
1471 ref = IBaseFilter_Release(filter);
1472 ok(!ref, "Got outstanding refcount %ld.\n", ref);
1473 ref = IBaseFilter_Release(&testsink.filter.IBaseFilter_iface);
1474 ok(!ref, "Got outstanding refcount %ld.\n", ref);
1475 ret = DeleteFileW(filename);
1476 ok(ret, "Failed to delete file, error %lu.\n", GetLastError());
1479 START_TEST(filesource)
1481 CoInitialize(NULL);
1483 test_interfaces();
1484 test_aggregation();
1485 test_enum_pins();
1486 test_find_pin();
1487 test_pin_info();
1488 test_unconnected_filter_state();
1489 test_file_source_filter();
1490 test_async_reader();
1491 test_enum_media_types();
1492 test_connect_pin();
1494 CoUninitialize();