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 GUID format
= GUID_NULL
;
259 IMediaSeeking
*seeking
= NULL
;
260 IMediaFilter
*filter
= NULL
;
261 IMediaControl
*control
= NULL
;
263 IGraphBuilder_SetDefaultSyncSource(pgraph
);
264 hr
= IGraphBuilder_QueryInterface(pgraph
, &IID_IMediaSeeking
, (void**) &seeking
);
265 ok(hr
== S_OK
, "QueryInterface IMediaControl failed: %08x\n", hr
);
269 hr
= IGraphBuilder_QueryInterface(pgraph
, &IID_IMediaFilter
, (void**) &filter
);
270 ok(hr
== S_OK
, "QueryInterface IMediaFilter failed: %08x\n", hr
);
273 IMediaSeeking_Release(seeking
);
277 hr
= IGraphBuilder_QueryInterface(pgraph
, &IID_IMediaControl
, (void**) &control
);
278 ok(hr
== S_OK
, "QueryInterface IMediaControl failed: %08x\n", hr
);
281 IMediaSeeking_Release(seeking
);
282 IMediaFilter_Release(filter
);
287 hr
= IMediaSeeking_GetTimeFormat(seeking
, &format
);
288 ok(hr
== S_OK
, "GetTimeFormat failed: %08x\n", hr
);
289 ok(IsEqualGUID(&format
, &TIME_FORMAT_MEDIA_TIME
), "GetTimeFormat: unexpected format %s\n", wine_dbgstr_guid(&format
));
292 hr
= IMediaSeeking_ConvertTimeFormat(seeking
, &pos
, NULL
, 0x123456789a, NULL
);
293 ok(hr
== S_OK
, "ConvertTimeFormat failed: %08x\n", hr
);
294 ok(pos
== 0x123456789a, "ConvertTimeFormat: expected 123456789a, got (%x%08x)\n", (DWORD
)(pos
>> 32), (DWORD
)pos
);
297 hr
= IMediaSeeking_ConvertTimeFormat(seeking
, &pos
, &TIME_FORMAT_MEDIA_TIME
, 0x123456789a, NULL
);
298 ok(hr
== S_OK
, "ConvertTimeFormat failed: %08x\n", hr
);
299 ok(pos
== 0x123456789a, "ConvertTimeFormat: expected 123456789a, got (%x%08x)\n", (DWORD
)(pos
>> 32), (DWORD
)pos
);
302 hr
= IMediaSeeking_ConvertTimeFormat(seeking
, &pos
, NULL
, 0x123456789a, &TIME_FORMAT_MEDIA_TIME
);
303 ok(hr
== S_OK
, "ConvertTimeFormat failed: %08x\n", hr
);
304 ok(pos
== 0x123456789a, "ConvertTimeFormat: expected 123456789a, got (%x%08x)\n", (DWORD
)(pos
>> 32), (DWORD
)pos
);
306 hr
= IMediaSeeking_GetCurrentPosition(seeking
, &pos
);
307 ok(hr
== S_OK
, "GetCurrentPosition failed: %08x\n", hr
);
308 ok(pos
== 0, "Position != 0 (%x%08x)\n", (DWORD
)(pos
>> 32), (DWORD
)pos
);
310 hr
= IMediaSeeking_SetPositions(seeking
, NULL
, AM_SEEKING_ReturnTime
, NULL
, AM_SEEKING_NoPositioning
);
311 ok(hr
== S_OK
, "SetPositions failed: %08x\n", hr
);
312 hr
= IMediaSeeking_SetPositions(seeking
, NULL
, AM_SEEKING_NoPositioning
, NULL
, AM_SEEKING_ReturnTime
);
313 ok(hr
== S_OK
, "SetPositions failed: %08x\n", hr
);
315 IMediaFilter_SetSyncSource(filter
, NULL
);
317 hr
= IMediaSeeking_GetCurrentPosition(seeking
, &pos
);
318 ok(hr
== S_OK
, "GetCurrentPosition failed: %08x\n", hr
);
319 ok(pos
== 0, "Position != 0 (%x%08x)\n", (DWORD
)(pos
>> 32), (DWORD
)pos
);
321 hr
= IMediaControl_GetState(control
, 1000, NULL
);
322 ok(hr
== E_POINTER
, "GetState expected %08x, got %08x\n", E_POINTER
, hr
);
324 IMediaControl_Release(control
);
325 IMediaSeeking_Release(seeking
);
326 IMediaFilter_Release(filter
);
327 releasefiltergraph();
330 static void test_filter_graph2(void)
333 IFilterGraph2
*pF
= NULL
;
335 hr
= CoCreateInstance(&CLSID_FilterGraph
, NULL
, CLSCTX_INPROC_SERVER
,
336 &IID_IFilterGraph2
, (LPVOID
*)&pF
);
337 ok(hr
== S_OK
, "CoCreateInstance failed with %x\n", hr
);
338 ok(pF
!= NULL
, "pF is NULL\n");
340 hr
= IFilterGraph2_Release(pF
);
341 ok(hr
== 0, "IFilterGraph2_Release returned: %x\n", hr
);
344 /* IEnumMediaTypes implementation (supporting code for Render() test.) */
345 static void FreeMediaType(AM_MEDIA_TYPE
* pMediaType
)
347 if (pMediaType
->pbFormat
)
349 CoTaskMemFree(pMediaType
->pbFormat
);
350 pMediaType
->pbFormat
= NULL
;
352 if (pMediaType
->pUnk
)
354 IUnknown_Release(pMediaType
->pUnk
);
355 pMediaType
->pUnk
= NULL
;
359 static HRESULT
CopyMediaType(AM_MEDIA_TYPE
* pDest
, const AM_MEDIA_TYPE
*pSrc
)
362 if (!pSrc
->pbFormat
) return S_OK
;
363 if (!(pDest
->pbFormat
= CoTaskMemAlloc(pSrc
->cbFormat
)))
364 return E_OUTOFMEMORY
;
365 memcpy(pDest
->pbFormat
, pSrc
->pbFormat
, pSrc
->cbFormat
);
367 IUnknown_AddRef(pDest
->pUnk
);
371 static AM_MEDIA_TYPE
* CreateMediaType(AM_MEDIA_TYPE
const * pSrc
)
373 AM_MEDIA_TYPE
* pDest
;
375 pDest
= CoTaskMemAlloc(sizeof(AM_MEDIA_TYPE
));
379 if (FAILED(CopyMediaType(pDest
, pSrc
)))
381 CoTaskMemFree(pDest
);
388 static BOOL
CompareMediaTypes(const AM_MEDIA_TYPE
* pmt1
, const AM_MEDIA_TYPE
* pmt2
, BOOL bWildcards
)
390 return (((bWildcards
&& (IsEqualGUID(&pmt1
->majortype
, &GUID_NULL
) || IsEqualGUID(&pmt2
->majortype
, &GUID_NULL
))) || IsEqualGUID(&pmt1
->majortype
, &pmt2
->majortype
)) &&
391 ((bWildcards
&& (IsEqualGUID(&pmt1
->subtype
, &GUID_NULL
) || IsEqualGUID(&pmt2
->subtype
, &GUID_NULL
))) || IsEqualGUID(&pmt1
->subtype
, &pmt2
->subtype
)));
394 static void DeleteMediaType(AM_MEDIA_TYPE
* pMediaType
)
396 FreeMediaType(pMediaType
);
397 CoTaskMemFree(pMediaType
);
400 typedef struct IEnumMediaTypesImpl
402 IEnumMediaTypes IEnumMediaTypes_iface
;
404 AM_MEDIA_TYPE
*pMediaTypes
;
407 } IEnumMediaTypesImpl
;
409 static const struct IEnumMediaTypesVtbl IEnumMediaTypesImpl_Vtbl
;
411 static inline IEnumMediaTypesImpl
*impl_from_IEnumMediaTypes(IEnumMediaTypes
*iface
)
413 return CONTAINING_RECORD(iface
, IEnumMediaTypesImpl
, IEnumMediaTypes_iface
);
416 static HRESULT
IEnumMediaTypesImpl_Construct(const AM_MEDIA_TYPE
* pMediaTypes
, ULONG cMediaTypes
, IEnumMediaTypes
** ppEnum
)
419 IEnumMediaTypesImpl
* pEnumMediaTypes
= CoTaskMemAlloc(sizeof(IEnumMediaTypesImpl
));
421 if (!pEnumMediaTypes
)
424 return E_OUTOFMEMORY
;
426 pEnumMediaTypes
->IEnumMediaTypes_iface
.lpVtbl
= &IEnumMediaTypesImpl_Vtbl
;
427 pEnumMediaTypes
->refCount
= 1;
428 pEnumMediaTypes
->uIndex
= 0;
429 pEnumMediaTypes
->cMediaTypes
= cMediaTypes
;
430 pEnumMediaTypes
->pMediaTypes
= CoTaskMemAlloc(sizeof(AM_MEDIA_TYPE
) * cMediaTypes
);
431 for (i
= 0; i
< cMediaTypes
; i
++)
432 if (FAILED(CopyMediaType(&pEnumMediaTypes
->pMediaTypes
[i
], &pMediaTypes
[i
])))
435 FreeMediaType(&pEnumMediaTypes
->pMediaTypes
[i
]);
436 CoTaskMemFree(pEnumMediaTypes
->pMediaTypes
);
437 return E_OUTOFMEMORY
;
439 *ppEnum
= &pEnumMediaTypes
->IEnumMediaTypes_iface
;
443 static HRESULT WINAPI
IEnumMediaTypesImpl_QueryInterface(IEnumMediaTypes
* iface
, REFIID riid
, LPVOID
* ppv
)
447 if (IsEqualIID(riid
, &IID_IUnknown
))
449 else if (IsEqualIID(riid
, &IID_IEnumMediaTypes
))
454 IUnknown_AddRef((IUnknown
*)(*ppv
));
458 return E_NOINTERFACE
;
461 static ULONG WINAPI
IEnumMediaTypesImpl_AddRef(IEnumMediaTypes
* iface
)
463 IEnumMediaTypesImpl
*This
= impl_from_IEnumMediaTypes(iface
);
464 ULONG refCount
= InterlockedIncrement(&This
->refCount
);
469 static ULONG WINAPI
IEnumMediaTypesImpl_Release(IEnumMediaTypes
* iface
)
471 IEnumMediaTypesImpl
*This
= impl_from_IEnumMediaTypes(iface
);
472 ULONG refCount
= InterlockedDecrement(&This
->refCount
);
477 for (i
= 0; i
< This
->cMediaTypes
; i
++)
478 FreeMediaType(&This
->pMediaTypes
[i
]);
479 CoTaskMemFree(This
->pMediaTypes
);
485 static HRESULT WINAPI
IEnumMediaTypesImpl_Next(IEnumMediaTypes
* iface
, ULONG cMediaTypes
, AM_MEDIA_TYPE
** ppMediaTypes
, ULONG
* pcFetched
)
488 IEnumMediaTypesImpl
*This
= impl_from_IEnumMediaTypes(iface
);
490 cFetched
= min(This
->cMediaTypes
, This
->uIndex
+ cMediaTypes
) - This
->uIndex
;
495 for (i
= 0; i
< cFetched
; i
++)
496 if (!(ppMediaTypes
[i
] = CreateMediaType(&This
->pMediaTypes
[This
->uIndex
+ i
])))
499 DeleteMediaType(ppMediaTypes
[i
]);
501 return E_OUTOFMEMORY
;
505 if ((cMediaTypes
!= 1) || pcFetched
)
506 *pcFetched
= cFetched
;
508 This
->uIndex
+= cFetched
;
510 if (cFetched
!= cMediaTypes
)
515 static HRESULT WINAPI
IEnumMediaTypesImpl_Skip(IEnumMediaTypes
* iface
, ULONG cMediaTypes
)
517 IEnumMediaTypesImpl
*This
= impl_from_IEnumMediaTypes(iface
);
519 if (This
->uIndex
+ cMediaTypes
< This
->cMediaTypes
)
521 This
->uIndex
+= cMediaTypes
;
527 static HRESULT WINAPI
IEnumMediaTypesImpl_Reset(IEnumMediaTypes
* iface
)
529 IEnumMediaTypesImpl
*This
= impl_from_IEnumMediaTypes(iface
);
535 static HRESULT WINAPI
IEnumMediaTypesImpl_Clone(IEnumMediaTypes
* iface
, IEnumMediaTypes
** ppEnum
)
538 IEnumMediaTypesImpl
*This
= impl_from_IEnumMediaTypes(iface
);
540 hr
= IEnumMediaTypesImpl_Construct(This
->pMediaTypes
, This
->cMediaTypes
, ppEnum
);
543 return IEnumMediaTypes_Skip(*ppEnum
, This
->uIndex
);
546 static const IEnumMediaTypesVtbl IEnumMediaTypesImpl_Vtbl
=
548 IEnumMediaTypesImpl_QueryInterface
,
549 IEnumMediaTypesImpl_AddRef
,
550 IEnumMediaTypesImpl_Release
,
551 IEnumMediaTypesImpl_Next
,
552 IEnumMediaTypesImpl_Skip
,
553 IEnumMediaTypesImpl_Reset
,
554 IEnumMediaTypesImpl_Clone
557 /* Implementation of a very stripped down pin for the test filter. Just enough
558 functionality for connecting and Render() to work. */
560 static void Copy_PinInfo(PIN_INFO
* pDest
, const PIN_INFO
* pSrc
)
562 lstrcpyW(pDest
->achName
, pSrc
->achName
);
563 pDest
->dir
= pSrc
->dir
;
564 pDest
->pFilter
= pSrc
->pFilter
;
567 typedef struct ITestPinImpl
571 LPCRITICAL_SECTION pCritSec
;
574 AM_MEDIA_TYPE mtCurrent
;
578 static inline ITestPinImpl
*impl_from_IPin(IPin
*iface
)
580 return CONTAINING_RECORD(iface
, ITestPinImpl
, IPin_iface
);
583 static HRESULT WINAPI
TestFilter_Pin_QueryInterface(IPin
* iface
, REFIID riid
, LPVOID
* ppv
)
587 if (IsEqualIID(riid
, &IID_IUnknown
))
589 else if (IsEqualIID(riid
, &IID_IPin
))
594 IUnknown_AddRef((IUnknown
*)(*ppv
));
598 return E_NOINTERFACE
;
601 static ULONG WINAPI
TestFilter_Pin_AddRef(IPin
* iface
)
603 ITestPinImpl
*This
= impl_from_IPin(iface
);
604 ULONG refCount
= InterlockedIncrement(&This
->refCount
);
608 static ULONG WINAPI
TestFilter_Pin_Release(IPin
* iface
)
610 ITestPinImpl
*This
= impl_from_IPin(iface
);
611 ULONG refCount
= InterlockedDecrement(&This
->refCount
);
615 FreeMediaType(&This
->mtCurrent
);
623 static HRESULT WINAPI
TestFilter_InputPin_Connect(IPin
* iface
, IPin
* pConnector
, const AM_MEDIA_TYPE
* pmt
)
628 static HRESULT WINAPI
TestFilter_InputPin_ReceiveConnection(IPin
* iface
, IPin
* pReceivePin
, const AM_MEDIA_TYPE
* pmt
)
630 ITestPinImpl
*This
= impl_from_IPin(iface
);
631 PIN_DIRECTION pindirReceive
;
634 EnterCriticalSection(This
->pCritSec
);
636 if (!(IsEqualIID(&pmt
->majortype
, &This
->mtCurrent
.majortype
) && (IsEqualIID(&pmt
->subtype
, &This
->mtCurrent
.subtype
) ||
637 IsEqualIID(&GUID_NULL
, &This
->mtCurrent
.subtype
))))
638 hr
= VFW_E_TYPE_NOT_ACCEPTED
;
640 if (This
->pConnectedTo
)
641 hr
= VFW_E_ALREADY_CONNECTED
;
645 IPin_QueryDirection(pReceivePin
, &pindirReceive
);
647 if (pindirReceive
!= PINDIR_OUTPUT
)
649 hr
= VFW_E_INVALID_DIRECTION
;
655 CopyMediaType(&This
->mtCurrent
, pmt
);
656 This
->pConnectedTo
= pReceivePin
;
657 IPin_AddRef(pReceivePin
);
660 LeaveCriticalSection(This
->pCritSec
);
665 static HRESULT WINAPI
TestFilter_Pin_Disconnect(IPin
* iface
)
668 ITestPinImpl
*This
= impl_from_IPin(iface
);
670 EnterCriticalSection(This
->pCritSec
);
672 if (This
->pConnectedTo
)
674 IPin_Release(This
->pConnectedTo
);
675 This
->pConnectedTo
= NULL
;
681 LeaveCriticalSection(This
->pCritSec
);
686 static HRESULT WINAPI
TestFilter_Pin_ConnectedTo(IPin
* iface
, IPin
** ppPin
)
689 ITestPinImpl
*This
= impl_from_IPin(iface
);
691 EnterCriticalSection(This
->pCritSec
);
693 if (This
->pConnectedTo
)
695 *ppPin
= This
->pConnectedTo
;
701 hr
= VFW_E_NOT_CONNECTED
;
705 LeaveCriticalSection(This
->pCritSec
);
710 static HRESULT WINAPI
TestFilter_Pin_ConnectionMediaType(IPin
* iface
, AM_MEDIA_TYPE
* pmt
)
713 ITestPinImpl
*This
= impl_from_IPin(iface
);
715 EnterCriticalSection(This
->pCritSec
);
717 if (This
->pConnectedTo
)
719 CopyMediaType(pmt
, &This
->mtCurrent
);
724 ZeroMemory(pmt
, sizeof(*pmt
));
725 hr
= VFW_E_NOT_CONNECTED
;
728 LeaveCriticalSection(This
->pCritSec
);
733 static HRESULT WINAPI
TestFilter_Pin_QueryPinInfo(IPin
* iface
, PIN_INFO
* pInfo
)
735 ITestPinImpl
*This
= impl_from_IPin(iface
);
737 Copy_PinInfo(pInfo
, &This
->pinInfo
);
738 IBaseFilter_AddRef(pInfo
->pFilter
);
743 static HRESULT WINAPI
TestFilter_Pin_QueryDirection(IPin
* iface
, PIN_DIRECTION
* pPinDir
)
745 ITestPinImpl
*This
= impl_from_IPin(iface
);
747 *pPinDir
= This
->pinInfo
.dir
;
752 static HRESULT WINAPI
TestFilter_Pin_QueryId(IPin
* iface
, LPWSTR
* Id
)
757 static HRESULT WINAPI
TestFilter_Pin_QueryAccept(IPin
* iface
, const AM_MEDIA_TYPE
* pmt
)
759 ITestPinImpl
*This
= impl_from_IPin(iface
);
761 if (IsEqualIID(&pmt
->majortype
, &This
->mtCurrent
.majortype
) && (IsEqualIID(&pmt
->subtype
, &This
->mtCurrent
.subtype
) ||
762 IsEqualIID(&GUID_NULL
, &This
->mtCurrent
.subtype
)))
765 return VFW_E_TYPE_NOT_ACCEPTED
;
768 static HRESULT WINAPI
TestFilter_Pin_EnumMediaTypes(IPin
* iface
, IEnumMediaTypes
** ppEnum
)
770 ITestPinImpl
*This
= impl_from_IPin(iface
);
772 return IEnumMediaTypesImpl_Construct(&This
->mtCurrent
, 1, ppEnum
);
775 static HRESULT WINAPI
TestFilter_Pin_QueryInternalConnections(IPin
* iface
, IPin
** apPin
, ULONG
* cPin
)
780 static HRESULT WINAPI
TestFilter_Pin_BeginFlush(IPin
* iface
)
785 static HRESULT WINAPI
TestFilter_Pin_EndFlush(IPin
* iface
)
790 static HRESULT WINAPI
TestFilter_Pin_NewSegment(IPin
* iface
, REFERENCE_TIME tStart
, REFERENCE_TIME tStop
, double dRate
)
795 static HRESULT WINAPI
TestFilter_Pin_EndOfStream(IPin
* iface
)
800 static const IPinVtbl TestFilter_InputPin_Vtbl
=
802 TestFilter_Pin_QueryInterface
,
803 TestFilter_Pin_AddRef
,
804 TestFilter_Pin_Release
,
805 TestFilter_InputPin_Connect
,
806 TestFilter_InputPin_ReceiveConnection
,
807 TestFilter_Pin_Disconnect
,
808 TestFilter_Pin_ConnectedTo
,
809 TestFilter_Pin_ConnectionMediaType
,
810 TestFilter_Pin_QueryPinInfo
,
811 TestFilter_Pin_QueryDirection
,
812 TestFilter_Pin_QueryId
,
813 TestFilter_Pin_QueryAccept
,
814 TestFilter_Pin_EnumMediaTypes
,
815 TestFilter_Pin_QueryInternalConnections
,
816 TestFilter_Pin_EndOfStream
,
817 TestFilter_Pin_BeginFlush
,
818 TestFilter_Pin_EndFlush
,
819 TestFilter_Pin_NewSegment
822 static HRESULT WINAPI
TestFilter_OutputPin_ReceiveConnection(IPin
* iface
, IPin
* pReceivePin
, const AM_MEDIA_TYPE
* pmt
)
827 /* Private helper function */
828 static HRESULT
TestFilter_OutputPin_ConnectSpecific(ITestPinImpl
* This
, IPin
* pReceivePin
,
829 const AM_MEDIA_TYPE
* pmt
)
833 This
->pConnectedTo
= pReceivePin
;
834 IPin_AddRef(pReceivePin
);
836 hr
= IPin_ReceiveConnection(pReceivePin
, &This
->IPin_iface
, pmt
);
840 IPin_Release(This
->pConnectedTo
);
841 This
->pConnectedTo
= NULL
;
847 static HRESULT WINAPI
TestFilter_OutputPin_Connect(IPin
* iface
, IPin
* pReceivePin
, const AM_MEDIA_TYPE
* pmt
)
849 ITestPinImpl
*This
= impl_from_IPin(iface
);
852 EnterCriticalSection(This
->pCritSec
);
854 /* if we have been a specific type to connect with, then we can either connect
855 * with that or fail. We cannot choose different AM_MEDIA_TYPE */
856 if (pmt
&& !IsEqualGUID(&pmt
->majortype
, &GUID_NULL
) && !IsEqualGUID(&pmt
->subtype
, &GUID_NULL
))
857 hr
= TestFilter_OutputPin_ConnectSpecific(This
, pReceivePin
, pmt
);
860 if (( !pmt
|| CompareMediaTypes(pmt
, &This
->mtCurrent
, TRUE
) ) &&
861 (TestFilter_OutputPin_ConnectSpecific(This
, pReceivePin
, &This
->mtCurrent
) == S_OK
))
863 else hr
= VFW_E_NO_ACCEPTABLE_TYPES
;
864 } /* if negotiate media type */
866 LeaveCriticalSection(This
->pCritSec
);
871 static const IPinVtbl TestFilter_OutputPin_Vtbl
=
873 TestFilter_Pin_QueryInterface
,
874 TestFilter_Pin_AddRef
,
875 TestFilter_Pin_Release
,
876 TestFilter_OutputPin_Connect
,
877 TestFilter_OutputPin_ReceiveConnection
,
878 TestFilter_Pin_Disconnect
,
879 TestFilter_Pin_ConnectedTo
,
880 TestFilter_Pin_ConnectionMediaType
,
881 TestFilter_Pin_QueryPinInfo
,
882 TestFilter_Pin_QueryDirection
,
883 TestFilter_Pin_QueryId
,
884 TestFilter_Pin_QueryAccept
,
885 TestFilter_Pin_EnumMediaTypes
,
886 TestFilter_Pin_QueryInternalConnections
,
887 TestFilter_Pin_EndOfStream
,
888 TestFilter_Pin_BeginFlush
,
889 TestFilter_Pin_EndFlush
,
890 TestFilter_Pin_NewSegment
893 static HRESULT
TestFilter_Pin_Construct(const IPinVtbl
*Pin_Vtbl
, const PIN_INFO
* pPinInfo
, AM_MEDIA_TYPE
*pinmt
,
894 LPCRITICAL_SECTION pCritSec
, IPin
** ppPin
)
896 ITestPinImpl
* pPinImpl
;
900 pPinImpl
= CoTaskMemAlloc(sizeof(ITestPinImpl
));
903 return E_OUTOFMEMORY
;
905 pPinImpl
->refCount
= 1;
906 pPinImpl
->pConnectedTo
= NULL
;
907 pPinImpl
->pCritSec
= pCritSec
;
908 Copy_PinInfo(&pPinImpl
->pinInfo
, pPinInfo
);
909 pPinImpl
->mtCurrent
= *pinmt
;
911 pPinImpl
->IPin_iface
.lpVtbl
= Pin_Vtbl
;
913 *ppPin
= &pPinImpl
->IPin_iface
;
917 /* IEnumPins implementation */
919 typedef HRESULT (* FNOBTAINPIN
)(TestFilterImpl
*tf
, ULONG pos
, IPin
**pin
, DWORD
*lastsynctick
);
921 typedef struct IEnumPinsImpl
923 IEnumPins IEnumPins_iface
;
926 TestFilterImpl
*base
;
927 FNOBTAINPIN receive_pin
;
931 static const struct IEnumPinsVtbl IEnumPinsImpl_Vtbl
;
933 static inline IEnumPinsImpl
*impl_from_IEnumPins(IEnumPins
*iface
)
935 return CONTAINING_RECORD(iface
, IEnumPinsImpl
, IEnumPins_iface
);
938 static HRESULT
createenumpins(IEnumPins
** ppEnum
, FNOBTAINPIN receive_pin
, TestFilterImpl
*base
)
940 IEnumPinsImpl
* pEnumPins
;
945 pEnumPins
= CoTaskMemAlloc(sizeof(IEnumPinsImpl
));
949 return E_OUTOFMEMORY
;
951 pEnumPins
->IEnumPins_iface
.lpVtbl
= &IEnumPinsImpl_Vtbl
;
952 pEnumPins
->refCount
= 1;
953 pEnumPins
->uIndex
= 0;
954 pEnumPins
->receive_pin
= receive_pin
;
955 pEnumPins
->base
= base
;
956 IBaseFilter_AddRef(&base
->IBaseFilter_iface
);
957 *ppEnum
= &pEnumPins
->IEnumPins_iface
;
959 receive_pin(base
, ~0, NULL
, &pEnumPins
->synctime
);
964 static HRESULT WINAPI
IEnumPinsImpl_QueryInterface(IEnumPins
* iface
, REFIID riid
, LPVOID
* ppv
)
968 if (IsEqualIID(riid
, &IID_IUnknown
))
970 else if (IsEqualIID(riid
, &IID_IEnumPins
))
975 IUnknown_AddRef((IUnknown
*)(*ppv
));
979 return E_NOINTERFACE
;
982 static ULONG WINAPI
IEnumPinsImpl_AddRef(IEnumPins
* iface
)
984 IEnumPinsImpl
*This
= impl_from_IEnumPins(iface
);
985 ULONG refCount
= InterlockedIncrement(&This
->refCount
);
990 static ULONG WINAPI
IEnumPinsImpl_Release(IEnumPins
* iface
)
992 IEnumPinsImpl
*This
= impl_from_IEnumPins(iface
);
993 ULONG refCount
= InterlockedDecrement(&This
->refCount
);
997 IBaseFilter_Release(&This
->base
->IBaseFilter_iface
);
1005 static HRESULT WINAPI
IEnumPinsImpl_Next(IEnumPins
* iface
, ULONG cPins
, IPin
** ppPins
, ULONG
* pcFetched
)
1007 IEnumPinsImpl
*This
= impl_from_IEnumPins(iface
);
1008 DWORD synctime
= This
->synctime
;
1015 if (cPins
> 1 && !pcFetched
)
1016 return E_INVALIDARG
;
1021 while (i
< cPins
&& hr
== S_OK
)
1023 hr
= This
->receive_pin(This
->base
, This
->uIndex
+ i
, &ppPins
[i
], &synctime
);
1028 if (synctime
!= This
->synctime
)
1032 if (!i
&& synctime
!= This
->synctime
)
1033 return VFW_E_ENUM_OUT_OF_SYNC
;
1044 static HRESULT WINAPI
IEnumPinsImpl_Skip(IEnumPins
* iface
, ULONG cPins
)
1046 IEnumPinsImpl
*This
= impl_from_IEnumPins(iface
);
1047 DWORD synctime
= This
->synctime
;
1051 hr
= This
->receive_pin(This
->base
, This
->uIndex
+ cPins
, &pin
, &synctime
);
1055 if (synctime
!= This
->synctime
)
1056 return VFW_E_ENUM_OUT_OF_SYNC
;
1059 This
->uIndex
+= cPins
;
1064 static HRESULT WINAPI
IEnumPinsImpl_Reset(IEnumPins
* iface
)
1066 IEnumPinsImpl
*This
= impl_from_IEnumPins(iface
);
1068 This
->receive_pin(This
->base
, ~0, NULL
, &This
->synctime
);
1074 static HRESULT WINAPI
IEnumPinsImpl_Clone(IEnumPins
* iface
, IEnumPins
** ppEnum
)
1077 IEnumPinsImpl
*This
= impl_from_IEnumPins(iface
);
1079 hr
= createenumpins(ppEnum
, This
->receive_pin
, This
->base
);
1082 return IEnumPins_Skip(*ppEnum
, This
->uIndex
);
1085 static const IEnumPinsVtbl IEnumPinsImpl_Vtbl
=
1087 IEnumPinsImpl_QueryInterface
,
1088 IEnumPinsImpl_AddRef
,
1089 IEnumPinsImpl_Release
,
1092 IEnumPinsImpl_Reset
,
1096 /* Test filter implementation - a filter that has few predefined pins with single media type
1097 * that accept only this single media type. Enough for Render(). */
1099 typedef struct TestFilterPinData
1101 PIN_DIRECTION pinDir
;
1102 const GUID
*mediasubtype
;
1103 } TestFilterPinData
;
1105 static const IBaseFilterVtbl TestFilter_Vtbl
;
1107 static inline TestFilterImpl
*impl_from_IBaseFilter(IBaseFilter
*iface
)
1109 return CONTAINING_RECORD(iface
, TestFilterImpl
, IBaseFilter_iface
);
1112 static HRESULT
createtestfilter(const CLSID
* pClsid
, const TestFilterPinData
*pinData
,
1113 TestFilterImpl
**tf
)
1115 static const WCHAR wcsInputPinName
[] = {'i','n','p','u','t',' ','p','i','n',0};
1116 static const WCHAR wcsOutputPinName
[] = {'o','u','t','p','u','t',' ','p','i','n',0};
1119 TestFilterImpl
* pTestFilter
= NULL
;
1123 pTestFilter
= CoTaskMemAlloc(sizeof(TestFilterImpl
));
1124 if (!pTestFilter
) return E_OUTOFMEMORY
;
1126 pTestFilter
->clsid
= *pClsid
;
1127 pTestFilter
->IBaseFilter_iface
.lpVtbl
= &TestFilter_Vtbl
;
1128 pTestFilter
->refCount
= 1;
1129 InitializeCriticalSection(&pTestFilter
->csFilter
);
1130 pTestFilter
->state
= State_Stopped
;
1132 ZeroMemory(&pTestFilter
->filterInfo
, sizeof(FILTER_INFO
));
1135 while(pinData
[nPins
].mediasubtype
) ++nPins
;
1137 pTestFilter
->ppPins
= CoTaskMemAlloc(nPins
* sizeof(IPin
*));
1138 if (!pTestFilter
->ppPins
)
1143 ZeroMemory(pTestFilter
->ppPins
, nPins
* sizeof(IPin
*));
1145 for (i
= 0; i
< nPins
; i
++)
1147 ZeroMemory(&mt
, sizeof(mt
));
1148 mt
.majortype
= MEDIATYPE_Video
;
1149 mt
.formattype
= FORMAT_None
;
1150 mt
.subtype
= *pinData
[i
].mediasubtype
;
1152 pinInfo
.dir
= pinData
[i
].pinDir
;
1153 pinInfo
.pFilter
= &pTestFilter
->IBaseFilter_iface
;
1154 if (pinInfo
.dir
== PINDIR_INPUT
)
1156 lstrcpynW(pinInfo
.achName
, wcsInputPinName
, sizeof(pinInfo
.achName
) / sizeof(pinInfo
.achName
[0]));
1157 hr
= TestFilter_Pin_Construct(&TestFilter_InputPin_Vtbl
, &pinInfo
, &mt
, &pTestFilter
->csFilter
,
1158 &pTestFilter
->ppPins
[i
]);
1163 lstrcpynW(pinInfo
.achName
, wcsOutputPinName
, sizeof(pinInfo
.achName
) / sizeof(pinInfo
.achName
[0]));
1164 hr
= TestFilter_Pin_Construct(&TestFilter_OutputPin_Vtbl
, &pinInfo
, &mt
, &pTestFilter
->csFilter
,
1165 &pTestFilter
->ppPins
[i
]);
1167 if (FAILED(hr
) || !pTestFilter
->ppPins
[i
]) goto error
;
1170 pTestFilter
->nPins
= nPins
;
1176 if (pTestFilter
->ppPins
)
1178 for (i
= 0; i
< nPins
; i
++)
1180 if (pTestFilter
->ppPins
[i
]) IPin_Release(pTestFilter
->ppPins
[i
]);
1183 CoTaskMemFree(pTestFilter
->ppPins
);
1184 DeleteCriticalSection(&pTestFilter
->csFilter
);
1185 CoTaskMemFree(pTestFilter
);
1190 static HRESULT WINAPI
TestFilter_QueryInterface(IBaseFilter
* iface
, REFIID riid
, LPVOID
* ppv
)
1192 TestFilterImpl
*This
= impl_from_IBaseFilter(iface
);
1196 if (IsEqualIID(riid
, &IID_IUnknown
))
1198 else if (IsEqualIID(riid
, &IID_IPersist
))
1200 else if (IsEqualIID(riid
, &IID_IMediaFilter
))
1202 else if (IsEqualIID(riid
, &IID_IBaseFilter
))
1207 IUnknown_AddRef((IUnknown
*)(*ppv
));
1211 return E_NOINTERFACE
;
1214 static ULONG WINAPI
TestFilter_AddRef(IBaseFilter
* iface
)
1216 TestFilterImpl
*This
= impl_from_IBaseFilter(iface
);
1217 ULONG refCount
= InterlockedIncrement(&This
->refCount
);
1222 static ULONG WINAPI
TestFilter_Release(IBaseFilter
* iface
)
1224 TestFilterImpl
*This
= impl_from_IBaseFilter(iface
);
1225 ULONG refCount
= InterlockedDecrement(&This
->refCount
);
1231 for (i
= 0; i
< This
->nPins
; i
++)
1235 if (SUCCEEDED(IPin_ConnectedTo(This
->ppPins
[i
], &pConnectedTo
)))
1237 IPin_Disconnect(pConnectedTo
);
1238 IPin_Release(pConnectedTo
);
1240 IPin_Disconnect(This
->ppPins
[i
]);
1242 IPin_Release(This
->ppPins
[i
]);
1245 CoTaskMemFree(This
->ppPins
);
1247 DeleteCriticalSection(&This
->csFilter
);
1249 CoTaskMemFree(This
);
1256 /** IPersist methods **/
1258 static HRESULT WINAPI
TestFilter_GetClassID(IBaseFilter
* iface
, CLSID
* pClsid
)
1260 TestFilterImpl
*This
= impl_from_IBaseFilter(iface
);
1262 *pClsid
= This
->clsid
;
1267 /** IMediaFilter methods **/
1269 static HRESULT WINAPI
TestFilter_Stop(IBaseFilter
* iface
)
1274 static HRESULT WINAPI
TestFilter_Pause(IBaseFilter
* iface
)
1279 static HRESULT WINAPI
TestFilter_Run(IBaseFilter
* iface
, REFERENCE_TIME tStart
)
1284 static HRESULT WINAPI
TestFilter_GetState(IBaseFilter
* iface
, DWORD dwMilliSecsTimeout
, FILTER_STATE
*pState
)
1286 TestFilterImpl
*This
= impl_from_IBaseFilter(iface
);
1288 EnterCriticalSection(&This
->csFilter
);
1290 *pState
= This
->state
;
1292 LeaveCriticalSection(&This
->csFilter
);
1297 static HRESULT WINAPI
TestFilter_SetSyncSource(IBaseFilter
* iface
, IReferenceClock
*pClock
)
1302 static HRESULT WINAPI
TestFilter_GetSyncSource(IBaseFilter
* iface
, IReferenceClock
**ppClock
)
1307 /** IBaseFilter implementation **/
1309 static HRESULT
getpin_callback(TestFilterImpl
*tf
, ULONG pos
, IPin
**pin
, DWORD
*lastsynctick
)
1311 /* Our pins are static, not changing so setting static tick count is ok */
1314 if (pos
>= tf
->nPins
)
1317 *pin
= tf
->ppPins
[pos
];
1322 static HRESULT WINAPI
TestFilter_EnumPins(IBaseFilter
* iface
, IEnumPins
**ppEnum
)
1324 TestFilterImpl
*This
= impl_from_IBaseFilter(iface
);
1326 return createenumpins(ppEnum
, getpin_callback
, This
);
1329 static HRESULT WINAPI
TestFilter_FindPin(IBaseFilter
* iface
, LPCWSTR Id
, IPin
**ppPin
)
1334 static HRESULT WINAPI
TestFilter_QueryFilterInfo(IBaseFilter
* iface
, FILTER_INFO
*pInfo
)
1336 TestFilterImpl
*This
= impl_from_IBaseFilter(iface
);
1338 lstrcpyW(pInfo
->achName
, This
->filterInfo
.achName
);
1339 pInfo
->pGraph
= This
->filterInfo
.pGraph
;
1342 IFilterGraph_AddRef(pInfo
->pGraph
);
1347 static HRESULT WINAPI
TestFilter_JoinFilterGraph(IBaseFilter
* iface
, IFilterGraph
*pGraph
, LPCWSTR pName
)
1350 TestFilterImpl
*This
= impl_from_IBaseFilter(iface
);
1352 EnterCriticalSection(&This
->csFilter
);
1355 lstrcpyW(This
->filterInfo
.achName
, pName
);
1357 *This
->filterInfo
.achName
= '\0';
1358 This
->filterInfo
.pGraph
= pGraph
; /* NOTE: do NOT increase ref. count */
1360 LeaveCriticalSection(&This
->csFilter
);
1365 static HRESULT WINAPI
TestFilter_QueryVendorInfo(IBaseFilter
* iface
, LPWSTR
*pVendorInfo
)
1370 static const IBaseFilterVtbl TestFilter_Vtbl
=
1372 TestFilter_QueryInterface
,
1375 TestFilter_GetClassID
,
1379 TestFilter_GetState
,
1380 TestFilter_SetSyncSource
,
1381 TestFilter_GetSyncSource
,
1382 TestFilter_EnumPins
,
1384 TestFilter_QueryFilterInfo
,
1385 TestFilter_JoinFilterGraph
,
1386 TestFilter_QueryVendorInfo
1389 /* IClassFactory implementation */
1391 typedef struct TestClassFactoryImpl
1393 IClassFactory IClassFactory_iface
;
1394 const TestFilterPinData
*filterPinData
;
1396 } TestClassFactoryImpl
;
1398 static inline TestClassFactoryImpl
*impl_from_IClassFactory(IClassFactory
*iface
)
1400 return CONTAINING_RECORD(iface
, TestClassFactoryImpl
, IClassFactory_iface
);
1403 static HRESULT WINAPI
Test_IClassFactory_QueryInterface(
1404 LPCLASSFACTORY iface
,
1408 if (ppvObj
== NULL
) return E_POINTER
;
1410 if (IsEqualGUID(riid
, &IID_IUnknown
) ||
1411 IsEqualGUID(riid
, &IID_IClassFactory
))
1414 IClassFactory_AddRef(iface
);
1419 return E_NOINTERFACE
;
1422 static ULONG WINAPI
Test_IClassFactory_AddRef(LPCLASSFACTORY iface
)
1424 return 2; /* non-heap-based object */
1427 static ULONG WINAPI
Test_IClassFactory_Release(LPCLASSFACTORY iface
)
1429 return 1; /* non-heap-based object */
1432 static HRESULT WINAPI
Test_IClassFactory_CreateInstance(
1433 LPCLASSFACTORY iface
,
1434 LPUNKNOWN pUnkOuter
,
1438 TestClassFactoryImpl
*This
= impl_from_IClassFactory(iface
);
1440 TestFilterImpl
*testfilter
;
1444 if (pUnkOuter
) return CLASS_E_NOAGGREGATION
;
1446 hr
= createtestfilter(This
->clsid
, This
->filterPinData
, &testfilter
);
1447 if (SUCCEEDED(hr
)) {
1448 hr
= IBaseFilter_QueryInterface(&testfilter
->IBaseFilter_iface
, riid
, ppvObj
);
1449 IBaseFilter_Release(&testfilter
->IBaseFilter_iface
);
1454 static HRESULT WINAPI
Test_IClassFactory_LockServer(
1455 LPCLASSFACTORY iface
,
1461 static IClassFactoryVtbl TestClassFactory_Vtbl
=
1463 Test_IClassFactory_QueryInterface
,
1464 Test_IClassFactory_AddRef
,
1465 Test_IClassFactory_Release
,
1466 Test_IClassFactory_CreateInstance
,
1467 Test_IClassFactory_LockServer
1470 static HRESULT
get_connected_filter_name(TestFilterImpl
*pFilter
, char *FilterName
)
1474 FILTER_INFO filterInfo
;
1479 hr
= IPin_ConnectedTo(pFilter
->ppPins
[0], &pin
);
1480 ok(hr
== S_OK
, "IPin_ConnectedTo failed with %x\n", hr
);
1481 if (FAILED(hr
)) return hr
;
1483 hr
= IPin_QueryPinInfo(pin
, &pinInfo
);
1484 ok(hr
== S_OK
, "IPin_QueryPinInfo failed with %x\n", hr
);
1486 if (FAILED(hr
)) return hr
;
1488 SetLastError(0xdeadbeef);
1489 hr
= IBaseFilter_QueryFilterInfo(pinInfo
.pFilter
, &filterInfo
);
1490 if (hr
== S_OK
&& GetLastError() == ERROR_CALL_NOT_IMPLEMENTED
)
1492 IBaseFilter_Release(pinInfo
.pFilter
);
1495 ok(hr
== S_OK
, "IBaseFilter_QueryFilterInfo failed with %x\n", hr
);
1496 IBaseFilter_Release(pinInfo
.pFilter
);
1497 if (FAILED(hr
)) return hr
;
1499 IFilterGraph_Release(filterInfo
.pGraph
);
1501 WideCharToMultiByte(CP_ACP
, 0, filterInfo
.achName
, -1, FilterName
, MAX_FILTER_NAME
, NULL
, NULL
);
1506 static void test_render_filter_priority(void)
1508 /* Tests filter choice priorities in Render(). */
1509 DWORD cookie1
= 0, cookie2
= 0, cookie3
= 0;
1511 IFilterGraph2
* pgraph2
= NULL
;
1512 IFilterMapper2
*pMapper2
= NULL
;
1513 TestFilterImpl
*ptestfilter
= NULL
;
1514 TestFilterImpl
*ptestfilter2
= NULL
;
1515 static const CLSID CLSID_TestFilter2
= {
1519 {0xe8, 0x9b, 0x00, 0x19, 0x66, 0x2f, 0xf0, 0xce}
1521 static const CLSID CLSID_TestFilter3
= {
1525 {0xe8, 0x9b, 0x00, 0x19, 0x66, 0x2f, 0xf0, 0xce}
1527 static const CLSID CLSID_TestFilter4
= {
1531 {0xe8, 0x9b, 0x00, 0x19, 0x66, 0x2f, 0xf0, 0xce}
1533 static const GUID mediasubtype1
= {
1537 {0xe8, 0x9b, 0x00, 0x19, 0x66, 0x2f, 0xf0, 0xce}
1539 static const GUID mediasubtype2
= {
1543 {0xe8, 0x9b, 0x00, 0x19, 0x66, 0x2f, 0xf0, 0xce}
1545 static const TestFilterPinData PinData1
[] = {
1546 { PINDIR_OUTPUT
, &mediasubtype1
},
1549 static const TestFilterPinData PinData2
[] = {
1550 { PINDIR_INPUT
, &mediasubtype1
},
1553 static const TestFilterPinData PinData3
[] = {
1554 { PINDIR_INPUT
, &GUID_NULL
},
1557 static const TestFilterPinData PinData4
[] = {
1558 { PINDIR_INPUT
, &mediasubtype1
},
1559 { PINDIR_OUTPUT
, &mediasubtype2
},
1562 static const TestFilterPinData PinData5
[] = {
1563 { PINDIR_INPUT
, &mediasubtype2
},
1566 TestClassFactoryImpl Filter1ClassFactory
= {
1567 { &TestClassFactory_Vtbl
},
1568 PinData2
, &CLSID_TestFilter2
1570 TestClassFactoryImpl Filter2ClassFactory
= {
1571 { &TestClassFactory_Vtbl
},
1572 PinData4
, &CLSID_TestFilter3
1574 TestClassFactoryImpl Filter3ClassFactory
= {
1575 { &TestClassFactory_Vtbl
},
1576 PinData5
, &CLSID_TestFilter4
1578 char ConnectedFilterName1
[MAX_FILTER_NAME
];
1579 char ConnectedFilterName2
[MAX_FILTER_NAME
];
1581 REGFILTERPINS2 rgPins2
[2];
1582 REGPINTYPES rgPinType
[2];
1583 static const WCHAR wszFilterInstanceName1
[] = {'T', 'e', 's', 't', 'f', 'i', 'l', 't', 'e', 'r', 'I',
1584 'n', 's', 't', 'a', 'n', 'c', 'e', '1', 0 };
1585 static const WCHAR wszFilterInstanceName2
[] = {'T', 'e', 's', 't', 'f', 'i', 'l', 't', 'e', 'r', 'I',
1586 'n', 's', 't', 'a', 'n', 'c', 'e', '2', 0 };
1587 static const WCHAR wszFilterInstanceName3
[] = {'T', 'e', 's', 't', 'f', 'i', 'l', 't', 'e', 'r', 'I',
1588 'n', 's', 't', 'a', 'n', 'c', 'e', '3', 0 };
1589 static const WCHAR wszFilterInstanceName4
[] = {'T', 'e', 's', 't', 'f', 'i', 'l', 't', 'e', 'r', 'I',
1590 'n', 's', 't', 'a', 'n', 'c', 'e', '4', 0 };
1592 /* Test which renderer of two already added to the graph will be chosen
1593 * (one is "exact" match, other is "wildcard" match. Seems to depend
1594 * on the order in which filters are added to the graph, thus indicating
1595 * no preference given to exact match. */
1596 hr
= CoCreateInstance(&CLSID_FilterGraph
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IFilterGraph2
, (LPVOID
*)&pgraph2
);
1597 ok(hr
== S_OK
, "CoCreateInstance failed with %08x\n", hr
);
1598 if (!pgraph2
) return;
1600 hr
= createtestfilter(&GUID_NULL
, PinData1
, &ptestfilter
);
1601 ok(hr
== S_OK
, "createtestfilter failed with %08x\n", hr
);
1602 if (FAILED(hr
)) goto out
;
1604 hr
= IFilterGraph2_AddFilter(pgraph2
, &ptestfilter
->IBaseFilter_iface
, wszFilterInstanceName1
);
1605 ok(hr
== S_OK
, "IFilterGraph2_AddFilter failed with %08x\n", hr
);
1607 hr
= createtestfilter(&GUID_NULL
, PinData2
, &ptestfilter2
);
1608 ok(hr
== S_OK
, "createtestfilter failed with %08x\n", hr
);
1609 if (FAILED(hr
)) goto out
;
1611 hr
= IFilterGraph2_AddFilter(pgraph2
, &ptestfilter2
->IBaseFilter_iface
, wszFilterInstanceName2
);
1612 ok(hr
== S_OK
, "IFilterGraph2_AddFilter failed with %08x\n", hr
);
1614 IBaseFilter_Release(&ptestfilter2
->IBaseFilter_iface
);
1615 ptestfilter2
= NULL
;
1617 hr
= createtestfilter(&GUID_NULL
, PinData3
, &ptestfilter2
);
1618 ok(hr
== S_OK
, "createtestfilter failed with %08x\n", hr
);
1619 if (FAILED(hr
)) goto out
;
1621 hr
= IFilterGraph2_AddFilter(pgraph2
, &ptestfilter2
->IBaseFilter_iface
, wszFilterInstanceName3
);
1622 ok(hr
== S_OK
, "IFilterGraph2_AddFilter failed with %08x\n", hr
);
1624 hr
= IFilterGraph2_Render(pgraph2
, ptestfilter
->ppPins
[0]);
1625 ok(hr
== S_OK
, "IFilterGraph2_Render failed with %08x\n", hr
);
1627 hr
= get_connected_filter_name(ptestfilter
, ConnectedFilterName1
);
1629 IFilterGraph2_Release(pgraph2
);
1631 IBaseFilter_Release(&ptestfilter
->IBaseFilter_iface
);
1633 IBaseFilter_Release(&ptestfilter2
->IBaseFilter_iface
);
1634 ptestfilter2
= NULL
;
1636 if (hr
== E_NOTIMPL
)
1638 win_skip("Needed functions are not implemented\n");
1642 hr
= CoCreateInstance(&CLSID_FilterGraph
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IFilterGraph2
, (LPVOID
*)&pgraph2
);
1643 ok(hr
== S_OK
, "CoCreateInstance failed with %08x\n", hr
);
1644 if (!pgraph2
) goto out
;
1646 hr
= createtestfilter(&GUID_NULL
, PinData1
, &ptestfilter
);
1647 ok(hr
== S_OK
, "createtestfilter failed with %08x\n", hr
);
1648 if (FAILED(hr
)) goto out
;
1650 hr
= IFilterGraph2_AddFilter(pgraph2
, &ptestfilter
->IBaseFilter_iface
, wszFilterInstanceName1
);
1651 ok(hr
== S_OK
, "IFilterGraph2_AddFilter failed with %08x\n", hr
);
1653 hr
= createtestfilter(&GUID_NULL
, PinData3
, &ptestfilter2
);
1654 ok(hr
== S_OK
, "createtestfilter failed with %08x\n", hr
);
1655 if (FAILED(hr
)) goto out
;
1657 hr
= IFilterGraph2_AddFilter(pgraph2
, &ptestfilter2
->IBaseFilter_iface
, wszFilterInstanceName3
);
1658 ok(hr
== S_OK
, "IFilterGraph2_AddFilter failed with %08x\n", hr
);
1660 IBaseFilter_Release(&ptestfilter2
->IBaseFilter_iface
);
1661 ptestfilter2
= NULL
;
1663 hr
= createtestfilter(&GUID_NULL
, PinData2
, &ptestfilter2
);
1664 ok(hr
== S_OK
, "createtestfilter failed with %08x\n", hr
);
1665 if (FAILED(hr
)) goto out
;
1667 hr
= IFilterGraph2_AddFilter(pgraph2
, &ptestfilter2
->IBaseFilter_iface
, wszFilterInstanceName2
);
1668 ok(hr
== S_OK
, "IFilterGraph2_AddFilter failed with %08x\n", hr
);
1670 hr
= IFilterGraph2_Render(pgraph2
, ptestfilter
->ppPins
[0]);
1671 ok(hr
== S_OK
, "IFilterGraph2_Render failed with %08x\n", hr
);
1673 hr
= IFilterGraph2_Disconnect(pgraph2
, NULL
);
1674 ok(hr
== E_POINTER
, "IFilterGraph2_Disconnect failed. Expected E_POINTER, received %08x\n", hr
);
1676 get_connected_filter_name(ptestfilter
, ConnectedFilterName2
);
1677 ok(strcmp(ConnectedFilterName1
, ConnectedFilterName2
),
1678 "expected connected filters to be different but got %s both times\n", ConnectedFilterName1
);
1680 IFilterGraph2_Release(pgraph2
);
1682 IBaseFilter_Release(&ptestfilter
->IBaseFilter_iface
);
1684 IBaseFilter_Release(&ptestfilter2
->IBaseFilter_iface
);
1685 ptestfilter2
= NULL
;
1687 /* Test if any preference is given to existing renderer which renders the pin directly vs
1688 an existing renderer which renders the pin indirectly, through an additional middle filter,
1689 again trying different orders of creation. Native appears not to give a preference. */
1691 hr
= CoCreateInstance(&CLSID_FilterGraph
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IFilterGraph2
, (LPVOID
*)&pgraph2
);
1692 ok(hr
== S_OK
, "CoCreateInstance failed with %08x\n", hr
);
1693 if (!pgraph2
) goto out
;
1695 hr
= createtestfilter(&GUID_NULL
, PinData1
, &ptestfilter
);
1696 ok(hr
== S_OK
, "createtestfilter failed with %08x\n", hr
);
1697 if (FAILED(hr
)) goto out
;
1699 hr
= IFilterGraph2_AddFilter(pgraph2
, &ptestfilter
->IBaseFilter_iface
, wszFilterInstanceName1
);
1700 ok(hr
== S_OK
, "IFilterGraph2_AddFilter failed with %08x\n", hr
);
1702 hr
= createtestfilter(&GUID_NULL
, PinData2
, &ptestfilter2
);
1703 ok(hr
== S_OK
, "createtestfilter failed with %08x\n", hr
);
1704 if (FAILED(hr
)) goto out
;
1706 hr
= IFilterGraph2_AddFilter(pgraph2
, &ptestfilter2
->IBaseFilter_iface
, wszFilterInstanceName2
);
1707 ok(hr
== S_OK
, "IFilterGraph2_AddFilter failed with %08x\n", hr
);
1709 IBaseFilter_Release(&ptestfilter2
->IBaseFilter_iface
);
1710 ptestfilter2
= NULL
;
1712 hr
= createtestfilter(&GUID_NULL
, PinData4
, &ptestfilter2
);
1713 ok(hr
== S_OK
, "createtestfilter failed with %08x\n", hr
);
1714 if (FAILED(hr
)) goto out
;
1716 hr
= IFilterGraph2_AddFilter(pgraph2
, &ptestfilter2
->IBaseFilter_iface
, wszFilterInstanceName3
);
1717 ok(hr
== S_OK
, "IFilterGraph2_AddFilter failed with %08x\n", hr
);
1719 IBaseFilter_Release(&ptestfilter2
->IBaseFilter_iface
);
1720 ptestfilter2
= NULL
;
1722 hr
= createtestfilter(&GUID_NULL
, PinData5
, &ptestfilter2
);
1723 ok(hr
== S_OK
, "createtestfilter failed with %08x\n", hr
);
1724 if (FAILED(hr
)) goto out
;
1726 hr
= IFilterGraph2_AddFilter(pgraph2
, &ptestfilter2
->IBaseFilter_iface
, wszFilterInstanceName4
);
1727 ok(hr
== S_OK
, "IFilterGraph2_AddFilter failed with %08x\n", hr
);
1729 hr
= IFilterGraph2_Render(pgraph2
, ptestfilter
->ppPins
[0]);
1730 ok(hr
== S_OK
, "IFilterGraph2_Render failed with %08x\n", hr
);
1732 get_connected_filter_name(ptestfilter
, ConnectedFilterName1
);
1733 ok(!strcmp(ConnectedFilterName1
, "TestfilterInstance3") || !strcmp(ConnectedFilterName1
, "TestfilterInstance2"),
1734 "unexpected connected filter: %s\n", ConnectedFilterName1
);
1736 IFilterGraph2_Release(pgraph2
);
1738 IBaseFilter_Release(&ptestfilter
->IBaseFilter_iface
);
1740 IBaseFilter_Release(&ptestfilter2
->IBaseFilter_iface
);
1741 ptestfilter2
= NULL
;
1743 hr
= CoCreateInstance(&CLSID_FilterGraph
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IFilterGraph2
, (LPVOID
*)&pgraph2
);
1744 ok(hr
== S_OK
, "CoCreateInstance failed with %08x\n", hr
);
1745 if (!pgraph2
) goto out
;
1747 hr
= createtestfilter(&GUID_NULL
, PinData1
, &ptestfilter
);
1748 ok(hr
== S_OK
, "createtestfilter failed with %08x\n", hr
);
1749 if (FAILED(hr
)) goto out
;
1751 hr
= IFilterGraph2_AddFilter(pgraph2
, &ptestfilter
->IBaseFilter_iface
, wszFilterInstanceName1
);
1752 ok(hr
== S_OK
, "IFilterGraph2_AddFilter failed with %08x\n", hr
);
1754 hr
= createtestfilter(&GUID_NULL
, PinData4
, &ptestfilter2
);
1755 ok(hr
== S_OK
, "createtestfilter failed with %08x\n", hr
);
1756 if (FAILED(hr
)) goto out
;
1758 hr
= IFilterGraph2_AddFilter(pgraph2
, &ptestfilter2
->IBaseFilter_iface
, wszFilterInstanceName3
);
1759 ok(hr
== S_OK
, "IFilterGraph2_AddFilter failed with %08x\n", hr
);
1761 IBaseFilter_Release(&ptestfilter2
->IBaseFilter_iface
);
1762 ptestfilter2
= NULL
;
1764 hr
= createtestfilter(&GUID_NULL
, PinData5
, &ptestfilter2
);
1765 ok(hr
== S_OK
, "createtestfilter failed with %08x\n", hr
);
1766 if (FAILED(hr
)) goto out
;
1768 hr
= IFilterGraph2_AddFilter(pgraph2
, &ptestfilter2
->IBaseFilter_iface
, wszFilterInstanceName4
);
1769 ok(hr
== S_OK
, "IFilterGraph2_AddFilter failed with %08x\n", hr
);
1771 IBaseFilter_Release(&ptestfilter2
->IBaseFilter_iface
);
1772 ptestfilter2
= NULL
;
1774 hr
= createtestfilter(&GUID_NULL
, PinData2
, &ptestfilter2
);
1775 ok(hr
== S_OK
, "createtestfilter failed with %08x\n", hr
);
1776 if (FAILED(hr
)) goto out
;
1778 hr
= IFilterGraph2_AddFilter(pgraph2
, &ptestfilter2
->IBaseFilter_iface
, wszFilterInstanceName2
);
1779 ok(hr
== S_OK
, "IFilterGraph2_AddFilter failed with %08x\n", hr
);
1781 hr
= IFilterGraph2_Render(pgraph2
, ptestfilter
->ppPins
[0]);
1782 ok(hr
== S_OK
, "IFilterGraph2_Render failed with %08x\n", hr
);
1784 get_connected_filter_name(ptestfilter
, ConnectedFilterName2
);
1785 ok(!strcmp(ConnectedFilterName2
, "TestfilterInstance3") || !strcmp(ConnectedFilterName2
, "TestfilterInstance2"),
1786 "unexpected connected filter: %s\n", ConnectedFilterName2
);
1787 ok(strcmp(ConnectedFilterName1
, ConnectedFilterName2
),
1788 "expected connected filters to be different but got %s both times\n", ConnectedFilterName1
);
1790 IFilterGraph2_Release(pgraph2
);
1792 IBaseFilter_Release(&ptestfilter
->IBaseFilter_iface
);
1794 IBaseFilter_Release(&ptestfilter2
->IBaseFilter_iface
);
1795 ptestfilter2
= NULL
;
1797 /* Test if renderers are tried before non-renderers (intermediary filters). */
1798 hr
= CoCreateInstance(&CLSID_FilterGraph
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IFilterGraph2
, (LPVOID
*)&pgraph2
);
1799 ok(hr
== S_OK
, "CoCreateInstance failed with %08x\n", hr
);
1800 if (!pgraph2
) goto out
;
1802 hr
= CoCreateInstance(&CLSID_FilterMapper2
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IFilterMapper2
, (LPVOID
*)&pMapper2
);
1803 ok(hr
== S_OK
, "CoCreateInstance failed with %08x\n", hr
);
1804 if (!pMapper2
) goto out
;
1806 hr
= createtestfilter(&GUID_NULL
, PinData1
, &ptestfilter
);
1807 ok(hr
== S_OK
, "createtestfilter failed with %08x\n", hr
);
1808 if (FAILED(hr
)) goto out
;
1810 hr
= IFilterGraph2_AddFilter(pgraph2
, &ptestfilter
->IBaseFilter_iface
, wszFilterInstanceName1
);
1811 ok(hr
== S_OK
, "IFilterGraph2_AddFilter failed with %08x\n", hr
);
1813 /* Register our filters with COM and with Filtermapper. */
1814 hr
= CoRegisterClassObject(Filter1ClassFactory
.clsid
,
1815 (IUnknown
*)&Filter1ClassFactory
.IClassFactory_iface
, CLSCTX_INPROC_SERVER
,
1816 REGCLS_MULTIPLEUSE
, &cookie1
);
1817 ok(hr
== S_OK
, "CoRegisterClassObject failed with %08x\n", hr
);
1818 if (FAILED(hr
)) goto out
;
1819 hr
= CoRegisterClassObject(Filter2ClassFactory
.clsid
,
1820 (IUnknown
*)&Filter2ClassFactory
.IClassFactory_iface
, CLSCTX_INPROC_SERVER
,
1821 REGCLS_MULTIPLEUSE
, &cookie2
);
1822 ok(hr
== S_OK
, "CoRegisterClassObject failed with %08x\n", hr
);
1823 if (FAILED(hr
)) goto out
;
1824 hr
= CoRegisterClassObject(Filter3ClassFactory
.clsid
,
1825 (IUnknown
*)&Filter3ClassFactory
.IClassFactory_iface
, CLSCTX_INPROC_SERVER
,
1826 REGCLS_MULTIPLEUSE
, &cookie3
);
1827 ok(hr
== S_OK
, "CoRegisterClassObject failed with %08x\n", hr
);
1828 if (FAILED(hr
)) goto out
;
1831 rgf2
.dwMerit
= MERIT_UNLIKELY
;
1832 S2(U(rgf2
)).cPins2
= 1;
1833 S2(U(rgf2
)).rgPins2
= rgPins2
;
1834 rgPins2
[0].dwFlags
= REG_PINFLAG_B_RENDERER
;
1835 rgPins2
[0].cInstances
= 1;
1836 rgPins2
[0].nMediaTypes
= 1;
1837 rgPins2
[0].lpMediaType
= &rgPinType
[0];
1838 rgPins2
[0].nMediums
= 0;
1839 rgPins2
[0].lpMedium
= NULL
;
1840 rgPins2
[0].clsPinCategory
= NULL
;
1841 rgPinType
[0].clsMajorType
= &MEDIATYPE_Video
;
1842 rgPinType
[0].clsMinorType
= &mediasubtype1
;
1844 hr
= IFilterMapper2_RegisterFilter(pMapper2
, &CLSID_TestFilter2
, wszFilterInstanceName2
, NULL
,
1845 &CLSID_LegacyAmFilterCategory
, NULL
, &rgf2
);
1846 if (hr
== E_ACCESSDENIED
)
1847 skip("Not authorized to register filters\n");
1850 ok(hr
== S_OK
, "IFilterMapper2_RegisterFilter failed with %x\n", hr
);
1852 rgf2
.dwMerit
= MERIT_PREFERRED
;
1853 rgPinType
[0].clsMinorType
= &mediasubtype2
;
1855 hr
= IFilterMapper2_RegisterFilter(pMapper2
, &CLSID_TestFilter4
, wszFilterInstanceName4
, NULL
,
1856 &CLSID_LegacyAmFilterCategory
, NULL
, &rgf2
);
1857 ok(hr
== S_OK
, "IFilterMapper2_RegisterFilter failed with %x\n", hr
);
1859 S2(U(rgf2
)).cPins2
= 2;
1860 rgPins2
[0].dwFlags
= 0;
1861 rgPinType
[0].clsMinorType
= &mediasubtype1
;
1863 rgPins2
[1].dwFlags
= REG_PINFLAG_B_OUTPUT
;
1864 rgPins2
[1].cInstances
= 1;
1865 rgPins2
[1].nMediaTypes
= 1;
1866 rgPins2
[1].lpMediaType
= &rgPinType
[1];
1867 rgPins2
[1].nMediums
= 0;
1868 rgPins2
[1].lpMedium
= NULL
;
1869 rgPins2
[1].clsPinCategory
= NULL
;
1870 rgPinType
[1].clsMajorType
= &MEDIATYPE_Video
;
1871 rgPinType
[1].clsMinorType
= &mediasubtype2
;
1873 hr
= IFilterMapper2_RegisterFilter(pMapper2
, &CLSID_TestFilter3
, wszFilterInstanceName3
, NULL
,
1874 &CLSID_LegacyAmFilterCategory
, NULL
, &rgf2
);
1875 ok(hr
== S_OK
, "IFilterMapper2_RegisterFilter failed with %x\n", hr
);
1877 hr
= IFilterGraph2_Render(pgraph2
, ptestfilter
->ppPins
[0]);
1878 ok(hr
== S_OK
, "IFilterGraph2_Render failed with %08x\n", hr
);
1880 get_connected_filter_name(ptestfilter
, ConnectedFilterName1
);
1881 ok(!strcmp(ConnectedFilterName1
, "TestfilterInstance3"),
1882 "unexpected connected filter: %s\n", ConnectedFilterName1
);
1884 hr
= IFilterMapper2_UnregisterFilter(pMapper2
, &CLSID_LegacyAmFilterCategory
, NULL
,
1885 &CLSID_TestFilter2
);
1886 ok(hr
== S_OK
, "IFilterMapper2_UnregisterFilter failed with %x\n", hr
);
1887 hr
= IFilterMapper2_UnregisterFilter(pMapper2
, &CLSID_LegacyAmFilterCategory
, NULL
,
1888 &CLSID_TestFilter3
);
1889 ok(hr
== S_OK
, "IFilterMapper2_UnregisterFilter failed with %x\n", hr
);
1890 hr
= IFilterMapper2_UnregisterFilter(pMapper2
, &CLSID_LegacyAmFilterCategory
, NULL
,
1891 &CLSID_TestFilter4
);
1892 ok(hr
== S_OK
, "IFilterMapper2_UnregisterFilter failed with %x\n", hr
);
1897 if (ptestfilter
) IBaseFilter_Release(&ptestfilter
->IBaseFilter_iface
);
1898 if (ptestfilter2
) IBaseFilter_Release(&ptestfilter2
->IBaseFilter_iface
);
1899 if (pgraph2
) IFilterGraph2_Release(pgraph2
);
1900 if (pMapper2
) IFilterMapper2_Release(pMapper2
);
1902 hr
= CoRevokeClassObject(cookie1
);
1903 ok(hr
== S_OK
, "CoRevokeClassObject failed with %08x\n", hr
);
1904 hr
= CoRevokeClassObject(cookie2
);
1905 ok(hr
== S_OK
, "CoRevokeClassObject failed with %08x\n", hr
);
1906 hr
= CoRevokeClassObject(cookie3
);
1907 ok(hr
== S_OK
, "CoRevokeClassObject failed with %08x\n", hr
);
1910 typedef struct IUnknownImpl
1912 IUnknown IUnknown_iface
;
1917 static IUnknownImpl
*IUnknownImpl_from_iface(IUnknown
* iface
)
1919 return CONTAINING_RECORD(iface
, IUnknownImpl
, IUnknown_iface
);
1922 static HRESULT WINAPI
IUnknownImpl_QueryInterface(IUnknown
* iface
, REFIID riid
, LPVOID
* ppv
)
1924 ok(0, "QueryInterface should not be called for %s\n", wine_dbgstr_guid(riid
));
1925 return E_NOINTERFACE
;
1928 static ULONG WINAPI
IUnknownImpl_AddRef(IUnknown
* iface
)
1930 IUnknownImpl
*This
= IUnknownImpl_from_iface(iface
);
1931 This
->AddRef_called
++;
1935 static ULONG WINAPI
IUnknownImpl_Release(IUnknown
* iface
)
1937 IUnknownImpl
*This
= IUnknownImpl_from_iface(iface
);
1938 This
->Release_called
++;
1942 static CONST_VTBL IUnknownVtbl IUnknownImpl_Vtbl
=
1944 IUnknownImpl_QueryInterface
,
1945 IUnknownImpl_AddRef
,
1946 IUnknownImpl_Release
1949 static void test_aggregate_filter_graph(void)
1954 IUnknownImpl unk_outer
= { { &IUnknownImpl_Vtbl
}, 0, 0 };
1956 hr
= CoCreateInstance(&CLSID_FilterGraph
, &unk_outer
.IUnknown_iface
, CLSCTX_INPROC_SERVER
,
1957 &IID_IUnknown
, (void **)&pgraph
);
1958 ok(hr
== S_OK
, "CoCreateInstance returned %x\n", hr
);
1959 ok(pgraph
!= &unk_outer
.IUnknown_iface
, "pgraph = %p, expected not %p\n", pgraph
, &unk_outer
.IUnknown_iface
);
1961 hr
= IUnknown_QueryInterface(pgraph
, &IID_IUnknown
, (void **)&punk
);
1962 ok(hr
== S_OK
, "CoCreateInstance returned %x\n", hr
);
1963 ok(punk
!= &unk_outer
.IUnknown_iface
, "punk = %p, expected not %p\n", punk
, &unk_outer
.IUnknown_iface
);
1964 IUnknown_Release(punk
);
1966 ok(unk_outer
.AddRef_called
== 0, "IUnknownImpl_AddRef called %d times\n", unk_outer
.AddRef_called
);
1967 ok(unk_outer
.Release_called
== 0, "IUnknownImpl_Release called %d times\n", unk_outer
.Release_called
);
1968 unk_outer
.AddRef_called
= 0;
1969 unk_outer
.Release_called
= 0;
1971 hr
= IUnknown_QueryInterface(pgraph
, &IID_IFilterMapper
, (void **)&punk
);
1972 ok(hr
== S_OK
, "CoCreateInstance returned %x\n", hr
);
1973 ok(punk
!= &unk_outer
.IUnknown_iface
, "punk = %p, expected not %p\n", punk
, &unk_outer
.IUnknown_iface
);
1974 IUnknown_Release(punk
);
1976 ok(unk_outer
.AddRef_called
== 1, "IUnknownImpl_AddRef called %d times\n", unk_outer
.AddRef_called
);
1977 ok(unk_outer
.Release_called
== 1, "IUnknownImpl_Release called %d times\n", unk_outer
.Release_called
);
1978 unk_outer
.AddRef_called
= 0;
1979 unk_outer
.Release_called
= 0;
1981 hr
= IUnknown_QueryInterface(pgraph
, &IID_IFilterMapper2
, (void **)&punk
);
1982 ok(hr
== S_OK
, "CoCreateInstance returned %x\n", hr
);
1983 ok(punk
!= &unk_outer
.IUnknown_iface
, "punk = %p, expected not %p\n", punk
, &unk_outer
.IUnknown_iface
);
1984 IUnknown_Release(punk
);
1986 ok(unk_outer
.AddRef_called
== 1, "IUnknownImpl_AddRef called %d times\n", unk_outer
.AddRef_called
);
1987 ok(unk_outer
.Release_called
== 1, "IUnknownImpl_Release called %d times\n", unk_outer
.Release_called
);
1988 unk_outer
.AddRef_called
= 0;
1989 unk_outer
.Release_called
= 0;
1991 hr
= IUnknown_QueryInterface(pgraph
, &IID_IFilterMapper3
, (void **)&punk
);
1992 ok(hr
== S_OK
, "CoCreateInstance returned %x\n", hr
);
1993 ok(punk
!= &unk_outer
.IUnknown_iface
, "punk = %p, expected not %p\n", punk
, &unk_outer
.IUnknown_iface
);
1994 IUnknown_Release(punk
);
1996 ok(unk_outer
.AddRef_called
== 1, "IUnknownImpl_AddRef called %d times\n", unk_outer
.AddRef_called
);
1997 ok(unk_outer
.Release_called
== 1, "IUnknownImpl_Release called %d times\n", unk_outer
.Release_called
);
1999 IUnknown_Release(pgraph
);
2002 START_TEST(filtergraph
)
2005 CoInitializeEx(NULL
, COINIT_MULTITHREADED
);
2006 hr
= CoCreateInstance(&CLSID_FilterGraph
, NULL
, CLSCTX_INPROC_SERVER
,
2007 &IID_IGraphBuilder
, (LPVOID
*)&pgraph
);
2009 skip("Creating filtergraph returned %08x, skipping tests\n", hr
);
2012 IGraphBuilder_Release(pgraph
);
2013 test_render_run(avifile
);
2014 test_render_run(mpegfile
);
2015 test_graph_builder();
2016 test_graph_builder_addfilter();
2017 test_mediacontrol();
2018 test_filter_graph2();
2019 test_render_filter_priority();
2020 test_aggregate_filter_graph();