Release 4.0.4.
[wine.git] / dlls / quartz / tests / avisplitter.c
blob757b71c6409ded3831cf00afcad93ec69dc36468
1 /*
2 * Unit tests for the avi splitter functions
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
22 #define COBJMACROS
24 #include "wine/test.h"
25 #include "dshow.h"
26 #include "tlhelp32.h"
28 static IUnknown *pAviSplitter = NULL;
30 static BOOL create_avisplitter(void)
32 HRESULT hr;
34 hr = CoCreateInstance(&CLSID_AviSplitter, NULL, CLSCTX_INPROC_SERVER,
35 &IID_IUnknown, (LPVOID*)&pAviSplitter);
36 return (hr == S_OK && pAviSplitter != NULL);
39 static void release_avisplitter(void)
41 HRESULT hr;
43 Sleep(1000);
44 hr = IUnknown_Release(pAviSplitter);
46 /* Looks like wine has a reference leak somewhere on test_threads tests,
47 * it passes in windows
49 ok(hr == 0, "IUnknown_Release failed with %d\n", (INT)hr);
51 while (hr > 0)
52 hr = IUnknown_Release(pAviSplitter);
53 pAviSplitter = NULL;
56 static void test_query_interface(void)
58 HRESULT hr;
59 ULONG ref;
60 IUnknown *iface= NULL;
62 #define TEST_INTERFACE(riid,expected) do { \
63 hr = IUnknown_QueryInterface(pAviSplitter, &riid, (void**)&iface); \
64 ok( hr == expected, #riid" should %s got %08X\n", expected==S_OK ? "exist" : "not be present", GetLastError() ); \
65 if (hr == S_OK) { \
66 ref = IUnknown_Release(iface); \
67 ok(ref == 1, "Reference is %u, expected 1\n", ref); \
68 } \
69 iface = NULL; \
70 } while(0)
72 TEST_INTERFACE(IID_IBaseFilter,S_OK);
73 TEST_INTERFACE(IID_IMediaSeeking,E_NOINTERFACE);
74 TEST_INTERFACE(IID_IKsPropertySet,E_NOINTERFACE);
75 TEST_INTERFACE(IID_IMediaPosition,E_NOINTERFACE);
76 TEST_INTERFACE(IID_IQualityControl,E_NOINTERFACE);
77 TEST_INTERFACE(IID_IQualProp,E_NOINTERFACE);
78 #undef TEST_INTERFACE
81 static void test_pin(IPin *pin)
83 IMemInputPin *mpin = NULL;
85 IPin_QueryInterface(pin, &IID_IMemInputPin, (void **)&mpin);
87 ok(mpin == NULL, "IMemInputPin found!\n");
88 if (mpin)
89 IMemInputPin_Release(mpin);
90 /* TODO */
93 static void test_basefilter(void)
95 IEnumPins *pin_enum = NULL;
96 IBaseFilter *base = NULL;
97 IPin *pins[2];
98 ULONG ref;
99 HRESULT hr;
101 IUnknown_QueryInterface(pAviSplitter, &IID_IBaseFilter, (void **)&base);
102 if (base == NULL)
104 /* test_query_interface handles this case */
105 skip("No IBaseFilter\n");
106 return;
109 hr = IBaseFilter_EnumPins(base, NULL);
110 ok(hr == E_POINTER, "hr = %08x and not E_POINTER\n", hr);
112 hr= IBaseFilter_EnumPins(base, &pin_enum);
113 ok(hr == S_OK, "hr = %08x and not S_OK\n", hr);
115 hr = IEnumPins_Next(pin_enum, 1, NULL, NULL);
116 ok(hr == E_POINTER, "hr = %08x and not E_POINTER\n", hr);
118 hr = IEnumPins_Next(pin_enum, 2, pins, NULL);
119 ok(hr == E_INVALIDARG, "hr = %08x and not E_INVALIDARG\n", hr);
121 pins[0] = (void *)0xdead;
122 pins[1] = (void *)0xdeed;
124 hr = IEnumPins_Next(pin_enum, 2, pins, &ref);
125 ok(hr == S_FALSE, "hr = %08x instead of S_FALSE\n", hr);
126 ok(pins[0] != (void *)0xdead && pins[0] != NULL,
127 "pins[0] = %p\n", pins[0]);
128 if (pins[0] != (void *)0xdead && pins[0] != NULL)
130 test_pin(pins[0]);
131 IPin_Release(pins[0]);
134 ok(pins[1] == (void *)0xdeed, "pins[1] = %p\n", pins[1]);
136 ref = IEnumPins_Release(pin_enum);
137 ok(ref == 0, "ref is %u and not 0!\n", ref);
139 IBaseFilter_Release(base);
142 static const WCHAR avifile[] = {'t','e','s','t','.','a','v','i',0};
144 static WCHAR *load_resource(const WCHAR *name)
146 static WCHAR pathW[MAX_PATH];
147 DWORD written;
148 HANDLE file;
149 HRSRC res;
150 void *ptr;
152 GetTempPathW(ARRAY_SIZE(pathW), pathW);
153 lstrcatW(pathW, name);
155 file = CreateFileW(pathW, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0);
156 ok(file != INVALID_HANDLE_VALUE, "file creation failed, at %s, error %d\n", wine_dbgstr_w(pathW),
157 GetLastError());
159 res = FindResourceW(NULL, name, (LPCWSTR)RT_RCDATA);
160 ok( res != 0, "couldn't find resource\n" );
161 ptr = LockResource( LoadResource( GetModuleHandleA(NULL), res ));
162 WriteFile( file, ptr, SizeofResource( GetModuleHandleA(NULL), res ), &written, NULL );
163 ok( written == SizeofResource( GetModuleHandleA(NULL), res ), "couldn't write resource\n" );
164 CloseHandle( file );
166 return pathW;
169 static void test_filter_graph(void)
171 IFileSourceFilter *pfile = NULL;
172 IBaseFilter *preader = NULL, *pavi = NULL;
173 IEnumPins *enumpins = NULL;
174 IPin *filepin = NULL, *avipin = NULL;
175 HRESULT hr;
176 HANDLE file = NULL;
177 PIN_DIRECTION dir = PINDIR_OUTPUT;
178 char buffer[13];
179 DWORD readbytes;
180 FILTER_STATE state;
182 WCHAR *filename = load_resource(avifile);
184 file = CreateFileW(filename, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE,
185 NULL, OPEN_EXISTING, 0, NULL);
186 if (file == INVALID_HANDLE_VALUE)
188 skip("Could not read test file \"%s\", skipping test\n", wine_dbgstr_w(filename));
189 DeleteFileW(filename);
190 return;
193 memset(buffer, 0, 13);
194 readbytes = 12;
195 ReadFile(file, buffer, readbytes, &readbytes, NULL);
196 CloseHandle(file);
197 if (strncmp(buffer, "RIFF", 4) || strcmp(buffer + 8, "AVI "))
199 skip("%s is not an avi riff file, not doing the avi splitter test\n",
200 wine_dbgstr_w(filename));
201 DeleteFileW(filename);
202 return;
205 hr = IUnknown_QueryInterface(pAviSplitter, &IID_IFileSourceFilter,
206 (void **)&pfile);
207 ok(hr == E_NOINTERFACE,
208 "Avi splitter returns unexpected error: %08x\n", hr);
209 if (pfile)
210 IFileSourceFilter_Release(pfile);
211 pfile = NULL;
213 hr = CoCreateInstance(&CLSID_AsyncReader, NULL, CLSCTX_INPROC_SERVER,
214 &IID_IBaseFilter, (LPVOID*)&preader);
215 ok(hr == S_OK, "Could not create asynchronous reader: %08x\n", hr);
216 if (hr != S_OK)
217 goto fail;
219 hr = IBaseFilter_QueryInterface(preader, &IID_IFileSourceFilter,
220 (void**)&pfile);
221 ok(hr == S_OK, "Could not get IFileSourceFilter: %08x\n", hr);
222 if (hr != S_OK)
223 goto fail;
225 hr = IUnknown_QueryInterface(pAviSplitter, &IID_IBaseFilter,
226 (void**)&pavi);
227 ok(hr == S_OK, "Could not get base filter: %08x\n", hr);
228 if (hr != S_OK)
229 goto fail;
231 hr = IFileSourceFilter_Load(pfile, filename, NULL);
232 if (hr != S_OK)
234 trace("Could not load file: %08x\n", hr);
235 goto fail;
238 hr = IBaseFilter_EnumPins(preader, &enumpins);
239 ok(hr == S_OK, "No enumpins: %08x\n", hr);
240 if (hr != S_OK)
241 goto fail;
243 hr = IEnumPins_Next(enumpins, 1, &filepin, NULL);
244 ok(hr == S_OK, "No pin: %08x\n", hr);
245 if (hr != S_OK)
246 goto fail;
248 IEnumPins_Release(enumpins);
249 enumpins = NULL;
251 hr = IBaseFilter_EnumPins(pavi, &enumpins);
252 ok(hr == S_OK, "No enumpins: %08x\n", hr);
253 if (hr != S_OK)
254 goto fail;
256 hr = IEnumPins_Next(enumpins, 1, &avipin, NULL);
257 ok(hr == S_OK, "No pin: %08x\n", hr);
258 if (hr != S_OK)
259 goto fail;
261 hr = IPin_Connect(filepin, avipin, NULL);
262 ok(hr == S_OK, "Could not connect: %08x\n", hr);
263 if (hr != S_OK)
264 goto fail;
266 IPin_Release(avipin);
267 avipin = NULL;
269 IEnumPins_Reset(enumpins);
271 /* Windows puts the pins in the order: Outputpins - Inputpin,
272 * wine does the reverse, just don't test it for now
273 * Hate to admit it, but windows way makes more sense
275 while (IEnumPins_Next(enumpins, 1, &avipin, NULL) == S_OK)
277 IPin_QueryDirection(avipin, &dir);
278 if (dir == PINDIR_OUTPUT)
280 /* Well, connect it to a null renderer! */
281 IBaseFilter *pnull = NULL;
282 IEnumPins *nullenum = NULL;
283 IPin *nullpin = NULL;
285 hr = CoCreateInstance(&CLSID_NullRenderer, NULL,
286 CLSCTX_INPROC_SERVER, &IID_IBaseFilter, (LPVOID*)&pnull);
287 if (hr == REGDB_E_CLASSNOTREG)
289 win_skip("Null renderer not registered, skipping\n");
290 break;
292 ok(hr == S_OK, "Could not create null renderer: %08x\n", hr);
294 hr = IBaseFilter_EnumPins(pnull, &nullenum);
295 ok(hr == S_OK, "Failed to enum pins, hr %#x.\n", hr);
296 hr = IEnumPins_Next(nullenum, 1, &nullpin, NULL);
297 ok(hr == S_OK, "Failed to get next pin, hr %#x.\n", hr);
298 IEnumPins_Release(nullenum);
299 IPin_QueryDirection(nullpin, &dir);
301 hr = IPin_Connect(avipin, nullpin, NULL);
302 ok(hr == S_OK, "Failed to connect output pin: %08x\n", hr);
303 IPin_Release(nullpin);
304 if (hr != S_OK)
306 IBaseFilter_Release(pnull);
307 break;
309 IBaseFilter_Run(pnull, 0);
312 IPin_Release(avipin);
313 avipin = NULL;
316 if (avipin)
317 IPin_Release(avipin);
318 avipin = NULL;
320 if (hr != S_OK)
321 goto fail2;
322 /* At this point there is a minimalistic connected avi splitter that can
323 * be used for all sorts of source filter tests. However that still needs
324 * to be written at a later time.
326 * Interesting tests:
327 * - Can you disconnect an output pin while running?
328 * Expecting: Yes
329 * - Can you disconnect the pullpin while running?
330 * Expecting: No
331 * - Is the reference count incremented during playback or when connected?
332 * Does this happen once for every output pin? Or is there something else
333 * going on.
334 * Expecting: You tell me
337 IBaseFilter_Run(preader, 0);
338 IBaseFilter_Run(pavi, 0);
339 IBaseFilter_GetState(pavi, INFINITE, &state);
341 IBaseFilter_Pause(pavi);
342 IBaseFilter_Pause(preader);
343 IBaseFilter_Stop(pavi);
344 IBaseFilter_Stop(preader);
345 IBaseFilter_GetState(pavi, INFINITE, &state);
346 IBaseFilter_GetState(preader, INFINITE, &state);
348 fail2:
349 IEnumPins_Reset(enumpins);
350 while (IEnumPins_Next(enumpins, 1, &avipin, NULL) == S_OK)
352 IPin *to = NULL;
354 IPin_QueryDirection(avipin, &dir);
355 IPin_ConnectedTo(avipin, &to);
356 if (to)
358 IPin_Release(to);
360 if (dir == PINDIR_OUTPUT)
362 PIN_INFO info;
364 hr = IPin_QueryPinInfo(to, &info);
365 ok(hr == S_OK, "Failed to query pin info, hr %#x.\n", hr);
367 /* Release twice: Once normal, second from the
368 * previous while loop
370 IBaseFilter_Stop(info.pFilter);
371 IPin_Disconnect(to);
372 IPin_Disconnect(avipin);
373 IBaseFilter_Release(info.pFilter);
374 IBaseFilter_Release(info.pFilter);
376 else
378 IPin_Disconnect(to);
379 IPin_Disconnect(avipin);
382 IPin_Release(avipin);
383 avipin = NULL;
386 fail:
387 if (hr != S_OK)
388 skip("Prerequisites not matched, skipping remainder of test\n");
389 if (enumpins)
390 IEnumPins_Release(enumpins);
392 if (avipin)
393 IPin_Release(avipin);
394 if (filepin)
396 IPin *to = NULL;
398 IPin_ConnectedTo(filepin, &to);
399 if (to)
401 IPin_Disconnect(filepin);
402 IPin_Disconnect(to);
404 IPin_Release(filepin);
407 if (preader)
408 IBaseFilter_Release(preader);
409 if (pavi)
410 IBaseFilter_Release(pavi);
411 if (pfile)
412 IFileSourceFilter_Release(pfile);
414 DeleteFileW(filename);
417 START_TEST(avisplitter)
419 CoInitialize(NULL);
421 if (!create_avisplitter())
423 skip("Could not create avisplitter\n");
424 return;
427 test_query_interface();
428 test_basefilter();
429 test_filter_graph();
431 release_avisplitter();
433 CoUninitialize();