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 rungraph(void)
61 hr
= IGraphBuilder_QueryInterface(pgraph
, &IID_IMediaControl
, (LPVOID
*)&pmc
);
62 ok(hr
==S_OK
, "Cannot get IMediaControl interface returned: %x\n", hr
);
64 hr
= IGraphBuilder_QueryInterface(pgraph
, &IID_IMediaFilter
, (LPVOID
*)&pmf
);
65 ok(hr
==S_OK
, "Cannot get IMediaFilter interface returned: %x\n", hr
);
67 IMediaControl_Stop(pmc
);
69 IMediaFilter_SetSyncSource(pmf
, NULL
);
71 IMediaFilter_Release(pmf
);
73 hr
= IMediaControl_Run(pmc
);
74 ok(hr
==S_FALSE
, "Cannot run the graph returned: %x\n", hr
);
78 trace("run -> stop\n");
79 hr
= IMediaControl_Stop(pmc
);
80 ok(hr
==S_OK
|| hr
== S_FALSE
, "Cannot stop the graph returned: %x\n", hr
);
82 IGraphBuilder_SetDefaultSyncSource(pgraph
);
85 trace("stop -> pause\n");
86 hr
= IMediaControl_Pause(pmc
);
87 ok(hr
==S_OK
|| hr
== S_FALSE
, "Cannot pause the graph returned: %x\n", hr
);
90 trace("pause -> run\n");
91 hr
= IMediaControl_Run(pmc
);
92 ok(hr
==S_OK
|| hr
== S_FALSE
, "Cannot start the graph returned: %x\n", hr
);
95 trace("run -> pause\n");
96 hr
= IMediaControl_Pause(pmc
);
97 ok(hr
==S_OK
|| hr
== S_FALSE
, "Cannot pause the graph returned: %x\n", hr
);
100 trace("pause -> stop\n");
101 hr
= IMediaControl_Stop(pmc
);
102 ok(hr
==S_OK
|| hr
== S_FALSE
, "Cannot stop the graph returned: %x\n", hr
);
105 trace("pause -> run\n");
106 hr
= IMediaControl_Run(pmc
);
107 ok(hr
==S_OK
|| hr
== S_FALSE
, "Cannot start the graph returned: %x\n", hr
);
109 trace("run -> stop\n");
110 hr
= IMediaControl_Stop(pmc
);
111 ok(hr
==S_OK
|| hr
== S_FALSE
, "Cannot stop the graph returned: %x\n", hr
);
113 trace("stop -> run\n");
114 hr
= IMediaControl_Run(pmc
);
115 ok(hr
==S_OK
|| hr
== S_FALSE
, "Cannot start the graph returned: %x\n", hr
);
117 hr
= IGraphBuilder_QueryInterface(pgraph
, &IID_IMediaEvent
, (LPVOID
*)&pme
);
118 ok(hr
==S_OK
, "Cannot get IMediaEvent interface returned: %x\n", hr
);
120 hr
= IMediaEvent_GetEventHandle(pme
, (OAEVENT
*)&hEvent
);
121 ok(hr
==S_OK
, "Cannot get event handle returned: %x\n", hr
);
123 /* WaitForSingleObject(hEvent, INFINITE); */
126 hr
= IMediaEvent_Release(pme
);
127 ok(hr
==2, "Releasing mediaevent returned: %x\n", hr
);
129 hr
= IMediaControl_Stop(pmc
);
130 ok(hr
==S_OK
, "Cannot stop the graph returned: %x\n", hr
);
132 hr
= IMediaControl_Release(pmc
);
133 ok(hr
==1, "Releasing mediacontrol returned: %x\n", hr
);
136 static void releasefiltergraph(void)
140 hr
= IGraphBuilder_Release(pgraph
);
141 ok(hr
==0, "Releasing filtergraph returned: %x\n", hr
);
144 static void test_render_run(const WCHAR
*file
)
149 if (!createfiltergraph())
152 h
= CreateFileW(file
, 0, 0, NULL
, OPEN_EXISTING
, 0, NULL
);
153 if (h
!= INVALID_HANDLE_VALUE
) {
155 hr
= IGraphBuilder_RenderFile(pgraph
, file
, NULL
);
156 ok(hr
==S_OK
, "RenderFile returned: %x\n", hr
);
160 releasefiltergraph();
163 static void test_graph_builder(void)
166 IBaseFilter
*pF
= NULL
;
167 IBaseFilter
*pF2
= NULL
;
169 IEnumPins
*pEnum
= NULL
;
171 static const WCHAR testFilterW
[] = {'t','e','s','t','F','i','l','t','e','r',0};
172 static const WCHAR fooBarW
[] = {'f','o','o','B','a','r',0};
174 if (!createfiltergraph())
177 /* create video filter */
178 hr
= CoCreateInstance(&CLSID_VideoRenderer
, NULL
, CLSCTX_INPROC_SERVER
,
179 &IID_IBaseFilter
, (LPVOID
*)&pF
);
180 ok(hr
== S_OK
, "CoCreateInstance failed with %x\n", hr
);
181 ok(pF
!= NULL
, "pF is NULL\n");
183 hr
= IGraphBuilder_AddFilter(pgraph
, NULL
, testFilterW
);
184 ok(hr
== E_POINTER
, "IGraphBuilder_AddFilter returned %x\n", hr
);
186 /* add the two filters to the graph */
187 hr
= IGraphBuilder_AddFilter(pgraph
, pF
, testFilterW
);
188 ok(hr
== S_OK
, "failed to add pF to the graph: %x\n", hr
);
191 hr
= IBaseFilter_EnumPins(pF
, &pEnum
);
192 ok(hr
== S_OK
, "IBaseFilter_EnumPins failed for pF: %x\n", hr
);
193 ok(pEnum
!= NULL
, "pEnum is NULL\n");
194 hr
= IEnumPins_Next(pEnum
, 1, &pIn
, NULL
);
195 ok(hr
== S_OK
, "IEnumPins_Next failed for pF: %x\n", hr
);
196 ok(pIn
!= NULL
, "pIn is NULL\n");
197 hr
= IPin_QueryDirection(pIn
, &dir
);
198 ok(hr
== S_OK
, "IPin_QueryDirection failed: %x\n", hr
);
199 ok(dir
== PINDIR_INPUT
, "pin has wrong direction\n");
201 hr
= IGraphBuilder_FindFilterByName(pgraph
, fooBarW
, &pF2
);
202 ok(hr
== VFW_E_NOT_FOUND
, "IGraphBuilder_FindFilterByName returned %x\n", hr
);
203 ok(pF2
== NULL
, "IGraphBuilder_FindFilterByName returned %p\n", pF2
);
204 hr
= IGraphBuilder_FindFilterByName(pgraph
, testFilterW
, &pF2
);
205 ok(hr
== S_OK
, "IGraphBuilder_FindFilterByName returned %x\n", hr
);
206 ok(pF2
!= NULL
, "IGraphBuilder_FindFilterByName returned NULL\n");
207 hr
= IGraphBuilder_FindFilterByName(pgraph
, testFilterW
, NULL
);
208 ok(hr
== E_POINTER
, "IGraphBuilder_FindFilterByName returned %x\n", hr
);
210 hr
= IGraphBuilder_Connect(pgraph
, NULL
, pIn
);
211 ok(hr
== E_POINTER
, "IGraphBuilder_Connect returned %x\n", hr
);
213 hr
= IGraphBuilder_Connect(pgraph
, pIn
, NULL
);
214 ok(hr
== E_POINTER
, "IGraphBuilder_Connect returned %x\n", hr
);
216 hr
= IGraphBuilder_Connect(pgraph
, pIn
, pIn
);
217 ok(hr
== VFW_E_CANNOT_CONNECT
, "IGraphBuilder_Connect returned %x\n", hr
);
219 if (pIn
) IPin_Release(pIn
);
220 if (pEnum
) IEnumPins_Release(pEnum
);
221 if (pF
) IBaseFilter_Release(pF
);
222 if (pF2
) IBaseFilter_Release(pF2
);
224 releasefiltergraph();
227 static void test_graph_builder_addfilter(void)
230 IBaseFilter
*pF
= NULL
;
231 static const WCHAR testFilterW
[] = {'t','e','s','t','F','i','l','t','e','r',0};
233 if (!createfiltergraph())
236 hr
= IGraphBuilder_AddFilter(pgraph
, NULL
, testFilterW
);
237 ok(hr
== E_POINTER
, "IGraphBuilder_AddFilter returned: %x\n", hr
);
239 /* create video filter */
240 hr
= CoCreateInstance(&CLSID_VideoRenderer
, NULL
, CLSCTX_INPROC_SERVER
,
241 &IID_IBaseFilter
, (LPVOID
*)&pF
);
242 ok(hr
== S_OK
, "CoCreateInstance failed with %x\n", hr
);
243 ok(pF
!= NULL
, "pF is NULL\n");
245 skip("failed to created filter, skipping\n");
249 hr
= IGraphBuilder_AddFilter(pgraph
, pF
, NULL
);
250 ok(hr
== S_OK
, "IGraphBuilder_AddFilter returned: %x\n", hr
);
251 IBaseFilter_Release(pF
);
254 static void test_mediacontrol(void)
257 LONGLONG pos
= 0xdeadbeef;
258 IMediaSeeking
*seeking
= NULL
;
259 IMediaFilter
*filter
= NULL
;
260 IMediaControl
*control
= NULL
;
262 IGraphBuilder_SetDefaultSyncSource(pgraph
);
263 hr
= IGraphBuilder_QueryInterface(pgraph
, &IID_IMediaSeeking
, (void**) &seeking
);
264 ok(hr
== S_OK
, "QueryInterface IMediaControl failed: %08x\n", hr
);
268 hr
= IGraphBuilder_QueryInterface(pgraph
, &IID_IMediaFilter
, (void**) &filter
);
269 ok(hr
== S_OK
, "QueryInterface IMediaFilter failed: %08x\n", hr
);
272 IMediaSeeking_Release(seeking
);
276 hr
= IGraphBuilder_QueryInterface(pgraph
, &IID_IMediaControl
, (void**) &control
);
277 ok(hr
== S_OK
, "QueryInterface IMediaControl failed: %08x\n", hr
);
280 IMediaSeeking_Release(seeking
);
281 IMediaFilter_Release(filter
);
285 hr
= IMediaSeeking_GetCurrentPosition(seeking
, &pos
);
286 ok(hr
== S_OK
, "GetCurrentPosition failed: %08x\n", hr
);
287 ok(pos
== 0, "Position != 0 (%x%08x)\n", (DWORD
)(pos
>> 32), (DWORD
)pos
);
289 hr
= IMediaSeeking_SetPositions(seeking
, NULL
, AM_SEEKING_ReturnTime
, NULL
, AM_SEEKING_NoPositioning
);
290 ok(hr
== S_OK
, "SetPositions failed: %08x\n", hr
);
291 hr
= IMediaSeeking_SetPositions(seeking
, NULL
, AM_SEEKING_NoPositioning
, NULL
, AM_SEEKING_ReturnTime
);
292 ok(hr
== S_OK
, "SetPositions failed: %08x\n", hr
);
294 IMediaFilter_SetSyncSource(filter
, NULL
);
296 hr
= IMediaSeeking_GetCurrentPosition(seeking
, &pos
);
297 ok(hr
== S_OK
, "GetCurrentPosition failed: %08x\n", hr
);
298 ok(pos
== 0, "Position != 0 (%x%08x)\n", (DWORD
)(pos
>> 32), (DWORD
)pos
);
300 hr
= IMediaControl_GetState(control
, 1000, NULL
);
301 ok(hr
== E_POINTER
, "GetState expected %08x, got %08x\n", E_POINTER
, hr
);
303 IMediaControl_Release(control
);
304 IMediaSeeking_Release(seeking
);
305 IMediaFilter_Release(filter
);
306 releasefiltergraph();
309 static void test_filter_graph2(void)
312 IFilterGraph2
*pF
= NULL
;
314 hr
= CoCreateInstance(&CLSID_FilterGraph
, NULL
, CLSCTX_INPROC_SERVER
,
315 &IID_IFilterGraph2
, (LPVOID
*)&pF
);
316 ok(hr
== S_OK
, "CoCreateInstance failed with %x\n", hr
);
317 ok(pF
!= NULL
, "pF is NULL\n");
319 hr
= IFilterGraph2_Release(pF
);
320 ok(hr
== 0, "IFilterGraph2_Release returned: %x\n", hr
);
323 /* IEnumMediaTypes implementation (supporting code for Render() test.) */
324 static void FreeMediaType(AM_MEDIA_TYPE
* pMediaType
)
326 if (pMediaType
->pbFormat
)
328 CoTaskMemFree(pMediaType
->pbFormat
);
329 pMediaType
->pbFormat
= NULL
;
331 if (pMediaType
->pUnk
)
333 IUnknown_Release(pMediaType
->pUnk
);
334 pMediaType
->pUnk
= NULL
;
338 static HRESULT
CopyMediaType(AM_MEDIA_TYPE
* pDest
, const AM_MEDIA_TYPE
*pSrc
)
341 if (!pSrc
->pbFormat
) return S_OK
;
342 if (!(pDest
->pbFormat
= CoTaskMemAlloc(pSrc
->cbFormat
)))
343 return E_OUTOFMEMORY
;
344 memcpy(pDest
->pbFormat
, pSrc
->pbFormat
, pSrc
->cbFormat
);
346 IUnknown_AddRef(pDest
->pUnk
);
350 static AM_MEDIA_TYPE
* CreateMediaType(AM_MEDIA_TYPE
const * pSrc
)
352 AM_MEDIA_TYPE
* pDest
;
354 pDest
= CoTaskMemAlloc(sizeof(AM_MEDIA_TYPE
));
358 if (FAILED(CopyMediaType(pDest
, pSrc
)))
360 CoTaskMemFree(pDest
);
367 static BOOL
CompareMediaTypes(const AM_MEDIA_TYPE
* pmt1
, const AM_MEDIA_TYPE
* pmt2
, BOOL bWildcards
)
369 return (((bWildcards
&& (IsEqualGUID(&pmt1
->majortype
, &GUID_NULL
) || IsEqualGUID(&pmt2
->majortype
, &GUID_NULL
))) || IsEqualGUID(&pmt1
->majortype
, &pmt2
->majortype
)) &&
370 ((bWildcards
&& (IsEqualGUID(&pmt1
->subtype
, &GUID_NULL
) || IsEqualGUID(&pmt2
->subtype
, &GUID_NULL
))) || IsEqualGUID(&pmt1
->subtype
, &pmt2
->subtype
)));
373 static void DeleteMediaType(AM_MEDIA_TYPE
* pMediaType
)
375 FreeMediaType(pMediaType
);
376 CoTaskMemFree(pMediaType
);
379 typedef struct IEnumMediaTypesImpl
381 IEnumMediaTypes IEnumMediaTypes_iface
;
383 AM_MEDIA_TYPE
*pMediaTypes
;
386 } IEnumMediaTypesImpl
;
388 static const struct IEnumMediaTypesVtbl IEnumMediaTypesImpl_Vtbl
;
390 static inline IEnumMediaTypesImpl
*impl_from_IEnumMediaTypes(IEnumMediaTypes
*iface
)
392 return CONTAINING_RECORD(iface
, IEnumMediaTypesImpl
, IEnumMediaTypes_iface
);
395 static HRESULT
IEnumMediaTypesImpl_Construct(const AM_MEDIA_TYPE
* pMediaTypes
, ULONG cMediaTypes
, IEnumMediaTypes
** ppEnum
)
398 IEnumMediaTypesImpl
* pEnumMediaTypes
= CoTaskMemAlloc(sizeof(IEnumMediaTypesImpl
));
400 if (!pEnumMediaTypes
)
403 return E_OUTOFMEMORY
;
405 pEnumMediaTypes
->IEnumMediaTypes_iface
.lpVtbl
= &IEnumMediaTypesImpl_Vtbl
;
406 pEnumMediaTypes
->refCount
= 1;
407 pEnumMediaTypes
->uIndex
= 0;
408 pEnumMediaTypes
->cMediaTypes
= cMediaTypes
;
409 pEnumMediaTypes
->pMediaTypes
= CoTaskMemAlloc(sizeof(AM_MEDIA_TYPE
) * cMediaTypes
);
410 for (i
= 0; i
< cMediaTypes
; i
++)
411 if (FAILED(CopyMediaType(&pEnumMediaTypes
->pMediaTypes
[i
], &pMediaTypes
[i
])))
414 FreeMediaType(&pEnumMediaTypes
->pMediaTypes
[i
]);
415 CoTaskMemFree(pEnumMediaTypes
->pMediaTypes
);
416 return E_OUTOFMEMORY
;
418 *ppEnum
= &pEnumMediaTypes
->IEnumMediaTypes_iface
;
422 static HRESULT WINAPI
IEnumMediaTypesImpl_QueryInterface(IEnumMediaTypes
* iface
, REFIID riid
, LPVOID
* ppv
)
426 if (IsEqualIID(riid
, &IID_IUnknown
))
428 else if (IsEqualIID(riid
, &IID_IEnumMediaTypes
))
433 IUnknown_AddRef((IUnknown
*)(*ppv
));
437 return E_NOINTERFACE
;
440 static ULONG WINAPI
IEnumMediaTypesImpl_AddRef(IEnumMediaTypes
* iface
)
442 IEnumMediaTypesImpl
*This
= impl_from_IEnumMediaTypes(iface
);
443 ULONG refCount
= InterlockedIncrement(&This
->refCount
);
448 static ULONG WINAPI
IEnumMediaTypesImpl_Release(IEnumMediaTypes
* iface
)
450 IEnumMediaTypesImpl
*This
= impl_from_IEnumMediaTypes(iface
);
451 ULONG refCount
= InterlockedDecrement(&This
->refCount
);
456 for (i
= 0; i
< This
->cMediaTypes
; i
++)
457 FreeMediaType(&This
->pMediaTypes
[i
]);
458 CoTaskMemFree(This
->pMediaTypes
);
464 static HRESULT WINAPI
IEnumMediaTypesImpl_Next(IEnumMediaTypes
* iface
, ULONG cMediaTypes
, AM_MEDIA_TYPE
** ppMediaTypes
, ULONG
* pcFetched
)
467 IEnumMediaTypesImpl
*This
= impl_from_IEnumMediaTypes(iface
);
469 cFetched
= min(This
->cMediaTypes
, This
->uIndex
+ cMediaTypes
) - This
->uIndex
;
474 for (i
= 0; i
< cFetched
; i
++)
475 if (!(ppMediaTypes
[i
] = CreateMediaType(&This
->pMediaTypes
[This
->uIndex
+ i
])))
478 DeleteMediaType(ppMediaTypes
[i
]);
480 return E_OUTOFMEMORY
;
484 if ((cMediaTypes
!= 1) || pcFetched
)
485 *pcFetched
= cFetched
;
487 This
->uIndex
+= cFetched
;
489 if (cFetched
!= cMediaTypes
)
494 static HRESULT WINAPI
IEnumMediaTypesImpl_Skip(IEnumMediaTypes
* iface
, ULONG cMediaTypes
)
496 IEnumMediaTypesImpl
*This
= impl_from_IEnumMediaTypes(iface
);
498 if (This
->uIndex
+ cMediaTypes
< This
->cMediaTypes
)
500 This
->uIndex
+= cMediaTypes
;
506 static HRESULT WINAPI
IEnumMediaTypesImpl_Reset(IEnumMediaTypes
* iface
)
508 IEnumMediaTypesImpl
*This
= impl_from_IEnumMediaTypes(iface
);
514 static HRESULT WINAPI
IEnumMediaTypesImpl_Clone(IEnumMediaTypes
* iface
, IEnumMediaTypes
** ppEnum
)
517 IEnumMediaTypesImpl
*This
= impl_from_IEnumMediaTypes(iface
);
519 hr
= IEnumMediaTypesImpl_Construct(This
->pMediaTypes
, This
->cMediaTypes
, ppEnum
);
522 return IEnumMediaTypes_Skip(*ppEnum
, This
->uIndex
);
525 static const IEnumMediaTypesVtbl IEnumMediaTypesImpl_Vtbl
=
527 IEnumMediaTypesImpl_QueryInterface
,
528 IEnumMediaTypesImpl_AddRef
,
529 IEnumMediaTypesImpl_Release
,
530 IEnumMediaTypesImpl_Next
,
531 IEnumMediaTypesImpl_Skip
,
532 IEnumMediaTypesImpl_Reset
,
533 IEnumMediaTypesImpl_Clone
536 /* Implementation of a very stripped down pin for the test filter. Just enough
537 functionality for connecting and Render() to work. */
539 static void Copy_PinInfo(PIN_INFO
* pDest
, const PIN_INFO
* pSrc
)
541 lstrcpyW(pDest
->achName
, pSrc
->achName
);
542 pDest
->dir
= pSrc
->dir
;
543 pDest
->pFilter
= pSrc
->pFilter
;
546 typedef struct ITestPinImpl
550 LPCRITICAL_SECTION pCritSec
;
553 AM_MEDIA_TYPE mtCurrent
;
557 static inline ITestPinImpl
*impl_from_IPin(IPin
*iface
)
559 return CONTAINING_RECORD(iface
, ITestPinImpl
, IPin_iface
);
562 static HRESULT WINAPI
TestFilter_Pin_QueryInterface(IPin
* iface
, REFIID riid
, LPVOID
* ppv
)
566 if (IsEqualIID(riid
, &IID_IUnknown
))
568 else if (IsEqualIID(riid
, &IID_IPin
))
573 IUnknown_AddRef((IUnknown
*)(*ppv
));
577 return E_NOINTERFACE
;
580 static ULONG WINAPI
TestFilter_Pin_AddRef(IPin
* iface
)
582 ITestPinImpl
*This
= impl_from_IPin(iface
);
583 ULONG refCount
= InterlockedIncrement(&This
->refCount
);
587 static ULONG WINAPI
TestFilter_Pin_Release(IPin
* iface
)
589 ITestPinImpl
*This
= impl_from_IPin(iface
);
590 ULONG refCount
= InterlockedDecrement(&This
->refCount
);
594 FreeMediaType(&This
->mtCurrent
);
602 static HRESULT WINAPI
TestFilter_InputPin_Connect(IPin
* iface
, IPin
* pConnector
, const AM_MEDIA_TYPE
* pmt
)
607 static HRESULT WINAPI
TestFilter_InputPin_ReceiveConnection(IPin
* iface
, IPin
* pReceivePin
, const AM_MEDIA_TYPE
* pmt
)
609 ITestPinImpl
*This
= impl_from_IPin(iface
);
610 PIN_DIRECTION pindirReceive
;
613 EnterCriticalSection(This
->pCritSec
);
615 if (!(IsEqualIID(&pmt
->majortype
, &This
->mtCurrent
.majortype
) && (IsEqualIID(&pmt
->subtype
, &This
->mtCurrent
.subtype
) ||
616 IsEqualIID(&GUID_NULL
, &This
->mtCurrent
.subtype
))))
617 hr
= VFW_E_TYPE_NOT_ACCEPTED
;
619 if (This
->pConnectedTo
)
620 hr
= VFW_E_ALREADY_CONNECTED
;
624 IPin_QueryDirection(pReceivePin
, &pindirReceive
);
626 if (pindirReceive
!= PINDIR_OUTPUT
)
628 hr
= VFW_E_INVALID_DIRECTION
;
634 CopyMediaType(&This
->mtCurrent
, pmt
);
635 This
->pConnectedTo
= pReceivePin
;
636 IPin_AddRef(pReceivePin
);
639 LeaveCriticalSection(This
->pCritSec
);
644 static HRESULT WINAPI
TestFilter_Pin_Disconnect(IPin
* iface
)
647 ITestPinImpl
*This
= impl_from_IPin(iface
);
649 EnterCriticalSection(This
->pCritSec
);
651 if (This
->pConnectedTo
)
653 IPin_Release(This
->pConnectedTo
);
654 This
->pConnectedTo
= NULL
;
660 LeaveCriticalSection(This
->pCritSec
);
665 static HRESULT WINAPI
TestFilter_Pin_ConnectedTo(IPin
* iface
, IPin
** ppPin
)
668 ITestPinImpl
*This
= impl_from_IPin(iface
);
670 EnterCriticalSection(This
->pCritSec
);
672 if (This
->pConnectedTo
)
674 *ppPin
= This
->pConnectedTo
;
680 hr
= VFW_E_NOT_CONNECTED
;
684 LeaveCriticalSection(This
->pCritSec
);
689 static HRESULT WINAPI
TestFilter_Pin_ConnectionMediaType(IPin
* iface
, AM_MEDIA_TYPE
* pmt
)
692 ITestPinImpl
*This
= impl_from_IPin(iface
);
694 EnterCriticalSection(This
->pCritSec
);
696 if (This
->pConnectedTo
)
698 CopyMediaType(pmt
, &This
->mtCurrent
);
703 ZeroMemory(pmt
, sizeof(*pmt
));
704 hr
= VFW_E_NOT_CONNECTED
;
707 LeaveCriticalSection(This
->pCritSec
);
712 static HRESULT WINAPI
TestFilter_Pin_QueryPinInfo(IPin
* iface
, PIN_INFO
* pInfo
)
714 ITestPinImpl
*This
= impl_from_IPin(iface
);
716 Copy_PinInfo(pInfo
, &This
->pinInfo
);
717 IBaseFilter_AddRef(pInfo
->pFilter
);
722 static HRESULT WINAPI
TestFilter_Pin_QueryDirection(IPin
* iface
, PIN_DIRECTION
* pPinDir
)
724 ITestPinImpl
*This
= impl_from_IPin(iface
);
726 *pPinDir
= This
->pinInfo
.dir
;
731 static HRESULT WINAPI
TestFilter_Pin_QueryId(IPin
* iface
, LPWSTR
* Id
)
736 static HRESULT WINAPI
TestFilter_Pin_QueryAccept(IPin
* iface
, const AM_MEDIA_TYPE
* pmt
)
738 ITestPinImpl
*This
= impl_from_IPin(iface
);
740 if (IsEqualIID(&pmt
->majortype
, &This
->mtCurrent
.majortype
) && (IsEqualIID(&pmt
->subtype
, &This
->mtCurrent
.subtype
) ||
741 IsEqualIID(&GUID_NULL
, &This
->mtCurrent
.subtype
)))
744 return VFW_E_TYPE_NOT_ACCEPTED
;
747 static HRESULT WINAPI
TestFilter_Pin_EnumMediaTypes(IPin
* iface
, IEnumMediaTypes
** ppEnum
)
749 ITestPinImpl
*This
= impl_from_IPin(iface
);
751 return IEnumMediaTypesImpl_Construct(&This
->mtCurrent
, 1, ppEnum
);
754 static HRESULT WINAPI
TestFilter_Pin_QueryInternalConnections(IPin
* iface
, IPin
** apPin
, ULONG
* cPin
)
759 static HRESULT WINAPI
TestFilter_Pin_BeginFlush(IPin
* iface
)
764 static HRESULT WINAPI
TestFilter_Pin_EndFlush(IPin
* iface
)
769 static HRESULT WINAPI
TestFilter_Pin_NewSegment(IPin
* iface
, REFERENCE_TIME tStart
, REFERENCE_TIME tStop
, double dRate
)
774 static HRESULT WINAPI
TestFilter_Pin_EndOfStream(IPin
* iface
)
779 static const IPinVtbl TestFilter_InputPin_Vtbl
=
781 TestFilter_Pin_QueryInterface
,
782 TestFilter_Pin_AddRef
,
783 TestFilter_Pin_Release
,
784 TestFilter_InputPin_Connect
,
785 TestFilter_InputPin_ReceiveConnection
,
786 TestFilter_Pin_Disconnect
,
787 TestFilter_Pin_ConnectedTo
,
788 TestFilter_Pin_ConnectionMediaType
,
789 TestFilter_Pin_QueryPinInfo
,
790 TestFilter_Pin_QueryDirection
,
791 TestFilter_Pin_QueryId
,
792 TestFilter_Pin_QueryAccept
,
793 TestFilter_Pin_EnumMediaTypes
,
794 TestFilter_Pin_QueryInternalConnections
,
795 TestFilter_Pin_EndOfStream
,
796 TestFilter_Pin_BeginFlush
,
797 TestFilter_Pin_EndFlush
,
798 TestFilter_Pin_NewSegment
801 static HRESULT WINAPI
TestFilter_OutputPin_ReceiveConnection(IPin
* iface
, IPin
* pReceivePin
, const AM_MEDIA_TYPE
* pmt
)
806 /* Private helper function */
807 static HRESULT
TestFilter_OutputPin_ConnectSpecific(ITestPinImpl
* This
, IPin
* pReceivePin
,
808 const AM_MEDIA_TYPE
* pmt
)
812 This
->pConnectedTo
= pReceivePin
;
813 IPin_AddRef(pReceivePin
);
815 hr
= IPin_ReceiveConnection(pReceivePin
, &This
->IPin_iface
, pmt
);
819 IPin_Release(This
->pConnectedTo
);
820 This
->pConnectedTo
= NULL
;
826 static HRESULT WINAPI
TestFilter_OutputPin_Connect(IPin
* iface
, IPin
* pReceivePin
, const AM_MEDIA_TYPE
* pmt
)
828 ITestPinImpl
*This
= impl_from_IPin(iface
);
831 EnterCriticalSection(This
->pCritSec
);
833 /* if we have been a specific type to connect with, then we can either connect
834 * with that or fail. We cannot choose different AM_MEDIA_TYPE */
835 if (pmt
&& !IsEqualGUID(&pmt
->majortype
, &GUID_NULL
) && !IsEqualGUID(&pmt
->subtype
, &GUID_NULL
))
836 hr
= TestFilter_OutputPin_ConnectSpecific(This
, pReceivePin
, pmt
);
839 if (( !pmt
|| CompareMediaTypes(pmt
, &This
->mtCurrent
, TRUE
) ) &&
840 (TestFilter_OutputPin_ConnectSpecific(This
, pReceivePin
, &This
->mtCurrent
) == S_OK
))
842 else hr
= VFW_E_NO_ACCEPTABLE_TYPES
;
843 } /* if negotiate media type */
845 LeaveCriticalSection(This
->pCritSec
);
850 static const IPinVtbl TestFilter_OutputPin_Vtbl
=
852 TestFilter_Pin_QueryInterface
,
853 TestFilter_Pin_AddRef
,
854 TestFilter_Pin_Release
,
855 TestFilter_OutputPin_Connect
,
856 TestFilter_OutputPin_ReceiveConnection
,
857 TestFilter_Pin_Disconnect
,
858 TestFilter_Pin_ConnectedTo
,
859 TestFilter_Pin_ConnectionMediaType
,
860 TestFilter_Pin_QueryPinInfo
,
861 TestFilter_Pin_QueryDirection
,
862 TestFilter_Pin_QueryId
,
863 TestFilter_Pin_QueryAccept
,
864 TestFilter_Pin_EnumMediaTypes
,
865 TestFilter_Pin_QueryInternalConnections
,
866 TestFilter_Pin_EndOfStream
,
867 TestFilter_Pin_BeginFlush
,
868 TestFilter_Pin_EndFlush
,
869 TestFilter_Pin_NewSegment
872 static HRESULT
TestFilter_Pin_Construct(const IPinVtbl
*Pin_Vtbl
, const PIN_INFO
* pPinInfo
, AM_MEDIA_TYPE
*pinmt
,
873 LPCRITICAL_SECTION pCritSec
, IPin
** ppPin
)
875 ITestPinImpl
* pPinImpl
;
879 pPinImpl
= CoTaskMemAlloc(sizeof(ITestPinImpl
));
882 return E_OUTOFMEMORY
;
884 pPinImpl
->refCount
= 1;
885 pPinImpl
->pConnectedTo
= NULL
;
886 pPinImpl
->pCritSec
= pCritSec
;
887 Copy_PinInfo(&pPinImpl
->pinInfo
, pPinInfo
);
888 pPinImpl
->mtCurrent
= *pinmt
;
890 pPinImpl
->IPin_iface
.lpVtbl
= Pin_Vtbl
;
892 *ppPin
= &pPinImpl
->IPin_iface
;
896 /* IEnumPins implementation */
898 typedef HRESULT (* FNOBTAINPIN
)(TestFilterImpl
*tf
, ULONG pos
, IPin
**pin
, DWORD
*lastsynctick
);
900 typedef struct IEnumPinsImpl
902 IEnumPins IEnumPins_iface
;
905 TestFilterImpl
*base
;
906 FNOBTAINPIN receive_pin
;
910 static const struct IEnumPinsVtbl IEnumPinsImpl_Vtbl
;
912 static inline IEnumPinsImpl
*impl_from_IEnumPins(IEnumPins
*iface
)
914 return CONTAINING_RECORD(iface
, IEnumPinsImpl
, IEnumPins_iface
);
917 static HRESULT
createenumpins(IEnumPins
** ppEnum
, FNOBTAINPIN receive_pin
, TestFilterImpl
*base
)
919 IEnumPinsImpl
* pEnumPins
;
924 pEnumPins
= CoTaskMemAlloc(sizeof(IEnumPinsImpl
));
928 return E_OUTOFMEMORY
;
930 pEnumPins
->IEnumPins_iface
.lpVtbl
= &IEnumPinsImpl_Vtbl
;
931 pEnumPins
->refCount
= 1;
932 pEnumPins
->uIndex
= 0;
933 pEnumPins
->receive_pin
= receive_pin
;
934 pEnumPins
->base
= base
;
935 IBaseFilter_AddRef(&base
->IBaseFilter_iface
);
936 *ppEnum
= &pEnumPins
->IEnumPins_iface
;
938 receive_pin(base
, ~0, NULL
, &pEnumPins
->synctime
);
943 static HRESULT WINAPI
IEnumPinsImpl_QueryInterface(IEnumPins
* iface
, REFIID riid
, LPVOID
* ppv
)
947 if (IsEqualIID(riid
, &IID_IUnknown
))
949 else if (IsEqualIID(riid
, &IID_IEnumPins
))
954 IUnknown_AddRef((IUnknown
*)(*ppv
));
958 return E_NOINTERFACE
;
961 static ULONG WINAPI
IEnumPinsImpl_AddRef(IEnumPins
* iface
)
963 IEnumPinsImpl
*This
= impl_from_IEnumPins(iface
);
964 ULONG refCount
= InterlockedIncrement(&This
->refCount
);
969 static ULONG WINAPI
IEnumPinsImpl_Release(IEnumPins
* iface
)
971 IEnumPinsImpl
*This
= impl_from_IEnumPins(iface
);
972 ULONG refCount
= InterlockedDecrement(&This
->refCount
);
976 IBaseFilter_Release(&This
->base
->IBaseFilter_iface
);
984 static HRESULT WINAPI
IEnumPinsImpl_Next(IEnumPins
* iface
, ULONG cPins
, IPin
** ppPins
, ULONG
* pcFetched
)
986 IEnumPinsImpl
*This
= impl_from_IEnumPins(iface
);
987 DWORD synctime
= This
->synctime
;
994 if (cPins
> 1 && !pcFetched
)
1000 while (i
< cPins
&& hr
== S_OK
)
1002 hr
= This
->receive_pin(This
->base
, This
->uIndex
+ i
, &ppPins
[i
], &synctime
);
1007 if (synctime
!= This
->synctime
)
1011 if (!i
&& synctime
!= This
->synctime
)
1012 return VFW_E_ENUM_OUT_OF_SYNC
;
1023 static HRESULT WINAPI
IEnumPinsImpl_Skip(IEnumPins
* iface
, ULONG cPins
)
1025 IEnumPinsImpl
*This
= impl_from_IEnumPins(iface
);
1026 DWORD synctime
= This
->synctime
;
1030 hr
= This
->receive_pin(This
->base
, This
->uIndex
+ cPins
, &pin
, &synctime
);
1034 if (synctime
!= This
->synctime
)
1035 return VFW_E_ENUM_OUT_OF_SYNC
;
1038 This
->uIndex
+= cPins
;
1043 static HRESULT WINAPI
IEnumPinsImpl_Reset(IEnumPins
* iface
)
1045 IEnumPinsImpl
*This
= impl_from_IEnumPins(iface
);
1047 This
->receive_pin(This
->base
, ~0, NULL
, &This
->synctime
);
1053 static HRESULT WINAPI
IEnumPinsImpl_Clone(IEnumPins
* iface
, IEnumPins
** ppEnum
)
1056 IEnumPinsImpl
*This
= impl_from_IEnumPins(iface
);
1058 hr
= createenumpins(ppEnum
, This
->receive_pin
, This
->base
);
1061 return IEnumPins_Skip(*ppEnum
, This
->uIndex
);
1064 static const IEnumPinsVtbl IEnumPinsImpl_Vtbl
=
1066 IEnumPinsImpl_QueryInterface
,
1067 IEnumPinsImpl_AddRef
,
1068 IEnumPinsImpl_Release
,
1071 IEnumPinsImpl_Reset
,
1075 /* Test filter implementation - a filter that has few predefined pins with single media type
1076 * that accept only this single media type. Enough for Render(). */
1078 typedef struct TestFilterPinData
1080 PIN_DIRECTION pinDir
;
1081 const GUID
*mediasubtype
;
1082 } TestFilterPinData
;
1084 static const IBaseFilterVtbl TestFilter_Vtbl
;
1086 static inline TestFilterImpl
*impl_from_IBaseFilter(IBaseFilter
*iface
)
1088 return CONTAINING_RECORD(iface
, TestFilterImpl
, IBaseFilter_iface
);
1091 static HRESULT
createtestfilter(const CLSID
* pClsid
, const TestFilterPinData
*pinData
,
1092 TestFilterImpl
**tf
)
1094 static const WCHAR wcsInputPinName
[] = {'i','n','p','u','t',' ','p','i','n',0};
1095 static const WCHAR wcsOutputPinName
[] = {'o','u','t','p','u','t',' ','p','i','n',0};
1098 TestFilterImpl
* pTestFilter
= NULL
;
1102 pTestFilter
= CoTaskMemAlloc(sizeof(TestFilterImpl
));
1103 if (!pTestFilter
) return E_OUTOFMEMORY
;
1105 pTestFilter
->clsid
= *pClsid
;
1106 pTestFilter
->IBaseFilter_iface
.lpVtbl
= &TestFilter_Vtbl
;
1107 pTestFilter
->refCount
= 1;
1108 InitializeCriticalSection(&pTestFilter
->csFilter
);
1109 pTestFilter
->state
= State_Stopped
;
1111 ZeroMemory(&pTestFilter
->filterInfo
, sizeof(FILTER_INFO
));
1114 while(pinData
[nPins
].mediasubtype
) ++nPins
;
1116 pTestFilter
->ppPins
= CoTaskMemAlloc(nPins
* sizeof(IPin
*));
1117 if (!pTestFilter
->ppPins
)
1122 ZeroMemory(pTestFilter
->ppPins
, nPins
* sizeof(IPin
*));
1124 for (i
= 0; i
< nPins
; i
++)
1126 ZeroMemory(&mt
, sizeof(mt
));
1127 mt
.majortype
= MEDIATYPE_Video
;
1128 mt
.formattype
= FORMAT_None
;
1129 mt
.subtype
= *pinData
[i
].mediasubtype
;
1131 pinInfo
.dir
= pinData
[i
].pinDir
;
1132 pinInfo
.pFilter
= &pTestFilter
->IBaseFilter_iface
;
1133 if (pinInfo
.dir
== PINDIR_INPUT
)
1135 lstrcpynW(pinInfo
.achName
, wcsInputPinName
, sizeof(pinInfo
.achName
) / sizeof(pinInfo
.achName
[0]));
1136 hr
= TestFilter_Pin_Construct(&TestFilter_InputPin_Vtbl
, &pinInfo
, &mt
, &pTestFilter
->csFilter
,
1137 &pTestFilter
->ppPins
[i
]);
1142 lstrcpynW(pinInfo
.achName
, wcsOutputPinName
, sizeof(pinInfo
.achName
) / sizeof(pinInfo
.achName
[0]));
1143 hr
= TestFilter_Pin_Construct(&TestFilter_OutputPin_Vtbl
, &pinInfo
, &mt
, &pTestFilter
->csFilter
,
1144 &pTestFilter
->ppPins
[i
]);
1146 if (FAILED(hr
) || !pTestFilter
->ppPins
[i
]) goto error
;
1149 pTestFilter
->nPins
= nPins
;
1155 if (pTestFilter
->ppPins
)
1157 for (i
= 0; i
< nPins
; i
++)
1159 if (pTestFilter
->ppPins
[i
]) IPin_Release(pTestFilter
->ppPins
[i
]);
1162 CoTaskMemFree(pTestFilter
->ppPins
);
1163 DeleteCriticalSection(&pTestFilter
->csFilter
);
1164 CoTaskMemFree(pTestFilter
);
1169 static HRESULT WINAPI
TestFilter_QueryInterface(IBaseFilter
* iface
, REFIID riid
, LPVOID
* ppv
)
1171 TestFilterImpl
*This
= impl_from_IBaseFilter(iface
);
1175 if (IsEqualIID(riid
, &IID_IUnknown
))
1177 else if (IsEqualIID(riid
, &IID_IPersist
))
1179 else if (IsEqualIID(riid
, &IID_IMediaFilter
))
1181 else if (IsEqualIID(riid
, &IID_IBaseFilter
))
1186 IUnknown_AddRef((IUnknown
*)(*ppv
));
1190 return E_NOINTERFACE
;
1193 static ULONG WINAPI
TestFilter_AddRef(IBaseFilter
* iface
)
1195 TestFilterImpl
*This
= impl_from_IBaseFilter(iface
);
1196 ULONG refCount
= InterlockedIncrement(&This
->refCount
);
1201 static ULONG WINAPI
TestFilter_Release(IBaseFilter
* iface
)
1203 TestFilterImpl
*This
= impl_from_IBaseFilter(iface
);
1204 ULONG refCount
= InterlockedDecrement(&This
->refCount
);
1210 for (i
= 0; i
< This
->nPins
; i
++)
1214 if (SUCCEEDED(IPin_ConnectedTo(This
->ppPins
[i
], &pConnectedTo
)))
1216 IPin_Disconnect(pConnectedTo
);
1217 IPin_Release(pConnectedTo
);
1219 IPin_Disconnect(This
->ppPins
[i
]);
1221 IPin_Release(This
->ppPins
[i
]);
1224 CoTaskMemFree(This
->ppPins
);
1226 DeleteCriticalSection(&This
->csFilter
);
1228 CoTaskMemFree(This
);
1235 /** IPersist methods **/
1237 static HRESULT WINAPI
TestFilter_GetClassID(IBaseFilter
* iface
, CLSID
* pClsid
)
1239 TestFilterImpl
*This
= impl_from_IBaseFilter(iface
);
1241 *pClsid
= This
->clsid
;
1246 /** IMediaFilter methods **/
1248 static HRESULT WINAPI
TestFilter_Stop(IBaseFilter
* iface
)
1253 static HRESULT WINAPI
TestFilter_Pause(IBaseFilter
* iface
)
1258 static HRESULT WINAPI
TestFilter_Run(IBaseFilter
* iface
, REFERENCE_TIME tStart
)
1263 static HRESULT WINAPI
TestFilter_GetState(IBaseFilter
* iface
, DWORD dwMilliSecsTimeout
, FILTER_STATE
*pState
)
1265 TestFilterImpl
*This
= impl_from_IBaseFilter(iface
);
1267 EnterCriticalSection(&This
->csFilter
);
1269 *pState
= This
->state
;
1271 LeaveCriticalSection(&This
->csFilter
);
1276 static HRESULT WINAPI
TestFilter_SetSyncSource(IBaseFilter
* iface
, IReferenceClock
*pClock
)
1281 static HRESULT WINAPI
TestFilter_GetSyncSource(IBaseFilter
* iface
, IReferenceClock
**ppClock
)
1286 /** IBaseFilter implementation **/
1288 static HRESULT
getpin_callback(TestFilterImpl
*tf
, ULONG pos
, IPin
**pin
, DWORD
*lastsynctick
)
1290 /* Our pins are static, not changing so setting static tick count is ok */
1293 if (pos
>= tf
->nPins
)
1296 *pin
= tf
->ppPins
[pos
];
1301 static HRESULT WINAPI
TestFilter_EnumPins(IBaseFilter
* iface
, IEnumPins
**ppEnum
)
1303 TestFilterImpl
*This
= impl_from_IBaseFilter(iface
);
1305 return createenumpins(ppEnum
, getpin_callback
, This
);
1308 static HRESULT WINAPI
TestFilter_FindPin(IBaseFilter
* iface
, LPCWSTR Id
, IPin
**ppPin
)
1313 static HRESULT WINAPI
TestFilter_QueryFilterInfo(IBaseFilter
* iface
, FILTER_INFO
*pInfo
)
1315 TestFilterImpl
*This
= impl_from_IBaseFilter(iface
);
1317 lstrcpyW(pInfo
->achName
, This
->filterInfo
.achName
);
1318 pInfo
->pGraph
= This
->filterInfo
.pGraph
;
1321 IFilterGraph_AddRef(pInfo
->pGraph
);
1326 static HRESULT WINAPI
TestFilter_JoinFilterGraph(IBaseFilter
* iface
, IFilterGraph
*pGraph
, LPCWSTR pName
)
1329 TestFilterImpl
*This
= impl_from_IBaseFilter(iface
);
1331 EnterCriticalSection(&This
->csFilter
);
1334 lstrcpyW(This
->filterInfo
.achName
, pName
);
1336 *This
->filterInfo
.achName
= '\0';
1337 This
->filterInfo
.pGraph
= pGraph
; /* NOTE: do NOT increase ref. count */
1339 LeaveCriticalSection(&This
->csFilter
);
1344 static HRESULT WINAPI
TestFilter_QueryVendorInfo(IBaseFilter
* iface
, LPWSTR
*pVendorInfo
)
1349 static const IBaseFilterVtbl TestFilter_Vtbl
=
1351 TestFilter_QueryInterface
,
1354 TestFilter_GetClassID
,
1358 TestFilter_GetState
,
1359 TestFilter_SetSyncSource
,
1360 TestFilter_GetSyncSource
,
1361 TestFilter_EnumPins
,
1363 TestFilter_QueryFilterInfo
,
1364 TestFilter_JoinFilterGraph
,
1365 TestFilter_QueryVendorInfo
1368 /* IClassFactory implementation */
1370 typedef struct TestClassFactoryImpl
1372 IClassFactory IClassFactory_iface
;
1373 const TestFilterPinData
*filterPinData
;
1375 } TestClassFactoryImpl
;
1377 static inline TestClassFactoryImpl
*impl_from_IClassFactory(IClassFactory
*iface
)
1379 return CONTAINING_RECORD(iface
, TestClassFactoryImpl
, IClassFactory_iface
);
1382 static HRESULT WINAPI
Test_IClassFactory_QueryInterface(
1383 LPCLASSFACTORY iface
,
1387 if (ppvObj
== NULL
) return E_POINTER
;
1389 if (IsEqualGUID(riid
, &IID_IUnknown
) ||
1390 IsEqualGUID(riid
, &IID_IClassFactory
))
1393 IClassFactory_AddRef(iface
);
1398 return E_NOINTERFACE
;
1401 static ULONG WINAPI
Test_IClassFactory_AddRef(LPCLASSFACTORY iface
)
1403 return 2; /* non-heap-based object */
1406 static ULONG WINAPI
Test_IClassFactory_Release(LPCLASSFACTORY iface
)
1408 return 1; /* non-heap-based object */
1411 static HRESULT WINAPI
Test_IClassFactory_CreateInstance(
1412 LPCLASSFACTORY iface
,
1413 LPUNKNOWN pUnkOuter
,
1417 TestClassFactoryImpl
*This
= impl_from_IClassFactory(iface
);
1419 TestFilterImpl
*testfilter
;
1423 if (pUnkOuter
) return CLASS_E_NOAGGREGATION
;
1425 hr
= createtestfilter(This
->clsid
, This
->filterPinData
, &testfilter
);
1426 if (SUCCEEDED(hr
)) {
1427 hr
= IBaseFilter_QueryInterface(&testfilter
->IBaseFilter_iface
, riid
, ppvObj
);
1428 IBaseFilter_Release(&testfilter
->IBaseFilter_iface
);
1433 static HRESULT WINAPI
Test_IClassFactory_LockServer(
1434 LPCLASSFACTORY iface
,
1440 static IClassFactoryVtbl TestClassFactory_Vtbl
=
1442 Test_IClassFactory_QueryInterface
,
1443 Test_IClassFactory_AddRef
,
1444 Test_IClassFactory_Release
,
1445 Test_IClassFactory_CreateInstance
,
1446 Test_IClassFactory_LockServer
1449 static HRESULT
get_connected_filter_name(TestFilterImpl
*pFilter
, char *FilterName
)
1453 FILTER_INFO filterInfo
;
1458 hr
= IPin_ConnectedTo(pFilter
->ppPins
[0], &pin
);
1459 ok(hr
== S_OK
, "IPin_ConnectedTo failed with %x\n", hr
);
1460 if (FAILED(hr
)) return hr
;
1462 hr
= IPin_QueryPinInfo(pin
, &pinInfo
);
1463 ok(hr
== S_OK
, "IPin_QueryPinInfo failed with %x\n", hr
);
1465 if (FAILED(hr
)) return hr
;
1467 SetLastError(0xdeadbeef);
1468 hr
= IBaseFilter_QueryFilterInfo(pinInfo
.pFilter
, &filterInfo
);
1469 if (hr
== S_OK
&& GetLastError() == ERROR_CALL_NOT_IMPLEMENTED
)
1471 IBaseFilter_Release(pinInfo
.pFilter
);
1474 ok(hr
== S_OK
, "IBaseFilter_QueryFilterInfo failed with %x\n", hr
);
1475 IBaseFilter_Release(pinInfo
.pFilter
);
1476 if (FAILED(hr
)) return hr
;
1478 IFilterGraph_Release(filterInfo
.pGraph
);
1480 WideCharToMultiByte(CP_ACP
, 0, filterInfo
.achName
, -1, FilterName
, MAX_FILTER_NAME
, NULL
, NULL
);
1485 static void test_render_filter_priority(void)
1487 /* Tests filter choice priorities in Render(). */
1488 DWORD cookie1
= 0, cookie2
= 0, cookie3
= 0;
1490 IFilterGraph2
* pgraph2
= NULL
;
1491 IFilterMapper2
*pMapper2
= NULL
;
1492 TestFilterImpl
*ptestfilter
= NULL
;
1493 TestFilterImpl
*ptestfilter2
= NULL
;
1494 static const CLSID CLSID_TestFilter2
= {
1498 {0xe8, 0x9b, 0x00, 0x19, 0x66, 0x2f, 0xf0, 0xce}
1500 static const CLSID CLSID_TestFilter3
= {
1504 {0xe8, 0x9b, 0x00, 0x19, 0x66, 0x2f, 0xf0, 0xce}
1506 static const CLSID CLSID_TestFilter4
= {
1510 {0xe8, 0x9b, 0x00, 0x19, 0x66, 0x2f, 0xf0, 0xce}
1512 static const GUID mediasubtype1
= {
1516 {0xe8, 0x9b, 0x00, 0x19, 0x66, 0x2f, 0xf0, 0xce}
1518 static const GUID mediasubtype2
= {
1522 {0xe8, 0x9b, 0x00, 0x19, 0x66, 0x2f, 0xf0, 0xce}
1524 static const TestFilterPinData PinData1
[] = {
1525 { PINDIR_OUTPUT
, &mediasubtype1
},
1528 static const TestFilterPinData PinData2
[] = {
1529 { PINDIR_INPUT
, &mediasubtype1
},
1532 static const TestFilterPinData PinData3
[] = {
1533 { PINDIR_INPUT
, &GUID_NULL
},
1536 static const TestFilterPinData PinData4
[] = {
1537 { PINDIR_INPUT
, &mediasubtype1
},
1538 { PINDIR_OUTPUT
, &mediasubtype2
},
1541 static const TestFilterPinData PinData5
[] = {
1542 { PINDIR_INPUT
, &mediasubtype2
},
1545 TestClassFactoryImpl Filter1ClassFactory
= {
1546 { &TestClassFactory_Vtbl
},
1547 PinData2
, &CLSID_TestFilter2
1549 TestClassFactoryImpl Filter2ClassFactory
= {
1550 { &TestClassFactory_Vtbl
},
1551 PinData4
, &CLSID_TestFilter3
1553 TestClassFactoryImpl Filter3ClassFactory
= {
1554 { &TestClassFactory_Vtbl
},
1555 PinData5
, &CLSID_TestFilter4
1557 char ConnectedFilterName1
[MAX_FILTER_NAME
];
1558 char ConnectedFilterName2
[MAX_FILTER_NAME
];
1560 REGFILTERPINS2 rgPins2
[2];
1561 REGPINTYPES rgPinType
[2];
1562 static const WCHAR wszFilterInstanceName1
[] = {'T', 'e', 's', 't', 'f', 'i', 'l', 't', 'e', 'r', 'I',
1563 'n', 's', 't', 'a', 'n', 'c', 'e', '1', 0 };
1564 static const WCHAR wszFilterInstanceName2
[] = {'T', 'e', 's', 't', 'f', 'i', 'l', 't', 'e', 'r', 'I',
1565 'n', 's', 't', 'a', 'n', 'c', 'e', '2', 0 };
1566 static const WCHAR wszFilterInstanceName3
[] = {'T', 'e', 's', 't', 'f', 'i', 'l', 't', 'e', 'r', 'I',
1567 'n', 's', 't', 'a', 'n', 'c', 'e', '3', 0 };
1568 static const WCHAR wszFilterInstanceName4
[] = {'T', 'e', 's', 't', 'f', 'i', 'l', 't', 'e', 'r', 'I',
1569 'n', 's', 't', 'a', 'n', 'c', 'e', '4', 0 };
1571 /* Test which renderer of two already added to the graph will be chosen
1572 * (one is "exact" match, other is "wildcard" match. Seems to depend
1573 * on the order in which filters are added to the graph, thus indicating
1574 * no preference given to exact match. */
1575 hr
= CoCreateInstance(&CLSID_FilterGraph
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IFilterGraph2
, (LPVOID
*)&pgraph2
);
1576 ok(hr
== S_OK
, "CoCreateInstance failed with %08x\n", hr
);
1577 if (!pgraph2
) return;
1579 hr
= createtestfilter(&GUID_NULL
, PinData1
, &ptestfilter
);
1580 ok(hr
== S_OK
, "createtestfilter failed with %08x\n", hr
);
1581 if (FAILED(hr
)) goto out
;
1583 hr
= IFilterGraph2_AddFilter(pgraph2
, &ptestfilter
->IBaseFilter_iface
, wszFilterInstanceName1
);
1584 ok(hr
== S_OK
, "IFilterGraph2_AddFilter failed with %08x\n", hr
);
1586 hr
= createtestfilter(&GUID_NULL
, PinData2
, &ptestfilter2
);
1587 ok(hr
== S_OK
, "createtestfilter failed with %08x\n", hr
);
1588 if (FAILED(hr
)) goto out
;
1590 hr
= IFilterGraph2_AddFilter(pgraph2
, &ptestfilter2
->IBaseFilter_iface
, wszFilterInstanceName2
);
1591 ok(hr
== S_OK
, "IFilterGraph2_AddFilter failed with %08x\n", hr
);
1593 IBaseFilter_Release(&ptestfilter2
->IBaseFilter_iface
);
1594 ptestfilter2
= NULL
;
1596 hr
= createtestfilter(&GUID_NULL
, PinData3
, &ptestfilter2
);
1597 ok(hr
== S_OK
, "createtestfilter failed with %08x\n", hr
);
1598 if (FAILED(hr
)) goto out
;
1600 hr
= IFilterGraph2_AddFilter(pgraph2
, &ptestfilter2
->IBaseFilter_iface
, wszFilterInstanceName3
);
1601 ok(hr
== S_OK
, "IFilterGraph2_AddFilter failed with %08x\n", hr
);
1603 hr
= IFilterGraph2_Render(pgraph2
, ptestfilter
->ppPins
[0]);
1604 ok(hr
== S_OK
, "IFilterGraph2_Render failed with %08x\n", hr
);
1606 hr
= get_connected_filter_name(ptestfilter
, ConnectedFilterName1
);
1608 IFilterGraph2_Release(pgraph2
);
1610 IBaseFilter_Release(&ptestfilter
->IBaseFilter_iface
);
1612 IBaseFilter_Release(&ptestfilter2
->IBaseFilter_iface
);
1613 ptestfilter2
= NULL
;
1615 if (hr
== E_NOTIMPL
)
1617 win_skip("Needed functions are not implemented\n");
1621 hr
= CoCreateInstance(&CLSID_FilterGraph
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IFilterGraph2
, (LPVOID
*)&pgraph2
);
1622 ok(hr
== S_OK
, "CoCreateInstance failed with %08x\n", hr
);
1623 if (!pgraph2
) goto out
;
1625 hr
= createtestfilter(&GUID_NULL
, PinData1
, &ptestfilter
);
1626 ok(hr
== S_OK
, "createtestfilter failed with %08x\n", hr
);
1627 if (FAILED(hr
)) goto out
;
1629 hr
= IFilterGraph2_AddFilter(pgraph2
, &ptestfilter
->IBaseFilter_iface
, wszFilterInstanceName1
);
1630 ok(hr
== S_OK
, "IFilterGraph2_AddFilter failed with %08x\n", hr
);
1632 hr
= createtestfilter(&GUID_NULL
, PinData3
, &ptestfilter2
);
1633 ok(hr
== S_OK
, "createtestfilter failed with %08x\n", hr
);
1634 if (FAILED(hr
)) goto out
;
1636 hr
= IFilterGraph2_AddFilter(pgraph2
, &ptestfilter2
->IBaseFilter_iface
, wszFilterInstanceName3
);
1637 ok(hr
== S_OK
, "IFilterGraph2_AddFilter failed with %08x\n", hr
);
1639 IBaseFilter_Release(&ptestfilter2
->IBaseFilter_iface
);
1640 ptestfilter2
= NULL
;
1642 hr
= createtestfilter(&GUID_NULL
, PinData2
, &ptestfilter2
);
1643 ok(hr
== S_OK
, "createtestfilter failed with %08x\n", hr
);
1644 if (FAILED(hr
)) goto out
;
1646 hr
= IFilterGraph2_AddFilter(pgraph2
, &ptestfilter2
->IBaseFilter_iface
, wszFilterInstanceName2
);
1647 ok(hr
== S_OK
, "IFilterGraph2_AddFilter failed with %08x\n", hr
);
1649 hr
= IFilterGraph2_Render(pgraph2
, ptestfilter
->ppPins
[0]);
1650 ok(hr
== S_OK
, "IFilterGraph2_Render failed with %08x\n", hr
);
1652 hr
= IFilterGraph2_Disconnect(pgraph2
, NULL
);
1653 ok(hr
== E_POINTER
, "IFilterGraph2_Disconnect failed. Expected E_POINTER, received %08x\n", hr
);
1655 get_connected_filter_name(ptestfilter
, ConnectedFilterName2
);
1656 ok(strcmp(ConnectedFilterName1
, ConnectedFilterName2
),
1657 "expected connected filters to be different but got %s both times\n", ConnectedFilterName1
);
1659 IFilterGraph2_Release(pgraph2
);
1661 IBaseFilter_Release(&ptestfilter
->IBaseFilter_iface
);
1663 IBaseFilter_Release(&ptestfilter2
->IBaseFilter_iface
);
1664 ptestfilter2
= NULL
;
1666 /* Test if any preference is given to existing renderer which renders the pin directly vs
1667 an existing renderer which renders the pin indirectly, through an additional middle filter,
1668 again trying different orders of creation. Native appears not to give a preference. */
1670 hr
= CoCreateInstance(&CLSID_FilterGraph
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IFilterGraph2
, (LPVOID
*)&pgraph2
);
1671 ok(hr
== S_OK
, "CoCreateInstance failed with %08x\n", hr
);
1672 if (!pgraph2
) goto out
;
1674 hr
= createtestfilter(&GUID_NULL
, PinData1
, &ptestfilter
);
1675 ok(hr
== S_OK
, "createtestfilter failed with %08x\n", hr
);
1676 if (FAILED(hr
)) goto out
;
1678 hr
= IFilterGraph2_AddFilter(pgraph2
, &ptestfilter
->IBaseFilter_iface
, wszFilterInstanceName1
);
1679 ok(hr
== S_OK
, "IFilterGraph2_AddFilter failed with %08x\n", hr
);
1681 hr
= createtestfilter(&GUID_NULL
, PinData2
, &ptestfilter2
);
1682 ok(hr
== S_OK
, "createtestfilter failed with %08x\n", hr
);
1683 if (FAILED(hr
)) goto out
;
1685 hr
= IFilterGraph2_AddFilter(pgraph2
, &ptestfilter2
->IBaseFilter_iface
, wszFilterInstanceName2
);
1686 ok(hr
== S_OK
, "IFilterGraph2_AddFilter failed with %08x\n", hr
);
1688 IBaseFilter_Release(&ptestfilter2
->IBaseFilter_iface
);
1689 ptestfilter2
= NULL
;
1691 hr
= createtestfilter(&GUID_NULL
, PinData4
, &ptestfilter2
);
1692 ok(hr
== S_OK
, "createtestfilter failed with %08x\n", hr
);
1693 if (FAILED(hr
)) goto out
;
1695 hr
= IFilterGraph2_AddFilter(pgraph2
, &ptestfilter2
->IBaseFilter_iface
, wszFilterInstanceName3
);
1696 ok(hr
== S_OK
, "IFilterGraph2_AddFilter failed with %08x\n", hr
);
1698 IBaseFilter_Release(&ptestfilter2
->IBaseFilter_iface
);
1699 ptestfilter2
= NULL
;
1701 hr
= createtestfilter(&GUID_NULL
, PinData5
, &ptestfilter2
);
1702 ok(hr
== S_OK
, "createtestfilter failed with %08x\n", hr
);
1703 if (FAILED(hr
)) goto out
;
1705 hr
= IFilterGraph2_AddFilter(pgraph2
, &ptestfilter2
->IBaseFilter_iface
, wszFilterInstanceName4
);
1706 ok(hr
== S_OK
, "IFilterGraph2_AddFilter failed with %08x\n", hr
);
1708 hr
= IFilterGraph2_Render(pgraph2
, ptestfilter
->ppPins
[0]);
1709 ok(hr
== S_OK
, "IFilterGraph2_Render failed with %08x\n", hr
);
1711 get_connected_filter_name(ptestfilter
, ConnectedFilterName1
);
1712 ok(!strcmp(ConnectedFilterName1
, "TestfilterInstance3") || !strcmp(ConnectedFilterName1
, "TestfilterInstance2"),
1713 "unexpected connected filter: %s\n", ConnectedFilterName1
);
1715 IFilterGraph2_Release(pgraph2
);
1717 IBaseFilter_Release(&ptestfilter
->IBaseFilter_iface
);
1719 IBaseFilter_Release(&ptestfilter2
->IBaseFilter_iface
);
1720 ptestfilter2
= NULL
;
1722 hr
= CoCreateInstance(&CLSID_FilterGraph
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IFilterGraph2
, (LPVOID
*)&pgraph2
);
1723 ok(hr
== S_OK
, "CoCreateInstance failed with %08x\n", hr
);
1724 if (!pgraph2
) goto out
;
1726 hr
= createtestfilter(&GUID_NULL
, PinData1
, &ptestfilter
);
1727 ok(hr
== S_OK
, "createtestfilter failed with %08x\n", hr
);
1728 if (FAILED(hr
)) goto out
;
1730 hr
= IFilterGraph2_AddFilter(pgraph2
, &ptestfilter
->IBaseFilter_iface
, wszFilterInstanceName1
);
1731 ok(hr
== S_OK
, "IFilterGraph2_AddFilter failed with %08x\n", hr
);
1733 hr
= createtestfilter(&GUID_NULL
, PinData4
, &ptestfilter2
);
1734 ok(hr
== S_OK
, "createtestfilter failed with %08x\n", hr
);
1735 if (FAILED(hr
)) goto out
;
1737 hr
= IFilterGraph2_AddFilter(pgraph2
, &ptestfilter2
->IBaseFilter_iface
, wszFilterInstanceName3
);
1738 ok(hr
== S_OK
, "IFilterGraph2_AddFilter failed with %08x\n", hr
);
1740 IBaseFilter_Release(&ptestfilter2
->IBaseFilter_iface
);
1741 ptestfilter2
= NULL
;
1743 hr
= createtestfilter(&GUID_NULL
, PinData5
, &ptestfilter2
);
1744 ok(hr
== S_OK
, "createtestfilter failed with %08x\n", hr
);
1745 if (FAILED(hr
)) goto out
;
1747 hr
= IFilterGraph2_AddFilter(pgraph2
, &ptestfilter2
->IBaseFilter_iface
, wszFilterInstanceName4
);
1748 ok(hr
== S_OK
, "IFilterGraph2_AddFilter failed with %08x\n", hr
);
1750 IBaseFilter_Release(&ptestfilter2
->IBaseFilter_iface
);
1751 ptestfilter2
= NULL
;
1753 hr
= createtestfilter(&GUID_NULL
, PinData2
, &ptestfilter2
);
1754 ok(hr
== S_OK
, "createtestfilter failed with %08x\n", hr
);
1755 if (FAILED(hr
)) goto out
;
1757 hr
= IFilterGraph2_AddFilter(pgraph2
, &ptestfilter2
->IBaseFilter_iface
, wszFilterInstanceName2
);
1758 ok(hr
== S_OK
, "IFilterGraph2_AddFilter failed with %08x\n", hr
);
1760 hr
= IFilterGraph2_Render(pgraph2
, ptestfilter
->ppPins
[0]);
1761 ok(hr
== S_OK
, "IFilterGraph2_Render failed with %08x\n", hr
);
1763 get_connected_filter_name(ptestfilter
, ConnectedFilterName2
);
1764 ok(!strcmp(ConnectedFilterName2
, "TestfilterInstance3") || !strcmp(ConnectedFilterName2
, "TestfilterInstance2"),
1765 "unexpected connected filter: %s\n", ConnectedFilterName2
);
1766 ok(strcmp(ConnectedFilterName1
, ConnectedFilterName2
),
1767 "expected connected filters to be different but got %s both times\n", ConnectedFilterName1
);
1769 IFilterGraph2_Release(pgraph2
);
1771 IBaseFilter_Release(&ptestfilter
->IBaseFilter_iface
);
1773 IBaseFilter_Release(&ptestfilter2
->IBaseFilter_iface
);
1774 ptestfilter2
= NULL
;
1776 /* Test if renderers are tried before non-renderers (intermediary filters). */
1777 hr
= CoCreateInstance(&CLSID_FilterGraph
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IFilterGraph2
, (LPVOID
*)&pgraph2
);
1778 ok(hr
== S_OK
, "CoCreateInstance failed with %08x\n", hr
);
1779 if (!pgraph2
) goto out
;
1781 hr
= CoCreateInstance(&CLSID_FilterMapper2
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IFilterMapper2
, (LPVOID
*)&pMapper2
);
1782 ok(hr
== S_OK
, "CoCreateInstance failed with %08x\n", hr
);
1783 if (!pMapper2
) goto out
;
1785 hr
= createtestfilter(&GUID_NULL
, PinData1
, &ptestfilter
);
1786 ok(hr
== S_OK
, "createtestfilter failed with %08x\n", hr
);
1787 if (FAILED(hr
)) goto out
;
1789 hr
= IFilterGraph2_AddFilter(pgraph2
, &ptestfilter
->IBaseFilter_iface
, wszFilterInstanceName1
);
1790 ok(hr
== S_OK
, "IFilterGraph2_AddFilter failed with %08x\n", hr
);
1792 /* Register our filters with COM and with Filtermapper. */
1793 hr
= CoRegisterClassObject(Filter1ClassFactory
.clsid
,
1794 (IUnknown
*)&Filter1ClassFactory
.IClassFactory_iface
, CLSCTX_INPROC_SERVER
,
1795 REGCLS_MULTIPLEUSE
, &cookie1
);
1796 ok(hr
== S_OK
, "CoRegisterClassObject failed with %08x\n", hr
);
1797 if (FAILED(hr
)) goto out
;
1798 hr
= CoRegisterClassObject(Filter2ClassFactory
.clsid
,
1799 (IUnknown
*)&Filter2ClassFactory
.IClassFactory_iface
, CLSCTX_INPROC_SERVER
,
1800 REGCLS_MULTIPLEUSE
, &cookie2
);
1801 ok(hr
== S_OK
, "CoRegisterClassObject failed with %08x\n", hr
);
1802 if (FAILED(hr
)) goto out
;
1803 hr
= CoRegisterClassObject(Filter3ClassFactory
.clsid
,
1804 (IUnknown
*)&Filter3ClassFactory
.IClassFactory_iface
, CLSCTX_INPROC_SERVER
,
1805 REGCLS_MULTIPLEUSE
, &cookie3
);
1806 ok(hr
== S_OK
, "CoRegisterClassObject failed with %08x\n", hr
);
1807 if (FAILED(hr
)) goto out
;
1810 rgf2
.dwMerit
= MERIT_UNLIKELY
;
1811 S2(U(rgf2
)).cPins2
= 1;
1812 S2(U(rgf2
)).rgPins2
= rgPins2
;
1813 rgPins2
[0].dwFlags
= REG_PINFLAG_B_RENDERER
;
1814 rgPins2
[0].cInstances
= 1;
1815 rgPins2
[0].nMediaTypes
= 1;
1816 rgPins2
[0].lpMediaType
= &rgPinType
[0];
1817 rgPins2
[0].nMediums
= 0;
1818 rgPins2
[0].lpMedium
= NULL
;
1819 rgPins2
[0].clsPinCategory
= NULL
;
1820 rgPinType
[0].clsMajorType
= &MEDIATYPE_Video
;
1821 rgPinType
[0].clsMinorType
= &mediasubtype1
;
1823 hr
= IFilterMapper2_RegisterFilter(pMapper2
, &CLSID_TestFilter2
, wszFilterInstanceName2
, NULL
,
1824 &CLSID_LegacyAmFilterCategory
, NULL
, &rgf2
);
1825 if (hr
== E_ACCESSDENIED
)
1826 skip("Not authorized to register filters\n");
1829 ok(hr
== S_OK
, "IFilterMapper2_RegisterFilter failed with %x\n", hr
);
1831 rgf2
.dwMerit
= MERIT_PREFERRED
;
1832 rgPinType
[0].clsMinorType
= &mediasubtype2
;
1834 hr
= IFilterMapper2_RegisterFilter(pMapper2
, &CLSID_TestFilter4
, wszFilterInstanceName4
, NULL
,
1835 &CLSID_LegacyAmFilterCategory
, NULL
, &rgf2
);
1836 ok(hr
== S_OK
, "IFilterMapper2_RegisterFilter failed with %x\n", hr
);
1838 S2(U(rgf2
)).cPins2
= 2;
1839 rgPins2
[0].dwFlags
= 0;
1840 rgPinType
[0].clsMinorType
= &mediasubtype1
;
1842 rgPins2
[1].dwFlags
= REG_PINFLAG_B_OUTPUT
;
1843 rgPins2
[1].cInstances
= 1;
1844 rgPins2
[1].nMediaTypes
= 1;
1845 rgPins2
[1].lpMediaType
= &rgPinType
[1];
1846 rgPins2
[1].nMediums
= 0;
1847 rgPins2
[1].lpMedium
= NULL
;
1848 rgPins2
[1].clsPinCategory
= NULL
;
1849 rgPinType
[1].clsMajorType
= &MEDIATYPE_Video
;
1850 rgPinType
[1].clsMinorType
= &mediasubtype2
;
1852 hr
= IFilterMapper2_RegisterFilter(pMapper2
, &CLSID_TestFilter3
, wszFilterInstanceName3
, NULL
,
1853 &CLSID_LegacyAmFilterCategory
, NULL
, &rgf2
);
1854 ok(hr
== S_OK
, "IFilterMapper2_RegisterFilter failed with %x\n", hr
);
1856 hr
= IFilterGraph2_Render(pgraph2
, ptestfilter
->ppPins
[0]);
1857 ok(hr
== S_OK
, "IFilterGraph2_Render failed with %08x\n", hr
);
1859 get_connected_filter_name(ptestfilter
, ConnectedFilterName1
);
1860 ok(!strcmp(ConnectedFilterName1
, "TestfilterInstance3"),
1861 "unexpected connected filter: %s\n", ConnectedFilterName1
);
1863 hr
= IFilterMapper2_UnregisterFilter(pMapper2
, &CLSID_LegacyAmFilterCategory
, NULL
,
1864 &CLSID_TestFilter2
);
1865 ok(hr
== S_OK
, "IFilterMapper2_UnregisterFilter failed with %x\n", hr
);
1866 hr
= IFilterMapper2_UnregisterFilter(pMapper2
, &CLSID_LegacyAmFilterCategory
, NULL
,
1867 &CLSID_TestFilter3
);
1868 ok(hr
== S_OK
, "IFilterMapper2_UnregisterFilter failed with %x\n", hr
);
1869 hr
= IFilterMapper2_UnregisterFilter(pMapper2
, &CLSID_LegacyAmFilterCategory
, NULL
,
1870 &CLSID_TestFilter4
);
1871 ok(hr
== S_OK
, "IFilterMapper2_UnregisterFilter failed with %x\n", hr
);
1876 if (ptestfilter
) IBaseFilter_Release(&ptestfilter
->IBaseFilter_iface
);
1877 if (ptestfilter2
) IBaseFilter_Release(&ptestfilter2
->IBaseFilter_iface
);
1878 if (pgraph2
) IFilterGraph2_Release(pgraph2
);
1879 if (pMapper2
) IFilterMapper2_Release(pMapper2
);
1881 hr
= CoRevokeClassObject(cookie1
);
1882 ok(hr
== S_OK
, "CoRevokeClassObject failed with %08x\n", hr
);
1883 hr
= CoRevokeClassObject(cookie2
);
1884 ok(hr
== S_OK
, "CoRevokeClassObject failed with %08x\n", hr
);
1885 hr
= CoRevokeClassObject(cookie3
);
1886 ok(hr
== S_OK
, "CoRevokeClassObject failed with %08x\n", hr
);
1889 typedef struct IUnknownImpl
1891 IUnknown IUnknown_iface
;
1896 static IUnknownImpl
*IUnknownImpl_from_iface(IUnknown
* iface
)
1898 return CONTAINING_RECORD(iface
, IUnknownImpl
, IUnknown_iface
);
1901 static HRESULT WINAPI
IUnknownImpl_QueryInterface(IUnknown
* iface
, REFIID riid
, LPVOID
* ppv
)
1903 ok(0, "QueryInterface should not be called for %s\n", wine_dbgstr_guid(riid
));
1904 return E_NOINTERFACE
;
1907 static ULONG WINAPI
IUnknownImpl_AddRef(IUnknown
* iface
)
1909 IUnknownImpl
*This
= IUnknownImpl_from_iface(iface
);
1910 This
->AddRef_called
++;
1914 static ULONG WINAPI
IUnknownImpl_Release(IUnknown
* iface
)
1916 IUnknownImpl
*This
= IUnknownImpl_from_iface(iface
);
1917 This
->Release_called
++;
1921 static CONST_VTBL IUnknownVtbl IUnknownImpl_Vtbl
=
1923 IUnknownImpl_QueryInterface
,
1924 IUnknownImpl_AddRef
,
1925 IUnknownImpl_Release
1928 static void test_aggregate_filter_graph(void)
1933 IUnknownImpl unk_outer
= { { &IUnknownImpl_Vtbl
}, 0, 0 };
1935 hr
= CoCreateInstance(&CLSID_FilterGraph
, &unk_outer
.IUnknown_iface
, CLSCTX_INPROC_SERVER
,
1936 &IID_IUnknown
, (void **)&pgraph
);
1937 ok(hr
== S_OK
, "CoCreateInstance returned %x\n", hr
);
1938 ok(pgraph
!= &unk_outer
.IUnknown_iface
, "pgraph = %p, expected not %p\n", pgraph
, &unk_outer
.IUnknown_iface
);
1940 hr
= IUnknown_QueryInterface(pgraph
, &IID_IUnknown
, (void **)&punk
);
1941 ok(hr
== S_OK
, "CoCreateInstance returned %x\n", hr
);
1942 ok(punk
!= &unk_outer
.IUnknown_iface
, "punk = %p, expected not %p\n", punk
, &unk_outer
.IUnknown_iface
);
1943 IUnknown_Release(punk
);
1946 ok(unk_outer
.AddRef_called
== 0, "IUnknownImpl_AddRef called %d times\n", unk_outer
.AddRef_called
);
1948 ok(unk_outer
.Release_called
== 0, "IUnknownImpl_Release called %d times\n", unk_outer
.Release_called
);
1949 unk_outer
.AddRef_called
= 0;
1950 unk_outer
.Release_called
= 0;
1952 hr
= IUnknown_QueryInterface(pgraph
, &IID_IFilterMapper
, (void **)&punk
);
1953 ok(hr
== S_OK
, "CoCreateInstance returned %x\n", hr
);
1954 ok(punk
!= &unk_outer
.IUnknown_iface
, "punk = %p, expected not %p\n", punk
, &unk_outer
.IUnknown_iface
);
1955 IUnknown_Release(punk
);
1957 ok(unk_outer
.AddRef_called
== 1, "IUnknownImpl_AddRef called %d times\n", unk_outer
.AddRef_called
);
1958 ok(unk_outer
.Release_called
== 1, "IUnknownImpl_Release called %d times\n", unk_outer
.Release_called
);
1959 unk_outer
.AddRef_called
= 0;
1960 unk_outer
.Release_called
= 0;
1962 hr
= IUnknown_QueryInterface(pgraph
, &IID_IFilterMapper2
, (void **)&punk
);
1963 ok(hr
== S_OK
, "CoCreateInstance returned %x\n", hr
);
1964 ok(punk
!= &unk_outer
.IUnknown_iface
, "punk = %p, expected not %p\n", punk
, &unk_outer
.IUnknown_iface
);
1965 IUnknown_Release(punk
);
1967 ok(unk_outer
.AddRef_called
== 1, "IUnknownImpl_AddRef called %d times\n", unk_outer
.AddRef_called
);
1968 ok(unk_outer
.Release_called
== 1, "IUnknownImpl_Release called %d times\n", unk_outer
.Release_called
);
1969 unk_outer
.AddRef_called
= 0;
1970 unk_outer
.Release_called
= 0;
1972 hr
= IUnknown_QueryInterface(pgraph
, &IID_IFilterMapper3
, (void **)&punk
);
1973 ok(hr
== S_OK
, "CoCreateInstance returned %x\n", hr
);
1974 ok(punk
!= &unk_outer
.IUnknown_iface
, "punk = %p, expected not %p\n", punk
, &unk_outer
.IUnknown_iface
);
1975 IUnknown_Release(punk
);
1977 ok(unk_outer
.AddRef_called
== 1, "IUnknownImpl_AddRef called %d times\n", unk_outer
.AddRef_called
);
1978 ok(unk_outer
.Release_called
== 1, "IUnknownImpl_Release called %d times\n", unk_outer
.Release_called
);
1980 IUnknown_Release(pgraph
);
1983 START_TEST(filtergraph
)
1986 CoInitializeEx(NULL
, COINIT_MULTITHREADED
);
1987 hr
= CoCreateInstance(&CLSID_FilterGraph
, NULL
, CLSCTX_INPROC_SERVER
,
1988 &IID_IGraphBuilder
, (LPVOID
*)&pgraph
);
1990 skip("Creating filtergraph returned %08x, skipping tests\n", hr
);
1993 IGraphBuilder_Release(pgraph
);
1994 test_render_run(avifile
);
1995 test_render_run(mpegfile
);
1996 test_graph_builder();
1997 test_graph_builder_addfilter();
1998 test_mediacontrol();
1999 test_filter_graph2();
2000 test_render_filter_priority();
2001 test_aggregate_filter_graph();