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
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
);
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
];
50 GetTempPathW(ARRAY_SIZE(pathW
), pathW
);
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");
67 static void load_file(IBaseFilter
*filter
, const WCHAR
*filename
)
69 IFileSourceFilter
*filesource
;
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
;
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
);
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();
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
);
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;
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
,
172 static IUnknown test_outer
= {&outer_vtbl
};
174 static void test_aggregation(void)
176 IBaseFilter
*filter
, *filter2
;
177 IUnknown
*unk
, *unk2
;
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)
246 "\x52\x49\x46\x46xxxx\x41\x56\x49\x20",
252 "\x00\x00\x01\xBA\x21\x00\x01\x00\x01\x80\x00\x01\x00\x00\x01\xBB",
254 &MEDIASUBTYPE_MPEG1System
,
260 &MEDIASUBTYPE_MPEG1Video
,
266 &MEDIASUBTYPE_MPEG1Audio
,
270 "\x00\x00\x01\xBA\x40",
272 &MEDIASUBTYPE_MPEG2_PROGRAM
,
276 "\x52\x49\x46\x46xxxx\x57\x41\x56\x45",
287 WCHAR path
[MAX_PATH
], temp
[MAX_PATH
], *filename
;
288 AM_MEDIA_TYPE mt
, file_mt
, *pmt
;
289 IFileSourceFilter
*filesource
;
290 IEnumMediaTypes
*enum_mt
;
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());
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
);
332 hr
= IFileSourceFilter_GetCurFile(filesource
, &olepath
, NULL
);
333 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
334 CoTaskMemFree(olepath
);
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");
370 hr
= IEnumMediaTypes_Next(enum_mt
, 1, &pmt
, NULL
);
371 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
373 mt
.subtype
= GUID_NULL
;
374 ok(!memcmp(pmt
, &mt
, sizeof(*pmt
)), "Media types did not match.\n");
377 hr
= IEnumMediaTypes_Next(enum_mt
, 1, &pmt
, NULL
);
378 ok(hr
== S_FALSE
, "Got hr %#lx.\n", hr
);
380 IEnumMediaTypes_Release(enum_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
);
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
;
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");
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
);
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
);
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
;
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();
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
);
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();
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
));
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();
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
;
762 IMemAllocator_GetBuffer(allocator
, &sample
, NULL
, NULL
, 0);
763 IMediaSample_GetPointer(sample
, &data
);
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
);
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
;
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
);
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
);
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
);
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
);
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
, ¶ms
, 0, NULL
);
915 ok(!WaitForSingleObject(thread
, 1000), "Wait timed out.\n");
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
;
932 HRESULT hr
= IAsyncReader_WaitForNext(reader
, 2000, &sample
, &cookie
);
933 ok(hr
== VFW_E_WRONG_STATE
, "Got hr %#lx.\n", hr
);
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
;
947 IMemAllocator_GetBuffer(allocator
, &sample
, NULL
, NULL
, 0);
948 IMediaSample_GetPointer(sample
, &data
);
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
);
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
);
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
;
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
++)
1034 WriteFile(file
, &b
, 1, &written
, NULL
);
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
);
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
);
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];
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
);
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());
1210 struct strmbase_filter filter
;
1211 struct strmbase_sink pin
;
1212 IAsyncReader
*reader
;
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
);
1226 return &filter
->pin
.pin
;
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
);
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
);
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
,
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
;
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
);
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. */
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
)
1488 test_unconnected_filter_state();
1489 test_file_source_filter();
1490 test_async_reader();
1491 test_enum_media_types();