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
25 #include "wine/test.h"
29 typedef struct TestFilterImpl
31 IBaseFilter IBaseFilter_iface
;
34 CRITICAL_SECTION csFilter
;
36 FILTER_INFO filterInfo
;
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 WCHAR
*load_resource(const WCHAR
*name
)
47 static WCHAR pathW
[MAX_PATH
];
53 GetTempPathW(sizeof(pathW
)/sizeof(WCHAR
), pathW
);
54 lstrcatW(pathW
, name
);
56 file
= CreateFileW(pathW
, GENERIC_READ
|GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, 0, 0);
57 ok(file
!= INVALID_HANDLE_VALUE
, "file creation failed, at %s, error %d\n", wine_dbgstr_w(pathW
),
60 res
= FindResourceW(NULL
, name
, (LPCWSTR
)RT_RCDATA
);
61 ok( res
!= 0, "couldn't find resource\n" );
62 ptr
= LockResource( LoadResource( GetModuleHandleA(NULL
), res
));
63 WriteFile( file
, ptr
, SizeofResource( GetModuleHandleA(NULL
), res
), &written
, NULL
);
64 ok( written
== SizeofResource( GetModuleHandleA(NULL
), res
), "couldn't write resource\n" );
70 static IGraphBuilder
*pgraph
;
72 static int createfiltergraph(void)
74 return S_OK
== CoCreateInstance(
75 &CLSID_FilterGraph
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IGraphBuilder
, (LPVOID
*)&pgraph
);
78 static void test_basic_video(void)
81 LONG video_width
, video_height
, window_width
;
82 LONG left
, top
, width
, height
;
85 hr
= IGraphBuilder_QueryInterface(pgraph
, &IID_IBasicVideo
, (LPVOID
*)&pbv
);
86 ok(hr
==S_OK
, "Cannot get IBasicVideo interface returned: %x\n", hr
);
88 /* test get video size */
89 hr
= IBasicVideo_GetVideoSize(pbv
, NULL
, NULL
);
90 ok(hr
==E_POINTER
, "IBasicVideo_GetVideoSize returned: %x\n", hr
);
91 hr
= IBasicVideo_GetVideoSize(pbv
, &video_width
, NULL
);
92 ok(hr
==E_POINTER
, "IBasicVideo_GetVideoSize returned: %x\n", hr
);
93 hr
= IBasicVideo_GetVideoSize(pbv
, NULL
, &video_height
);
94 ok(hr
==E_POINTER
, "IBasicVideo_GetVideoSize returned: %x\n", hr
);
95 hr
= IBasicVideo_GetVideoSize(pbv
, &video_width
, &video_height
);
96 ok(hr
==S_OK
, "Cannot get video size returned: %x\n", hr
);
98 /* test source position */
99 hr
= IBasicVideo_GetSourcePosition(pbv
, NULL
, NULL
, NULL
, NULL
);
100 ok(hr
== E_POINTER
, "IBasicVideo_GetSourcePosition returned: %x\n", hr
);
101 hr
= IBasicVideo_GetSourcePosition(pbv
, &left
, &top
, NULL
, NULL
);
102 ok(hr
== E_POINTER
, "IBasicVideo_GetSourcePosition returned: %x\n", hr
);
103 hr
= IBasicVideo_GetSourcePosition(pbv
, NULL
, NULL
, &width
, &height
);
104 ok(hr
== E_POINTER
, "IBasicVideo_GetSourcePosition returned: %x\n", hr
);
105 hr
= IBasicVideo_GetSourcePosition(pbv
, &left
, &top
, &width
, &height
);
106 ok(hr
== S_OK
, "Cannot get source position returned: %x\n", hr
);
107 ok(left
== 0, "expected 0, got %d\n", left
);
108 ok(top
== 0, "expected 0, got %d\n", top
);
109 ok(width
== video_width
, "expected %d, got %d\n", video_width
, width
);
110 ok(height
== video_height
, "expected %d, got %d\n", video_height
, height
);
112 hr
= IBasicVideo_SetSourcePosition(pbv
, 0, 0, 0, 0);
113 ok(hr
==E_INVALIDARG
, "IBasicVideo_SetSourcePosition returned: %x\n", hr
);
114 hr
= IBasicVideo_SetSourcePosition(pbv
, 0, 0, video_width
*2, video_height
*2);
115 ok(hr
==E_INVALIDARG
, "IBasicVideo_SetSourcePosition returned: %x\n", hr
);
116 hr
= IBasicVideo_put_SourceTop(pbv
, -1);
117 ok(hr
==E_INVALIDARG
, "IBasicVideo_put_SourceTop returned: %x\n", hr
);
118 hr
= IBasicVideo_put_SourceTop(pbv
, 0);
119 ok(hr
==S_OK
, "Cannot put source top returned: %x\n", hr
);
120 hr
= IBasicVideo_put_SourceTop(pbv
, 1);
121 ok(hr
==E_INVALIDARG
, "IBasicVideo_put_SourceTop returned: %x\n", hr
);
123 hr
= IBasicVideo_SetSourcePosition(pbv
, video_width
, 0, video_width
, video_height
);
124 ok(hr
==E_INVALIDARG
, "IBasicVideo_SetSourcePosition returned: %x\n", hr
);
125 hr
= IBasicVideo_SetSourcePosition(pbv
, 0, video_height
, video_width
, video_height
);
126 ok(hr
==E_INVALIDARG
, "IBasicVideo_SetSourcePosition returned: %x\n", hr
);
127 hr
= IBasicVideo_SetSourcePosition(pbv
, -1, 0, video_width
, video_height
);
128 ok(hr
==E_INVALIDARG
, "IBasicVideo_SetSourcePosition returned: %x\n", hr
);
129 hr
= IBasicVideo_SetSourcePosition(pbv
, 0, -1, video_width
, video_height
);
130 ok(hr
==E_INVALIDARG
, "IBasicVideo_SetSourcePosition returned: %x\n", hr
);
131 hr
= IBasicVideo_SetSourcePosition(pbv
, video_width
/2, video_height
/2, video_width
, video_height
);
132 ok(hr
==E_INVALIDARG
, "IBasicVideo_SetSourcePosition returned: %x\n", hr
);
133 hr
= IBasicVideo_SetSourcePosition(pbv
, video_width
/2, video_height
/2, video_width
, video_height
);
134 ok(hr
==E_INVALIDARG
, "IBasicVideo_SetSourcePosition returned: %x\n", hr
);
136 hr
= IBasicVideo_SetSourcePosition(pbv
, 0, 0, video_width
, video_height
+1);
137 ok(hr
==E_INVALIDARG
, "IBasicVideo_SetSourcePosition returned: %x\n", hr
);
138 hr
= IBasicVideo_SetSourcePosition(pbv
, 0, 0, video_width
+1, video_height
);
139 ok(hr
==E_INVALIDARG
, "IBasicVideo_SetSourcePosition returned: %x\n", hr
);
141 hr
= IBasicVideo_SetSourcePosition(pbv
, video_width
/2, video_height
/2, video_width
/3+1, video_height
/3+1);
142 ok(hr
==S_OK
, "Cannot set source position returned: %x\n", hr
);
144 hr
= IBasicVideo_get_SourceLeft(pbv
, &left
);
145 ok(hr
==S_OK
, "Cannot get source left returned: %x\n", hr
);
146 ok(left
==video_width
/2, "expected %d, got %d\n", video_width
/2, left
);
147 hr
= IBasicVideo_get_SourceTop(pbv
, &top
);
148 ok(hr
==S_OK
, "Cannot get source top returned: %x\n", hr
);
149 ok(top
==video_height
/2, "expected %d, got %d\n", video_height
/2, top
);
150 hr
= IBasicVideo_get_SourceWidth(pbv
, &width
);
151 ok(hr
==S_OK
, "Cannot get source width returned: %x\n", hr
);
152 ok(width
==video_width
/3+1, "expected %d, got %d\n", video_width
/3+1, width
);
153 hr
= IBasicVideo_get_SourceHeight(pbv
, &height
);
154 ok(hr
==S_OK
, "Cannot get source height returned: %x\n", hr
);
155 ok(height
==video_height
/3+1, "expected %d, got %d\n", video_height
/3+1, height
);
157 hr
= IBasicVideo_put_SourceLeft(pbv
, video_width
/3);
158 ok(hr
==S_OK
, "Cannot put source left returned: %x\n", hr
);
159 hr
= IBasicVideo_GetSourcePosition(pbv
, &left
, &top
, &width
, &height
);
160 ok(hr
== S_OK
, "Cannot get source position returned: %x\n", hr
);
161 ok(left
== video_width
/3, "expected %d, got %d\n", video_width
/3, left
);
162 ok(width
== video_width
/3+1, "expected %d, got %d\n", video_width
/3+1, width
);
164 hr
= IBasicVideo_put_SourceTop(pbv
, video_height
/3);
165 ok(hr
==S_OK
, "Cannot put source top returned: %x\n", hr
);
166 hr
= IBasicVideo_GetSourcePosition(pbv
, &left
, &top
, &width
, &height
);
167 ok(hr
== S_OK
, "Cannot get source position returned: %x\n", hr
);
168 ok(top
== video_height
/3, "expected %d, got %d\n", video_height
/3, top
);
169 ok(height
== video_height
/3+1, "expected %d, got %d\n", video_height
/3+1, height
);
171 hr
= IBasicVideo_put_SourceWidth(pbv
, video_width
/4+1);
172 ok(hr
==S_OK
, "Cannot put source width returned: %x\n", hr
);
173 hr
= IBasicVideo_GetSourcePosition(pbv
, &left
, &top
, &width
, &height
);
174 ok(hr
== S_OK
, "Cannot get source position returned: %x\n", hr
);
175 ok(left
== video_width
/3, "expected %d, got %d\n", video_width
/3, left
);
176 ok(width
== video_width
/4+1, "expected %d, got %d\n", video_width
/4+1, width
);
178 hr
= IBasicVideo_put_SourceHeight(pbv
, video_height
/4+1);
179 ok(hr
==S_OK
, "Cannot put source height returned: %x\n", hr
);
180 hr
= IBasicVideo_GetSourcePosition(pbv
, &left
, &top
, &width
, &height
);
181 ok(hr
== S_OK
, "Cannot get source position returned: %x\n", hr
);
182 ok(top
== video_height
/3, "expected %d, got %d\n", video_height
/3, top
);
183 ok(height
== video_height
/4+1, "expected %d, got %d\n", video_height
/4+1, height
);
185 /* test destination rectangle */
186 window_width
= max(video_width
, GetSystemMetrics(SM_CXMIN
) - 2 * GetSystemMetrics(SM_CXFRAME
));
188 hr
= IBasicVideo_GetDestinationPosition(pbv
, NULL
, NULL
, NULL
, NULL
);
189 ok(hr
== E_POINTER
, "IBasicVideo_GetDestinationPosition returned: %x\n", hr
);
190 hr
= IBasicVideo_GetDestinationPosition(pbv
, &left
, &top
, NULL
, NULL
);
191 ok(hr
== E_POINTER
, "IBasicVideo_GetDestinationPosition returned: %x\n", hr
);
192 hr
= IBasicVideo_GetDestinationPosition(pbv
, NULL
, NULL
, &width
, &height
);
193 ok(hr
== E_POINTER
, "IBasicVideo_GetDestinationPosition returned: %x\n", hr
);
194 hr
= IBasicVideo_GetDestinationPosition(pbv
, &left
, &top
, &width
, &height
);
195 ok(hr
== S_OK
, "Cannot get destination position returned: %x\n", hr
);
196 ok(left
== 0, "expected 0, got %d\n", left
);
197 ok(top
== 0, "expected 0, got %d\n", top
);
198 todo_wine
ok(width
== window_width
, "expected %d, got %d\n", window_width
, width
);
199 todo_wine
ok(height
== video_height
, "expected %d, got %d\n", video_height
, height
);
201 hr
= IBasicVideo_SetDestinationPosition(pbv
, 0, 0, 0, 0);
202 ok(hr
==E_INVALIDARG
, "IBasicVideo_SetDestinationPosition returned: %x\n", hr
);
203 hr
= IBasicVideo_SetDestinationPosition(pbv
, 0, 0, video_width
*2, video_height
*2);
204 ok(hr
==S_OK
, "Cannot put destination position returned: %x\n", hr
);
206 hr
= IBasicVideo_put_DestinationLeft(pbv
, -1);
207 ok(hr
==S_OK
, "Cannot put destination left returned: %x\n", hr
);
208 hr
= IBasicVideo_put_DestinationLeft(pbv
, 0);
209 ok(hr
==S_OK
, "Cannot put destination left returned: %x\n", hr
);
210 hr
= IBasicVideo_put_DestinationLeft(pbv
, 1);
211 ok(hr
==S_OK
, "Cannot put destination left returned: %x\n", hr
);
213 hr
= IBasicVideo_SetDestinationPosition(pbv
, video_width
, 0, video_width
, video_height
);
214 ok(hr
==S_OK
, "Cannot set destinaiton position returned: %x\n", hr
);
215 hr
= IBasicVideo_SetDestinationPosition(pbv
, 0, video_height
, video_width
, video_height
);
216 ok(hr
==S_OK
, "Cannot set destinaiton position returned: %x\n", hr
);
217 hr
= IBasicVideo_SetDestinationPosition(pbv
, -1, 0, video_width
, video_height
);
218 ok(hr
==S_OK
, "Cannot set destination position returned: %x\n", hr
);
219 hr
= IBasicVideo_SetDestinationPosition(pbv
, 0, -1, video_width
, video_height
);
220 ok(hr
==S_OK
, "Cannot set destination position returned: %x\n", hr
);
221 hr
= IBasicVideo_SetDestinationPosition(pbv
, video_width
/2, video_height
/2, video_width
, video_height
);
222 ok(hr
==S_OK
, "Cannot set destination position returned: %x\n", hr
);
223 hr
= IBasicVideo_SetDestinationPosition(pbv
, video_width
/2, video_height
/2, video_width
, video_height
);
224 ok(hr
==S_OK
, "Cannot set destination position returned: %x\n", hr
);
226 hr
= IBasicVideo_SetDestinationPosition(pbv
, 0, 0, video_width
, video_height
+1);
227 ok(hr
==S_OK
, "Cannot set destination position returned: %x\n", hr
);
228 hr
= IBasicVideo_SetDestinationPosition(pbv
, 0, 0, video_width
+1, video_height
);
229 ok(hr
==S_OK
, "Cannot set destination position returned: %x\n", hr
);
231 hr
= IBasicVideo_SetDestinationPosition(pbv
, video_width
/2, video_height
/2, video_width
/3+1, video_height
/3+1);
232 ok(hr
==S_OK
, "Cannot set destination position returned: %x\n", hr
);
234 hr
= IBasicVideo_get_DestinationLeft(pbv
, &left
);
235 ok(hr
==S_OK
, "Cannot get destination left returned: %x\n", hr
);
236 ok(left
==video_width
/2, "expected %d, got %d\n", video_width
/2, left
);
237 hr
= IBasicVideo_get_DestinationTop(pbv
, &top
);
238 ok(hr
==S_OK
, "Cannot get destination top returned: %x\n", hr
);
239 ok(top
==video_height
/2, "expected %d, got %d\n", video_height
/2, top
);
240 hr
= IBasicVideo_get_DestinationWidth(pbv
, &width
);
241 ok(hr
==S_OK
, "Cannot get destination width returned: %x\n", hr
);
242 ok(width
==video_width
/3+1, "expected %d, got %d\n", video_width
/3+1, width
);
243 hr
= IBasicVideo_get_DestinationHeight(pbv
, &height
);
244 ok(hr
==S_OK
, "Cannot get destination height returned: %x\n", hr
);
245 ok(height
==video_height
/3+1, "expected %d, got %d\n", video_height
/3+1, height
);
247 hr
= IBasicVideo_put_DestinationLeft(pbv
, video_width
/3);
248 ok(hr
==S_OK
, "Cannot put destination left returned: %x\n", hr
);
249 hr
= IBasicVideo_GetDestinationPosition(pbv
, &left
, &top
, &width
, &height
);
250 ok(hr
== S_OK
, "Cannot get source position returned: %x\n", hr
);
251 ok(left
== video_width
/3, "expected %d, got %d\n", video_width
/3, left
);
252 ok(width
== video_width
/3+1, "expected %d, got %d\n", video_width
/3+1, width
);
254 hr
= IBasicVideo_put_DestinationTop(pbv
, video_height
/3);
255 ok(hr
==S_OK
, "Cannot put destination top returned: %x\n", hr
);
256 hr
= IBasicVideo_GetDestinationPosition(pbv
, &left
, &top
, &width
, &height
);
257 ok(hr
== S_OK
, "Cannot get source position returned: %x\n", hr
);
258 ok(top
== video_height
/3, "expected %d, got %d\n", video_height
/3, top
);
259 ok(height
== video_height
/3+1, "expected %d, got %d\n", video_height
/3+1, height
);
261 hr
= IBasicVideo_put_DestinationWidth(pbv
, video_width
/4+1);
262 ok(hr
==S_OK
, "Cannot put destination width returned: %x\n", hr
);
263 hr
= IBasicVideo_GetDestinationPosition(pbv
, &left
, &top
, &width
, &height
);
264 ok(hr
== S_OK
, "Cannot get source position returned: %x\n", hr
);
265 ok(left
== video_width
/3, "expected %d, got %d\n", video_width
/3, left
);
266 ok(width
== video_width
/4+1, "expected %d, got %d\n", video_width
/4+1, width
);
268 hr
= IBasicVideo_put_DestinationHeight(pbv
, video_height
/4+1);
269 ok(hr
==S_OK
, "Cannot put destination height returned: %x\n", hr
);
270 hr
= IBasicVideo_GetDestinationPosition(pbv
, &left
, &top
, &width
, &height
);
271 ok(hr
== S_OK
, "Cannot get source position returned: %x\n", hr
);
272 ok(top
== video_height
/3, "expected %d, got %d\n", video_height
/3, top
);
273 ok(height
== video_height
/4+1, "expected %d, got %d\n", video_height
/4+1, height
);
275 /* reset source rectangle */
276 hr
= IBasicVideo_SetDefaultSourcePosition(pbv
);
277 ok(hr
==S_OK
, "IBasicVideo_SetDefaultSourcePosition returned: %x\n", hr
);
279 /* reset destination position */
280 hr
= IBasicVideo_SetDestinationPosition(pbv
, 0, 0, video_width
, video_height
);
281 ok(hr
==S_OK
, "Cannot set destination position returned: %x\n", hr
);
283 IBasicVideo_Release(pbv
);
286 static void rungraph(void)
294 hr
= IGraphBuilder_QueryInterface(pgraph
, &IID_IMediaControl
, (LPVOID
*)&pmc
);
295 ok(hr
==S_OK
, "Cannot get IMediaControl interface returned: %x\n", hr
);
297 hr
= IGraphBuilder_QueryInterface(pgraph
, &IID_IMediaFilter
, (LPVOID
*)&pmf
);
298 ok(hr
==S_OK
, "Cannot get IMediaFilter interface returned: %x\n", hr
);
300 IMediaControl_Stop(pmc
);
302 IMediaFilter_SetSyncSource(pmf
, NULL
);
304 IMediaFilter_Release(pmf
);
308 hr
= IMediaControl_Run(pmc
);
309 ok(hr
==S_FALSE
, "Cannot run the graph returned: %x\n", hr
);
313 trace("run -> stop\n");
314 hr
= IMediaControl_Stop(pmc
);
315 ok(hr
==S_OK
|| hr
== S_FALSE
, "Cannot stop the graph returned: %x\n", hr
);
317 IGraphBuilder_SetDefaultSyncSource(pgraph
);
320 trace("stop -> pause\n");
321 hr
= IMediaControl_Pause(pmc
);
322 ok(hr
==S_OK
|| hr
== S_FALSE
, "Cannot pause the graph returned: %x\n", hr
);
325 trace("pause -> run\n");
326 hr
= IMediaControl_Run(pmc
);
327 ok(hr
==S_OK
|| hr
== S_FALSE
, "Cannot start the graph returned: %x\n", hr
);
330 trace("run -> pause\n");
331 hr
= IMediaControl_Pause(pmc
);
332 ok(hr
==S_OK
|| hr
== S_FALSE
, "Cannot pause the graph returned: %x\n", hr
);
335 trace("pause -> stop\n");
336 hr
= IMediaControl_Stop(pmc
);
337 ok(hr
==S_OK
|| hr
== S_FALSE
, "Cannot stop the graph returned: %x\n", hr
);
340 trace("pause -> run\n");
341 hr
= IMediaControl_Run(pmc
);
342 ok(hr
==S_OK
|| hr
== S_FALSE
, "Cannot start the graph returned: %x\n", hr
);
344 trace("run -> stop\n");
345 hr
= IMediaControl_Stop(pmc
);
346 ok(hr
==S_OK
|| hr
== S_FALSE
, "Cannot stop the graph returned: %x\n", hr
);
348 trace("stop -> run\n");
349 hr
= IMediaControl_Run(pmc
);
350 ok(hr
==S_OK
|| hr
== S_FALSE
, "Cannot start the graph returned: %x\n", hr
);
352 hr
= IGraphBuilder_QueryInterface(pgraph
, &IID_IMediaEvent
, (LPVOID
*)&pme
);
353 ok(hr
==S_OK
, "Cannot get IMediaEvent interface returned: %x\n", hr
);
355 hr
= IMediaEvent_GetEventHandle(pme
, (OAEVENT
*)&hEvent
);
356 ok(hr
==S_OK
, "Cannot get event handle returned: %x\n", hr
);
358 ok(WaitForSingleObject(hEvent
, 2000) == WAIT_OBJECT_0
, "Wait failed\n");
360 hr
= IMediaEvent_Release(pme
);
361 ok(hr
==2, "Releasing mediaevent returned: %x\n", hr
);
363 hr
= IMediaControl_Stop(pmc
);
364 ok(hr
==S_OK
, "Cannot stop the graph returned: %x\n", hr
);
366 hr
= IMediaControl_Release(pmc
);
367 ok(hr
==1, "Releasing mediacontrol returned: %x\n", hr
);
370 static void releasefiltergraph(void)
374 hr
= IGraphBuilder_Release(pgraph
);
375 ok(hr
==0, "Releasing filtergraph returned: %x\n", hr
);
378 static void test_render_run(const WCHAR
*file
)
383 WCHAR
*filename
= load_resource(file
);
385 h
= CreateFileW(filename
, 0, 0, NULL
, OPEN_EXISTING
, 0, NULL
);
386 if (h
== INVALID_HANDLE_VALUE
) {
387 skip("Could not read test file %s, skipping test\n", wine_dbgstr_w(file
));
388 DeleteFileW(filename
);
393 if (!createfiltergraph())
395 DeleteFileW(filename
);
399 hr
= IGraphBuilder_RenderFile(pgraph
, filename
, NULL
);
400 if (hr
== VFW_E_CANNOT_RENDER
)
401 skip("%s: codec not supported; skipping test\n", wine_dbgstr_w(file
));
404 ok(hr
== S_OK
|| hr
== VFW_S_AUDIO_NOT_RENDERED
, "RenderFile failed: %x\n", hr
);
408 releasefiltergraph();
410 /* check reference leaks */
411 h
= CreateFileW(filename
, GENERIC_READ
, 0, NULL
, OPEN_EXISTING
, 0, NULL
);
412 ok(h
!= INVALID_HANDLE_VALUE
, "CreateFile failed: err=%d\n", GetLastError());
415 DeleteFileW(filename
);
418 static DWORD WINAPI
call_RenderFile_multithread(LPVOID lParam
)
420 IFilterGraph2
*filter_graph
= lParam
;
422 WCHAR mp3file
[] = {'t','e','s','t','.','m','p','3',0};
425 handle
= CreateFileW(mp3file
, 0, 0, NULL
, CREATE_ALWAYS
, 0, NULL
);
426 if (handle
== INVALID_HANDLE_VALUE
)
428 skip("Could not read test file %s, skipping test\n", wine_dbgstr_w(mp3file
));
433 hr
= IFilterGraph2_RenderFile(filter_graph
, mp3file
, NULL
);
434 todo_wine
ok(hr
== VFW_E_CANNOT_RENDER
|| /* xp or older + DirectX 9 */
435 hr
== VFW_E_NO_TRANSPORT
|| /* win7 or newer */
436 broken(hr
== CLASS_E_CLASSNOTAVAILABLE
), /* xp or older + DirectX 8 or older */
437 "Expected 0x%08x or 0x%08x, returned 0x%08x\n", VFW_E_CANNOT_RENDER
, VFW_E_NO_TRANSPORT
, hr
);
439 DeleteFileW(mp3file
);
443 static void test_render_with_multithread(void)
447 static HRESULT (WINAPI
*pDllGetClassObject
)(REFCLSID rclsid
, REFIID riid
, void **out
);
448 IClassFactory
*classfactory
= NULL
;
449 static IGraphBuilder
*graph_builder
;
450 static IFilterGraph2
*filter_graph
;
453 CoInitializeEx(NULL
, COINIT_APARTMENTTHREADED
);
455 hmod
= LoadLibraryA("quartz.dll");
458 skip("Fail to load quartz.dll.\n");
462 pDllGetClassObject
= (void*)GetProcAddress(hmod
, "DllGetClassObject");
463 if (!pDllGetClassObject
)
465 skip("Fail to get DllGetClassObject.\n");
469 hr
= pDllGetClassObject(&CLSID_FilterGraph
, &IID_IClassFactory
, (void **)&classfactory
);
470 ok(hr
== S_OK
, "DllGetClassObject failed 0x%08x\n", hr
);
473 skip("Can't create IClassFactory 0x%08x.\n", hr
);
477 hr
= IClassFactory_CreateInstance(classfactory
, NULL
, &IID_IUnknown
, (LPVOID
*)&graph_builder
);
478 ok(hr
== S_OK
, "IClassFactory_CreateInstance failed 0x%08x\n", hr
);
480 hr
= IGraphBuilder_QueryInterface(graph_builder
, &IID_IFilterGraph2
, (void**)&filter_graph
);
481 ok(hr
== S_OK
, "IGraphBuilder_QueryInterface failed 0x%08x\n", hr
);
483 thread
= CreateThread(NULL
, 0, call_RenderFile_multithread
, filter_graph
, 0, NULL
);
485 WaitForSingleObject(thread
, 1000);
486 IFilterGraph2_Release(filter_graph
);
487 IGraphBuilder_Release(graph_builder
);
488 IClassFactory_Release(classfactory
);
494 static void test_graph_builder(void)
497 IBaseFilter
*pF
= NULL
;
498 IBaseFilter
*pF2
= NULL
;
500 IEnumPins
*pEnum
= NULL
;
502 static const WCHAR testFilterW
[] = {'t','e','s','t','F','i','l','t','e','r',0};
503 static const WCHAR fooBarW
[] = {'f','o','o','B','a','r',0};
505 if (!createfiltergraph())
508 /* create video filter */
509 hr
= CoCreateInstance(&CLSID_VideoRenderer
, NULL
, CLSCTX_INPROC_SERVER
,
510 &IID_IBaseFilter
, (LPVOID
*)&pF
);
511 ok(hr
== S_OK
, "CoCreateInstance failed with %x\n", hr
);
512 ok(pF
!= NULL
, "pF is NULL\n");
514 hr
= IGraphBuilder_AddFilter(pgraph
, NULL
, testFilterW
);
515 ok(hr
== E_POINTER
, "IGraphBuilder_AddFilter returned %x\n", hr
);
517 /* add the two filters to the graph */
518 hr
= IGraphBuilder_AddFilter(pgraph
, pF
, testFilterW
);
519 ok(hr
== S_OK
, "failed to add pF to the graph: %x\n", hr
);
522 hr
= IBaseFilter_EnumPins(pF
, &pEnum
);
523 ok(hr
== S_OK
, "IBaseFilter_EnumPins failed for pF: %x\n", hr
);
524 ok(pEnum
!= NULL
, "pEnum is NULL\n");
525 hr
= IEnumPins_Next(pEnum
, 1, &pIn
, NULL
);
526 ok(hr
== S_OK
, "IEnumPins_Next failed for pF: %x\n", hr
);
527 ok(pIn
!= NULL
, "pIn is NULL\n");
528 hr
= IPin_QueryDirection(pIn
, &dir
);
529 ok(hr
== S_OK
, "IPin_QueryDirection failed: %x\n", hr
);
530 ok(dir
== PINDIR_INPUT
, "pin has wrong direction\n");
532 hr
= IGraphBuilder_FindFilterByName(pgraph
, fooBarW
, &pF2
);
533 ok(hr
== VFW_E_NOT_FOUND
, "IGraphBuilder_FindFilterByName returned %x\n", hr
);
534 ok(pF2
== NULL
, "IGraphBuilder_FindFilterByName returned %p\n", pF2
);
535 hr
= IGraphBuilder_FindFilterByName(pgraph
, testFilterW
, &pF2
);
536 ok(hr
== S_OK
, "IGraphBuilder_FindFilterByName returned %x\n", hr
);
537 ok(pF2
!= NULL
, "IGraphBuilder_FindFilterByName returned NULL\n");
538 hr
= IGraphBuilder_FindFilterByName(pgraph
, testFilterW
, NULL
);
539 ok(hr
== E_POINTER
, "IGraphBuilder_FindFilterByName returned %x\n", hr
);
541 hr
= IGraphBuilder_Connect(pgraph
, NULL
, pIn
);
542 ok(hr
== E_POINTER
, "IGraphBuilder_Connect returned %x\n", hr
);
544 hr
= IGraphBuilder_Connect(pgraph
, pIn
, NULL
);
545 ok(hr
== E_POINTER
, "IGraphBuilder_Connect returned %x\n", hr
);
547 hr
= IGraphBuilder_Connect(pgraph
, pIn
, pIn
);
548 ok(hr
== VFW_E_CANNOT_CONNECT
, "IGraphBuilder_Connect returned %x\n", hr
);
550 if (pIn
) IPin_Release(pIn
);
551 if (pEnum
) IEnumPins_Release(pEnum
);
552 if (pF
) IBaseFilter_Release(pF
);
553 if (pF2
) IBaseFilter_Release(pF2
);
555 releasefiltergraph();
558 static void test_graph_builder_addfilter(void)
561 IBaseFilter
*pF
= NULL
;
562 static const WCHAR testFilterW
[] = {'t','e','s','t','F','i','l','t','e','r',0};
564 if (!createfiltergraph())
567 hr
= IGraphBuilder_AddFilter(pgraph
, NULL
, testFilterW
);
568 ok(hr
== E_POINTER
, "IGraphBuilder_AddFilter returned: %x\n", hr
);
570 /* create video filter */
571 hr
= CoCreateInstance(&CLSID_VideoRenderer
, NULL
, CLSCTX_INPROC_SERVER
,
572 &IID_IBaseFilter
, (LPVOID
*)&pF
);
573 ok(hr
== S_OK
, "CoCreateInstance failed with %x\n", hr
);
574 ok(pF
!= NULL
, "pF is NULL\n");
576 skip("failed to created filter, skipping\n");
580 hr
= IGraphBuilder_AddFilter(pgraph
, pF
, NULL
);
581 ok(hr
== S_OK
, "IGraphBuilder_AddFilter returned: %x\n", hr
);
582 IBaseFilter_Release(pF
);
585 static void test_mediacontrol(void)
588 LONGLONG pos
= 0xdeadbeef;
589 GUID format
= GUID_NULL
;
590 IMediaSeeking
*seeking
= NULL
;
591 IMediaFilter
*filter
= NULL
;
592 IMediaControl
*control
= NULL
;
594 IGraphBuilder_SetDefaultSyncSource(pgraph
);
595 hr
= IGraphBuilder_QueryInterface(pgraph
, &IID_IMediaSeeking
, (void**) &seeking
);
596 ok(hr
== S_OK
, "QueryInterface IMediaControl failed: %08x\n", hr
);
600 hr
= IGraphBuilder_QueryInterface(pgraph
, &IID_IMediaFilter
, (void**) &filter
);
601 ok(hr
== S_OK
, "QueryInterface IMediaFilter failed: %08x\n", hr
);
604 IMediaSeeking_Release(seeking
);
608 hr
= IGraphBuilder_QueryInterface(pgraph
, &IID_IMediaControl
, (void**) &control
);
609 ok(hr
== S_OK
, "QueryInterface IMediaControl failed: %08x\n", hr
);
612 IMediaSeeking_Release(seeking
);
613 IMediaFilter_Release(filter
);
618 hr
= IMediaSeeking_GetTimeFormat(seeking
, &format
);
619 ok(hr
== S_OK
, "GetTimeFormat failed: %08x\n", hr
);
620 ok(IsEqualGUID(&format
, &TIME_FORMAT_MEDIA_TIME
), "GetTimeFormat: unexpected format %s\n", wine_dbgstr_guid(&format
));
623 hr
= IMediaSeeking_ConvertTimeFormat(seeking
, &pos
, NULL
, 0x123456789a, NULL
);
624 ok(hr
== S_OK
, "ConvertTimeFormat failed: %08x\n", hr
);
625 ok(pos
== 0x123456789a, "ConvertTimeFormat: expected 123456789a, got (%s)\n", wine_dbgstr_longlong(pos
));
628 hr
= IMediaSeeking_ConvertTimeFormat(seeking
, &pos
, &TIME_FORMAT_MEDIA_TIME
, 0x123456789a, NULL
);
629 ok(hr
== S_OK
, "ConvertTimeFormat failed: %08x\n", hr
);
630 ok(pos
== 0x123456789a, "ConvertTimeFormat: expected 123456789a, got (%s)\n", wine_dbgstr_longlong(pos
));
633 hr
= IMediaSeeking_ConvertTimeFormat(seeking
, &pos
, NULL
, 0x123456789a, &TIME_FORMAT_MEDIA_TIME
);
634 ok(hr
== S_OK
, "ConvertTimeFormat failed: %08x\n", hr
);
635 ok(pos
== 0x123456789a, "ConvertTimeFormat: expected 123456789a, got (%s)\n", wine_dbgstr_longlong(pos
));
637 hr
= IMediaSeeking_GetCurrentPosition(seeking
, &pos
);
638 ok(hr
== S_OK
, "GetCurrentPosition failed: %08x\n", hr
);
639 ok(pos
== 0, "Position != 0 (%s)\n", wine_dbgstr_longlong(pos
));
641 hr
= IMediaSeeking_SetPositions(seeking
, NULL
, AM_SEEKING_ReturnTime
, NULL
, AM_SEEKING_NoPositioning
);
642 ok(hr
== S_OK
, "SetPositions failed: %08x\n", hr
);
643 hr
= IMediaSeeking_SetPositions(seeking
, NULL
, AM_SEEKING_NoPositioning
, NULL
, AM_SEEKING_ReturnTime
);
644 ok(hr
== S_OK
, "SetPositions failed: %08x\n", hr
);
646 IMediaFilter_SetSyncSource(filter
, NULL
);
648 hr
= IMediaSeeking_GetCurrentPosition(seeking
, &pos
);
649 ok(hr
== S_OK
, "GetCurrentPosition failed: %08x\n", hr
);
650 ok(pos
== 0, "Position != 0 (%s)\n", wine_dbgstr_longlong(pos
));
652 hr
= IMediaControl_GetState(control
, 1000, NULL
);
653 ok(hr
== E_POINTER
, "GetState expected %08x, got %08x\n", E_POINTER
, hr
);
655 IMediaControl_Release(control
);
656 IMediaSeeking_Release(seeking
);
657 IMediaFilter_Release(filter
);
658 releasefiltergraph();
661 static void test_filter_graph2(void)
664 IFilterGraph2
*pF
= NULL
;
666 hr
= CoCreateInstance(&CLSID_FilterGraph
, NULL
, CLSCTX_INPROC_SERVER
,
667 &IID_IFilterGraph2
, (LPVOID
*)&pF
);
668 ok(hr
== S_OK
, "CoCreateInstance failed with %x\n", hr
);
669 ok(pF
!= NULL
, "pF is NULL\n");
671 hr
= IFilterGraph2_Release(pF
);
672 ok(hr
== 0, "IFilterGraph2_Release returned: %x\n", hr
);
675 /* IEnumMediaTypes implementation (supporting code for Render() test.) */
676 static void FreeMediaType(AM_MEDIA_TYPE
* pMediaType
)
678 if (pMediaType
->pbFormat
)
680 CoTaskMemFree(pMediaType
->pbFormat
);
681 pMediaType
->pbFormat
= NULL
;
683 if (pMediaType
->pUnk
)
685 IUnknown_Release(pMediaType
->pUnk
);
686 pMediaType
->pUnk
= NULL
;
690 static HRESULT
CopyMediaType(AM_MEDIA_TYPE
* pDest
, const AM_MEDIA_TYPE
*pSrc
)
693 if (!pSrc
->pbFormat
) return S_OK
;
694 if (!(pDest
->pbFormat
= CoTaskMemAlloc(pSrc
->cbFormat
)))
695 return E_OUTOFMEMORY
;
696 memcpy(pDest
->pbFormat
, pSrc
->pbFormat
, pSrc
->cbFormat
);
698 IUnknown_AddRef(pDest
->pUnk
);
702 static AM_MEDIA_TYPE
* CreateMediaType(AM_MEDIA_TYPE
const * pSrc
)
704 AM_MEDIA_TYPE
* pDest
;
706 pDest
= CoTaskMemAlloc(sizeof(AM_MEDIA_TYPE
));
710 if (FAILED(CopyMediaType(pDest
, pSrc
)))
712 CoTaskMemFree(pDest
);
719 static BOOL
CompareMediaTypes(const AM_MEDIA_TYPE
* pmt1
, const AM_MEDIA_TYPE
* pmt2
, BOOL bWildcards
)
721 return (((bWildcards
&& (IsEqualGUID(&pmt1
->majortype
, &GUID_NULL
) || IsEqualGUID(&pmt2
->majortype
, &GUID_NULL
))) || IsEqualGUID(&pmt1
->majortype
, &pmt2
->majortype
)) &&
722 ((bWildcards
&& (IsEqualGUID(&pmt1
->subtype
, &GUID_NULL
) || IsEqualGUID(&pmt2
->subtype
, &GUID_NULL
))) || IsEqualGUID(&pmt1
->subtype
, &pmt2
->subtype
)));
725 static void DeleteMediaType(AM_MEDIA_TYPE
* pMediaType
)
727 FreeMediaType(pMediaType
);
728 CoTaskMemFree(pMediaType
);
731 typedef struct IEnumMediaTypesImpl
733 IEnumMediaTypes IEnumMediaTypes_iface
;
735 AM_MEDIA_TYPE
*pMediaTypes
;
738 } IEnumMediaTypesImpl
;
740 static const struct IEnumMediaTypesVtbl IEnumMediaTypesImpl_Vtbl
;
742 static inline IEnumMediaTypesImpl
*impl_from_IEnumMediaTypes(IEnumMediaTypes
*iface
)
744 return CONTAINING_RECORD(iface
, IEnumMediaTypesImpl
, IEnumMediaTypes_iface
);
747 static HRESULT
IEnumMediaTypesImpl_Construct(const AM_MEDIA_TYPE
* pMediaTypes
, ULONG cMediaTypes
, IEnumMediaTypes
** ppEnum
)
750 IEnumMediaTypesImpl
* pEnumMediaTypes
= CoTaskMemAlloc(sizeof(IEnumMediaTypesImpl
));
752 if (!pEnumMediaTypes
)
755 return E_OUTOFMEMORY
;
757 pEnumMediaTypes
->IEnumMediaTypes_iface
.lpVtbl
= &IEnumMediaTypesImpl_Vtbl
;
758 pEnumMediaTypes
->refCount
= 1;
759 pEnumMediaTypes
->uIndex
= 0;
760 pEnumMediaTypes
->cMediaTypes
= cMediaTypes
;
761 pEnumMediaTypes
->pMediaTypes
= CoTaskMemAlloc(sizeof(AM_MEDIA_TYPE
) * cMediaTypes
);
762 for (i
= 0; i
< cMediaTypes
; i
++)
763 if (FAILED(CopyMediaType(&pEnumMediaTypes
->pMediaTypes
[i
], &pMediaTypes
[i
])))
766 FreeMediaType(&pEnumMediaTypes
->pMediaTypes
[i
]);
767 CoTaskMemFree(pEnumMediaTypes
->pMediaTypes
);
768 return E_OUTOFMEMORY
;
770 *ppEnum
= &pEnumMediaTypes
->IEnumMediaTypes_iface
;
774 static HRESULT WINAPI
IEnumMediaTypesImpl_QueryInterface(IEnumMediaTypes
* iface
, REFIID riid
, LPVOID
* ppv
)
778 if (IsEqualIID(riid
, &IID_IUnknown
))
780 else if (IsEqualIID(riid
, &IID_IEnumMediaTypes
))
785 IUnknown_AddRef((IUnknown
*)(*ppv
));
789 return E_NOINTERFACE
;
792 static ULONG WINAPI
IEnumMediaTypesImpl_AddRef(IEnumMediaTypes
* iface
)
794 IEnumMediaTypesImpl
*This
= impl_from_IEnumMediaTypes(iface
);
795 ULONG refCount
= InterlockedIncrement(&This
->refCount
);
800 static ULONG WINAPI
IEnumMediaTypesImpl_Release(IEnumMediaTypes
* iface
)
802 IEnumMediaTypesImpl
*This
= impl_from_IEnumMediaTypes(iface
);
803 ULONG refCount
= InterlockedDecrement(&This
->refCount
);
808 for (i
= 0; i
< This
->cMediaTypes
; i
++)
809 FreeMediaType(&This
->pMediaTypes
[i
]);
810 CoTaskMemFree(This
->pMediaTypes
);
816 static HRESULT WINAPI
IEnumMediaTypesImpl_Next(IEnumMediaTypes
* iface
, ULONG cMediaTypes
, AM_MEDIA_TYPE
** ppMediaTypes
, ULONG
* pcFetched
)
819 IEnumMediaTypesImpl
*This
= impl_from_IEnumMediaTypes(iface
);
821 cFetched
= min(This
->cMediaTypes
, This
->uIndex
+ cMediaTypes
) - This
->uIndex
;
826 for (i
= 0; i
< cFetched
; i
++)
827 if (!(ppMediaTypes
[i
] = CreateMediaType(&This
->pMediaTypes
[This
->uIndex
+ i
])))
830 DeleteMediaType(ppMediaTypes
[i
]);
832 return E_OUTOFMEMORY
;
836 if ((cMediaTypes
!= 1) || pcFetched
)
837 *pcFetched
= cFetched
;
839 This
->uIndex
+= cFetched
;
841 if (cFetched
!= cMediaTypes
)
846 static HRESULT WINAPI
IEnumMediaTypesImpl_Skip(IEnumMediaTypes
* iface
, ULONG cMediaTypes
)
848 IEnumMediaTypesImpl
*This
= impl_from_IEnumMediaTypes(iface
);
850 if (This
->uIndex
+ cMediaTypes
< This
->cMediaTypes
)
852 This
->uIndex
+= cMediaTypes
;
858 static HRESULT WINAPI
IEnumMediaTypesImpl_Reset(IEnumMediaTypes
* iface
)
860 IEnumMediaTypesImpl
*This
= impl_from_IEnumMediaTypes(iface
);
866 static HRESULT WINAPI
IEnumMediaTypesImpl_Clone(IEnumMediaTypes
* iface
, IEnumMediaTypes
** ppEnum
)
869 IEnumMediaTypesImpl
*This
= impl_from_IEnumMediaTypes(iface
);
871 hr
= IEnumMediaTypesImpl_Construct(This
->pMediaTypes
, This
->cMediaTypes
, ppEnum
);
874 return IEnumMediaTypes_Skip(*ppEnum
, This
->uIndex
);
877 static const IEnumMediaTypesVtbl IEnumMediaTypesImpl_Vtbl
=
879 IEnumMediaTypesImpl_QueryInterface
,
880 IEnumMediaTypesImpl_AddRef
,
881 IEnumMediaTypesImpl_Release
,
882 IEnumMediaTypesImpl_Next
,
883 IEnumMediaTypesImpl_Skip
,
884 IEnumMediaTypesImpl_Reset
,
885 IEnumMediaTypesImpl_Clone
888 /* Implementation of a very stripped down pin for the test filter. Just enough
889 functionality for connecting and Render() to work. */
891 static void Copy_PinInfo(PIN_INFO
* pDest
, const PIN_INFO
* pSrc
)
893 lstrcpyW(pDest
->achName
, pSrc
->achName
);
894 pDest
->dir
= pSrc
->dir
;
895 pDest
->pFilter
= pSrc
->pFilter
;
898 typedef struct ITestPinImpl
902 LPCRITICAL_SECTION pCritSec
;
905 AM_MEDIA_TYPE mtCurrent
;
909 static inline ITestPinImpl
*impl_from_IPin(IPin
*iface
)
911 return CONTAINING_RECORD(iface
, ITestPinImpl
, IPin_iface
);
914 static HRESULT WINAPI
TestFilter_Pin_QueryInterface(IPin
* iface
, REFIID riid
, LPVOID
* ppv
)
918 if (IsEqualIID(riid
, &IID_IUnknown
))
920 else if (IsEqualIID(riid
, &IID_IPin
))
925 IUnknown_AddRef((IUnknown
*)(*ppv
));
929 return E_NOINTERFACE
;
932 static ULONG WINAPI
TestFilter_Pin_AddRef(IPin
* iface
)
934 ITestPinImpl
*This
= impl_from_IPin(iface
);
935 ULONG refCount
= InterlockedIncrement(&This
->refCount
);
939 static ULONG WINAPI
TestFilter_Pin_Release(IPin
* iface
)
941 ITestPinImpl
*This
= impl_from_IPin(iface
);
942 ULONG refCount
= InterlockedDecrement(&This
->refCount
);
946 FreeMediaType(&This
->mtCurrent
);
954 static HRESULT WINAPI
TestFilter_InputPin_Connect(IPin
* iface
, IPin
* pConnector
, const AM_MEDIA_TYPE
* pmt
)
959 static HRESULT WINAPI
TestFilter_InputPin_ReceiveConnection(IPin
* iface
, IPin
* pReceivePin
, const AM_MEDIA_TYPE
* pmt
)
961 ITestPinImpl
*This
= impl_from_IPin(iface
);
962 PIN_DIRECTION pindirReceive
;
965 EnterCriticalSection(This
->pCritSec
);
967 if (!(IsEqualIID(&pmt
->majortype
, &This
->mtCurrent
.majortype
) && (IsEqualIID(&pmt
->subtype
, &This
->mtCurrent
.subtype
) ||
968 IsEqualIID(&GUID_NULL
, &This
->mtCurrent
.subtype
))))
969 hr
= VFW_E_TYPE_NOT_ACCEPTED
;
971 if (This
->pConnectedTo
)
972 hr
= VFW_E_ALREADY_CONNECTED
;
976 IPin_QueryDirection(pReceivePin
, &pindirReceive
);
978 if (pindirReceive
!= PINDIR_OUTPUT
)
980 hr
= VFW_E_INVALID_DIRECTION
;
986 CopyMediaType(&This
->mtCurrent
, pmt
);
987 This
->pConnectedTo
= pReceivePin
;
988 IPin_AddRef(pReceivePin
);
991 LeaveCriticalSection(This
->pCritSec
);
996 static HRESULT WINAPI
TestFilter_Pin_Disconnect(IPin
* iface
)
999 ITestPinImpl
*This
= impl_from_IPin(iface
);
1001 EnterCriticalSection(This
->pCritSec
);
1003 if (This
->pConnectedTo
)
1005 IPin_Release(This
->pConnectedTo
);
1006 This
->pConnectedTo
= NULL
;
1012 LeaveCriticalSection(This
->pCritSec
);
1017 static HRESULT WINAPI
TestFilter_Pin_ConnectedTo(IPin
* iface
, IPin
** ppPin
)
1020 ITestPinImpl
*This
= impl_from_IPin(iface
);
1022 EnterCriticalSection(This
->pCritSec
);
1024 if (This
->pConnectedTo
)
1026 *ppPin
= This
->pConnectedTo
;
1027 IPin_AddRef(*ppPin
);
1032 hr
= VFW_E_NOT_CONNECTED
;
1036 LeaveCriticalSection(This
->pCritSec
);
1041 static HRESULT WINAPI
TestFilter_Pin_ConnectionMediaType(IPin
* iface
, AM_MEDIA_TYPE
* pmt
)
1044 ITestPinImpl
*This
= impl_from_IPin(iface
);
1046 EnterCriticalSection(This
->pCritSec
);
1048 if (This
->pConnectedTo
)
1050 CopyMediaType(pmt
, &This
->mtCurrent
);
1055 ZeroMemory(pmt
, sizeof(*pmt
));
1056 hr
= VFW_E_NOT_CONNECTED
;
1059 LeaveCriticalSection(This
->pCritSec
);
1064 static HRESULT WINAPI
TestFilter_Pin_QueryPinInfo(IPin
* iface
, PIN_INFO
* pInfo
)
1066 ITestPinImpl
*This
= impl_from_IPin(iface
);
1068 Copy_PinInfo(pInfo
, &This
->pinInfo
);
1069 IBaseFilter_AddRef(pInfo
->pFilter
);
1074 static HRESULT WINAPI
TestFilter_Pin_QueryDirection(IPin
* iface
, PIN_DIRECTION
* pPinDir
)
1076 ITestPinImpl
*This
= impl_from_IPin(iface
);
1078 *pPinDir
= This
->pinInfo
.dir
;
1083 static HRESULT WINAPI
TestFilter_Pin_QueryId(IPin
* iface
, LPWSTR
* Id
)
1088 static HRESULT WINAPI
TestFilter_Pin_QueryAccept(IPin
* iface
, const AM_MEDIA_TYPE
* pmt
)
1090 ITestPinImpl
*This
= impl_from_IPin(iface
);
1092 if (IsEqualIID(&pmt
->majortype
, &This
->mtCurrent
.majortype
) && (IsEqualIID(&pmt
->subtype
, &This
->mtCurrent
.subtype
) ||
1093 IsEqualIID(&GUID_NULL
, &This
->mtCurrent
.subtype
)))
1096 return VFW_E_TYPE_NOT_ACCEPTED
;
1099 static HRESULT WINAPI
TestFilter_Pin_EnumMediaTypes(IPin
* iface
, IEnumMediaTypes
** ppEnum
)
1101 ITestPinImpl
*This
= impl_from_IPin(iface
);
1103 return IEnumMediaTypesImpl_Construct(&This
->mtCurrent
, 1, ppEnum
);
1106 static HRESULT WINAPI
TestFilter_Pin_QueryInternalConnections(IPin
* iface
, IPin
** apPin
, ULONG
* cPin
)
1111 static HRESULT WINAPI
TestFilter_Pin_BeginFlush(IPin
* iface
)
1116 static HRESULT WINAPI
TestFilter_Pin_EndFlush(IPin
* iface
)
1121 static HRESULT WINAPI
TestFilter_Pin_NewSegment(IPin
* iface
, REFERENCE_TIME tStart
, REFERENCE_TIME tStop
, double dRate
)
1126 static HRESULT WINAPI
TestFilter_Pin_EndOfStream(IPin
* iface
)
1131 static const IPinVtbl TestFilter_InputPin_Vtbl
=
1133 TestFilter_Pin_QueryInterface
,
1134 TestFilter_Pin_AddRef
,
1135 TestFilter_Pin_Release
,
1136 TestFilter_InputPin_Connect
,
1137 TestFilter_InputPin_ReceiveConnection
,
1138 TestFilter_Pin_Disconnect
,
1139 TestFilter_Pin_ConnectedTo
,
1140 TestFilter_Pin_ConnectionMediaType
,
1141 TestFilter_Pin_QueryPinInfo
,
1142 TestFilter_Pin_QueryDirection
,
1143 TestFilter_Pin_QueryId
,
1144 TestFilter_Pin_QueryAccept
,
1145 TestFilter_Pin_EnumMediaTypes
,
1146 TestFilter_Pin_QueryInternalConnections
,
1147 TestFilter_Pin_EndOfStream
,
1148 TestFilter_Pin_BeginFlush
,
1149 TestFilter_Pin_EndFlush
,
1150 TestFilter_Pin_NewSegment
1153 static HRESULT WINAPI
TestFilter_OutputPin_ReceiveConnection(IPin
* iface
, IPin
* pReceivePin
, const AM_MEDIA_TYPE
* pmt
)
1155 return E_UNEXPECTED
;
1158 /* Private helper function */
1159 static HRESULT
TestFilter_OutputPin_ConnectSpecific(ITestPinImpl
* This
, IPin
* pReceivePin
,
1160 const AM_MEDIA_TYPE
* pmt
)
1164 This
->pConnectedTo
= pReceivePin
;
1165 IPin_AddRef(pReceivePin
);
1167 hr
= IPin_ReceiveConnection(pReceivePin
, &This
->IPin_iface
, pmt
);
1171 IPin_Release(This
->pConnectedTo
);
1172 This
->pConnectedTo
= NULL
;
1178 static HRESULT WINAPI
TestFilter_OutputPin_Connect(IPin
* iface
, IPin
* pReceivePin
, const AM_MEDIA_TYPE
* pmt
)
1180 ITestPinImpl
*This
= impl_from_IPin(iface
);
1183 EnterCriticalSection(This
->pCritSec
);
1185 /* if we have been a specific type to connect with, then we can either connect
1186 * with that or fail. We cannot choose different AM_MEDIA_TYPE */
1187 if (pmt
&& !IsEqualGUID(&pmt
->majortype
, &GUID_NULL
) && !IsEqualGUID(&pmt
->subtype
, &GUID_NULL
))
1188 hr
= TestFilter_OutputPin_ConnectSpecific(This
, pReceivePin
, pmt
);
1191 if (( !pmt
|| CompareMediaTypes(pmt
, &This
->mtCurrent
, TRUE
) ) &&
1192 (TestFilter_OutputPin_ConnectSpecific(This
, pReceivePin
, &This
->mtCurrent
) == S_OK
))
1194 else hr
= VFW_E_NO_ACCEPTABLE_TYPES
;
1195 } /* if negotiate media type */
1196 } /* if succeeded */
1197 LeaveCriticalSection(This
->pCritSec
);
1202 static const IPinVtbl TestFilter_OutputPin_Vtbl
=
1204 TestFilter_Pin_QueryInterface
,
1205 TestFilter_Pin_AddRef
,
1206 TestFilter_Pin_Release
,
1207 TestFilter_OutputPin_Connect
,
1208 TestFilter_OutputPin_ReceiveConnection
,
1209 TestFilter_Pin_Disconnect
,
1210 TestFilter_Pin_ConnectedTo
,
1211 TestFilter_Pin_ConnectionMediaType
,
1212 TestFilter_Pin_QueryPinInfo
,
1213 TestFilter_Pin_QueryDirection
,
1214 TestFilter_Pin_QueryId
,
1215 TestFilter_Pin_QueryAccept
,
1216 TestFilter_Pin_EnumMediaTypes
,
1217 TestFilter_Pin_QueryInternalConnections
,
1218 TestFilter_Pin_EndOfStream
,
1219 TestFilter_Pin_BeginFlush
,
1220 TestFilter_Pin_EndFlush
,
1221 TestFilter_Pin_NewSegment
1224 static HRESULT
TestFilter_Pin_Construct(const IPinVtbl
*Pin_Vtbl
, const PIN_INFO
* pPinInfo
, AM_MEDIA_TYPE
*pinmt
,
1225 LPCRITICAL_SECTION pCritSec
, IPin
** ppPin
)
1227 ITestPinImpl
* pPinImpl
;
1231 pPinImpl
= CoTaskMemAlloc(sizeof(ITestPinImpl
));
1234 return E_OUTOFMEMORY
;
1236 pPinImpl
->refCount
= 1;
1237 pPinImpl
->pConnectedTo
= NULL
;
1238 pPinImpl
->pCritSec
= pCritSec
;
1239 Copy_PinInfo(&pPinImpl
->pinInfo
, pPinInfo
);
1240 pPinImpl
->mtCurrent
= *pinmt
;
1242 pPinImpl
->IPin_iface
.lpVtbl
= Pin_Vtbl
;
1244 *ppPin
= &pPinImpl
->IPin_iface
;
1248 /* IEnumPins implementation */
1250 typedef HRESULT (* FNOBTAINPIN
)(TestFilterImpl
*tf
, ULONG pos
, IPin
**pin
, DWORD
*lastsynctick
);
1252 typedef struct IEnumPinsImpl
1254 IEnumPins IEnumPins_iface
;
1257 TestFilterImpl
*base
;
1258 FNOBTAINPIN receive_pin
;
1262 static const struct IEnumPinsVtbl IEnumPinsImpl_Vtbl
;
1264 static inline IEnumPinsImpl
*impl_from_IEnumPins(IEnumPins
*iface
)
1266 return CONTAINING_RECORD(iface
, IEnumPinsImpl
, IEnumPins_iface
);
1269 static HRESULT
createenumpins(IEnumPins
** ppEnum
, FNOBTAINPIN receive_pin
, TestFilterImpl
*base
)
1271 IEnumPinsImpl
* pEnumPins
;
1276 pEnumPins
= CoTaskMemAlloc(sizeof(IEnumPinsImpl
));
1280 return E_OUTOFMEMORY
;
1282 pEnumPins
->IEnumPins_iface
.lpVtbl
= &IEnumPinsImpl_Vtbl
;
1283 pEnumPins
->refCount
= 1;
1284 pEnumPins
->uIndex
= 0;
1285 pEnumPins
->receive_pin
= receive_pin
;
1286 pEnumPins
->base
= base
;
1287 IBaseFilter_AddRef(&base
->IBaseFilter_iface
);
1288 *ppEnum
= &pEnumPins
->IEnumPins_iface
;
1290 receive_pin(base
, ~0, NULL
, &pEnumPins
->synctime
);
1295 static HRESULT WINAPI
IEnumPinsImpl_QueryInterface(IEnumPins
* iface
, REFIID riid
, LPVOID
* ppv
)
1299 if (IsEqualIID(riid
, &IID_IUnknown
))
1301 else if (IsEqualIID(riid
, &IID_IEnumPins
))
1306 IUnknown_AddRef((IUnknown
*)(*ppv
));
1310 return E_NOINTERFACE
;
1313 static ULONG WINAPI
IEnumPinsImpl_AddRef(IEnumPins
* iface
)
1315 IEnumPinsImpl
*This
= impl_from_IEnumPins(iface
);
1316 ULONG refCount
= InterlockedIncrement(&This
->refCount
);
1321 static ULONG WINAPI
IEnumPinsImpl_Release(IEnumPins
* iface
)
1323 IEnumPinsImpl
*This
= impl_from_IEnumPins(iface
);
1324 ULONG refCount
= InterlockedDecrement(&This
->refCount
);
1328 IBaseFilter_Release(&This
->base
->IBaseFilter_iface
);
1329 CoTaskMemFree(This
);
1336 static HRESULT WINAPI
IEnumPinsImpl_Next(IEnumPins
* iface
, ULONG cPins
, IPin
** ppPins
, ULONG
* pcFetched
)
1338 IEnumPinsImpl
*This
= impl_from_IEnumPins(iface
);
1339 DWORD synctime
= This
->synctime
;
1346 if (cPins
> 1 && !pcFetched
)
1347 return E_INVALIDARG
;
1352 while (i
< cPins
&& hr
== S_OK
)
1354 hr
= This
->receive_pin(This
->base
, This
->uIndex
+ i
, &ppPins
[i
], &synctime
);
1359 if (synctime
!= This
->synctime
)
1363 if (!i
&& synctime
!= This
->synctime
)
1364 return VFW_E_ENUM_OUT_OF_SYNC
;
1375 static HRESULT WINAPI
IEnumPinsImpl_Skip(IEnumPins
* iface
, ULONG cPins
)
1377 IEnumPinsImpl
*This
= impl_from_IEnumPins(iface
);
1378 DWORD synctime
= This
->synctime
;
1382 hr
= This
->receive_pin(This
->base
, This
->uIndex
+ cPins
, &pin
, &synctime
);
1386 if (synctime
!= This
->synctime
)
1387 return VFW_E_ENUM_OUT_OF_SYNC
;
1390 This
->uIndex
+= cPins
;
1395 static HRESULT WINAPI
IEnumPinsImpl_Reset(IEnumPins
* iface
)
1397 IEnumPinsImpl
*This
= impl_from_IEnumPins(iface
);
1399 This
->receive_pin(This
->base
, ~0, NULL
, &This
->synctime
);
1405 static HRESULT WINAPI
IEnumPinsImpl_Clone(IEnumPins
* iface
, IEnumPins
** ppEnum
)
1408 IEnumPinsImpl
*This
= impl_from_IEnumPins(iface
);
1410 hr
= createenumpins(ppEnum
, This
->receive_pin
, This
->base
);
1413 return IEnumPins_Skip(*ppEnum
, This
->uIndex
);
1416 static const IEnumPinsVtbl IEnumPinsImpl_Vtbl
=
1418 IEnumPinsImpl_QueryInterface
,
1419 IEnumPinsImpl_AddRef
,
1420 IEnumPinsImpl_Release
,
1423 IEnumPinsImpl_Reset
,
1427 /* Test filter implementation - a filter that has few predefined pins with single media type
1428 * that accept only this single media type. Enough for Render(). */
1430 typedef struct TestFilterPinData
1432 PIN_DIRECTION pinDir
;
1433 const GUID
*mediasubtype
;
1434 } TestFilterPinData
;
1436 static const IBaseFilterVtbl TestFilter_Vtbl
;
1438 static inline TestFilterImpl
*impl_from_IBaseFilter(IBaseFilter
*iface
)
1440 return CONTAINING_RECORD(iface
, TestFilterImpl
, IBaseFilter_iface
);
1443 static HRESULT
createtestfilter(const CLSID
* pClsid
, const TestFilterPinData
*pinData
,
1444 TestFilterImpl
**tf
)
1446 static const WCHAR wcsInputPinName
[] = {'i','n','p','u','t',' ','p','i','n',0};
1447 static const WCHAR wcsOutputPinName
[] = {'o','u','t','p','u','t',' ','p','i','n',0};
1450 TestFilterImpl
* pTestFilter
= NULL
;
1454 pTestFilter
= CoTaskMemAlloc(sizeof(TestFilterImpl
));
1455 if (!pTestFilter
) return E_OUTOFMEMORY
;
1457 pTestFilter
->clsid
= *pClsid
;
1458 pTestFilter
->IBaseFilter_iface
.lpVtbl
= &TestFilter_Vtbl
;
1459 pTestFilter
->refCount
= 1;
1460 InitializeCriticalSection(&pTestFilter
->csFilter
);
1461 pTestFilter
->state
= State_Stopped
;
1463 ZeroMemory(&pTestFilter
->filterInfo
, sizeof(FILTER_INFO
));
1466 while(pinData
[nPins
].mediasubtype
) ++nPins
;
1468 pTestFilter
->ppPins
= CoTaskMemAlloc(nPins
* sizeof(IPin
*));
1469 if (!pTestFilter
->ppPins
)
1474 ZeroMemory(pTestFilter
->ppPins
, nPins
* sizeof(IPin
*));
1476 for (i
= 0; i
< nPins
; i
++)
1478 ZeroMemory(&mt
, sizeof(mt
));
1479 mt
.majortype
= MEDIATYPE_Video
;
1480 mt
.formattype
= FORMAT_None
;
1481 mt
.subtype
= *pinData
[i
].mediasubtype
;
1483 pinInfo
.dir
= pinData
[i
].pinDir
;
1484 pinInfo
.pFilter
= &pTestFilter
->IBaseFilter_iface
;
1485 if (pinInfo
.dir
== PINDIR_INPUT
)
1487 lstrcpynW(pinInfo
.achName
, wcsInputPinName
, sizeof(pinInfo
.achName
) / sizeof(pinInfo
.achName
[0]));
1488 hr
= TestFilter_Pin_Construct(&TestFilter_InputPin_Vtbl
, &pinInfo
, &mt
, &pTestFilter
->csFilter
,
1489 &pTestFilter
->ppPins
[i
]);
1494 lstrcpynW(pinInfo
.achName
, wcsOutputPinName
, sizeof(pinInfo
.achName
) / sizeof(pinInfo
.achName
[0]));
1495 hr
= TestFilter_Pin_Construct(&TestFilter_OutputPin_Vtbl
, &pinInfo
, &mt
, &pTestFilter
->csFilter
,
1496 &pTestFilter
->ppPins
[i
]);
1498 if (FAILED(hr
) || !pTestFilter
->ppPins
[i
]) goto error
;
1501 pTestFilter
->nPins
= nPins
;
1507 if (pTestFilter
->ppPins
)
1509 for (i
= 0; i
< nPins
; i
++)
1511 if (pTestFilter
->ppPins
[i
]) IPin_Release(pTestFilter
->ppPins
[i
]);
1514 CoTaskMemFree(pTestFilter
->ppPins
);
1515 DeleteCriticalSection(&pTestFilter
->csFilter
);
1516 CoTaskMemFree(pTestFilter
);
1521 static HRESULT WINAPI
TestFilter_QueryInterface(IBaseFilter
* iface
, REFIID riid
, LPVOID
* ppv
)
1523 TestFilterImpl
*This
= impl_from_IBaseFilter(iface
);
1527 if (IsEqualIID(riid
, &IID_IUnknown
))
1529 else if (IsEqualIID(riid
, &IID_IPersist
))
1531 else if (IsEqualIID(riid
, &IID_IMediaFilter
))
1533 else if (IsEqualIID(riid
, &IID_IBaseFilter
))
1538 IUnknown_AddRef((IUnknown
*)(*ppv
));
1542 return E_NOINTERFACE
;
1545 static ULONG WINAPI
TestFilter_AddRef(IBaseFilter
* iface
)
1547 TestFilterImpl
*This
= impl_from_IBaseFilter(iface
);
1548 ULONG refCount
= InterlockedIncrement(&This
->refCount
);
1553 static ULONG WINAPI
TestFilter_Release(IBaseFilter
* iface
)
1555 TestFilterImpl
*This
= impl_from_IBaseFilter(iface
);
1556 ULONG refCount
= InterlockedDecrement(&This
->refCount
);
1562 for (i
= 0; i
< This
->nPins
; i
++)
1566 if (SUCCEEDED(IPin_ConnectedTo(This
->ppPins
[i
], &pConnectedTo
)))
1568 IPin_Disconnect(pConnectedTo
);
1569 IPin_Release(pConnectedTo
);
1571 IPin_Disconnect(This
->ppPins
[i
]);
1573 IPin_Release(This
->ppPins
[i
]);
1576 CoTaskMemFree(This
->ppPins
);
1578 DeleteCriticalSection(&This
->csFilter
);
1580 CoTaskMemFree(This
);
1587 /** IPersist methods **/
1589 static HRESULT WINAPI
TestFilter_GetClassID(IBaseFilter
* iface
, CLSID
* pClsid
)
1591 TestFilterImpl
*This
= impl_from_IBaseFilter(iface
);
1593 *pClsid
= This
->clsid
;
1598 /** IMediaFilter methods **/
1600 static HRESULT WINAPI
TestFilter_Stop(IBaseFilter
* iface
)
1605 static HRESULT WINAPI
TestFilter_Pause(IBaseFilter
* iface
)
1610 static HRESULT WINAPI
TestFilter_Run(IBaseFilter
* iface
, REFERENCE_TIME tStart
)
1615 static HRESULT WINAPI
TestFilter_GetState(IBaseFilter
* iface
, DWORD dwMilliSecsTimeout
, FILTER_STATE
*pState
)
1617 TestFilterImpl
*This
= impl_from_IBaseFilter(iface
);
1619 EnterCriticalSection(&This
->csFilter
);
1621 *pState
= This
->state
;
1623 LeaveCriticalSection(&This
->csFilter
);
1628 static HRESULT WINAPI
TestFilter_SetSyncSource(IBaseFilter
* iface
, IReferenceClock
*pClock
)
1633 static HRESULT WINAPI
TestFilter_GetSyncSource(IBaseFilter
* iface
, IReferenceClock
**ppClock
)
1638 /** IBaseFilter implementation **/
1640 static HRESULT
getpin_callback(TestFilterImpl
*tf
, ULONG pos
, IPin
**pin
, DWORD
*lastsynctick
)
1642 /* Our pins are static, not changing so setting static tick count is ok */
1645 if (pos
>= tf
->nPins
)
1648 *pin
= tf
->ppPins
[pos
];
1653 static HRESULT WINAPI
TestFilter_EnumPins(IBaseFilter
* iface
, IEnumPins
**ppEnum
)
1655 TestFilterImpl
*This
= impl_from_IBaseFilter(iface
);
1657 return createenumpins(ppEnum
, getpin_callback
, This
);
1660 static HRESULT WINAPI
TestFilter_FindPin(IBaseFilter
* iface
, LPCWSTR Id
, IPin
**ppPin
)
1665 static HRESULT WINAPI
TestFilter_QueryFilterInfo(IBaseFilter
* iface
, FILTER_INFO
*pInfo
)
1667 TestFilterImpl
*This
= impl_from_IBaseFilter(iface
);
1669 lstrcpyW(pInfo
->achName
, This
->filterInfo
.achName
);
1670 pInfo
->pGraph
= This
->filterInfo
.pGraph
;
1673 IFilterGraph_AddRef(pInfo
->pGraph
);
1678 static HRESULT WINAPI
TestFilter_JoinFilterGraph(IBaseFilter
* iface
, IFilterGraph
*pGraph
, LPCWSTR pName
)
1681 TestFilterImpl
*This
= impl_from_IBaseFilter(iface
);
1683 EnterCriticalSection(&This
->csFilter
);
1686 lstrcpyW(This
->filterInfo
.achName
, pName
);
1688 *This
->filterInfo
.achName
= '\0';
1689 This
->filterInfo
.pGraph
= pGraph
; /* NOTE: do NOT increase ref. count */
1691 LeaveCriticalSection(&This
->csFilter
);
1696 static HRESULT WINAPI
TestFilter_QueryVendorInfo(IBaseFilter
* iface
, LPWSTR
*pVendorInfo
)
1701 static const IBaseFilterVtbl TestFilter_Vtbl
=
1703 TestFilter_QueryInterface
,
1706 TestFilter_GetClassID
,
1710 TestFilter_GetState
,
1711 TestFilter_SetSyncSource
,
1712 TestFilter_GetSyncSource
,
1713 TestFilter_EnumPins
,
1715 TestFilter_QueryFilterInfo
,
1716 TestFilter_JoinFilterGraph
,
1717 TestFilter_QueryVendorInfo
1720 /* IClassFactory implementation */
1722 typedef struct TestClassFactoryImpl
1724 IClassFactory IClassFactory_iface
;
1725 const TestFilterPinData
*filterPinData
;
1727 } TestClassFactoryImpl
;
1729 static inline TestClassFactoryImpl
*impl_from_IClassFactory(IClassFactory
*iface
)
1731 return CONTAINING_RECORD(iface
, TestClassFactoryImpl
, IClassFactory_iface
);
1734 static HRESULT WINAPI
Test_IClassFactory_QueryInterface(
1735 LPCLASSFACTORY iface
,
1739 if (ppvObj
== NULL
) return E_POINTER
;
1741 if (IsEqualGUID(riid
, &IID_IUnknown
) ||
1742 IsEqualGUID(riid
, &IID_IClassFactory
))
1745 IClassFactory_AddRef(iface
);
1750 return E_NOINTERFACE
;
1753 static ULONG WINAPI
Test_IClassFactory_AddRef(LPCLASSFACTORY iface
)
1755 return 2; /* non-heap-based object */
1758 static ULONG WINAPI
Test_IClassFactory_Release(LPCLASSFACTORY iface
)
1760 return 1; /* non-heap-based object */
1763 static HRESULT WINAPI
Test_IClassFactory_CreateInstance(
1764 LPCLASSFACTORY iface
,
1765 LPUNKNOWN pUnkOuter
,
1769 TestClassFactoryImpl
*This
= impl_from_IClassFactory(iface
);
1771 TestFilterImpl
*testfilter
;
1775 if (pUnkOuter
) return CLASS_E_NOAGGREGATION
;
1777 hr
= createtestfilter(This
->clsid
, This
->filterPinData
, &testfilter
);
1778 if (SUCCEEDED(hr
)) {
1779 hr
= IBaseFilter_QueryInterface(&testfilter
->IBaseFilter_iface
, riid
, ppvObj
);
1780 IBaseFilter_Release(&testfilter
->IBaseFilter_iface
);
1785 static HRESULT WINAPI
Test_IClassFactory_LockServer(
1786 LPCLASSFACTORY iface
,
1792 static IClassFactoryVtbl TestClassFactory_Vtbl
=
1794 Test_IClassFactory_QueryInterface
,
1795 Test_IClassFactory_AddRef
,
1796 Test_IClassFactory_Release
,
1797 Test_IClassFactory_CreateInstance
,
1798 Test_IClassFactory_LockServer
1801 static HRESULT
get_connected_filter_name(TestFilterImpl
*pFilter
, char *FilterName
)
1805 FILTER_INFO filterInfo
;
1810 hr
= IPin_ConnectedTo(pFilter
->ppPins
[0], &pin
);
1811 ok(hr
== S_OK
, "IPin_ConnectedTo failed with %x\n", hr
);
1812 if (FAILED(hr
)) return hr
;
1814 hr
= IPin_QueryPinInfo(pin
, &pinInfo
);
1815 ok(hr
== S_OK
, "IPin_QueryPinInfo failed with %x\n", hr
);
1817 if (FAILED(hr
)) return hr
;
1819 SetLastError(0xdeadbeef);
1820 hr
= IBaseFilter_QueryFilterInfo(pinInfo
.pFilter
, &filterInfo
);
1821 if (hr
== S_OK
&& GetLastError() == ERROR_CALL_NOT_IMPLEMENTED
)
1823 IBaseFilter_Release(pinInfo
.pFilter
);
1826 ok(hr
== S_OK
, "IBaseFilter_QueryFilterInfo failed with %x\n", hr
);
1827 IBaseFilter_Release(pinInfo
.pFilter
);
1828 if (FAILED(hr
)) return hr
;
1830 IFilterGraph_Release(filterInfo
.pGraph
);
1832 WideCharToMultiByte(CP_ACP
, 0, filterInfo
.achName
, -1, FilterName
, MAX_FILTER_NAME
, NULL
, NULL
);
1837 static void test_render_filter_priority(void)
1839 /* Tests filter choice priorities in Render(). */
1840 DWORD cookie1
= 0, cookie2
= 0, cookie3
= 0;
1842 IFilterGraph2
* pgraph2
= NULL
;
1843 IFilterMapper2
*pMapper2
= NULL
;
1844 TestFilterImpl
*ptestfilter
= NULL
;
1845 TestFilterImpl
*ptestfilter2
= NULL
;
1846 static const CLSID CLSID_TestFilter2
= {
1850 {0xe8, 0x9b, 0x00, 0x19, 0x66, 0x2f, 0xf0, 0xce}
1852 static const CLSID CLSID_TestFilter3
= {
1856 {0xe8, 0x9b, 0x00, 0x19, 0x66, 0x2f, 0xf0, 0xce}
1858 static const CLSID CLSID_TestFilter4
= {
1862 {0xe8, 0x9b, 0x00, 0x19, 0x66, 0x2f, 0xf0, 0xce}
1864 static const GUID mediasubtype1
= {
1868 {0xe8, 0x9b, 0x00, 0x19, 0x66, 0x2f, 0xf0, 0xce}
1870 static const GUID mediasubtype2
= {
1874 {0xe8, 0x9b, 0x00, 0x19, 0x66, 0x2f, 0xf0, 0xce}
1876 static const TestFilterPinData PinData1
[] = {
1877 { PINDIR_OUTPUT
, &mediasubtype1
},
1880 static const TestFilterPinData PinData2
[] = {
1881 { PINDIR_INPUT
, &mediasubtype1
},
1884 static const TestFilterPinData PinData3
[] = {
1885 { PINDIR_INPUT
, &GUID_NULL
},
1888 static const TestFilterPinData PinData4
[] = {
1889 { PINDIR_INPUT
, &mediasubtype1
},
1890 { PINDIR_OUTPUT
, &mediasubtype2
},
1893 static const TestFilterPinData PinData5
[] = {
1894 { PINDIR_INPUT
, &mediasubtype2
},
1897 TestClassFactoryImpl Filter1ClassFactory
= {
1898 { &TestClassFactory_Vtbl
},
1899 PinData2
, &CLSID_TestFilter2
1901 TestClassFactoryImpl Filter2ClassFactory
= {
1902 { &TestClassFactory_Vtbl
},
1903 PinData4
, &CLSID_TestFilter3
1905 TestClassFactoryImpl Filter3ClassFactory
= {
1906 { &TestClassFactory_Vtbl
},
1907 PinData5
, &CLSID_TestFilter4
1909 char ConnectedFilterName1
[MAX_FILTER_NAME
];
1910 char ConnectedFilterName2
[MAX_FILTER_NAME
];
1912 REGFILTERPINS2 rgPins2
[2];
1913 REGPINTYPES rgPinType
[2];
1914 static const WCHAR wszFilterInstanceName1
[] = {'T', 'e', 's', 't', 'f', 'i', 'l', 't', 'e', 'r', 'I',
1915 'n', 's', 't', 'a', 'n', 'c', 'e', '1', 0 };
1916 static const WCHAR wszFilterInstanceName2
[] = {'T', 'e', 's', 't', 'f', 'i', 'l', 't', 'e', 'r', 'I',
1917 'n', 's', 't', 'a', 'n', 'c', 'e', '2', 0 };
1918 static const WCHAR wszFilterInstanceName3
[] = {'T', 'e', 's', 't', 'f', 'i', 'l', 't', 'e', 'r', 'I',
1919 'n', 's', 't', 'a', 'n', 'c', 'e', '3', 0 };
1920 static const WCHAR wszFilterInstanceName4
[] = {'T', 'e', 's', 't', 'f', 'i', 'l', 't', 'e', 'r', 'I',
1921 'n', 's', 't', 'a', 'n', 'c', 'e', '4', 0 };
1923 /* Test which renderer of two already added to the graph will be chosen
1924 * (one is "exact" match, other is "wildcard" match. Seems to depend
1925 * on the order in which filters are added to the graph, thus indicating
1926 * no preference given to exact match. */
1927 hr
= CoCreateInstance(&CLSID_FilterGraph
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IFilterGraph2
, (LPVOID
*)&pgraph2
);
1928 ok(hr
== S_OK
, "CoCreateInstance failed with %08x\n", hr
);
1929 if (!pgraph2
) return;
1931 hr
= createtestfilter(&GUID_NULL
, PinData1
, &ptestfilter
);
1932 ok(hr
== S_OK
, "createtestfilter failed with %08x\n", hr
);
1933 if (FAILED(hr
)) goto out
;
1935 hr
= IFilterGraph2_AddFilter(pgraph2
, &ptestfilter
->IBaseFilter_iface
, wszFilterInstanceName1
);
1936 ok(hr
== S_OK
, "IFilterGraph2_AddFilter failed with %08x\n", hr
);
1938 hr
= createtestfilter(&GUID_NULL
, PinData2
, &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
, wszFilterInstanceName2
);
1943 ok(hr
== S_OK
, "IFilterGraph2_AddFilter failed with %08x\n", hr
);
1945 IBaseFilter_Release(&ptestfilter2
->IBaseFilter_iface
);
1946 ptestfilter2
= NULL
;
1948 hr
= createtestfilter(&GUID_NULL
, PinData3
, &ptestfilter2
);
1949 ok(hr
== S_OK
, "createtestfilter failed with %08x\n", hr
);
1950 if (FAILED(hr
)) goto out
;
1952 hr
= IFilterGraph2_AddFilter(pgraph2
, &ptestfilter2
->IBaseFilter_iface
, wszFilterInstanceName3
);
1953 ok(hr
== S_OK
, "IFilterGraph2_AddFilter failed with %08x\n", hr
);
1955 hr
= IFilterGraph2_Render(pgraph2
, ptestfilter
->ppPins
[0]);
1956 ok(hr
== S_OK
, "IFilterGraph2_Render failed with %08x\n", hr
);
1958 hr
= get_connected_filter_name(ptestfilter
, ConnectedFilterName1
);
1960 IFilterGraph2_Release(pgraph2
);
1962 IBaseFilter_Release(&ptestfilter
->IBaseFilter_iface
);
1964 IBaseFilter_Release(&ptestfilter2
->IBaseFilter_iface
);
1965 ptestfilter2
= NULL
;
1967 if (hr
== E_NOTIMPL
)
1969 win_skip("Needed functions are not implemented\n");
1973 hr
= CoCreateInstance(&CLSID_FilterGraph
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IFilterGraph2
, (LPVOID
*)&pgraph2
);
1974 ok(hr
== S_OK
, "CoCreateInstance failed with %08x\n", hr
);
1975 if (!pgraph2
) goto out
;
1977 hr
= createtestfilter(&GUID_NULL
, PinData1
, &ptestfilter
);
1978 ok(hr
== S_OK
, "createtestfilter failed with %08x\n", hr
);
1979 if (FAILED(hr
)) goto out
;
1981 hr
= IFilterGraph2_AddFilter(pgraph2
, &ptestfilter
->IBaseFilter_iface
, wszFilterInstanceName1
);
1982 ok(hr
== S_OK
, "IFilterGraph2_AddFilter failed with %08x\n", hr
);
1984 hr
= createtestfilter(&GUID_NULL
, PinData3
, &ptestfilter2
);
1985 ok(hr
== S_OK
, "createtestfilter failed with %08x\n", hr
);
1986 if (FAILED(hr
)) goto out
;
1988 hr
= IFilterGraph2_AddFilter(pgraph2
, &ptestfilter2
->IBaseFilter_iface
, wszFilterInstanceName3
);
1989 ok(hr
== S_OK
, "IFilterGraph2_AddFilter failed with %08x\n", hr
);
1991 IBaseFilter_Release(&ptestfilter2
->IBaseFilter_iface
);
1992 ptestfilter2
= NULL
;
1994 hr
= createtestfilter(&GUID_NULL
, PinData2
, &ptestfilter2
);
1995 ok(hr
== S_OK
, "createtestfilter failed with %08x\n", hr
);
1996 if (FAILED(hr
)) goto out
;
1998 hr
= IFilterGraph2_AddFilter(pgraph2
, &ptestfilter2
->IBaseFilter_iface
, wszFilterInstanceName2
);
1999 ok(hr
== S_OK
, "IFilterGraph2_AddFilter failed with %08x\n", hr
);
2001 hr
= IFilterGraph2_Render(pgraph2
, ptestfilter
->ppPins
[0]);
2002 ok(hr
== S_OK
, "IFilterGraph2_Render failed with %08x\n", hr
);
2004 hr
= IFilterGraph2_Disconnect(pgraph2
, NULL
);
2005 ok(hr
== E_POINTER
, "IFilterGraph2_Disconnect failed. Expected E_POINTER, received %08x\n", hr
);
2007 get_connected_filter_name(ptestfilter
, ConnectedFilterName2
);
2008 ok(strcmp(ConnectedFilterName1
, ConnectedFilterName2
),
2009 "expected connected filters to be different but got %s both times\n", ConnectedFilterName1
);
2011 IFilterGraph2_Release(pgraph2
);
2013 IBaseFilter_Release(&ptestfilter
->IBaseFilter_iface
);
2015 IBaseFilter_Release(&ptestfilter2
->IBaseFilter_iface
);
2016 ptestfilter2
= NULL
;
2018 /* Test if any preference is given to existing renderer which renders the pin directly vs
2019 an existing renderer which renders the pin indirectly, through an additional middle filter,
2020 again trying different orders of creation. Native appears not to give a preference. */
2022 hr
= CoCreateInstance(&CLSID_FilterGraph
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IFilterGraph2
, (LPVOID
*)&pgraph2
);
2023 ok(hr
== S_OK
, "CoCreateInstance failed with %08x\n", hr
);
2024 if (!pgraph2
) goto out
;
2026 hr
= createtestfilter(&GUID_NULL
, PinData1
, &ptestfilter
);
2027 ok(hr
== S_OK
, "createtestfilter failed with %08x\n", hr
);
2028 if (FAILED(hr
)) goto out
;
2030 hr
= IFilterGraph2_AddFilter(pgraph2
, &ptestfilter
->IBaseFilter_iface
, wszFilterInstanceName1
);
2031 ok(hr
== S_OK
, "IFilterGraph2_AddFilter failed with %08x\n", hr
);
2033 hr
= createtestfilter(&GUID_NULL
, PinData2
, &ptestfilter2
);
2034 ok(hr
== S_OK
, "createtestfilter failed with %08x\n", hr
);
2035 if (FAILED(hr
)) goto out
;
2037 hr
= IFilterGraph2_AddFilter(pgraph2
, &ptestfilter2
->IBaseFilter_iface
, wszFilterInstanceName2
);
2038 ok(hr
== S_OK
, "IFilterGraph2_AddFilter failed with %08x\n", hr
);
2040 IBaseFilter_Release(&ptestfilter2
->IBaseFilter_iface
);
2041 ptestfilter2
= NULL
;
2043 hr
= createtestfilter(&GUID_NULL
, PinData4
, &ptestfilter2
);
2044 ok(hr
== S_OK
, "createtestfilter failed with %08x\n", hr
);
2045 if (FAILED(hr
)) goto out
;
2047 hr
= IFilterGraph2_AddFilter(pgraph2
, &ptestfilter2
->IBaseFilter_iface
, wszFilterInstanceName3
);
2048 ok(hr
== S_OK
, "IFilterGraph2_AddFilter failed with %08x\n", hr
);
2050 IBaseFilter_Release(&ptestfilter2
->IBaseFilter_iface
);
2051 ptestfilter2
= NULL
;
2053 hr
= createtestfilter(&GUID_NULL
, PinData5
, &ptestfilter2
);
2054 ok(hr
== S_OK
, "createtestfilter failed with %08x\n", hr
);
2055 if (FAILED(hr
)) goto out
;
2057 hr
= IFilterGraph2_AddFilter(pgraph2
, &ptestfilter2
->IBaseFilter_iface
, wszFilterInstanceName4
);
2058 ok(hr
== S_OK
, "IFilterGraph2_AddFilter failed with %08x\n", hr
);
2060 hr
= IFilterGraph2_Render(pgraph2
, ptestfilter
->ppPins
[0]);
2061 ok(hr
== S_OK
, "IFilterGraph2_Render failed with %08x\n", hr
);
2063 get_connected_filter_name(ptestfilter
, ConnectedFilterName1
);
2064 ok(!strcmp(ConnectedFilterName1
, "TestfilterInstance3") || !strcmp(ConnectedFilterName1
, "TestfilterInstance2"),
2065 "unexpected connected filter: %s\n", ConnectedFilterName1
);
2067 IFilterGraph2_Release(pgraph2
);
2069 IBaseFilter_Release(&ptestfilter
->IBaseFilter_iface
);
2071 IBaseFilter_Release(&ptestfilter2
->IBaseFilter_iface
);
2072 ptestfilter2
= NULL
;
2074 hr
= CoCreateInstance(&CLSID_FilterGraph
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IFilterGraph2
, (LPVOID
*)&pgraph2
);
2075 ok(hr
== S_OK
, "CoCreateInstance failed with %08x\n", hr
);
2076 if (!pgraph2
) goto out
;
2078 hr
= createtestfilter(&GUID_NULL
, PinData1
, &ptestfilter
);
2079 ok(hr
== S_OK
, "createtestfilter failed with %08x\n", hr
);
2080 if (FAILED(hr
)) goto out
;
2082 hr
= IFilterGraph2_AddFilter(pgraph2
, &ptestfilter
->IBaseFilter_iface
, wszFilterInstanceName1
);
2083 ok(hr
== S_OK
, "IFilterGraph2_AddFilter failed with %08x\n", hr
);
2085 hr
= createtestfilter(&GUID_NULL
, PinData4
, &ptestfilter2
);
2086 ok(hr
== S_OK
, "createtestfilter failed with %08x\n", hr
);
2087 if (FAILED(hr
)) goto out
;
2089 hr
= IFilterGraph2_AddFilter(pgraph2
, &ptestfilter2
->IBaseFilter_iface
, wszFilterInstanceName3
);
2090 ok(hr
== S_OK
, "IFilterGraph2_AddFilter failed with %08x\n", hr
);
2092 IBaseFilter_Release(&ptestfilter2
->IBaseFilter_iface
);
2093 ptestfilter2
= NULL
;
2095 hr
= createtestfilter(&GUID_NULL
, PinData5
, &ptestfilter2
);
2096 ok(hr
== S_OK
, "createtestfilter failed with %08x\n", hr
);
2097 if (FAILED(hr
)) goto out
;
2099 hr
= IFilterGraph2_AddFilter(pgraph2
, &ptestfilter2
->IBaseFilter_iface
, wszFilterInstanceName4
);
2100 ok(hr
== S_OK
, "IFilterGraph2_AddFilter failed with %08x\n", hr
);
2102 IBaseFilter_Release(&ptestfilter2
->IBaseFilter_iface
);
2103 ptestfilter2
= NULL
;
2105 hr
= createtestfilter(&GUID_NULL
, PinData2
, &ptestfilter2
);
2106 ok(hr
== S_OK
, "createtestfilter failed with %08x\n", hr
);
2107 if (FAILED(hr
)) goto out
;
2109 hr
= IFilterGraph2_AddFilter(pgraph2
, &ptestfilter2
->IBaseFilter_iface
, wszFilterInstanceName2
);
2110 ok(hr
== S_OK
, "IFilterGraph2_AddFilter failed with %08x\n", hr
);
2112 hr
= IFilterGraph2_Render(pgraph2
, ptestfilter
->ppPins
[0]);
2113 ok(hr
== S_OK
, "IFilterGraph2_Render failed with %08x\n", hr
);
2115 get_connected_filter_name(ptestfilter
, ConnectedFilterName2
);
2116 ok(!strcmp(ConnectedFilterName2
, "TestfilterInstance3") || !strcmp(ConnectedFilterName2
, "TestfilterInstance2"),
2117 "unexpected connected filter: %s\n", ConnectedFilterName2
);
2118 ok(strcmp(ConnectedFilterName1
, ConnectedFilterName2
),
2119 "expected connected filters to be different but got %s both times\n", ConnectedFilterName1
);
2121 IFilterGraph2_Release(pgraph2
);
2123 IBaseFilter_Release(&ptestfilter
->IBaseFilter_iface
);
2125 IBaseFilter_Release(&ptestfilter2
->IBaseFilter_iface
);
2126 ptestfilter2
= NULL
;
2128 /* Test if renderers are tried before non-renderers (intermediary filters). */
2129 hr
= CoCreateInstance(&CLSID_FilterGraph
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IFilterGraph2
, (LPVOID
*)&pgraph2
);
2130 ok(hr
== S_OK
, "CoCreateInstance failed with %08x\n", hr
);
2131 if (!pgraph2
) goto out
;
2133 hr
= CoCreateInstance(&CLSID_FilterMapper2
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IFilterMapper2
, (LPVOID
*)&pMapper2
);
2134 ok(hr
== S_OK
, "CoCreateInstance failed with %08x\n", hr
);
2135 if (!pMapper2
) goto out
;
2137 hr
= createtestfilter(&GUID_NULL
, PinData1
, &ptestfilter
);
2138 ok(hr
== S_OK
, "createtestfilter failed with %08x\n", hr
);
2139 if (FAILED(hr
)) goto out
;
2141 hr
= IFilterGraph2_AddFilter(pgraph2
, &ptestfilter
->IBaseFilter_iface
, wszFilterInstanceName1
);
2142 ok(hr
== S_OK
, "IFilterGraph2_AddFilter failed with %08x\n", hr
);
2144 /* Register our filters with COM and with Filtermapper. */
2145 hr
= CoRegisterClassObject(Filter1ClassFactory
.clsid
,
2146 (IUnknown
*)&Filter1ClassFactory
.IClassFactory_iface
, CLSCTX_INPROC_SERVER
,
2147 REGCLS_MULTIPLEUSE
, &cookie1
);
2148 ok(hr
== S_OK
, "CoRegisterClassObject failed with %08x\n", hr
);
2149 if (FAILED(hr
)) goto out
;
2150 hr
= CoRegisterClassObject(Filter2ClassFactory
.clsid
,
2151 (IUnknown
*)&Filter2ClassFactory
.IClassFactory_iface
, CLSCTX_INPROC_SERVER
,
2152 REGCLS_MULTIPLEUSE
, &cookie2
);
2153 ok(hr
== S_OK
, "CoRegisterClassObject failed with %08x\n", hr
);
2154 if (FAILED(hr
)) goto out
;
2155 hr
= CoRegisterClassObject(Filter3ClassFactory
.clsid
,
2156 (IUnknown
*)&Filter3ClassFactory
.IClassFactory_iface
, CLSCTX_INPROC_SERVER
,
2157 REGCLS_MULTIPLEUSE
, &cookie3
);
2158 ok(hr
== S_OK
, "CoRegisterClassObject failed with %08x\n", hr
);
2159 if (FAILED(hr
)) goto out
;
2162 rgf2
.dwMerit
= MERIT_UNLIKELY
;
2163 S2(U(rgf2
)).cPins2
= 1;
2164 S2(U(rgf2
)).rgPins2
= rgPins2
;
2165 rgPins2
[0].dwFlags
= REG_PINFLAG_B_RENDERER
;
2166 rgPins2
[0].cInstances
= 1;
2167 rgPins2
[0].nMediaTypes
= 1;
2168 rgPins2
[0].lpMediaType
= &rgPinType
[0];
2169 rgPins2
[0].nMediums
= 0;
2170 rgPins2
[0].lpMedium
= NULL
;
2171 rgPins2
[0].clsPinCategory
= NULL
;
2172 rgPinType
[0].clsMajorType
= &MEDIATYPE_Video
;
2173 rgPinType
[0].clsMinorType
= &mediasubtype1
;
2175 hr
= IFilterMapper2_RegisterFilter(pMapper2
, &CLSID_TestFilter2
, wszFilterInstanceName2
, NULL
,
2176 &CLSID_LegacyAmFilterCategory
, NULL
, &rgf2
);
2177 if (hr
== E_ACCESSDENIED
)
2178 skip("Not authorized to register filters\n");
2181 ok(hr
== S_OK
, "IFilterMapper2_RegisterFilter failed with %x\n", hr
);
2183 rgf2
.dwMerit
= MERIT_PREFERRED
;
2184 rgPinType
[0].clsMinorType
= &mediasubtype2
;
2186 hr
= IFilterMapper2_RegisterFilter(pMapper2
, &CLSID_TestFilter4
, wszFilterInstanceName4
, NULL
,
2187 &CLSID_LegacyAmFilterCategory
, NULL
, &rgf2
);
2188 ok(hr
== S_OK
, "IFilterMapper2_RegisterFilter failed with %x\n", hr
);
2190 S2(U(rgf2
)).cPins2
= 2;
2191 rgPins2
[0].dwFlags
= 0;
2192 rgPinType
[0].clsMinorType
= &mediasubtype1
;
2194 rgPins2
[1].dwFlags
= REG_PINFLAG_B_OUTPUT
;
2195 rgPins2
[1].cInstances
= 1;
2196 rgPins2
[1].nMediaTypes
= 1;
2197 rgPins2
[1].lpMediaType
= &rgPinType
[1];
2198 rgPins2
[1].nMediums
= 0;
2199 rgPins2
[1].lpMedium
= NULL
;
2200 rgPins2
[1].clsPinCategory
= NULL
;
2201 rgPinType
[1].clsMajorType
= &MEDIATYPE_Video
;
2202 rgPinType
[1].clsMinorType
= &mediasubtype2
;
2204 hr
= IFilterMapper2_RegisterFilter(pMapper2
, &CLSID_TestFilter3
, wszFilterInstanceName3
, NULL
,
2205 &CLSID_LegacyAmFilterCategory
, NULL
, &rgf2
);
2206 ok(hr
== S_OK
, "IFilterMapper2_RegisterFilter failed with %x\n", hr
);
2208 hr
= IFilterGraph2_Render(pgraph2
, ptestfilter
->ppPins
[0]);
2209 ok(hr
== S_OK
, "IFilterGraph2_Render failed with %08x\n", hr
);
2211 get_connected_filter_name(ptestfilter
, ConnectedFilterName1
);
2212 ok(!strcmp(ConnectedFilterName1
, "TestfilterInstance3"),
2213 "unexpected connected filter: %s\n", ConnectedFilterName1
);
2215 hr
= IFilterMapper2_UnregisterFilter(pMapper2
, &CLSID_LegacyAmFilterCategory
, NULL
,
2216 &CLSID_TestFilter2
);
2217 ok(hr
== S_OK
, "IFilterMapper2_UnregisterFilter failed with %x\n", hr
);
2218 hr
= IFilterMapper2_UnregisterFilter(pMapper2
, &CLSID_LegacyAmFilterCategory
, NULL
,
2219 &CLSID_TestFilter3
);
2220 ok(hr
== S_OK
, "IFilterMapper2_UnregisterFilter failed with %x\n", hr
);
2221 hr
= IFilterMapper2_UnregisterFilter(pMapper2
, &CLSID_LegacyAmFilterCategory
, NULL
,
2222 &CLSID_TestFilter4
);
2223 ok(hr
== S_OK
, "IFilterMapper2_UnregisterFilter failed with %x\n", hr
);
2228 if (ptestfilter
) IBaseFilter_Release(&ptestfilter
->IBaseFilter_iface
);
2229 if (ptestfilter2
) IBaseFilter_Release(&ptestfilter2
->IBaseFilter_iface
);
2230 if (pgraph2
) IFilterGraph2_Release(pgraph2
);
2231 if (pMapper2
) IFilterMapper2_Release(pMapper2
);
2233 hr
= CoRevokeClassObject(cookie1
);
2234 ok(hr
== S_OK
, "CoRevokeClassObject failed with %08x\n", hr
);
2235 hr
= CoRevokeClassObject(cookie2
);
2236 ok(hr
== S_OK
, "CoRevokeClassObject failed with %08x\n", hr
);
2237 hr
= CoRevokeClassObject(cookie3
);
2238 ok(hr
== S_OK
, "CoRevokeClassObject failed with %08x\n", hr
);
2241 typedef struct IUnknownImpl
2243 IUnknown IUnknown_iface
;
2248 static IUnknownImpl
*IUnknownImpl_from_iface(IUnknown
* iface
)
2250 return CONTAINING_RECORD(iface
, IUnknownImpl
, IUnknown_iface
);
2253 static HRESULT WINAPI
IUnknownImpl_QueryInterface(IUnknown
* iface
, REFIID riid
, LPVOID
* ppv
)
2255 ok(0, "QueryInterface should not be called for %s\n", wine_dbgstr_guid(riid
));
2256 return E_NOINTERFACE
;
2259 static ULONG WINAPI
IUnknownImpl_AddRef(IUnknown
* iface
)
2261 IUnknownImpl
*This
= IUnknownImpl_from_iface(iface
);
2262 This
->AddRef_called
++;
2266 static ULONG WINAPI
IUnknownImpl_Release(IUnknown
* iface
)
2268 IUnknownImpl
*This
= IUnknownImpl_from_iface(iface
);
2269 This
->Release_called
++;
2273 static CONST_VTBL IUnknownVtbl IUnknownImpl_Vtbl
=
2275 IUnknownImpl_QueryInterface
,
2276 IUnknownImpl_AddRef
,
2277 IUnknownImpl_Release
2280 static void test_aggregate_filter_graph(void)
2285 IUnknownImpl unk_outer
= { { &IUnknownImpl_Vtbl
}, 0, 0 };
2287 hr
= CoCreateInstance(&CLSID_FilterGraph
, &unk_outer
.IUnknown_iface
, CLSCTX_INPROC_SERVER
,
2288 &IID_IUnknown
, (void **)&pgraph
);
2289 ok(hr
== S_OK
, "CoCreateInstance returned %x\n", hr
);
2290 ok(pgraph
!= &unk_outer
.IUnknown_iface
, "pgraph = %p, expected not %p\n", pgraph
, &unk_outer
.IUnknown_iface
);
2292 hr
= IUnknown_QueryInterface(pgraph
, &IID_IUnknown
, (void **)&punk
);
2293 ok(hr
== S_OK
, "CoCreateInstance returned %x\n", hr
);
2294 ok(punk
!= &unk_outer
.IUnknown_iface
, "punk = %p, expected not %p\n", punk
, &unk_outer
.IUnknown_iface
);
2295 IUnknown_Release(punk
);
2297 ok(unk_outer
.AddRef_called
== 0, "IUnknownImpl_AddRef called %d times\n", unk_outer
.AddRef_called
);
2298 ok(unk_outer
.Release_called
== 0, "IUnknownImpl_Release called %d times\n", unk_outer
.Release_called
);
2299 unk_outer
.AddRef_called
= 0;
2300 unk_outer
.Release_called
= 0;
2302 hr
= IUnknown_QueryInterface(pgraph
, &IID_IFilterMapper
, (void **)&punk
);
2303 ok(hr
== S_OK
, "CoCreateInstance returned %x\n", hr
);
2304 ok(punk
!= &unk_outer
.IUnknown_iface
, "punk = %p, expected not %p\n", punk
, &unk_outer
.IUnknown_iface
);
2305 IUnknown_Release(punk
);
2307 ok(unk_outer
.AddRef_called
== 1, "IUnknownImpl_AddRef called %d times\n", unk_outer
.AddRef_called
);
2308 ok(unk_outer
.Release_called
== 1, "IUnknownImpl_Release called %d times\n", unk_outer
.Release_called
);
2309 unk_outer
.AddRef_called
= 0;
2310 unk_outer
.Release_called
= 0;
2312 hr
= IUnknown_QueryInterface(pgraph
, &IID_IFilterMapper2
, (void **)&punk
);
2313 ok(hr
== S_OK
, "CoCreateInstance returned %x\n", hr
);
2314 ok(punk
!= &unk_outer
.IUnknown_iface
, "punk = %p, expected not %p\n", punk
, &unk_outer
.IUnknown_iface
);
2315 IUnknown_Release(punk
);
2317 ok(unk_outer
.AddRef_called
== 1, "IUnknownImpl_AddRef called %d times\n", unk_outer
.AddRef_called
);
2318 ok(unk_outer
.Release_called
== 1, "IUnknownImpl_Release called %d times\n", unk_outer
.Release_called
);
2319 unk_outer
.AddRef_called
= 0;
2320 unk_outer
.Release_called
= 0;
2322 hr
= IUnknown_QueryInterface(pgraph
, &IID_IFilterMapper3
, (void **)&punk
);
2323 ok(hr
== S_OK
, "CoCreateInstance returned %x\n", hr
);
2324 ok(punk
!= &unk_outer
.IUnknown_iface
, "punk = %p, expected not %p\n", punk
, &unk_outer
.IUnknown_iface
);
2325 IUnknown_Release(punk
);
2327 ok(unk_outer
.AddRef_called
== 1, "IUnknownImpl_AddRef called %d times\n", unk_outer
.AddRef_called
);
2328 ok(unk_outer
.Release_called
== 1, "IUnknownImpl_Release called %d times\n", unk_outer
.Release_called
);
2330 IUnknown_Release(pgraph
);
2333 START_TEST(filtergraph
)
2336 CoInitializeEx(NULL
, COINIT_MULTITHREADED
);
2337 hr
= CoCreateInstance(&CLSID_FilterGraph
, NULL
, CLSCTX_INPROC_SERVER
,
2338 &IID_IGraphBuilder
, (LPVOID
*)&pgraph
);
2340 skip("Creating filtergraph returned %08x, skipping tests\n", hr
);
2343 IGraphBuilder_Release(pgraph
);
2344 test_render_run(avifile
);
2345 test_render_run(mpegfile
);
2346 test_graph_builder();
2347 test_graph_builder_addfilter();
2348 test_mediacontrol();
2349 test_filter_graph2();
2350 test_render_filter_priority();
2351 test_aggregate_filter_graph();
2353 test_render_with_multithread();