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 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)
56 LONG video_width
, video_height
;
57 LONG left
, top
, width
, height
;
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)
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
);
281 hr
= IMediaControl_Run(pmc
);
282 ok(hr
==S_FALSE
, "Cannot run the graph returned: %x\n", hr
);
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
);
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
);
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
);
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
);
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
);
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); */
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)
348 hr
= IGraphBuilder_Release(pgraph
);
349 ok(hr
==0, "Releasing filtergraph returned: %x\n", hr
);
352 static void test_render_run(const WCHAR
*file
)
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
));
364 if (!createfiltergraph())
367 hr
= IGraphBuilder_RenderFile(pgraph
, file
, NULL
);
368 ok(hr
== S_OK
, "RenderFile returned: %x\n", hr
);
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());
379 static DWORD WINAPI
call_RenderFile_multithread(LPVOID lParam
)
381 IFilterGraph2
*filter_graph
= lParam
;
383 WCHAR mp3file
[] = {'t','e','s','t','.','m','p','3',0};
386 handle
= CreateFileW(mp3file
, 0, 0, NULL
, CREATE_ALWAYS
, 0, NULL
);
387 if (handle
== INVALID_HANDLE_VALUE
)
389 skip("Could not read test file %s, skipping test\n", wine_dbgstr_w(mp3file
));
394 hr
= IFilterGraph2_RenderFile(filter_graph
, mp3file
, NULL
);
395 todo_wine
ok(hr
== VFW_E_CANNOT_RENDER
|| /* xp or older + DirectX 9 */
396 hr
== VFW_E_NO_TRANSPORT
|| /* win7 or newer */
397 broken(hr
== CLASS_E_CLASSNOTAVAILABLE
), /* xp or older + DirectX 8 or older */
398 "Expected 0x%08x or 0x%08x, returned 0x%08x\n", VFW_E_CANNOT_RENDER
, VFW_E_NO_TRANSPORT
, hr
);
400 DeleteFileW(mp3file
);
404 static void test_render_with_multithread(void)
408 static HRESULT (WINAPI
*pDllGetClassObject
)(REFCLSID rclsid
, REFIID riid
, void **out
);
409 IClassFactory
*classfactory
= NULL
;
410 static IGraphBuilder
*graph_builder
;
411 static IFilterGraph2
*filter_graph
;
414 CoInitializeEx(NULL
, COINIT_APARTMENTTHREADED
);
416 hmod
= LoadLibraryA("quartz.dll");
419 skip("Fail to load quartz.dll.\n");
423 pDllGetClassObject
= (void*)GetProcAddress(hmod
, "DllGetClassObject");
424 if (!pDllGetClassObject
)
426 skip("Fail to get DllGetClassObject.\n");
430 hr
= pDllGetClassObject(&CLSID_FilterGraph
, &IID_IClassFactory
, (void **)&classfactory
);
431 ok(hr
== S_OK
, "DllGetClassObject failed 0x%08x\n", hr
);
434 skip("Can't create IClassFactory 0x%08x.\n", hr
);
438 hr
= IClassFactory_CreateInstance(classfactory
, NULL
, &IID_IUnknown
, (LPVOID
*)&graph_builder
);
439 ok(hr
== S_OK
, "IClassFactory_CreateInstance failed 0x%08x\n", hr
);
441 hr
= IGraphBuilder_QueryInterface(graph_builder
, &IID_IFilterGraph2
, (void**)&filter_graph
);
442 ok(hr
== S_OK
, "IGraphBuilder_QueryInterface failed 0x%08x\n", hr
);
444 thread
= CreateThread(NULL
, 0, call_RenderFile_multithread
, filter_graph
, 0, NULL
);
446 WaitForSingleObject(thread
, 1000);
447 IFilterGraph2_Release(filter_graph
);
448 IGraphBuilder_Release(graph_builder
);
449 IClassFactory_Release(classfactory
);
454 static void test_graph_builder(void)
457 IBaseFilter
*pF
= NULL
;
458 IBaseFilter
*pF2
= NULL
;
460 IEnumPins
*pEnum
= NULL
;
462 static const WCHAR testFilterW
[] = {'t','e','s','t','F','i','l','t','e','r',0};
463 static const WCHAR fooBarW
[] = {'f','o','o','B','a','r',0};
465 if (!createfiltergraph())
468 /* create video filter */
469 hr
= CoCreateInstance(&CLSID_VideoRenderer
, NULL
, CLSCTX_INPROC_SERVER
,
470 &IID_IBaseFilter
, (LPVOID
*)&pF
);
471 ok(hr
== S_OK
, "CoCreateInstance failed with %x\n", hr
);
472 ok(pF
!= NULL
, "pF is NULL\n");
474 hr
= IGraphBuilder_AddFilter(pgraph
, NULL
, testFilterW
);
475 ok(hr
== E_POINTER
, "IGraphBuilder_AddFilter returned %x\n", hr
);
477 /* add the two filters to the graph */
478 hr
= IGraphBuilder_AddFilter(pgraph
, pF
, testFilterW
);
479 ok(hr
== S_OK
, "failed to add pF to the graph: %x\n", hr
);
482 hr
= IBaseFilter_EnumPins(pF
, &pEnum
);
483 ok(hr
== S_OK
, "IBaseFilter_EnumPins failed for pF: %x\n", hr
);
484 ok(pEnum
!= NULL
, "pEnum is NULL\n");
485 hr
= IEnumPins_Next(pEnum
, 1, &pIn
, NULL
);
486 ok(hr
== S_OK
, "IEnumPins_Next failed for pF: %x\n", hr
);
487 ok(pIn
!= NULL
, "pIn is NULL\n");
488 hr
= IPin_QueryDirection(pIn
, &dir
);
489 ok(hr
== S_OK
, "IPin_QueryDirection failed: %x\n", hr
);
490 ok(dir
== PINDIR_INPUT
, "pin has wrong direction\n");
492 hr
= IGraphBuilder_FindFilterByName(pgraph
, fooBarW
, &pF2
);
493 ok(hr
== VFW_E_NOT_FOUND
, "IGraphBuilder_FindFilterByName returned %x\n", hr
);
494 ok(pF2
== NULL
, "IGraphBuilder_FindFilterByName returned %p\n", pF2
);
495 hr
= IGraphBuilder_FindFilterByName(pgraph
, testFilterW
, &pF2
);
496 ok(hr
== S_OK
, "IGraphBuilder_FindFilterByName returned %x\n", hr
);
497 ok(pF2
!= NULL
, "IGraphBuilder_FindFilterByName returned NULL\n");
498 hr
= IGraphBuilder_FindFilterByName(pgraph
, testFilterW
, NULL
);
499 ok(hr
== E_POINTER
, "IGraphBuilder_FindFilterByName returned %x\n", hr
);
501 hr
= IGraphBuilder_Connect(pgraph
, NULL
, pIn
);
502 ok(hr
== E_POINTER
, "IGraphBuilder_Connect returned %x\n", hr
);
504 hr
= IGraphBuilder_Connect(pgraph
, pIn
, NULL
);
505 ok(hr
== E_POINTER
, "IGraphBuilder_Connect returned %x\n", hr
);
507 hr
= IGraphBuilder_Connect(pgraph
, pIn
, pIn
);
508 ok(hr
== VFW_E_CANNOT_CONNECT
, "IGraphBuilder_Connect returned %x\n", hr
);
510 if (pIn
) IPin_Release(pIn
);
511 if (pEnum
) IEnumPins_Release(pEnum
);
512 if (pF
) IBaseFilter_Release(pF
);
513 if (pF2
) IBaseFilter_Release(pF2
);
515 releasefiltergraph();
518 static void test_graph_builder_addfilter(void)
521 IBaseFilter
*pF
= NULL
;
522 static const WCHAR testFilterW
[] = {'t','e','s','t','F','i','l','t','e','r',0};
524 if (!createfiltergraph())
527 hr
= IGraphBuilder_AddFilter(pgraph
, NULL
, testFilterW
);
528 ok(hr
== E_POINTER
, "IGraphBuilder_AddFilter returned: %x\n", hr
);
530 /* create video filter */
531 hr
= CoCreateInstance(&CLSID_VideoRenderer
, NULL
, CLSCTX_INPROC_SERVER
,
532 &IID_IBaseFilter
, (LPVOID
*)&pF
);
533 ok(hr
== S_OK
, "CoCreateInstance failed with %x\n", hr
);
534 ok(pF
!= NULL
, "pF is NULL\n");
536 skip("failed to created filter, skipping\n");
540 hr
= IGraphBuilder_AddFilter(pgraph
, pF
, NULL
);
541 ok(hr
== S_OK
, "IGraphBuilder_AddFilter returned: %x\n", hr
);
542 IBaseFilter_Release(pF
);
545 static void test_mediacontrol(void)
548 LONGLONG pos
= 0xdeadbeef;
549 GUID format
= GUID_NULL
;
550 IMediaSeeking
*seeking
= NULL
;
551 IMediaFilter
*filter
= NULL
;
552 IMediaControl
*control
= NULL
;
554 IGraphBuilder_SetDefaultSyncSource(pgraph
);
555 hr
= IGraphBuilder_QueryInterface(pgraph
, &IID_IMediaSeeking
, (void**) &seeking
);
556 ok(hr
== S_OK
, "QueryInterface IMediaControl failed: %08x\n", hr
);
560 hr
= IGraphBuilder_QueryInterface(pgraph
, &IID_IMediaFilter
, (void**) &filter
);
561 ok(hr
== S_OK
, "QueryInterface IMediaFilter failed: %08x\n", hr
);
564 IMediaSeeking_Release(seeking
);
568 hr
= IGraphBuilder_QueryInterface(pgraph
, &IID_IMediaControl
, (void**) &control
);
569 ok(hr
== S_OK
, "QueryInterface IMediaControl failed: %08x\n", hr
);
572 IMediaSeeking_Release(seeking
);
573 IMediaFilter_Release(filter
);
578 hr
= IMediaSeeking_GetTimeFormat(seeking
, &format
);
579 ok(hr
== S_OK
, "GetTimeFormat failed: %08x\n", hr
);
580 ok(IsEqualGUID(&format
, &TIME_FORMAT_MEDIA_TIME
), "GetTimeFormat: unexpected format %s\n", wine_dbgstr_guid(&format
));
583 hr
= IMediaSeeking_ConvertTimeFormat(seeking
, &pos
, NULL
, 0x123456789a, NULL
);
584 ok(hr
== S_OK
, "ConvertTimeFormat failed: %08x\n", hr
);
585 ok(pos
== 0x123456789a, "ConvertTimeFormat: expected 123456789a, got (%s)\n", wine_dbgstr_longlong(pos
));
588 hr
= IMediaSeeking_ConvertTimeFormat(seeking
, &pos
, &TIME_FORMAT_MEDIA_TIME
, 0x123456789a, NULL
);
589 ok(hr
== S_OK
, "ConvertTimeFormat failed: %08x\n", hr
);
590 ok(pos
== 0x123456789a, "ConvertTimeFormat: expected 123456789a, got (%s)\n", wine_dbgstr_longlong(pos
));
593 hr
= IMediaSeeking_ConvertTimeFormat(seeking
, &pos
, NULL
, 0x123456789a, &TIME_FORMAT_MEDIA_TIME
);
594 ok(hr
== S_OK
, "ConvertTimeFormat failed: %08x\n", hr
);
595 ok(pos
== 0x123456789a, "ConvertTimeFormat: expected 123456789a, got (%s)\n", wine_dbgstr_longlong(pos
));
597 hr
= IMediaSeeking_GetCurrentPosition(seeking
, &pos
);
598 ok(hr
== S_OK
, "GetCurrentPosition failed: %08x\n", hr
);
599 ok(pos
== 0, "Position != 0 (%s)\n", wine_dbgstr_longlong(pos
));
601 hr
= IMediaSeeking_SetPositions(seeking
, NULL
, AM_SEEKING_ReturnTime
, NULL
, AM_SEEKING_NoPositioning
);
602 ok(hr
== S_OK
, "SetPositions failed: %08x\n", hr
);
603 hr
= IMediaSeeking_SetPositions(seeking
, NULL
, AM_SEEKING_NoPositioning
, NULL
, AM_SEEKING_ReturnTime
);
604 ok(hr
== S_OK
, "SetPositions failed: %08x\n", hr
);
606 IMediaFilter_SetSyncSource(filter
, NULL
);
608 hr
= IMediaSeeking_GetCurrentPosition(seeking
, &pos
);
609 ok(hr
== S_OK
, "GetCurrentPosition failed: %08x\n", hr
);
610 ok(pos
== 0, "Position != 0 (%s)\n", wine_dbgstr_longlong(pos
));
612 hr
= IMediaControl_GetState(control
, 1000, NULL
);
613 ok(hr
== E_POINTER
, "GetState expected %08x, got %08x\n", E_POINTER
, hr
);
615 IMediaControl_Release(control
);
616 IMediaSeeking_Release(seeking
);
617 IMediaFilter_Release(filter
);
618 releasefiltergraph();
621 static void test_filter_graph2(void)
624 IFilterGraph2
*pF
= NULL
;
626 hr
= CoCreateInstance(&CLSID_FilterGraph
, NULL
, CLSCTX_INPROC_SERVER
,
627 &IID_IFilterGraph2
, (LPVOID
*)&pF
);
628 ok(hr
== S_OK
, "CoCreateInstance failed with %x\n", hr
);
629 ok(pF
!= NULL
, "pF is NULL\n");
631 hr
= IFilterGraph2_Release(pF
);
632 ok(hr
== 0, "IFilterGraph2_Release returned: %x\n", hr
);
635 /* IEnumMediaTypes implementation (supporting code for Render() test.) */
636 static void FreeMediaType(AM_MEDIA_TYPE
* pMediaType
)
638 if (pMediaType
->pbFormat
)
640 CoTaskMemFree(pMediaType
->pbFormat
);
641 pMediaType
->pbFormat
= NULL
;
643 if (pMediaType
->pUnk
)
645 IUnknown_Release(pMediaType
->pUnk
);
646 pMediaType
->pUnk
= NULL
;
650 static HRESULT
CopyMediaType(AM_MEDIA_TYPE
* pDest
, const AM_MEDIA_TYPE
*pSrc
)
653 if (!pSrc
->pbFormat
) return S_OK
;
654 if (!(pDest
->pbFormat
= CoTaskMemAlloc(pSrc
->cbFormat
)))
655 return E_OUTOFMEMORY
;
656 memcpy(pDest
->pbFormat
, pSrc
->pbFormat
, pSrc
->cbFormat
);
658 IUnknown_AddRef(pDest
->pUnk
);
662 static AM_MEDIA_TYPE
* CreateMediaType(AM_MEDIA_TYPE
const * pSrc
)
664 AM_MEDIA_TYPE
* pDest
;
666 pDest
= CoTaskMemAlloc(sizeof(AM_MEDIA_TYPE
));
670 if (FAILED(CopyMediaType(pDest
, pSrc
)))
672 CoTaskMemFree(pDest
);
679 static BOOL
CompareMediaTypes(const AM_MEDIA_TYPE
* pmt1
, const AM_MEDIA_TYPE
* pmt2
, BOOL bWildcards
)
681 return (((bWildcards
&& (IsEqualGUID(&pmt1
->majortype
, &GUID_NULL
) || IsEqualGUID(&pmt2
->majortype
, &GUID_NULL
))) || IsEqualGUID(&pmt1
->majortype
, &pmt2
->majortype
)) &&
682 ((bWildcards
&& (IsEqualGUID(&pmt1
->subtype
, &GUID_NULL
) || IsEqualGUID(&pmt2
->subtype
, &GUID_NULL
))) || IsEqualGUID(&pmt1
->subtype
, &pmt2
->subtype
)));
685 static void DeleteMediaType(AM_MEDIA_TYPE
* pMediaType
)
687 FreeMediaType(pMediaType
);
688 CoTaskMemFree(pMediaType
);
691 typedef struct IEnumMediaTypesImpl
693 IEnumMediaTypes IEnumMediaTypes_iface
;
695 AM_MEDIA_TYPE
*pMediaTypes
;
698 } IEnumMediaTypesImpl
;
700 static const struct IEnumMediaTypesVtbl IEnumMediaTypesImpl_Vtbl
;
702 static inline IEnumMediaTypesImpl
*impl_from_IEnumMediaTypes(IEnumMediaTypes
*iface
)
704 return CONTAINING_RECORD(iface
, IEnumMediaTypesImpl
, IEnumMediaTypes_iface
);
707 static HRESULT
IEnumMediaTypesImpl_Construct(const AM_MEDIA_TYPE
* pMediaTypes
, ULONG cMediaTypes
, IEnumMediaTypes
** ppEnum
)
710 IEnumMediaTypesImpl
* pEnumMediaTypes
= CoTaskMemAlloc(sizeof(IEnumMediaTypesImpl
));
712 if (!pEnumMediaTypes
)
715 return E_OUTOFMEMORY
;
717 pEnumMediaTypes
->IEnumMediaTypes_iface
.lpVtbl
= &IEnumMediaTypesImpl_Vtbl
;
718 pEnumMediaTypes
->refCount
= 1;
719 pEnumMediaTypes
->uIndex
= 0;
720 pEnumMediaTypes
->cMediaTypes
= cMediaTypes
;
721 pEnumMediaTypes
->pMediaTypes
= CoTaskMemAlloc(sizeof(AM_MEDIA_TYPE
) * cMediaTypes
);
722 for (i
= 0; i
< cMediaTypes
; i
++)
723 if (FAILED(CopyMediaType(&pEnumMediaTypes
->pMediaTypes
[i
], &pMediaTypes
[i
])))
726 FreeMediaType(&pEnumMediaTypes
->pMediaTypes
[i
]);
727 CoTaskMemFree(pEnumMediaTypes
->pMediaTypes
);
728 return E_OUTOFMEMORY
;
730 *ppEnum
= &pEnumMediaTypes
->IEnumMediaTypes_iface
;
734 static HRESULT WINAPI
IEnumMediaTypesImpl_QueryInterface(IEnumMediaTypes
* iface
, REFIID riid
, LPVOID
* ppv
)
738 if (IsEqualIID(riid
, &IID_IUnknown
))
740 else if (IsEqualIID(riid
, &IID_IEnumMediaTypes
))
745 IUnknown_AddRef((IUnknown
*)(*ppv
));
749 return E_NOINTERFACE
;
752 static ULONG WINAPI
IEnumMediaTypesImpl_AddRef(IEnumMediaTypes
* iface
)
754 IEnumMediaTypesImpl
*This
= impl_from_IEnumMediaTypes(iface
);
755 ULONG refCount
= InterlockedIncrement(&This
->refCount
);
760 static ULONG WINAPI
IEnumMediaTypesImpl_Release(IEnumMediaTypes
* iface
)
762 IEnumMediaTypesImpl
*This
= impl_from_IEnumMediaTypes(iface
);
763 ULONG refCount
= InterlockedDecrement(&This
->refCount
);
768 for (i
= 0; i
< This
->cMediaTypes
; i
++)
769 FreeMediaType(&This
->pMediaTypes
[i
]);
770 CoTaskMemFree(This
->pMediaTypes
);
776 static HRESULT WINAPI
IEnumMediaTypesImpl_Next(IEnumMediaTypes
* iface
, ULONG cMediaTypes
, AM_MEDIA_TYPE
** ppMediaTypes
, ULONG
* pcFetched
)
779 IEnumMediaTypesImpl
*This
= impl_from_IEnumMediaTypes(iface
);
781 cFetched
= min(This
->cMediaTypes
, This
->uIndex
+ cMediaTypes
) - This
->uIndex
;
786 for (i
= 0; i
< cFetched
; i
++)
787 if (!(ppMediaTypes
[i
] = CreateMediaType(&This
->pMediaTypes
[This
->uIndex
+ i
])))
790 DeleteMediaType(ppMediaTypes
[i
]);
792 return E_OUTOFMEMORY
;
796 if ((cMediaTypes
!= 1) || pcFetched
)
797 *pcFetched
= cFetched
;
799 This
->uIndex
+= cFetched
;
801 if (cFetched
!= cMediaTypes
)
806 static HRESULT WINAPI
IEnumMediaTypesImpl_Skip(IEnumMediaTypes
* iface
, ULONG cMediaTypes
)
808 IEnumMediaTypesImpl
*This
= impl_from_IEnumMediaTypes(iface
);
810 if (This
->uIndex
+ cMediaTypes
< This
->cMediaTypes
)
812 This
->uIndex
+= cMediaTypes
;
818 static HRESULT WINAPI
IEnumMediaTypesImpl_Reset(IEnumMediaTypes
* iface
)
820 IEnumMediaTypesImpl
*This
= impl_from_IEnumMediaTypes(iface
);
826 static HRESULT WINAPI
IEnumMediaTypesImpl_Clone(IEnumMediaTypes
* iface
, IEnumMediaTypes
** ppEnum
)
829 IEnumMediaTypesImpl
*This
= impl_from_IEnumMediaTypes(iface
);
831 hr
= IEnumMediaTypesImpl_Construct(This
->pMediaTypes
, This
->cMediaTypes
, ppEnum
);
834 return IEnumMediaTypes_Skip(*ppEnum
, This
->uIndex
);
837 static const IEnumMediaTypesVtbl IEnumMediaTypesImpl_Vtbl
=
839 IEnumMediaTypesImpl_QueryInterface
,
840 IEnumMediaTypesImpl_AddRef
,
841 IEnumMediaTypesImpl_Release
,
842 IEnumMediaTypesImpl_Next
,
843 IEnumMediaTypesImpl_Skip
,
844 IEnumMediaTypesImpl_Reset
,
845 IEnumMediaTypesImpl_Clone
848 /* Implementation of a very stripped down pin for the test filter. Just enough
849 functionality for connecting and Render() to work. */
851 static void Copy_PinInfo(PIN_INFO
* pDest
, const PIN_INFO
* pSrc
)
853 lstrcpyW(pDest
->achName
, pSrc
->achName
);
854 pDest
->dir
= pSrc
->dir
;
855 pDest
->pFilter
= pSrc
->pFilter
;
858 typedef struct ITestPinImpl
862 LPCRITICAL_SECTION pCritSec
;
865 AM_MEDIA_TYPE mtCurrent
;
869 static inline ITestPinImpl
*impl_from_IPin(IPin
*iface
)
871 return CONTAINING_RECORD(iface
, ITestPinImpl
, IPin_iface
);
874 static HRESULT WINAPI
TestFilter_Pin_QueryInterface(IPin
* iface
, REFIID riid
, LPVOID
* ppv
)
878 if (IsEqualIID(riid
, &IID_IUnknown
))
880 else if (IsEqualIID(riid
, &IID_IPin
))
885 IUnknown_AddRef((IUnknown
*)(*ppv
));
889 return E_NOINTERFACE
;
892 static ULONG WINAPI
TestFilter_Pin_AddRef(IPin
* iface
)
894 ITestPinImpl
*This
= impl_from_IPin(iface
);
895 ULONG refCount
= InterlockedIncrement(&This
->refCount
);
899 static ULONG WINAPI
TestFilter_Pin_Release(IPin
* iface
)
901 ITestPinImpl
*This
= impl_from_IPin(iface
);
902 ULONG refCount
= InterlockedDecrement(&This
->refCount
);
906 FreeMediaType(&This
->mtCurrent
);
914 static HRESULT WINAPI
TestFilter_InputPin_Connect(IPin
* iface
, IPin
* pConnector
, const AM_MEDIA_TYPE
* pmt
)
919 static HRESULT WINAPI
TestFilter_InputPin_ReceiveConnection(IPin
* iface
, IPin
* pReceivePin
, const AM_MEDIA_TYPE
* pmt
)
921 ITestPinImpl
*This
= impl_from_IPin(iface
);
922 PIN_DIRECTION pindirReceive
;
925 EnterCriticalSection(This
->pCritSec
);
927 if (!(IsEqualIID(&pmt
->majortype
, &This
->mtCurrent
.majortype
) && (IsEqualIID(&pmt
->subtype
, &This
->mtCurrent
.subtype
) ||
928 IsEqualIID(&GUID_NULL
, &This
->mtCurrent
.subtype
))))
929 hr
= VFW_E_TYPE_NOT_ACCEPTED
;
931 if (This
->pConnectedTo
)
932 hr
= VFW_E_ALREADY_CONNECTED
;
936 IPin_QueryDirection(pReceivePin
, &pindirReceive
);
938 if (pindirReceive
!= PINDIR_OUTPUT
)
940 hr
= VFW_E_INVALID_DIRECTION
;
946 CopyMediaType(&This
->mtCurrent
, pmt
);
947 This
->pConnectedTo
= pReceivePin
;
948 IPin_AddRef(pReceivePin
);
951 LeaveCriticalSection(This
->pCritSec
);
956 static HRESULT WINAPI
TestFilter_Pin_Disconnect(IPin
* iface
)
959 ITestPinImpl
*This
= impl_from_IPin(iface
);
961 EnterCriticalSection(This
->pCritSec
);
963 if (This
->pConnectedTo
)
965 IPin_Release(This
->pConnectedTo
);
966 This
->pConnectedTo
= NULL
;
972 LeaveCriticalSection(This
->pCritSec
);
977 static HRESULT WINAPI
TestFilter_Pin_ConnectedTo(IPin
* iface
, IPin
** ppPin
)
980 ITestPinImpl
*This
= impl_from_IPin(iface
);
982 EnterCriticalSection(This
->pCritSec
);
984 if (This
->pConnectedTo
)
986 *ppPin
= This
->pConnectedTo
;
992 hr
= VFW_E_NOT_CONNECTED
;
996 LeaveCriticalSection(This
->pCritSec
);
1001 static HRESULT WINAPI
TestFilter_Pin_ConnectionMediaType(IPin
* iface
, AM_MEDIA_TYPE
* pmt
)
1004 ITestPinImpl
*This
= impl_from_IPin(iface
);
1006 EnterCriticalSection(This
->pCritSec
);
1008 if (This
->pConnectedTo
)
1010 CopyMediaType(pmt
, &This
->mtCurrent
);
1015 ZeroMemory(pmt
, sizeof(*pmt
));
1016 hr
= VFW_E_NOT_CONNECTED
;
1019 LeaveCriticalSection(This
->pCritSec
);
1024 static HRESULT WINAPI
TestFilter_Pin_QueryPinInfo(IPin
* iface
, PIN_INFO
* pInfo
)
1026 ITestPinImpl
*This
= impl_from_IPin(iface
);
1028 Copy_PinInfo(pInfo
, &This
->pinInfo
);
1029 IBaseFilter_AddRef(pInfo
->pFilter
);
1034 static HRESULT WINAPI
TestFilter_Pin_QueryDirection(IPin
* iface
, PIN_DIRECTION
* pPinDir
)
1036 ITestPinImpl
*This
= impl_from_IPin(iface
);
1038 *pPinDir
= This
->pinInfo
.dir
;
1043 static HRESULT WINAPI
TestFilter_Pin_QueryId(IPin
* iface
, LPWSTR
* Id
)
1048 static HRESULT WINAPI
TestFilter_Pin_QueryAccept(IPin
* iface
, const AM_MEDIA_TYPE
* pmt
)
1050 ITestPinImpl
*This
= impl_from_IPin(iface
);
1052 if (IsEqualIID(&pmt
->majortype
, &This
->mtCurrent
.majortype
) && (IsEqualIID(&pmt
->subtype
, &This
->mtCurrent
.subtype
) ||
1053 IsEqualIID(&GUID_NULL
, &This
->mtCurrent
.subtype
)))
1056 return VFW_E_TYPE_NOT_ACCEPTED
;
1059 static HRESULT WINAPI
TestFilter_Pin_EnumMediaTypes(IPin
* iface
, IEnumMediaTypes
** ppEnum
)
1061 ITestPinImpl
*This
= impl_from_IPin(iface
);
1063 return IEnumMediaTypesImpl_Construct(&This
->mtCurrent
, 1, ppEnum
);
1066 static HRESULT WINAPI
TestFilter_Pin_QueryInternalConnections(IPin
* iface
, IPin
** apPin
, ULONG
* cPin
)
1071 static HRESULT WINAPI
TestFilter_Pin_BeginFlush(IPin
* iface
)
1076 static HRESULT WINAPI
TestFilter_Pin_EndFlush(IPin
* iface
)
1081 static HRESULT WINAPI
TestFilter_Pin_NewSegment(IPin
* iface
, REFERENCE_TIME tStart
, REFERENCE_TIME tStop
, double dRate
)
1086 static HRESULT WINAPI
TestFilter_Pin_EndOfStream(IPin
* iface
)
1091 static const IPinVtbl TestFilter_InputPin_Vtbl
=
1093 TestFilter_Pin_QueryInterface
,
1094 TestFilter_Pin_AddRef
,
1095 TestFilter_Pin_Release
,
1096 TestFilter_InputPin_Connect
,
1097 TestFilter_InputPin_ReceiveConnection
,
1098 TestFilter_Pin_Disconnect
,
1099 TestFilter_Pin_ConnectedTo
,
1100 TestFilter_Pin_ConnectionMediaType
,
1101 TestFilter_Pin_QueryPinInfo
,
1102 TestFilter_Pin_QueryDirection
,
1103 TestFilter_Pin_QueryId
,
1104 TestFilter_Pin_QueryAccept
,
1105 TestFilter_Pin_EnumMediaTypes
,
1106 TestFilter_Pin_QueryInternalConnections
,
1107 TestFilter_Pin_EndOfStream
,
1108 TestFilter_Pin_BeginFlush
,
1109 TestFilter_Pin_EndFlush
,
1110 TestFilter_Pin_NewSegment
1113 static HRESULT WINAPI
TestFilter_OutputPin_ReceiveConnection(IPin
* iface
, IPin
* pReceivePin
, const AM_MEDIA_TYPE
* pmt
)
1115 return E_UNEXPECTED
;
1118 /* Private helper function */
1119 static HRESULT
TestFilter_OutputPin_ConnectSpecific(ITestPinImpl
* This
, IPin
* pReceivePin
,
1120 const AM_MEDIA_TYPE
* pmt
)
1124 This
->pConnectedTo
= pReceivePin
;
1125 IPin_AddRef(pReceivePin
);
1127 hr
= IPin_ReceiveConnection(pReceivePin
, &This
->IPin_iface
, pmt
);
1131 IPin_Release(This
->pConnectedTo
);
1132 This
->pConnectedTo
= NULL
;
1138 static HRESULT WINAPI
TestFilter_OutputPin_Connect(IPin
* iface
, IPin
* pReceivePin
, const AM_MEDIA_TYPE
* pmt
)
1140 ITestPinImpl
*This
= impl_from_IPin(iface
);
1143 EnterCriticalSection(This
->pCritSec
);
1145 /* if we have been a specific type to connect with, then we can either connect
1146 * with that or fail. We cannot choose different AM_MEDIA_TYPE */
1147 if (pmt
&& !IsEqualGUID(&pmt
->majortype
, &GUID_NULL
) && !IsEqualGUID(&pmt
->subtype
, &GUID_NULL
))
1148 hr
= TestFilter_OutputPin_ConnectSpecific(This
, pReceivePin
, pmt
);
1151 if (( !pmt
|| CompareMediaTypes(pmt
, &This
->mtCurrent
, TRUE
) ) &&
1152 (TestFilter_OutputPin_ConnectSpecific(This
, pReceivePin
, &This
->mtCurrent
) == S_OK
))
1154 else hr
= VFW_E_NO_ACCEPTABLE_TYPES
;
1155 } /* if negotiate media type */
1156 } /* if succeeded */
1157 LeaveCriticalSection(This
->pCritSec
);
1162 static const IPinVtbl TestFilter_OutputPin_Vtbl
=
1164 TestFilter_Pin_QueryInterface
,
1165 TestFilter_Pin_AddRef
,
1166 TestFilter_Pin_Release
,
1167 TestFilter_OutputPin_Connect
,
1168 TestFilter_OutputPin_ReceiveConnection
,
1169 TestFilter_Pin_Disconnect
,
1170 TestFilter_Pin_ConnectedTo
,
1171 TestFilter_Pin_ConnectionMediaType
,
1172 TestFilter_Pin_QueryPinInfo
,
1173 TestFilter_Pin_QueryDirection
,
1174 TestFilter_Pin_QueryId
,
1175 TestFilter_Pin_QueryAccept
,
1176 TestFilter_Pin_EnumMediaTypes
,
1177 TestFilter_Pin_QueryInternalConnections
,
1178 TestFilter_Pin_EndOfStream
,
1179 TestFilter_Pin_BeginFlush
,
1180 TestFilter_Pin_EndFlush
,
1181 TestFilter_Pin_NewSegment
1184 static HRESULT
TestFilter_Pin_Construct(const IPinVtbl
*Pin_Vtbl
, const PIN_INFO
* pPinInfo
, AM_MEDIA_TYPE
*pinmt
,
1185 LPCRITICAL_SECTION pCritSec
, IPin
** ppPin
)
1187 ITestPinImpl
* pPinImpl
;
1191 pPinImpl
= CoTaskMemAlloc(sizeof(ITestPinImpl
));
1194 return E_OUTOFMEMORY
;
1196 pPinImpl
->refCount
= 1;
1197 pPinImpl
->pConnectedTo
= NULL
;
1198 pPinImpl
->pCritSec
= pCritSec
;
1199 Copy_PinInfo(&pPinImpl
->pinInfo
, pPinInfo
);
1200 pPinImpl
->mtCurrent
= *pinmt
;
1202 pPinImpl
->IPin_iface
.lpVtbl
= Pin_Vtbl
;
1204 *ppPin
= &pPinImpl
->IPin_iface
;
1208 /* IEnumPins implementation */
1210 typedef HRESULT (* FNOBTAINPIN
)(TestFilterImpl
*tf
, ULONG pos
, IPin
**pin
, DWORD
*lastsynctick
);
1212 typedef struct IEnumPinsImpl
1214 IEnumPins IEnumPins_iface
;
1217 TestFilterImpl
*base
;
1218 FNOBTAINPIN receive_pin
;
1222 static const struct IEnumPinsVtbl IEnumPinsImpl_Vtbl
;
1224 static inline IEnumPinsImpl
*impl_from_IEnumPins(IEnumPins
*iface
)
1226 return CONTAINING_RECORD(iface
, IEnumPinsImpl
, IEnumPins_iface
);
1229 static HRESULT
createenumpins(IEnumPins
** ppEnum
, FNOBTAINPIN receive_pin
, TestFilterImpl
*base
)
1231 IEnumPinsImpl
* pEnumPins
;
1236 pEnumPins
= CoTaskMemAlloc(sizeof(IEnumPinsImpl
));
1240 return E_OUTOFMEMORY
;
1242 pEnumPins
->IEnumPins_iface
.lpVtbl
= &IEnumPinsImpl_Vtbl
;
1243 pEnumPins
->refCount
= 1;
1244 pEnumPins
->uIndex
= 0;
1245 pEnumPins
->receive_pin
= receive_pin
;
1246 pEnumPins
->base
= base
;
1247 IBaseFilter_AddRef(&base
->IBaseFilter_iface
);
1248 *ppEnum
= &pEnumPins
->IEnumPins_iface
;
1250 receive_pin(base
, ~0, NULL
, &pEnumPins
->synctime
);
1255 static HRESULT WINAPI
IEnumPinsImpl_QueryInterface(IEnumPins
* iface
, REFIID riid
, LPVOID
* ppv
)
1259 if (IsEqualIID(riid
, &IID_IUnknown
))
1261 else if (IsEqualIID(riid
, &IID_IEnumPins
))
1266 IUnknown_AddRef((IUnknown
*)(*ppv
));
1270 return E_NOINTERFACE
;
1273 static ULONG WINAPI
IEnumPinsImpl_AddRef(IEnumPins
* iface
)
1275 IEnumPinsImpl
*This
= impl_from_IEnumPins(iface
);
1276 ULONG refCount
= InterlockedIncrement(&This
->refCount
);
1281 static ULONG WINAPI
IEnumPinsImpl_Release(IEnumPins
* iface
)
1283 IEnumPinsImpl
*This
= impl_from_IEnumPins(iface
);
1284 ULONG refCount
= InterlockedDecrement(&This
->refCount
);
1288 IBaseFilter_Release(&This
->base
->IBaseFilter_iface
);
1289 CoTaskMemFree(This
);
1296 static HRESULT WINAPI
IEnumPinsImpl_Next(IEnumPins
* iface
, ULONG cPins
, IPin
** ppPins
, ULONG
* pcFetched
)
1298 IEnumPinsImpl
*This
= impl_from_IEnumPins(iface
);
1299 DWORD synctime
= This
->synctime
;
1306 if (cPins
> 1 && !pcFetched
)
1307 return E_INVALIDARG
;
1312 while (i
< cPins
&& hr
== S_OK
)
1314 hr
= This
->receive_pin(This
->base
, This
->uIndex
+ i
, &ppPins
[i
], &synctime
);
1319 if (synctime
!= This
->synctime
)
1323 if (!i
&& synctime
!= This
->synctime
)
1324 return VFW_E_ENUM_OUT_OF_SYNC
;
1335 static HRESULT WINAPI
IEnumPinsImpl_Skip(IEnumPins
* iface
, ULONG cPins
)
1337 IEnumPinsImpl
*This
= impl_from_IEnumPins(iface
);
1338 DWORD synctime
= This
->synctime
;
1342 hr
= This
->receive_pin(This
->base
, This
->uIndex
+ cPins
, &pin
, &synctime
);
1346 if (synctime
!= This
->synctime
)
1347 return VFW_E_ENUM_OUT_OF_SYNC
;
1350 This
->uIndex
+= cPins
;
1355 static HRESULT WINAPI
IEnumPinsImpl_Reset(IEnumPins
* iface
)
1357 IEnumPinsImpl
*This
= impl_from_IEnumPins(iface
);
1359 This
->receive_pin(This
->base
, ~0, NULL
, &This
->synctime
);
1365 static HRESULT WINAPI
IEnumPinsImpl_Clone(IEnumPins
* iface
, IEnumPins
** ppEnum
)
1368 IEnumPinsImpl
*This
= impl_from_IEnumPins(iface
);
1370 hr
= createenumpins(ppEnum
, This
->receive_pin
, This
->base
);
1373 return IEnumPins_Skip(*ppEnum
, This
->uIndex
);
1376 static const IEnumPinsVtbl IEnumPinsImpl_Vtbl
=
1378 IEnumPinsImpl_QueryInterface
,
1379 IEnumPinsImpl_AddRef
,
1380 IEnumPinsImpl_Release
,
1383 IEnumPinsImpl_Reset
,
1387 /* Test filter implementation - a filter that has few predefined pins with single media type
1388 * that accept only this single media type. Enough for Render(). */
1390 typedef struct TestFilterPinData
1392 PIN_DIRECTION pinDir
;
1393 const GUID
*mediasubtype
;
1394 } TestFilterPinData
;
1396 static const IBaseFilterVtbl TestFilter_Vtbl
;
1398 static inline TestFilterImpl
*impl_from_IBaseFilter(IBaseFilter
*iface
)
1400 return CONTAINING_RECORD(iface
, TestFilterImpl
, IBaseFilter_iface
);
1403 static HRESULT
createtestfilter(const CLSID
* pClsid
, const TestFilterPinData
*pinData
,
1404 TestFilterImpl
**tf
)
1406 static const WCHAR wcsInputPinName
[] = {'i','n','p','u','t',' ','p','i','n',0};
1407 static const WCHAR wcsOutputPinName
[] = {'o','u','t','p','u','t',' ','p','i','n',0};
1410 TestFilterImpl
* pTestFilter
= NULL
;
1414 pTestFilter
= CoTaskMemAlloc(sizeof(TestFilterImpl
));
1415 if (!pTestFilter
) return E_OUTOFMEMORY
;
1417 pTestFilter
->clsid
= *pClsid
;
1418 pTestFilter
->IBaseFilter_iface
.lpVtbl
= &TestFilter_Vtbl
;
1419 pTestFilter
->refCount
= 1;
1420 InitializeCriticalSection(&pTestFilter
->csFilter
);
1421 pTestFilter
->state
= State_Stopped
;
1423 ZeroMemory(&pTestFilter
->filterInfo
, sizeof(FILTER_INFO
));
1426 while(pinData
[nPins
].mediasubtype
) ++nPins
;
1428 pTestFilter
->ppPins
= CoTaskMemAlloc(nPins
* sizeof(IPin
*));
1429 if (!pTestFilter
->ppPins
)
1434 ZeroMemory(pTestFilter
->ppPins
, nPins
* sizeof(IPin
*));
1436 for (i
= 0; i
< nPins
; i
++)
1438 ZeroMemory(&mt
, sizeof(mt
));
1439 mt
.majortype
= MEDIATYPE_Video
;
1440 mt
.formattype
= FORMAT_None
;
1441 mt
.subtype
= *pinData
[i
].mediasubtype
;
1443 pinInfo
.dir
= pinData
[i
].pinDir
;
1444 pinInfo
.pFilter
= &pTestFilter
->IBaseFilter_iface
;
1445 if (pinInfo
.dir
== PINDIR_INPUT
)
1447 lstrcpynW(pinInfo
.achName
, wcsInputPinName
, sizeof(pinInfo
.achName
) / sizeof(pinInfo
.achName
[0]));
1448 hr
= TestFilter_Pin_Construct(&TestFilter_InputPin_Vtbl
, &pinInfo
, &mt
, &pTestFilter
->csFilter
,
1449 &pTestFilter
->ppPins
[i
]);
1454 lstrcpynW(pinInfo
.achName
, wcsOutputPinName
, sizeof(pinInfo
.achName
) / sizeof(pinInfo
.achName
[0]));
1455 hr
= TestFilter_Pin_Construct(&TestFilter_OutputPin_Vtbl
, &pinInfo
, &mt
, &pTestFilter
->csFilter
,
1456 &pTestFilter
->ppPins
[i
]);
1458 if (FAILED(hr
) || !pTestFilter
->ppPins
[i
]) goto error
;
1461 pTestFilter
->nPins
= nPins
;
1467 if (pTestFilter
->ppPins
)
1469 for (i
= 0; i
< nPins
; i
++)
1471 if (pTestFilter
->ppPins
[i
]) IPin_Release(pTestFilter
->ppPins
[i
]);
1474 CoTaskMemFree(pTestFilter
->ppPins
);
1475 DeleteCriticalSection(&pTestFilter
->csFilter
);
1476 CoTaskMemFree(pTestFilter
);
1481 static HRESULT WINAPI
TestFilter_QueryInterface(IBaseFilter
* iface
, REFIID riid
, LPVOID
* ppv
)
1483 TestFilterImpl
*This
= impl_from_IBaseFilter(iface
);
1487 if (IsEqualIID(riid
, &IID_IUnknown
))
1489 else if (IsEqualIID(riid
, &IID_IPersist
))
1491 else if (IsEqualIID(riid
, &IID_IMediaFilter
))
1493 else if (IsEqualIID(riid
, &IID_IBaseFilter
))
1498 IUnknown_AddRef((IUnknown
*)(*ppv
));
1502 return E_NOINTERFACE
;
1505 static ULONG WINAPI
TestFilter_AddRef(IBaseFilter
* iface
)
1507 TestFilterImpl
*This
= impl_from_IBaseFilter(iface
);
1508 ULONG refCount
= InterlockedIncrement(&This
->refCount
);
1513 static ULONG WINAPI
TestFilter_Release(IBaseFilter
* iface
)
1515 TestFilterImpl
*This
= impl_from_IBaseFilter(iface
);
1516 ULONG refCount
= InterlockedDecrement(&This
->refCount
);
1522 for (i
= 0; i
< This
->nPins
; i
++)
1526 if (SUCCEEDED(IPin_ConnectedTo(This
->ppPins
[i
], &pConnectedTo
)))
1528 IPin_Disconnect(pConnectedTo
);
1529 IPin_Release(pConnectedTo
);
1531 IPin_Disconnect(This
->ppPins
[i
]);
1533 IPin_Release(This
->ppPins
[i
]);
1536 CoTaskMemFree(This
->ppPins
);
1538 DeleteCriticalSection(&This
->csFilter
);
1540 CoTaskMemFree(This
);
1547 /** IPersist methods **/
1549 static HRESULT WINAPI
TestFilter_GetClassID(IBaseFilter
* iface
, CLSID
* pClsid
)
1551 TestFilterImpl
*This
= impl_from_IBaseFilter(iface
);
1553 *pClsid
= This
->clsid
;
1558 /** IMediaFilter methods **/
1560 static HRESULT WINAPI
TestFilter_Stop(IBaseFilter
* iface
)
1565 static HRESULT WINAPI
TestFilter_Pause(IBaseFilter
* iface
)
1570 static HRESULT WINAPI
TestFilter_Run(IBaseFilter
* iface
, REFERENCE_TIME tStart
)
1575 static HRESULT WINAPI
TestFilter_GetState(IBaseFilter
* iface
, DWORD dwMilliSecsTimeout
, FILTER_STATE
*pState
)
1577 TestFilterImpl
*This
= impl_from_IBaseFilter(iface
);
1579 EnterCriticalSection(&This
->csFilter
);
1581 *pState
= This
->state
;
1583 LeaveCriticalSection(&This
->csFilter
);
1588 static HRESULT WINAPI
TestFilter_SetSyncSource(IBaseFilter
* iface
, IReferenceClock
*pClock
)
1593 static HRESULT WINAPI
TestFilter_GetSyncSource(IBaseFilter
* iface
, IReferenceClock
**ppClock
)
1598 /** IBaseFilter implementation **/
1600 static HRESULT
getpin_callback(TestFilterImpl
*tf
, ULONG pos
, IPin
**pin
, DWORD
*lastsynctick
)
1602 /* Our pins are static, not changing so setting static tick count is ok */
1605 if (pos
>= tf
->nPins
)
1608 *pin
= tf
->ppPins
[pos
];
1613 static HRESULT WINAPI
TestFilter_EnumPins(IBaseFilter
* iface
, IEnumPins
**ppEnum
)
1615 TestFilterImpl
*This
= impl_from_IBaseFilter(iface
);
1617 return createenumpins(ppEnum
, getpin_callback
, This
);
1620 static HRESULT WINAPI
TestFilter_FindPin(IBaseFilter
* iface
, LPCWSTR Id
, IPin
**ppPin
)
1625 static HRESULT WINAPI
TestFilter_QueryFilterInfo(IBaseFilter
* iface
, FILTER_INFO
*pInfo
)
1627 TestFilterImpl
*This
= impl_from_IBaseFilter(iface
);
1629 lstrcpyW(pInfo
->achName
, This
->filterInfo
.achName
);
1630 pInfo
->pGraph
= This
->filterInfo
.pGraph
;
1633 IFilterGraph_AddRef(pInfo
->pGraph
);
1638 static HRESULT WINAPI
TestFilter_JoinFilterGraph(IBaseFilter
* iface
, IFilterGraph
*pGraph
, LPCWSTR pName
)
1641 TestFilterImpl
*This
= impl_from_IBaseFilter(iface
);
1643 EnterCriticalSection(&This
->csFilter
);
1646 lstrcpyW(This
->filterInfo
.achName
, pName
);
1648 *This
->filterInfo
.achName
= '\0';
1649 This
->filterInfo
.pGraph
= pGraph
; /* NOTE: do NOT increase ref. count */
1651 LeaveCriticalSection(&This
->csFilter
);
1656 static HRESULT WINAPI
TestFilter_QueryVendorInfo(IBaseFilter
* iface
, LPWSTR
*pVendorInfo
)
1661 static const IBaseFilterVtbl TestFilter_Vtbl
=
1663 TestFilter_QueryInterface
,
1666 TestFilter_GetClassID
,
1670 TestFilter_GetState
,
1671 TestFilter_SetSyncSource
,
1672 TestFilter_GetSyncSource
,
1673 TestFilter_EnumPins
,
1675 TestFilter_QueryFilterInfo
,
1676 TestFilter_JoinFilterGraph
,
1677 TestFilter_QueryVendorInfo
1680 /* IClassFactory implementation */
1682 typedef struct TestClassFactoryImpl
1684 IClassFactory IClassFactory_iface
;
1685 const TestFilterPinData
*filterPinData
;
1687 } TestClassFactoryImpl
;
1689 static inline TestClassFactoryImpl
*impl_from_IClassFactory(IClassFactory
*iface
)
1691 return CONTAINING_RECORD(iface
, TestClassFactoryImpl
, IClassFactory_iface
);
1694 static HRESULT WINAPI
Test_IClassFactory_QueryInterface(
1695 LPCLASSFACTORY iface
,
1699 if (ppvObj
== NULL
) return E_POINTER
;
1701 if (IsEqualGUID(riid
, &IID_IUnknown
) ||
1702 IsEqualGUID(riid
, &IID_IClassFactory
))
1705 IClassFactory_AddRef(iface
);
1710 return E_NOINTERFACE
;
1713 static ULONG WINAPI
Test_IClassFactory_AddRef(LPCLASSFACTORY iface
)
1715 return 2; /* non-heap-based object */
1718 static ULONG WINAPI
Test_IClassFactory_Release(LPCLASSFACTORY iface
)
1720 return 1; /* non-heap-based object */
1723 static HRESULT WINAPI
Test_IClassFactory_CreateInstance(
1724 LPCLASSFACTORY iface
,
1725 LPUNKNOWN pUnkOuter
,
1729 TestClassFactoryImpl
*This
= impl_from_IClassFactory(iface
);
1731 TestFilterImpl
*testfilter
;
1735 if (pUnkOuter
) return CLASS_E_NOAGGREGATION
;
1737 hr
= createtestfilter(This
->clsid
, This
->filterPinData
, &testfilter
);
1738 if (SUCCEEDED(hr
)) {
1739 hr
= IBaseFilter_QueryInterface(&testfilter
->IBaseFilter_iface
, riid
, ppvObj
);
1740 IBaseFilter_Release(&testfilter
->IBaseFilter_iface
);
1745 static HRESULT WINAPI
Test_IClassFactory_LockServer(
1746 LPCLASSFACTORY iface
,
1752 static IClassFactoryVtbl TestClassFactory_Vtbl
=
1754 Test_IClassFactory_QueryInterface
,
1755 Test_IClassFactory_AddRef
,
1756 Test_IClassFactory_Release
,
1757 Test_IClassFactory_CreateInstance
,
1758 Test_IClassFactory_LockServer
1761 static HRESULT
get_connected_filter_name(TestFilterImpl
*pFilter
, char *FilterName
)
1765 FILTER_INFO filterInfo
;
1770 hr
= IPin_ConnectedTo(pFilter
->ppPins
[0], &pin
);
1771 ok(hr
== S_OK
, "IPin_ConnectedTo failed with %x\n", hr
);
1772 if (FAILED(hr
)) return hr
;
1774 hr
= IPin_QueryPinInfo(pin
, &pinInfo
);
1775 ok(hr
== S_OK
, "IPin_QueryPinInfo failed with %x\n", hr
);
1777 if (FAILED(hr
)) return hr
;
1779 SetLastError(0xdeadbeef);
1780 hr
= IBaseFilter_QueryFilterInfo(pinInfo
.pFilter
, &filterInfo
);
1781 if (hr
== S_OK
&& GetLastError() == ERROR_CALL_NOT_IMPLEMENTED
)
1783 IBaseFilter_Release(pinInfo
.pFilter
);
1786 ok(hr
== S_OK
, "IBaseFilter_QueryFilterInfo failed with %x\n", hr
);
1787 IBaseFilter_Release(pinInfo
.pFilter
);
1788 if (FAILED(hr
)) return hr
;
1790 IFilterGraph_Release(filterInfo
.pGraph
);
1792 WideCharToMultiByte(CP_ACP
, 0, filterInfo
.achName
, -1, FilterName
, MAX_FILTER_NAME
, NULL
, NULL
);
1797 static void test_render_filter_priority(void)
1799 /* Tests filter choice priorities in Render(). */
1800 DWORD cookie1
= 0, cookie2
= 0, cookie3
= 0;
1802 IFilterGraph2
* pgraph2
= NULL
;
1803 IFilterMapper2
*pMapper2
= NULL
;
1804 TestFilterImpl
*ptestfilter
= NULL
;
1805 TestFilterImpl
*ptestfilter2
= NULL
;
1806 static const CLSID CLSID_TestFilter2
= {
1810 {0xe8, 0x9b, 0x00, 0x19, 0x66, 0x2f, 0xf0, 0xce}
1812 static const CLSID CLSID_TestFilter3
= {
1816 {0xe8, 0x9b, 0x00, 0x19, 0x66, 0x2f, 0xf0, 0xce}
1818 static const CLSID CLSID_TestFilter4
= {
1822 {0xe8, 0x9b, 0x00, 0x19, 0x66, 0x2f, 0xf0, 0xce}
1824 static const GUID mediasubtype1
= {
1828 {0xe8, 0x9b, 0x00, 0x19, 0x66, 0x2f, 0xf0, 0xce}
1830 static const GUID mediasubtype2
= {
1834 {0xe8, 0x9b, 0x00, 0x19, 0x66, 0x2f, 0xf0, 0xce}
1836 static const TestFilterPinData PinData1
[] = {
1837 { PINDIR_OUTPUT
, &mediasubtype1
},
1840 static const TestFilterPinData PinData2
[] = {
1841 { PINDIR_INPUT
, &mediasubtype1
},
1844 static const TestFilterPinData PinData3
[] = {
1845 { PINDIR_INPUT
, &GUID_NULL
},
1848 static const TestFilterPinData PinData4
[] = {
1849 { PINDIR_INPUT
, &mediasubtype1
},
1850 { PINDIR_OUTPUT
, &mediasubtype2
},
1853 static const TestFilterPinData PinData5
[] = {
1854 { PINDIR_INPUT
, &mediasubtype2
},
1857 TestClassFactoryImpl Filter1ClassFactory
= {
1858 { &TestClassFactory_Vtbl
},
1859 PinData2
, &CLSID_TestFilter2
1861 TestClassFactoryImpl Filter2ClassFactory
= {
1862 { &TestClassFactory_Vtbl
},
1863 PinData4
, &CLSID_TestFilter3
1865 TestClassFactoryImpl Filter3ClassFactory
= {
1866 { &TestClassFactory_Vtbl
},
1867 PinData5
, &CLSID_TestFilter4
1869 char ConnectedFilterName1
[MAX_FILTER_NAME
];
1870 char ConnectedFilterName2
[MAX_FILTER_NAME
];
1872 REGFILTERPINS2 rgPins2
[2];
1873 REGPINTYPES rgPinType
[2];
1874 static const WCHAR wszFilterInstanceName1
[] = {'T', 'e', 's', 't', 'f', 'i', 'l', 't', 'e', 'r', 'I',
1875 'n', 's', 't', 'a', 'n', 'c', 'e', '1', 0 };
1876 static const WCHAR wszFilterInstanceName2
[] = {'T', 'e', 's', 't', 'f', 'i', 'l', 't', 'e', 'r', 'I',
1877 'n', 's', 't', 'a', 'n', 'c', 'e', '2', 0 };
1878 static const WCHAR wszFilterInstanceName3
[] = {'T', 'e', 's', 't', 'f', 'i', 'l', 't', 'e', 'r', 'I',
1879 'n', 's', 't', 'a', 'n', 'c', 'e', '3', 0 };
1880 static const WCHAR wszFilterInstanceName4
[] = {'T', 'e', 's', 't', 'f', 'i', 'l', 't', 'e', 'r', 'I',
1881 'n', 's', 't', 'a', 'n', 'c', 'e', '4', 0 };
1883 /* Test which renderer of two already added to the graph will be chosen
1884 * (one is "exact" match, other is "wildcard" match. Seems to depend
1885 * on the order in which filters are added to the graph, thus indicating
1886 * no preference given to exact match. */
1887 hr
= CoCreateInstance(&CLSID_FilterGraph
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IFilterGraph2
, (LPVOID
*)&pgraph2
);
1888 ok(hr
== S_OK
, "CoCreateInstance failed with %08x\n", hr
);
1889 if (!pgraph2
) return;
1891 hr
= createtestfilter(&GUID_NULL
, PinData1
, &ptestfilter
);
1892 ok(hr
== S_OK
, "createtestfilter failed with %08x\n", hr
);
1893 if (FAILED(hr
)) goto out
;
1895 hr
= IFilterGraph2_AddFilter(pgraph2
, &ptestfilter
->IBaseFilter_iface
, wszFilterInstanceName1
);
1896 ok(hr
== S_OK
, "IFilterGraph2_AddFilter failed with %08x\n", hr
);
1898 hr
= createtestfilter(&GUID_NULL
, PinData2
, &ptestfilter2
);
1899 ok(hr
== S_OK
, "createtestfilter failed with %08x\n", hr
);
1900 if (FAILED(hr
)) goto out
;
1902 hr
= IFilterGraph2_AddFilter(pgraph2
, &ptestfilter2
->IBaseFilter_iface
, wszFilterInstanceName2
);
1903 ok(hr
== S_OK
, "IFilterGraph2_AddFilter failed with %08x\n", hr
);
1905 IBaseFilter_Release(&ptestfilter2
->IBaseFilter_iface
);
1906 ptestfilter2
= NULL
;
1908 hr
= createtestfilter(&GUID_NULL
, PinData3
, &ptestfilter2
);
1909 ok(hr
== S_OK
, "createtestfilter failed with %08x\n", hr
);
1910 if (FAILED(hr
)) goto out
;
1912 hr
= IFilterGraph2_AddFilter(pgraph2
, &ptestfilter2
->IBaseFilter_iface
, wszFilterInstanceName3
);
1913 ok(hr
== S_OK
, "IFilterGraph2_AddFilter failed with %08x\n", hr
);
1915 hr
= IFilterGraph2_Render(pgraph2
, ptestfilter
->ppPins
[0]);
1916 ok(hr
== S_OK
, "IFilterGraph2_Render failed with %08x\n", hr
);
1918 hr
= get_connected_filter_name(ptestfilter
, ConnectedFilterName1
);
1920 IFilterGraph2_Release(pgraph2
);
1922 IBaseFilter_Release(&ptestfilter
->IBaseFilter_iface
);
1924 IBaseFilter_Release(&ptestfilter2
->IBaseFilter_iface
);
1925 ptestfilter2
= NULL
;
1927 if (hr
== E_NOTIMPL
)
1929 win_skip("Needed functions are not implemented\n");
1933 hr
= CoCreateInstance(&CLSID_FilterGraph
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IFilterGraph2
, (LPVOID
*)&pgraph2
);
1934 ok(hr
== S_OK
, "CoCreateInstance failed with %08x\n", hr
);
1935 if (!pgraph2
) goto out
;
1937 hr
= createtestfilter(&GUID_NULL
, PinData1
, &ptestfilter
);
1938 ok(hr
== S_OK
, "createtestfilter failed with %08x\n", hr
);
1939 if (FAILED(hr
)) goto out
;
1941 hr
= IFilterGraph2_AddFilter(pgraph2
, &ptestfilter
->IBaseFilter_iface
, wszFilterInstanceName1
);
1942 ok(hr
== S_OK
, "IFilterGraph2_AddFilter failed with %08x\n", hr
);
1944 hr
= createtestfilter(&GUID_NULL
, PinData3
, &ptestfilter2
);
1945 ok(hr
== S_OK
, "createtestfilter failed with %08x\n", hr
);
1946 if (FAILED(hr
)) goto out
;
1948 hr
= IFilterGraph2_AddFilter(pgraph2
, &ptestfilter2
->IBaseFilter_iface
, wszFilterInstanceName3
);
1949 ok(hr
== S_OK
, "IFilterGraph2_AddFilter failed with %08x\n", hr
);
1951 IBaseFilter_Release(&ptestfilter2
->IBaseFilter_iface
);
1952 ptestfilter2
= NULL
;
1954 hr
= createtestfilter(&GUID_NULL
, PinData2
, &ptestfilter2
);
1955 ok(hr
== S_OK
, "createtestfilter failed with %08x\n", hr
);
1956 if (FAILED(hr
)) goto out
;
1958 hr
= IFilterGraph2_AddFilter(pgraph2
, &ptestfilter2
->IBaseFilter_iface
, wszFilterInstanceName2
);
1959 ok(hr
== S_OK
, "IFilterGraph2_AddFilter failed with %08x\n", hr
);
1961 hr
= IFilterGraph2_Render(pgraph2
, ptestfilter
->ppPins
[0]);
1962 ok(hr
== S_OK
, "IFilterGraph2_Render failed with %08x\n", hr
);
1964 hr
= IFilterGraph2_Disconnect(pgraph2
, NULL
);
1965 ok(hr
== E_POINTER
, "IFilterGraph2_Disconnect failed. Expected E_POINTER, received %08x\n", hr
);
1967 get_connected_filter_name(ptestfilter
, ConnectedFilterName2
);
1968 ok(strcmp(ConnectedFilterName1
, ConnectedFilterName2
),
1969 "expected connected filters to be different but got %s both times\n", ConnectedFilterName1
);
1971 IFilterGraph2_Release(pgraph2
);
1973 IBaseFilter_Release(&ptestfilter
->IBaseFilter_iface
);
1975 IBaseFilter_Release(&ptestfilter2
->IBaseFilter_iface
);
1976 ptestfilter2
= NULL
;
1978 /* Test if any preference is given to existing renderer which renders the pin directly vs
1979 an existing renderer which renders the pin indirectly, through an additional middle filter,
1980 again trying different orders of creation. Native appears not to give a preference. */
1982 hr
= CoCreateInstance(&CLSID_FilterGraph
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IFilterGraph2
, (LPVOID
*)&pgraph2
);
1983 ok(hr
== S_OK
, "CoCreateInstance failed with %08x\n", hr
);
1984 if (!pgraph2
) goto out
;
1986 hr
= createtestfilter(&GUID_NULL
, PinData1
, &ptestfilter
);
1987 ok(hr
== S_OK
, "createtestfilter failed with %08x\n", hr
);
1988 if (FAILED(hr
)) goto out
;
1990 hr
= IFilterGraph2_AddFilter(pgraph2
, &ptestfilter
->IBaseFilter_iface
, wszFilterInstanceName1
);
1991 ok(hr
== S_OK
, "IFilterGraph2_AddFilter failed with %08x\n", hr
);
1993 hr
= createtestfilter(&GUID_NULL
, PinData2
, &ptestfilter2
);
1994 ok(hr
== S_OK
, "createtestfilter failed with %08x\n", hr
);
1995 if (FAILED(hr
)) goto out
;
1997 hr
= IFilterGraph2_AddFilter(pgraph2
, &ptestfilter2
->IBaseFilter_iface
, wszFilterInstanceName2
);
1998 ok(hr
== S_OK
, "IFilterGraph2_AddFilter failed with %08x\n", hr
);
2000 IBaseFilter_Release(&ptestfilter2
->IBaseFilter_iface
);
2001 ptestfilter2
= NULL
;
2003 hr
= createtestfilter(&GUID_NULL
, PinData4
, &ptestfilter2
);
2004 ok(hr
== S_OK
, "createtestfilter failed with %08x\n", hr
);
2005 if (FAILED(hr
)) goto out
;
2007 hr
= IFilterGraph2_AddFilter(pgraph2
, &ptestfilter2
->IBaseFilter_iface
, wszFilterInstanceName3
);
2008 ok(hr
== S_OK
, "IFilterGraph2_AddFilter failed with %08x\n", hr
);
2010 IBaseFilter_Release(&ptestfilter2
->IBaseFilter_iface
);
2011 ptestfilter2
= NULL
;
2013 hr
= createtestfilter(&GUID_NULL
, PinData5
, &ptestfilter2
);
2014 ok(hr
== S_OK
, "createtestfilter failed with %08x\n", hr
);
2015 if (FAILED(hr
)) goto out
;
2017 hr
= IFilterGraph2_AddFilter(pgraph2
, &ptestfilter2
->IBaseFilter_iface
, wszFilterInstanceName4
);
2018 ok(hr
== S_OK
, "IFilterGraph2_AddFilter failed with %08x\n", hr
);
2020 hr
= IFilterGraph2_Render(pgraph2
, ptestfilter
->ppPins
[0]);
2021 ok(hr
== S_OK
, "IFilterGraph2_Render failed with %08x\n", hr
);
2023 get_connected_filter_name(ptestfilter
, ConnectedFilterName1
);
2024 ok(!strcmp(ConnectedFilterName1
, "TestfilterInstance3") || !strcmp(ConnectedFilterName1
, "TestfilterInstance2"),
2025 "unexpected connected filter: %s\n", ConnectedFilterName1
);
2027 IFilterGraph2_Release(pgraph2
);
2029 IBaseFilter_Release(&ptestfilter
->IBaseFilter_iface
);
2031 IBaseFilter_Release(&ptestfilter2
->IBaseFilter_iface
);
2032 ptestfilter2
= NULL
;
2034 hr
= CoCreateInstance(&CLSID_FilterGraph
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IFilterGraph2
, (LPVOID
*)&pgraph2
);
2035 ok(hr
== S_OK
, "CoCreateInstance failed with %08x\n", hr
);
2036 if (!pgraph2
) goto out
;
2038 hr
= createtestfilter(&GUID_NULL
, PinData1
, &ptestfilter
);
2039 ok(hr
== S_OK
, "createtestfilter failed with %08x\n", hr
);
2040 if (FAILED(hr
)) goto out
;
2042 hr
= IFilterGraph2_AddFilter(pgraph2
, &ptestfilter
->IBaseFilter_iface
, wszFilterInstanceName1
);
2043 ok(hr
== S_OK
, "IFilterGraph2_AddFilter failed with %08x\n", hr
);
2045 hr
= createtestfilter(&GUID_NULL
, PinData4
, &ptestfilter2
);
2046 ok(hr
== S_OK
, "createtestfilter failed with %08x\n", hr
);
2047 if (FAILED(hr
)) goto out
;
2049 hr
= IFilterGraph2_AddFilter(pgraph2
, &ptestfilter2
->IBaseFilter_iface
, wszFilterInstanceName3
);
2050 ok(hr
== S_OK
, "IFilterGraph2_AddFilter failed with %08x\n", hr
);
2052 IBaseFilter_Release(&ptestfilter2
->IBaseFilter_iface
);
2053 ptestfilter2
= NULL
;
2055 hr
= createtestfilter(&GUID_NULL
, PinData5
, &ptestfilter2
);
2056 ok(hr
== S_OK
, "createtestfilter failed with %08x\n", hr
);
2057 if (FAILED(hr
)) goto out
;
2059 hr
= IFilterGraph2_AddFilter(pgraph2
, &ptestfilter2
->IBaseFilter_iface
, wszFilterInstanceName4
);
2060 ok(hr
== S_OK
, "IFilterGraph2_AddFilter failed with %08x\n", hr
);
2062 IBaseFilter_Release(&ptestfilter2
->IBaseFilter_iface
);
2063 ptestfilter2
= NULL
;
2065 hr
= createtestfilter(&GUID_NULL
, PinData2
, &ptestfilter2
);
2066 ok(hr
== S_OK
, "createtestfilter failed with %08x\n", hr
);
2067 if (FAILED(hr
)) goto out
;
2069 hr
= IFilterGraph2_AddFilter(pgraph2
, &ptestfilter2
->IBaseFilter_iface
, wszFilterInstanceName2
);
2070 ok(hr
== S_OK
, "IFilterGraph2_AddFilter failed with %08x\n", hr
);
2072 hr
= IFilterGraph2_Render(pgraph2
, ptestfilter
->ppPins
[0]);
2073 ok(hr
== S_OK
, "IFilterGraph2_Render failed with %08x\n", hr
);
2075 get_connected_filter_name(ptestfilter
, ConnectedFilterName2
);
2076 ok(!strcmp(ConnectedFilterName2
, "TestfilterInstance3") || !strcmp(ConnectedFilterName2
, "TestfilterInstance2"),
2077 "unexpected connected filter: %s\n", ConnectedFilterName2
);
2078 ok(strcmp(ConnectedFilterName1
, ConnectedFilterName2
),
2079 "expected connected filters to be different but got %s both times\n", ConnectedFilterName1
);
2081 IFilterGraph2_Release(pgraph2
);
2083 IBaseFilter_Release(&ptestfilter
->IBaseFilter_iface
);
2085 IBaseFilter_Release(&ptestfilter2
->IBaseFilter_iface
);
2086 ptestfilter2
= NULL
;
2088 /* Test if renderers are tried before non-renderers (intermediary filters). */
2089 hr
= CoCreateInstance(&CLSID_FilterGraph
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IFilterGraph2
, (LPVOID
*)&pgraph2
);
2090 ok(hr
== S_OK
, "CoCreateInstance failed with %08x\n", hr
);
2091 if (!pgraph2
) goto out
;
2093 hr
= CoCreateInstance(&CLSID_FilterMapper2
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IFilterMapper2
, (LPVOID
*)&pMapper2
);
2094 ok(hr
== S_OK
, "CoCreateInstance failed with %08x\n", hr
);
2095 if (!pMapper2
) goto out
;
2097 hr
= createtestfilter(&GUID_NULL
, PinData1
, &ptestfilter
);
2098 ok(hr
== S_OK
, "createtestfilter failed with %08x\n", hr
);
2099 if (FAILED(hr
)) goto out
;
2101 hr
= IFilterGraph2_AddFilter(pgraph2
, &ptestfilter
->IBaseFilter_iface
, wszFilterInstanceName1
);
2102 ok(hr
== S_OK
, "IFilterGraph2_AddFilter failed with %08x\n", hr
);
2104 /* Register our filters with COM and with Filtermapper. */
2105 hr
= CoRegisterClassObject(Filter1ClassFactory
.clsid
,
2106 (IUnknown
*)&Filter1ClassFactory
.IClassFactory_iface
, CLSCTX_INPROC_SERVER
,
2107 REGCLS_MULTIPLEUSE
, &cookie1
);
2108 ok(hr
== S_OK
, "CoRegisterClassObject failed with %08x\n", hr
);
2109 if (FAILED(hr
)) goto out
;
2110 hr
= CoRegisterClassObject(Filter2ClassFactory
.clsid
,
2111 (IUnknown
*)&Filter2ClassFactory
.IClassFactory_iface
, CLSCTX_INPROC_SERVER
,
2112 REGCLS_MULTIPLEUSE
, &cookie2
);
2113 ok(hr
== S_OK
, "CoRegisterClassObject failed with %08x\n", hr
);
2114 if (FAILED(hr
)) goto out
;
2115 hr
= CoRegisterClassObject(Filter3ClassFactory
.clsid
,
2116 (IUnknown
*)&Filter3ClassFactory
.IClassFactory_iface
, CLSCTX_INPROC_SERVER
,
2117 REGCLS_MULTIPLEUSE
, &cookie3
);
2118 ok(hr
== S_OK
, "CoRegisterClassObject failed with %08x\n", hr
);
2119 if (FAILED(hr
)) goto out
;
2122 rgf2
.dwMerit
= MERIT_UNLIKELY
;
2123 S2(U(rgf2
)).cPins2
= 1;
2124 S2(U(rgf2
)).rgPins2
= rgPins2
;
2125 rgPins2
[0].dwFlags
= REG_PINFLAG_B_RENDERER
;
2126 rgPins2
[0].cInstances
= 1;
2127 rgPins2
[0].nMediaTypes
= 1;
2128 rgPins2
[0].lpMediaType
= &rgPinType
[0];
2129 rgPins2
[0].nMediums
= 0;
2130 rgPins2
[0].lpMedium
= NULL
;
2131 rgPins2
[0].clsPinCategory
= NULL
;
2132 rgPinType
[0].clsMajorType
= &MEDIATYPE_Video
;
2133 rgPinType
[0].clsMinorType
= &mediasubtype1
;
2135 hr
= IFilterMapper2_RegisterFilter(pMapper2
, &CLSID_TestFilter2
, wszFilterInstanceName2
, NULL
,
2136 &CLSID_LegacyAmFilterCategory
, NULL
, &rgf2
);
2137 if (hr
== E_ACCESSDENIED
)
2138 skip("Not authorized to register filters\n");
2141 ok(hr
== S_OK
, "IFilterMapper2_RegisterFilter failed with %x\n", hr
);
2143 rgf2
.dwMerit
= MERIT_PREFERRED
;
2144 rgPinType
[0].clsMinorType
= &mediasubtype2
;
2146 hr
= IFilterMapper2_RegisterFilter(pMapper2
, &CLSID_TestFilter4
, wszFilterInstanceName4
, NULL
,
2147 &CLSID_LegacyAmFilterCategory
, NULL
, &rgf2
);
2148 ok(hr
== S_OK
, "IFilterMapper2_RegisterFilter failed with %x\n", hr
);
2150 S2(U(rgf2
)).cPins2
= 2;
2151 rgPins2
[0].dwFlags
= 0;
2152 rgPinType
[0].clsMinorType
= &mediasubtype1
;
2154 rgPins2
[1].dwFlags
= REG_PINFLAG_B_OUTPUT
;
2155 rgPins2
[1].cInstances
= 1;
2156 rgPins2
[1].nMediaTypes
= 1;
2157 rgPins2
[1].lpMediaType
= &rgPinType
[1];
2158 rgPins2
[1].nMediums
= 0;
2159 rgPins2
[1].lpMedium
= NULL
;
2160 rgPins2
[1].clsPinCategory
= NULL
;
2161 rgPinType
[1].clsMajorType
= &MEDIATYPE_Video
;
2162 rgPinType
[1].clsMinorType
= &mediasubtype2
;
2164 hr
= IFilterMapper2_RegisterFilter(pMapper2
, &CLSID_TestFilter3
, wszFilterInstanceName3
, NULL
,
2165 &CLSID_LegacyAmFilterCategory
, NULL
, &rgf2
);
2166 ok(hr
== S_OK
, "IFilterMapper2_RegisterFilter failed with %x\n", hr
);
2168 hr
= IFilterGraph2_Render(pgraph2
, ptestfilter
->ppPins
[0]);
2169 ok(hr
== S_OK
, "IFilterGraph2_Render failed with %08x\n", hr
);
2171 get_connected_filter_name(ptestfilter
, ConnectedFilterName1
);
2172 ok(!strcmp(ConnectedFilterName1
, "TestfilterInstance3"),
2173 "unexpected connected filter: %s\n", ConnectedFilterName1
);
2175 hr
= IFilterMapper2_UnregisterFilter(pMapper2
, &CLSID_LegacyAmFilterCategory
, NULL
,
2176 &CLSID_TestFilter2
);
2177 ok(hr
== S_OK
, "IFilterMapper2_UnregisterFilter failed with %x\n", hr
);
2178 hr
= IFilterMapper2_UnregisterFilter(pMapper2
, &CLSID_LegacyAmFilterCategory
, NULL
,
2179 &CLSID_TestFilter3
);
2180 ok(hr
== S_OK
, "IFilterMapper2_UnregisterFilter failed with %x\n", hr
);
2181 hr
= IFilterMapper2_UnregisterFilter(pMapper2
, &CLSID_LegacyAmFilterCategory
, NULL
,
2182 &CLSID_TestFilter4
);
2183 ok(hr
== S_OK
, "IFilterMapper2_UnregisterFilter failed with %x\n", hr
);
2188 if (ptestfilter
) IBaseFilter_Release(&ptestfilter
->IBaseFilter_iface
);
2189 if (ptestfilter2
) IBaseFilter_Release(&ptestfilter2
->IBaseFilter_iface
);
2190 if (pgraph2
) IFilterGraph2_Release(pgraph2
);
2191 if (pMapper2
) IFilterMapper2_Release(pMapper2
);
2193 hr
= CoRevokeClassObject(cookie1
);
2194 ok(hr
== S_OK
, "CoRevokeClassObject failed with %08x\n", hr
);
2195 hr
= CoRevokeClassObject(cookie2
);
2196 ok(hr
== S_OK
, "CoRevokeClassObject failed with %08x\n", hr
);
2197 hr
= CoRevokeClassObject(cookie3
);
2198 ok(hr
== S_OK
, "CoRevokeClassObject failed with %08x\n", hr
);
2201 typedef struct IUnknownImpl
2203 IUnknown IUnknown_iface
;
2208 static IUnknownImpl
*IUnknownImpl_from_iface(IUnknown
* iface
)
2210 return CONTAINING_RECORD(iface
, IUnknownImpl
, IUnknown_iface
);
2213 static HRESULT WINAPI
IUnknownImpl_QueryInterface(IUnknown
* iface
, REFIID riid
, LPVOID
* ppv
)
2215 ok(0, "QueryInterface should not be called for %s\n", wine_dbgstr_guid(riid
));
2216 return E_NOINTERFACE
;
2219 static ULONG WINAPI
IUnknownImpl_AddRef(IUnknown
* iface
)
2221 IUnknownImpl
*This
= IUnknownImpl_from_iface(iface
);
2222 This
->AddRef_called
++;
2226 static ULONG WINAPI
IUnknownImpl_Release(IUnknown
* iface
)
2228 IUnknownImpl
*This
= IUnknownImpl_from_iface(iface
);
2229 This
->Release_called
++;
2233 static CONST_VTBL IUnknownVtbl IUnknownImpl_Vtbl
=
2235 IUnknownImpl_QueryInterface
,
2236 IUnknownImpl_AddRef
,
2237 IUnknownImpl_Release
2240 static void test_aggregate_filter_graph(void)
2245 IUnknownImpl unk_outer
= { { &IUnknownImpl_Vtbl
}, 0, 0 };
2247 hr
= CoCreateInstance(&CLSID_FilterGraph
, &unk_outer
.IUnknown_iface
, CLSCTX_INPROC_SERVER
,
2248 &IID_IUnknown
, (void **)&pgraph
);
2249 ok(hr
== S_OK
, "CoCreateInstance returned %x\n", hr
);
2250 ok(pgraph
!= &unk_outer
.IUnknown_iface
, "pgraph = %p, expected not %p\n", pgraph
, &unk_outer
.IUnknown_iface
);
2252 hr
= IUnknown_QueryInterface(pgraph
, &IID_IUnknown
, (void **)&punk
);
2253 ok(hr
== S_OK
, "CoCreateInstance returned %x\n", hr
);
2254 ok(punk
!= &unk_outer
.IUnknown_iface
, "punk = %p, expected not %p\n", punk
, &unk_outer
.IUnknown_iface
);
2255 IUnknown_Release(punk
);
2257 ok(unk_outer
.AddRef_called
== 0, "IUnknownImpl_AddRef called %d times\n", unk_outer
.AddRef_called
);
2258 ok(unk_outer
.Release_called
== 0, "IUnknownImpl_Release called %d times\n", unk_outer
.Release_called
);
2259 unk_outer
.AddRef_called
= 0;
2260 unk_outer
.Release_called
= 0;
2262 hr
= IUnknown_QueryInterface(pgraph
, &IID_IFilterMapper
, (void **)&punk
);
2263 ok(hr
== S_OK
, "CoCreateInstance returned %x\n", hr
);
2264 ok(punk
!= &unk_outer
.IUnknown_iface
, "punk = %p, expected not %p\n", punk
, &unk_outer
.IUnknown_iface
);
2265 IUnknown_Release(punk
);
2267 ok(unk_outer
.AddRef_called
== 1, "IUnknownImpl_AddRef called %d times\n", unk_outer
.AddRef_called
);
2268 ok(unk_outer
.Release_called
== 1, "IUnknownImpl_Release called %d times\n", unk_outer
.Release_called
);
2269 unk_outer
.AddRef_called
= 0;
2270 unk_outer
.Release_called
= 0;
2272 hr
= IUnknown_QueryInterface(pgraph
, &IID_IFilterMapper2
, (void **)&punk
);
2273 ok(hr
== S_OK
, "CoCreateInstance returned %x\n", hr
);
2274 ok(punk
!= &unk_outer
.IUnknown_iface
, "punk = %p, expected not %p\n", punk
, &unk_outer
.IUnknown_iface
);
2275 IUnknown_Release(punk
);
2277 ok(unk_outer
.AddRef_called
== 1, "IUnknownImpl_AddRef called %d times\n", unk_outer
.AddRef_called
);
2278 ok(unk_outer
.Release_called
== 1, "IUnknownImpl_Release called %d times\n", unk_outer
.Release_called
);
2279 unk_outer
.AddRef_called
= 0;
2280 unk_outer
.Release_called
= 0;
2282 hr
= IUnknown_QueryInterface(pgraph
, &IID_IFilterMapper3
, (void **)&punk
);
2283 ok(hr
== S_OK
, "CoCreateInstance returned %x\n", hr
);
2284 ok(punk
!= &unk_outer
.IUnknown_iface
, "punk = %p, expected not %p\n", punk
, &unk_outer
.IUnknown_iface
);
2285 IUnknown_Release(punk
);
2287 ok(unk_outer
.AddRef_called
== 1, "IUnknownImpl_AddRef called %d times\n", unk_outer
.AddRef_called
);
2288 ok(unk_outer
.Release_called
== 1, "IUnknownImpl_Release called %d times\n", unk_outer
.Release_called
);
2290 IUnknown_Release(pgraph
);
2293 START_TEST(filtergraph
)
2296 CoInitializeEx(NULL
, COINIT_MULTITHREADED
);
2297 hr
= CoCreateInstance(&CLSID_FilterGraph
, NULL
, CLSCTX_INPROC_SERVER
,
2298 &IID_IGraphBuilder
, (LPVOID
*)&pgraph
);
2300 skip("Creating filtergraph returned %08x, skipping tests\n", hr
);
2303 IGraphBuilder_Release(pgraph
);
2304 test_render_run(avifile
);
2305 test_render_run(mpegfile
);
2306 test_graph_builder();
2307 test_graph_builder_addfilter();
2308 test_mediacontrol();
2309 test_filter_graph2();
2310 test_render_filter_priority();
2311 test_aggregate_filter_graph();
2313 test_render_with_multithread();