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 /* add the two filters to the graph */
184 hr
= IGraphBuilder_AddFilter(pgraph
, pF
, testFilterW
);
185 ok(hr
== S_OK
, "failed to add pF to the graph: %x\n", hr
);
188 hr
= IBaseFilter_EnumPins(pF
, &pEnum
);
189 ok(hr
== S_OK
, "IBaseFilter_EnumPins failed for pF: %x\n", hr
);
190 ok(pEnum
!= NULL
, "pEnum is NULL\n");
191 hr
= IEnumPins_Next(pEnum
, 1, &pIn
, NULL
);
192 ok(hr
== S_OK
, "IEnumPins_Next failed for pF: %x\n", hr
);
193 ok(pIn
!= NULL
, "pIn is NULL\n");
194 hr
= IPin_QueryDirection(pIn
, &dir
);
195 ok(hr
== S_OK
, "IPin_QueryDirection failed: %x\n", hr
);
196 ok(dir
== PINDIR_INPUT
, "pin has wrong direction\n");
198 hr
= IGraphBuilder_FindFilterByName(pgraph
, fooBarW
, &pF2
);
199 ok(hr
== VFW_E_NOT_FOUND
, "IGraphBuilder_FindFilterByName returned %x\n", hr
);
200 ok(pF2
== NULL
, "IGraphBuilder_FindFilterByName returned %p\n", pF2
);
201 hr
= IGraphBuilder_FindFilterByName(pgraph
, testFilterW
, &pF2
);
202 ok(hr
== S_OK
, "IGraphBuilder_FindFilterByName returned %x\n", hr
);
203 ok(pF2
!= NULL
, "IGraphBuilder_FindFilterByName returned NULL\n");
204 hr
= IGraphBuilder_FindFilterByName(pgraph
, testFilterW
, NULL
);
205 ok(hr
== E_POINTER
, "IGraphBuilder_FindFilterByName returned %x\n", hr
);
207 if (pIn
) IPin_Release(pIn
);
208 if (pEnum
) IEnumPins_Release(pEnum
);
209 if (pF
) IBaseFilter_Release(pF
);
210 if (pF2
) IBaseFilter_Release(pF2
);
212 releasefiltergraph();
215 static void test_graph_builder_addfilter(void)
218 IBaseFilter
*pF
= NULL
;
219 static const WCHAR testFilterW
[] = {'t','e','s','t','F','i','l','t','e','r',0};
221 if (!createfiltergraph())
224 hr
= IGraphBuilder_AddFilter(pgraph
, NULL
, testFilterW
);
225 ok(hr
== E_POINTER
, "IGraphBuilder_AddFilter returned: %x\n", hr
);
227 /* create video filter */
228 hr
= CoCreateInstance(&CLSID_VideoRenderer
, NULL
, CLSCTX_INPROC_SERVER
,
229 &IID_IBaseFilter
, (LPVOID
*)&pF
);
230 ok(hr
== S_OK
, "CoCreateInstance failed with %x\n", hr
);
231 ok(pF
!= NULL
, "pF is NULL\n");
233 skip("failed to created filter, skipping\n");
237 hr
= IGraphBuilder_AddFilter(pgraph
, pF
, NULL
);
238 ok(hr
== S_OK
, "IGraphBuilder_AddFilter returned: %x\n", hr
);
239 IBaseFilter_Release(pF
);
242 static void test_mediacontrol(void)
245 LONGLONG pos
= 0xdeadbeef;
246 IMediaSeeking
*seeking
= NULL
;
247 IMediaFilter
*filter
= NULL
;
248 IMediaControl
*control
= NULL
;
250 IGraphBuilder_SetDefaultSyncSource(pgraph
);
251 hr
= IGraphBuilder_QueryInterface(pgraph
, &IID_IMediaSeeking
, (void**) &seeking
);
252 ok(hr
== S_OK
, "QueryInterface IMediaControl failed: %08x\n", hr
);
256 hr
= IGraphBuilder_QueryInterface(pgraph
, &IID_IMediaFilter
, (void**) &filter
);
257 ok(hr
== S_OK
, "QueryInterface IMediaFilter failed: %08x\n", hr
);
260 IMediaSeeking_Release(seeking
);
264 hr
= IGraphBuilder_QueryInterface(pgraph
, &IID_IMediaControl
, (void**) &control
);
265 ok(hr
== S_OK
, "QueryInterface IMediaControl failed: %08x\n", hr
);
268 IMediaSeeking_Release(seeking
);
269 IMediaFilter_Release(filter
);
273 hr
= IMediaSeeking_GetCurrentPosition(seeking
, &pos
);
274 ok(hr
== S_OK
, "GetCurrentPosition failed: %08x\n", hr
);
275 ok(pos
== 0, "Position != 0 (%x%08x)\n", (DWORD
)(pos
>> 32), (DWORD
)pos
);
277 hr
= IMediaSeeking_SetPositions(seeking
, NULL
, AM_SEEKING_ReturnTime
, NULL
, AM_SEEKING_NoPositioning
);
278 ok(hr
== S_OK
, "SetPositions failed: %08x\n", hr
);
279 hr
= IMediaSeeking_SetPositions(seeking
, NULL
, AM_SEEKING_NoPositioning
, NULL
, AM_SEEKING_ReturnTime
);
280 ok(hr
== S_OK
, "SetPositions failed: %08x\n", hr
);
282 IMediaFilter_SetSyncSource(filter
, NULL
);
284 hr
= IMediaSeeking_GetCurrentPosition(seeking
, &pos
);
285 ok(hr
== S_OK
, "GetCurrentPosition failed: %08x\n", hr
);
286 ok(pos
== 0, "Position != 0 (%x%08x)\n", (DWORD
)(pos
>> 32), (DWORD
)pos
);
288 hr
= IMediaControl_GetState(control
, 1000, NULL
);
289 ok(hr
== E_POINTER
, "GetState expected %08x, got %08x\n", E_POINTER
, hr
);
291 IMediaControl_Release(control
);
292 IMediaSeeking_Release(seeking
);
293 IMediaFilter_Release(filter
);
294 releasefiltergraph();
297 static void test_filter_graph2(void)
300 IFilterGraph2
*pF
= NULL
;
302 hr
= CoCreateInstance(&CLSID_FilterGraph
, NULL
, CLSCTX_INPROC_SERVER
,
303 &IID_IFilterGraph2
, (LPVOID
*)&pF
);
304 ok(hr
== S_OK
, "CoCreateInstance failed with %x\n", hr
);
305 ok(pF
!= NULL
, "pF is NULL\n");
307 hr
= IFilterGraph2_Release(pF
);
308 ok(hr
== 0, "IFilterGraph2_Release returned: %x\n", hr
);
311 /* IEnumMediaTypes implementation (supporting code for Render() test.) */
312 static void FreeMediaType(AM_MEDIA_TYPE
* pMediaType
)
314 if (pMediaType
->pbFormat
)
316 CoTaskMemFree(pMediaType
->pbFormat
);
317 pMediaType
->pbFormat
= NULL
;
319 if (pMediaType
->pUnk
)
321 IUnknown_Release(pMediaType
->pUnk
);
322 pMediaType
->pUnk
= NULL
;
326 static HRESULT
CopyMediaType(AM_MEDIA_TYPE
* pDest
, const AM_MEDIA_TYPE
*pSrc
)
329 if (!pSrc
->pbFormat
) return S_OK
;
330 if (!(pDest
->pbFormat
= CoTaskMemAlloc(pSrc
->cbFormat
)))
331 return E_OUTOFMEMORY
;
332 memcpy(pDest
->pbFormat
, pSrc
->pbFormat
, pSrc
->cbFormat
);
334 IUnknown_AddRef(pDest
->pUnk
);
338 static AM_MEDIA_TYPE
* CreateMediaType(AM_MEDIA_TYPE
const * pSrc
)
340 AM_MEDIA_TYPE
* pDest
;
342 pDest
= CoTaskMemAlloc(sizeof(AM_MEDIA_TYPE
));
346 if (FAILED(CopyMediaType(pDest
, pSrc
)))
348 CoTaskMemFree(pDest
);
355 static BOOL
CompareMediaTypes(const AM_MEDIA_TYPE
* pmt1
, const AM_MEDIA_TYPE
* pmt2
, BOOL bWildcards
)
357 return (((bWildcards
&& (IsEqualGUID(&pmt1
->majortype
, &GUID_NULL
) || IsEqualGUID(&pmt2
->majortype
, &GUID_NULL
))) || IsEqualGUID(&pmt1
->majortype
, &pmt2
->majortype
)) &&
358 ((bWildcards
&& (IsEqualGUID(&pmt1
->subtype
, &GUID_NULL
) || IsEqualGUID(&pmt2
->subtype
, &GUID_NULL
))) || IsEqualGUID(&pmt1
->subtype
, &pmt2
->subtype
)));
361 static void DeleteMediaType(AM_MEDIA_TYPE
* pMediaType
)
363 FreeMediaType(pMediaType
);
364 CoTaskMemFree(pMediaType
);
367 typedef struct IEnumMediaTypesImpl
369 IEnumMediaTypes IEnumMediaTypes_iface
;
371 AM_MEDIA_TYPE
*pMediaTypes
;
374 } IEnumMediaTypesImpl
;
376 static const struct IEnumMediaTypesVtbl IEnumMediaTypesImpl_Vtbl
;
378 static inline IEnumMediaTypesImpl
*impl_from_IEnumMediaTypes(IEnumMediaTypes
*iface
)
380 return CONTAINING_RECORD(iface
, IEnumMediaTypesImpl
, IEnumMediaTypes_iface
);
383 static HRESULT
IEnumMediaTypesImpl_Construct(const AM_MEDIA_TYPE
* pMediaTypes
, ULONG cMediaTypes
, IEnumMediaTypes
** ppEnum
)
386 IEnumMediaTypesImpl
* pEnumMediaTypes
= CoTaskMemAlloc(sizeof(IEnumMediaTypesImpl
));
388 if (!pEnumMediaTypes
)
391 return E_OUTOFMEMORY
;
393 pEnumMediaTypes
->IEnumMediaTypes_iface
.lpVtbl
= &IEnumMediaTypesImpl_Vtbl
;
394 pEnumMediaTypes
->refCount
= 1;
395 pEnumMediaTypes
->uIndex
= 0;
396 pEnumMediaTypes
->cMediaTypes
= cMediaTypes
;
397 pEnumMediaTypes
->pMediaTypes
= CoTaskMemAlloc(sizeof(AM_MEDIA_TYPE
) * cMediaTypes
);
398 for (i
= 0; i
< cMediaTypes
; i
++)
399 if (FAILED(CopyMediaType(&pEnumMediaTypes
->pMediaTypes
[i
], &pMediaTypes
[i
])))
402 FreeMediaType(&pEnumMediaTypes
->pMediaTypes
[i
]);
403 CoTaskMemFree(pEnumMediaTypes
->pMediaTypes
);
404 return E_OUTOFMEMORY
;
406 *ppEnum
= &pEnumMediaTypes
->IEnumMediaTypes_iface
;
410 static HRESULT WINAPI
IEnumMediaTypesImpl_QueryInterface(IEnumMediaTypes
* iface
, REFIID riid
, LPVOID
* ppv
)
414 if (IsEqualIID(riid
, &IID_IUnknown
))
416 else if (IsEqualIID(riid
, &IID_IEnumMediaTypes
))
421 IUnknown_AddRef((IUnknown
*)(*ppv
));
425 return E_NOINTERFACE
;
428 static ULONG WINAPI
IEnumMediaTypesImpl_AddRef(IEnumMediaTypes
* iface
)
430 IEnumMediaTypesImpl
*This
= impl_from_IEnumMediaTypes(iface
);
431 ULONG refCount
= InterlockedIncrement(&This
->refCount
);
436 static ULONG WINAPI
IEnumMediaTypesImpl_Release(IEnumMediaTypes
* iface
)
438 IEnumMediaTypesImpl
*This
= impl_from_IEnumMediaTypes(iface
);
439 ULONG refCount
= InterlockedDecrement(&This
->refCount
);
444 for (i
= 0; i
< This
->cMediaTypes
; i
++)
445 FreeMediaType(&This
->pMediaTypes
[i
]);
446 CoTaskMemFree(This
->pMediaTypes
);
452 static HRESULT WINAPI
IEnumMediaTypesImpl_Next(IEnumMediaTypes
* iface
, ULONG cMediaTypes
, AM_MEDIA_TYPE
** ppMediaTypes
, ULONG
* pcFetched
)
455 IEnumMediaTypesImpl
*This
= impl_from_IEnumMediaTypes(iface
);
457 cFetched
= min(This
->cMediaTypes
, This
->uIndex
+ cMediaTypes
) - This
->uIndex
;
462 for (i
= 0; i
< cFetched
; i
++)
463 if (!(ppMediaTypes
[i
] = CreateMediaType(&This
->pMediaTypes
[This
->uIndex
+ i
])))
466 DeleteMediaType(ppMediaTypes
[i
]);
468 return E_OUTOFMEMORY
;
472 if ((cMediaTypes
!= 1) || pcFetched
)
473 *pcFetched
= cFetched
;
475 This
->uIndex
+= cFetched
;
477 if (cFetched
!= cMediaTypes
)
482 static HRESULT WINAPI
IEnumMediaTypesImpl_Skip(IEnumMediaTypes
* iface
, ULONG cMediaTypes
)
484 IEnumMediaTypesImpl
*This
= impl_from_IEnumMediaTypes(iface
);
486 if (This
->uIndex
+ cMediaTypes
< This
->cMediaTypes
)
488 This
->uIndex
+= cMediaTypes
;
494 static HRESULT WINAPI
IEnumMediaTypesImpl_Reset(IEnumMediaTypes
* iface
)
496 IEnumMediaTypesImpl
*This
= impl_from_IEnumMediaTypes(iface
);
502 static HRESULT WINAPI
IEnumMediaTypesImpl_Clone(IEnumMediaTypes
* iface
, IEnumMediaTypes
** ppEnum
)
505 IEnumMediaTypesImpl
*This
= impl_from_IEnumMediaTypes(iface
);
507 hr
= IEnumMediaTypesImpl_Construct(This
->pMediaTypes
, This
->cMediaTypes
, ppEnum
);
510 return IEnumMediaTypes_Skip(*ppEnum
, This
->uIndex
);
513 static const IEnumMediaTypesVtbl IEnumMediaTypesImpl_Vtbl
=
515 IEnumMediaTypesImpl_QueryInterface
,
516 IEnumMediaTypesImpl_AddRef
,
517 IEnumMediaTypesImpl_Release
,
518 IEnumMediaTypesImpl_Next
,
519 IEnumMediaTypesImpl_Skip
,
520 IEnumMediaTypesImpl_Reset
,
521 IEnumMediaTypesImpl_Clone
524 /* Implementation of a very stripped down pin for the test filter. Just enough
525 functionality for connecting and Render() to work. */
527 static void Copy_PinInfo(PIN_INFO
* pDest
, const PIN_INFO
* pSrc
)
529 lstrcpyW(pDest
->achName
, pSrc
->achName
);
530 pDest
->dir
= pSrc
->dir
;
531 pDest
->pFilter
= pSrc
->pFilter
;
534 typedef struct ITestPinImpl
538 LPCRITICAL_SECTION pCritSec
;
541 AM_MEDIA_TYPE mtCurrent
;
545 static inline ITestPinImpl
*impl_from_IPin(IPin
*iface
)
547 return CONTAINING_RECORD(iface
, ITestPinImpl
, IPin_iface
);
550 static HRESULT WINAPI
TestFilter_Pin_QueryInterface(IPin
* iface
, REFIID riid
, LPVOID
* ppv
)
554 if (IsEqualIID(riid
, &IID_IUnknown
))
556 else if (IsEqualIID(riid
, &IID_IPin
))
561 IUnknown_AddRef((IUnknown
*)(*ppv
));
565 return E_NOINTERFACE
;
568 static ULONG WINAPI
TestFilter_Pin_AddRef(IPin
* iface
)
570 ITestPinImpl
*This
= impl_from_IPin(iface
);
571 ULONG refCount
= InterlockedIncrement(&This
->refCount
);
575 static ULONG WINAPI
TestFilter_Pin_Release(IPin
* iface
)
577 ITestPinImpl
*This
= impl_from_IPin(iface
);
578 ULONG refCount
= InterlockedDecrement(&This
->refCount
);
582 FreeMediaType(&This
->mtCurrent
);
590 static HRESULT WINAPI
TestFilter_InputPin_Connect(IPin
* iface
, IPin
* pConnector
, const AM_MEDIA_TYPE
* pmt
)
595 static HRESULT WINAPI
TestFilter_InputPin_ReceiveConnection(IPin
* iface
, IPin
* pReceivePin
, const AM_MEDIA_TYPE
* pmt
)
597 ITestPinImpl
*This
= impl_from_IPin(iface
);
598 PIN_DIRECTION pindirReceive
;
601 EnterCriticalSection(This
->pCritSec
);
603 if (!(IsEqualIID(&pmt
->majortype
, &This
->mtCurrent
.majortype
) && (IsEqualIID(&pmt
->subtype
, &This
->mtCurrent
.subtype
) ||
604 IsEqualIID(&GUID_NULL
, &This
->mtCurrent
.subtype
))))
605 hr
= VFW_E_TYPE_NOT_ACCEPTED
;
607 if (This
->pConnectedTo
)
608 hr
= VFW_E_ALREADY_CONNECTED
;
612 IPin_QueryDirection(pReceivePin
, &pindirReceive
);
614 if (pindirReceive
!= PINDIR_OUTPUT
)
616 hr
= VFW_E_INVALID_DIRECTION
;
622 CopyMediaType(&This
->mtCurrent
, pmt
);
623 This
->pConnectedTo
= pReceivePin
;
624 IPin_AddRef(pReceivePin
);
627 LeaveCriticalSection(This
->pCritSec
);
632 static HRESULT WINAPI
TestFilter_Pin_Disconnect(IPin
* iface
)
635 ITestPinImpl
*This
= impl_from_IPin(iface
);
637 EnterCriticalSection(This
->pCritSec
);
639 if (This
->pConnectedTo
)
641 IPin_Release(This
->pConnectedTo
);
642 This
->pConnectedTo
= NULL
;
648 LeaveCriticalSection(This
->pCritSec
);
653 static HRESULT WINAPI
TestFilter_Pin_ConnectedTo(IPin
* iface
, IPin
** ppPin
)
656 ITestPinImpl
*This
= impl_from_IPin(iface
);
658 EnterCriticalSection(This
->pCritSec
);
660 if (This
->pConnectedTo
)
662 *ppPin
= This
->pConnectedTo
;
668 hr
= VFW_E_NOT_CONNECTED
;
672 LeaveCriticalSection(This
->pCritSec
);
677 static HRESULT WINAPI
TestFilter_Pin_ConnectionMediaType(IPin
* iface
, AM_MEDIA_TYPE
* pmt
)
680 ITestPinImpl
*This
= impl_from_IPin(iface
);
682 EnterCriticalSection(This
->pCritSec
);
684 if (This
->pConnectedTo
)
686 CopyMediaType(pmt
, &This
->mtCurrent
);
691 ZeroMemory(pmt
, sizeof(*pmt
));
692 hr
= VFW_E_NOT_CONNECTED
;
695 LeaveCriticalSection(This
->pCritSec
);
700 static HRESULT WINAPI
TestFilter_Pin_QueryPinInfo(IPin
* iface
, PIN_INFO
* pInfo
)
702 ITestPinImpl
*This
= impl_from_IPin(iface
);
704 Copy_PinInfo(pInfo
, &This
->pinInfo
);
705 IBaseFilter_AddRef(pInfo
->pFilter
);
710 static HRESULT WINAPI
TestFilter_Pin_QueryDirection(IPin
* iface
, PIN_DIRECTION
* pPinDir
)
712 ITestPinImpl
*This
= impl_from_IPin(iface
);
714 *pPinDir
= This
->pinInfo
.dir
;
719 static HRESULT WINAPI
TestFilter_Pin_QueryId(IPin
* iface
, LPWSTR
* Id
)
724 static HRESULT WINAPI
TestFilter_Pin_QueryAccept(IPin
* iface
, const AM_MEDIA_TYPE
* pmt
)
726 ITestPinImpl
*This
= impl_from_IPin(iface
);
728 if (IsEqualIID(&pmt
->majortype
, &This
->mtCurrent
.majortype
) && (IsEqualIID(&pmt
->subtype
, &This
->mtCurrent
.subtype
) ||
729 IsEqualIID(&GUID_NULL
, &This
->mtCurrent
.subtype
)))
732 return VFW_E_TYPE_NOT_ACCEPTED
;
735 static HRESULT WINAPI
TestFilter_Pin_EnumMediaTypes(IPin
* iface
, IEnumMediaTypes
** ppEnum
)
737 ITestPinImpl
*This
= impl_from_IPin(iface
);
739 return IEnumMediaTypesImpl_Construct(&This
->mtCurrent
, 1, ppEnum
);
742 static HRESULT WINAPI
TestFilter_Pin_QueryInternalConnections(IPin
* iface
, IPin
** apPin
, ULONG
* cPin
)
747 static HRESULT WINAPI
TestFilter_Pin_BeginFlush(IPin
* iface
)
752 static HRESULT WINAPI
TestFilter_Pin_EndFlush(IPin
* iface
)
757 static HRESULT WINAPI
TestFilter_Pin_NewSegment(IPin
* iface
, REFERENCE_TIME tStart
, REFERENCE_TIME tStop
, double dRate
)
762 static HRESULT WINAPI
TestFilter_Pin_EndOfStream(IPin
* iface
)
767 static const IPinVtbl TestFilter_InputPin_Vtbl
=
769 TestFilter_Pin_QueryInterface
,
770 TestFilter_Pin_AddRef
,
771 TestFilter_Pin_Release
,
772 TestFilter_InputPin_Connect
,
773 TestFilter_InputPin_ReceiveConnection
,
774 TestFilter_Pin_Disconnect
,
775 TestFilter_Pin_ConnectedTo
,
776 TestFilter_Pin_ConnectionMediaType
,
777 TestFilter_Pin_QueryPinInfo
,
778 TestFilter_Pin_QueryDirection
,
779 TestFilter_Pin_QueryId
,
780 TestFilter_Pin_QueryAccept
,
781 TestFilter_Pin_EnumMediaTypes
,
782 TestFilter_Pin_QueryInternalConnections
,
783 TestFilter_Pin_EndOfStream
,
784 TestFilter_Pin_BeginFlush
,
785 TestFilter_Pin_EndFlush
,
786 TestFilter_Pin_NewSegment
789 static HRESULT WINAPI
TestFilter_OutputPin_ReceiveConnection(IPin
* iface
, IPin
* pReceivePin
, const AM_MEDIA_TYPE
* pmt
)
794 /* Private helper function */
795 static HRESULT
TestFilter_OutputPin_ConnectSpecific(ITestPinImpl
* This
, IPin
* pReceivePin
,
796 const AM_MEDIA_TYPE
* pmt
)
800 This
->pConnectedTo
= pReceivePin
;
801 IPin_AddRef(pReceivePin
);
803 hr
= IPin_ReceiveConnection(pReceivePin
, &This
->IPin_iface
, pmt
);
807 IPin_Release(This
->pConnectedTo
);
808 This
->pConnectedTo
= NULL
;
814 static HRESULT WINAPI
TestFilter_OutputPin_Connect(IPin
* iface
, IPin
* pReceivePin
, const AM_MEDIA_TYPE
* pmt
)
816 ITestPinImpl
*This
= impl_from_IPin(iface
);
819 EnterCriticalSection(This
->pCritSec
);
821 /* if we have been a specific type to connect with, then we can either connect
822 * with that or fail. We cannot choose different AM_MEDIA_TYPE */
823 if (pmt
&& !IsEqualGUID(&pmt
->majortype
, &GUID_NULL
) && !IsEqualGUID(&pmt
->subtype
, &GUID_NULL
))
824 hr
= TestFilter_OutputPin_ConnectSpecific(This
, pReceivePin
, pmt
);
827 if (( !pmt
|| CompareMediaTypes(pmt
, &This
->mtCurrent
, TRUE
) ) &&
828 (TestFilter_OutputPin_ConnectSpecific(This
, pReceivePin
, &This
->mtCurrent
) == S_OK
))
830 else hr
= VFW_E_NO_ACCEPTABLE_TYPES
;
831 } /* if negotiate media type */
833 LeaveCriticalSection(This
->pCritSec
);
838 static const IPinVtbl TestFilter_OutputPin_Vtbl
=
840 TestFilter_Pin_QueryInterface
,
841 TestFilter_Pin_AddRef
,
842 TestFilter_Pin_Release
,
843 TestFilter_OutputPin_Connect
,
844 TestFilter_OutputPin_ReceiveConnection
,
845 TestFilter_Pin_Disconnect
,
846 TestFilter_Pin_ConnectedTo
,
847 TestFilter_Pin_ConnectionMediaType
,
848 TestFilter_Pin_QueryPinInfo
,
849 TestFilter_Pin_QueryDirection
,
850 TestFilter_Pin_QueryId
,
851 TestFilter_Pin_QueryAccept
,
852 TestFilter_Pin_EnumMediaTypes
,
853 TestFilter_Pin_QueryInternalConnections
,
854 TestFilter_Pin_EndOfStream
,
855 TestFilter_Pin_BeginFlush
,
856 TestFilter_Pin_EndFlush
,
857 TestFilter_Pin_NewSegment
860 static HRESULT
TestFilter_Pin_Construct(const IPinVtbl
*Pin_Vtbl
, const PIN_INFO
* pPinInfo
, AM_MEDIA_TYPE
*pinmt
,
861 LPCRITICAL_SECTION pCritSec
, IPin
** ppPin
)
863 ITestPinImpl
* pPinImpl
;
867 pPinImpl
= CoTaskMemAlloc(sizeof(ITestPinImpl
));
870 return E_OUTOFMEMORY
;
872 pPinImpl
->refCount
= 1;
873 pPinImpl
->pConnectedTo
= NULL
;
874 pPinImpl
->pCritSec
= pCritSec
;
875 Copy_PinInfo(&pPinImpl
->pinInfo
, pPinInfo
);
876 pPinImpl
->mtCurrent
= *pinmt
;
878 pPinImpl
->IPin_iface
.lpVtbl
= Pin_Vtbl
;
880 *ppPin
= &pPinImpl
->IPin_iface
;
884 /* IEnumPins implementation */
886 typedef HRESULT (* FNOBTAINPIN
)(TestFilterImpl
*tf
, ULONG pos
, IPin
**pin
, DWORD
*lastsynctick
);
888 typedef struct IEnumPinsImpl
890 IEnumPins IEnumPins_iface
;
893 TestFilterImpl
*base
;
894 FNOBTAINPIN receive_pin
;
898 static const struct IEnumPinsVtbl IEnumPinsImpl_Vtbl
;
900 static inline IEnumPinsImpl
*impl_from_IEnumPins(IEnumPins
*iface
)
902 return CONTAINING_RECORD(iface
, IEnumPinsImpl
, IEnumPins_iface
);
905 static HRESULT
createenumpins(IEnumPins
** ppEnum
, FNOBTAINPIN receive_pin
, TestFilterImpl
*base
)
907 IEnumPinsImpl
* pEnumPins
;
912 pEnumPins
= CoTaskMemAlloc(sizeof(IEnumPinsImpl
));
916 return E_OUTOFMEMORY
;
918 pEnumPins
->IEnumPins_iface
.lpVtbl
= &IEnumPinsImpl_Vtbl
;
919 pEnumPins
->refCount
= 1;
920 pEnumPins
->uIndex
= 0;
921 pEnumPins
->receive_pin
= receive_pin
;
922 pEnumPins
->base
= base
;
923 IBaseFilter_AddRef(&base
->IBaseFilter_iface
);
924 *ppEnum
= &pEnumPins
->IEnumPins_iface
;
926 receive_pin(base
, ~0, NULL
, &pEnumPins
->synctime
);
931 static HRESULT WINAPI
IEnumPinsImpl_QueryInterface(IEnumPins
* iface
, REFIID riid
, LPVOID
* ppv
)
935 if (IsEqualIID(riid
, &IID_IUnknown
))
937 else if (IsEqualIID(riid
, &IID_IEnumPins
))
942 IUnknown_AddRef((IUnknown
*)(*ppv
));
946 return E_NOINTERFACE
;
949 static ULONG WINAPI
IEnumPinsImpl_AddRef(IEnumPins
* iface
)
951 IEnumPinsImpl
*This
= impl_from_IEnumPins(iface
);
952 ULONG refCount
= InterlockedIncrement(&This
->refCount
);
957 static ULONG WINAPI
IEnumPinsImpl_Release(IEnumPins
* iface
)
959 IEnumPinsImpl
*This
= impl_from_IEnumPins(iface
);
960 ULONG refCount
= InterlockedDecrement(&This
->refCount
);
964 IBaseFilter_Release(&This
->base
->IBaseFilter_iface
);
972 static HRESULT WINAPI
IEnumPinsImpl_Next(IEnumPins
* iface
, ULONG cPins
, IPin
** ppPins
, ULONG
* pcFetched
)
974 IEnumPinsImpl
*This
= impl_from_IEnumPins(iface
);
975 DWORD synctime
= This
->synctime
;
982 if (cPins
> 1 && !pcFetched
)
988 while (i
< cPins
&& hr
== S_OK
)
990 hr
= This
->receive_pin(This
->base
, This
->uIndex
+ i
, &ppPins
[i
], &synctime
);
995 if (synctime
!= This
->synctime
)
999 if (!i
&& synctime
!= This
->synctime
)
1000 return VFW_E_ENUM_OUT_OF_SYNC
;
1011 static HRESULT WINAPI
IEnumPinsImpl_Skip(IEnumPins
* iface
, ULONG cPins
)
1013 IEnumPinsImpl
*This
= impl_from_IEnumPins(iface
);
1014 DWORD synctime
= This
->synctime
;
1018 hr
= This
->receive_pin(This
->base
, This
->uIndex
+ cPins
, &pin
, &synctime
);
1022 if (synctime
!= This
->synctime
)
1023 return VFW_E_ENUM_OUT_OF_SYNC
;
1026 This
->uIndex
+= cPins
;
1031 static HRESULT WINAPI
IEnumPinsImpl_Reset(IEnumPins
* iface
)
1033 IEnumPinsImpl
*This
= impl_from_IEnumPins(iface
);
1035 This
->receive_pin(This
->base
, ~0, NULL
, &This
->synctime
);
1041 static HRESULT WINAPI
IEnumPinsImpl_Clone(IEnumPins
* iface
, IEnumPins
** ppEnum
)
1044 IEnumPinsImpl
*This
= impl_from_IEnumPins(iface
);
1046 hr
= createenumpins(ppEnum
, This
->receive_pin
, This
->base
);
1049 return IEnumPins_Skip(*ppEnum
, This
->uIndex
);
1052 static const IEnumPinsVtbl IEnumPinsImpl_Vtbl
=
1054 IEnumPinsImpl_QueryInterface
,
1055 IEnumPinsImpl_AddRef
,
1056 IEnumPinsImpl_Release
,
1059 IEnumPinsImpl_Reset
,
1063 /* Test filter implementation - a filter that has few predefined pins with single media type
1064 * that accept only this single media type. Enough for Render(). */
1066 typedef struct TestFilterPinData
1068 PIN_DIRECTION pinDir
;
1069 const GUID
*mediasubtype
;
1070 } TestFilterPinData
;
1072 static const IBaseFilterVtbl TestFilter_Vtbl
;
1074 static inline TestFilterImpl
*impl_from_IBaseFilter(IBaseFilter
*iface
)
1076 return CONTAINING_RECORD(iface
, TestFilterImpl
, IBaseFilter_iface
);
1079 static HRESULT
createtestfilter(const CLSID
* pClsid
, const TestFilterPinData
*pinData
,
1080 TestFilterImpl
**tf
)
1082 static const WCHAR wcsInputPinName
[] = {'i','n','p','u','t',' ','p','i','n',0};
1083 static const WCHAR wcsOutputPinName
[] = {'o','u','t','p','u','t',' ','p','i','n',0};
1086 TestFilterImpl
* pTestFilter
= NULL
;
1090 pTestFilter
= CoTaskMemAlloc(sizeof(TestFilterImpl
));
1091 if (!pTestFilter
) return E_OUTOFMEMORY
;
1093 pTestFilter
->clsid
= *pClsid
;
1094 pTestFilter
->IBaseFilter_iface
.lpVtbl
= &TestFilter_Vtbl
;
1095 pTestFilter
->refCount
= 1;
1096 InitializeCriticalSection(&pTestFilter
->csFilter
);
1097 pTestFilter
->state
= State_Stopped
;
1099 ZeroMemory(&pTestFilter
->filterInfo
, sizeof(FILTER_INFO
));
1102 while(pinData
[nPins
].mediasubtype
) ++nPins
;
1104 pTestFilter
->ppPins
= CoTaskMemAlloc(nPins
* sizeof(IPin
*));
1105 if (!pTestFilter
->ppPins
)
1110 ZeroMemory(pTestFilter
->ppPins
, nPins
* sizeof(IPin
*));
1112 for (i
= 0; i
< nPins
; i
++)
1114 ZeroMemory(&mt
, sizeof(mt
));
1115 mt
.majortype
= MEDIATYPE_Video
;
1116 mt
.formattype
= FORMAT_None
;
1117 mt
.subtype
= *pinData
[i
].mediasubtype
;
1119 pinInfo
.dir
= pinData
[i
].pinDir
;
1120 pinInfo
.pFilter
= &pTestFilter
->IBaseFilter_iface
;
1121 if (pinInfo
.dir
== PINDIR_INPUT
)
1123 lstrcpynW(pinInfo
.achName
, wcsInputPinName
, sizeof(pinInfo
.achName
) / sizeof(pinInfo
.achName
[0]));
1124 hr
= TestFilter_Pin_Construct(&TestFilter_InputPin_Vtbl
, &pinInfo
, &mt
, &pTestFilter
->csFilter
,
1125 &pTestFilter
->ppPins
[i
]);
1130 lstrcpynW(pinInfo
.achName
, wcsOutputPinName
, sizeof(pinInfo
.achName
) / sizeof(pinInfo
.achName
[0]));
1131 hr
= TestFilter_Pin_Construct(&TestFilter_OutputPin_Vtbl
, &pinInfo
, &mt
, &pTestFilter
->csFilter
,
1132 &pTestFilter
->ppPins
[i
]);
1134 if (FAILED(hr
) || !pTestFilter
->ppPins
[i
]) goto error
;
1137 pTestFilter
->nPins
= nPins
;
1143 if (pTestFilter
->ppPins
)
1145 for (i
= 0; i
< nPins
; i
++)
1147 if (pTestFilter
->ppPins
[i
]) IPin_Release(pTestFilter
->ppPins
[i
]);
1150 CoTaskMemFree(pTestFilter
->ppPins
);
1151 DeleteCriticalSection(&pTestFilter
->csFilter
);
1152 CoTaskMemFree(pTestFilter
);
1157 static HRESULT WINAPI
TestFilter_QueryInterface(IBaseFilter
* iface
, REFIID riid
, LPVOID
* ppv
)
1159 TestFilterImpl
*This
= impl_from_IBaseFilter(iface
);
1163 if (IsEqualIID(riid
, &IID_IUnknown
))
1165 else if (IsEqualIID(riid
, &IID_IPersist
))
1167 else if (IsEqualIID(riid
, &IID_IMediaFilter
))
1169 else if (IsEqualIID(riid
, &IID_IBaseFilter
))
1174 IUnknown_AddRef((IUnknown
*)(*ppv
));
1178 return E_NOINTERFACE
;
1181 static ULONG WINAPI
TestFilter_AddRef(IBaseFilter
* iface
)
1183 TestFilterImpl
*This
= impl_from_IBaseFilter(iface
);
1184 ULONG refCount
= InterlockedIncrement(&This
->refCount
);
1189 static ULONG WINAPI
TestFilter_Release(IBaseFilter
* iface
)
1191 TestFilterImpl
*This
= impl_from_IBaseFilter(iface
);
1192 ULONG refCount
= InterlockedDecrement(&This
->refCount
);
1198 for (i
= 0; i
< This
->nPins
; i
++)
1202 if (SUCCEEDED(IPin_ConnectedTo(This
->ppPins
[i
], &pConnectedTo
)))
1204 IPin_Disconnect(pConnectedTo
);
1205 IPin_Release(pConnectedTo
);
1207 IPin_Disconnect(This
->ppPins
[i
]);
1209 IPin_Release(This
->ppPins
[i
]);
1212 CoTaskMemFree(This
->ppPins
);
1214 DeleteCriticalSection(&This
->csFilter
);
1216 CoTaskMemFree(This
);
1223 /** IPersist methods **/
1225 static HRESULT WINAPI
TestFilter_GetClassID(IBaseFilter
* iface
, CLSID
* pClsid
)
1227 TestFilterImpl
*This
= impl_from_IBaseFilter(iface
);
1229 *pClsid
= This
->clsid
;
1234 /** IMediaFilter methods **/
1236 static HRESULT WINAPI
TestFilter_Stop(IBaseFilter
* iface
)
1241 static HRESULT WINAPI
TestFilter_Pause(IBaseFilter
* iface
)
1246 static HRESULT WINAPI
TestFilter_Run(IBaseFilter
* iface
, REFERENCE_TIME tStart
)
1251 static HRESULT WINAPI
TestFilter_GetState(IBaseFilter
* iface
, DWORD dwMilliSecsTimeout
, FILTER_STATE
*pState
)
1253 TestFilterImpl
*This
= impl_from_IBaseFilter(iface
);
1255 EnterCriticalSection(&This
->csFilter
);
1257 *pState
= This
->state
;
1259 LeaveCriticalSection(&This
->csFilter
);
1264 static HRESULT WINAPI
TestFilter_SetSyncSource(IBaseFilter
* iface
, IReferenceClock
*pClock
)
1269 static HRESULT WINAPI
TestFilter_GetSyncSource(IBaseFilter
* iface
, IReferenceClock
**ppClock
)
1274 /** IBaseFilter implementation **/
1276 static HRESULT
getpin_callback(TestFilterImpl
*tf
, ULONG pos
, IPin
**pin
, DWORD
*lastsynctick
)
1278 /* Our pins are static, not changing so setting static tick count is ok */
1281 if (pos
>= tf
->nPins
)
1284 *pin
= tf
->ppPins
[pos
];
1289 static HRESULT WINAPI
TestFilter_EnumPins(IBaseFilter
* iface
, IEnumPins
**ppEnum
)
1291 TestFilterImpl
*This
= impl_from_IBaseFilter(iface
);
1293 return createenumpins(ppEnum
, getpin_callback
, This
);
1296 static HRESULT WINAPI
TestFilter_FindPin(IBaseFilter
* iface
, LPCWSTR Id
, IPin
**ppPin
)
1301 static HRESULT WINAPI
TestFilter_QueryFilterInfo(IBaseFilter
* iface
, FILTER_INFO
*pInfo
)
1303 TestFilterImpl
*This
= impl_from_IBaseFilter(iface
);
1305 lstrcpyW(pInfo
->achName
, This
->filterInfo
.achName
);
1306 pInfo
->pGraph
= This
->filterInfo
.pGraph
;
1309 IFilterGraph_AddRef(pInfo
->pGraph
);
1314 static HRESULT WINAPI
TestFilter_JoinFilterGraph(IBaseFilter
* iface
, IFilterGraph
*pGraph
, LPCWSTR pName
)
1317 TestFilterImpl
*This
= impl_from_IBaseFilter(iface
);
1319 EnterCriticalSection(&This
->csFilter
);
1322 lstrcpyW(This
->filterInfo
.achName
, pName
);
1324 *This
->filterInfo
.achName
= '\0';
1325 This
->filterInfo
.pGraph
= pGraph
; /* NOTE: do NOT increase ref. count */
1327 LeaveCriticalSection(&This
->csFilter
);
1332 static HRESULT WINAPI
TestFilter_QueryVendorInfo(IBaseFilter
* iface
, LPWSTR
*pVendorInfo
)
1337 static const IBaseFilterVtbl TestFilter_Vtbl
=
1339 TestFilter_QueryInterface
,
1342 TestFilter_GetClassID
,
1346 TestFilter_GetState
,
1347 TestFilter_SetSyncSource
,
1348 TestFilter_GetSyncSource
,
1349 TestFilter_EnumPins
,
1351 TestFilter_QueryFilterInfo
,
1352 TestFilter_JoinFilterGraph
,
1353 TestFilter_QueryVendorInfo
1356 /* IClassFactory implementation */
1358 typedef struct TestClassFactoryImpl
1360 IClassFactory IClassFactory_iface
;
1361 const TestFilterPinData
*filterPinData
;
1363 } TestClassFactoryImpl
;
1365 static inline TestClassFactoryImpl
*impl_from_IClassFactory(IClassFactory
*iface
)
1367 return CONTAINING_RECORD(iface
, TestClassFactoryImpl
, IClassFactory_iface
);
1370 static HRESULT WINAPI
Test_IClassFactory_QueryInterface(
1371 LPCLASSFACTORY iface
,
1375 if (ppvObj
== NULL
) return E_POINTER
;
1377 if (IsEqualGUID(riid
, &IID_IUnknown
) ||
1378 IsEqualGUID(riid
, &IID_IClassFactory
))
1381 IClassFactory_AddRef(iface
);
1386 return E_NOINTERFACE
;
1389 static ULONG WINAPI
Test_IClassFactory_AddRef(LPCLASSFACTORY iface
)
1391 return 2; /* non-heap-based object */
1394 static ULONG WINAPI
Test_IClassFactory_Release(LPCLASSFACTORY iface
)
1396 return 1; /* non-heap-based object */
1399 static HRESULT WINAPI
Test_IClassFactory_CreateInstance(
1400 LPCLASSFACTORY iface
,
1401 LPUNKNOWN pUnkOuter
,
1405 TestClassFactoryImpl
*This
= impl_from_IClassFactory(iface
);
1407 TestFilterImpl
*testfilter
;
1411 if (pUnkOuter
) return CLASS_E_NOAGGREGATION
;
1413 hr
= createtestfilter(This
->clsid
, This
->filterPinData
, &testfilter
);
1414 if (SUCCEEDED(hr
)) {
1415 hr
= IBaseFilter_QueryInterface(&testfilter
->IBaseFilter_iface
, riid
, ppvObj
);
1416 IBaseFilter_Release(&testfilter
->IBaseFilter_iface
);
1421 static HRESULT WINAPI
Test_IClassFactory_LockServer(
1422 LPCLASSFACTORY iface
,
1428 static IClassFactoryVtbl TestClassFactory_Vtbl
=
1430 Test_IClassFactory_QueryInterface
,
1431 Test_IClassFactory_AddRef
,
1432 Test_IClassFactory_Release
,
1433 Test_IClassFactory_CreateInstance
,
1434 Test_IClassFactory_LockServer
1437 static HRESULT
get_connected_filter_name(TestFilterImpl
*pFilter
, char *FilterName
)
1441 FILTER_INFO filterInfo
;
1446 hr
= IPin_ConnectedTo(pFilter
->ppPins
[0], &pin
);
1447 ok(hr
== S_OK
, "IPin_ConnectedTo failed with %x\n", hr
);
1448 if (FAILED(hr
)) return hr
;
1450 hr
= IPin_QueryPinInfo(pin
, &pinInfo
);
1451 ok(hr
== S_OK
, "IPin_QueryPinInfo failed with %x\n", hr
);
1453 if (FAILED(hr
)) return hr
;
1455 SetLastError(0xdeadbeef);
1456 hr
= IBaseFilter_QueryFilterInfo(pinInfo
.pFilter
, &filterInfo
);
1457 if (hr
== S_OK
&& GetLastError() == ERROR_CALL_NOT_IMPLEMENTED
)
1459 IBaseFilter_Release(pinInfo
.pFilter
);
1462 ok(hr
== S_OK
, "IBaseFilter_QueryFilterInfo failed with %x\n", hr
);
1463 IBaseFilter_Release(pinInfo
.pFilter
);
1464 if (FAILED(hr
)) return hr
;
1466 IFilterGraph_Release(filterInfo
.pGraph
);
1468 WideCharToMultiByte(CP_ACP
, 0, filterInfo
.achName
, -1, FilterName
, MAX_FILTER_NAME
, NULL
, NULL
);
1473 static void test_render_filter_priority(void)
1475 /* Tests filter choice priorities in Render(). */
1476 DWORD cookie1
= 0, cookie2
= 0, cookie3
= 0;
1478 IFilterGraph2
* pgraph2
= NULL
;
1479 IFilterMapper2
*pMapper2
= NULL
;
1480 TestFilterImpl
*ptestfilter
= NULL
;
1481 TestFilterImpl
*ptestfilter2
= NULL
;
1482 static const CLSID CLSID_TestFilter2
= {
1486 {0xe8, 0x9b, 0x00, 0x19, 0x66, 0x2f, 0xf0, 0xce}
1488 static const CLSID CLSID_TestFilter3
= {
1492 {0xe8, 0x9b, 0x00, 0x19, 0x66, 0x2f, 0xf0, 0xce}
1494 static const CLSID CLSID_TestFilter4
= {
1498 {0xe8, 0x9b, 0x00, 0x19, 0x66, 0x2f, 0xf0, 0xce}
1500 static const GUID mediasubtype1
= {
1504 {0xe8, 0x9b, 0x00, 0x19, 0x66, 0x2f, 0xf0, 0xce}
1506 static const GUID mediasubtype2
= {
1510 {0xe8, 0x9b, 0x00, 0x19, 0x66, 0x2f, 0xf0, 0xce}
1512 static const TestFilterPinData PinData1
[] = {
1513 { PINDIR_OUTPUT
, &mediasubtype1
},
1516 static const TestFilterPinData PinData2
[] = {
1517 { PINDIR_INPUT
, &mediasubtype1
},
1520 static const TestFilterPinData PinData3
[] = {
1521 { PINDIR_INPUT
, &GUID_NULL
},
1524 static const TestFilterPinData PinData4
[] = {
1525 { PINDIR_INPUT
, &mediasubtype1
},
1526 { PINDIR_OUTPUT
, &mediasubtype2
},
1529 static const TestFilterPinData PinData5
[] = {
1530 { PINDIR_INPUT
, &mediasubtype2
},
1533 TestClassFactoryImpl Filter1ClassFactory
= {
1534 { &TestClassFactory_Vtbl
},
1535 PinData2
, &CLSID_TestFilter2
1537 TestClassFactoryImpl Filter2ClassFactory
= {
1538 { &TestClassFactory_Vtbl
},
1539 PinData4
, &CLSID_TestFilter3
1541 TestClassFactoryImpl Filter3ClassFactory
= {
1542 { &TestClassFactory_Vtbl
},
1543 PinData5
, &CLSID_TestFilter4
1545 char ConnectedFilterName1
[MAX_FILTER_NAME
];
1546 char ConnectedFilterName2
[MAX_FILTER_NAME
];
1548 REGFILTERPINS2 rgPins2
[2];
1549 REGPINTYPES rgPinType
[2];
1550 static const WCHAR wszFilterInstanceName1
[] = {'T', 'e', 's', 't', 'f', 'i', 'l', 't', 'e', 'r', 'I',
1551 'n', 's', 't', 'a', 'n', 'c', 'e', '1', 0 };
1552 static const WCHAR wszFilterInstanceName2
[] = {'T', 'e', 's', 't', 'f', 'i', 'l', 't', 'e', 'r', 'I',
1553 'n', 's', 't', 'a', 'n', 'c', 'e', '2', 0 };
1554 static const WCHAR wszFilterInstanceName3
[] = {'T', 'e', 's', 't', 'f', 'i', 'l', 't', 'e', 'r', 'I',
1555 'n', 's', 't', 'a', 'n', 'c', 'e', '3', 0 };
1556 static const WCHAR wszFilterInstanceName4
[] = {'T', 'e', 's', 't', 'f', 'i', 'l', 't', 'e', 'r', 'I',
1557 'n', 's', 't', 'a', 'n', 'c', 'e', '4', 0 };
1559 /* Test which renderer of two already added to the graph will be chosen
1560 * (one is "exact" match, other is "wildcard" match. Seems to depend
1561 * on the order in which filters are added to the graph, thus indicating
1562 * no preference given to exact match. */
1563 hr
= CoCreateInstance(&CLSID_FilterGraph
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IFilterGraph2
, (LPVOID
*)&pgraph2
);
1564 ok(hr
== S_OK
, "CoCreateInstance failed with %08x\n", hr
);
1565 if (!pgraph2
) return;
1567 hr
= createtestfilter(&GUID_NULL
, PinData1
, &ptestfilter
);
1568 ok(hr
== S_OK
, "createtestfilter failed with %08x\n", hr
);
1569 if (FAILED(hr
)) goto out
;
1571 hr
= IFilterGraph2_AddFilter(pgraph2
, &ptestfilter
->IBaseFilter_iface
, wszFilterInstanceName1
);
1572 ok(hr
== S_OK
, "IFilterGraph2_AddFilter failed with %08x\n", hr
);
1574 hr
= createtestfilter(&GUID_NULL
, PinData2
, &ptestfilter2
);
1575 ok(hr
== S_OK
, "createtestfilter failed with %08x\n", hr
);
1576 if (FAILED(hr
)) goto out
;
1578 hr
= IFilterGraph2_AddFilter(pgraph2
, &ptestfilter2
->IBaseFilter_iface
, wszFilterInstanceName2
);
1579 ok(hr
== S_OK
, "IFilterGraph2_AddFilter failed with %08x\n", hr
);
1581 IBaseFilter_Release(&ptestfilter2
->IBaseFilter_iface
);
1582 ptestfilter2
= NULL
;
1584 hr
= createtestfilter(&GUID_NULL
, PinData3
, &ptestfilter2
);
1585 ok(hr
== S_OK
, "createtestfilter failed with %08x\n", hr
);
1586 if (FAILED(hr
)) goto out
;
1588 hr
= IFilterGraph2_AddFilter(pgraph2
, &ptestfilter2
->IBaseFilter_iface
, wszFilterInstanceName3
);
1589 ok(hr
== S_OK
, "IFilterGraph2_AddFilter failed with %08x\n", hr
);
1591 hr
= IFilterGraph2_Render(pgraph2
, ptestfilter
->ppPins
[0]);
1592 ok(hr
== S_OK
, "IFilterGraph2_Render failed with %08x\n", hr
);
1594 hr
= get_connected_filter_name(ptestfilter
, ConnectedFilterName1
);
1596 IFilterGraph2_Release(pgraph2
);
1598 IBaseFilter_Release(&ptestfilter
->IBaseFilter_iface
);
1600 IBaseFilter_Release(&ptestfilter2
->IBaseFilter_iface
);
1601 ptestfilter2
= NULL
;
1603 if (hr
== E_NOTIMPL
)
1605 win_skip("Needed functions are not implemented\n");
1609 hr
= CoCreateInstance(&CLSID_FilterGraph
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IFilterGraph2
, (LPVOID
*)&pgraph2
);
1610 ok(hr
== S_OK
, "CoCreateInstance failed with %08x\n", hr
);
1611 if (!pgraph2
) goto out
;
1613 hr
= createtestfilter(&GUID_NULL
, PinData1
, &ptestfilter
);
1614 ok(hr
== S_OK
, "createtestfilter failed with %08x\n", hr
);
1615 if (FAILED(hr
)) goto out
;
1617 hr
= IFilterGraph2_AddFilter(pgraph2
, &ptestfilter
->IBaseFilter_iface
, wszFilterInstanceName1
);
1618 ok(hr
== S_OK
, "IFilterGraph2_AddFilter failed with %08x\n", hr
);
1620 hr
= createtestfilter(&GUID_NULL
, PinData3
, &ptestfilter2
);
1621 ok(hr
== S_OK
, "createtestfilter failed with %08x\n", hr
);
1622 if (FAILED(hr
)) goto out
;
1624 hr
= IFilterGraph2_AddFilter(pgraph2
, &ptestfilter2
->IBaseFilter_iface
, wszFilterInstanceName3
);
1625 ok(hr
== S_OK
, "IFilterGraph2_AddFilter failed with %08x\n", hr
);
1627 IBaseFilter_Release(&ptestfilter2
->IBaseFilter_iface
);
1628 ptestfilter2
= NULL
;
1630 hr
= createtestfilter(&GUID_NULL
, PinData2
, &ptestfilter2
);
1631 ok(hr
== S_OK
, "createtestfilter failed with %08x\n", hr
);
1632 if (FAILED(hr
)) goto out
;
1634 hr
= IFilterGraph2_AddFilter(pgraph2
, &ptestfilter2
->IBaseFilter_iface
, wszFilterInstanceName2
);
1635 ok(hr
== S_OK
, "IFilterGraph2_AddFilter failed with %08x\n", hr
);
1637 hr
= IFilterGraph2_Render(pgraph2
, ptestfilter
->ppPins
[0]);
1638 ok(hr
== S_OK
, "IFilterGraph2_Render failed with %08x\n", hr
);
1640 hr
= IFilterGraph2_Disconnect(pgraph2
, NULL
);
1641 ok(hr
== E_POINTER
, "IFilterGraph2_Disconnect failed. Expected E_POINTER, received %08x\n", hr
);
1643 get_connected_filter_name(ptestfilter
, ConnectedFilterName2
);
1644 ok(strcmp(ConnectedFilterName1
, ConnectedFilterName2
),
1645 "expected connected filters to be different but got %s both times\n", ConnectedFilterName1
);
1647 IFilterGraph2_Release(pgraph2
);
1649 IBaseFilter_Release(&ptestfilter
->IBaseFilter_iface
);
1651 IBaseFilter_Release(&ptestfilter2
->IBaseFilter_iface
);
1652 ptestfilter2
= NULL
;
1654 /* Test if any preference is given to existing renderer which renders the pin directly vs
1655 an existing renderer which renders the pin indirectly, through an additional middle filter,
1656 again trying different orders of creation. Native appears not to give a preference. */
1658 hr
= CoCreateInstance(&CLSID_FilterGraph
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IFilterGraph2
, (LPVOID
*)&pgraph2
);
1659 ok(hr
== S_OK
, "CoCreateInstance failed with %08x\n", hr
);
1660 if (!pgraph2
) goto out
;
1662 hr
= createtestfilter(&GUID_NULL
, PinData1
, &ptestfilter
);
1663 ok(hr
== S_OK
, "createtestfilter failed with %08x\n", hr
);
1664 if (FAILED(hr
)) goto out
;
1666 hr
= IFilterGraph2_AddFilter(pgraph2
, &ptestfilter
->IBaseFilter_iface
, wszFilterInstanceName1
);
1667 ok(hr
== S_OK
, "IFilterGraph2_AddFilter failed with %08x\n", hr
);
1669 hr
= createtestfilter(&GUID_NULL
, PinData2
, &ptestfilter2
);
1670 ok(hr
== S_OK
, "createtestfilter failed with %08x\n", hr
);
1671 if (FAILED(hr
)) goto out
;
1673 hr
= IFilterGraph2_AddFilter(pgraph2
, &ptestfilter2
->IBaseFilter_iface
, wszFilterInstanceName2
);
1674 ok(hr
== S_OK
, "IFilterGraph2_AddFilter failed with %08x\n", hr
);
1676 IBaseFilter_Release(&ptestfilter2
->IBaseFilter_iface
);
1677 ptestfilter2
= NULL
;
1679 hr
= createtestfilter(&GUID_NULL
, PinData4
, &ptestfilter2
);
1680 ok(hr
== S_OK
, "createtestfilter failed with %08x\n", hr
);
1681 if (FAILED(hr
)) goto out
;
1683 hr
= IFilterGraph2_AddFilter(pgraph2
, &ptestfilter2
->IBaseFilter_iface
, wszFilterInstanceName3
);
1684 ok(hr
== S_OK
, "IFilterGraph2_AddFilter failed with %08x\n", hr
);
1686 IBaseFilter_Release(&ptestfilter2
->IBaseFilter_iface
);
1687 ptestfilter2
= NULL
;
1689 hr
= createtestfilter(&GUID_NULL
, PinData5
, &ptestfilter2
);
1690 ok(hr
== S_OK
, "createtestfilter failed with %08x\n", hr
);
1691 if (FAILED(hr
)) goto out
;
1693 hr
= IFilterGraph2_AddFilter(pgraph2
, &ptestfilter2
->IBaseFilter_iface
, wszFilterInstanceName4
);
1694 ok(hr
== S_OK
, "IFilterGraph2_AddFilter failed with %08x\n", hr
);
1696 hr
= IFilterGraph2_Render(pgraph2
, ptestfilter
->ppPins
[0]);
1697 ok(hr
== S_OK
, "IFilterGraph2_Render failed with %08x\n", hr
);
1699 get_connected_filter_name(ptestfilter
, ConnectedFilterName1
);
1700 ok(!strcmp(ConnectedFilterName1
, "TestfilterInstance3") || !strcmp(ConnectedFilterName1
, "TestfilterInstance2"),
1701 "unexpected connected filter: %s\n", ConnectedFilterName1
);
1703 IFilterGraph2_Release(pgraph2
);
1705 IBaseFilter_Release(&ptestfilter
->IBaseFilter_iface
);
1707 IBaseFilter_Release(&ptestfilter2
->IBaseFilter_iface
);
1708 ptestfilter2
= NULL
;
1710 hr
= CoCreateInstance(&CLSID_FilterGraph
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IFilterGraph2
, (LPVOID
*)&pgraph2
);
1711 ok(hr
== S_OK
, "CoCreateInstance failed with %08x\n", hr
);
1712 if (!pgraph2
) goto out
;
1714 hr
= createtestfilter(&GUID_NULL
, PinData1
, &ptestfilter
);
1715 ok(hr
== S_OK
, "createtestfilter failed with %08x\n", hr
);
1716 if (FAILED(hr
)) goto out
;
1718 hr
= IFilterGraph2_AddFilter(pgraph2
, &ptestfilter
->IBaseFilter_iface
, wszFilterInstanceName1
);
1719 ok(hr
== S_OK
, "IFilterGraph2_AddFilter failed with %08x\n", hr
);
1721 hr
= createtestfilter(&GUID_NULL
, PinData4
, &ptestfilter2
);
1722 ok(hr
== S_OK
, "createtestfilter failed with %08x\n", hr
);
1723 if (FAILED(hr
)) goto out
;
1725 hr
= IFilterGraph2_AddFilter(pgraph2
, &ptestfilter2
->IBaseFilter_iface
, wszFilterInstanceName3
);
1726 ok(hr
== S_OK
, "IFilterGraph2_AddFilter failed with %08x\n", hr
);
1728 IBaseFilter_Release(&ptestfilter2
->IBaseFilter_iface
);
1729 ptestfilter2
= NULL
;
1731 hr
= createtestfilter(&GUID_NULL
, PinData5
, &ptestfilter2
);
1732 ok(hr
== S_OK
, "createtestfilter failed with %08x\n", hr
);
1733 if (FAILED(hr
)) goto out
;
1735 hr
= IFilterGraph2_AddFilter(pgraph2
, &ptestfilter2
->IBaseFilter_iface
, wszFilterInstanceName4
);
1736 ok(hr
== S_OK
, "IFilterGraph2_AddFilter failed with %08x\n", hr
);
1738 IBaseFilter_Release(&ptestfilter2
->IBaseFilter_iface
);
1739 ptestfilter2
= NULL
;
1741 hr
= createtestfilter(&GUID_NULL
, PinData2
, &ptestfilter2
);
1742 ok(hr
== S_OK
, "createtestfilter failed with %08x\n", hr
);
1743 if (FAILED(hr
)) goto out
;
1745 hr
= IFilterGraph2_AddFilter(pgraph2
, &ptestfilter2
->IBaseFilter_iface
, wszFilterInstanceName2
);
1746 ok(hr
== S_OK
, "IFilterGraph2_AddFilter failed with %08x\n", hr
);
1748 hr
= IFilterGraph2_Render(pgraph2
, ptestfilter
->ppPins
[0]);
1749 ok(hr
== S_OK
, "IFilterGraph2_Render failed with %08x\n", hr
);
1751 get_connected_filter_name(ptestfilter
, ConnectedFilterName2
);
1752 ok(!strcmp(ConnectedFilterName2
, "TestfilterInstance3") || !strcmp(ConnectedFilterName2
, "TestfilterInstance2"),
1753 "unexpected connected filter: %s\n", ConnectedFilterName2
);
1754 ok(strcmp(ConnectedFilterName1
, ConnectedFilterName2
),
1755 "expected connected filters to be different but got %s both times\n", ConnectedFilterName1
);
1757 IFilterGraph2_Release(pgraph2
);
1759 IBaseFilter_Release(&ptestfilter
->IBaseFilter_iface
);
1761 IBaseFilter_Release(&ptestfilter2
->IBaseFilter_iface
);
1762 ptestfilter2
= NULL
;
1764 /* Test if renderers are tried before non-renderers (intermediary filters). */
1765 hr
= CoCreateInstance(&CLSID_FilterGraph
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IFilterGraph2
, (LPVOID
*)&pgraph2
);
1766 ok(hr
== S_OK
, "CoCreateInstance failed with %08x\n", hr
);
1767 if (!pgraph2
) goto out
;
1769 hr
= CoCreateInstance(&CLSID_FilterMapper2
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IFilterMapper2
, (LPVOID
*)&pMapper2
);
1770 ok(hr
== S_OK
, "CoCreateInstance failed with %08x\n", hr
);
1771 if (!pMapper2
) goto out
;
1773 hr
= createtestfilter(&GUID_NULL
, PinData1
, &ptestfilter
);
1774 ok(hr
== S_OK
, "createtestfilter failed with %08x\n", hr
);
1775 if (FAILED(hr
)) goto out
;
1777 hr
= IFilterGraph2_AddFilter(pgraph2
, &ptestfilter
->IBaseFilter_iface
, wszFilterInstanceName1
);
1778 ok(hr
== S_OK
, "IFilterGraph2_AddFilter failed with %08x\n", hr
);
1780 /* Register our filters with COM and with Filtermapper. */
1781 hr
= CoRegisterClassObject(Filter1ClassFactory
.clsid
,
1782 (IUnknown
*)&Filter1ClassFactory
.IClassFactory_iface
, CLSCTX_INPROC_SERVER
,
1783 REGCLS_MULTIPLEUSE
, &cookie1
);
1784 ok(hr
== S_OK
, "CoRegisterClassObject failed with %08x\n", hr
);
1785 if (FAILED(hr
)) goto out
;
1786 hr
= CoRegisterClassObject(Filter2ClassFactory
.clsid
,
1787 (IUnknown
*)&Filter2ClassFactory
.IClassFactory_iface
, CLSCTX_INPROC_SERVER
,
1788 REGCLS_MULTIPLEUSE
, &cookie2
);
1789 ok(hr
== S_OK
, "CoRegisterClassObject failed with %08x\n", hr
);
1790 if (FAILED(hr
)) goto out
;
1791 hr
= CoRegisterClassObject(Filter3ClassFactory
.clsid
,
1792 (IUnknown
*)&Filter3ClassFactory
.IClassFactory_iface
, CLSCTX_INPROC_SERVER
,
1793 REGCLS_MULTIPLEUSE
, &cookie3
);
1794 ok(hr
== S_OK
, "CoRegisterClassObject failed with %08x\n", hr
);
1795 if (FAILED(hr
)) goto out
;
1798 rgf2
.dwMerit
= MERIT_UNLIKELY
;
1799 S2(U(rgf2
)).cPins2
= 1;
1800 S2(U(rgf2
)).rgPins2
= rgPins2
;
1801 rgPins2
[0].dwFlags
= REG_PINFLAG_B_RENDERER
;
1802 rgPins2
[0].cInstances
= 1;
1803 rgPins2
[0].nMediaTypes
= 1;
1804 rgPins2
[0].lpMediaType
= &rgPinType
[0];
1805 rgPins2
[0].nMediums
= 0;
1806 rgPins2
[0].lpMedium
= NULL
;
1807 rgPins2
[0].clsPinCategory
= NULL
;
1808 rgPinType
[0].clsMajorType
= &MEDIATYPE_Video
;
1809 rgPinType
[0].clsMinorType
= &mediasubtype1
;
1811 hr
= IFilterMapper2_RegisterFilter(pMapper2
, &CLSID_TestFilter2
, wszFilterInstanceName2
, NULL
,
1812 &CLSID_LegacyAmFilterCategory
, NULL
, &rgf2
);
1813 if (hr
== E_ACCESSDENIED
)
1814 skip("Not authorized to register filters\n");
1817 ok(hr
== S_OK
, "IFilterMapper2_RegisterFilter failed with %x\n", hr
);
1819 rgf2
.dwMerit
= MERIT_PREFERRED
;
1820 rgPinType
[0].clsMinorType
= &mediasubtype2
;
1822 hr
= IFilterMapper2_RegisterFilter(pMapper2
, &CLSID_TestFilter4
, wszFilterInstanceName4
, NULL
,
1823 &CLSID_LegacyAmFilterCategory
, NULL
, &rgf2
);
1824 ok(hr
== S_OK
, "IFilterMapper2_RegisterFilter failed with %x\n", hr
);
1826 S2(U(rgf2
)).cPins2
= 2;
1827 rgPins2
[0].dwFlags
= 0;
1828 rgPinType
[0].clsMinorType
= &mediasubtype1
;
1830 rgPins2
[1].dwFlags
= REG_PINFLAG_B_OUTPUT
;
1831 rgPins2
[1].cInstances
= 1;
1832 rgPins2
[1].nMediaTypes
= 1;
1833 rgPins2
[1].lpMediaType
= &rgPinType
[1];
1834 rgPins2
[1].nMediums
= 0;
1835 rgPins2
[1].lpMedium
= NULL
;
1836 rgPins2
[1].clsPinCategory
= NULL
;
1837 rgPinType
[1].clsMajorType
= &MEDIATYPE_Video
;
1838 rgPinType
[1].clsMinorType
= &mediasubtype2
;
1840 hr
= IFilterMapper2_RegisterFilter(pMapper2
, &CLSID_TestFilter3
, wszFilterInstanceName3
, NULL
,
1841 &CLSID_LegacyAmFilterCategory
, NULL
, &rgf2
);
1842 ok(hr
== S_OK
, "IFilterMapper2_RegisterFilter failed with %x\n", hr
);
1844 hr
= IFilterGraph2_Render(pgraph2
, ptestfilter
->ppPins
[0]);
1845 ok(hr
== S_OK
, "IFilterGraph2_Render failed with %08x\n", hr
);
1847 get_connected_filter_name(ptestfilter
, ConnectedFilterName1
);
1848 ok(!strcmp(ConnectedFilterName1
, "TestfilterInstance3"),
1849 "unexpected connected filter: %s\n", ConnectedFilterName1
);
1852 hr
= IFilterMapper2_UnregisterFilter(pMapper2
, &CLSID_LegacyAmFilterCategory
, NULL
,
1853 &CLSID_TestFilter2
);
1854 ok(SUCCEEDED(hr
), "IFilterMapper2_UnregisterFilter failed with %x\n", hr
);
1855 hr
= IFilterMapper2_UnregisterFilter(pMapper2
, &CLSID_LegacyAmFilterCategory
, NULL
,
1856 &CLSID_TestFilter3
);
1857 ok(SUCCEEDED(hr
), "IFilterMapper2_UnregisterFilter failed with %x\n", hr
);
1858 hr
= IFilterMapper2_UnregisterFilter(pMapper2
, &CLSID_LegacyAmFilterCategory
, NULL
,
1859 &CLSID_TestFilter4
);
1860 ok(SUCCEEDED(hr
), "IFilterMapper2_UnregisterFilter failed with %x\n", hr
);
1864 if (ptestfilter
) IBaseFilter_Release(&ptestfilter
->IBaseFilter_iface
);
1865 if (ptestfilter2
) IBaseFilter_Release(&ptestfilter2
->IBaseFilter_iface
);
1866 if (pgraph2
) IFilterGraph2_Release(pgraph2
);
1867 if (pMapper2
) IFilterMapper2_Release(pMapper2
);
1869 hr
= CoRevokeClassObject(cookie1
);
1870 ok(hr
== S_OK
, "CoRevokeClassObject failed with %08x\n", hr
);
1871 hr
= CoRevokeClassObject(cookie2
);
1872 ok(hr
== S_OK
, "CoRevokeClassObject failed with %08x\n", hr
);
1873 hr
= CoRevokeClassObject(cookie3
);
1874 ok(hr
== S_OK
, "CoRevokeClassObject failed with %08x\n", hr
);
1877 START_TEST(filtergraph
)
1881 if (!winetest_interactive
)
1883 skip("Skipping filtergraph test, see ROSTESTS-116\n");
1887 CoInitializeEx(NULL
, COINIT_MULTITHREADED
);
1888 hr
= CoCreateInstance(&CLSID_FilterGraph
, NULL
, CLSCTX_INPROC_SERVER
,
1889 &IID_IGraphBuilder
, (LPVOID
*)&pgraph
);
1891 skip("Creating filtergraph returned %08x, skipping tests\n", hr
);
1894 test_render_run(avifile
);
1895 test_render_run(mpegfile
);
1896 test_graph_builder();
1897 test_graph_builder_addfilter();
1898 test_mediacontrol();
1899 test_filter_graph2();
1900 test_render_filter_priority();