quartz: A couple of spelling fixes in comments.
[wine.git] / dlls / quartz / tests / filtergraph.c
blob1089de7224f95d9da8ad4750dcfc5959199435f0
1 /*
2 * Unit tests for Direct Show functions
4 * Copyright (C) 2004 Christian Costa
5 * Copyright (C) 2008 Alexander Dorofeyev
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 #define COBJMACROS
23 #define CONST_VTABLE
25 #include "wine/test.h"
26 #include "dshow.h"
27 #include "control.h"
29 typedef struct TestFilterImpl
31 IBaseFilter IBaseFilter_iface;
33 LONG refCount;
34 CRITICAL_SECTION csFilter;
35 FILTER_STATE state;
36 FILTER_INFO filterInfo;
37 CLSID clsid;
38 IPin **ppPins;
39 UINT nPins;
40 } TestFilterImpl;
42 static const WCHAR avifile[] = {'t','e','s','t','.','a','v','i',0};
43 static const WCHAR mpegfile[] = {'t','e','s','t','.','m','p','g',0};
45 static IGraphBuilder *pgraph;
47 static int createfiltergraph(void)
49 return S_OK == CoCreateInstance(
50 &CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, &IID_IGraphBuilder, (LPVOID*)&pgraph);
53 static void test_basic_video(void)
55 IBasicVideo* pbv;
56 LONG video_width, video_height;
57 LONG left, top, width, height;
58 HRESULT hr;
60 hr = IGraphBuilder_QueryInterface(pgraph, &IID_IBasicVideo, (LPVOID*)&pbv);
61 ok(hr==S_OK, "Cannot get IBasicVideo interface returned: %x\n", hr);
63 /* test get video size */
64 hr = IBasicVideo_GetVideoSize(pbv, NULL, NULL);
65 ok(hr==E_POINTER, "IBasicVideo_GetVideoSize returned: %x\n", hr);
66 hr = IBasicVideo_GetVideoSize(pbv, &video_width, NULL);
67 ok(hr==E_POINTER, "IBasicVideo_GetVideoSize returned: %x\n", hr);
68 hr = IBasicVideo_GetVideoSize(pbv, NULL, &video_height);
69 ok(hr==E_POINTER, "IBasicVideo_GetVideoSize returned: %x\n", hr);
70 hr = IBasicVideo_GetVideoSize(pbv, &video_width, &video_height);
71 ok(hr==S_OK, "Cannot get video size returned: %x\n", hr);
73 /* test source position */
74 hr = IBasicVideo_GetSourcePosition(pbv, NULL, NULL, NULL, NULL);
75 ok(hr == E_POINTER, "IBasicVideo_GetSourcePosition returned: %x\n", hr);
76 hr = IBasicVideo_GetSourcePosition(pbv, &left, &top, NULL, NULL);
77 ok(hr == E_POINTER, "IBasicVideo_GetSourcePosition returned: %x\n", hr);
78 hr = IBasicVideo_GetSourcePosition(pbv, NULL, NULL, &width, &height);
79 ok(hr == E_POINTER, "IBasicVideo_GetSourcePosition returned: %x\n", hr);
80 hr = IBasicVideo_GetSourcePosition(pbv, &left, &top, &width, &height);
81 ok(hr == S_OK, "Cannot get source position returned: %x\n", hr);
82 ok(left == 0, "expected 0, got %d\n", left);
83 ok(top == 0, "expected 0, got %d\n", top);
84 ok(width == video_width, "expected %d, got %d\n", video_width, width);
85 ok(height == video_height, "expected %d, got %d\n", video_height, height);
87 hr = IBasicVideo_SetSourcePosition(pbv, 0, 0, 0, 0);
88 ok(hr==E_INVALIDARG, "IBasicVideo_SetSourcePosition returned: %x\n", hr);
89 hr = IBasicVideo_SetSourcePosition(pbv, 0, 0, video_width*2, video_height*2);
90 ok(hr==E_INVALIDARG, "IBasicVideo_SetSourcePosition returned: %x\n", hr);
91 hr = IBasicVideo_put_SourceTop(pbv, -1);
92 ok(hr==E_INVALIDARG, "IBasicVideo_put_SourceTop returned: %x\n", hr);
93 hr = IBasicVideo_put_SourceTop(pbv, 0);
94 ok(hr==S_OK, "Cannot put source top returned: %x\n", hr);
95 hr = IBasicVideo_put_SourceTop(pbv, 1);
96 ok(hr==E_INVALIDARG, "IBasicVideo_put_SourceTop returned: %x\n", hr);
98 hr = IBasicVideo_SetSourcePosition(pbv, video_width, 0, video_width, video_height);
99 ok(hr==E_INVALIDARG, "IBasicVideo_SetSourcePosition returned: %x\n", hr);
100 hr = IBasicVideo_SetSourcePosition(pbv, 0, video_height, video_width, video_height);
101 ok(hr==E_INVALIDARG, "IBasicVideo_SetSourcePosition returned: %x\n", hr);
102 hr = IBasicVideo_SetSourcePosition(pbv, -1, 0, video_width, video_height);
103 ok(hr==E_INVALIDARG, "IBasicVideo_SetSourcePosition returned: %x\n", hr);
104 hr = IBasicVideo_SetSourcePosition(pbv, 0, -1, video_width, video_height);
105 ok(hr==E_INVALIDARG, "IBasicVideo_SetSourcePosition returned: %x\n", hr);
106 hr = IBasicVideo_SetSourcePosition(pbv, video_width/2, video_height/2, video_width, video_height);
107 ok(hr==E_INVALIDARG, "IBasicVideo_SetSourcePosition returned: %x\n", hr);
108 hr = IBasicVideo_SetSourcePosition(pbv, video_width/2, video_height/2, video_width, video_height);
109 ok(hr==E_INVALIDARG, "IBasicVideo_SetSourcePosition returned: %x\n", hr);
111 hr = IBasicVideo_SetSourcePosition(pbv, 0, 0, video_width, video_height+1);
112 ok(hr==E_INVALIDARG, "IBasicVideo_SetSourcePosition returned: %x\n", hr);
113 hr = IBasicVideo_SetSourcePosition(pbv, 0, 0, video_width+1, video_height);
114 ok(hr==E_INVALIDARG, "IBasicVideo_SetSourcePosition returned: %x\n", hr);
116 hr = IBasicVideo_SetSourcePosition(pbv, video_width/2, video_height/2, video_width/3+1, video_height/3+1);
117 ok(hr==S_OK, "Cannot set source position returned: %x\n", hr);
119 hr = IBasicVideo_get_SourceLeft(pbv, &left);
120 ok(hr==S_OK, "Cannot get source left returned: %x\n", hr);
121 ok(left==video_width/2, "expected %d, got %d\n", video_width/2, left);
122 hr = IBasicVideo_get_SourceTop(pbv, &top);
123 ok(hr==S_OK, "Cannot get source top returned: %x\n", hr);
124 ok(top==video_height/2, "expected %d, got %d\n", video_height/2, top);
125 hr = IBasicVideo_get_SourceWidth(pbv, &width);
126 ok(hr==S_OK, "Cannot get source width returned: %x\n", hr);
127 ok(width==video_width/3+1, "expected %d, got %d\n", video_width/3+1, width);
128 hr = IBasicVideo_get_SourceHeight(pbv, &height);
129 ok(hr==S_OK, "Cannot get source height returned: %x\n", hr);
130 ok(height==video_height/3+1, "expected %d, got %d\n", video_height/3+1, height);
132 hr = IBasicVideo_put_SourceLeft(pbv, video_width/3);
133 ok(hr==S_OK, "Cannot put source left returned: %x\n", hr);
134 hr = IBasicVideo_GetSourcePosition(pbv, &left, &top, &width, &height);
135 ok(hr == S_OK, "Cannot get source position returned: %x\n", hr);
136 ok(left == video_width/3, "expected %d, got %d\n", video_width/3, left);
137 ok(width == video_width/3+1, "expected %d, got %d\n", video_width/3+1, width);
139 hr = IBasicVideo_put_SourceTop(pbv, video_height/3);
140 ok(hr==S_OK, "Cannot put source top returned: %x\n", hr);
141 hr = IBasicVideo_GetSourcePosition(pbv, &left, &top, &width, &height);
142 ok(hr == S_OK, "Cannot get source position returned: %x\n", hr);
143 ok(top == video_height/3, "expected %d, got %d\n", video_height/3, top);
144 ok(height == video_height/3+1, "expected %d, got %d\n", video_height/3+1, height);
146 hr = IBasicVideo_put_SourceWidth(pbv, video_width/4+1);
147 ok(hr==S_OK, "Cannot put source width returned: %x\n", hr);
148 hr = IBasicVideo_GetSourcePosition(pbv, &left, &top, &width, &height);
149 ok(hr == S_OK, "Cannot get source position returned: %x\n", hr);
150 ok(left == video_width/3, "expected %d, got %d\n", video_width/3, left);
151 ok(width == video_width/4+1, "expected %d, got %d\n", video_width/4+1, width);
153 hr = IBasicVideo_put_SourceHeight(pbv, video_height/4+1);
154 ok(hr==S_OK, "Cannot put source height returned: %x\n", hr);
155 hr = IBasicVideo_GetSourcePosition(pbv, &left, &top, &width, &height);
156 ok(hr == S_OK, "Cannot get source position returned: %x\n", hr);
157 ok(top == video_height/3, "expected %d, got %d\n", video_height/3, top);
158 ok(height == video_height/4+1, "expected %d, got %d\n", video_height/4+1, height);
160 /* test destination rectangle */
161 hr = IBasicVideo_GetDestinationPosition(pbv, NULL, NULL, NULL, NULL);
162 ok(hr == E_POINTER, "IBasicVideo_GetDestinationPosition returned: %x\n", hr);
163 hr = IBasicVideo_GetDestinationPosition(pbv, &left, &top, NULL, NULL);
164 ok(hr == E_POINTER, "IBasicVideo_GetDestinationPosition returned: %x\n", hr);
165 hr = IBasicVideo_GetDestinationPosition(pbv, NULL, NULL, &width, &height);
166 ok(hr == E_POINTER, "IBasicVideo_GetDestinationPosition returned: %x\n", hr);
167 hr = IBasicVideo_GetDestinationPosition(pbv, &left, &top, &width, &height);
168 ok(hr == S_OK, "Cannot get destination position returned: %x\n", hr);
169 ok(left == 0, "expected 0, got %d\n", left);
170 ok(top == 0, "expected 0, got %d\n", top);
171 todo_wine ok(width == video_width, "expected %d, got %d\n", video_width, width);
172 todo_wine ok(height == video_height, "expected %d, got %d\n", video_height, height);
174 hr = IBasicVideo_SetDestinationPosition(pbv, 0, 0, 0, 0);
175 ok(hr==E_INVALIDARG, "IBasicVideo_SetDestinationPosition returned: %x\n", hr);
176 hr = IBasicVideo_SetDestinationPosition(pbv, 0, 0, video_width*2, video_height*2);
177 ok(hr==S_OK, "Cannot put destination position returned: %x\n", hr);
179 hr = IBasicVideo_put_DestinationLeft(pbv, -1);
180 ok(hr==S_OK, "Cannot put destination left returned: %x\n", hr);
181 hr = IBasicVideo_put_DestinationLeft(pbv, 0);
182 ok(hr==S_OK, "Cannot put destination left returned: %x\n", hr);
183 hr = IBasicVideo_put_DestinationLeft(pbv, 1);
184 ok(hr==S_OK, "Cannot put destination left returned: %x\n", hr);
186 hr = IBasicVideo_SetDestinationPosition(pbv, video_width, 0, video_width, video_height);
187 ok(hr==S_OK, "Cannot set destinaiton position returned: %x\n", hr);
188 hr = IBasicVideo_SetDestinationPosition(pbv, 0, video_height, video_width, video_height);
189 ok(hr==S_OK, "Cannot set destinaiton position returned: %x\n", hr);
190 hr = IBasicVideo_SetDestinationPosition(pbv, -1, 0, video_width, video_height);
191 ok(hr==S_OK, "Cannot set destination position returned: %x\n", hr);
192 hr = IBasicVideo_SetDestinationPosition(pbv, 0, -1, video_width, video_height);
193 ok(hr==S_OK, "Cannot set destination position returned: %x\n", hr);
194 hr = IBasicVideo_SetDestinationPosition(pbv, video_width/2, video_height/2, video_width, video_height);
195 ok(hr==S_OK, "Cannot set destination position returned: %x\n", hr);
196 hr = IBasicVideo_SetDestinationPosition(pbv, video_width/2, video_height/2, video_width, video_height);
197 ok(hr==S_OK, "Cannot set destination position returned: %x\n", hr);
199 hr = IBasicVideo_SetDestinationPosition(pbv, 0, 0, video_width, video_height+1);
200 ok(hr==S_OK, "Cannot set destination position returned: %x\n", hr);
201 hr = IBasicVideo_SetDestinationPosition(pbv, 0, 0, video_width+1, video_height);
202 ok(hr==S_OK, "Cannot set destination position returned: %x\n", hr);
204 hr = IBasicVideo_SetDestinationPosition(pbv, video_width/2, video_height/2, video_width/3+1, video_height/3+1);
205 ok(hr==S_OK, "Cannot set destination position returned: %x\n", hr);
207 hr = IBasicVideo_get_DestinationLeft(pbv, &left);
208 ok(hr==S_OK, "Cannot get destination left returned: %x\n", hr);
209 ok(left==video_width/2, "expected %d, got %d\n", video_width/2, left);
210 hr = IBasicVideo_get_DestinationTop(pbv, &top);
211 ok(hr==S_OK, "Cannot get destination top returned: %x\n", hr);
212 ok(top==video_height/2, "expected %d, got %d\n", video_height/2, top);
213 hr = IBasicVideo_get_DestinationWidth(pbv, &width);
214 ok(hr==S_OK, "Cannot get destination width returned: %x\n", hr);
215 ok(width==video_width/3+1, "expected %d, got %d\n", video_width/3+1, width);
216 hr = IBasicVideo_get_DestinationHeight(pbv, &height);
217 ok(hr==S_OK, "Cannot get destination height returned: %x\n", hr);
218 ok(height==video_height/3+1, "expected %d, got %d\n", video_height/3+1, height);
220 hr = IBasicVideo_put_DestinationLeft(pbv, video_width/3);
221 ok(hr==S_OK, "Cannot put destination left returned: %x\n", hr);
222 hr = IBasicVideo_GetDestinationPosition(pbv, &left, &top, &width, &height);
223 ok(hr == S_OK, "Cannot get source position returned: %x\n", hr);
224 ok(left == video_width/3, "expected %d, got %d\n", video_width/3, left);
225 ok(width == video_width/3+1, "expected %d, got %d\n", video_width/3+1, width);
227 hr = IBasicVideo_put_DestinationTop(pbv, video_height/3);
228 ok(hr==S_OK, "Cannot put destination top returned: %x\n", hr);
229 hr = IBasicVideo_GetDestinationPosition(pbv, &left, &top, &width, &height);
230 ok(hr == S_OK, "Cannot get source position returned: %x\n", hr);
231 ok(top == video_height/3, "expected %d, got %d\n", video_height/3, top);
232 ok(height == video_height/3+1, "expected %d, got %d\n", video_height/3+1, height);
234 hr = IBasicVideo_put_DestinationWidth(pbv, video_width/4+1);
235 ok(hr==S_OK, "Cannot put destination width returned: %x\n", hr);
236 hr = IBasicVideo_GetDestinationPosition(pbv, &left, &top, &width, &height);
237 ok(hr == S_OK, "Cannot get source position returned: %x\n", hr);
238 ok(left == video_width/3, "expected %d, got %d\n", video_width/3, left);
239 ok(width == video_width/4+1, "expected %d, got %d\n", video_width/4+1, width);
241 hr = IBasicVideo_put_DestinationHeight(pbv, video_height/4+1);
242 ok(hr==S_OK, "Cannot put destination height returned: %x\n", hr);
243 hr = IBasicVideo_GetDestinationPosition(pbv, &left, &top, &width, &height);
244 ok(hr == S_OK, "Cannot get source position returned: %x\n", hr);
245 ok(top == video_height/3, "expected %d, got %d\n", video_height/3, top);
246 ok(height == video_height/4+1, "expected %d, got %d\n", video_height/4+1, height);
248 /* reset source rectangle */
249 hr = IBasicVideo_SetDefaultSourcePosition(pbv);
250 ok(hr==S_OK, "IBasicVideo_SetDefaultSourcePosition returned: %x\n", hr);
252 /* reset destination position */
253 hr = IBasicVideo_SetDestinationPosition(pbv, 0, 0, video_width, video_height);
254 ok(hr==S_OK, "Cannot set destination position returned: %x\n", hr);
256 IBasicVideo_Release(pbv);
259 static void rungraph(void)
261 HRESULT hr;
262 IMediaControl* pmc;
263 IMediaEvent* pme;
264 IMediaFilter* pmf;
265 HANDLE hEvent;
267 hr = IGraphBuilder_QueryInterface(pgraph, &IID_IMediaControl, (LPVOID*)&pmc);
268 ok(hr==S_OK, "Cannot get IMediaControl interface returned: %x\n", hr);
270 hr = IGraphBuilder_QueryInterface(pgraph, &IID_IMediaFilter, (LPVOID*)&pmf);
271 ok(hr==S_OK, "Cannot get IMediaFilter interface returned: %x\n", hr);
273 IMediaControl_Stop(pmc);
275 IMediaFilter_SetSyncSource(pmf, NULL);
277 IMediaFilter_Release(pmf);
279 test_basic_video();
281 hr = IMediaControl_Run(pmc);
282 ok(hr==S_FALSE, "Cannot run the graph returned: %x\n", hr);
284 Sleep(10);
285 /* Crash fun */
286 trace("run -> stop\n");
287 hr = IMediaControl_Stop(pmc);
288 ok(hr==S_OK || hr == S_FALSE, "Cannot stop the graph returned: %x\n", hr);
290 IGraphBuilder_SetDefaultSyncSource(pgraph);
292 Sleep(10);
293 trace("stop -> pause\n");
294 hr = IMediaControl_Pause(pmc);
295 ok(hr==S_OK || hr == S_FALSE, "Cannot pause the graph returned: %x\n", hr);
297 Sleep(10);
298 trace("pause -> run\n");
299 hr = IMediaControl_Run(pmc);
300 ok(hr==S_OK || hr == S_FALSE, "Cannot start the graph returned: %x\n", hr);
302 Sleep(10);
303 trace("run -> pause\n");
304 hr = IMediaControl_Pause(pmc);
305 ok(hr==S_OK || hr == S_FALSE, "Cannot pause the graph returned: %x\n", hr);
307 Sleep(10);
308 trace("pause -> stop\n");
309 hr = IMediaControl_Stop(pmc);
310 ok(hr==S_OK || hr == S_FALSE, "Cannot stop the graph returned: %x\n", hr);
312 Sleep(10);
313 trace("pause -> run\n");
314 hr = IMediaControl_Run(pmc);
315 ok(hr==S_OK || hr == S_FALSE, "Cannot start the graph returned: %x\n", hr);
317 trace("run -> stop\n");
318 hr = IMediaControl_Stop(pmc);
319 ok(hr==S_OK || hr == S_FALSE, "Cannot stop the graph returned: %x\n", hr);
321 trace("stop -> run\n");
322 hr = IMediaControl_Run(pmc);
323 ok(hr==S_OK || hr == S_FALSE, "Cannot start the graph returned: %x\n", hr);
325 hr = IGraphBuilder_QueryInterface(pgraph, &IID_IMediaEvent, (LPVOID*)&pme);
326 ok(hr==S_OK, "Cannot get IMediaEvent interface returned: %x\n", hr);
328 hr = IMediaEvent_GetEventHandle(pme, (OAEVENT*)&hEvent);
329 ok(hr==S_OK, "Cannot get event handle returned: %x\n", hr);
331 /* WaitForSingleObject(hEvent, INFINITE); */
332 Sleep(20000);
334 hr = IMediaEvent_Release(pme);
335 ok(hr==2, "Releasing mediaevent returned: %x\n", hr);
337 hr = IMediaControl_Stop(pmc);
338 ok(hr==S_OK, "Cannot stop the graph returned: %x\n", hr);
340 hr = IMediaControl_Release(pmc);
341 ok(hr==1, "Releasing mediacontrol returned: %x\n", hr);
344 static void releasefiltergraph(void)
346 HRESULT hr;
348 hr = IGraphBuilder_Release(pgraph);
349 ok(hr==0, "Releasing filtergraph returned: %x\n", hr);
352 static void test_render_run(const WCHAR *file)
354 HANDLE h;
355 HRESULT hr;
357 h = CreateFileW(file, 0, 0, NULL, OPEN_EXISTING, 0, NULL);
358 if (h == INVALID_HANDLE_VALUE) {
359 skip("Could not read test file %s, skipping test\n", wine_dbgstr_w(file));
360 return;
362 CloseHandle(h);
364 if (!createfiltergraph())
365 return;
367 hr = IGraphBuilder_RenderFile(pgraph, file, NULL);
368 ok(hr == S_OK, "RenderFile returned: %x\n", hr);
369 rungraph();
371 releasefiltergraph();
373 /* check reference leaks */
374 h = CreateFileW(file, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);
375 ok(h != INVALID_HANDLE_VALUE, "CreateFile failed: err=%d\n", GetLastError());
376 CloseHandle(h);
379 static void test_graph_builder(void)
381 HRESULT hr;
382 IBaseFilter *pF = NULL;
383 IBaseFilter *pF2 = NULL;
384 IPin *pIn = NULL;
385 IEnumPins *pEnum = NULL;
386 PIN_DIRECTION dir;
387 static const WCHAR testFilterW[] = {'t','e','s','t','F','i','l','t','e','r',0};
388 static const WCHAR fooBarW[] = {'f','o','o','B','a','r',0};
390 if (!createfiltergraph())
391 return;
393 /* create video filter */
394 hr = CoCreateInstance(&CLSID_VideoRenderer, NULL, CLSCTX_INPROC_SERVER,
395 &IID_IBaseFilter, (LPVOID*)&pF);
396 ok(hr == S_OK, "CoCreateInstance failed with %x\n", hr);
397 ok(pF != NULL, "pF is NULL\n");
399 hr = IGraphBuilder_AddFilter(pgraph, NULL, testFilterW);
400 ok(hr == E_POINTER, "IGraphBuilder_AddFilter returned %x\n", hr);
402 /* add the two filters to the graph */
403 hr = IGraphBuilder_AddFilter(pgraph, pF, testFilterW);
404 ok(hr == S_OK, "failed to add pF to the graph: %x\n", hr);
406 /* find the pins */
407 hr = IBaseFilter_EnumPins(pF, &pEnum);
408 ok(hr == S_OK, "IBaseFilter_EnumPins failed for pF: %x\n", hr);
409 ok(pEnum != NULL, "pEnum is NULL\n");
410 hr = IEnumPins_Next(pEnum, 1, &pIn, NULL);
411 ok(hr == S_OK, "IEnumPins_Next failed for pF: %x\n", hr);
412 ok(pIn != NULL, "pIn is NULL\n");
413 hr = IPin_QueryDirection(pIn, &dir);
414 ok(hr == S_OK, "IPin_QueryDirection failed: %x\n", hr);
415 ok(dir == PINDIR_INPUT, "pin has wrong direction\n");
417 hr = IGraphBuilder_FindFilterByName(pgraph, fooBarW, &pF2);
418 ok(hr == VFW_E_NOT_FOUND, "IGraphBuilder_FindFilterByName returned %x\n", hr);
419 ok(pF2 == NULL, "IGraphBuilder_FindFilterByName returned %p\n", pF2);
420 hr = IGraphBuilder_FindFilterByName(pgraph, testFilterW, &pF2);
421 ok(hr == S_OK, "IGraphBuilder_FindFilterByName returned %x\n", hr);
422 ok(pF2 != NULL, "IGraphBuilder_FindFilterByName returned NULL\n");
423 hr = IGraphBuilder_FindFilterByName(pgraph, testFilterW, NULL);
424 ok(hr == E_POINTER, "IGraphBuilder_FindFilterByName returned %x\n", hr);
426 hr = IGraphBuilder_Connect(pgraph, NULL, pIn);
427 ok(hr == E_POINTER, "IGraphBuilder_Connect returned %x\n", hr);
429 hr = IGraphBuilder_Connect(pgraph, pIn, NULL);
430 ok(hr == E_POINTER, "IGraphBuilder_Connect returned %x\n", hr);
432 hr = IGraphBuilder_Connect(pgraph, pIn, pIn);
433 ok(hr == VFW_E_CANNOT_CONNECT, "IGraphBuilder_Connect returned %x\n", hr);
435 if (pIn) IPin_Release(pIn);
436 if (pEnum) IEnumPins_Release(pEnum);
437 if (pF) IBaseFilter_Release(pF);
438 if (pF2) IBaseFilter_Release(pF2);
440 releasefiltergraph();
443 static void test_graph_builder_addfilter(void)
445 HRESULT hr;
446 IBaseFilter *pF = NULL;
447 static const WCHAR testFilterW[] = {'t','e','s','t','F','i','l','t','e','r',0};
449 if (!createfiltergraph())
450 return;
452 hr = IGraphBuilder_AddFilter(pgraph, NULL, testFilterW);
453 ok(hr == E_POINTER, "IGraphBuilder_AddFilter returned: %x\n", hr);
455 /* create video filter */
456 hr = CoCreateInstance(&CLSID_VideoRenderer, NULL, CLSCTX_INPROC_SERVER,
457 &IID_IBaseFilter, (LPVOID*)&pF);
458 ok(hr == S_OK, "CoCreateInstance failed with %x\n", hr);
459 ok(pF != NULL, "pF is NULL\n");
460 if (!pF) {
461 skip("failed to created filter, skipping\n");
462 return;
465 hr = IGraphBuilder_AddFilter(pgraph, pF, NULL);
466 ok(hr == S_OK, "IGraphBuilder_AddFilter returned: %x\n", hr);
467 IBaseFilter_Release(pF);
470 static void test_mediacontrol(void)
472 HRESULT hr;
473 LONGLONG pos = 0xdeadbeef;
474 GUID format = GUID_NULL;
475 IMediaSeeking *seeking = NULL;
476 IMediaFilter *filter = NULL;
477 IMediaControl *control = NULL;
479 IGraphBuilder_SetDefaultSyncSource(pgraph);
480 hr = IGraphBuilder_QueryInterface(pgraph, &IID_IMediaSeeking, (void**) &seeking);
481 ok(hr == S_OK, "QueryInterface IMediaControl failed: %08x\n", hr);
482 if (FAILED(hr))
483 return;
485 hr = IGraphBuilder_QueryInterface(pgraph, &IID_IMediaFilter, (void**) &filter);
486 ok(hr == S_OK, "QueryInterface IMediaFilter failed: %08x\n", hr);
487 if (FAILED(hr))
489 IMediaSeeking_Release(seeking);
490 return;
493 hr = IGraphBuilder_QueryInterface(pgraph, &IID_IMediaControl, (void**) &control);
494 ok(hr == S_OK, "QueryInterface IMediaControl failed: %08x\n", hr);
495 if (FAILED(hr))
497 IMediaSeeking_Release(seeking);
498 IMediaFilter_Release(filter);
499 return;
502 format = GUID_NULL;
503 hr = IMediaSeeking_GetTimeFormat(seeking, &format);
504 ok(hr == S_OK, "GetTimeFormat failed: %08x\n", hr);
505 ok(IsEqualGUID(&format, &TIME_FORMAT_MEDIA_TIME), "GetTimeFormat: unexpected format %s\n", wine_dbgstr_guid(&format));
507 pos = 0xdeadbeef;
508 hr = IMediaSeeking_ConvertTimeFormat(seeking, &pos, NULL, 0x123456789a, NULL);
509 ok(hr == S_OK, "ConvertTimeFormat failed: %08x\n", hr);
510 ok(pos == 0x123456789a, "ConvertTimeFormat: expected 123456789a, got (%x%08x)\n", (DWORD)(pos >> 32), (DWORD)pos);
512 pos = 0xdeadbeef;
513 hr = IMediaSeeking_ConvertTimeFormat(seeking, &pos, &TIME_FORMAT_MEDIA_TIME, 0x123456789a, NULL);
514 ok(hr == S_OK, "ConvertTimeFormat failed: %08x\n", hr);
515 ok(pos == 0x123456789a, "ConvertTimeFormat: expected 123456789a, got (%x%08x)\n", (DWORD)(pos >> 32), (DWORD)pos);
517 pos = 0xdeadbeef;
518 hr = IMediaSeeking_ConvertTimeFormat(seeking, &pos, NULL, 0x123456789a, &TIME_FORMAT_MEDIA_TIME);
519 ok(hr == S_OK, "ConvertTimeFormat failed: %08x\n", hr);
520 ok(pos == 0x123456789a, "ConvertTimeFormat: expected 123456789a, got (%x%08x)\n", (DWORD)(pos >> 32), (DWORD)pos);
522 hr = IMediaSeeking_GetCurrentPosition(seeking, &pos);
523 ok(hr == S_OK, "GetCurrentPosition failed: %08x\n", hr);
524 ok(pos == 0, "Position != 0 (%x%08x)\n", (DWORD)(pos >> 32), (DWORD)pos);
526 hr = IMediaSeeking_SetPositions(seeking, NULL, AM_SEEKING_ReturnTime, NULL, AM_SEEKING_NoPositioning);
527 ok(hr == S_OK, "SetPositions failed: %08x\n", hr);
528 hr = IMediaSeeking_SetPositions(seeking, NULL, AM_SEEKING_NoPositioning, NULL, AM_SEEKING_ReturnTime);
529 ok(hr == S_OK, "SetPositions failed: %08x\n", hr);
531 IMediaFilter_SetSyncSource(filter, NULL);
532 pos = 0xdeadbeef;
533 hr = IMediaSeeking_GetCurrentPosition(seeking, &pos);
534 ok(hr == S_OK, "GetCurrentPosition failed: %08x\n", hr);
535 ok(pos == 0, "Position != 0 (%x%08x)\n", (DWORD)(pos >> 32), (DWORD)pos);
537 hr = IMediaControl_GetState(control, 1000, NULL);
538 ok(hr == E_POINTER, "GetState expected %08x, got %08x\n", E_POINTER, hr);
540 IMediaControl_Release(control);
541 IMediaSeeking_Release(seeking);
542 IMediaFilter_Release(filter);
543 releasefiltergraph();
546 static void test_filter_graph2(void)
548 HRESULT hr;
549 IFilterGraph2 *pF = NULL;
551 hr = CoCreateInstance(&CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER,
552 &IID_IFilterGraph2, (LPVOID*)&pF);
553 ok(hr == S_OK, "CoCreateInstance failed with %x\n", hr);
554 ok(pF != NULL, "pF is NULL\n");
556 hr = IFilterGraph2_Release(pF);
557 ok(hr == 0, "IFilterGraph2_Release returned: %x\n", hr);
560 /* IEnumMediaTypes implementation (supporting code for Render() test.) */
561 static void FreeMediaType(AM_MEDIA_TYPE * pMediaType)
563 if (pMediaType->pbFormat)
565 CoTaskMemFree(pMediaType->pbFormat);
566 pMediaType->pbFormat = NULL;
568 if (pMediaType->pUnk)
570 IUnknown_Release(pMediaType->pUnk);
571 pMediaType->pUnk = NULL;
575 static HRESULT CopyMediaType(AM_MEDIA_TYPE * pDest, const AM_MEDIA_TYPE *pSrc)
577 *pDest = *pSrc;
578 if (!pSrc->pbFormat) return S_OK;
579 if (!(pDest->pbFormat = CoTaskMemAlloc(pSrc->cbFormat)))
580 return E_OUTOFMEMORY;
581 memcpy(pDest->pbFormat, pSrc->pbFormat, pSrc->cbFormat);
582 if (pDest->pUnk)
583 IUnknown_AddRef(pDest->pUnk);
584 return S_OK;
587 static AM_MEDIA_TYPE * CreateMediaType(AM_MEDIA_TYPE const * pSrc)
589 AM_MEDIA_TYPE * pDest;
591 pDest = CoTaskMemAlloc(sizeof(AM_MEDIA_TYPE));
592 if (!pDest)
593 return NULL;
595 if (FAILED(CopyMediaType(pDest, pSrc)))
597 CoTaskMemFree(pDest);
598 return NULL;
601 return pDest;
604 static BOOL CompareMediaTypes(const AM_MEDIA_TYPE * pmt1, const AM_MEDIA_TYPE * pmt2, BOOL bWildcards)
606 return (((bWildcards && (IsEqualGUID(&pmt1->majortype, &GUID_NULL) || IsEqualGUID(&pmt2->majortype, &GUID_NULL))) || IsEqualGUID(&pmt1->majortype, &pmt2->majortype)) &&
607 ((bWildcards && (IsEqualGUID(&pmt1->subtype, &GUID_NULL) || IsEqualGUID(&pmt2->subtype, &GUID_NULL))) || IsEqualGUID(&pmt1->subtype, &pmt2->subtype)));
610 static void DeleteMediaType(AM_MEDIA_TYPE * pMediaType)
612 FreeMediaType(pMediaType);
613 CoTaskMemFree(pMediaType);
616 typedef struct IEnumMediaTypesImpl
618 IEnumMediaTypes IEnumMediaTypes_iface;
619 LONG refCount;
620 AM_MEDIA_TYPE *pMediaTypes;
621 ULONG cMediaTypes;
622 ULONG uIndex;
623 } IEnumMediaTypesImpl;
625 static const struct IEnumMediaTypesVtbl IEnumMediaTypesImpl_Vtbl;
627 static inline IEnumMediaTypesImpl *impl_from_IEnumMediaTypes(IEnumMediaTypes *iface)
629 return CONTAINING_RECORD(iface, IEnumMediaTypesImpl, IEnumMediaTypes_iface);
632 static HRESULT IEnumMediaTypesImpl_Construct(const AM_MEDIA_TYPE * pMediaTypes, ULONG cMediaTypes, IEnumMediaTypes ** ppEnum)
634 ULONG i;
635 IEnumMediaTypesImpl * pEnumMediaTypes = CoTaskMemAlloc(sizeof(IEnumMediaTypesImpl));
637 if (!pEnumMediaTypes)
639 *ppEnum = NULL;
640 return E_OUTOFMEMORY;
642 pEnumMediaTypes->IEnumMediaTypes_iface.lpVtbl = &IEnumMediaTypesImpl_Vtbl;
643 pEnumMediaTypes->refCount = 1;
644 pEnumMediaTypes->uIndex = 0;
645 pEnumMediaTypes->cMediaTypes = cMediaTypes;
646 pEnumMediaTypes->pMediaTypes = CoTaskMemAlloc(sizeof(AM_MEDIA_TYPE) * cMediaTypes);
647 for (i = 0; i < cMediaTypes; i++)
648 if (FAILED(CopyMediaType(&pEnumMediaTypes->pMediaTypes[i], &pMediaTypes[i])))
650 while (i--)
651 FreeMediaType(&pEnumMediaTypes->pMediaTypes[i]);
652 CoTaskMemFree(pEnumMediaTypes->pMediaTypes);
653 return E_OUTOFMEMORY;
655 *ppEnum = &pEnumMediaTypes->IEnumMediaTypes_iface;
656 return S_OK;
659 static HRESULT WINAPI IEnumMediaTypesImpl_QueryInterface(IEnumMediaTypes * iface, REFIID riid, LPVOID * ppv)
661 *ppv = NULL;
663 if (IsEqualIID(riid, &IID_IUnknown))
664 *ppv = iface;
665 else if (IsEqualIID(riid, &IID_IEnumMediaTypes))
666 *ppv = iface;
668 if (*ppv)
670 IUnknown_AddRef((IUnknown *)(*ppv));
671 return S_OK;
674 return E_NOINTERFACE;
677 static ULONG WINAPI IEnumMediaTypesImpl_AddRef(IEnumMediaTypes * iface)
679 IEnumMediaTypesImpl *This = impl_from_IEnumMediaTypes(iface);
680 ULONG refCount = InterlockedIncrement(&This->refCount);
682 return refCount;
685 static ULONG WINAPI IEnumMediaTypesImpl_Release(IEnumMediaTypes * iface)
687 IEnumMediaTypesImpl *This = impl_from_IEnumMediaTypes(iface);
688 ULONG refCount = InterlockedDecrement(&This->refCount);
690 if (!refCount)
692 int i;
693 for (i = 0; i < This->cMediaTypes; i++)
694 FreeMediaType(&This->pMediaTypes[i]);
695 CoTaskMemFree(This->pMediaTypes);
696 CoTaskMemFree(This);
698 return refCount;
701 static HRESULT WINAPI IEnumMediaTypesImpl_Next(IEnumMediaTypes * iface, ULONG cMediaTypes, AM_MEDIA_TYPE ** ppMediaTypes, ULONG * pcFetched)
703 ULONG cFetched;
704 IEnumMediaTypesImpl *This = impl_from_IEnumMediaTypes(iface);
706 cFetched = min(This->cMediaTypes, This->uIndex + cMediaTypes) - This->uIndex;
708 if (cFetched > 0)
710 ULONG i;
711 for (i = 0; i < cFetched; i++)
712 if (!(ppMediaTypes[i] = CreateMediaType(&This->pMediaTypes[This->uIndex + i])))
714 while (i--)
715 DeleteMediaType(ppMediaTypes[i]);
716 *pcFetched = 0;
717 return E_OUTOFMEMORY;
721 if ((cMediaTypes != 1) || pcFetched)
722 *pcFetched = cFetched;
724 This->uIndex += cFetched;
726 if (cFetched != cMediaTypes)
727 return S_FALSE;
728 return S_OK;
731 static HRESULT WINAPI IEnumMediaTypesImpl_Skip(IEnumMediaTypes * iface, ULONG cMediaTypes)
733 IEnumMediaTypesImpl *This = impl_from_IEnumMediaTypes(iface);
735 if (This->uIndex + cMediaTypes < This->cMediaTypes)
737 This->uIndex += cMediaTypes;
738 return S_OK;
740 return S_FALSE;
743 static HRESULT WINAPI IEnumMediaTypesImpl_Reset(IEnumMediaTypes * iface)
745 IEnumMediaTypesImpl *This = impl_from_IEnumMediaTypes(iface);
747 This->uIndex = 0;
748 return S_OK;
751 static HRESULT WINAPI IEnumMediaTypesImpl_Clone(IEnumMediaTypes * iface, IEnumMediaTypes ** ppEnum)
753 HRESULT hr;
754 IEnumMediaTypesImpl *This = impl_from_IEnumMediaTypes(iface);
756 hr = IEnumMediaTypesImpl_Construct(This->pMediaTypes, This->cMediaTypes, ppEnum);
757 if (FAILED(hr))
758 return hr;
759 return IEnumMediaTypes_Skip(*ppEnum, This->uIndex);
762 static const IEnumMediaTypesVtbl IEnumMediaTypesImpl_Vtbl =
764 IEnumMediaTypesImpl_QueryInterface,
765 IEnumMediaTypesImpl_AddRef,
766 IEnumMediaTypesImpl_Release,
767 IEnumMediaTypesImpl_Next,
768 IEnumMediaTypesImpl_Skip,
769 IEnumMediaTypesImpl_Reset,
770 IEnumMediaTypesImpl_Clone
773 /* Implementation of a very stripped down pin for the test filter. Just enough
774 functionality for connecting and Render() to work. */
776 static void Copy_PinInfo(PIN_INFO * pDest, const PIN_INFO * pSrc)
778 lstrcpyW(pDest->achName, pSrc->achName);
779 pDest->dir = pSrc->dir;
780 pDest->pFilter = pSrc->pFilter;
783 typedef struct ITestPinImpl
785 IPin IPin_iface;
786 LONG refCount;
787 LPCRITICAL_SECTION pCritSec;
788 PIN_INFO pinInfo;
789 IPin * pConnectedTo;
790 AM_MEDIA_TYPE mtCurrent;
791 LPVOID pUserData;
792 } ITestPinImpl;
794 static inline ITestPinImpl *impl_from_IPin(IPin *iface)
796 return CONTAINING_RECORD(iface, ITestPinImpl, IPin_iface);
799 static HRESULT WINAPI TestFilter_Pin_QueryInterface(IPin * iface, REFIID riid, LPVOID * ppv)
801 *ppv = NULL;
803 if (IsEqualIID(riid, &IID_IUnknown))
804 *ppv = iface;
805 else if (IsEqualIID(riid, &IID_IPin))
806 *ppv = iface;
808 if (*ppv)
810 IUnknown_AddRef((IUnknown *)(*ppv));
811 return S_OK;
814 return E_NOINTERFACE;
817 static ULONG WINAPI TestFilter_Pin_AddRef(IPin * iface)
819 ITestPinImpl *This = impl_from_IPin(iface);
820 ULONG refCount = InterlockedIncrement(&This->refCount);
821 return refCount;
824 static ULONG WINAPI TestFilter_Pin_Release(IPin * iface)
826 ITestPinImpl *This = impl_from_IPin(iface);
827 ULONG refCount = InterlockedDecrement(&This->refCount);
829 if (!refCount)
831 FreeMediaType(&This->mtCurrent);
832 CoTaskMemFree(This);
833 return 0;
835 else
836 return refCount;
839 static HRESULT WINAPI TestFilter_InputPin_Connect(IPin * iface, IPin * pConnector, const AM_MEDIA_TYPE * pmt)
841 return E_UNEXPECTED;
844 static HRESULT WINAPI TestFilter_InputPin_ReceiveConnection(IPin * iface, IPin * pReceivePin, const AM_MEDIA_TYPE * pmt)
846 ITestPinImpl *This = impl_from_IPin(iface);
847 PIN_DIRECTION pindirReceive;
848 HRESULT hr = S_OK;
850 EnterCriticalSection(This->pCritSec);
852 if (!(IsEqualIID(&pmt->majortype, &This->mtCurrent.majortype) && (IsEqualIID(&pmt->subtype, &This->mtCurrent.subtype) ||
853 IsEqualIID(&GUID_NULL, &This->mtCurrent.subtype))))
854 hr = VFW_E_TYPE_NOT_ACCEPTED;
856 if (This->pConnectedTo)
857 hr = VFW_E_ALREADY_CONNECTED;
859 if (SUCCEEDED(hr))
861 IPin_QueryDirection(pReceivePin, &pindirReceive);
863 if (pindirReceive != PINDIR_OUTPUT)
865 hr = VFW_E_INVALID_DIRECTION;
869 if (SUCCEEDED(hr))
871 CopyMediaType(&This->mtCurrent, pmt);
872 This->pConnectedTo = pReceivePin;
873 IPin_AddRef(pReceivePin);
876 LeaveCriticalSection(This->pCritSec);
878 return hr;
881 static HRESULT WINAPI TestFilter_Pin_Disconnect(IPin * iface)
883 HRESULT hr;
884 ITestPinImpl *This = impl_from_IPin(iface);
886 EnterCriticalSection(This->pCritSec);
888 if (This->pConnectedTo)
890 IPin_Release(This->pConnectedTo);
891 This->pConnectedTo = NULL;
892 hr = S_OK;
894 else
895 hr = S_FALSE;
897 LeaveCriticalSection(This->pCritSec);
899 return hr;
902 static HRESULT WINAPI TestFilter_Pin_ConnectedTo(IPin * iface, IPin ** ppPin)
904 HRESULT hr;
905 ITestPinImpl *This = impl_from_IPin(iface);
907 EnterCriticalSection(This->pCritSec);
909 if (This->pConnectedTo)
911 *ppPin = This->pConnectedTo;
912 IPin_AddRef(*ppPin);
913 hr = S_OK;
915 else
917 hr = VFW_E_NOT_CONNECTED;
918 *ppPin = NULL;
921 LeaveCriticalSection(This->pCritSec);
923 return hr;
926 static HRESULT WINAPI TestFilter_Pin_ConnectionMediaType(IPin * iface, AM_MEDIA_TYPE * pmt)
928 HRESULT hr;
929 ITestPinImpl *This = impl_from_IPin(iface);
931 EnterCriticalSection(This->pCritSec);
933 if (This->pConnectedTo)
935 CopyMediaType(pmt, &This->mtCurrent);
936 hr = S_OK;
938 else
940 ZeroMemory(pmt, sizeof(*pmt));
941 hr = VFW_E_NOT_CONNECTED;
944 LeaveCriticalSection(This->pCritSec);
946 return hr;
949 static HRESULT WINAPI TestFilter_Pin_QueryPinInfo(IPin * iface, PIN_INFO * pInfo)
951 ITestPinImpl *This = impl_from_IPin(iface);
953 Copy_PinInfo(pInfo, &This->pinInfo);
954 IBaseFilter_AddRef(pInfo->pFilter);
956 return S_OK;
959 static HRESULT WINAPI TestFilter_Pin_QueryDirection(IPin * iface, PIN_DIRECTION * pPinDir)
961 ITestPinImpl *This = impl_from_IPin(iface);
963 *pPinDir = This->pinInfo.dir;
965 return S_OK;
968 static HRESULT WINAPI TestFilter_Pin_QueryId(IPin * iface, LPWSTR * Id)
970 return E_NOTIMPL;
973 static HRESULT WINAPI TestFilter_Pin_QueryAccept(IPin * iface, const AM_MEDIA_TYPE * pmt)
975 ITestPinImpl *This = impl_from_IPin(iface);
977 if (IsEqualIID(&pmt->majortype, &This->mtCurrent.majortype) && (IsEqualIID(&pmt->subtype, &This->mtCurrent.subtype) ||
978 IsEqualIID(&GUID_NULL, &This->mtCurrent.subtype)))
979 return S_OK;
980 else
981 return VFW_E_TYPE_NOT_ACCEPTED;
984 static HRESULT WINAPI TestFilter_Pin_EnumMediaTypes(IPin * iface, IEnumMediaTypes ** ppEnum)
986 ITestPinImpl *This = impl_from_IPin(iface);
988 return IEnumMediaTypesImpl_Construct(&This->mtCurrent, 1, ppEnum);
991 static HRESULT WINAPI TestFilter_Pin_QueryInternalConnections(IPin * iface, IPin ** apPin, ULONG * cPin)
993 return E_NOTIMPL;
996 static HRESULT WINAPI TestFilter_Pin_BeginFlush(IPin * iface)
998 return E_NOTIMPL;
1001 static HRESULT WINAPI TestFilter_Pin_EndFlush(IPin * iface)
1003 return E_NOTIMPL;
1006 static HRESULT WINAPI TestFilter_Pin_NewSegment(IPin * iface, REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate)
1008 return E_NOTIMPL;
1011 static HRESULT WINAPI TestFilter_Pin_EndOfStream(IPin * iface)
1013 return E_NOTIMPL;
1016 static const IPinVtbl TestFilter_InputPin_Vtbl =
1018 TestFilter_Pin_QueryInterface,
1019 TestFilter_Pin_AddRef,
1020 TestFilter_Pin_Release,
1021 TestFilter_InputPin_Connect,
1022 TestFilter_InputPin_ReceiveConnection,
1023 TestFilter_Pin_Disconnect,
1024 TestFilter_Pin_ConnectedTo,
1025 TestFilter_Pin_ConnectionMediaType,
1026 TestFilter_Pin_QueryPinInfo,
1027 TestFilter_Pin_QueryDirection,
1028 TestFilter_Pin_QueryId,
1029 TestFilter_Pin_QueryAccept,
1030 TestFilter_Pin_EnumMediaTypes,
1031 TestFilter_Pin_QueryInternalConnections,
1032 TestFilter_Pin_EndOfStream,
1033 TestFilter_Pin_BeginFlush,
1034 TestFilter_Pin_EndFlush,
1035 TestFilter_Pin_NewSegment
1038 static HRESULT WINAPI TestFilter_OutputPin_ReceiveConnection(IPin * iface, IPin * pReceivePin, const AM_MEDIA_TYPE * pmt)
1040 return E_UNEXPECTED;
1043 /* Private helper function */
1044 static HRESULT TestFilter_OutputPin_ConnectSpecific(ITestPinImpl * This, IPin * pReceivePin,
1045 const AM_MEDIA_TYPE * pmt)
1047 HRESULT hr;
1049 This->pConnectedTo = pReceivePin;
1050 IPin_AddRef(pReceivePin);
1052 hr = IPin_ReceiveConnection(pReceivePin, &This->IPin_iface, pmt);
1054 if (FAILED(hr))
1056 IPin_Release(This->pConnectedTo);
1057 This->pConnectedTo = NULL;
1060 return hr;
1063 static HRESULT WINAPI TestFilter_OutputPin_Connect(IPin * iface, IPin * pReceivePin, const AM_MEDIA_TYPE * pmt)
1065 ITestPinImpl *This = impl_from_IPin(iface);
1066 HRESULT hr;
1068 EnterCriticalSection(This->pCritSec);
1070 /* if we have been a specific type to connect with, then we can either connect
1071 * with that or fail. We cannot choose different AM_MEDIA_TYPE */
1072 if (pmt && !IsEqualGUID(&pmt->majortype, &GUID_NULL) && !IsEqualGUID(&pmt->subtype, &GUID_NULL))
1073 hr = TestFilter_OutputPin_ConnectSpecific(This, pReceivePin, pmt);
1074 else
1076 if (( !pmt || CompareMediaTypes(pmt, &This->mtCurrent, TRUE) ) &&
1077 (TestFilter_OutputPin_ConnectSpecific(This, pReceivePin, &This->mtCurrent) == S_OK))
1078 hr = S_OK;
1079 else hr = VFW_E_NO_ACCEPTABLE_TYPES;
1080 } /* if negotiate media type */
1081 } /* if succeeded */
1082 LeaveCriticalSection(This->pCritSec);
1084 return hr;
1087 static const IPinVtbl TestFilter_OutputPin_Vtbl =
1089 TestFilter_Pin_QueryInterface,
1090 TestFilter_Pin_AddRef,
1091 TestFilter_Pin_Release,
1092 TestFilter_OutputPin_Connect,
1093 TestFilter_OutputPin_ReceiveConnection,
1094 TestFilter_Pin_Disconnect,
1095 TestFilter_Pin_ConnectedTo,
1096 TestFilter_Pin_ConnectionMediaType,
1097 TestFilter_Pin_QueryPinInfo,
1098 TestFilter_Pin_QueryDirection,
1099 TestFilter_Pin_QueryId,
1100 TestFilter_Pin_QueryAccept,
1101 TestFilter_Pin_EnumMediaTypes,
1102 TestFilter_Pin_QueryInternalConnections,
1103 TestFilter_Pin_EndOfStream,
1104 TestFilter_Pin_BeginFlush,
1105 TestFilter_Pin_EndFlush,
1106 TestFilter_Pin_NewSegment
1109 static HRESULT TestFilter_Pin_Construct(const IPinVtbl *Pin_Vtbl, const PIN_INFO * pPinInfo, AM_MEDIA_TYPE *pinmt,
1110 LPCRITICAL_SECTION pCritSec, IPin ** ppPin)
1112 ITestPinImpl * pPinImpl;
1114 *ppPin = NULL;
1116 pPinImpl = CoTaskMemAlloc(sizeof(ITestPinImpl));
1118 if (!pPinImpl)
1119 return E_OUTOFMEMORY;
1121 pPinImpl->refCount = 1;
1122 pPinImpl->pConnectedTo = NULL;
1123 pPinImpl->pCritSec = pCritSec;
1124 Copy_PinInfo(&pPinImpl->pinInfo, pPinInfo);
1125 pPinImpl->mtCurrent = *pinmt;
1127 pPinImpl->IPin_iface.lpVtbl = Pin_Vtbl;
1129 *ppPin = &pPinImpl->IPin_iface;
1130 return S_OK;
1133 /* IEnumPins implementation */
1135 typedef HRESULT (* FNOBTAINPIN)(TestFilterImpl *tf, ULONG pos, IPin **pin, DWORD *lastsynctick);
1137 typedef struct IEnumPinsImpl
1139 IEnumPins IEnumPins_iface;
1140 LONG refCount;
1141 ULONG uIndex;
1142 TestFilterImpl *base;
1143 FNOBTAINPIN receive_pin;
1144 DWORD synctime;
1145 } IEnumPinsImpl;
1147 static const struct IEnumPinsVtbl IEnumPinsImpl_Vtbl;
1149 static inline IEnumPinsImpl *impl_from_IEnumPins(IEnumPins *iface)
1151 return CONTAINING_RECORD(iface, IEnumPinsImpl, IEnumPins_iface);
1154 static HRESULT createenumpins(IEnumPins ** ppEnum, FNOBTAINPIN receive_pin, TestFilterImpl *base)
1156 IEnumPinsImpl * pEnumPins;
1158 if (!ppEnum)
1159 return E_POINTER;
1161 pEnumPins = CoTaskMemAlloc(sizeof(IEnumPinsImpl));
1162 if (!pEnumPins)
1164 *ppEnum = NULL;
1165 return E_OUTOFMEMORY;
1167 pEnumPins->IEnumPins_iface.lpVtbl = &IEnumPinsImpl_Vtbl;
1168 pEnumPins->refCount = 1;
1169 pEnumPins->uIndex = 0;
1170 pEnumPins->receive_pin = receive_pin;
1171 pEnumPins->base = base;
1172 IBaseFilter_AddRef(&base->IBaseFilter_iface);
1173 *ppEnum = &pEnumPins->IEnumPins_iface;
1175 receive_pin(base, ~0, NULL, &pEnumPins->synctime);
1177 return S_OK;
1180 static HRESULT WINAPI IEnumPinsImpl_QueryInterface(IEnumPins * iface, REFIID riid, LPVOID * ppv)
1182 *ppv = NULL;
1184 if (IsEqualIID(riid, &IID_IUnknown))
1185 *ppv = iface;
1186 else if (IsEqualIID(riid, &IID_IEnumPins))
1187 *ppv = iface;
1189 if (*ppv)
1191 IUnknown_AddRef((IUnknown *)(*ppv));
1192 return S_OK;
1195 return E_NOINTERFACE;
1198 static ULONG WINAPI IEnumPinsImpl_AddRef(IEnumPins * iface)
1200 IEnumPinsImpl *This = impl_from_IEnumPins(iface);
1201 ULONG refCount = InterlockedIncrement(&This->refCount);
1203 return refCount;
1206 static ULONG WINAPI IEnumPinsImpl_Release(IEnumPins * iface)
1208 IEnumPinsImpl *This = impl_from_IEnumPins(iface);
1209 ULONG refCount = InterlockedDecrement(&This->refCount);
1211 if (!refCount)
1213 IBaseFilter_Release(&This->base->IBaseFilter_iface);
1214 CoTaskMemFree(This);
1215 return 0;
1217 else
1218 return refCount;
1221 static HRESULT WINAPI IEnumPinsImpl_Next(IEnumPins * iface, ULONG cPins, IPin ** ppPins, ULONG * pcFetched)
1223 IEnumPinsImpl *This = impl_from_IEnumPins(iface);
1224 DWORD synctime = This->synctime;
1225 HRESULT hr = S_OK;
1226 ULONG i = 0;
1228 if (!ppPins)
1229 return E_POINTER;
1231 if (cPins > 1 && !pcFetched)
1232 return E_INVALIDARG;
1234 if (pcFetched)
1235 *pcFetched = 0;
1237 while (i < cPins && hr == S_OK)
1239 hr = This->receive_pin(This->base, This->uIndex + i, &ppPins[i], &synctime);
1241 if (hr == S_OK)
1242 ++i;
1244 if (synctime != This->synctime)
1245 break;
1248 if (!i && synctime != This->synctime)
1249 return VFW_E_ENUM_OUT_OF_SYNC;
1251 if (pcFetched)
1252 *pcFetched = i;
1253 This->uIndex += i;
1255 if (i < cPins)
1256 return S_FALSE;
1257 return S_OK;
1260 static HRESULT WINAPI IEnumPinsImpl_Skip(IEnumPins * iface, ULONG cPins)
1262 IEnumPinsImpl *This = impl_from_IEnumPins(iface);
1263 DWORD synctime = This->synctime;
1264 HRESULT hr;
1265 IPin *pin = NULL;
1267 hr = This->receive_pin(This->base, This->uIndex + cPins, &pin, &synctime);
1268 if (pin)
1269 IPin_Release(pin);
1271 if (synctime != This->synctime)
1272 return VFW_E_ENUM_OUT_OF_SYNC;
1274 if (hr == S_OK)
1275 This->uIndex += cPins;
1277 return hr;
1280 static HRESULT WINAPI IEnumPinsImpl_Reset(IEnumPins * iface)
1282 IEnumPinsImpl *This = impl_from_IEnumPins(iface);
1284 This->receive_pin(This->base, ~0, NULL, &This->synctime);
1286 This->uIndex = 0;
1287 return S_OK;
1290 static HRESULT WINAPI IEnumPinsImpl_Clone(IEnumPins * iface, IEnumPins ** ppEnum)
1292 HRESULT hr;
1293 IEnumPinsImpl *This = impl_from_IEnumPins(iface);
1295 hr = createenumpins(ppEnum, This->receive_pin, This->base);
1296 if (FAILED(hr))
1297 return hr;
1298 return IEnumPins_Skip(*ppEnum, This->uIndex);
1301 static const IEnumPinsVtbl IEnumPinsImpl_Vtbl =
1303 IEnumPinsImpl_QueryInterface,
1304 IEnumPinsImpl_AddRef,
1305 IEnumPinsImpl_Release,
1306 IEnumPinsImpl_Next,
1307 IEnumPinsImpl_Skip,
1308 IEnumPinsImpl_Reset,
1309 IEnumPinsImpl_Clone
1312 /* Test filter implementation - a filter that has few predefined pins with single media type
1313 * that accept only this single media type. Enough for Render(). */
1315 typedef struct TestFilterPinData
1317 PIN_DIRECTION pinDir;
1318 const GUID *mediasubtype;
1319 } TestFilterPinData;
1321 static const IBaseFilterVtbl TestFilter_Vtbl;
1323 static inline TestFilterImpl *impl_from_IBaseFilter(IBaseFilter *iface)
1325 return CONTAINING_RECORD(iface, TestFilterImpl, IBaseFilter_iface);
1328 static HRESULT createtestfilter(const CLSID* pClsid, const TestFilterPinData *pinData,
1329 TestFilterImpl **tf)
1331 static const WCHAR wcsInputPinName[] = {'i','n','p','u','t',' ','p','i','n',0};
1332 static const WCHAR wcsOutputPinName[] = {'o','u','t','p','u','t',' ','p','i','n',0};
1333 HRESULT hr;
1334 PIN_INFO pinInfo;
1335 TestFilterImpl* pTestFilter = NULL;
1336 UINT nPins, i;
1337 AM_MEDIA_TYPE mt;
1339 pTestFilter = CoTaskMemAlloc(sizeof(TestFilterImpl));
1340 if (!pTestFilter) return E_OUTOFMEMORY;
1342 pTestFilter->clsid = *pClsid;
1343 pTestFilter->IBaseFilter_iface.lpVtbl = &TestFilter_Vtbl;
1344 pTestFilter->refCount = 1;
1345 InitializeCriticalSection(&pTestFilter->csFilter);
1346 pTestFilter->state = State_Stopped;
1348 ZeroMemory(&pTestFilter->filterInfo, sizeof(FILTER_INFO));
1350 nPins = 0;
1351 while(pinData[nPins].mediasubtype) ++nPins;
1353 pTestFilter->ppPins = CoTaskMemAlloc(nPins * sizeof(IPin *));
1354 if (!pTestFilter->ppPins)
1356 hr = E_OUTOFMEMORY;
1357 goto error;
1359 ZeroMemory(pTestFilter->ppPins, nPins * sizeof(IPin *));
1361 for (i = 0; i < nPins; i++)
1363 ZeroMemory(&mt, sizeof(mt));
1364 mt.majortype = MEDIATYPE_Video;
1365 mt.formattype = FORMAT_None;
1366 mt.subtype = *pinData[i].mediasubtype;
1368 pinInfo.dir = pinData[i].pinDir;
1369 pinInfo.pFilter = &pTestFilter->IBaseFilter_iface;
1370 if (pinInfo.dir == PINDIR_INPUT)
1372 lstrcpynW(pinInfo.achName, wcsInputPinName, sizeof(pinInfo.achName) / sizeof(pinInfo.achName[0]));
1373 hr = TestFilter_Pin_Construct(&TestFilter_InputPin_Vtbl, &pinInfo, &mt, &pTestFilter->csFilter,
1374 &pTestFilter->ppPins[i]);
1377 else
1379 lstrcpynW(pinInfo.achName, wcsOutputPinName, sizeof(pinInfo.achName) / sizeof(pinInfo.achName[0]));
1380 hr = TestFilter_Pin_Construct(&TestFilter_OutputPin_Vtbl, &pinInfo, &mt, &pTestFilter->csFilter,
1381 &pTestFilter->ppPins[i]);
1383 if (FAILED(hr) || !pTestFilter->ppPins[i]) goto error;
1386 pTestFilter->nPins = nPins;
1387 *tf = pTestFilter;
1388 return S_OK;
1390 error:
1392 if (pTestFilter->ppPins)
1394 for (i = 0; i < nPins; i++)
1396 if (pTestFilter->ppPins[i]) IPin_Release(pTestFilter->ppPins[i]);
1399 CoTaskMemFree(pTestFilter->ppPins);
1400 DeleteCriticalSection(&pTestFilter->csFilter);
1401 CoTaskMemFree(pTestFilter);
1403 return hr;
1406 static HRESULT WINAPI TestFilter_QueryInterface(IBaseFilter * iface, REFIID riid, LPVOID * ppv)
1408 TestFilterImpl *This = impl_from_IBaseFilter(iface);
1410 *ppv = NULL;
1412 if (IsEqualIID(riid, &IID_IUnknown))
1413 *ppv = This;
1414 else if (IsEqualIID(riid, &IID_IPersist))
1415 *ppv = This;
1416 else if (IsEqualIID(riid, &IID_IMediaFilter))
1417 *ppv = This;
1418 else if (IsEqualIID(riid, &IID_IBaseFilter))
1419 *ppv = This;
1421 if (*ppv)
1423 IUnknown_AddRef((IUnknown *)(*ppv));
1424 return S_OK;
1427 return E_NOINTERFACE;
1430 static ULONG WINAPI TestFilter_AddRef(IBaseFilter * iface)
1432 TestFilterImpl *This = impl_from_IBaseFilter(iface);
1433 ULONG refCount = InterlockedIncrement(&This->refCount);
1435 return refCount;
1438 static ULONG WINAPI TestFilter_Release(IBaseFilter * iface)
1440 TestFilterImpl *This = impl_from_IBaseFilter(iface);
1441 ULONG refCount = InterlockedDecrement(&This->refCount);
1443 if (!refCount)
1445 ULONG i;
1447 for (i = 0; i < This->nPins; i++)
1449 IPin *pConnectedTo;
1451 if (SUCCEEDED(IPin_ConnectedTo(This->ppPins[i], &pConnectedTo)))
1453 IPin_Disconnect(pConnectedTo);
1454 IPin_Release(pConnectedTo);
1456 IPin_Disconnect(This->ppPins[i]);
1458 IPin_Release(This->ppPins[i]);
1461 CoTaskMemFree(This->ppPins);
1463 DeleteCriticalSection(&This->csFilter);
1465 CoTaskMemFree(This);
1467 return 0;
1469 else
1470 return refCount;
1472 /** IPersist methods **/
1474 static HRESULT WINAPI TestFilter_GetClassID(IBaseFilter * iface, CLSID * pClsid)
1476 TestFilterImpl *This = impl_from_IBaseFilter(iface);
1478 *pClsid = This->clsid;
1480 return S_OK;
1483 /** IMediaFilter methods **/
1485 static HRESULT WINAPI TestFilter_Stop(IBaseFilter * iface)
1487 return E_NOTIMPL;
1490 static HRESULT WINAPI TestFilter_Pause(IBaseFilter * iface)
1492 return E_NOTIMPL;
1495 static HRESULT WINAPI TestFilter_Run(IBaseFilter * iface, REFERENCE_TIME tStart)
1497 return E_NOTIMPL;
1500 static HRESULT WINAPI TestFilter_GetState(IBaseFilter * iface, DWORD dwMilliSecsTimeout, FILTER_STATE *pState)
1502 TestFilterImpl *This = impl_from_IBaseFilter(iface);
1504 EnterCriticalSection(&This->csFilter);
1506 *pState = This->state;
1508 LeaveCriticalSection(&This->csFilter);
1510 return S_OK;
1513 static HRESULT WINAPI TestFilter_SetSyncSource(IBaseFilter * iface, IReferenceClock *pClock)
1515 return E_NOTIMPL;
1518 static HRESULT WINAPI TestFilter_GetSyncSource(IBaseFilter * iface, IReferenceClock **ppClock)
1520 return E_NOTIMPL;
1523 /** IBaseFilter implementation **/
1525 static HRESULT getpin_callback(TestFilterImpl *tf, ULONG pos, IPin **pin, DWORD *lastsynctick)
1527 /* Our pins are static, not changing so setting static tick count is ok */
1528 *lastsynctick = 0;
1530 if (pos >= tf->nPins)
1531 return S_FALSE;
1533 *pin = tf->ppPins[pos];
1534 IPin_AddRef(*pin);
1535 return S_OK;
1538 static HRESULT WINAPI TestFilter_EnumPins(IBaseFilter * iface, IEnumPins **ppEnum)
1540 TestFilterImpl *This = impl_from_IBaseFilter(iface);
1542 return createenumpins(ppEnum, getpin_callback, This);
1545 static HRESULT WINAPI TestFilter_FindPin(IBaseFilter * iface, LPCWSTR Id, IPin **ppPin)
1547 return E_NOTIMPL;
1550 static HRESULT WINAPI TestFilter_QueryFilterInfo(IBaseFilter * iface, FILTER_INFO *pInfo)
1552 TestFilterImpl *This = impl_from_IBaseFilter(iface);
1554 lstrcpyW(pInfo->achName, This->filterInfo.achName);
1555 pInfo->pGraph = This->filterInfo.pGraph;
1557 if (pInfo->pGraph)
1558 IFilterGraph_AddRef(pInfo->pGraph);
1560 return S_OK;
1563 static HRESULT WINAPI TestFilter_JoinFilterGraph(IBaseFilter * iface, IFilterGraph *pGraph, LPCWSTR pName)
1565 HRESULT hr = S_OK;
1566 TestFilterImpl *This = impl_from_IBaseFilter(iface);
1568 EnterCriticalSection(&This->csFilter);
1570 if (pName)
1571 lstrcpyW(This->filterInfo.achName, pName);
1572 else
1573 *This->filterInfo.achName = '\0';
1574 This->filterInfo.pGraph = pGraph; /* NOTE: do NOT increase ref. count */
1576 LeaveCriticalSection(&This->csFilter);
1578 return hr;
1581 static HRESULT WINAPI TestFilter_QueryVendorInfo(IBaseFilter * iface, LPWSTR *pVendorInfo)
1583 return E_NOTIMPL;
1586 static const IBaseFilterVtbl TestFilter_Vtbl =
1588 TestFilter_QueryInterface,
1589 TestFilter_AddRef,
1590 TestFilter_Release,
1591 TestFilter_GetClassID,
1592 TestFilter_Stop,
1593 TestFilter_Pause,
1594 TestFilter_Run,
1595 TestFilter_GetState,
1596 TestFilter_SetSyncSource,
1597 TestFilter_GetSyncSource,
1598 TestFilter_EnumPins,
1599 TestFilter_FindPin,
1600 TestFilter_QueryFilterInfo,
1601 TestFilter_JoinFilterGraph,
1602 TestFilter_QueryVendorInfo
1605 /* IClassFactory implementation */
1607 typedef struct TestClassFactoryImpl
1609 IClassFactory IClassFactory_iface;
1610 const TestFilterPinData *filterPinData;
1611 const CLSID *clsid;
1612 } TestClassFactoryImpl;
1614 static inline TestClassFactoryImpl *impl_from_IClassFactory(IClassFactory *iface)
1616 return CONTAINING_RECORD(iface, TestClassFactoryImpl, IClassFactory_iface);
1619 static HRESULT WINAPI Test_IClassFactory_QueryInterface(
1620 LPCLASSFACTORY iface,
1621 REFIID riid,
1622 LPVOID *ppvObj)
1624 if (ppvObj == NULL) return E_POINTER;
1626 if (IsEqualGUID(riid, &IID_IUnknown) ||
1627 IsEqualGUID(riid, &IID_IClassFactory))
1629 *ppvObj = iface;
1630 IClassFactory_AddRef(iface);
1631 return S_OK;
1634 *ppvObj = NULL;
1635 return E_NOINTERFACE;
1638 static ULONG WINAPI Test_IClassFactory_AddRef(LPCLASSFACTORY iface)
1640 return 2; /* non-heap-based object */
1643 static ULONG WINAPI Test_IClassFactory_Release(LPCLASSFACTORY iface)
1645 return 1; /* non-heap-based object */
1648 static HRESULT WINAPI Test_IClassFactory_CreateInstance(
1649 LPCLASSFACTORY iface,
1650 LPUNKNOWN pUnkOuter,
1651 REFIID riid,
1652 LPVOID *ppvObj)
1654 TestClassFactoryImpl *This = impl_from_IClassFactory(iface);
1655 HRESULT hr;
1656 TestFilterImpl *testfilter;
1658 *ppvObj = NULL;
1660 if (pUnkOuter) return CLASS_E_NOAGGREGATION;
1662 hr = createtestfilter(This->clsid, This->filterPinData, &testfilter);
1663 if (SUCCEEDED(hr)) {
1664 hr = IBaseFilter_QueryInterface(&testfilter->IBaseFilter_iface, riid, ppvObj);
1665 IBaseFilter_Release(&testfilter->IBaseFilter_iface);
1667 return hr;
1670 static HRESULT WINAPI Test_IClassFactory_LockServer(
1671 LPCLASSFACTORY iface,
1672 BOOL fLock)
1674 return S_OK;
1677 static IClassFactoryVtbl TestClassFactory_Vtbl =
1679 Test_IClassFactory_QueryInterface,
1680 Test_IClassFactory_AddRef,
1681 Test_IClassFactory_Release,
1682 Test_IClassFactory_CreateInstance,
1683 Test_IClassFactory_LockServer
1686 static HRESULT get_connected_filter_name(TestFilterImpl *pFilter, char *FilterName)
1688 IPin *pin = NULL;
1689 PIN_INFO pinInfo;
1690 FILTER_INFO filterInfo;
1691 HRESULT hr;
1693 FilterName[0] = 0;
1695 hr = IPin_ConnectedTo(pFilter->ppPins[0], &pin);
1696 ok(hr == S_OK, "IPin_ConnectedTo failed with %x\n", hr);
1697 if (FAILED(hr)) return hr;
1699 hr = IPin_QueryPinInfo(pin, &pinInfo);
1700 ok(hr == S_OK, "IPin_QueryPinInfo failed with %x\n", hr);
1701 IPin_Release(pin);
1702 if (FAILED(hr)) return hr;
1704 SetLastError(0xdeadbeef);
1705 hr = IBaseFilter_QueryFilterInfo(pinInfo.pFilter, &filterInfo);
1706 if (hr == S_OK && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
1708 IBaseFilter_Release(pinInfo.pFilter);
1709 return E_NOTIMPL;
1711 ok(hr == S_OK, "IBaseFilter_QueryFilterInfo failed with %x\n", hr);
1712 IBaseFilter_Release(pinInfo.pFilter);
1713 if (FAILED(hr)) return hr;
1715 IFilterGraph_Release(filterInfo.pGraph);
1717 WideCharToMultiByte(CP_ACP, 0, filterInfo.achName, -1, FilterName, MAX_FILTER_NAME, NULL, NULL);
1719 return S_OK;
1722 static void test_render_filter_priority(void)
1724 /* Tests filter choice priorities in Render(). */
1725 DWORD cookie1 = 0, cookie2 = 0, cookie3 = 0;
1726 HRESULT hr;
1727 IFilterGraph2* pgraph2 = NULL;
1728 IFilterMapper2 *pMapper2 = NULL;
1729 TestFilterImpl *ptestfilter = NULL;
1730 TestFilterImpl *ptestfilter2 = NULL;
1731 static const CLSID CLSID_TestFilter2 = {
1732 0x37a4edb0,
1733 0x4d13,
1734 0x11dd,
1735 {0xe8, 0x9b, 0x00, 0x19, 0x66, 0x2f, 0xf0, 0xce}
1737 static const CLSID CLSID_TestFilter3 = {
1738 0x37a4f2d8,
1739 0x4d13,
1740 0x11dd,
1741 {0xe8, 0x9b, 0x00, 0x19, 0x66, 0x2f, 0xf0, 0xce}
1743 static const CLSID CLSID_TestFilter4 = {
1744 0x37a4f3b4,
1745 0x4d13,
1746 0x11dd,
1747 {0xe8, 0x9b, 0x00, 0x19, 0x66, 0x2f, 0xf0, 0xce}
1749 static const GUID mediasubtype1 = {
1750 0x37a4f51c,
1751 0x4d13,
1752 0x11dd,
1753 {0xe8, 0x9b, 0x00, 0x19, 0x66, 0x2f, 0xf0, 0xce}
1755 static const GUID mediasubtype2 = {
1756 0x37a4f5c6,
1757 0x4d13,
1758 0x11dd,
1759 {0xe8, 0x9b, 0x00, 0x19, 0x66, 0x2f, 0xf0, 0xce}
1761 static const TestFilterPinData PinData1[] = {
1762 { PINDIR_OUTPUT, &mediasubtype1 },
1763 { 0, 0 }
1765 static const TestFilterPinData PinData2[] = {
1766 { PINDIR_INPUT, &mediasubtype1 },
1767 { 0, 0 }
1769 static const TestFilterPinData PinData3[] = {
1770 { PINDIR_INPUT, &GUID_NULL },
1771 { 0, 0 }
1773 static const TestFilterPinData PinData4[] = {
1774 { PINDIR_INPUT, &mediasubtype1 },
1775 { PINDIR_OUTPUT, &mediasubtype2 },
1776 { 0, 0 }
1778 static const TestFilterPinData PinData5[] = {
1779 { PINDIR_INPUT, &mediasubtype2 },
1780 { 0, 0 }
1782 TestClassFactoryImpl Filter1ClassFactory = {
1783 { &TestClassFactory_Vtbl },
1784 PinData2, &CLSID_TestFilter2
1786 TestClassFactoryImpl Filter2ClassFactory = {
1787 { &TestClassFactory_Vtbl },
1788 PinData4, &CLSID_TestFilter3
1790 TestClassFactoryImpl Filter3ClassFactory = {
1791 { &TestClassFactory_Vtbl },
1792 PinData5, &CLSID_TestFilter4
1794 char ConnectedFilterName1[MAX_FILTER_NAME];
1795 char ConnectedFilterName2[MAX_FILTER_NAME];
1796 REGFILTER2 rgf2;
1797 REGFILTERPINS2 rgPins2[2];
1798 REGPINTYPES rgPinType[2];
1799 static const WCHAR wszFilterInstanceName1[] = {'T', 'e', 's', 't', 'f', 'i', 'l', 't', 'e', 'r', 'I',
1800 'n', 's', 't', 'a', 'n', 'c', 'e', '1', 0 };
1801 static const WCHAR wszFilterInstanceName2[] = {'T', 'e', 's', 't', 'f', 'i', 'l', 't', 'e', 'r', 'I',
1802 'n', 's', 't', 'a', 'n', 'c', 'e', '2', 0 };
1803 static const WCHAR wszFilterInstanceName3[] = {'T', 'e', 's', 't', 'f', 'i', 'l', 't', 'e', 'r', 'I',
1804 'n', 's', 't', 'a', 'n', 'c', 'e', '3', 0 };
1805 static const WCHAR wszFilterInstanceName4[] = {'T', 'e', 's', 't', 'f', 'i', 'l', 't', 'e', 'r', 'I',
1806 'n', 's', 't', 'a', 'n', 'c', 'e', '4', 0 };
1808 /* Test which renderer of two already added to the graph will be chosen
1809 * (one is "exact" match, other is "wildcard" match. Seems to depend
1810 * on the order in which filters are added to the graph, thus indicating
1811 * no preference given to exact match. */
1812 hr = CoCreateInstance(&CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, &IID_IFilterGraph2, (LPVOID*)&pgraph2);
1813 ok(hr == S_OK, "CoCreateInstance failed with %08x\n", hr);
1814 if (!pgraph2) return;
1816 hr = createtestfilter(&GUID_NULL, PinData1, &ptestfilter);
1817 ok(hr == S_OK, "createtestfilter failed with %08x\n", hr);
1818 if (FAILED(hr)) goto out;
1820 hr = IFilterGraph2_AddFilter(pgraph2, &ptestfilter->IBaseFilter_iface, wszFilterInstanceName1);
1821 ok(hr == S_OK, "IFilterGraph2_AddFilter failed with %08x\n", hr);
1823 hr = createtestfilter(&GUID_NULL, PinData2, &ptestfilter2);
1824 ok(hr == S_OK, "createtestfilter failed with %08x\n", hr);
1825 if (FAILED(hr)) goto out;
1827 hr = IFilterGraph2_AddFilter(pgraph2, &ptestfilter2->IBaseFilter_iface, wszFilterInstanceName2);
1828 ok(hr == S_OK, "IFilterGraph2_AddFilter failed with %08x\n", hr);
1830 IBaseFilter_Release(&ptestfilter2->IBaseFilter_iface);
1831 ptestfilter2 = NULL;
1833 hr = createtestfilter(&GUID_NULL, PinData3, &ptestfilter2);
1834 ok(hr == S_OK, "createtestfilter failed with %08x\n", hr);
1835 if (FAILED(hr)) goto out;
1837 hr = IFilterGraph2_AddFilter(pgraph2, &ptestfilter2->IBaseFilter_iface, wszFilterInstanceName3);
1838 ok(hr == S_OK, "IFilterGraph2_AddFilter failed with %08x\n", hr);
1840 hr = IFilterGraph2_Render(pgraph2, ptestfilter->ppPins[0]);
1841 ok(hr == S_OK, "IFilterGraph2_Render failed with %08x\n", hr);
1843 hr = get_connected_filter_name(ptestfilter, ConnectedFilterName1);
1845 IFilterGraph2_Release(pgraph2);
1846 pgraph2 = NULL;
1847 IBaseFilter_Release(&ptestfilter->IBaseFilter_iface);
1848 ptestfilter = NULL;
1849 IBaseFilter_Release(&ptestfilter2->IBaseFilter_iface);
1850 ptestfilter2 = NULL;
1852 if (hr == E_NOTIMPL)
1854 win_skip("Needed functions are not implemented\n");
1855 return;
1858 hr = CoCreateInstance(&CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, &IID_IFilterGraph2, (LPVOID*)&pgraph2);
1859 ok(hr == S_OK, "CoCreateInstance failed with %08x\n", hr);
1860 if (!pgraph2) goto out;
1862 hr = createtestfilter(&GUID_NULL, PinData1, &ptestfilter);
1863 ok(hr == S_OK, "createtestfilter failed with %08x\n", hr);
1864 if (FAILED(hr)) goto out;
1866 hr = IFilterGraph2_AddFilter(pgraph2, &ptestfilter->IBaseFilter_iface, wszFilterInstanceName1);
1867 ok(hr == S_OK, "IFilterGraph2_AddFilter failed with %08x\n", hr);
1869 hr = createtestfilter(&GUID_NULL, PinData3, &ptestfilter2);
1870 ok(hr == S_OK, "createtestfilter failed with %08x\n", hr);
1871 if (FAILED(hr)) goto out;
1873 hr = IFilterGraph2_AddFilter(pgraph2, &ptestfilter2->IBaseFilter_iface, wszFilterInstanceName3);
1874 ok(hr == S_OK, "IFilterGraph2_AddFilter failed with %08x\n", hr);
1876 IBaseFilter_Release(&ptestfilter2->IBaseFilter_iface);
1877 ptestfilter2 = NULL;
1879 hr = createtestfilter(&GUID_NULL, PinData2, &ptestfilter2);
1880 ok(hr == S_OK, "createtestfilter failed with %08x\n", hr);
1881 if (FAILED(hr)) goto out;
1883 hr = IFilterGraph2_AddFilter(pgraph2, &ptestfilter2->IBaseFilter_iface, wszFilterInstanceName2);
1884 ok(hr == S_OK, "IFilterGraph2_AddFilter failed with %08x\n", hr);
1886 hr = IFilterGraph2_Render(pgraph2, ptestfilter->ppPins[0]);
1887 ok(hr == S_OK, "IFilterGraph2_Render failed with %08x\n", hr);
1889 hr = IFilterGraph2_Disconnect(pgraph2, NULL);
1890 ok(hr == E_POINTER, "IFilterGraph2_Disconnect failed. Expected E_POINTER, received %08x\n", hr);
1892 get_connected_filter_name(ptestfilter, ConnectedFilterName2);
1893 ok(strcmp(ConnectedFilterName1, ConnectedFilterName2),
1894 "expected connected filters to be different but got %s both times\n", ConnectedFilterName1);
1896 IFilterGraph2_Release(pgraph2);
1897 pgraph2 = NULL;
1898 IBaseFilter_Release(&ptestfilter->IBaseFilter_iface);
1899 ptestfilter = NULL;
1900 IBaseFilter_Release(&ptestfilter2->IBaseFilter_iface);
1901 ptestfilter2 = NULL;
1903 /* Test if any preference is given to existing renderer which renders the pin directly vs
1904 an existing renderer which renders the pin indirectly, through an additional middle filter,
1905 again trying different orders of creation. Native appears not to give a preference. */
1907 hr = CoCreateInstance(&CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, &IID_IFilterGraph2, (LPVOID*)&pgraph2);
1908 ok(hr == S_OK, "CoCreateInstance failed with %08x\n", hr);
1909 if (!pgraph2) goto out;
1911 hr = createtestfilter(&GUID_NULL, PinData1, &ptestfilter);
1912 ok(hr == S_OK, "createtestfilter failed with %08x\n", hr);
1913 if (FAILED(hr)) goto out;
1915 hr = IFilterGraph2_AddFilter(pgraph2, &ptestfilter->IBaseFilter_iface, wszFilterInstanceName1);
1916 ok(hr == S_OK, "IFilterGraph2_AddFilter failed with %08x\n", hr);
1918 hr = createtestfilter(&GUID_NULL, PinData2, &ptestfilter2);
1919 ok(hr == S_OK, "createtestfilter failed with %08x\n", hr);
1920 if (FAILED(hr)) goto out;
1922 hr = IFilterGraph2_AddFilter(pgraph2, &ptestfilter2->IBaseFilter_iface, wszFilterInstanceName2);
1923 ok(hr == S_OK, "IFilterGraph2_AddFilter failed with %08x\n", hr);
1925 IBaseFilter_Release(&ptestfilter2->IBaseFilter_iface);
1926 ptestfilter2 = NULL;
1928 hr = createtestfilter(&GUID_NULL, PinData4, &ptestfilter2);
1929 ok(hr == S_OK, "createtestfilter failed with %08x\n", hr);
1930 if (FAILED(hr)) goto out;
1932 hr = IFilterGraph2_AddFilter(pgraph2, &ptestfilter2->IBaseFilter_iface, wszFilterInstanceName3);
1933 ok(hr == S_OK, "IFilterGraph2_AddFilter failed with %08x\n", hr);
1935 IBaseFilter_Release(&ptestfilter2->IBaseFilter_iface);
1936 ptestfilter2 = NULL;
1938 hr = createtestfilter(&GUID_NULL, PinData5, &ptestfilter2);
1939 ok(hr == S_OK, "createtestfilter failed with %08x\n", hr);
1940 if (FAILED(hr)) goto out;
1942 hr = IFilterGraph2_AddFilter(pgraph2, &ptestfilter2->IBaseFilter_iface, wszFilterInstanceName4);
1943 ok(hr == S_OK, "IFilterGraph2_AddFilter failed with %08x\n", hr);
1945 hr = IFilterGraph2_Render(pgraph2, ptestfilter->ppPins[0]);
1946 ok(hr == S_OK, "IFilterGraph2_Render failed with %08x\n", hr);
1948 get_connected_filter_name(ptestfilter, ConnectedFilterName1);
1949 ok(!strcmp(ConnectedFilterName1, "TestfilterInstance3") || !strcmp(ConnectedFilterName1, "TestfilterInstance2"),
1950 "unexpected connected filter: %s\n", ConnectedFilterName1);
1952 IFilterGraph2_Release(pgraph2);
1953 pgraph2 = NULL;
1954 IBaseFilter_Release(&ptestfilter->IBaseFilter_iface);
1955 ptestfilter = NULL;
1956 IBaseFilter_Release(&ptestfilter2->IBaseFilter_iface);
1957 ptestfilter2 = NULL;
1959 hr = CoCreateInstance(&CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, &IID_IFilterGraph2, (LPVOID*)&pgraph2);
1960 ok(hr == S_OK, "CoCreateInstance failed with %08x\n", hr);
1961 if (!pgraph2) goto out;
1963 hr = createtestfilter(&GUID_NULL, PinData1, &ptestfilter);
1964 ok(hr == S_OK, "createtestfilter failed with %08x\n", hr);
1965 if (FAILED(hr)) goto out;
1967 hr = IFilterGraph2_AddFilter(pgraph2, &ptestfilter->IBaseFilter_iface, wszFilterInstanceName1);
1968 ok(hr == S_OK, "IFilterGraph2_AddFilter failed with %08x\n", hr);
1970 hr = createtestfilter(&GUID_NULL, PinData4, &ptestfilter2);
1971 ok(hr == S_OK, "createtestfilter failed with %08x\n", hr);
1972 if (FAILED(hr)) goto out;
1974 hr = IFilterGraph2_AddFilter(pgraph2, &ptestfilter2->IBaseFilter_iface, wszFilterInstanceName3);
1975 ok(hr == S_OK, "IFilterGraph2_AddFilter failed with %08x\n", hr);
1977 IBaseFilter_Release(&ptestfilter2->IBaseFilter_iface);
1978 ptestfilter2 = NULL;
1980 hr = createtestfilter(&GUID_NULL, PinData5, &ptestfilter2);
1981 ok(hr == S_OK, "createtestfilter failed with %08x\n", hr);
1982 if (FAILED(hr)) goto out;
1984 hr = IFilterGraph2_AddFilter(pgraph2, &ptestfilter2->IBaseFilter_iface, wszFilterInstanceName4);
1985 ok(hr == S_OK, "IFilterGraph2_AddFilter failed with %08x\n", hr);
1987 IBaseFilter_Release(&ptestfilter2->IBaseFilter_iface);
1988 ptestfilter2 = NULL;
1990 hr = createtestfilter(&GUID_NULL, PinData2, &ptestfilter2);
1991 ok(hr == S_OK, "createtestfilter failed with %08x\n", hr);
1992 if (FAILED(hr)) goto out;
1994 hr = IFilterGraph2_AddFilter(pgraph2, &ptestfilter2->IBaseFilter_iface, wszFilterInstanceName2);
1995 ok(hr == S_OK, "IFilterGraph2_AddFilter failed with %08x\n", hr);
1997 hr = IFilterGraph2_Render(pgraph2, ptestfilter->ppPins[0]);
1998 ok(hr == S_OK, "IFilterGraph2_Render failed with %08x\n", hr);
2000 get_connected_filter_name(ptestfilter, ConnectedFilterName2);
2001 ok(!strcmp(ConnectedFilterName2, "TestfilterInstance3") || !strcmp(ConnectedFilterName2, "TestfilterInstance2"),
2002 "unexpected connected filter: %s\n", ConnectedFilterName2);
2003 ok(strcmp(ConnectedFilterName1, ConnectedFilterName2),
2004 "expected connected filters to be different but got %s both times\n", ConnectedFilterName1);
2006 IFilterGraph2_Release(pgraph2);
2007 pgraph2 = NULL;
2008 IBaseFilter_Release(&ptestfilter->IBaseFilter_iface);
2009 ptestfilter = NULL;
2010 IBaseFilter_Release(&ptestfilter2->IBaseFilter_iface);
2011 ptestfilter2 = NULL;
2013 /* Test if renderers are tried before non-renderers (intermediary filters). */
2014 hr = CoCreateInstance(&CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, &IID_IFilterGraph2, (LPVOID*)&pgraph2);
2015 ok(hr == S_OK, "CoCreateInstance failed with %08x\n", hr);
2016 if (!pgraph2) goto out;
2018 hr = CoCreateInstance(&CLSID_FilterMapper2, NULL, CLSCTX_INPROC_SERVER, &IID_IFilterMapper2, (LPVOID*)&pMapper2);
2019 ok(hr == S_OK, "CoCreateInstance failed with %08x\n", hr);
2020 if (!pMapper2) goto out;
2022 hr = createtestfilter(&GUID_NULL, PinData1, &ptestfilter);
2023 ok(hr == S_OK, "createtestfilter failed with %08x\n", hr);
2024 if (FAILED(hr)) goto out;
2026 hr = IFilterGraph2_AddFilter(pgraph2, &ptestfilter->IBaseFilter_iface, wszFilterInstanceName1);
2027 ok(hr == S_OK, "IFilterGraph2_AddFilter failed with %08x\n", hr);
2029 /* Register our filters with COM and with Filtermapper. */
2030 hr = CoRegisterClassObject(Filter1ClassFactory.clsid,
2031 (IUnknown *)&Filter1ClassFactory.IClassFactory_iface, CLSCTX_INPROC_SERVER,
2032 REGCLS_MULTIPLEUSE, &cookie1);
2033 ok(hr == S_OK, "CoRegisterClassObject failed with %08x\n", hr);
2034 if (FAILED(hr)) goto out;
2035 hr = CoRegisterClassObject(Filter2ClassFactory.clsid,
2036 (IUnknown *)&Filter2ClassFactory.IClassFactory_iface, CLSCTX_INPROC_SERVER,
2037 REGCLS_MULTIPLEUSE, &cookie2);
2038 ok(hr == S_OK, "CoRegisterClassObject failed with %08x\n", hr);
2039 if (FAILED(hr)) goto out;
2040 hr = CoRegisterClassObject(Filter3ClassFactory.clsid,
2041 (IUnknown *)&Filter3ClassFactory.IClassFactory_iface, CLSCTX_INPROC_SERVER,
2042 REGCLS_MULTIPLEUSE, &cookie3);
2043 ok(hr == S_OK, "CoRegisterClassObject failed with %08x\n", hr);
2044 if (FAILED(hr)) goto out;
2046 rgf2.dwVersion = 2;
2047 rgf2.dwMerit = MERIT_UNLIKELY;
2048 S2(U(rgf2)).cPins2 = 1;
2049 S2(U(rgf2)).rgPins2 = rgPins2;
2050 rgPins2[0].dwFlags = REG_PINFLAG_B_RENDERER;
2051 rgPins2[0].cInstances = 1;
2052 rgPins2[0].nMediaTypes = 1;
2053 rgPins2[0].lpMediaType = &rgPinType[0];
2054 rgPins2[0].nMediums = 0;
2055 rgPins2[0].lpMedium = NULL;
2056 rgPins2[0].clsPinCategory = NULL;
2057 rgPinType[0].clsMajorType = &MEDIATYPE_Video;
2058 rgPinType[0].clsMinorType = &mediasubtype1;
2060 hr = IFilterMapper2_RegisterFilter(pMapper2, &CLSID_TestFilter2, wszFilterInstanceName2, NULL,
2061 &CLSID_LegacyAmFilterCategory, NULL, &rgf2);
2062 if (hr == E_ACCESSDENIED)
2063 skip("Not authorized to register filters\n");
2064 else
2066 ok(hr == S_OK, "IFilterMapper2_RegisterFilter failed with %x\n", hr);
2068 rgf2.dwMerit = MERIT_PREFERRED;
2069 rgPinType[0].clsMinorType = &mediasubtype2;
2071 hr = IFilterMapper2_RegisterFilter(pMapper2, &CLSID_TestFilter4, wszFilterInstanceName4, NULL,
2072 &CLSID_LegacyAmFilterCategory, NULL, &rgf2);
2073 ok(hr == S_OK, "IFilterMapper2_RegisterFilter failed with %x\n", hr);
2075 S2(U(rgf2)).cPins2 = 2;
2076 rgPins2[0].dwFlags = 0;
2077 rgPinType[0].clsMinorType = &mediasubtype1;
2079 rgPins2[1].dwFlags = REG_PINFLAG_B_OUTPUT;
2080 rgPins2[1].cInstances = 1;
2081 rgPins2[1].nMediaTypes = 1;
2082 rgPins2[1].lpMediaType = &rgPinType[1];
2083 rgPins2[1].nMediums = 0;
2084 rgPins2[1].lpMedium = NULL;
2085 rgPins2[1].clsPinCategory = NULL;
2086 rgPinType[1].clsMajorType = &MEDIATYPE_Video;
2087 rgPinType[1].clsMinorType = &mediasubtype2;
2089 hr = IFilterMapper2_RegisterFilter(pMapper2, &CLSID_TestFilter3, wszFilterInstanceName3, NULL,
2090 &CLSID_LegacyAmFilterCategory, NULL, &rgf2);
2091 ok(hr == S_OK, "IFilterMapper2_RegisterFilter failed with %x\n", hr);
2093 hr = IFilterGraph2_Render(pgraph2, ptestfilter->ppPins[0]);
2094 ok(hr == S_OK, "IFilterGraph2_Render failed with %08x\n", hr);
2096 get_connected_filter_name(ptestfilter, ConnectedFilterName1);
2097 ok(!strcmp(ConnectedFilterName1, "TestfilterInstance3"),
2098 "unexpected connected filter: %s\n", ConnectedFilterName1);
2100 hr = IFilterMapper2_UnregisterFilter(pMapper2, &CLSID_LegacyAmFilterCategory, NULL,
2101 &CLSID_TestFilter2);
2102 ok(hr == S_OK, "IFilterMapper2_UnregisterFilter failed with %x\n", hr);
2103 hr = IFilterMapper2_UnregisterFilter(pMapper2, &CLSID_LegacyAmFilterCategory, NULL,
2104 &CLSID_TestFilter3);
2105 ok(hr == S_OK, "IFilterMapper2_UnregisterFilter failed with %x\n", hr);
2106 hr = IFilterMapper2_UnregisterFilter(pMapper2, &CLSID_LegacyAmFilterCategory, NULL,
2107 &CLSID_TestFilter4);
2108 ok(hr == S_OK, "IFilterMapper2_UnregisterFilter failed with %x\n", hr);
2111 out:
2113 if (ptestfilter) IBaseFilter_Release(&ptestfilter->IBaseFilter_iface);
2114 if (ptestfilter2) IBaseFilter_Release(&ptestfilter2->IBaseFilter_iface);
2115 if (pgraph2) IFilterGraph2_Release(pgraph2);
2116 if (pMapper2) IFilterMapper2_Release(pMapper2);
2118 hr = CoRevokeClassObject(cookie1);
2119 ok(hr == S_OK, "CoRevokeClassObject failed with %08x\n", hr);
2120 hr = CoRevokeClassObject(cookie2);
2121 ok(hr == S_OK, "CoRevokeClassObject failed with %08x\n", hr);
2122 hr = CoRevokeClassObject(cookie3);
2123 ok(hr == S_OK, "CoRevokeClassObject failed with %08x\n", hr);
2126 typedef struct IUnknownImpl
2128 IUnknown IUnknown_iface;
2129 int AddRef_called;
2130 int Release_called;
2131 } IUnknownImpl;
2133 static IUnknownImpl *IUnknownImpl_from_iface(IUnknown * iface)
2135 return CONTAINING_RECORD(iface, IUnknownImpl, IUnknown_iface);
2138 static HRESULT WINAPI IUnknownImpl_QueryInterface(IUnknown * iface, REFIID riid, LPVOID * ppv)
2140 ok(0, "QueryInterface should not be called for %s\n", wine_dbgstr_guid(riid));
2141 return E_NOINTERFACE;
2144 static ULONG WINAPI IUnknownImpl_AddRef(IUnknown * iface)
2146 IUnknownImpl *This = IUnknownImpl_from_iface(iface);
2147 This->AddRef_called++;
2148 return 2;
2151 static ULONG WINAPI IUnknownImpl_Release(IUnknown * iface)
2153 IUnknownImpl *This = IUnknownImpl_from_iface(iface);
2154 This->Release_called++;
2155 return 1;
2158 static CONST_VTBL IUnknownVtbl IUnknownImpl_Vtbl =
2160 IUnknownImpl_QueryInterface,
2161 IUnknownImpl_AddRef,
2162 IUnknownImpl_Release
2165 static void test_aggregate_filter_graph(void)
2167 HRESULT hr;
2168 IUnknown *pgraph;
2169 IUnknown *punk;
2170 IUnknownImpl unk_outer = { { &IUnknownImpl_Vtbl }, 0, 0 };
2172 hr = CoCreateInstance(&CLSID_FilterGraph, &unk_outer.IUnknown_iface, CLSCTX_INPROC_SERVER,
2173 &IID_IUnknown, (void **)&pgraph);
2174 ok(hr == S_OK, "CoCreateInstance returned %x\n", hr);
2175 ok(pgraph != &unk_outer.IUnknown_iface, "pgraph = %p, expected not %p\n", pgraph, &unk_outer.IUnknown_iface);
2177 hr = IUnknown_QueryInterface(pgraph, &IID_IUnknown, (void **)&punk);
2178 ok(hr == S_OK, "CoCreateInstance returned %x\n", hr);
2179 ok(punk != &unk_outer.IUnknown_iface, "punk = %p, expected not %p\n", punk, &unk_outer.IUnknown_iface);
2180 IUnknown_Release(punk);
2182 ok(unk_outer.AddRef_called == 0, "IUnknownImpl_AddRef called %d times\n", unk_outer.AddRef_called);
2183 ok(unk_outer.Release_called == 0, "IUnknownImpl_Release called %d times\n", unk_outer.Release_called);
2184 unk_outer.AddRef_called = 0;
2185 unk_outer.Release_called = 0;
2187 hr = IUnknown_QueryInterface(pgraph, &IID_IFilterMapper, (void **)&punk);
2188 ok(hr == S_OK, "CoCreateInstance returned %x\n", hr);
2189 ok(punk != &unk_outer.IUnknown_iface, "punk = %p, expected not %p\n", punk, &unk_outer.IUnknown_iface);
2190 IUnknown_Release(punk);
2192 ok(unk_outer.AddRef_called == 1, "IUnknownImpl_AddRef called %d times\n", unk_outer.AddRef_called);
2193 ok(unk_outer.Release_called == 1, "IUnknownImpl_Release called %d times\n", unk_outer.Release_called);
2194 unk_outer.AddRef_called = 0;
2195 unk_outer.Release_called = 0;
2197 hr = IUnknown_QueryInterface(pgraph, &IID_IFilterMapper2, (void **)&punk);
2198 ok(hr == S_OK, "CoCreateInstance returned %x\n", hr);
2199 ok(punk != &unk_outer.IUnknown_iface, "punk = %p, expected not %p\n", punk, &unk_outer.IUnknown_iface);
2200 IUnknown_Release(punk);
2202 ok(unk_outer.AddRef_called == 1, "IUnknownImpl_AddRef called %d times\n", unk_outer.AddRef_called);
2203 ok(unk_outer.Release_called == 1, "IUnknownImpl_Release called %d times\n", unk_outer.Release_called);
2204 unk_outer.AddRef_called = 0;
2205 unk_outer.Release_called = 0;
2207 hr = IUnknown_QueryInterface(pgraph, &IID_IFilterMapper3, (void **)&punk);
2208 ok(hr == S_OK, "CoCreateInstance returned %x\n", hr);
2209 ok(punk != &unk_outer.IUnknown_iface, "punk = %p, expected not %p\n", punk, &unk_outer.IUnknown_iface);
2210 IUnknown_Release(punk);
2212 ok(unk_outer.AddRef_called == 1, "IUnknownImpl_AddRef called %d times\n", unk_outer.AddRef_called);
2213 ok(unk_outer.Release_called == 1, "IUnknownImpl_Release called %d times\n", unk_outer.Release_called);
2215 IUnknown_Release(pgraph);
2218 START_TEST(filtergraph)
2220 HRESULT hr;
2221 CoInitializeEx(NULL, COINIT_MULTITHREADED);
2222 hr = CoCreateInstance(&CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER,
2223 &IID_IGraphBuilder, (LPVOID*)&pgraph);
2224 if (FAILED(hr)) {
2225 skip("Creating filtergraph returned %08x, skipping tests\n", hr);
2226 return;
2228 IGraphBuilder_Release(pgraph);
2229 test_render_run(avifile);
2230 test_render_run(mpegfile);
2231 test_graph_builder();
2232 test_graph_builder_addfilter();
2233 test_mediacontrol();
2234 test_filter_graph2();
2235 test_render_filter_priority();
2236 test_aggregate_filter_graph();
2237 CoUninitialize();