2 * AVI splitter filter unit tests
4 * Copyright (C) 2007 Google (Lei Zhang)
5 * Copyright (C) 2008 Google (Maarten Lankhorst)
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 "wmcodecdsp.h"
25 #include "wine/strmbase.h"
26 #include "wine/test.h"
28 static const GUID testguid
= {0xfacade};
30 static IBaseFilter
*create_avi_splitter(void)
32 IBaseFilter
*filter
= NULL
;
33 HRESULT hr
= CoCreateInstance(&CLSID_AviSplitter
, NULL
, CLSCTX_INPROC_SERVER
,
34 &IID_IBaseFilter
, (void **)&filter
);
35 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
39 static inline BOOL
compare_media_types(const AM_MEDIA_TYPE
*a
, const AM_MEDIA_TYPE
*b
)
41 return !memcmp(a
, b
, offsetof(AM_MEDIA_TYPE
, pbFormat
))
42 && !memcmp(a
->pbFormat
, b
->pbFormat
, a
->cbFormat
);
45 static WCHAR
*load_resource(const WCHAR
*name
)
47 static WCHAR pathW
[MAX_PATH
];
53 GetTempPathW(ARRAY_SIZE(pathW
), pathW
);
56 file
= CreateFileW(pathW
, GENERIC_READ
|GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, 0, 0);
57 ok(file
!= INVALID_HANDLE_VALUE
, "Failed to create file %s, error %u.\n",
58 wine_dbgstr_w(pathW
), GetLastError());
60 res
= FindResourceW(NULL
, name
, (LPCWSTR
)RT_RCDATA
);
61 ok(!!res
, "Failed to load resource, error %u.\n", GetLastError());
62 ptr
= LockResource(LoadResource(GetModuleHandleA(NULL
), res
));
63 WriteFile(file
, ptr
, SizeofResource( GetModuleHandleA(NULL
), res
), &written
, NULL
);
64 ok(written
== SizeofResource(GetModuleHandleA(NULL
), res
), "Failed to write resource.\n");
70 static ULONG
get_refcount(void *iface
)
72 IUnknown
*unknown
= iface
;
73 IUnknown_AddRef(unknown
);
74 return IUnknown_Release(unknown
);
77 static IFilterGraph2
*connect_input(IBaseFilter
*splitter
, const WCHAR
*filename
)
79 IFileSourceFilter
*filesource
;
85 CoCreateInstance(&CLSID_AsyncReader
, NULL
, CLSCTX_INPROC_SERVER
,
86 &IID_IBaseFilter
, (void **)&reader
);
87 IBaseFilter_QueryInterface(reader
, &IID_IFileSourceFilter
, (void **)&filesource
);
88 IFileSourceFilter_Load(filesource
, filename
, NULL
);
90 CoCreateInstance(&CLSID_FilterGraph
, NULL
, CLSCTX_INPROC_SERVER
,
91 &IID_IFilterGraph2
, (void **)&graph
);
92 IFilterGraph2_AddFilter(graph
, reader
, NULL
);
93 IFilterGraph2_AddFilter(graph
, splitter
, NULL
);
95 IBaseFilter_FindPin(splitter
, L
"input pin", &sink
);
96 IBaseFilter_FindPin(reader
, L
"Output", &source
);
98 hr
= IFilterGraph2_ConnectDirect(graph
, source
, sink
, NULL
);
99 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
101 IPin_Release(source
);
103 IBaseFilter_Release(reader
);
104 IFileSourceFilter_Release(filesource
);
108 #define check_interface(a, b, c) check_interface_(__LINE__, a, b, c)
109 static void check_interface_(unsigned int line
, void *iface_ptr
, REFIID iid
, BOOL supported
)
111 IUnknown
*iface
= iface_ptr
;
112 HRESULT hr
, expected_hr
;
115 expected_hr
= supported
? S_OK
: E_NOINTERFACE
;
117 hr
= IUnknown_QueryInterface(iface
, iid
, (void **)&unk
);
118 ok_(__FILE__
, line
)(hr
== expected_hr
, "Got hr %#x, expected %#x.\n", hr
, expected_hr
);
120 IUnknown_Release(unk
);
123 static void test_interfaces(void)
125 const WCHAR
*filename
= load_resource(L
"test.avi");
126 IBaseFilter
*filter
= create_avi_splitter();
127 IFilterGraph2
*graph
= connect_input(filter
, filename
);
130 check_interface(filter
, &IID_IBaseFilter
, TRUE
);
131 check_interface(filter
, &IID_IMediaFilter
, TRUE
);
132 check_interface(filter
, &IID_IPersist
, TRUE
);
133 check_interface(filter
, &IID_IUnknown
, TRUE
);
135 check_interface(filter
, &IID_IAMFilterMiscFlags
, FALSE
);
136 check_interface(filter
, &IID_IBasicAudio
, FALSE
);
137 check_interface(filter
, &IID_IBasicVideo
, FALSE
);
138 check_interface(filter
, &IID_IKsPropertySet
, FALSE
);
139 check_interface(filter
, &IID_IMediaPosition
, FALSE
);
140 check_interface(filter
, &IID_IMediaSeeking
, FALSE
);
141 check_interface(filter
, &IID_IPersistPropertyBag
, FALSE
);
142 check_interface(filter
, &IID_IPin
, FALSE
);
143 check_interface(filter
, &IID_IQualityControl
, FALSE
);
144 check_interface(filter
, &IID_IQualProp
, FALSE
);
145 check_interface(filter
, &IID_IReferenceClock
, FALSE
);
146 check_interface(filter
, &IID_IVideoWindow
, FALSE
);
148 IBaseFilter_FindPin(filter
, L
"input pin", &pin
);
150 check_interface(pin
, &IID_IPin
, TRUE
);
151 check_interface(pin
, &IID_IUnknown
, TRUE
);
153 check_interface(pin
, &IID_IKsPropertySet
, FALSE
);
154 check_interface(pin
, &IID_IMemInputPin
, FALSE
);
155 check_interface(pin
, &IID_IMediaPosition
, FALSE
);
156 check_interface(pin
, &IID_IMediaSeeking
, FALSE
);
160 IBaseFilter_FindPin(filter
, L
"Stream 00", &pin
);
162 todo_wine
check_interface(pin
, &IID_IMediaPosition
, TRUE
);
163 check_interface(pin
, &IID_IMediaSeeking
, TRUE
);
164 check_interface(pin
, &IID_IPin
, TRUE
);
165 check_interface(pin
, &IID_IQualityControl
, TRUE
);
166 check_interface(pin
, &IID_IUnknown
, TRUE
);
168 check_interface(pin
, &IID_IAsyncReader
, FALSE
);
169 check_interface(pin
, &IID_IKsPropertySet
, FALSE
);
173 IBaseFilter_Release(filter
);
174 IFilterGraph2_Release(graph
);
175 DeleteFileW(filename
);
178 static const GUID test_iid
= {0x33333333};
179 static LONG outer_ref
= 1;
181 static HRESULT WINAPI
outer_QueryInterface(IUnknown
*iface
, REFIID iid
, void **out
)
183 if (IsEqualGUID(iid
, &IID_IUnknown
)
184 || IsEqualGUID(iid
, &IID_IBaseFilter
)
185 || IsEqualGUID(iid
, &test_iid
))
187 *out
= (IUnknown
*)0xdeadbeef;
190 ok(0, "unexpected call %s\n", wine_dbgstr_guid(iid
));
191 return E_NOINTERFACE
;
194 static ULONG WINAPI
outer_AddRef(IUnknown
*iface
)
196 return InterlockedIncrement(&outer_ref
);
199 static ULONG WINAPI
outer_Release(IUnknown
*iface
)
201 return InterlockedDecrement(&outer_ref
);
204 static const IUnknownVtbl outer_vtbl
=
206 outer_QueryInterface
,
211 static IUnknown test_outer
= {&outer_vtbl
};
213 static void test_aggregation(void)
215 IBaseFilter
*filter
, *filter2
;
216 IUnknown
*unk
, *unk2
;
220 filter
= (IBaseFilter
*)0xdeadbeef;
221 hr
= CoCreateInstance(&CLSID_AviSplitter
, &test_outer
, CLSCTX_INPROC_SERVER
,
222 &IID_IBaseFilter
, (void **)&filter
);
223 ok(hr
== E_NOINTERFACE
, "Got hr %#x.\n", hr
);
224 ok(!filter
, "Got interface %p.\n", filter
);
226 hr
= CoCreateInstance(&CLSID_AviSplitter
, &test_outer
, CLSCTX_INPROC_SERVER
,
227 &IID_IUnknown
, (void **)&unk
);
228 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
229 ok(outer_ref
== 1, "Got unexpected refcount %d.\n", outer_ref
);
230 ok(unk
!= &test_outer
, "Returned IUnknown should not be outer IUnknown.\n");
231 ref
= get_refcount(unk
);
232 ok(ref
== 1, "Got unexpected refcount %d.\n", ref
);
234 ref
= IUnknown_AddRef(unk
);
235 ok(ref
== 2, "Got unexpected refcount %d.\n", ref
);
236 ok(outer_ref
== 1, "Got unexpected refcount %d.\n", outer_ref
);
238 ref
= IUnknown_Release(unk
);
239 ok(ref
== 1, "Got unexpected refcount %d.\n", ref
);
240 ok(outer_ref
== 1, "Got unexpected refcount %d.\n", outer_ref
);
242 hr
= IUnknown_QueryInterface(unk
, &IID_IUnknown
, (void **)&unk2
);
243 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
244 ok(unk2
== unk
, "Got unexpected IUnknown %p.\n", unk2
);
245 IUnknown_Release(unk2
);
247 hr
= IUnknown_QueryInterface(unk
, &IID_IBaseFilter
, (void **)&filter
);
248 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
250 hr
= IBaseFilter_QueryInterface(filter
, &IID_IUnknown
, (void **)&unk2
);
251 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
252 ok(unk2
== (IUnknown
*)0xdeadbeef, "Got unexpected IUnknown %p.\n", unk2
);
254 hr
= IBaseFilter_QueryInterface(filter
, &IID_IBaseFilter
, (void **)&filter2
);
255 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
256 ok(filter2
== (IBaseFilter
*)0xdeadbeef, "Got unexpected IBaseFilter %p.\n", filter2
);
258 hr
= IUnknown_QueryInterface(unk
, &test_iid
, (void **)&unk2
);
259 ok(hr
== E_NOINTERFACE
, "Got hr %#x.\n", hr
);
260 ok(!unk2
, "Got unexpected IUnknown %p.\n", unk2
);
262 hr
= IBaseFilter_QueryInterface(filter
, &test_iid
, (void **)&unk2
);
263 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
264 ok(unk2
== (IUnknown
*)0xdeadbeef, "Got unexpected IUnknown %p.\n", unk2
);
266 IBaseFilter_Release(filter
);
267 ref
= IUnknown_Release(unk
);
268 ok(!ref
, "Got unexpected refcount %d.\n", ref
);
269 ok(outer_ref
== 1, "Got unexpected refcount %d.\n", outer_ref
);
272 static void test_enum_pins(void)
274 const WCHAR
*filename
= load_resource(L
"test.avi");
275 IBaseFilter
*filter
= create_avi_splitter();
276 IEnumPins
*enum1
, *enum2
;
277 IFilterGraph2
*graph
;
283 ref
= get_refcount(filter
);
284 ok(ref
== 1, "Got unexpected refcount %d.\n", ref
);
286 hr
= IBaseFilter_EnumPins(filter
, NULL
);
287 ok(hr
== E_POINTER
, "Got hr %#x.\n", hr
);
289 hr
= IBaseFilter_EnumPins(filter
, &enum1
);
290 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
291 ref
= get_refcount(filter
);
292 ok(ref
== 2, "Got unexpected refcount %d.\n", ref
);
293 ref
= get_refcount(enum1
);
294 ok(ref
== 1, "Got unexpected refcount %d.\n", ref
);
296 hr
= IEnumPins_Next(enum1
, 1, NULL
, NULL
);
297 ok(hr
== E_POINTER
, "Got hr %#x.\n", hr
);
299 hr
= IEnumPins_Next(enum1
, 1, pins
, NULL
);
300 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
301 ref
= get_refcount(filter
);
302 ok(ref
== 3, "Got unexpected refcount %d.\n", ref
);
303 ref
= get_refcount(pins
[0]);
304 ok(ref
== 3, "Got unexpected refcount %d.\n", ref
);
305 ref
= get_refcount(enum1
);
306 ok(ref
== 1, "Got unexpected refcount %d.\n", ref
);
307 IPin_Release(pins
[0]);
308 ref
= get_refcount(filter
);
309 ok(ref
== 2, "Got unexpected refcount %d.\n", ref
);
311 hr
= IEnumPins_Next(enum1
, 1, pins
, NULL
);
312 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
314 hr
= IEnumPins_Reset(enum1
);
315 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
317 hr
= IEnumPins_Next(enum1
, 1, pins
, &count
);
318 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
319 ok(count
== 1, "Got count %u.\n", count
);
320 IPin_Release(pins
[0]);
322 hr
= IEnumPins_Next(enum1
, 1, pins
, &count
);
323 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
324 ok(!count
, "Got count %u.\n", count
);
326 hr
= IEnumPins_Reset(enum1
);
327 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
329 hr
= IEnumPins_Next(enum1
, 2, pins
, NULL
);
330 ok(hr
== E_INVALIDARG
, "Got hr %#x.\n", hr
);
332 hr
= IEnumPins_Next(enum1
, 2, pins
, &count
);
333 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
334 ok(count
== 1, "Got count %u.\n", count
);
335 IPin_Release(pins
[0]);
337 hr
= IEnumPins_Reset(enum1
);
338 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
340 hr
= IEnumPins_Clone(enum1
, &enum2
);
341 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
343 hr
= IEnumPins_Skip(enum1
, 2);
344 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
346 hr
= IEnumPins_Skip(enum1
, 1);
347 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
349 hr
= IEnumPins_Skip(enum1
, 1);
350 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
352 hr
= IEnumPins_Next(enum1
, 1, pins
, NULL
);
353 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
355 hr
= IEnumPins_Next(enum2
, 1, pins
, NULL
);
356 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
357 IPin_Release(pins
[0]);
359 IEnumPins_Release(enum2
);
361 graph
= connect_input(filter
, filename
);
363 hr
= IEnumPins_Next(enum1
, 1, pins
, NULL
);
364 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
366 hr
= IEnumPins_Reset(enum1
);
367 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
369 hr
= IEnumPins_Next(enum1
, 1, pins
, NULL
);
370 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
371 IPin_Release(pins
[0]);
373 hr
= IEnumPins_Next(enum1
, 1, pins
, NULL
);
374 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
375 IPin_Release(pins
[0]);
377 hr
= IEnumPins_Next(enum1
, 1, pins
, NULL
);
378 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
380 hr
= IEnumPins_Reset(enum1
);
381 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
383 hr
= IEnumPins_Next(enum1
, 2, pins
, &count
);
384 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
385 ok(count
== 2, "Got count %u.\n", count
);
386 IPin_Release(pins
[0]);
387 IPin_Release(pins
[1]);
389 hr
= IEnumPins_Reset(enum1
);
390 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
392 hr
= IEnumPins_Next(enum1
, 3, pins
, &count
);
393 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
394 ok(count
== 2, "Got count %u.\n", count
);
395 IPin_Release(pins
[0]);
396 IPin_Release(pins
[1]);
398 IEnumPins_Release(enum1
);
399 IFilterGraph2_Release(graph
);
400 ref
= IBaseFilter_Release(filter
);
401 ok(!ref
, "Got outstanding refcount %d.\n", ref
);
402 ret
= DeleteFileW(filename
);
403 ok(ret
, "Failed to delete file, error %u.\n", GetLastError());
406 static void test_find_pin(void)
408 const WCHAR
*filename
= load_resource(L
"test.avi");
409 IBaseFilter
*filter
= create_avi_splitter();
410 IFilterGraph2
*graph
;
411 IEnumPins
*enum_pins
;
417 hr
= IBaseFilter_FindPin(filter
, L
"input pin", &pin
);
418 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
421 hr
= IBaseFilter_FindPin(filter
, L
"Stream 00", &pin
);
422 ok(hr
== VFW_E_NOT_FOUND
, "Got hr %#x.\n", hr
);
424 hr
= IBaseFilter_FindPin(filter
, L
"Input", &pin
);
425 ok(hr
== VFW_E_NOT_FOUND
, "Got hr %#x.\n", hr
);
427 graph
= connect_input(filter
, filename
);
429 hr
= IBaseFilter_EnumPins(filter
, &enum_pins
);
430 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
432 hr
= IEnumPins_Next(enum_pins
, 1, &pin2
, NULL
);
433 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
435 hr
= IBaseFilter_FindPin(filter
, L
"Stream 00", &pin
);
436 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
437 ok(pin
== pin2
, "Expected pin %p, got %p.\n", pin2
, pin
);
441 hr
= IEnumPins_Next(enum_pins
, 1, &pin2
, NULL
);
442 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
444 hr
= IBaseFilter_FindPin(filter
, L
"input pin", &pin
);
445 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
446 ok(pin
== pin2
, "Expected pin %p, got %p.\n", pin2
, pin
);
450 IEnumPins_Release(enum_pins
);
451 IFilterGraph2_Release(graph
);
452 ref
= IBaseFilter_Release(filter
);
453 ok(!ref
, "Got outstanding refcount %d.\n", ref
);
454 ret
= DeleteFileW(filename
);
455 ok(ret
, "Failed to delete file, error %u.\n", GetLastError());
458 static void test_pin_info(void)
460 const WCHAR
*filename
= load_resource(L
"test.avi");
461 IBaseFilter
*filter
= create_avi_splitter();
462 ULONG ref
, expect_ref
;
463 IFilterGraph2
*graph
;
471 graph
= connect_input(filter
, filename
);
473 hr
= IBaseFilter_FindPin(filter
, L
"input pin", &pin
);
474 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
475 expect_ref
= get_refcount(filter
);
476 ref
= get_refcount(pin
);
477 ok(ref
== expect_ref
, "Got unexpected refcount %d.\n", ref
);
479 hr
= IPin_QueryPinInfo(pin
, &info
);
480 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
481 ok(info
.pFilter
== filter
, "Expected filter %p, got %p.\n", filter
, info
.pFilter
);
482 ok(info
.dir
== PINDIR_INPUT
, "Got direction %d.\n", info
.dir
);
483 ok(!wcscmp(info
.achName
, L
"input pin"), "Got name %s.\n", wine_dbgstr_w(info
.achName
));
484 ref
= get_refcount(filter
);
485 ok(ref
== expect_ref
+ 1, "Got unexpected refcount %d.\n", ref
);
486 ref
= get_refcount(pin
);
487 ok(ref
== expect_ref
+ 1, "Got unexpected refcount %d.\n", ref
);
488 IBaseFilter_Release(info
.pFilter
);
490 hr
= IPin_QueryDirection(pin
, &dir
);
491 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
492 ok(dir
== PINDIR_INPUT
, "Got direction %d.\n", dir
);
494 hr
= IPin_QueryId(pin
, &id
);
495 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
496 ok(!wcscmp(id
, L
"input pin"), "Got id %s.\n", wine_dbgstr_w(id
));
501 hr
= IBaseFilter_FindPin(filter
, L
"Stream 00", &pin
);
502 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
504 check_interface(pin
, &IID_IPin
, TRUE
);
505 check_interface(pin
, &IID_IMediaSeeking
, TRUE
);
507 hr
= IPin_QueryPinInfo(pin
, &info
);
508 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
509 ok(info
.pFilter
== filter
, "Expected filter %p, got %p.\n", filter
, info
.pFilter
);
510 ok(info
.dir
== PINDIR_OUTPUT
, "Got direction %d.\n", info
.dir
);
511 ok(!wcscmp(info
.achName
, L
"Stream 00"), "Got name %s.\n", wine_dbgstr_w(info
.achName
));
512 IBaseFilter_Release(info
.pFilter
);
514 hr
= IPin_QueryDirection(pin
, &dir
);
515 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
516 ok(dir
== PINDIR_OUTPUT
, "Got direction %d.\n", dir
);
518 hr
= IPin_QueryId(pin
, &id
);
519 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
520 ok(!wcscmp(id
, L
"Stream 00"), "Got id %s.\n", wine_dbgstr_w(id
));
525 IFilterGraph2_Release(graph
);
526 ref
= IBaseFilter_Release(filter
);
527 ok(!ref
, "Got outstanding refcount %d.\n", ref
);
528 ret
= DeleteFileW(filename
);
529 ok(ret
, "Failed to delete file, error %u.\n", GetLastError());
532 static void test_media_types(void)
534 static const VIDEOINFOHEADER expect_vih
=
536 .AvgTimePerFrame
= 1000 * 10000,
537 .bmiHeader
.biSize
= sizeof(BITMAPINFOHEADER
),
538 .bmiHeader
.biWidth
= 32,
539 .bmiHeader
.biHeight
= 24,
540 .bmiHeader
.biPlanes
= 1,
541 .bmiHeader
.biBitCount
= 12,
542 .bmiHeader
.biCompression
= mmioFOURCC('I','4','2','0'),
543 .bmiHeader
.biSizeImage
= 32 * 24 * 12 / 8,
546 const WCHAR
*filename
= load_resource(L
"test.avi");
547 IBaseFilter
*filter
= create_avi_splitter();
548 AM_MEDIA_TYPE mt
= {{0}}, *pmt
;
549 IEnumMediaTypes
*enummt
;
550 VIDEOINFOHEADER
*vih
;
551 IFilterGraph2
*graph
;
557 IBaseFilter_FindPin(filter
, L
"input pin", &pin
);
559 hr
= IPin_EnumMediaTypes(pin
, &enummt
);
560 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
562 hr
= IEnumMediaTypes_Next(enummt
, 1, &pmt
, NULL
);
563 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
565 IEnumMediaTypes_Release(enummt
);
567 mt
.majortype
= MEDIATYPE_Stream
;
568 mt
.subtype
= MEDIASUBTYPE_Avi
;
569 hr
= IPin_QueryAccept(pin
, &mt
);
570 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
572 mt
.bFixedSizeSamples
= TRUE
;
573 mt
.bTemporalCompression
= TRUE
;
574 mt
.lSampleSize
= 123;
575 mt
.formattype
= FORMAT_WaveFormatEx
;
576 hr
= IPin_QueryAccept(pin
, &mt
);
577 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
579 mt
.majortype
= GUID_NULL
;
580 hr
= IPin_QueryAccept(pin
, &mt
);
581 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
582 mt
.majortype
= MEDIATYPE_Stream
;
584 mt
.subtype
= GUID_NULL
;
585 hr
= IPin_QueryAccept(pin
, &mt
);
586 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
587 mt
.subtype
= MEDIASUBTYPE_Avi
;
589 graph
= connect_input(filter
, filename
);
591 hr
= IPin_EnumMediaTypes(pin
, &enummt
);
592 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
594 hr
= IEnumMediaTypes_Next(enummt
, 1, &pmt
, NULL
);
595 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
597 IEnumMediaTypes_Release(enummt
);
600 IBaseFilter_FindPin(filter
, L
"Stream 00", &pin
);
602 hr
= IPin_EnumMediaTypes(pin
, &enummt
);
603 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
605 hr
= IEnumMediaTypes_Next(enummt
, 1, &pmt
, NULL
);
606 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
607 ok(IsEqualGUID(&pmt
->majortype
, &MEDIATYPE_Video
), "Got major type %s\n",
608 wine_dbgstr_guid(&pmt
->majortype
));
609 ok(IsEqualGUID(&pmt
->subtype
, &MEDIASUBTYPE_I420
), "Got subtype %s\n",
610 wine_dbgstr_guid(&pmt
->subtype
));
611 ok(!pmt
->bFixedSizeSamples
, "Got fixed size %d.\n", pmt
->bFixedSizeSamples
);
612 todo_wine
ok(!pmt
->bTemporalCompression
, "Got temporal compression %d.\n", pmt
->bTemporalCompression
);
613 ok(pmt
->lSampleSize
== 1, "Got sample size %u.\n", pmt
->lSampleSize
);
614 ok(IsEqualGUID(&pmt
->formattype
, &FORMAT_VideoInfo
), "Got format type %s.\n",
615 wine_dbgstr_guid(&pmt
->formattype
));
616 ok(!pmt
->pUnk
, "Got pUnk %p.\n", pmt
->pUnk
);
617 ok(pmt
->cbFormat
== sizeof(VIDEOINFOHEADER
), "Got format size %u.\n", pmt
->cbFormat
);
618 ok(!memcmp(pmt
->pbFormat
, &expect_vih
, sizeof(VIDEOINFOHEADER
)), "Format blocks didn't match.\n");
620 hr
= IPin_QueryAccept(pin
, pmt
);
621 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
623 pmt
->bFixedSizeSamples
= TRUE
;
624 pmt
->bTemporalCompression
= TRUE
;
625 pmt
->lSampleSize
= 123;
626 hr
= IPin_QueryAccept(pin
, pmt
);
627 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
629 pmt
->majortype
= GUID_NULL
;
630 hr
= IPin_QueryAccept(pin
, pmt
);
631 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
632 pmt
->majortype
= MEDIATYPE_Video
;
634 pmt
->subtype
= GUID_NULL
;
635 hr
= IPin_QueryAccept(pin
, pmt
);
636 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
637 pmt
->subtype
= MEDIASUBTYPE_I420
;
639 pmt
->formattype
= GUID_NULL
;
640 hr
= IPin_QueryAccept(pin
, pmt
);
641 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
642 pmt
->formattype
= FORMAT_None
;
643 hr
= IPin_QueryAccept(pin
, pmt
);
644 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
645 pmt
->formattype
= FORMAT_VideoInfo
;
647 vih
= (VIDEOINFOHEADER
*)pmt
->pbFormat
;
649 vih
->AvgTimePerFrame
= 10000;
650 hr
= IPin_QueryAccept(pin
, pmt
);
651 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
652 vih
->AvgTimePerFrame
= 1000 * 10000;
654 vih
->dwBitRate
= 1000000;
655 hr
= IPin_QueryAccept(pin
, pmt
);
656 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
659 SetRect(&vih
->rcSource
, 0, 0, 32, 24);
660 hr
= IPin_QueryAccept(pin
, pmt
);
661 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
662 SetRect(&vih
->rcSource
, 0, 0, 0, 0);
664 vih
->bmiHeader
.biCompression
= BI_RGB
;
665 hr
= IPin_QueryAccept(pin
, pmt
);
666 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
667 vih
->bmiHeader
.biCompression
= mmioFOURCC('I','4','2','0');
669 CoTaskMemFree(pmt
->pbFormat
);
672 hr
= IEnumMediaTypes_Next(enummt
, 1, &pmt
, NULL
);
673 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
675 IEnumMediaTypes_Release(enummt
);
678 IFilterGraph2_Release(graph
);
679 ref
= IBaseFilter_Release(filter
);
680 ok(!ref
, "Got outstanding refcount %d.\n", ref
);
681 ret
= DeleteFileW(filename
);
682 ok(ret
, "Failed to delete file, error %u.\n", GetLastError());
685 static void test_enum_media_types(void)
687 const WCHAR
*filename
= load_resource(L
"test.avi");
688 IBaseFilter
*filter
= create_avi_splitter();
689 IFilterGraph2
*graph
= connect_input(filter
, filename
);
690 IEnumMediaTypes
*enum1
, *enum2
;
691 AM_MEDIA_TYPE
*mts
[2];
697 IBaseFilter_FindPin(filter
, L
"input pin", &pin
);
699 hr
= IPin_EnumMediaTypes(pin
, &enum1
);
700 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
702 hr
= IEnumMediaTypes_Next(enum1
, 1, mts
, NULL
);
703 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
705 hr
= IEnumMediaTypes_Next(enum1
, 1, mts
, &count
);
706 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
707 ok(!count
, "Got count %u.\n", count
);
709 hr
= IEnumMediaTypes_Reset(enum1
);
710 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
712 hr
= IEnumMediaTypes_Next(enum1
, 1, mts
, NULL
);
713 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
715 hr
= IEnumMediaTypes_Clone(enum1
, &enum2
);
716 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
718 hr
= IEnumMediaTypes_Skip(enum1
, 1);
719 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
721 hr
= IEnumMediaTypes_Next(enum2
, 1, mts
, NULL
);
722 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
724 IEnumMediaTypes_Release(enum1
);
725 IEnumMediaTypes_Release(enum2
);
728 IBaseFilter_FindPin(filter
, L
"Stream 00", &pin
);
730 hr
= IPin_EnumMediaTypes(pin
, &enum1
);
731 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
733 hr
= IEnumMediaTypes_Next(enum1
, 1, mts
, NULL
);
734 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
735 CoTaskMemFree(mts
[0]->pbFormat
);
736 CoTaskMemFree(mts
[0]);
738 hr
= IEnumMediaTypes_Next(enum1
, 1, mts
, NULL
);
739 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
741 hr
= IEnumMediaTypes_Reset(enum1
);
742 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
744 hr
= IEnumMediaTypes_Next(enum1
, 1, mts
, &count
);
745 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
746 ok(count
== 1, "Got count %u.\n", count
);
747 CoTaskMemFree(mts
[0]->pbFormat
);
748 CoTaskMemFree(mts
[0]);
750 hr
= IEnumMediaTypes_Next(enum1
, 1, mts
, &count
);
751 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
752 ok(!count
, "Got count %u.\n", count
);
754 hr
= IEnumMediaTypes_Reset(enum1
);
755 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
757 hr
= IEnumMediaTypes_Next(enum1
, 2, mts
, &count
);
758 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
759 ok(count
== 1, "Got count %u.\n", count
);
760 CoTaskMemFree(mts
[0]->pbFormat
);
761 CoTaskMemFree(mts
[0]);
763 hr
= IEnumMediaTypes_Reset(enum1
);
764 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
766 hr
= IEnumMediaTypes_Clone(enum1
, &enum2
);
767 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
769 hr
= IEnumMediaTypes_Skip(enum1
, 2);
770 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
772 hr
= IEnumMediaTypes_Skip(enum1
, 1);
773 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
775 hr
= IEnumMediaTypes_Reset(enum1
);
776 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
778 hr
= IEnumMediaTypes_Skip(enum1
, 1);
779 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
781 hr
= IEnumMediaTypes_Skip(enum1
, 1);
782 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
784 hr
= IEnumMediaTypes_Next(enum1
, 1, mts
, NULL
);
785 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
787 hr
= IEnumMediaTypes_Next(enum2
, 1, mts
, NULL
);
788 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
789 CoTaskMemFree(mts
[0]->pbFormat
);
790 CoTaskMemFree(mts
[0]);
792 IEnumMediaTypes_Release(enum1
);
793 IEnumMediaTypes_Release(enum2
);
796 IFilterGraph2_Release(graph
);
797 ref
= IBaseFilter_Release(filter
);
798 ok(!ref
, "Got outstanding refcount %d.\n", ref
);
799 ret
= DeleteFileW(filename
);
800 ok(ret
, "Failed to delete file, error %u.\n", GetLastError());
805 struct strmbase_filter filter
;
806 struct strmbase_source source
;
807 struct strmbase_sink sink
;
808 IAsyncReader IAsyncReader_iface
, *reader
;
809 const AM_MEDIA_TYPE
*mt
;
811 unsigned int sample_count
, eos_count
, new_segment_count
;
812 REFERENCE_TIME seek_start
, seek_end
;
815 static inline struct testfilter
*impl_from_strmbase_filter(struct strmbase_filter
*iface
)
817 return CONTAINING_RECORD(iface
, struct testfilter
, filter
);
820 static struct strmbase_pin
*testfilter_get_pin(struct strmbase_filter
*iface
, unsigned int index
)
822 struct testfilter
*filter
= impl_from_strmbase_filter(iface
);
824 return &filter
->source
.pin
;
826 return &filter
->sink
.pin
;
830 static void testfilter_destroy(struct strmbase_filter
*iface
)
832 struct testfilter
*filter
= impl_from_strmbase_filter(iface
);
833 CloseHandle(filter
->eos_event
);
834 strmbase_source_cleanup(&filter
->source
);
835 strmbase_sink_cleanup(&filter
->sink
);
836 strmbase_filter_cleanup(&filter
->filter
);
839 static const struct strmbase_filter_ops testfilter_ops
=
841 .filter_get_pin
= testfilter_get_pin
,
842 .filter_destroy
= testfilter_destroy
,
845 static HRESULT
testsource_query_interface(struct strmbase_pin
*iface
, REFIID iid
, void **out
)
847 struct testfilter
*filter
= impl_from_strmbase_filter(iface
->filter
);
849 if (IsEqualGUID(iid
, &IID_IAsyncReader
))
850 *out
= &filter
->IAsyncReader_iface
;
852 return E_NOINTERFACE
;
854 IUnknown_AddRef((IUnknown
*)*out
);
858 static HRESULT WINAPI
testsource_AttemptConnection(struct strmbase_source
*iface
,
859 IPin
*peer
, const AM_MEDIA_TYPE
*mt
)
863 iface
->pin
.peer
= peer
;
865 CopyMediaType(&iface
->pin
.mt
, mt
);
867 if (FAILED(hr
= IPin_ReceiveConnection(peer
, &iface
->pin
.IPin_iface
, mt
)))
869 ok(hr
== VFW_E_TYPE_NOT_ACCEPTED
, "Got hr %#x.\n", hr
);
871 iface
->pin
.peer
= NULL
;
872 FreeMediaType(&iface
->pin
.mt
);
878 static const struct strmbase_source_ops testsource_ops
=
880 .base
.pin_query_interface
= testsource_query_interface
,
881 .pfnAttemptConnection
= testsource_AttemptConnection
,
884 static HRESULT
testsink_query_interface(struct strmbase_pin
*iface
, REFIID iid
, void **out
)
886 struct testfilter
*filter
= impl_from_strmbase_filter(iface
->filter
);
888 if (IsEqualGUID(iid
, &IID_IMemInputPin
))
889 *out
= &filter
->sink
.IMemInputPin_iface
;
891 return E_NOINTERFACE
;
893 IUnknown_AddRef((IUnknown
*)*out
);
897 static HRESULT
testsink_query_accept(struct strmbase_pin
*iface
, const AM_MEDIA_TYPE
*mt
)
899 struct testfilter
*filter
= impl_from_strmbase_filter(iface
->filter
);
900 if (filter
->mt
&& !compare_media_types(mt
, filter
->mt
))
905 static HRESULT
testsink_get_media_type(struct strmbase_pin
*iface
, unsigned int index
, AM_MEDIA_TYPE
*mt
)
907 struct testfilter
*filter
= impl_from_strmbase_filter(iface
->filter
);
908 if (!index
&& filter
->mt
)
910 CopyMediaType(mt
, filter
->mt
);
913 return VFW_S_NO_MORE_ITEMS
;
916 static HRESULT WINAPI
testsink_Receive(struct strmbase_sink
*iface
, IMediaSample
*sample
)
918 struct testfilter
*filter
= impl_from_strmbase_filter(iface
->pin
.filter
);
919 REFERENCE_TIME start
, end
;
920 IMediaSeeking
*seeking
;
923 hr
= IMediaSample_GetTime(sample
, &start
, &end
);
924 todo_wine_if (hr
== VFW_S_NO_STOP_TIME
) ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
926 if (winetest_debug
> 1)
927 trace("%04x: Got sample with timestamps %I64d-%I64d.\n", GetCurrentThreadId(), start
, end
);
929 ok(filter
->new_segment_count
, "Expected NewSegment() before Receive().\n");
931 IPin_QueryInterface(iface
->pin
.peer
, &IID_IMediaSeeking
, (void **)&seeking
);
932 hr
= IMediaSeeking_GetPositions(seeking
, &start
, &end
);
933 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
934 ok(start
== filter
->seek_start
, "Expected start position %I64u, got %I64u.\n", filter
->seek_start
, start
);
935 ok(end
== filter
->seek_end
, "Expected end position %I64u, got %I64u.\n", filter
->seek_end
, end
);
936 IMediaSeeking_Release(seeking
);
938 ok(!filter
->eos_count
, "Got a sample after EOS.\n");
939 ++filter
->sample_count
;
943 static HRESULT
testsink_eos(struct strmbase_sink
*iface
)
945 struct testfilter
*filter
= impl_from_strmbase_filter(iface
->pin
.filter
);
947 if (winetest_debug
> 1)
948 trace("%04x: Got EOS.\n", GetCurrentThreadId());
950 ok(!filter
->eos_count
, "Got %u EOS events.\n", filter
->eos_count
+ 1);
952 SetEvent(filter
->eos_event
);
956 static HRESULT
testsink_new_segment(struct strmbase_sink
*iface
,
957 REFERENCE_TIME start
, REFERENCE_TIME end
, double rate
)
959 struct testfilter
*filter
= impl_from_strmbase_filter(iface
->pin
.filter
);
960 IMediaSeeking
*seeking
;
963 ++filter
->new_segment_count
;
965 IPin_QueryInterface(iface
->pin
.peer
, &IID_IMediaSeeking
, (void **)&seeking
);
966 hr
= IMediaSeeking_GetPositions(seeking
, &filter
->seek_start
, &filter
->seek_end
);
967 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
968 ok(rate
== 1.0, "Got rate %.16e.\n", rate
);
969 IMediaSeeking_Release(seeking
);
974 static const struct strmbase_sink_ops testsink_ops
=
976 .base
.pin_query_interface
= testsink_query_interface
,
977 .base
.pin_query_accept
= testsink_query_accept
,
978 .base
.pin_get_media_type
= testsink_get_media_type
,
979 .pfnReceive
= testsink_Receive
,
980 .sink_eos
= testsink_eos
,
981 .sink_new_segment
= testsink_new_segment
,
984 static struct testfilter
*impl_from_IAsyncReader(IAsyncReader
*iface
)
986 return CONTAINING_RECORD(iface
, struct testfilter
, IAsyncReader_iface
);
989 static HRESULT WINAPI
async_reader_QueryInterface(IAsyncReader
*iface
, REFIID iid
, void **out
)
991 return IPin_QueryInterface(&impl_from_IAsyncReader(iface
)->source
.pin
.IPin_iface
, iid
, out
);
994 static ULONG WINAPI
async_reader_AddRef(IAsyncReader
*iface
)
996 return IPin_AddRef(&impl_from_IAsyncReader(iface
)->source
.pin
.IPin_iface
);
999 static ULONG WINAPI
async_reader_Release(IAsyncReader
*iface
)
1001 return IPin_Release(&impl_from_IAsyncReader(iface
)->source
.pin
.IPin_iface
);
1004 static HRESULT WINAPI
async_reader_RequestAllocator(IAsyncReader
*iface
,
1005 IMemAllocator
*preferred
, ALLOCATOR_PROPERTIES
*props
, IMemAllocator
**allocator
)
1007 return IAsyncReader_RequestAllocator(impl_from_IAsyncReader(iface
)->reader
, preferred
, props
, allocator
);
1010 static HRESULT WINAPI
async_reader_Request(IAsyncReader
*iface
, IMediaSample
*sample
, DWORD_PTR cookie
)
1012 return IAsyncReader_Request(impl_from_IAsyncReader(iface
)->reader
, sample
, cookie
);
1015 static HRESULT WINAPI
async_reader_WaitForNext(IAsyncReader
*iface
,
1016 DWORD timeout
, IMediaSample
**sample
, DWORD_PTR
*cookie
)
1018 return IAsyncReader_WaitForNext(impl_from_IAsyncReader(iface
)->reader
, timeout
, sample
, cookie
);
1021 static HRESULT WINAPI
async_reader_SyncReadAligned(IAsyncReader
*iface
, IMediaSample
*sample
)
1023 return IAsyncReader_SyncReadAligned(impl_from_IAsyncReader(iface
)->reader
, sample
);
1026 static HRESULT WINAPI
async_reader_SyncRead(IAsyncReader
*iface
, LONGLONG position
, LONG length
, BYTE
*buffer
)
1028 return IAsyncReader_SyncRead(impl_from_IAsyncReader(iface
)->reader
, position
, length
, buffer
);
1031 static HRESULT WINAPI
async_reader_Length(IAsyncReader
*iface
, LONGLONG
*total
, LONGLONG
*available
)
1033 return IAsyncReader_Length(impl_from_IAsyncReader(iface
)->reader
, total
, available
);
1036 static HRESULT WINAPI
async_reader_BeginFlush(IAsyncReader
*iface
)
1038 return IAsyncReader_BeginFlush(impl_from_IAsyncReader(iface
)->reader
);
1041 static HRESULT WINAPI
async_reader_EndFlush(IAsyncReader
*iface
)
1043 return IAsyncReader_EndFlush(impl_from_IAsyncReader(iface
)->reader
);
1046 static const struct IAsyncReaderVtbl async_reader_vtbl
=
1048 async_reader_QueryInterface
,
1049 async_reader_AddRef
,
1050 async_reader_Release
,
1051 async_reader_RequestAllocator
,
1052 async_reader_Request
,
1053 async_reader_WaitForNext
,
1054 async_reader_SyncReadAligned
,
1055 async_reader_SyncRead
,
1056 async_reader_Length
,
1057 async_reader_BeginFlush
,
1058 async_reader_EndFlush
,
1061 static void testfilter_init(struct testfilter
*filter
)
1063 static const GUID clsid
= {0xabacab};
1064 memset(filter
, 0, sizeof(*filter
));
1065 strmbase_filter_init(&filter
->filter
, NULL
, &clsid
, &testfilter_ops
);
1066 strmbase_source_init(&filter
->source
, &filter
->filter
, L
"source", &testsource_ops
);
1067 strmbase_sink_init(&filter
->sink
, &filter
->filter
, L
"sink", &testsink_ops
, NULL
);
1068 filter
->IAsyncReader_iface
.lpVtbl
= &async_reader_vtbl
;
1069 filter
->eos_event
= CreateEventW(NULL
, FALSE
, FALSE
, NULL
);
1072 static void test_filter_state(IMediaControl
*control
)
1074 OAFilterState state
;
1077 hr
= IMediaControl_GetState(control
, 0, &state
);
1078 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1079 ok(state
== State_Stopped
, "Got state %u.\n", state
);
1081 hr
= IMediaControl_Pause(control
);
1082 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1084 hr
= IMediaControl_GetState(control
, 0, &state
);
1085 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1086 ok(state
== State_Paused
, "Got state %u.\n", state
);
1088 hr
= IMediaControl_Run(control
);
1089 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1091 hr
= IMediaControl_GetState(control
, 0, &state
);
1092 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1093 ok(state
== State_Running
, "Got state %u.\n", state
);
1095 hr
= IMediaControl_Pause(control
);
1096 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1098 hr
= IMediaControl_GetState(control
, 0, &state
);
1099 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1100 ok(state
== State_Paused
, "Got state %u.\n", state
);
1102 hr
= IMediaControl_Stop(control
);
1103 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1105 hr
= IMediaControl_GetState(control
, 0, &state
);
1106 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1107 ok(state
== State_Stopped
, "Got state %u.\n", state
);
1109 hr
= IMediaControl_Run(control
);
1110 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1112 hr
= IMediaControl_GetState(control
, 0, &state
);
1113 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1114 ok(state
== State_Running
, "Got state %u.\n", state
);
1116 hr
= IMediaControl_Stop(control
);
1117 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1119 hr
= IMediaControl_GetState(control
, 0, &state
);
1120 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1121 ok(state
== State_Stopped
, "Got state %u.\n", state
);
1124 static void test_connect_pin(void)
1126 AM_MEDIA_TYPE req_mt
=
1128 .majortype
= MEDIATYPE_Stream
,
1129 .subtype
= MEDIASUBTYPE_Avi
,
1130 .formattype
= FORMAT_None
,
1133 IBaseFilter
*filter
= create_avi_splitter(), *reader
;
1134 const WCHAR
*filename
= load_resource(L
"test.avi");
1135 struct testfilter testsource
, testsink
;
1136 IFileSourceFilter
*filesource
;
1137 AM_MEDIA_TYPE mt
, *source_mt
;
1138 IPin
*sink
, *source
, *peer
;
1139 IEnumMediaTypes
*enummt
;
1140 IMediaControl
*control
;
1141 IFilterGraph2
*graph
;
1146 CoCreateInstance(&CLSID_FilterGraph
, NULL
, CLSCTX_INPROC_SERVER
,
1147 &IID_IFilterGraph2
, (void **)&graph
);
1148 testfilter_init(&testsource
);
1149 testfilter_init(&testsink
);
1150 IFilterGraph2_AddFilter(graph
, &testsink
.filter
.IBaseFilter_iface
, L
"sink");
1151 IFilterGraph2_AddFilter(graph
, &testsource
.filter
.IBaseFilter_iface
, L
"source");
1152 IFilterGraph2_AddFilter(graph
, filter
, L
"splitter");
1153 IBaseFilter_FindPin(filter
, L
"input pin", &sink
);
1154 IFilterGraph2_QueryInterface(graph
, &IID_IMediaControl
, (void **)&control
);
1156 CoCreateInstance(&CLSID_AsyncReader
, NULL
, CLSCTX_INPROC_SERVER
,
1157 &IID_IBaseFilter
, (void **)&reader
);
1158 IBaseFilter_QueryInterface(reader
, &IID_IFileSourceFilter
, (void **)&filesource
);
1159 IFileSourceFilter_Load(filesource
, filename
, NULL
);
1160 IFileSourceFilter_Release(filesource
);
1161 IBaseFilter_FindPin(reader
, L
"Output", &source
);
1162 IPin_QueryInterface(source
, &IID_IAsyncReader
, (void **)&testsource
.reader
);
1163 IPin_Release(source
);
1165 /* Test sink connection. */
1167 peer
= (IPin
*)0xdeadbeef;
1168 hr
= IPin_ConnectedTo(sink
, &peer
);
1169 ok(hr
== VFW_E_NOT_CONNECTED
, "Got hr %#x.\n", hr
);
1170 ok(!peer
, "Got peer %p.\n", peer
);
1172 hr
= IPin_ConnectionMediaType(sink
, &mt
);
1173 ok(hr
== VFW_E_NOT_CONNECTED
, "Got hr %#x.\n", hr
);
1175 hr
= IMediaControl_Pause(control
);
1176 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1177 hr
= IFilterGraph2_ConnectDirect(graph
, &testsource
.source
.pin
.IPin_iface
, sink
, &req_mt
);
1178 ok(hr
== VFW_E_NOT_STOPPED
, "Got hr %#x.\n", hr
);
1179 hr
= IMediaControl_Stop(control
);
1180 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1182 req_mt
.majortype
= MEDIATYPE_Video
;
1183 hr
= IFilterGraph2_ConnectDirect(graph
, &testsource
.source
.pin
.IPin_iface
, sink
, &req_mt
);
1184 ok(hr
== VFW_E_TYPE_NOT_ACCEPTED
, "Got hr %#x.\n", hr
);
1185 req_mt
.majortype
= MEDIATYPE_Stream
;
1187 req_mt
.subtype
= MEDIASUBTYPE_RGB8
;
1188 hr
= IFilterGraph2_ConnectDirect(graph
, &testsource
.source
.pin
.IPin_iface
, sink
, &req_mt
);
1189 ok(hr
== VFW_E_TYPE_NOT_ACCEPTED
, "Got hr %#x.\n", hr
);
1190 req_mt
.subtype
= MEDIASUBTYPE_Avi
;
1192 hr
= IFilterGraph2_ConnectDirect(graph
, &testsource
.source
.pin
.IPin_iface
, sink
, &req_mt
);
1193 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1195 hr
= IPin_ConnectedTo(sink
, &peer
);
1196 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1197 ok(peer
== &testsource
.source
.pin
.IPin_iface
, "Got peer %p.\n", peer
);
1200 hr
= IPin_ConnectionMediaType(sink
, &mt
);
1201 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1202 ok(compare_media_types(&mt
, &req_mt
), "Media types didn't match.\n");
1203 ok(compare_media_types(&testsource
.source
.pin
.mt
, &req_mt
), "Media types didn't match.\n");
1205 hr
= IMediaControl_Pause(control
);
1206 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1207 hr
= IFilterGraph2_Disconnect(graph
, sink
);
1208 ok(hr
== VFW_E_NOT_STOPPED
, "Got hr %#x.\n", hr
);
1209 hr
= IMediaControl_Stop(control
);
1210 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1212 /* Test source connection. */
1214 IBaseFilter_FindPin(filter
, L
"Stream 00", &source
);
1216 peer
= (IPin
*)0xdeadbeef;
1217 hr
= IPin_ConnectedTo(source
, &peer
);
1218 ok(hr
== VFW_E_NOT_CONNECTED
, "Got hr %#x.\n", hr
);
1219 ok(!peer
, "Got peer %p.\n", peer
);
1221 hr
= IPin_ConnectionMediaType(source
, &mt
);
1222 ok(hr
== VFW_E_NOT_CONNECTED
, "Got hr %#x.\n", hr
);
1224 /* Exact connection. */
1226 IPin_EnumMediaTypes(source
, &enummt
);
1227 IEnumMediaTypes_Next(enummt
, 1, &source_mt
, NULL
);
1228 IEnumMediaTypes_Release(enummt
);
1229 CopyMediaType(&req_mt
, source_mt
);
1231 hr
= IMediaControl_Pause(control
);
1232 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1233 hr
= IFilterGraph2_ConnectDirect(graph
, source
, &testsink
.sink
.pin
.IPin_iface
, &req_mt
);
1234 ok(hr
== VFW_E_NOT_STOPPED
, "Got hr %#x.\n", hr
);
1235 hr
= IMediaControl_Stop(control
);
1236 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1238 hr
= IFilterGraph2_ConnectDirect(graph
, source
, &testsink
.sink
.pin
.IPin_iface
, &req_mt
);
1239 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1241 test_filter_state(control
);
1243 hr
= IPin_ConnectedTo(source
, &peer
);
1244 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1245 ok(peer
== &testsink
.sink
.pin
.IPin_iface
, "Got peer %p.\n", peer
);
1248 hr
= IPin_ConnectionMediaType(source
, &mt
);
1249 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1250 ok(compare_media_types(&mt
, &req_mt
), "Media types didn't match.\n");
1251 ok(compare_media_types(&testsink
.sink
.pin
.mt
, &req_mt
), "Media types didn't match.\n");
1253 hr
= IMediaControl_Pause(control
);
1254 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1255 hr
= IFilterGraph2_Disconnect(graph
, source
);
1256 ok(hr
== VFW_E_NOT_STOPPED
, "Got hr %#x.\n", hr
);
1257 hr
= IMediaControl_Stop(control
);
1258 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1260 hr
= IFilterGraph2_Disconnect(graph
, source
);
1261 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1262 hr
= IFilterGraph2_Disconnect(graph
, source
);
1263 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
1264 ok(testsink
.sink
.pin
.peer
== source
, "Got peer %p.\n", testsink
.sink
.pin
.peer
);
1265 IFilterGraph2_Disconnect(graph
, &testsink
.sink
.pin
.IPin_iface
);
1267 req_mt
.lSampleSize
= 999;
1268 req_mt
.bTemporalCompression
= req_mt
.bFixedSizeSamples
= TRUE
;
1269 hr
= IFilterGraph2_ConnectDirect(graph
, source
, &testsink
.sink
.pin
.IPin_iface
, &req_mt
);
1270 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1271 ok(compare_media_types(&testsink
.sink
.pin
.mt
, &req_mt
), "Media types didn't match.\n");
1272 IFilterGraph2_Disconnect(graph
, source
);
1273 IFilterGraph2_Disconnect(graph
, &testsink
.sink
.pin
.IPin_iface
);
1275 req_mt
.majortype
= MEDIATYPE_Stream
;
1276 hr
= IFilterGraph2_ConnectDirect(graph
, source
, &testsink
.sink
.pin
.IPin_iface
, &req_mt
);
1277 ok(hr
== VFW_E_TYPE_NOT_ACCEPTED
, "Got hr %#x.\n", hr
);
1278 req_mt
.majortype
= MEDIATYPE_Video
;
1280 req_mt
.subtype
= MEDIASUBTYPE_RGB32
;
1281 hr
= IFilterGraph2_ConnectDirect(graph
, source
, &testsink
.sink
.pin
.IPin_iface
, &req_mt
);
1282 ok(hr
== VFW_E_TYPE_NOT_ACCEPTED
, "Got hr %#x.\n", hr
);
1283 req_mt
.subtype
= GUID_NULL
;
1284 hr
= IFilterGraph2_ConnectDirect(graph
, source
, &testsink
.sink
.pin
.IPin_iface
, &req_mt
);
1285 ok(hr
== VFW_E_TYPE_NOT_ACCEPTED
, "Got hr %#x.\n", hr
);
1286 req_mt
.subtype
= MEDIASUBTYPE_I420
;
1288 /* Connection with wildcards. */
1290 hr
= IFilterGraph2_ConnectDirect(graph
, source
, &testsink
.sink
.pin
.IPin_iface
, NULL
);
1291 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1292 ok(compare_media_types(&testsink
.sink
.pin
.mt
, source_mt
), "Media types didn't match.\n");
1293 IFilterGraph2_Disconnect(graph
, source
);
1294 IFilterGraph2_Disconnect(graph
, &testsink
.sink
.pin
.IPin_iface
);
1296 req_mt
.majortype
= GUID_NULL
;
1297 hr
= IFilterGraph2_ConnectDirect(graph
, source
, &testsink
.sink
.pin
.IPin_iface
, &req_mt
);
1298 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1299 ok(compare_media_types(&testsink
.sink
.pin
.mt
, source_mt
), "Media types didn't match.\n");
1300 IFilterGraph2_Disconnect(graph
, source
);
1301 IFilterGraph2_Disconnect(graph
, &testsink
.sink
.pin
.IPin_iface
);
1303 req_mt
.subtype
= MEDIASUBTYPE_RGB32
;
1304 hr
= IFilterGraph2_ConnectDirect(graph
, source
, &testsink
.sink
.pin
.IPin_iface
, &req_mt
);
1305 ok(hr
== VFW_E_NO_ACCEPTABLE_TYPES
, "Got hr %#x.\n", hr
);
1307 req_mt
.subtype
= GUID_NULL
;
1308 hr
= IFilterGraph2_ConnectDirect(graph
, source
, &testsink
.sink
.pin
.IPin_iface
, &req_mt
);
1309 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1310 ok(compare_media_types(&testsink
.sink
.pin
.mt
, source_mt
), "Media types didn't match.\n");
1311 IFilterGraph2_Disconnect(graph
, source
);
1312 IFilterGraph2_Disconnect(graph
, &testsink
.sink
.pin
.IPin_iface
);
1314 req_mt
.formattype
= FORMAT_None
;
1315 hr
= IFilterGraph2_ConnectDirect(graph
, source
, &testsink
.sink
.pin
.IPin_iface
, &req_mt
);
1316 ok(hr
== VFW_E_NO_ACCEPTABLE_TYPES
, "Got hr %#x.\n", hr
);
1318 req_mt
.majortype
= MEDIATYPE_Video
;
1319 req_mt
.subtype
= MEDIASUBTYPE_I420
;
1320 req_mt
.formattype
= GUID_NULL
;
1321 hr
= IFilterGraph2_ConnectDirect(graph
, source
, &testsink
.sink
.pin
.IPin_iface
, &req_mt
);
1322 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1323 ok(compare_media_types(&testsink
.sink
.pin
.mt
, source_mt
), "Media types didn't match.\n");
1324 IFilterGraph2_Disconnect(graph
, source
);
1325 IFilterGraph2_Disconnect(graph
, &testsink
.sink
.pin
.IPin_iface
);
1327 req_mt
.subtype
= MEDIASUBTYPE_RGB32
;
1328 hr
= IFilterGraph2_ConnectDirect(graph
, source
, &testsink
.sink
.pin
.IPin_iface
, &req_mt
);
1329 ok(hr
== VFW_E_NO_ACCEPTABLE_TYPES
, "Got hr %#x.\n", hr
);
1331 req_mt
.subtype
= GUID_NULL
;
1332 hr
= IFilterGraph2_ConnectDirect(graph
, source
, &testsink
.sink
.pin
.IPin_iface
, &req_mt
);
1333 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1334 ok(compare_media_types(&testsink
.sink
.pin
.mt
, source_mt
), "Media types didn't match.\n");
1335 IFilterGraph2_Disconnect(graph
, source
);
1336 IFilterGraph2_Disconnect(graph
, &testsink
.sink
.pin
.IPin_iface
);
1338 req_mt
.majortype
= MEDIATYPE_Audio
;
1339 hr
= IFilterGraph2_ConnectDirect(graph
, source
, &testsink
.sink
.pin
.IPin_iface
, &req_mt
);
1340 ok(hr
== VFW_E_NO_ACCEPTABLE_TYPES
, "Got hr %#x.\n", hr
);
1342 testsink
.mt
= &req_mt
;
1343 hr
= IFilterGraph2_ConnectDirect(graph
, source
, &testsink
.sink
.pin
.IPin_iface
, NULL
);
1344 ok(hr
== VFW_E_NO_ACCEPTABLE_TYPES
, "Got hr %#x.\n", hr
);
1346 req_mt
.majortype
= MEDIATYPE_Video
;
1347 req_mt
.subtype
= MEDIASUBTYPE_I420
;
1348 req_mt
.formattype
= FORMAT_VideoInfo
;
1349 hr
= IFilterGraph2_ConnectDirect(graph
, source
, &testsink
.sink
.pin
.IPin_iface
, NULL
);
1350 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1352 IPin_Release(source
);
1353 hr
= IFilterGraph2_Disconnect(graph
, sink
);
1354 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1355 hr
= IFilterGraph2_Disconnect(graph
, sink
);
1356 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
1357 ok(testsource
.source
.pin
.peer
== sink
, "Got peer %p.\n", testsource
.source
.pin
.peer
);
1358 IFilterGraph2_Disconnect(graph
, &testsource
.source
.pin
.IPin_iface
);
1360 CoTaskMemFree(req_mt
.pbFormat
);
1361 CoTaskMemFree(source_mt
->pbFormat
);
1362 CoTaskMemFree(source_mt
);
1364 IAsyncReader_Release(testsource
.reader
);
1366 IMediaControl_Release(control
);
1367 ref
= IFilterGraph2_Release(graph
);
1368 ok(!ref
, "Got outstanding refcount %d.\n", ref
);
1369 ref
= IBaseFilter_Release(reader
);
1370 ok(!ref
, "Got outstanding refcount %d.\n", ref
);
1371 ref
= IBaseFilter_Release(filter
);
1372 ok(!ref
, "Got outstanding refcount %d.\n", ref
);
1373 ref
= IBaseFilter_Release(&testsource
.filter
.IBaseFilter_iface
);
1374 ok(!ref
, "Got outstanding refcount %d.\n", ref
);
1375 ref
= IBaseFilter_Release(&testsink
.filter
.IBaseFilter_iface
);
1376 ok(!ref
, "Got outstanding refcount %d.\n", ref
);
1377 ret
= DeleteFileW(filename
);
1378 ok(ret
, "Failed to delete file, error %u.\n", GetLastError());
1381 static void test_unconnected_filter_state(void)
1383 IBaseFilter
*filter
= create_avi_splitter();
1388 hr
= IBaseFilter_GetState(filter
, 0, &state
);
1389 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1390 ok(state
== State_Stopped
, "Got state %u.\n", state
);
1392 hr
= IBaseFilter_Pause(filter
);
1393 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1395 hr
= IBaseFilter_GetState(filter
, 0, &state
);
1396 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1397 ok(state
== State_Paused
, "Got state %u.\n", state
);
1399 hr
= IBaseFilter_Run(filter
, 0);
1400 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1402 hr
= IBaseFilter_GetState(filter
, 0, &state
);
1403 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1404 ok(state
== State_Running
, "Got state %u.\n", state
);
1406 hr
= IBaseFilter_Pause(filter
);
1407 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1409 hr
= IBaseFilter_GetState(filter
, 0, &state
);
1410 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1411 ok(state
== State_Paused
, "Got state %u.\n", state
);
1413 hr
= IBaseFilter_Stop(filter
);
1414 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1416 hr
= IBaseFilter_GetState(filter
, 0, &state
);
1417 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1418 ok(state
== State_Stopped
, "Got state %u.\n", state
);
1420 hr
= IBaseFilter_Run(filter
, 0);
1421 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1423 hr
= IBaseFilter_GetState(filter
, 0, &state
);
1424 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1425 ok(state
== State_Running
, "Got state %u.\n", state
);
1427 hr
= IBaseFilter_Stop(filter
);
1428 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1430 hr
= IBaseFilter_GetState(filter
, 0, &state
);
1431 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1432 ok(state
== State_Stopped
, "Got state %u.\n", state
);
1434 ref
= IBaseFilter_Release(filter
);
1435 ok(!ref
, "Got outstanding refcount %d.\n", ref
);
1438 static void test_seeking(void)
1440 LONGLONG time
, current
, stop
, prev_stop
, earliest
, latest
, duration
;
1441 const WCHAR
*filename
= load_resource(L
"test.avi");
1442 IBaseFilter
*filter
= create_avi_splitter();
1443 IFilterGraph2
*graph
= connect_input(filter
, filename
);
1444 IMediaSeeking
*seeking
;
1461 {&TIME_FORMAT_MEDIA_TIME
, S_OK
},
1462 {&TIME_FORMAT_FRAME
, S_OK
},
1464 {&TIME_FORMAT_BYTE
, S_FALSE
},
1465 {&TIME_FORMAT_NONE
, S_FALSE
},
1466 {&TIME_FORMAT_SAMPLE
, S_FALSE
},
1467 {&TIME_FORMAT_FIELD
, S_FALSE
},
1468 {&testguid
, S_FALSE
},
1471 IBaseFilter_FindPin(filter
, L
"Stream 00", &pin
);
1472 IPin_QueryInterface(pin
, &IID_IMediaSeeking
, (void **)&seeking
);
1474 hr
= IMediaSeeking_GetCapabilities(seeking
, &caps
);
1475 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1476 ok(caps
== (AM_SEEKING_CanSeekAbsolute
| AM_SEEKING_CanSeekForwards
1477 | AM_SEEKING_CanSeekBackwards
| AM_SEEKING_CanGetStopPos
1478 | AM_SEEKING_CanGetDuration
), "Got caps %#x.\n", caps
);
1480 caps
= AM_SEEKING_CanSeekAbsolute
| AM_SEEKING_CanSeekForwards
;
1481 hr
= IMediaSeeking_CheckCapabilities(seeking
, &caps
);
1482 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1483 ok(caps
== (AM_SEEKING_CanSeekAbsolute
| AM_SEEKING_CanSeekForwards
), "Got caps %#x.\n", caps
);
1485 caps
= AM_SEEKING_CanSeekAbsolute
| AM_SEEKING_CanGetCurrentPos
;
1486 hr
= IMediaSeeking_CheckCapabilities(seeking
, &caps
);
1487 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
1488 ok(caps
== AM_SEEKING_CanSeekAbsolute
, "Got caps %#x.\n", caps
);
1490 caps
= AM_SEEKING_CanGetCurrentPos
;
1491 hr
= IMediaSeeking_CheckCapabilities(seeking
, &caps
);
1492 ok(hr
== E_FAIL
, "Got hr %#x.\n", hr
);
1493 ok(!caps
, "Got caps %#x.\n", caps
);
1496 hr
= IMediaSeeking_CheckCapabilities(seeking
, &caps
);
1497 ok(hr
== E_FAIL
, "Got hr %#x.\n", hr
);
1498 ok(!caps
, "Got caps %#x.\n", caps
);
1500 for (i
= 0; i
< ARRAY_SIZE(format_tests
); ++i
)
1502 hr
= IMediaSeeking_IsFormatSupported(seeking
, format_tests
[i
].guid
);
1503 todo_wine_if(i
== 1) ok(hr
== format_tests
[i
].hr
, "Got hr %#x for format %s.\n",
1504 hr
, wine_dbgstr_guid(format_tests
[i
].guid
));
1507 hr
= IMediaSeeking_QueryPreferredFormat(seeking
, &format
);
1508 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1509 ok(IsEqualGUID(&format
, &TIME_FORMAT_MEDIA_TIME
), "Got format %s.\n", wine_dbgstr_guid(&format
));
1511 hr
= IMediaSeeking_GetTimeFormat(seeking
, &format
);
1512 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1513 ok(IsEqualGUID(&format
, &TIME_FORMAT_MEDIA_TIME
), "Got format %s.\n", wine_dbgstr_guid(&format
));
1515 hr
= IMediaSeeking_IsUsingTimeFormat(seeking
, &TIME_FORMAT_MEDIA_TIME
);
1516 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1517 hr
= IMediaSeeking_IsUsingTimeFormat(seeking
, &TIME_FORMAT_FRAME
);
1518 ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
1520 hr
= IMediaSeeking_SetTimeFormat(seeking
, &TIME_FORMAT_SAMPLE
);
1521 ok(hr
== E_INVALIDARG
, "Got hr %#x.\n", hr
);
1522 hr
= IMediaSeeking_SetTimeFormat(seeking
, &TIME_FORMAT_FRAME
);
1523 todo_wine
ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1525 hr
= IMediaSeeking_GetTimeFormat(seeking
, &format
);
1526 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1527 todo_wine
ok(IsEqualGUID(&format
, &TIME_FORMAT_FRAME
), "Got format %s.\n", wine_dbgstr_guid(&format
));
1529 hr
= IMediaSeeking_IsUsingTimeFormat(seeking
, &TIME_FORMAT_MEDIA_TIME
);
1530 todo_wine
ok(hr
== S_FALSE
, "Got hr %#x.\n", hr
);
1531 hr
= IMediaSeeking_IsUsingTimeFormat(seeking
, &TIME_FORMAT_FRAME
);
1532 todo_wine
ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1534 hr
= IMediaSeeking_SetTimeFormat(seeking
, &TIME_FORMAT_MEDIA_TIME
);
1535 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1538 hr
= IMediaSeeking_GetDuration(seeking
, &duration
);
1539 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1540 ok(duration
== 50000000, "Got duration %I64d.\n", duration
);
1542 stop
= current
= 0xdeadbeef;
1543 hr
= IMediaSeeking_GetStopPosition(seeking
, &stop
);
1544 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1545 ok(stop
== duration
, "Expected time %s, got %s.\n",
1546 wine_dbgstr_longlong(duration
), wine_dbgstr_longlong(stop
));
1547 hr
= IMediaSeeking_GetCurrentPosition(seeking
, ¤t
);
1548 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1549 ok(!current
, "Got time %s.\n", wine_dbgstr_longlong(current
));
1550 stop
= current
= 0xdeadbeef;
1551 hr
= IMediaSeeking_GetPositions(seeking
, ¤t
, &stop
);
1552 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1553 ok(!current
, "Got time %s.\n", wine_dbgstr_longlong(current
));
1554 ok(stop
== duration
, "Expected time %s, got %s.\n",
1555 wine_dbgstr_longlong(duration
), wine_dbgstr_longlong(stop
));
1558 hr
= IMediaSeeking_ConvertTimeFormat(seeking
, &time
, &TIME_FORMAT_MEDIA_TIME
, 0x123456789a, NULL
);
1559 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1560 ok(time
== 0x123456789a, "Got time %s.\n", wine_dbgstr_longlong(time
));
1562 hr
= IMediaSeeking_ConvertTimeFormat(seeking
, &time
, NULL
, 0x123456789a, &TIME_FORMAT_MEDIA_TIME
);
1563 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1564 ok(time
== 0x123456789a, "Got time %s.\n", wine_dbgstr_longlong(time
));
1566 hr
= IMediaSeeking_ConvertTimeFormat(seeking
, &time
, NULL
, 123, &TIME_FORMAT_FRAME
);
1567 todo_wine
ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1568 todo_wine
ok(time
== 123 * 10000000, "Got time %s.\n", wine_dbgstr_longlong(time
));
1570 earliest
= latest
= 0xdeadbeef;
1571 hr
= IMediaSeeking_GetAvailable(seeking
, &earliest
, &latest
);
1572 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1573 ok(!earliest
, "Got time %s.\n", wine_dbgstr_longlong(earliest
));
1574 ok(latest
== duration
, "Expected time %s, got %s.\n",
1575 wine_dbgstr_longlong(duration
), wine_dbgstr_longlong(latest
));
1578 hr
= IMediaSeeking_GetRate(seeking
, &rate
);
1579 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1580 ok(rate
== 1.0, "Got rate %.16e.\n", rate
);
1582 hr
= IMediaSeeking_SetRate(seeking
, 200.0);
1583 todo_wine
ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1585 hr
= IMediaSeeking_GetRate(seeking
, &rate
);
1586 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1587 todo_wine
ok(rate
== 200.0, "Got rate %.16e.\n", rate
);
1589 hr
= IMediaSeeking_SetRate(seeking
, -1.0);
1590 todo_wine
ok(hr
== E_INVALIDARG
, "Got hr %#x.\n", hr
);
1592 hr
= IMediaSeeking_GetPreroll(seeking
, &time
);
1593 todo_wine
ok(hr
== E_NOTIMPL
, "Got hr %#x.\n", hr
);
1595 current
= 1500 * 10000;
1596 stop
= 3500 * 10000;
1597 hr
= IMediaSeeking_SetPositions(seeking
, ¤t
, AM_SEEKING_AbsolutePositioning
,
1598 &stop
, AM_SEEKING_AbsolutePositioning
);
1599 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1600 ok(current
== 1500 * 10000, "Got time %s.\n", wine_dbgstr_longlong(current
));
1601 ok(stop
== 3500 * 10000, "Got time %s.\n", wine_dbgstr_longlong(stop
));
1603 stop
= current
= 0xdeadbeef;
1604 hr
= IMediaSeeking_GetPositions(seeking
, ¤t
, &stop
);
1605 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1606 /* Native snaps to the nearest frame. */
1607 ok(current
> 0 && current
< duration
, "Got time %s.\n", wine_dbgstr_longlong(current
));
1608 ok(stop
> 0 && stop
< duration
&& stop
> current
, "Got time %s.\n", wine_dbgstr_longlong(stop
));
1610 current
= 1500 * 10000;
1611 stop
= 3500 * 10000;
1612 hr
= IMediaSeeking_SetPositions(seeking
, ¤t
, AM_SEEKING_AbsolutePositioning
| AM_SEEKING_ReturnTime
,
1613 &stop
, AM_SEEKING_AbsolutePositioning
| AM_SEEKING_ReturnTime
);
1614 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1615 ok(current
> 0 && current
< duration
, "Got time %s.\n", wine_dbgstr_longlong(current
));
1616 ok(stop
> 0 && stop
< duration
&& stop
> current
, "Got time %s.\n", wine_dbgstr_longlong(stop
));
1618 hr
= IMediaSeeking_GetStopPosition(seeking
, &prev_stop
);
1619 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1622 hr
= IMediaSeeking_SetPositions(seeking
, ¤t
, AM_SEEKING_AbsolutePositioning
,
1623 NULL
, AM_SEEKING_NoPositioning
);
1624 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1626 stop
= current
= 0xdeadbeef;
1627 hr
= IMediaSeeking_GetPositions(seeking
, ¤t
, &stop
);
1628 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1629 ok(!current
, "Got time %s.\n", wine_dbgstr_longlong(current
));
1630 ok(stop
== prev_stop
, "Expected time %s, got %s.\n",
1631 wine_dbgstr_longlong(prev_stop
), wine_dbgstr_longlong(stop
));
1633 IMediaSeeking_Release(seeking
);
1635 IFilterGraph2_Release(graph
);
1636 ref
= IBaseFilter_Release(filter
);
1637 ok(!ref
, "Got outstanding refcount %d.\n", ref
);
1638 ret
= DeleteFileW(filename
);
1639 ok(ret
, "Failed to delete file, error %u.\n", GetLastError());
1642 static void test_streaming(void)
1644 const WCHAR
*filename
= load_resource(L
"test.avi");
1645 IBaseFilter
*filter
= create_avi_splitter();
1646 IFilterGraph2
*graph
= connect_input(filter
, filename
);
1647 struct testfilter testsink
;
1648 REFERENCE_TIME start
, end
;
1649 IMediaSeeking
*seeking
;
1650 IMediaControl
*control
;
1656 testfilter_init(&testsink
);
1657 IFilterGraph2_AddFilter(graph
, &testsink
.filter
.IBaseFilter_iface
, L
"sink");
1658 IFilterGraph2_QueryInterface(graph
, &IID_IMediaControl
, (void **)&control
);
1659 IBaseFilter_FindPin(filter
, L
"Stream 00", &source
);
1660 IPin_QueryInterface(source
, &IID_IMediaSeeking
, (void **)&seeking
);
1662 hr
= IFilterGraph2_ConnectDirect(graph
, source
, &testsink
.sink
.pin
.IPin_iface
, NULL
);
1663 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1665 ok(WaitForSingleObject(testsink
.eos_event
, 100) == WAIT_TIMEOUT
, "Expected timeout.\n");
1667 hr
= IMediaControl_Pause(control
);
1668 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1670 ok(!WaitForSingleObject(testsink
.eos_event
, 1000), "Did not receive EOS.\n");
1671 ok(WaitForSingleObject(testsink
.eos_event
, 100) == WAIT_TIMEOUT
, "Got more than one EOS.\n");
1672 ok(testsink
.sample_count
, "Expected at least one sample.\n");
1674 testsink
.sample_count
= testsink
.eos_count
= 0;
1675 hr
= IMediaControl_Stop(control
);
1676 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1677 hr
= IMediaControl_Pause(control
);
1678 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1680 ok(!WaitForSingleObject(testsink
.eos_event
, 1000), "Did not receive EOS.\n");
1681 ok(WaitForSingleObject(testsink
.eos_event
, 100) == WAIT_TIMEOUT
, "Got more than one EOS.\n");
1682 ok(testsink
.sample_count
, "Expected at least one sample.\n");
1684 testsink
.sample_count
= testsink
.eos_count
= 0;
1685 start
= 1500 * 10000;
1687 hr
= IMediaSeeking_SetPositions(seeking
, &start
, AM_SEEKING_AbsolutePositioning
,
1688 &end
, AM_SEEKING_AbsolutePositioning
);
1689 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1691 ok(!WaitForSingleObject(testsink
.eos_event
, 1000), "Did not receive EOS.\n");
1692 ok(WaitForSingleObject(testsink
.eos_event
, 100) == WAIT_TIMEOUT
, "Got more than one EOS.\n");
1693 ok(testsink
.sample_count
, "Expected at least one sample.\n");
1695 start
= end
= 0xdeadbeef;
1696 hr
= IMediaSeeking_GetPositions(seeking
, &start
, &end
);
1697 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1698 ok(start
== testsink
.seek_start
, "Expected start position %I64u, got %I64u.\n", testsink
.seek_start
, start
);
1699 ok(end
== testsink
.seek_end
, "Expected end position %I64u, got %I64u.\n", testsink
.seek_end
, end
);
1701 testsink
.sample_count
= testsink
.eos_count
= 0;
1702 hr
= IMediaControl_Stop(control
);
1703 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1704 hr
= IMediaControl_Pause(control
);
1705 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1707 ok(!WaitForSingleObject(testsink
.eos_event
, 1000), "Did not receive EOS.\n");
1708 ok(WaitForSingleObject(testsink
.eos_event
, 100) == WAIT_TIMEOUT
, "Got more than one EOS.\n");
1709 ok(testsink
.sample_count
, "Expected at least one sample.\n");
1711 start
= end
= 0xdeadbeef;
1712 hr
= IMediaSeeking_GetPositions(seeking
, &start
, &end
);
1713 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1714 ok(start
== testsink
.seek_start
, "Expected start position %I64u, got %I64u.\n", testsink
.seek_start
, start
);
1715 ok(end
== testsink
.seek_end
, "Expected end position %I64u, got %I64u.\n", testsink
.seek_end
, end
);
1717 IMediaSeeking_Release(seeking
);
1718 IPin_Release(source
);
1719 IMediaControl_Release(control
);
1720 ref
= IFilterGraph2_Release(graph
);
1721 ok(!ref
, "Got outstanding refcount %d.\n", ref
);
1722 ref
= IBaseFilter_Release(filter
);
1723 ok(!ref
, "Got outstanding refcount %d.\n", ref
);
1724 ref
= IBaseFilter_Release(&testsink
.filter
.IBaseFilter_iface
);
1725 ok(!ref
, "Got outstanding refcount %d.\n", ref
);
1726 ret
= DeleteFileW(filename
);
1727 ok(ret
, "Failed to delete file, error %u.\n", GetLastError());
1730 START_TEST(avisplit
)
1732 IBaseFilter
*filter
;
1736 if (FAILED(CoCreateInstance(&CLSID_AviSplitter
, NULL
, CLSCTX_INPROC_SERVER
,
1737 &IID_IBaseFilter
, (void **)&filter
)))
1739 skip("Failed to create AVI splitter.\n");
1742 IBaseFilter_Release(filter
);
1750 test_enum_media_types();
1751 test_unconnected_filter_state();