Wine-Devel
By thread
wine-devel@list.winehq.org
By month
Messages by month
- ----- 2026 -----
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2025 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2007 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2006 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2005 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2004 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2003 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2002 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2001 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
September 2018
- 70 participants
- 1549 messages
Re: [PATCH 1/6] quartz/tests: Add some tests for IFilterGraph_EnumFilters().
by Zebediah Figura
On 18/09/18 05:31, Nikolay Sivov wrote:
> On 09/18/2018 08:24 AM, Zebediah Figura wrote:
>
>> + ref = IFilterGraph2_Release(graph);
>> + ok(!ref, "Got outstanding refcount %d.\n", hr);
> Wrong argument here.
>
>
Thanks for the catch, resent.
Sept. 18, 2018
[PATCH v2 6/6] quartz/tests: Rewrite test_render_filter_priority().
by Zebediah Figura
Signed-off-by: Zebediah Figura <z.figura12(a)gmail.com>
---
I have attempted to rewrite the test to be simpler, while still proving the
same set of results as 236451443 showed. A secondary purpose of this patch is
to take steps to make the test filter more generically usable, as I intend to
do in following tests.
The previous test attempted to demonstrate that no preference is given to
exact match over wildcard match. This test in fact proves a stronger result:
that Render() only ever calls Connect() with a NULL media type, so it never
attempts an exact match, and it never calls EnumMediaTypes() on the receiving
pin, so it cannot guess that a wildcard match has been made. The actual
negotation of the format type is left up entirely to the source pin; the
filter graph only uses EnumMediaTypes() to find matching filters from the
registry.
dlls/quartz/tests/filtergraph.c | 2134 ++++++++++++++-------------------------
1 file changed, 733 insertions(+), 1401 deletions(-)
diff --git a/dlls/quartz/tests/filtergraph.c b/dlls/quartz/tests/filtergraph.c
index 51196c1..3804058 100644
--- a/dlls/quartz/tests/filtergraph.c
+++ b/dlls/quartz/tests/filtergraph.c
@@ -22,9 +22,9 @@
#define COBJMACROS
#define CONST_VTABLE
-#include "wine/test.h"
#include "dshow.h"
-#include "control.h"
+#include "wine/heap.h"
+#include "wine/test.h"
typedef struct TestFilterImpl
{
@@ -783,1511 +783,843 @@ static void test_graph_builder(void)
IGraphBuilder_Release(pgraph);
}
-/* IEnumMediaTypes implementation (supporting code for Render() test.) */
-static void FreeMediaType(AM_MEDIA_TYPE * pMediaType)
-{
- if (pMediaType->pbFormat)
- {
- CoTaskMemFree(pMediaType->pbFormat);
- pMediaType->pbFormat = NULL;
- }
- if (pMediaType->pUnk)
- {
- IUnknown_Release(pMediaType->pUnk);
- pMediaType->pUnk = NULL;
- }
-}
-
-static HRESULT CopyMediaType(AM_MEDIA_TYPE * pDest, const AM_MEDIA_TYPE *pSrc)
-{
- *pDest = *pSrc;
- if (!pSrc->pbFormat) return S_OK;
- if (!(pDest->pbFormat = CoTaskMemAlloc(pSrc->cbFormat)))
- return E_OUTOFMEMORY;
- memcpy(pDest->pbFormat, pSrc->pbFormat, pSrc->cbFormat);
- if (pDest->pUnk)
- IUnknown_AddRef(pDest->pUnk);
- return S_OK;
-}
-
-static AM_MEDIA_TYPE * CreateMediaType(AM_MEDIA_TYPE const * pSrc)
-{
- AM_MEDIA_TYPE * pDest;
-
- pDest = CoTaskMemAlloc(sizeof(AM_MEDIA_TYPE));
- if (!pDest)
- return NULL;
-
- if (FAILED(CopyMediaType(pDest, pSrc)))
- {
- CoTaskMemFree(pDest);
- return NULL;
- }
-
- return pDest;
-}
-
-static BOOL CompareMediaTypes(const AM_MEDIA_TYPE * pmt1, const AM_MEDIA_TYPE * pmt2, BOOL bWildcards)
-{
- return (((bWildcards && (IsEqualGUID(&pmt1->majortype, &GUID_NULL) || IsEqualGUID(&pmt2->majortype, &GUID_NULL))) || IsEqualGUID(&pmt1->majortype, &pmt2->majortype)) &&
- ((bWildcards && (IsEqualGUID(&pmt1->subtype, &GUID_NULL) || IsEqualGUID(&pmt2->subtype, &GUID_NULL))) || IsEqualGUID(&pmt1->subtype, &pmt2->subtype)));
-}
-
-static void DeleteMediaType(AM_MEDIA_TYPE * pMediaType)
-{
- FreeMediaType(pMediaType);
- CoTaskMemFree(pMediaType);
-}
-
-typedef struct IEnumMediaTypesImpl
-{
- IEnumMediaTypes IEnumMediaTypes_iface;
- LONG refCount;
- AM_MEDIA_TYPE *pMediaTypes;
- ULONG cMediaTypes;
- ULONG uIndex;
-} IEnumMediaTypesImpl;
-
-static const struct IEnumMediaTypesVtbl IEnumMediaTypesImpl_Vtbl;
-
-static inline IEnumMediaTypesImpl *impl_from_IEnumMediaTypes(IEnumMediaTypes *iface)
-{
- return CONTAINING_RECORD(iface, IEnumMediaTypesImpl, IEnumMediaTypes_iface);
-}
-
-static HRESULT IEnumMediaTypesImpl_Construct(const AM_MEDIA_TYPE * pMediaTypes, ULONG cMediaTypes, IEnumMediaTypes ** ppEnum)
-{
- ULONG i;
- IEnumMediaTypesImpl * pEnumMediaTypes = CoTaskMemAlloc(sizeof(IEnumMediaTypesImpl));
-
- if (!pEnumMediaTypes)
- {
- *ppEnum = NULL;
- return E_OUTOFMEMORY;
- }
- pEnumMediaTypes->IEnumMediaTypes_iface.lpVtbl = &IEnumMediaTypesImpl_Vtbl;
- pEnumMediaTypes->refCount = 1;
- pEnumMediaTypes->uIndex = 0;
- pEnumMediaTypes->cMediaTypes = cMediaTypes;
- pEnumMediaTypes->pMediaTypes = CoTaskMemAlloc(sizeof(AM_MEDIA_TYPE) * cMediaTypes);
- for (i = 0; i < cMediaTypes; i++)
- if (FAILED(CopyMediaType(&pEnumMediaTypes->pMediaTypes[i], &pMediaTypes[i])))
- {
- while (i--)
- FreeMediaType(&pEnumMediaTypes->pMediaTypes[i]);
- CoTaskMemFree(pEnumMediaTypes->pMediaTypes);
- return E_OUTOFMEMORY;
- }
- *ppEnum = &pEnumMediaTypes->IEnumMediaTypes_iface;
- return S_OK;
-}
-
-static HRESULT WINAPI IEnumMediaTypesImpl_QueryInterface(IEnumMediaTypes * iface, REFIID riid, LPVOID * ppv)
-{
- *ppv = NULL;
-
- if (IsEqualIID(riid, &IID_IUnknown))
- *ppv = iface;
- else if (IsEqualIID(riid, &IID_IEnumMediaTypes))
- *ppv = iface;
-
- if (*ppv)
- {
- IUnknown_AddRef((IUnknown *)(*ppv));
- return S_OK;
- }
-
- return E_NOINTERFACE;
-}
-
-static ULONG WINAPI IEnumMediaTypesImpl_AddRef(IEnumMediaTypes * iface)
-{
- IEnumMediaTypesImpl *This = impl_from_IEnumMediaTypes(iface);
- ULONG refCount = InterlockedIncrement(&This->refCount);
-
- return refCount;
-}
-
-static ULONG WINAPI IEnumMediaTypesImpl_Release(IEnumMediaTypes * iface)
-{
- IEnumMediaTypesImpl *This = impl_from_IEnumMediaTypes(iface);
- ULONG refCount = InterlockedDecrement(&This->refCount);
-
- if (!refCount)
- {
- int i;
- for (i = 0; i < This->cMediaTypes; i++)
- FreeMediaType(&This->pMediaTypes[i]);
- CoTaskMemFree(This->pMediaTypes);
- CoTaskMemFree(This);
- }
- return refCount;
-}
-
-static HRESULT WINAPI IEnumMediaTypesImpl_Next(IEnumMediaTypes * iface, ULONG cMediaTypes, AM_MEDIA_TYPE ** ppMediaTypes, ULONG * pcFetched)
-{
- ULONG cFetched;
- IEnumMediaTypesImpl *This = impl_from_IEnumMediaTypes(iface);
-
- cFetched = min(This->cMediaTypes, This->uIndex + cMediaTypes) - This->uIndex;
-
- if (cFetched > 0)
- {
- ULONG i;
- for (i = 0; i < cFetched; i++)
- if (!(ppMediaTypes[i] = CreateMediaType(&This->pMediaTypes[This->uIndex + i])))
- {
- while (i--)
- DeleteMediaType(ppMediaTypes[i]);
- *pcFetched = 0;
- return E_OUTOFMEMORY;
- }
- }
-
- if ((cMediaTypes != 1) || pcFetched)
- *pcFetched = cFetched;
-
- This->uIndex += cFetched;
-
- if (cFetched != cMediaTypes)
- return S_FALSE;
- return S_OK;
-}
-
-static HRESULT WINAPI IEnumMediaTypesImpl_Skip(IEnumMediaTypes * iface, ULONG cMediaTypes)
-{
- IEnumMediaTypesImpl *This = impl_from_IEnumMediaTypes(iface);
-
- if (This->uIndex + cMediaTypes < This->cMediaTypes)
- {
- This->uIndex += cMediaTypes;
- return S_OK;
- }
- return S_FALSE;
-}
-
-static HRESULT WINAPI IEnumMediaTypesImpl_Reset(IEnumMediaTypes * iface)
-{
- IEnumMediaTypesImpl *This = impl_from_IEnumMediaTypes(iface);
-
- This->uIndex = 0;
- return S_OK;
-}
-
-static HRESULT WINAPI IEnumMediaTypesImpl_Clone(IEnumMediaTypes * iface, IEnumMediaTypes ** ppEnum)
-{
- HRESULT hr;
- IEnumMediaTypesImpl *This = impl_from_IEnumMediaTypes(iface);
-
- hr = IEnumMediaTypesImpl_Construct(This->pMediaTypes, This->cMediaTypes, ppEnum);
- if (FAILED(hr))
- return hr;
- return IEnumMediaTypes_Skip(*ppEnum, This->uIndex);
-}
-
-static const IEnumMediaTypesVtbl IEnumMediaTypesImpl_Vtbl =
-{
- IEnumMediaTypesImpl_QueryInterface,
- IEnumMediaTypesImpl_AddRef,
- IEnumMediaTypesImpl_Release,
- IEnumMediaTypesImpl_Next,
- IEnumMediaTypesImpl_Skip,
- IEnumMediaTypesImpl_Reset,
- IEnumMediaTypesImpl_Clone
-};
-
-/* Implementation of a very stripped down pin for the test filter. Just enough
- functionality for connecting and Render() to work. */
-
-static void Copy_PinInfo(PIN_INFO * pDest, const PIN_INFO * pSrc)
-{
- lstrcpyW(pDest->achName, pSrc->achName);
- pDest->dir = pSrc->dir;
- pDest->pFilter = pSrc->pFilter;
-}
-
-typedef struct ITestPinImpl
+struct testpin
{
IPin IPin_iface;
- LONG refCount;
- LPCRITICAL_SECTION pCritSec;
- PIN_INFO pinInfo;
- IPin * pConnectedTo;
- AM_MEDIA_TYPE mtCurrent;
- LPVOID pUserData;
-} ITestPinImpl;
+ LONG ref;
+ PIN_DIRECTION dir;
+ IBaseFilter *filter;
+ IPin *peer;
-static inline ITestPinImpl *impl_from_IPin(IPin *iface)
+ IEnumMediaTypes IEnumMediaTypes_iface;
+ const AM_MEDIA_TYPE *types;
+ unsigned int type_count, enum_idx;
+};
+
+static inline struct testpin *impl_from_IEnumMediaTypes(IEnumMediaTypes *iface)
{
- return CONTAINING_RECORD(iface, ITestPinImpl, IPin_iface);
+ return CONTAINING_RECORD(iface, struct testpin, IEnumMediaTypes_iface);
}
-static HRESULT WINAPI TestFilter_Pin_QueryInterface(IPin * iface, REFIID riid, LPVOID * ppv)
+static HRESULT WINAPI testenummt_QueryInterface(IEnumMediaTypes *iface, REFIID iid, void **out)
{
- *ppv = NULL;
-
- if (IsEqualIID(riid, &IID_IUnknown))
- *ppv = iface;
- else if (IsEqualIID(riid, &IID_IPin))
- *ppv = iface;
-
- if (*ppv)
- {
- IUnknown_AddRef((IUnknown *)(*ppv));
- return S_OK;
- }
+ struct testpin *pin = impl_from_IEnumMediaTypes(iface);
+ if (winetest_debug > 1) trace("%p->QueryInterface(%s)\n", pin, wine_dbgstr_guid(iid));
+ *out = NULL;
return E_NOINTERFACE;
}
-static ULONG WINAPI TestFilter_Pin_AddRef(IPin * iface)
+static ULONG WINAPI testenummt_AddRef(IEnumMediaTypes *iface)
{
- ITestPinImpl *This = impl_from_IPin(iface);
- ULONG refCount = InterlockedIncrement(&This->refCount);
- return refCount;
+ struct testpin *pin = impl_from_IEnumMediaTypes(iface);
+ return InterlockedIncrement(&pin->ref);
}
-static ULONG WINAPI TestFilter_Pin_Release(IPin * iface)
+static ULONG WINAPI testenummt_Release(IEnumMediaTypes *iface)
{
- ITestPinImpl *This = impl_from_IPin(iface);
- ULONG refCount = InterlockedDecrement(&This->refCount);
+ struct testpin *pin = impl_from_IEnumMediaTypes(iface);
+ return InterlockedDecrement(&pin->ref);
+}
- if (!refCount)
+static HRESULT WINAPI testenummt_Next(IEnumMediaTypes *iface, ULONG count, AM_MEDIA_TYPE **out, ULONG *fetched)
+{
+ struct testpin *pin = impl_from_IEnumMediaTypes(iface);
+ unsigned int i;
+
+ for (i = 0; i < count; ++i)
{
- FreeMediaType(&This->mtCurrent);
- CoTaskMemFree(This);
- return 0;
- }
- else
- return refCount;
-}
-
-static HRESULT WINAPI TestFilter_InputPin_Connect(IPin * iface, IPin * pConnector, const AM_MEDIA_TYPE * pmt)
-{
- return E_UNEXPECTED;
-}
-
-static HRESULT WINAPI TestFilter_InputPin_ReceiveConnection(IPin * iface, IPin * pReceivePin, const AM_MEDIA_TYPE * pmt)
-{
- ITestPinImpl *This = impl_from_IPin(iface);
- PIN_DIRECTION pindirReceive;
- HRESULT hr = S_OK;
-
- EnterCriticalSection(This->pCritSec);
- {
- if (!(IsEqualIID(&pmt->majortype, &This->mtCurrent.majortype) && (IsEqualIID(&pmt->subtype, &This->mtCurrent.subtype) ||
- IsEqualIID(&GUID_NULL, &This->mtCurrent.subtype))))
- hr = VFW_E_TYPE_NOT_ACCEPTED;
-
- if (This->pConnectedTo)
- hr = VFW_E_ALREADY_CONNECTED;
-
- if (SUCCEEDED(hr))
- {
- IPin_QueryDirection(pReceivePin, &pindirReceive);
-
- if (pindirReceive != PINDIR_OUTPUT)
- {
- hr = VFW_E_INVALID_DIRECTION;
- }
- }
-
- if (SUCCEEDED(hr))
- {
- CopyMediaType(&This->mtCurrent, pmt);
- This->pConnectedTo = pReceivePin;
- IPin_AddRef(pReceivePin);
- }
- }
- LeaveCriticalSection(This->pCritSec);
-
- return hr;
-}
-
-static HRESULT WINAPI TestFilter_Pin_Disconnect(IPin * iface)
-{
- HRESULT hr;
- ITestPinImpl *This = impl_from_IPin(iface);
-
- EnterCriticalSection(This->pCritSec);
- {
- if (This->pConnectedTo)
- {
- IPin_Release(This->pConnectedTo);
- This->pConnectedTo = NULL;
- hr = S_OK;
- }
- else
- hr = S_FALSE;
- }
- LeaveCriticalSection(This->pCritSec);
-
- return hr;
-}
-
-static HRESULT WINAPI TestFilter_Pin_ConnectedTo(IPin * iface, IPin ** ppPin)
-{
- HRESULT hr;
- ITestPinImpl *This = impl_from_IPin(iface);
-
- EnterCriticalSection(This->pCritSec);
- {
- if (This->pConnectedTo)
- {
- *ppPin = This->pConnectedTo;
- IPin_AddRef(*ppPin);
- hr = S_OK;
- }
- else
- {
- hr = VFW_E_NOT_CONNECTED;
- *ppPin = NULL;
- }
- }
- LeaveCriticalSection(This->pCritSec);
-
- return hr;
-}
-
-static HRESULT WINAPI TestFilter_Pin_ConnectionMediaType(IPin * iface, AM_MEDIA_TYPE * pmt)
-{
- HRESULT hr;
- ITestPinImpl *This = impl_from_IPin(iface);
-
- EnterCriticalSection(This->pCritSec);
- {
- if (This->pConnectedTo)
- {
- CopyMediaType(pmt, &This->mtCurrent);
- hr = S_OK;
- }
- else
- {
- ZeroMemory(pmt, sizeof(*pmt));
- hr = VFW_E_NOT_CONNECTED;
- }
- }
- LeaveCriticalSection(This->pCritSec);
-
- return hr;
-}
-
-static HRESULT WINAPI TestFilter_Pin_QueryPinInfo(IPin * iface, PIN_INFO * pInfo)
-{
- ITestPinImpl *This = impl_from_IPin(iface);
-
- Copy_PinInfo(pInfo, &This->pinInfo);
- IBaseFilter_AddRef(pInfo->pFilter);
-
- return S_OK;
-}
-
-static HRESULT WINAPI TestFilter_Pin_QueryDirection(IPin * iface, PIN_DIRECTION * pPinDir)
-{
- ITestPinImpl *This = impl_from_IPin(iface);
-
- *pPinDir = This->pinInfo.dir;
-
- return S_OK;
-}
-
-static HRESULT WINAPI TestFilter_Pin_QueryId(IPin * iface, LPWSTR * Id)
-{
- return E_NOTIMPL;
-}
-
-static HRESULT WINAPI TestFilter_Pin_QueryAccept(IPin * iface, const AM_MEDIA_TYPE * pmt)
-{
- ITestPinImpl *This = impl_from_IPin(iface);
-
- if (IsEqualIID(&pmt->majortype, &This->mtCurrent.majortype) && (IsEqualIID(&pmt->subtype, &This->mtCurrent.subtype) ||
- IsEqualIID(&GUID_NULL, &This->mtCurrent.subtype)))
- return S_OK;
- else
- return VFW_E_TYPE_NOT_ACCEPTED;
-}
-
-static HRESULT WINAPI TestFilter_Pin_EnumMediaTypes(IPin * iface, IEnumMediaTypes ** ppEnum)
-{
- ITestPinImpl *This = impl_from_IPin(iface);
-
- return IEnumMediaTypesImpl_Construct(&This->mtCurrent, 1, ppEnum);
-}
-
-static HRESULT WINAPI TestFilter_Pin_QueryInternalConnections(IPin * iface, IPin ** apPin, ULONG * cPin)
-{
- return E_NOTIMPL;
-}
-
-static HRESULT WINAPI TestFilter_Pin_BeginFlush(IPin * iface)
-{
- return E_NOTIMPL;
-}
-
-static HRESULT WINAPI TestFilter_Pin_EndFlush(IPin * iface)
-{
- return E_NOTIMPL;
-}
-
-static HRESULT WINAPI TestFilter_Pin_NewSegment(IPin * iface, REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate)
-{
- return E_NOTIMPL;
-}
-
-static HRESULT WINAPI TestFilter_Pin_EndOfStream(IPin * iface)
-{
- return E_NOTIMPL;
-}
-
-static const IPinVtbl TestFilter_InputPin_Vtbl =
-{
- TestFilter_Pin_QueryInterface,
- TestFilter_Pin_AddRef,
- TestFilter_Pin_Release,
- TestFilter_InputPin_Connect,
- TestFilter_InputPin_ReceiveConnection,
- TestFilter_Pin_Disconnect,
- TestFilter_Pin_ConnectedTo,
- TestFilter_Pin_ConnectionMediaType,
- TestFilter_Pin_QueryPinInfo,
- TestFilter_Pin_QueryDirection,
- TestFilter_Pin_QueryId,
- TestFilter_Pin_QueryAccept,
- TestFilter_Pin_EnumMediaTypes,
- TestFilter_Pin_QueryInternalConnections,
- TestFilter_Pin_EndOfStream,
- TestFilter_Pin_BeginFlush,
- TestFilter_Pin_EndFlush,
- TestFilter_Pin_NewSegment
-};
-
-static HRESULT WINAPI TestFilter_OutputPin_ReceiveConnection(IPin * iface, IPin * pReceivePin, const AM_MEDIA_TYPE * pmt)
-{
- return E_UNEXPECTED;
-}
-
-/* Private helper function */
-static HRESULT TestFilter_OutputPin_ConnectSpecific(ITestPinImpl * This, IPin * pReceivePin,
- const AM_MEDIA_TYPE * pmt)
-{
- HRESULT hr;
-
- This->pConnectedTo = pReceivePin;
- IPin_AddRef(pReceivePin);
-
- hr = IPin_ReceiveConnection(pReceivePin, &This->IPin_iface, pmt);
-
- if (FAILED(hr))
- {
- IPin_Release(This->pConnectedTo);
- This->pConnectedTo = NULL;
- }
-
- return hr;
-}
-
-static HRESULT WINAPI TestFilter_OutputPin_Connect(IPin * iface, IPin * pReceivePin, const AM_MEDIA_TYPE * pmt)
-{
- ITestPinImpl *This = impl_from_IPin(iface);
- HRESULT hr;
-
- EnterCriticalSection(This->pCritSec);
- {
- /* if we have been a specific type to connect with, then we can either connect
- * with that or fail. We cannot choose different AM_MEDIA_TYPE */
- if (pmt && !IsEqualGUID(&pmt->majortype, &GUID_NULL) && !IsEqualGUID(&pmt->subtype, &GUID_NULL))
- hr = TestFilter_OutputPin_ConnectSpecific(This, pReceivePin, pmt);
- else
- {
- if (( !pmt || CompareMediaTypes(pmt, &This->mtCurrent, TRUE) ) &&
- (TestFilter_OutputPin_ConnectSpecific(This, pReceivePin, &This->mtCurrent) == S_OK))
- hr = S_OK;
- else hr = VFW_E_NO_ACCEPTABLE_TYPES;
- } /* if negotiate media type */
- } /* if succeeded */
- LeaveCriticalSection(This->pCritSec);
-
- return hr;
-}
-
-static const IPinVtbl TestFilter_OutputPin_Vtbl =
-{
- TestFilter_Pin_QueryInterface,
- TestFilter_Pin_AddRef,
- TestFilter_Pin_Release,
- TestFilter_OutputPin_Connect,
- TestFilter_OutputPin_ReceiveConnection,
- TestFilter_Pin_Disconnect,
- TestFilter_Pin_ConnectedTo,
- TestFilter_Pin_ConnectionMediaType,
- TestFilter_Pin_QueryPinInfo,
- TestFilter_Pin_QueryDirection,
- TestFilter_Pin_QueryId,
- TestFilter_Pin_QueryAccept,
- TestFilter_Pin_EnumMediaTypes,
- TestFilter_Pin_QueryInternalConnections,
- TestFilter_Pin_EndOfStream,
- TestFilter_Pin_BeginFlush,
- TestFilter_Pin_EndFlush,
- TestFilter_Pin_NewSegment
-};
-
-static HRESULT TestFilter_Pin_Construct(const IPinVtbl *Pin_Vtbl, const PIN_INFO * pPinInfo, AM_MEDIA_TYPE *pinmt,
- LPCRITICAL_SECTION pCritSec, IPin ** ppPin)
-{
- ITestPinImpl * pPinImpl;
-
- *ppPin = NULL;
-
- pPinImpl = CoTaskMemAlloc(sizeof(ITestPinImpl));
-
- if (!pPinImpl)
- return E_OUTOFMEMORY;
-
- pPinImpl->refCount = 1;
- pPinImpl->pConnectedTo = NULL;
- pPinImpl->pCritSec = pCritSec;
- Copy_PinInfo(&pPinImpl->pinInfo, pPinInfo);
- pPinImpl->mtCurrent = *pinmt;
-
- pPinImpl->IPin_iface.lpVtbl = Pin_Vtbl;
-
- *ppPin = &pPinImpl->IPin_iface;
- return S_OK;
-}
-
-/* IEnumPins implementation */
-
-typedef HRESULT (* FNOBTAINPIN)(TestFilterImpl *tf, ULONG pos, IPin **pin, DWORD *lastsynctick);
-
-typedef struct IEnumPinsImpl
-{
- IEnumPins IEnumPins_iface;
- LONG refCount;
- ULONG uIndex;
- TestFilterImpl *base;
- FNOBTAINPIN receive_pin;
- DWORD synctime;
-} IEnumPinsImpl;
-
-static const struct IEnumPinsVtbl IEnumPinsImpl_Vtbl;
-
-static inline IEnumPinsImpl *impl_from_IEnumPins(IEnumPins *iface)
-{
- return CONTAINING_RECORD(iface, IEnumPinsImpl, IEnumPins_iface);
-}
-
-static HRESULT createenumpins(IEnumPins ** ppEnum, FNOBTAINPIN receive_pin, TestFilterImpl *base)
-{
- IEnumPinsImpl * pEnumPins;
-
- if (!ppEnum)
- return E_POINTER;
-
- pEnumPins = CoTaskMemAlloc(sizeof(IEnumPinsImpl));
- if (!pEnumPins)
- {
- *ppEnum = NULL;
- return E_OUTOFMEMORY;
- }
- pEnumPins->IEnumPins_iface.lpVtbl = &IEnumPinsImpl_Vtbl;
- pEnumPins->refCount = 1;
- pEnumPins->uIndex = 0;
- pEnumPins->receive_pin = receive_pin;
- pEnumPins->base = base;
- IBaseFilter_AddRef(&base->IBaseFilter_iface);
- *ppEnum = &pEnumPins->IEnumPins_iface;
-
- receive_pin(base, ~0, NULL, &pEnumPins->synctime);
-
- return S_OK;
-}
-
-static HRESULT WINAPI IEnumPinsImpl_QueryInterface(IEnumPins * iface, REFIID riid, LPVOID * ppv)
-{
- *ppv = NULL;
-
- if (IsEqualIID(riid, &IID_IUnknown))
- *ppv = iface;
- else if (IsEqualIID(riid, &IID_IEnumPins))
- *ppv = iface;
-
- if (*ppv)
- {
- IUnknown_AddRef((IUnknown *)(*ppv));
- return S_OK;
- }
-
- return E_NOINTERFACE;
-}
-
-static ULONG WINAPI IEnumPinsImpl_AddRef(IEnumPins * iface)
-{
- IEnumPinsImpl *This = impl_from_IEnumPins(iface);
- ULONG refCount = InterlockedIncrement(&This->refCount);
-
- return refCount;
-}
-
-static ULONG WINAPI IEnumPinsImpl_Release(IEnumPins * iface)
-{
- IEnumPinsImpl *This = impl_from_IEnumPins(iface);
- ULONG refCount = InterlockedDecrement(&This->refCount);
-
- if (!refCount)
- {
- IBaseFilter_Release(&This->base->IBaseFilter_iface);
- CoTaskMemFree(This);
- return 0;
- }
- else
- return refCount;
-}
-
-static HRESULT WINAPI IEnumPinsImpl_Next(IEnumPins * iface, ULONG cPins, IPin ** ppPins, ULONG * pcFetched)
-{
- IEnumPinsImpl *This = impl_from_IEnumPins(iface);
- DWORD synctime = This->synctime;
- HRESULT hr = S_OK;
- ULONG i = 0;
-
- if (!ppPins)
- return E_POINTER;
-
- if (cPins > 1 && !pcFetched)
- return E_INVALIDARG;
-
- if (pcFetched)
- *pcFetched = 0;
-
- while (i < cPins && hr == S_OK)
- {
- hr = This->receive_pin(This->base, This->uIndex + i, &ppPins[i], &synctime);
-
- if (hr == S_OK)
- ++i;
-
- if (synctime != This->synctime)
+ if (pin->enum_idx + i >= pin->type_count)
break;
+
+ out[i] = CoTaskMemAlloc(sizeof(*out[i]));
+ *out[i] = pin->types[pin->enum_idx + i];
}
- if (!i && synctime != This->synctime)
- return VFW_E_ENUM_OUT_OF_SYNC;
+ if (fetched)
+ *fetched = i;
+ pin->enum_idx += i;
- if (pcFetched)
- *pcFetched = i;
- This->uIndex += i;
+ return (i == count) ? S_OK : S_FALSE;
+}
- if (i < cPins)
- return S_FALSE;
+static HRESULT WINAPI testenummt_Skip(IEnumMediaTypes *iface, ULONG count)
+{
+ ok(0, "Unexpected call.\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI testenummt_Reset(IEnumMediaTypes *iface)
+{
+ struct testpin *pin = impl_from_IEnumMediaTypes(iface);
+ pin->enum_idx = 0;
return S_OK;
}
-static HRESULT WINAPI IEnumPinsImpl_Skip(IEnumPins * iface, ULONG cPins)
+static HRESULT WINAPI testenummt_Clone(IEnumMediaTypes *iface, IEnumMediaTypes **out)
{
- IEnumPinsImpl *This = impl_from_IEnumPins(iface);
- DWORD synctime = This->synctime;
- HRESULT hr;
- IPin *pin = NULL;
-
- hr = This->receive_pin(This->base, This->uIndex + cPins, &pin, &synctime);
- if (pin)
- IPin_Release(pin);
-
- if (synctime != This->synctime)
- return VFW_E_ENUM_OUT_OF_SYNC;
-
- if (hr == S_OK)
- This->uIndex += cPins;
-
- return hr;
+ ok(0, "Unexpected call.\n");
+ return E_NOTIMPL;
}
-static HRESULT WINAPI IEnumPinsImpl_Reset(IEnumPins * iface)
+static const IEnumMediaTypesVtbl testenummt_vtbl =
{
- IEnumPinsImpl *This = impl_from_IEnumPins(iface);
-
- This->receive_pin(This->base, ~0, NULL, &This->synctime);
-
- This->uIndex = 0;
- return S_OK;
-}
-
-static HRESULT WINAPI IEnumPinsImpl_Clone(IEnumPins * iface, IEnumPins ** ppEnum)
-{
- HRESULT hr;
- IEnumPinsImpl *This = impl_from_IEnumPins(iface);
-
- hr = createenumpins(ppEnum, This->receive_pin, This->base);
- if (FAILED(hr))
- return hr;
- return IEnumPins_Skip(*ppEnum, This->uIndex);
-}
-
-static const IEnumPinsVtbl IEnumPinsImpl_Vtbl =
-{
- IEnumPinsImpl_QueryInterface,
- IEnumPinsImpl_AddRef,
- IEnumPinsImpl_Release,
- IEnumPinsImpl_Next,
- IEnumPinsImpl_Skip,
- IEnumPinsImpl_Reset,
- IEnumPinsImpl_Clone
+ testenummt_QueryInterface,
+ testenummt_AddRef,
+ testenummt_Release,
+ testenummt_Next,
+ testenummt_Skip,
+ testenummt_Reset,
+ testenummt_Clone,
};
-/* Test filter implementation - a filter that has few predefined pins with single media type
- * that accept only this single media type. Enough for Render(). */
-
-typedef struct TestFilterPinData
+static inline struct testpin *impl_from_IPin(IPin *iface)
{
-PIN_DIRECTION pinDir;
-const GUID *mediasubtype;
-} TestFilterPinData;
-
-static const IBaseFilterVtbl TestFilter_Vtbl;
-
-static inline TestFilterImpl *impl_from_IBaseFilter(IBaseFilter *iface)
-{
- return CONTAINING_RECORD(iface, TestFilterImpl, IBaseFilter_iface);
+ return CONTAINING_RECORD(iface, struct testpin, IPin_iface);
}
-static HRESULT createtestfilter(const CLSID* pClsid, const TestFilterPinData *pinData,
- TestFilterImpl **tf)
+static HRESULT WINAPI testpin_QueryInterface(IPin *iface, REFIID iid, void **out)
{
- static const WCHAR wcsInputPinName[] = {'i','n','p','u','t',' ','p','i','n',0};
- static const WCHAR wcsOutputPinName[] = {'o','u','t','p','u','t',' ','p','i','n',0};
- HRESULT hr;
- PIN_INFO pinInfo;
- TestFilterImpl* pTestFilter = NULL;
- UINT nPins, i;
- AM_MEDIA_TYPE mt;
+ struct testpin *pin = impl_from_IPin(iface);
+ if (winetest_debug > 1) trace("%p->QueryInterface(%s)\n", pin, wine_dbgstr_guid(iid));
- pTestFilter = CoTaskMemAlloc(sizeof(TestFilterImpl));
- if (!pTestFilter) return E_OUTOFMEMORY;
-
- pTestFilter->clsid = *pClsid;
- pTestFilter->IBaseFilter_iface.lpVtbl = &TestFilter_Vtbl;
- pTestFilter->refCount = 1;
- InitializeCriticalSection(&pTestFilter->csFilter);
- pTestFilter->state = State_Stopped;
-
- ZeroMemory(&pTestFilter->filterInfo, sizeof(FILTER_INFO));
-
- nPins = 0;
- while(pinData[nPins].mediasubtype) ++nPins;
-
- pTestFilter->ppPins = CoTaskMemAlloc(nPins * sizeof(IPin *));
- if (!pTestFilter->ppPins)
+ if (IsEqualGUID(iid, &IID_IUnknown) || IsEqualGUID(iid, &IID_IPin))
{
- hr = E_OUTOFMEMORY;
- goto error;
- }
- ZeroMemory(pTestFilter->ppPins, nPins * sizeof(IPin *));
-
- for (i = 0; i < nPins; i++)
- {
- ZeroMemory(&mt, sizeof(mt));
- mt.majortype = MEDIATYPE_Video;
- mt.formattype = FORMAT_None;
- mt.subtype = *pinData[i].mediasubtype;
-
- pinInfo.dir = pinData[i].pinDir;
- pinInfo.pFilter = &pTestFilter->IBaseFilter_iface;
- if (pinInfo.dir == PINDIR_INPUT)
- {
- lstrcpynW(pinInfo.achName, wcsInputPinName, ARRAY_SIZE(pinInfo.achName));
- hr = TestFilter_Pin_Construct(&TestFilter_InputPin_Vtbl, &pinInfo, &mt, &pTestFilter->csFilter,
- &pTestFilter->ppPins[i]);
-
- }
- else
- {
- lstrcpynW(pinInfo.achName, wcsOutputPinName, ARRAY_SIZE(pinInfo.achName));
- hr = TestFilter_Pin_Construct(&TestFilter_OutputPin_Vtbl, &pinInfo, &mt, &pTestFilter->csFilter,
- &pTestFilter->ppPins[i]);
- }
- if (FAILED(hr) || !pTestFilter->ppPins[i]) goto error;
- }
-
- pTestFilter->nPins = nPins;
- *tf = pTestFilter;
- return S_OK;
-
- error:
-
- if (pTestFilter->ppPins)
- {
- for (i = 0; i < nPins; i++)
- {
- if (pTestFilter->ppPins[i]) IPin_Release(pTestFilter->ppPins[i]);
- }
- }
- CoTaskMemFree(pTestFilter->ppPins);
- DeleteCriticalSection(&pTestFilter->csFilter);
- CoTaskMemFree(pTestFilter);
-
- return hr;
-}
-
-static HRESULT WINAPI TestFilter_QueryInterface(IBaseFilter * iface, REFIID riid, LPVOID * ppv)
-{
- TestFilterImpl *This = impl_from_IBaseFilter(iface);
-
- *ppv = NULL;
-
- if (IsEqualIID(riid, &IID_IUnknown))
- *ppv = This;
- else if (IsEqualIID(riid, &IID_IPersist))
- *ppv = This;
- else if (IsEqualIID(riid, &IID_IMediaFilter))
- *ppv = This;
- else if (IsEqualIID(riid, &IID_IBaseFilter))
- *ppv = This;
-
- if (*ppv)
- {
- IUnknown_AddRef((IUnknown *)(*ppv));
+ *out = &pin->IPin_iface;
+ IPin_AddRef(*out);
return S_OK;
}
+ *out = NULL;
return E_NOINTERFACE;
}
-static ULONG WINAPI TestFilter_AddRef(IBaseFilter * iface)
+ULONG WINAPI testpin_AddRef(IPin *iface)
{
- TestFilterImpl *This = impl_from_IBaseFilter(iface);
- ULONG refCount = InterlockedIncrement(&This->refCount);
-
- return refCount;
+ struct testpin *pin = impl_from_IPin(iface);
+ return InterlockedIncrement(&pin->ref);
}
-static ULONG WINAPI TestFilter_Release(IBaseFilter * iface)
+ULONG WINAPI testpin_Release(IPin *iface)
{
- TestFilterImpl *This = impl_from_IBaseFilter(iface);
- ULONG refCount = InterlockedDecrement(&This->refCount);
-
- if (!refCount)
- {
- ULONG i;
-
- for (i = 0; i < This->nPins; i++)
- {
- IPin *pConnectedTo;
-
- if (SUCCEEDED(IPin_ConnectedTo(This->ppPins[i], &pConnectedTo)))
- {
- IPin_Disconnect(pConnectedTo);
- IPin_Release(pConnectedTo);
- }
- IPin_Disconnect(This->ppPins[i]);
-
- IPin_Release(This->ppPins[i]);
- }
-
- CoTaskMemFree(This->ppPins);
-
- DeleteCriticalSection(&This->csFilter);
-
- CoTaskMemFree(This);
-
- return 0;
- }
- else
- return refCount;
-}
-/** IPersist methods **/
-
-static HRESULT WINAPI TestFilter_GetClassID(IBaseFilter * iface, CLSID * pClsid)
-{
- TestFilterImpl *This = impl_from_IBaseFilter(iface);
-
- *pClsid = This->clsid;
-
- return S_OK;
+ struct testpin *pin = impl_from_IPin(iface);
+ return InterlockedDecrement(&pin->ref);
}
-/** IMediaFilter methods **/
-
-static HRESULT WINAPI TestFilter_Stop(IBaseFilter * iface)
+static HRESULT WINAPI testpin_Disconnect(IPin *iface)
{
- return E_NOTIMPL;
-}
+ struct testpin *pin = impl_from_IPin(iface);
+ if (winetest_debug > 1) trace("%p->Disconnect()\n", pin);
-static HRESULT WINAPI TestFilter_Pause(IBaseFilter * iface)
-{
- return E_NOTIMPL;
-}
-
-static HRESULT WINAPI TestFilter_Run(IBaseFilter * iface, REFERENCE_TIME tStart)
-{
- return E_NOTIMPL;
-}
-
-static HRESULT WINAPI TestFilter_GetState(IBaseFilter * iface, DWORD dwMilliSecsTimeout, FILTER_STATE *pState)
-{
- TestFilterImpl *This = impl_from_IBaseFilter(iface);
-
- EnterCriticalSection(&This->csFilter);
- {
- *pState = This->state;
- }
- LeaveCriticalSection(&This->csFilter);
-
- return S_OK;
-}
-
-static HRESULT WINAPI TestFilter_SetSyncSource(IBaseFilter * iface, IReferenceClock *pClock)
-{
- return E_NOTIMPL;
-}
-
-static HRESULT WINAPI TestFilter_GetSyncSource(IBaseFilter * iface, IReferenceClock **ppClock)
-{
- return E_NOTIMPL;
-}
-
-/** IBaseFilter implementation **/
-
-static HRESULT getpin_callback(TestFilterImpl *tf, ULONG pos, IPin **pin, DWORD *lastsynctick)
-{
- /* Our pins are static, not changing so setting static tick count is ok */
- *lastsynctick = 0;
-
- if (pos >= tf->nPins)
+ if (!pin->peer)
return S_FALSE;
- *pin = tf->ppPins[pos];
- IPin_AddRef(*pin);
+ IPin_Release(pin->peer);
+ pin->peer = NULL;
return S_OK;
}
-static HRESULT WINAPI TestFilter_EnumPins(IBaseFilter * iface, IEnumPins **ppEnum)
+static HRESULT WINAPI testpin_ConnectedTo(IPin *iface, IPin **peer)
{
- TestFilterImpl *This = impl_from_IBaseFilter(iface);
+ struct testpin *pin = impl_from_IPin(iface);
+ if (winetest_debug > 1) trace("%p->ConnectedTo()\n", pin);
- return createenumpins(ppEnum, getpin_callback, This);
-}
-
-static HRESULT WINAPI TestFilter_FindPin(IBaseFilter * iface, LPCWSTR Id, IPin **ppPin)
-{
- return E_NOTIMPL;
-}
-
-static HRESULT WINAPI TestFilter_QueryFilterInfo(IBaseFilter * iface, FILTER_INFO *pInfo)
-{
- TestFilterImpl *This = impl_from_IBaseFilter(iface);
-
- lstrcpyW(pInfo->achName, This->filterInfo.achName);
- pInfo->pGraph = This->filterInfo.pGraph;
-
- if (pInfo->pGraph)
- IFilterGraph_AddRef(pInfo->pGraph);
-
- return S_OK;
-}
-
-static HRESULT WINAPI TestFilter_JoinFilterGraph(IBaseFilter * iface, IFilterGraph *pGraph, LPCWSTR pName)
-{
- HRESULT hr = S_OK;
- TestFilterImpl *This = impl_from_IBaseFilter(iface);
-
- EnterCriticalSection(&This->csFilter);
+ *peer = pin->peer;
+ if (*peer)
{
- if (pName)
- lstrcpyW(This->filterInfo.achName, pName);
- else
- *This->filterInfo.achName = '\0';
- This->filterInfo.pGraph = pGraph; /* NOTE: do NOT increase ref. count */
+ IPin_AddRef(*peer);
+ return S_OK;
}
- LeaveCriticalSection(&This->csFilter);
-
- return hr;
+ return VFW_E_NOT_CONNECTED;
}
-static HRESULT WINAPI TestFilter_QueryVendorInfo(IBaseFilter * iface, LPWSTR *pVendorInfo)
+static HRESULT WINAPI testpin_ConnectionMediaType(IPin *iface, AM_MEDIA_TYPE *mt)
{
+ ok(0, "Unexpected call.\n");
return E_NOTIMPL;
}
-static const IBaseFilterVtbl TestFilter_Vtbl =
+static HRESULT WINAPI testpin_QueryPinInfo(IPin *iface, PIN_INFO *info)
{
- TestFilter_QueryInterface,
- TestFilter_AddRef,
- TestFilter_Release,
- TestFilter_GetClassID,
- TestFilter_Stop,
- TestFilter_Pause,
- TestFilter_Run,
- TestFilter_GetState,
- TestFilter_SetSyncSource,
- TestFilter_GetSyncSource,
- TestFilter_EnumPins,
- TestFilter_FindPin,
- TestFilter_QueryFilterInfo,
- TestFilter_JoinFilterGraph,
- TestFilter_QueryVendorInfo
+ struct testpin *pin = impl_from_IPin(iface);
+ if (winetest_debug > 1) trace("%p->QueryPinInfo()\n", pin);
+
+ info->pFilter = pin->filter;
+ IBaseFilter_AddRef(pin->filter);
+ info->dir = pin->dir;
+ info->achName[0] = 0;
+ return S_OK;
+}
+
+
+static HRESULT WINAPI testpin_QueryDirection(IPin *iface, PIN_DIRECTION *dir)
+{
+ struct testpin *pin = impl_from_IPin(iface);
+ if (winetest_debug > 1) trace("%p->QueryDirection()\n", pin);
+
+ *dir = pin->dir;
+ return S_OK;
+}
+
+static HRESULT WINAPI testpin_QueryId(IPin *iface, WCHAR **id)
+{
+ if (winetest_debug > 1) trace("%p->QueryId()\n", iface);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI testpin_QueryAccept(IPin *iface, const AM_MEDIA_TYPE *mt)
+{
+ ok(0, "Unexpected call.\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI testpin_EnumMediaTypes(IPin *iface, IEnumMediaTypes **out)
+{
+ struct testpin *pin = impl_from_IPin(iface);
+ if (winetest_debug > 1) trace("%p->EnumMediaTypes()\n", pin);
+
+ *out = &pin->IEnumMediaTypes_iface;
+ IEnumMediaTypes_AddRef(*out);
+ pin->enum_idx = 0;
+ return S_OK;
+}
+
+static HRESULT WINAPI testpin_QueryInternalConnections(IPin *iface, IPin **out, ULONG *count)
+{
+ if (winetest_debug > 1) trace("%p->QueryInternalConnections()\n", iface);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI testpin_BeginFlush(IPin *iface)
+{
+ ok(0, "Unexpected call.\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI testpin_EndFlush(IPin * iface)
+{
+ ok(0, "Unexpected call.\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI testpin_NewSegment(IPin *iface, REFERENCE_TIME start, REFERENCE_TIME stop, double rate)
+{
+ ok(0, "Unexpected call.\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI testpin_EndOfStream(IPin *iface)
+{
+ ok(0, "Unexpected call.\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI testsink_Connect(IPin *iface, IPin *peer, const AM_MEDIA_TYPE *mt)
+{
+ ok(0, "Unexpected call.\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI testsink_ReceiveConnection(IPin *iface, IPin *peer, const AM_MEDIA_TYPE *mt)
+{
+ struct testpin *pin = impl_from_IPin(iface);
+ if (winetest_debug > 1) trace("%p->ReceiveConnection(%p)\n", pin, peer);
+
+ pin->peer = peer;
+ IPin_AddRef(peer);
+ return S_OK;
+}
+
+static HRESULT WINAPI testsink_EnumMediaTypes(IPin *iface, IEnumMediaTypes **out)
+{
+ ok(0, "Unexpected call.\n");
+ return E_NOTIMPL;
+}
+
+static const IPinVtbl testsink_vtbl =
+{
+ testpin_QueryInterface,
+ testpin_AddRef,
+ testpin_Release,
+ testsink_Connect,
+ testsink_ReceiveConnection,
+ testpin_Disconnect,
+ testpin_ConnectedTo,
+ testpin_ConnectionMediaType,
+ testpin_QueryPinInfo,
+ testpin_QueryDirection,
+ testpin_QueryId,
+ testpin_QueryAccept,
+ testsink_EnumMediaTypes,
+ testpin_QueryInternalConnections,
+ testpin_EndOfStream,
+ testpin_BeginFlush,
+ testpin_EndFlush,
+ testpin_NewSegment
};
-/* IClassFactory implementation */
+static void testsink_init(struct testpin *pin)
+{
+ memset(pin, 0, sizeof(*pin));
+ pin->IPin_iface.lpVtbl = &testsink_vtbl;
+ pin->ref = 1;
+ pin->dir = PINDIR_INPUT;
-typedef struct TestClassFactoryImpl
+ pin->IEnumMediaTypes_iface.lpVtbl = &testenummt_vtbl;
+}
+
+static HRESULT WINAPI testsource_Connect(IPin *iface, IPin *peer, const AM_MEDIA_TYPE *mt)
+{
+ struct testpin *pin = impl_from_IPin(iface);
+ if (winetest_debug > 1) trace("%p->Connect(%p)\n", pin, peer);
+
+ ok(!mt, "Got media type %p.\n", mt);
+
+ pin->peer = peer;
+ IPin_AddRef(peer);
+ return IPin_ReceiveConnection(peer, &pin->IPin_iface, mt);
+}
+
+static HRESULT WINAPI testsource_ReceiveConnection(IPin *iface, IPin *peer, const AM_MEDIA_TYPE *mt)
+{
+ ok(0, "Unexpected call.\n");
+ return E_NOTIMPL;
+}
+
+static const IPinVtbl testsource_vtbl =
+{
+ testpin_QueryInterface,
+ testpin_AddRef,
+ testpin_Release,
+ testsource_Connect,
+ testsource_ReceiveConnection,
+ testpin_Disconnect,
+ testpin_ConnectedTo,
+ testpin_ConnectionMediaType,
+ testpin_QueryPinInfo,
+ testpin_QueryDirection,
+ testpin_QueryId,
+ testpin_QueryAccept,
+ testpin_EnumMediaTypes,
+ testpin_QueryInternalConnections,
+ testpin_EndOfStream,
+ testpin_BeginFlush,
+ testpin_EndFlush,
+ testpin_NewSegment
+};
+
+static void testsource_init(struct testpin *pin, const AM_MEDIA_TYPE *types, int type_count)
+{
+ memset(pin, 0, sizeof(*pin));
+ pin->IPin_iface.lpVtbl = &testsource_vtbl;
+ pin->ref = 1;
+ pin->dir = PINDIR_OUTPUT;
+
+ pin->IEnumMediaTypes_iface.lpVtbl = &testenummt_vtbl;
+ pin->types = types;
+ pin->type_count = type_count;
+}
+
+struct testfilter
+{
+ IBaseFilter IBaseFilter_iface;
+ LONG ref;
+ IFilterGraph *graph;
+ WCHAR *name;
+
+ IEnumPins IEnumPins_iface;
+ struct testpin *pins;
+ unsigned int pin_count, enum_idx;
+};
+
+static inline struct testfilter *impl_from_IEnumPins(IEnumPins *iface)
+{
+ return CONTAINING_RECORD(iface, struct testfilter, IEnumPins_iface);
+}
+
+static HRESULT WINAPI testenumpins_QueryInterface(IEnumPins *iface, REFIID iid, void **out)
+{
+ ok(0, "Unexpected iid %s.\n", wine_dbgstr_guid(iid));
+ return E_NOINTERFACE;
+}
+
+static ULONG WINAPI testenumpins_AddRef(IEnumPins * iface)
+{
+ struct testfilter *filter = impl_from_IEnumPins(iface);
+ return InterlockedIncrement(&filter->ref);
+}
+
+static ULONG WINAPI testenumpins_Release(IEnumPins * iface)
+{
+ struct testfilter *filter = impl_from_IEnumPins(iface);
+ return InterlockedDecrement(&filter->ref);
+}
+
+static HRESULT WINAPI testenumpins_Next(IEnumPins *iface, ULONG count, IPin **out, ULONG *fetched)
+{
+ struct testfilter *filter = impl_from_IEnumPins(iface);
+ unsigned int i;
+
+ for (i = 0; i < count; ++i)
+ {
+ if (filter->enum_idx + i >= filter->pin_count)
+ break;
+
+ out[i] = &filter->pins[filter->enum_idx + i].IPin_iface;
+ IPin_AddRef(out[i]);
+ }
+
+ if (fetched)
+ *fetched = i;
+ filter->enum_idx += i;
+
+ return (i == count) ? S_OK : S_FALSE;
+}
+
+static HRESULT WINAPI testenumpins_Skip(IEnumPins *iface, ULONG count)
+{
+ ok(0, "Unexpected call.\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI testenumpins_Reset(IEnumPins *iface)
+{
+ struct testfilter *filter = impl_from_IEnumPins(iface);
+ filter->enum_idx = 0;
+ return S_OK;
+}
+
+static HRESULT WINAPI testenumpins_Clone(IEnumPins *iface, IEnumPins **out)
+{
+ ok(0, "Unexpected call.\n");
+ return E_NOTIMPL;
+}
+
+static const IEnumPinsVtbl testenumpins_vtbl =
+{
+ testenumpins_QueryInterface,
+ testenumpins_AddRef,
+ testenumpins_Release,
+ testenumpins_Next,
+ testenumpins_Skip,
+ testenumpins_Reset,
+ testenumpins_Clone,
+};
+
+static inline struct testfilter *impl_from_IBaseFilter(IBaseFilter *iface)
+{
+ return CONTAINING_RECORD(iface, struct testfilter, IBaseFilter_iface);
+}
+
+static HRESULT WINAPI testfilter_QueryInterface(IBaseFilter *iface, REFIID iid, void **out)
+{
+ struct testfilter *filter = impl_from_IBaseFilter(iface);
+ if (winetest_debug > 1) trace("%p->QueryInterface(%s)\n", filter, wine_dbgstr_guid(iid));
+
+ if (IsEqualGUID(iid, &IID_IUnknown)
+ || IsEqualGUID(iid, &IID_IPersist)
+ || IsEqualGUID(iid, &IID_IMediaFilter)
+ || IsEqualGUID(iid, &IID_IBaseFilter))
+ {
+ *out = &filter->IBaseFilter_iface;
+ IBaseFilter_AddRef(*out);
+ return S_OK;
+ }
+
+ *out = NULL;
+ return E_NOINTERFACE;
+}
+
+static ULONG WINAPI testfilter_AddRef(IBaseFilter *iface)
+{
+ struct testfilter *filter = impl_from_IBaseFilter(iface);
+ return InterlockedIncrement(&filter->ref);
+}
+
+static ULONG WINAPI testfilter_Release(IBaseFilter *iface)
+{
+ struct testfilter *filter = impl_from_IBaseFilter(iface);
+ return InterlockedDecrement(&filter->ref);
+}
+
+static HRESULT WINAPI testfilter_GetClassID(IBaseFilter *iface, CLSID *clsid)
+{
+ if (winetest_debug > 1) trace("%p->GetClassID()\n", iface);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI testfilter_Stop(IBaseFilter *iface)
+{
+ if (winetest_debug > 1) trace("%p->Stop()\n", iface);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI testfilter_Pause(IBaseFilter *iface)
+{
+ ok(0, "Unexpected call.\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI testfilter_Run(IBaseFilter *iface, REFERENCE_TIME start)
+{
+ ok(0, "Unexpected call.\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI testfilter_GetState(IBaseFilter *iface, DWORD timeout, FILTER_STATE *state)
+{
+ if (winetest_debug > 1) trace("%p->GetState()\n", iface);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI testfilter_SetSyncSource(IBaseFilter *iface, IReferenceClock *clock)
+{
+ if (winetest_debug > 1) trace("%p->SetSyncSource(%p)\n", iface, clock);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI testfilter_GetSyncSource(IBaseFilter *iface, IReferenceClock **clock)
+{
+ ok(0, "Unexpected call.\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI testfilter_EnumPins(IBaseFilter *iface, IEnumPins **out)
+{
+ struct testfilter *filter = impl_from_IBaseFilter(iface);
+ if (winetest_debug > 1) trace("%p->EnumPins()\n", filter);
+
+ *out = &filter->IEnumPins_iface;
+ IEnumPins_AddRef(*out);
+ filter->enum_idx = 0;
+ return S_OK;
+}
+
+static HRESULT WINAPI testfilter_FindPin(IBaseFilter *iface, const WCHAR *id, IPin **pin)
+{
+ ok(0, "Unexpected call.\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI testfilter_QueryFilterInfo(IBaseFilter *iface, FILTER_INFO *info)
+{
+ struct testfilter *filter = impl_from_IBaseFilter(iface);
+ if (winetest_debug > 1) trace("%p->QueryFilterInfo()\n", filter);
+
+ info->pGraph = filter->graph;
+ if (filter->graph)
+ IFilterGraph_AddRef(filter->graph);
+ if (filter->name)
+ lstrcpyW(info->achName, filter->name);
+ else
+ info->achName[0] = 0;
+ return S_OK;
+}
+
+static HRESULT WINAPI testfilter_JoinFilterGraph(IBaseFilter *iface, IFilterGraph *graph, const WCHAR *name)
+{
+ struct testfilter *filter = impl_from_IBaseFilter(iface);
+ if (winetest_debug > 1) trace("%p->JoinFilterGraph(%p, %s)\n", filter, graph, wine_dbgstr_w(name));
+
+ filter->graph = graph;
+ heap_free(filter->name);
+ if (name)
+ {
+ filter->name = heap_alloc((lstrlenW(name)+1)*sizeof(WCHAR));
+ lstrcpyW(filter->name, name);
+ }
+ else
+ filter->name = NULL;
+ return S_OK;
+}
+
+static HRESULT WINAPI testfilter_QueryVendorInfo(IBaseFilter * iface, WCHAR **info)
+{
+ return E_NOTIMPL;
+}
+
+static const IBaseFilterVtbl testfilter_vtbl =
+{
+ testfilter_QueryInterface,
+ testfilter_AddRef,
+ testfilter_Release,
+ testfilter_GetClassID,
+ testfilter_Stop,
+ testfilter_Pause,
+ testfilter_Run,
+ testfilter_GetState,
+ testfilter_SetSyncSource,
+ testfilter_GetSyncSource,
+ testfilter_EnumPins,
+ testfilter_FindPin,
+ testfilter_QueryFilterInfo,
+ testfilter_JoinFilterGraph,
+ testfilter_QueryVendorInfo
+};
+
+struct testfilter_cf
{
IClassFactory IClassFactory_iface;
- const TestFilterPinData *filterPinData;
- const CLSID *clsid;
-} TestClassFactoryImpl;
+ struct testfilter *filter;
+};
-static inline TestClassFactoryImpl *impl_from_IClassFactory(IClassFactory *iface)
+static void testfilter_init(struct testfilter *filter, struct testpin *pins, int pin_count)
{
- return CONTAINING_RECORD(iface, TestClassFactoryImpl, IClassFactory_iface);
+ unsigned int i;
+
+ memset(filter, 0, sizeof(*filter));
+ filter->IBaseFilter_iface.lpVtbl = &testfilter_vtbl;
+ filter->IEnumPins_iface.lpVtbl = &testenumpins_vtbl;
+ filter->ref = 1;
+ filter->pins = pins;
+ filter->pin_count = pin_count;
+ for (i = 0; i < pin_count; i++)
+ pins[i].filter = &filter->IBaseFilter_iface;
}
-static HRESULT WINAPI Test_IClassFactory_QueryInterface(
- LPCLASSFACTORY iface,
- REFIID riid,
- LPVOID *ppvObj)
+static HRESULT WINAPI testfilter_cf_QueryInterface(IClassFactory *iface, REFIID iid, void **out)
{
- if (ppvObj == NULL) return E_POINTER;
-
- if (IsEqualGUID(riid, &IID_IUnknown) ||
- IsEqualGUID(riid, &IID_IClassFactory))
+ if (IsEqualGUID(iid, &IID_IUnknown) || IsEqualGUID(iid, &IID_IClassFactory))
{
- *ppvObj = iface;
- IClassFactory_AddRef(iface);
+ *out = iface;
return S_OK;
}
- *ppvObj = NULL;
+ *out = NULL;
return E_NOINTERFACE;
}
-static ULONG WINAPI Test_IClassFactory_AddRef(LPCLASSFACTORY iface)
+static ULONG WINAPI testfilter_cf_AddRef(IClassFactory *iface)
{
- return 2; /* non-heap-based object */
+ return 2;
}
-static ULONG WINAPI Test_IClassFactory_Release(LPCLASSFACTORY iface)
+static ULONG WINAPI testfilter_cf_Release(IClassFactory *iface)
{
- return 1; /* non-heap-based object */
+ return 1;
}
-static HRESULT WINAPI Test_IClassFactory_CreateInstance(
- LPCLASSFACTORY iface,
- LPUNKNOWN pUnkOuter,
- REFIID riid,
- LPVOID *ppvObj)
+static HRESULT WINAPI testfilter_cf_CreateInstance(IClassFactory *iface, IUnknown *outer, REFIID iid, void **out)
{
- TestClassFactoryImpl *This = impl_from_IClassFactory(iface);
- HRESULT hr;
- TestFilterImpl *testfilter;
+ struct testfilter_cf *factory = CONTAINING_RECORD(iface, struct testfilter_cf, IClassFactory_iface);
- *ppvObj = NULL;
-
- if (pUnkOuter) return CLASS_E_NOAGGREGATION;
-
- hr = createtestfilter(This->clsid, This->filterPinData, &testfilter);
- if (SUCCEEDED(hr)) {
- hr = IBaseFilter_QueryInterface(&testfilter->IBaseFilter_iface, riid, ppvObj);
- IBaseFilter_Release(&testfilter->IBaseFilter_iface);
- }
- return hr;
+ return IBaseFilter_QueryInterface(&factory->filter->IBaseFilter_iface, iid, out);
}
-static HRESULT WINAPI Test_IClassFactory_LockServer(
- LPCLASSFACTORY iface,
- BOOL fLock)
+static HRESULT WINAPI testfilter_cf_LockServer(IClassFactory *iface, BOOL lock)
{
- return S_OK;
+ return E_NOTIMPL;
}
-static IClassFactoryVtbl TestClassFactory_Vtbl =
+static IClassFactoryVtbl testfilter_cf_vtbl =
{
- Test_IClassFactory_QueryInterface,
- Test_IClassFactory_AddRef,
- Test_IClassFactory_Release,
- Test_IClassFactory_CreateInstance,
- Test_IClassFactory_LockServer
+ testfilter_cf_QueryInterface,
+ testfilter_cf_AddRef,
+ testfilter_cf_Release,
+ testfilter_cf_CreateInstance,
+ testfilter_cf_LockServer,
};
-static HRESULT get_connected_filter_name(TestFilterImpl *pFilter, char *FilterName)
+static void test_graph_builder_render(void)
{
- IPin *pin = NULL;
- PIN_INFO pinInfo;
- FILTER_INFO filterInfo;
+ static const WCHAR testW[] = {'t','e','s','t',0};
+ static const GUID sink1_clsid = {0x12345678};
+ static const GUID sink2_clsid = {0x87654321};
+ AM_MEDIA_TYPE source_type = {0};
+ struct testpin source_pin, sink1_pin, sink2_pin, parser_pins[2];
+ struct testfilter source, sink1, sink2, parser;
+ struct testfilter_cf sink1_cf = { {&testfilter_cf_vtbl}, &sink1 };
+ struct testfilter_cf sink2_cf = { {&testfilter_cf_vtbl}, &sink2 };
+
+ IFilterGraph2 *graph = create_graph();
+ REGFILTERPINS2 regpins = {0};
+ REGPINTYPES regtypes = {0};
+ REGFILTER2 regfilter = {0};
+ IFilterMapper2 *mapper;
+ DWORD cookie1, cookie2;
HRESULT hr;
-
- FilterName[0] = 0;
-
- hr = IPin_ConnectedTo(pFilter->ppPins[0], &pin);
- ok(hr == S_OK, "IPin_ConnectedTo failed with %x\n", hr);
-
- hr = IPin_QueryPinInfo(pin, &pinInfo);
- ok(hr == S_OK, "IPin_QueryPinInfo failed with %x\n", hr);
- IPin_Release(pin);
-
- SetLastError(0xdeadbeef);
- hr = IBaseFilter_QueryFilterInfo(pinInfo.pFilter, &filterInfo);
- if (hr == S_OK && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
- {
- IBaseFilter_Release(pinInfo.pFilter);
- return E_NOTIMPL;
- }
- ok(hr == S_OK, "IBaseFilter_QueryFilterInfo failed with %x\n", hr);
- IBaseFilter_Release(pinInfo.pFilter);
-
- IFilterGraph_Release(filterInfo.pGraph);
-
- WideCharToMultiByte(CP_ACP, 0, filterInfo.achName, -1, FilterName, MAX_FILTER_NAME, NULL, NULL);
-
- return S_OK;
-}
-
-static void test_render_filter_priority(void)
-{
- /* Tests filter choice priorities in Render(). */
- DWORD cookie1 = 0, cookie2 = 0, cookie3 = 0;
- HRESULT hr;
- IFilterGraph2* pgraph2 = NULL;
- IFilterMapper2 *pMapper2 = NULL;
- TestFilterImpl *ptestfilter = NULL;
- TestFilterImpl *ptestfilter2 = NULL;
- static const CLSID CLSID_TestFilter2 = {
- 0x37a4edb0,
- 0x4d13,
- 0x11dd,
- {0xe8, 0x9b, 0x00, 0x19, 0x66, 0x2f, 0xf0, 0xce}
- };
- static const CLSID CLSID_TestFilter3 = {
- 0x37a4f2d8,
- 0x4d13,
- 0x11dd,
- {0xe8, 0x9b, 0x00, 0x19, 0x66, 0x2f, 0xf0, 0xce}
- };
- static const CLSID CLSID_TestFilter4 = {
- 0x37a4f3b4,
- 0x4d13,
- 0x11dd,
- {0xe8, 0x9b, 0x00, 0x19, 0x66, 0x2f, 0xf0, 0xce}
- };
- static const GUID mediasubtype1 = {
- 0x37a4f51c,
- 0x4d13,
- 0x11dd,
- {0xe8, 0x9b, 0x00, 0x19, 0x66, 0x2f, 0xf0, 0xce}
- };
- static const GUID mediasubtype2 = {
- 0x37a4f5c6,
- 0x4d13,
- 0x11dd,
- {0xe8, 0x9b, 0x00, 0x19, 0x66, 0x2f, 0xf0, 0xce}
- };
- static const TestFilterPinData PinData1[] = {
- { PINDIR_OUTPUT, &mediasubtype1 },
- { 0, 0 }
- };
- static const TestFilterPinData PinData2[] = {
- { PINDIR_INPUT, &mediasubtype1 },
- { 0, 0 }
- };
- static const TestFilterPinData PinData3[] = {
- { PINDIR_INPUT, &GUID_NULL },
- { 0, 0 }
- };
- static const TestFilterPinData PinData4[] = {
- { PINDIR_INPUT, &mediasubtype1 },
- { PINDIR_OUTPUT, &mediasubtype2 },
- { 0, 0 }
- };
- static const TestFilterPinData PinData5[] = {
- { PINDIR_INPUT, &mediasubtype2 },
- { 0, 0 }
- };
- TestClassFactoryImpl Filter1ClassFactory = {
- { &TestClassFactory_Vtbl },
- PinData2, &CLSID_TestFilter2
- };
- TestClassFactoryImpl Filter2ClassFactory = {
- { &TestClassFactory_Vtbl },
- PinData4, &CLSID_TestFilter3
- };
- TestClassFactoryImpl Filter3ClassFactory = {
- { &TestClassFactory_Vtbl },
- PinData5, &CLSID_TestFilter4
- };
- char ConnectedFilterName1[MAX_FILTER_NAME];
- char ConnectedFilterName2[MAX_FILTER_NAME];
- REGFILTER2 rgf2;
- REGFILTERPINS2 rgPins2[2];
- REGPINTYPES rgPinType[2];
- static const WCHAR wszFilterInstanceName1[] = {'T', 'e', 's', 't', 'f', 'i', 'l', 't', 'e', 'r', 'I',
- 'n', 's', 't', 'a', 'n', 'c', 'e', '1', 0 };
- static const WCHAR wszFilterInstanceName2[] = {'T', 'e', 's', 't', 'f', 'i', 'l', 't', 'e', 'r', 'I',
- 'n', 's', 't', 'a', 'n', 'c', 'e', '2', 0 };
- static const WCHAR wszFilterInstanceName3[] = {'T', 'e', 's', 't', 'f', 'i', 'l', 't', 'e', 'r', 'I',
- 'n', 's', 't', 'a', 'n', 'c', 'e', '3', 0 };
- static const WCHAR wszFilterInstanceName4[] = {'T', 'e', 's', 't', 'f', 'i', 'l', 't', 'e', 'r', 'I',
- 'n', 's', 't', 'a', 'n', 'c', 'e', '4', 0 };
-
- /* Test which renderer of two already added to the graph will be chosen
- * (one is "exact" match, other is "wildcard" match. Seems to depend
- * on the order in which filters are added to the graph, thus indicating
- * no preference given to exact match. */
- pgraph2 = create_graph();
-
- hr = createtestfilter(&GUID_NULL, PinData1, &ptestfilter);
- ok(hr == S_OK, "createtestfilter failed with %08x\n", hr);
-
- hr = IFilterGraph2_AddFilter(pgraph2, &ptestfilter->IBaseFilter_iface, wszFilterInstanceName1);
- ok(hr == S_OK, "IFilterGraph2_AddFilter failed with %08x\n", hr);
-
- hr = createtestfilter(&GUID_NULL, PinData2, &ptestfilter2);
- ok(hr == S_OK, "createtestfilter failed with %08x\n", hr);
-
- hr = IFilterGraph2_AddFilter(pgraph2, &ptestfilter2->IBaseFilter_iface, wszFilterInstanceName2);
- ok(hr == S_OK, "IFilterGraph2_AddFilter failed with %08x\n", hr);
-
- IBaseFilter_Release(&ptestfilter2->IBaseFilter_iface);
-
- hr = createtestfilter(&GUID_NULL, PinData3, &ptestfilter2);
- ok(hr == S_OK, "createtestfilter failed with %08x\n", hr);
-
- hr = IFilterGraph2_AddFilter(pgraph2, &ptestfilter2->IBaseFilter_iface, wszFilterInstanceName3);
- ok(hr == S_OK, "IFilterGraph2_AddFilter failed with %08x\n", hr);
-
- hr = IFilterGraph2_Render(pgraph2, ptestfilter->ppPins[0]);
- ok(hr == S_OK, "IFilterGraph2_Render failed with %08x\n", hr);
-
- hr = get_connected_filter_name(ptestfilter, ConnectedFilterName1);
-
- IFilterGraph2_Release(pgraph2);
- IBaseFilter_Release(&ptestfilter->IBaseFilter_iface);
- IBaseFilter_Release(&ptestfilter2->IBaseFilter_iface);
-
- pgraph2 = create_graph();
-
- hr = createtestfilter(&GUID_NULL, PinData1, &ptestfilter);
- ok(hr == S_OK, "createtestfilter failed with %08x\n", hr);
-
- hr = IFilterGraph2_AddFilter(pgraph2, &ptestfilter->IBaseFilter_iface, wszFilterInstanceName1);
- ok(hr == S_OK, "IFilterGraph2_AddFilter failed with %08x\n", hr);
-
- hr = createtestfilter(&GUID_NULL, PinData3, &ptestfilter2);
- ok(hr == S_OK, "createtestfilter failed with %08x\n", hr);
-
- hr = IFilterGraph2_AddFilter(pgraph2, &ptestfilter2->IBaseFilter_iface, wszFilterInstanceName3);
- ok(hr == S_OK, "IFilterGraph2_AddFilter failed with %08x\n", hr);
-
- IBaseFilter_Release(&ptestfilter2->IBaseFilter_iface);
-
- hr = createtestfilter(&GUID_NULL, PinData2, &ptestfilter2);
- ok(hr == S_OK, "createtestfilter failed with %08x\n", hr);
-
- hr = IFilterGraph2_AddFilter(pgraph2, &ptestfilter2->IBaseFilter_iface, wszFilterInstanceName2);
- ok(hr == S_OK, "IFilterGraph2_AddFilter failed with %08x\n", hr);
-
- hr = IFilterGraph2_Render(pgraph2, ptestfilter->ppPins[0]);
- ok(hr == S_OK, "IFilterGraph2_Render failed with %08x\n", hr);
-
- hr = IFilterGraph2_Disconnect(pgraph2, NULL);
- ok(hr == E_POINTER, "IFilterGraph2_Disconnect failed. Expected E_POINTER, received %08x\n", hr);
-
- get_connected_filter_name(ptestfilter, ConnectedFilterName2);
- ok(strcmp(ConnectedFilterName1, ConnectedFilterName2),
- "expected connected filters to be different but got %s both times\n", ConnectedFilterName1);
-
- IFilterGraph2_Release(pgraph2);
- IBaseFilter_Release(&ptestfilter->IBaseFilter_iface);
- IBaseFilter_Release(&ptestfilter2->IBaseFilter_iface);
-
- /* Test if any preference is given to existing renderer which renders the pin directly vs
- an existing renderer which renders the pin indirectly, through an additional middle filter,
- again trying different orders of creation. Native appears not to give a preference. */
-
- pgraph2 = create_graph();
-
- hr = createtestfilter(&GUID_NULL, PinData1, &ptestfilter);
- ok(hr == S_OK, "createtestfilter failed with %08x\n", hr);
-
- hr = IFilterGraph2_AddFilter(pgraph2, &ptestfilter->IBaseFilter_iface, wszFilterInstanceName1);
- ok(hr == S_OK, "IFilterGraph2_AddFilter failed with %08x\n", hr);
-
- hr = createtestfilter(&GUID_NULL, PinData2, &ptestfilter2);
- ok(hr == S_OK, "createtestfilter failed with %08x\n", hr);
-
- hr = IFilterGraph2_AddFilter(pgraph2, &ptestfilter2->IBaseFilter_iface, wszFilterInstanceName2);
- ok(hr == S_OK, "IFilterGraph2_AddFilter failed with %08x\n", hr);
-
- IBaseFilter_Release(&ptestfilter2->IBaseFilter_iface);
-
- hr = createtestfilter(&GUID_NULL, PinData4, &ptestfilter2);
- ok(hr == S_OK, "createtestfilter failed with %08x\n", hr);
-
- hr = IFilterGraph2_AddFilter(pgraph2, &ptestfilter2->IBaseFilter_iface, wszFilterInstanceName3);
- ok(hr == S_OK, "IFilterGraph2_AddFilter failed with %08x\n", hr);
-
- IBaseFilter_Release(&ptestfilter2->IBaseFilter_iface);
-
- hr = createtestfilter(&GUID_NULL, PinData5, &ptestfilter2);
- ok(hr == S_OK, "createtestfilter failed with %08x\n", hr);
-
- hr = IFilterGraph2_AddFilter(pgraph2, &ptestfilter2->IBaseFilter_iface, wszFilterInstanceName4);
- ok(hr == S_OK, "IFilterGraph2_AddFilter failed with %08x\n", hr);
-
- hr = IFilterGraph2_Render(pgraph2, ptestfilter->ppPins[0]);
- ok(hr == S_OK, "IFilterGraph2_Render failed with %08x\n", hr);
-
- get_connected_filter_name(ptestfilter, ConnectedFilterName1);
- ok(!strcmp(ConnectedFilterName1, "TestfilterInstance3") || !strcmp(ConnectedFilterName1, "TestfilterInstance2"),
- "unexpected connected filter: %s\n", ConnectedFilterName1);
-
- IFilterGraph2_Release(pgraph2);
- IBaseFilter_Release(&ptestfilter->IBaseFilter_iface);
- IBaseFilter_Release(&ptestfilter2->IBaseFilter_iface);
-
- pgraph2 = create_graph();
-
- hr = createtestfilter(&GUID_NULL, PinData1, &ptestfilter);
- ok(hr == S_OK, "createtestfilter failed with %08x\n", hr);
-
- hr = IFilterGraph2_AddFilter(pgraph2, &ptestfilter->IBaseFilter_iface, wszFilterInstanceName1);
- ok(hr == S_OK, "IFilterGraph2_AddFilter failed with %08x\n", hr);
-
- hr = createtestfilter(&GUID_NULL, PinData4, &ptestfilter2);
- ok(hr == S_OK, "createtestfilter failed with %08x\n", hr);
-
- hr = IFilterGraph2_AddFilter(pgraph2, &ptestfilter2->IBaseFilter_iface, wszFilterInstanceName3);
- ok(hr == S_OK, "IFilterGraph2_AddFilter failed with %08x\n", hr);
-
- IBaseFilter_Release(&ptestfilter2->IBaseFilter_iface);
-
- hr = createtestfilter(&GUID_NULL, PinData5, &ptestfilter2);
- ok(hr == S_OK, "createtestfilter failed with %08x\n", hr);
-
- hr = IFilterGraph2_AddFilter(pgraph2, &ptestfilter2->IBaseFilter_iface, wszFilterInstanceName4);
- ok(hr == S_OK, "IFilterGraph2_AddFilter failed with %08x\n", hr);
-
- IBaseFilter_Release(&ptestfilter2->IBaseFilter_iface);
-
- hr = createtestfilter(&GUID_NULL, PinData2, &ptestfilter2);
- ok(hr == S_OK, "createtestfilter failed with %08x\n", hr);
-
- hr = IFilterGraph2_AddFilter(pgraph2, &ptestfilter2->IBaseFilter_iface, wszFilterInstanceName2);
- ok(hr == S_OK, "IFilterGraph2_AddFilter failed with %08x\n", hr);
-
- hr = IFilterGraph2_Render(pgraph2, ptestfilter->ppPins[0]);
- ok(hr == S_OK, "IFilterGraph2_Render failed with %08x\n", hr);
-
- get_connected_filter_name(ptestfilter, ConnectedFilterName2);
- ok(!strcmp(ConnectedFilterName2, "TestfilterInstance3") || !strcmp(ConnectedFilterName2, "TestfilterInstance2"),
- "unexpected connected filter: %s\n", ConnectedFilterName2);
- ok(strcmp(ConnectedFilterName1, ConnectedFilterName2),
- "expected connected filters to be different but got %s both times\n", ConnectedFilterName1);
-
- IFilterGraph2_Release(pgraph2);
- IBaseFilter_Release(&ptestfilter->IBaseFilter_iface);
- IBaseFilter_Release(&ptestfilter2->IBaseFilter_iface);
-
- /* Test if renderers are tried before non-renderers (intermediary filters). */
- pgraph2 = create_graph();
-
- hr = CoCreateInstance(&CLSID_FilterMapper2, NULL, CLSCTX_INPROC_SERVER, &IID_IFilterMapper2, (LPVOID*)&pMapper2);
- ok(hr == S_OK, "CoCreateInstance failed with %08x\n", hr);
-
- hr = createtestfilter(&GUID_NULL, PinData1, &ptestfilter);
- ok(hr == S_OK, "createtestfilter failed with %08x\n", hr);
-
- hr = IFilterGraph2_AddFilter(pgraph2, &ptestfilter->IBaseFilter_iface, wszFilterInstanceName1);
- ok(hr == S_OK, "IFilterGraph2_AddFilter failed with %08x\n", hr);
-
- /* Register our filters with COM and with Filtermapper. */
- hr = CoRegisterClassObject(Filter1ClassFactory.clsid,
- (IUnknown *)&Filter1ClassFactory.IClassFactory_iface, CLSCTX_INPROC_SERVER,
- REGCLS_MULTIPLEUSE, &cookie1);
- ok(hr == S_OK, "CoRegisterClassObject failed with %08x\n", hr);
- hr = CoRegisterClassObject(Filter2ClassFactory.clsid,
- (IUnknown *)&Filter2ClassFactory.IClassFactory_iface, CLSCTX_INPROC_SERVER,
- REGCLS_MULTIPLEUSE, &cookie2);
- ok(hr == S_OK, "CoRegisterClassObject failed with %08x\n", hr);
- hr = CoRegisterClassObject(Filter3ClassFactory.clsid,
- (IUnknown *)&Filter3ClassFactory.IClassFactory_iface, CLSCTX_INPROC_SERVER,
- REGCLS_MULTIPLEUSE, &cookie3);
- ok(hr == S_OK, "CoRegisterClassObject failed with %08x\n", hr);
-
- rgf2.dwVersion = 2;
- rgf2.dwMerit = MERIT_UNLIKELY;
- S2(U(rgf2)).cPins2 = 1;
- S2(U(rgf2)).rgPins2 = rgPins2;
- rgPins2[0].dwFlags = REG_PINFLAG_B_RENDERER;
- rgPins2[0].cInstances = 1;
- rgPins2[0].nMediaTypes = 1;
- rgPins2[0].lpMediaType = &rgPinType[0];
- rgPins2[0].nMediums = 0;
- rgPins2[0].lpMedium = NULL;
- rgPins2[0].clsPinCategory = NULL;
- rgPinType[0].clsMajorType = &MEDIATYPE_Video;
- rgPinType[0].clsMinorType = &mediasubtype1;
-
- hr = IFilterMapper2_RegisterFilter(pMapper2, &CLSID_TestFilter2, wszFilterInstanceName2, NULL,
- &CLSID_LegacyAmFilterCategory, NULL, &rgf2);
+ ULONG ref;
+
+ memset(&source_type.majortype, 0xcc, sizeof(GUID));
+ testsource_init(&source_pin, &source_type, 1);
+ testfilter_init(&source, &source_pin, 1);
+ testsink_init(&sink1_pin);
+ testfilter_init(&sink1, &sink1_pin, 1);
+ testsink_init(&sink2_pin);
+ testfilter_init(&sink2, &sink2_pin, 1);
+ testsink_init(&parser_pins[0]);
+ testsource_init(&parser_pins[1], &source_type, 1);
+ testfilter_init(&parser, parser_pins, 2);
+
+ IFilterGraph2_AddFilter(graph, &source.IBaseFilter_iface, NULL);
+ IFilterGraph2_AddFilter(graph, &sink1.IBaseFilter_iface, NULL);
+ IFilterGraph2_AddFilter(graph, &sink2.IBaseFilter_iface, NULL);
+
+ hr = IFilterGraph2_Render(graph, &source_pin.IPin_iface);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(source_pin.peer == &sink2_pin.IPin_iface, "Got peer %p.\n", source_pin.peer);
+ IFilterGraph2_Disconnect(graph, source_pin.peer);
+ IFilterGraph2_Disconnect(graph, &source_pin.IPin_iface);
+
+ IFilterGraph2_RemoveFilter(graph, &sink1.IBaseFilter_iface);
+ IFilterGraph2_AddFilter(graph, &sink1.IBaseFilter_iface, NULL);
+
+ hr = IFilterGraph2_Render(graph, &source_pin.IPin_iface);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(source_pin.peer == &sink1_pin.IPin_iface, "Got peer %p.\n", source_pin.peer);
+
+ IFilterGraph2_Disconnect(graph, &source_pin.IPin_iface);
+ IFilterGraph2_Disconnect(graph, &sink1_pin.IPin_iface);
+
+ /* No preference is given to smaller chains. */
+
+ IFilterGraph2_AddFilter(graph, &parser.IBaseFilter_iface, NULL);
+
+ hr = IFilterGraph2_Render(graph, &source_pin.IPin_iface);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(source_pin.peer == &parser_pins[0].IPin_iface, "Got peer %p.\n", source_pin.peer);
+ ok(parser_pins[1].peer == &sink1_pin.IPin_iface, "Got peer %p.\n", parser_pins[1].peer);
+ IFilterGraph2_Disconnect(graph, source_pin.peer);
+ IFilterGraph2_Disconnect(graph, &source_pin.IPin_iface);
+
+ IFilterGraph2_RemoveFilter(graph, &sink1.IBaseFilter_iface);
+ IFilterGraph2_AddFilter(graph, &sink1.IBaseFilter_iface, NULL);
+
+ hr = IFilterGraph2_Render(graph, &source_pin.IPin_iface);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(source_pin.peer == &sink1_pin.IPin_iface, "Got peer %p.\n", source_pin.peer);
+
+ ref = IFilterGraph2_Release(graph);
+ ok(!ref, "Got outstanding refcount %d.\n", ref);
+
+ /* Test enumeration of filters from the registry. */
+
+ graph = create_graph();
+ IFilterGraph2_AddFilter(graph, &source.IBaseFilter_iface, NULL);
+
+ CoRegisterClassObject(&sink1_clsid, (IUnknown *)&sink1_cf.IClassFactory_iface,
+ CLSCTX_INPROC_SERVER, REGCLS_MULTIPLEUSE, &cookie1);
+ CoRegisterClassObject(&sink2_clsid, (IUnknown *)&sink2_cf.IClassFactory_iface,
+ CLSCTX_INPROC_SERVER, REGCLS_MULTIPLEUSE, &cookie2);
+
+ CoCreateInstance(&CLSID_FilterMapper2, NULL, CLSCTX_INPROC_SERVER,
+ &IID_IFilterMapper2, (void **)&mapper);
+
+ regfilter.dwVersion = 2;
+ regfilter.dwMerit = MERIT_UNLIKELY;
+ regfilter.cPins2 = 1;
+ regfilter.rgPins2 = ®pins;
+ regpins.dwFlags = 0;
+ regpins.cInstances = 1;
+ regpins.nMediaTypes = 1;
+ regpins.lpMediaType = ®types;
+ regtypes.clsMajorType = &source_type.majortype;
+ regtypes.clsMinorType = &MEDIASUBTYPE_NULL;
+ hr = IFilterMapper2_RegisterFilter(mapper, &sink1_clsid, testW, NULL, NULL, NULL, ®filter);
if (hr == E_ACCESSDENIED)
- skip("Not authorized to register filters\n");
- else
{
- ok(hr == S_OK, "IFilterMapper2_RegisterFilter failed with %x\n", hr);
-
- rgf2.dwMerit = MERIT_PREFERRED;
- rgPinType[0].clsMinorType = &mediasubtype2;
-
- hr = IFilterMapper2_RegisterFilter(pMapper2, &CLSID_TestFilter4, wszFilterInstanceName4, NULL,
- &CLSID_LegacyAmFilterCategory, NULL, &rgf2);
- ok(hr == S_OK, "IFilterMapper2_RegisterFilter failed with %x\n", hr);
-
- S2(U(rgf2)).cPins2 = 2;
- rgPins2[0].dwFlags = 0;
- rgPinType[0].clsMinorType = &mediasubtype1;
-
- rgPins2[1].dwFlags = REG_PINFLAG_B_OUTPUT;
- rgPins2[1].cInstances = 1;
- rgPins2[1].nMediaTypes = 1;
- rgPins2[1].lpMediaType = &rgPinType[1];
- rgPins2[1].nMediums = 0;
- rgPins2[1].lpMedium = NULL;
- rgPins2[1].clsPinCategory = NULL;
- rgPinType[1].clsMajorType = &MEDIATYPE_Video;
- rgPinType[1].clsMinorType = &mediasubtype2;
-
- hr = IFilterMapper2_RegisterFilter(pMapper2, &CLSID_TestFilter3, wszFilterInstanceName3, NULL,
- &CLSID_LegacyAmFilterCategory, NULL, &rgf2);
- ok(hr == S_OK, "IFilterMapper2_RegisterFilter failed with %x\n", hr);
-
- hr = IFilterGraph2_Render(pgraph2, ptestfilter->ppPins[0]);
- ok(hr == S_OK, "IFilterGraph2_Render failed with %08x\n", hr);
-
- get_connected_filter_name(ptestfilter, ConnectedFilterName1);
- ok(!strcmp(ConnectedFilterName1, "TestfilterInstance3"),
- "unexpected connected filter: %s\n", ConnectedFilterName1);
-
- hr = IFilterMapper2_UnregisterFilter(pMapper2, &CLSID_LegacyAmFilterCategory, NULL,
- &CLSID_TestFilter2);
- ok(hr == S_OK, "IFilterMapper2_UnregisterFilter failed with %x\n", hr);
- hr = IFilterMapper2_UnregisterFilter(pMapper2, &CLSID_LegacyAmFilterCategory, NULL,
- &CLSID_TestFilter3);
- ok(hr == S_OK, "IFilterMapper2_UnregisterFilter failed with %x\n", hr);
- hr = IFilterMapper2_UnregisterFilter(pMapper2, &CLSID_LegacyAmFilterCategory, NULL,
- &CLSID_TestFilter4);
- ok(hr == S_OK, "IFilterMapper2_UnregisterFilter failed with %x\n", hr);
+ skip("Not enough permission to register filters.\n");
+ goto out;
}
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
- IBaseFilter_Release(&ptestfilter->IBaseFilter_iface);
- IFilterGraph2_Release(pgraph2);
- IFilterMapper2_Release(pMapper2);
+ regpins.dwFlags = REG_PINFLAG_B_RENDERER;
+ IFilterMapper2_RegisterFilter(mapper, &sink2_clsid, testW, NULL, NULL, NULL, ®filter);
- hr = CoRevokeClassObject(cookie1);
- ok(hr == S_OK, "CoRevokeClassObject failed with %08x\n", hr);
- hr = CoRevokeClassObject(cookie2);
- ok(hr == S_OK, "CoRevokeClassObject failed with %08x\n", hr);
- hr = CoRevokeClassObject(cookie3);
- ok(hr == S_OK, "CoRevokeClassObject failed with %08x\n", hr);
+ hr = IFilterGraph2_Render(graph, &source_pin.IPin_iface);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(source_pin.peer == &sink2_pin.IPin_iface || source_pin.peer == &sink1_pin.IPin_iface,
+ "Got peer %p.\n", source_pin.peer);
+
+ ref = IFilterGraph2_Release(graph);
+ ok(!ref, "Got outstanding refcount %d.\n", ref);
+
+ /* Preference is given to filters already in the graph. */
+
+ graph = create_graph();
+ IFilterGraph2_AddFilter(graph, &source.IBaseFilter_iface, NULL);
+ IFilterGraph2_AddFilter(graph, &sink2.IBaseFilter_iface, NULL);
+
+ hr = IFilterGraph2_Render(graph, &source_pin.IPin_iface);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(source_pin.peer == &sink2_pin.IPin_iface, "Got peer %p.\n", source_pin.peer);
+
+ ref = IFilterGraph2_Release(graph);
+ ok(!ref, "Got outstanding refcount %d.\n", ref);
+
+ /* No preference is given to renderer filters. */
+
+ graph = create_graph();
+ IFilterGraph2_AddFilter(graph, &source.IBaseFilter_iface, NULL);
+
+ IFilterMapper2_UnregisterFilter(mapper, NULL, NULL, &sink1_clsid);
+ IFilterMapper2_UnregisterFilter(mapper, NULL, NULL, &sink2_clsid);
+
+ IFilterMapper2_RegisterFilter(mapper, &sink1_clsid, testW, NULL, NULL, NULL, ®filter);
+ regpins.dwFlags = 0;
+ IFilterMapper2_RegisterFilter(mapper, &sink2_clsid, testW, NULL, NULL, NULL, ®filter);
+
+ hr = IFilterGraph2_Render(graph, &source_pin.IPin_iface);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(source_pin.peer == &sink2_pin.IPin_iface || source_pin.peer == &sink1_pin.IPin_iface,
+ "Got peer %p.\n", source_pin.peer);
+
+ ref = IFilterGraph2_Release(graph);
+ ok(!ref, "Got outstanding refcount %d.\n", ref);
+
+ /* Preference is given to filters with higher merit. */
+
+ graph = create_graph();
+ IFilterGraph2_AddFilter(graph, &source.IBaseFilter_iface, NULL);
+
+ IFilterMapper2_UnregisterFilter(mapper, NULL, NULL, &sink1_clsid);
+ IFilterMapper2_UnregisterFilter(mapper, NULL, NULL, &sink2_clsid);
+
+ regfilter.dwMerit = MERIT_UNLIKELY;
+ IFilterMapper2_RegisterFilter(mapper, &sink1_clsid, testW, NULL, NULL, NULL, ®filter);
+ regfilter.dwMerit = MERIT_PREFERRED;
+ IFilterMapper2_RegisterFilter(mapper, &sink2_clsid, testW, NULL, NULL, NULL, ®filter);
+
+ hr = IFilterGraph2_Render(graph, &source_pin.IPin_iface);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(source_pin.peer == &sink2_pin.IPin_iface, "Got peer %p.\n", source_pin.peer);
+
+ ref = IFilterGraph2_Release(graph);
+ ok(!ref, "Got outstanding refcount %d.\n", ref);
+
+ graph = create_graph();
+ IFilterGraph2_AddFilter(graph, &source.IBaseFilter_iface, NULL);
+
+ IFilterMapper2_UnregisterFilter(mapper, NULL, NULL, &sink1_clsid);
+ IFilterMapper2_UnregisterFilter(mapper, NULL, NULL, &sink2_clsid);
+
+ regfilter.dwMerit = MERIT_PREFERRED;
+ IFilterMapper2_RegisterFilter(mapper, &sink1_clsid, testW, NULL, NULL, NULL, ®filter);
+ regfilter.dwMerit = MERIT_UNLIKELY;
+ IFilterMapper2_RegisterFilter(mapper, &sink2_clsid, testW, NULL, NULL, NULL, ®filter);
+
+ hr = IFilterGraph2_Render(graph, &source_pin.IPin_iface);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(source_pin.peer == &sink1_pin.IPin_iface, "Got peer %p.\n", source_pin.peer);
+
+ IFilterMapper2_UnregisterFilter(mapper, NULL, NULL, &sink1_clsid);
+ IFilterMapper2_UnregisterFilter(mapper, NULL, NULL, &sink2_clsid);
+
+out:
+ CoRevokeClassObject(cookie1);
+ CoRevokeClassObject(cookie2);
+ IFilterMapper2_Release(mapper);
+ ref = IFilterGraph2_Release(graph);
+ ok(!ref, "Got outstanding refcount %d.\n", ref);
+ ok(source.ref == 1, "Got outstanding refcount %d.\n", source.ref);
+ ok(source_pin.ref == 1, "Got outstanding refcount %d.\n", source_pin.ref);
+ ok(sink1.ref == 1, "Got outstanding refcount %d.\n", sink1.ref);
+ ok(sink1_pin.ref == 1, "Got outstanding refcount %d.\n", sink1_pin.ref);
+ ok(sink2.ref == 1, "Got outstanding refcount %d.\n", sink2.ref);
+ ok(sink2_pin.ref == 1, "Got outstanding refcount %d.\n", sink2_pin.ref);
+ ok(parser.ref == 1, "Got outstanding refcount %d.\n", parser.ref);
+ ok(parser_pins[0].ref == 1, "Got outstanding refcount %d.\n", parser_pins[0].ref);
+ ok(parser_pins[1].ref == 1, "Got outstanding refcount %d.\n", parser_pins[1].ref);
}
typedef struct IUnknownImpl
@@ -2499,7 +1831,7 @@ START_TEST(filtergraph)
test_render_run(mpegfile);
test_enum_filters();
test_graph_builder();
- test_render_filter_priority();
+ test_graph_builder_render();
test_aggregate_filter_graph();
test_control_delegation();
--
2.7.4
Sept. 18, 2018
[PATCH v2 5/6] quartz/filtergraph: Use a linked list to store filters.
by Zebediah Figura
Signed-off-by: Zebediah Figura <z.figura12(a)gmail.com>
---
dlls/quartz/filtergraph.c | 215 +++++++++++++++++++---------------------
dlls/quartz/tests/filtergraph.c | 7 --
2 files changed, 100 insertions(+), 122 deletions(-)
diff --git a/dlls/quartz/filtergraph.c b/dlls/quartz/filtergraph.c
index 76cc0c7..9d34bd4 100644
--- a/dlls/quartz/filtergraph.c
+++ b/dlls/quartz/filtergraph.c
@@ -37,6 +37,7 @@
#include "vfwmsgs.h"
#include "evcode.h"
#include "wine/heap.h"
+#include "wine/list.h"
#include "wine/unicode.h"
@@ -149,6 +150,13 @@ typedef struct _ITF_CACHE_ENTRY {
IUnknown* iface;
} ITF_CACHE_ENTRY;
+struct filter
+{
+ struct list entry;
+ IBaseFilter *filter;
+ WCHAR *name;
+};
+
typedef struct _IFilterGraphImpl {
IUnknown IUnknown_inner;
IFilterGraph2 IFilterGraph2_iface;
@@ -177,10 +185,7 @@ typedef struct _IFilterGraphImpl {
IUnknown *outer_unk;
LONG ref;
IUnknown *punkFilterMapper2;
- IBaseFilter ** ppFiltersInGraph;
- LPWSTR * pFilterNames;
- ULONG nFilters;
- int filterCapacity;
+ struct list filters;
LONG nameIndex;
IReferenceClock *refClock;
IBaseFilter *refClockProvider;
@@ -213,10 +218,10 @@ struct enum_filters
LONG ref;
IFilterGraphImpl *graph;
LONG version;
- ULONG index;
+ struct list *cursor;
};
-static HRESULT create_enum_filters(IFilterGraphImpl *graph, IEnumFilters **out);
+static HRESULT create_enum_filters(IFilterGraphImpl *graph, struct list *cursor, IEnumFilters **out);
static inline struct enum_filters *impl_from_IEnumFilters(IEnumFilters *iface)
{
@@ -269,33 +274,32 @@ static HRESULT WINAPI EnumFilters_Next(IEnumFilters *iface, ULONG count,
IBaseFilter **filters, ULONG *fetched)
{
struct enum_filters *enum_filters = impl_from_IEnumFilters(iface);
- unsigned int i, cFetched;
+ unsigned int i = 0;
TRACE("enum_filters %p, count %u, filters %p, fetched %p.\n",
enum_filters, count, filters, fetched);
- cFetched = min(enum_filters->graph->nFilters, enum_filters->index + count) - enum_filters->index;
-
if (enum_filters->version != enum_filters->graph->version)
return VFW_E_ENUM_OUT_OF_SYNC;
if (!filters)
return E_POINTER;
- for (i = 0; i < cFetched; i++)
+ for (i = 0; i < count; ++i)
{
- filters[i] = enum_filters->graph->ppFiltersInGraph[enum_filters->index + i];
- IBaseFilter_AddRef(filters[i]);
+ struct filter *filter = LIST_ENTRY(enum_filters->cursor, struct filter, entry);
+
+ if (!enum_filters->cursor)
+ break;
+
+ IBaseFilter_AddRef(filters[i] = filter->filter);
+ enum_filters->cursor = list_next(&enum_filters->graph->filters, enum_filters->cursor);
}
- enum_filters->index += cFetched;
-
if (fetched)
- *fetched = cFetched;
+ *fetched = i;
- if (cFetched != count)
- return S_FALSE;
- return S_OK;
+ return (i == count) ? S_OK : S_FALSE;
}
static HRESULT WINAPI EnumFilters_Skip(IEnumFilters *iface, ULONG count)
@@ -304,12 +308,16 @@ static HRESULT WINAPI EnumFilters_Skip(IEnumFilters *iface, ULONG count)
TRACE("enum_filters %p, count %u.\n", enum_filters, count);
- if (enum_filters->index + count < enum_filters->graph->nFilters)
+ if (!enum_filters->cursor)
+ return S_FALSE;
+
+ while (count--)
{
- enum_filters->index += count;
- return S_OK;
+ if (!(enum_filters->cursor = list_next(&enum_filters->graph->filters, enum_filters->cursor)))
+ return S_FALSE;
}
- return S_FALSE;
+
+ return S_OK;
}
static HRESULT WINAPI EnumFilters_Reset(IEnumFilters *iface)
@@ -318,7 +326,7 @@ static HRESULT WINAPI EnumFilters_Reset(IEnumFilters *iface)
TRACE("enum_filters %p.\n", enum_filters);
- enum_filters->index = 0;
+ enum_filters->cursor = list_head(&enum_filters->graph->filters);
enum_filters->version = enum_filters->graph->version;
return S_OK;
}
@@ -326,14 +334,10 @@ static HRESULT WINAPI EnumFilters_Reset(IEnumFilters *iface)
static HRESULT WINAPI EnumFilters_Clone(IEnumFilters *iface, IEnumFilters **out)
{
struct enum_filters *enum_filters = impl_from_IEnumFilters(iface);
- HRESULT hr;
TRACE("enum_filters %p, out %p.\n", enum_filters, out);
- hr = create_enum_filters(enum_filters->graph, out);
- if (FAILED(hr))
- return hr;
- return IEnumFilters_Skip(*out, enum_filters->index);
+ return create_enum_filters(enum_filters->graph, enum_filters->cursor, out);
}
static const IEnumFiltersVtbl EnumFilters_vtbl =
@@ -347,7 +351,7 @@ static const IEnumFiltersVtbl EnumFilters_vtbl =
EnumFilters_Clone,
};
-static HRESULT create_enum_filters(IFilterGraphImpl *graph, IEnumFilters **out)
+static HRESULT create_enum_filters(IFilterGraphImpl *graph, struct list *cursor, IEnumFilters **out)
{
struct enum_filters *enum_filters;
@@ -356,7 +360,7 @@ static HRESULT create_enum_filters(IFilterGraphImpl *graph, IEnumFilters **out)
enum_filters->IEnumFilters_iface.lpVtbl = &EnumFilters_vtbl;
enum_filters->ref = 1;
- enum_filters->index = 0;
+ enum_filters->cursor = cursor;
enum_filters->graph = graph;
IUnknown_AddRef(graph->outer_unk);
enum_filters->version = graph->version;
@@ -455,6 +459,7 @@ static ULONG WINAPI FilterGraphInner_Release(IUnknown *iface)
{
IFilterGraphImpl *This = impl_from_IUnknown(iface);
ULONG ref = InterlockedDecrement(&This->ref);
+ struct filter *filter, *next;
TRACE("(%p)->(): new ref = %d\n", This, ref);
@@ -465,8 +470,10 @@ static ULONG WINAPI FilterGraphInner_Release(IUnknown *iface)
IMediaControl_Stop(&This->IMediaControl_iface);
- while (This->nFilters)
- IFilterGraph2_RemoveFilter(&This->IFilterGraph2_iface, This->ppFiltersInGraph[0]);
+ LIST_FOR_EACH_ENTRY_SAFE(filter, next, &This->filters, struct filter, entry)
+ {
+ IFilterGraph2_RemoveFilter(&This->IFilterGraph2_iface, filter->filter);
+ }
if (This->refClock)
IReferenceClock_Release(This->refClock);
@@ -485,8 +492,6 @@ static ULONG WINAPI FilterGraphInner_Release(IUnknown *iface)
EventsQueue_Destroy(&This->evqueue);
This->cs.DebugInfo->Spare[0] = 0;
DeleteCriticalSection(&This->cs);
- CoTaskMemFree(This->ppFiltersInGraph);
- CoTaskMemFree(This->pFilterNames);
CoTaskMemFree(This);
}
return ref;
@@ -526,12 +531,12 @@ static ULONG WINAPI FilterGraph2_Release(IFilterGraph2 *iface)
static IBaseFilter *find_filter_by_name(IFilterGraphImpl *graph, const WCHAR *name)
{
- unsigned int i;
+ struct filter *filter;
- for (i = 0; i < graph->nFilters; ++i)
+ LIST_FOR_EACH_ENTRY(filter, &graph->filters, struct filter, entry)
{
- if (!strcmpW(graph->pFilterNames[i], name))
- return graph->ppFiltersInGraph[i];
+ if (!strcmpW(filter->name, name))
+ return filter->filter;
}
return NULL;
@@ -542,6 +547,7 @@ static HRESULT WINAPI FilterGraph2_AddFilter(IFilterGraph2 *iface, IBaseFilter *
LPCWSTR pName)
{
IFilterGraphImpl *This = impl_from_IFilterGraph2(iface);
+ struct filter *entry;
HRESULT hr;
int j;
WCHAR* wszFilterName = NULL;
@@ -588,46 +594,31 @@ static HRESULT WINAPI FilterGraph2_AddFilter(IFilterGraph2 *iface, IBaseFilter *
else
memcpy(wszFilterName, pName, (strlenW(pName) + 1) * sizeof(WCHAR));
- if (This->nFilters + 1 > This->filterCapacity)
- {
- int newCapacity = This->filterCapacity ? 2 * This->filterCapacity : 1;
- IBaseFilter ** ppNewFilters = CoTaskMemAlloc(newCapacity * sizeof(IBaseFilter*));
- LPWSTR * pNewNames = CoTaskMemAlloc(newCapacity * sizeof(LPWSTR));
- memcpy(ppNewFilters, This->ppFiltersInGraph, This->nFilters * sizeof(IBaseFilter*));
- memcpy(pNewNames, This->pFilterNames, This->nFilters * sizeof(LPWSTR));
- if (This->filterCapacity)
- {
- CoTaskMemFree(This->ppFiltersInGraph);
- CoTaskMemFree(This->pFilterNames);
- }
- This->ppFiltersInGraph = ppNewFilters;
- This->pFilterNames = pNewNames;
- This->filterCapacity = newCapacity;
- }
-
hr = IBaseFilter_JoinFilterGraph(pFilter, (IFilterGraph *)&This->IFilterGraph2_iface, wszFilterName);
-
- if (SUCCEEDED(hr))
+ if (FAILED(hr))
{
- IBaseFilter_AddRef(pFilter);
- This->ppFiltersInGraph[This->nFilters] = pFilter;
- This->pFilterNames[This->nFilters] = wszFilterName;
- This->nFilters++;
- This->version++;
- IBaseFilter_SetSyncSource(pFilter, This->refClock);
- }
- else
CoTaskMemFree(wszFilterName);
+ return hr;
+ }
- if (SUCCEEDED(hr) && duplicate_name)
- return VFW_S_DUPLICATE_NAME;
+ if (!(entry = heap_alloc(sizeof(*entry))))
+ {
+ CoTaskMemFree(wszFilterName);
+ return E_OUTOFMEMORY;
+ }
- return hr;
+ IBaseFilter_AddRef(entry->filter = pFilter);
+ entry->name = wszFilterName;
+ list_add_head(&This->filters, &entry->entry);
+ This->version++;
+
+ return duplicate_name ? VFW_S_DUPLICATE_NAME : hr;
}
static HRESULT WINAPI FilterGraph2_RemoveFilter(IFilterGraph2 *iface, IBaseFilter *pFilter)
{
IFilterGraphImpl *This = impl_from_IFilterGraph2(iface);
+ struct filter *entry;
int i;
HRESULT hr = E_FAIL;
@@ -635,9 +626,9 @@ static HRESULT WINAPI FilterGraph2_RemoveFilter(IFilterGraph2 *iface, IBaseFilte
/* FIXME: check graph is stopped */
- for (i = 0; i < This->nFilters; i++)
+ LIST_FOR_EACH_ENTRY(entry, &This->filters, struct filter, entry)
{
- if (This->ppFiltersInGraph[i] == pFilter)
+ if (entry->filter == pFilter)
{
IEnumPins *penumpins = NULL;
FILTER_STATE state;
@@ -648,7 +639,7 @@ static HRESULT WINAPI FilterGraph2_RemoveFilter(IFilterGraph2 *iface, IBaseFilte
This->defaultclock = TRUE;
}
- TRACE("Removing filter %s\n", debugstr_w(This->pFilterNames[i]));
+ TRACE("Removing filter %s.\n", debugstr_w(entry->name));
IBaseFilter_GetState(pFilter, 0, &state);
if (state == State_Running)
IBaseFilter_Pause(pFilter);
@@ -690,15 +681,13 @@ static HRESULT WINAPI FilterGraph2_RemoveFilter(IFilterGraph2 *iface, IBaseFilte
IEnumPins_Release(penumpins);
}
- hr = IBaseFilter_JoinFilterGraph(pFilter, NULL, This->pFilterNames[i]);
+ hr = IBaseFilter_JoinFilterGraph(pFilter, NULL, entry->name);
if (SUCCEEDED(hr))
{
IBaseFilter_SetSyncSource(pFilter, NULL);
IBaseFilter_Release(pFilter);
- CoTaskMemFree(This->pFilterNames[i]);
- memmove(This->ppFiltersInGraph+i, This->ppFiltersInGraph+i+1, sizeof(IBaseFilter*)*(This->nFilters - 1 - i));
- memmove(This->pFilterNames+i, This->pFilterNames+i+1, sizeof(LPWSTR)*(This->nFilters - 1 - i));
- This->nFilters--;
+ list_remove(&entry->entry);
+ heap_free(entry);
This->version++;
/* Invalidate interfaces in the cache */
for (i = 0; i < This->nItfCacheEntries; i++)
@@ -723,7 +712,7 @@ static HRESULT WINAPI FilterGraph2_EnumFilters(IFilterGraph2 *iface, IEnumFilter
TRACE("graph %p, out %p.\n", graph, out);
- return create_enum_filters(graph, out);
+ return create_enum_filters(graph, list_head(&graph->filters), out);
}
static HRESULT WINAPI FilterGraph2_FindFilterByName(IFilterGraph2 *iface,
@@ -919,24 +908,24 @@ static HRESULT WINAPI FilterGraph2_SetDefaultSyncSource(IFilterGraph2 *iface)
{
IFilterGraphImpl *This = impl_from_IFilterGraph2(iface);
IReferenceClock *pClock = NULL;
+ struct filter *filter;
HRESULT hr = S_OK;
- int i;
TRACE("(%p/%p)->() live sources not handled properly!\n", This, iface);
EnterCriticalSection(&This->cs);
- for (i = 0; i < This->nFilters; ++i)
+ LIST_FOR_EACH_ENTRY(filter, &This->filters, struct filter, entry)
{
DWORD miscflags;
IAMFilterMiscFlags *flags = NULL;
- IBaseFilter_QueryInterface(This->ppFiltersInGraph[i], &IID_IAMFilterMiscFlags, (void**)&flags);
+ IBaseFilter_QueryInterface(filter->filter, &IID_IAMFilterMiscFlags, (void **)&flags);
if (!flags)
continue;
miscflags = IAMFilterMiscFlags_GetMiscFlags(flags);
IAMFilterMiscFlags_Release(flags);
if (miscflags == AM_FILTER_MISC_FLAGS_IS_RENDERER)
- IBaseFilter_QueryInterface(This->ppFiltersInGraph[i], &IID_IReferenceClock, (void**)&pClock);
+ IBaseFilter_QueryInterface(filter->filter, &IID_IReferenceClock, (void **)&pClock);
if (pClock)
break;
}
@@ -947,7 +936,10 @@ static HRESULT WINAPI FilterGraph2_SetDefaultSyncSource(IFilterGraph2 *iface)
This->refClockProvider = NULL;
}
else
- This->refClockProvider = This->ppFiltersInGraph[i];
+ {
+ filter = LIST_ENTRY(list_tail(&This->filters), struct filter, entry);
+ This->refClockProvider = filter->filter;
+ }
if (SUCCEEDED(hr))
{
@@ -1422,6 +1414,7 @@ static HRESULT WINAPI FilterGraph2_Render(IFilterGraph2 *iface, IPin *ppinOut)
{
IFilterGraphImpl *This = impl_from_IFilterGraph2(iface);
IEnumMediaTypes* penummt;
+ struct filter *filter;
AM_MEDIA_TYPE* mt;
ULONG nbmt;
HRESULT hr;
@@ -1430,7 +1423,6 @@ static HRESULT WINAPI FilterGraph2_Render(IFilterGraph2 *iface, IPin *ppinOut)
GUID tab[4];
ULONG nb;
IMoniker* pMoniker;
- INT x;
IFilterMapper2 *pFilterMapper2 = NULL;
TRACE("(%p/%p)->(%p)\n", This, iface, ppinOut);
@@ -1450,12 +1442,12 @@ static HRESULT WINAPI FilterGraph2_Render(IFilterGraph2 *iface, IPin *ppinOut)
/* Try to find out if there is a renderer for the specified subtype already, and use that
*/
EnterCriticalSection(&This->cs);
- for (x = 0; x < This->nFilters; ++x)
+ LIST_FOR_EACH_ENTRY(filter, &This->filters, struct filter, entry)
{
IEnumPins *enumpins = NULL;
IPin *pin = NULL;
- hr = IBaseFilter_EnumPins(This->ppFiltersInGraph[x], &enumpins);
+ hr = IBaseFilter_EnumPins(filter->filter, &enumpins);
if (FAILED(hr) || !enumpins)
continue;
@@ -1683,6 +1675,7 @@ static HRESULT WINAPI FilterGraph2_RenderFile(IFilterGraph2 *iface, LPCWSTR lpcw
IBaseFilter* preader = NULL;
IPin* ppinreader = NULL;
IEnumPins* penumpins = NULL;
+ struct filter *filter;
HRESULT hr;
BOOL partial = FALSE;
BOOL any = FALSE;
@@ -1706,13 +1699,11 @@ static HRESULT WINAPI FilterGraph2_RenderFile(IFilterGraph2 *iface, LPCWSTR lpcw
IPin_QueryDirection(ppinreader, &dir);
if (dir == PINDIR_OUTPUT)
{
- INT i;
-
hr = IFilterGraph2_Render(iface, ppinreader);
- TRACE("Render %08x\n", hr);
- for (i = 0; i < This->nFilters; ++i)
- TRACE("Filters in chain: %s\n", debugstr_w(This->pFilterNames[i]));
+ TRACE("Filters in chain:\n");
+ LIST_FOR_EACH_ENTRY(filter, &This->filters, struct filter, entry)
+ TRACE("- %s.\n", debugstr_w(filter->name));
if (SUCCEEDED(hr))
any = TRUE;
@@ -2160,8 +2151,7 @@ static HRESULT WINAPI SendGetState(IBaseFilter *pFilter, DWORD_PTR data)
static HRESULT SendFilterMessage(IFilterGraphImpl *This, fnFoundFilter FoundFilter, DWORD_PTR data)
{
- int i;
- IBaseFilter* pfilter;
+ struct filter *filter;
IEnumPins* pEnum;
HRESULT hr;
IPin* pPin;
@@ -2175,11 +2165,10 @@ static HRESULT SendFilterMessage(IFilterGraphImpl *This, fnFoundFilter FoundFilt
This->nRenderers = 0;
ResetEvent(This->hEventCompletion);
- for(i = 0; i < This->nFilters; i++)
+ LIST_FOR_EACH_ENTRY(filter, &This->filters, struct filter, entry)
{
BOOL source = TRUE;
- pfilter = This->ppFiltersInGraph[i];
- hr = IBaseFilter_EnumPins(pfilter, &pEnum);
+ hr = IBaseFilter_EnumPins(filter->filter, &pEnum);
if (hr != S_OK)
{
WARN("Enum pins failed %x\n", hr);
@@ -2198,7 +2187,7 @@ static HRESULT SendFilterMessage(IFilterGraphImpl *This, fnFoundFilter FoundFilt
}
if (source)
{
- TRACE("Found a source filter %p\n", pfilter);
+ TRACE("Found source filter %p.\n", filter->filter);
IEnumPins_Reset(pEnum);
while(IEnumPins_Next(pEnum, 1, &pPin, &dummy) == S_OK)
{
@@ -2206,7 +2195,7 @@ static HRESULT SendFilterMessage(IFilterGraphImpl *This, fnFoundFilter FoundFilt
ExploreGraph(This, pPin, FoundFilter, data);
IPin_Release(pPin);
}
- FoundFilter(pfilter, data);
+ FoundFilter(filter->filter, data);
}
IEnumPins_Release(pEnum);
}
@@ -2424,19 +2413,18 @@ typedef HRESULT (WINAPI *fnFoundSeek)(IFilterGraphImpl *This, IMediaSeeking*, DW
static HRESULT all_renderers_seek(IFilterGraphImpl *This, fnFoundSeek FoundSeek, DWORD_PTR arg) {
BOOL allnotimpl = TRUE;
- int i;
HRESULT hr, hr_return = S_OK;
+ struct filter *filter;
TRACE("(%p)->(%p %08lx)\n", This, FoundSeek, arg);
/* Send a message to all renderers, they are responsible for broadcasting it further */
- for(i = 0; i < This->nFilters; i++)
+ LIST_FOR_EACH_ENTRY(filter, &This->filters, struct filter, entry)
{
IMediaSeeking *seek = NULL;
- IBaseFilter* pfilter = This->ppFiltersInGraph[i];
IAMFilterMiscFlags *flags = NULL;
ULONG filterflags;
- IBaseFilter_QueryInterface(pfilter, &IID_IAMFilterMiscFlags, (void**)&flags);
+ IBaseFilter_QueryInterface(filter->filter, &IID_IAMFilterMiscFlags, (void **)&flags);
if (!flags)
continue;
filterflags = IAMFilterMiscFlags_GetMiscFlags(flags);
@@ -2444,7 +2432,7 @@ static HRESULT all_renderers_seek(IFilterGraphImpl *This, fnFoundSeek FoundSeek,
if (filterflags != AM_FILTER_MISC_FLAGS_IS_RENDERER)
continue;
- IBaseFilter_QueryInterface(pfilter, &IID_IMediaSeeking, (void**)&seek);
+ IBaseFilter_QueryInterface(filter->filter, &IID_IMediaSeeking, (void **)&seek);
if (!seek)
continue;
hr = FoundSeek(This, seek, arg);
@@ -3116,8 +3104,8 @@ static const IObjectWithSiteVtbl IObjectWithSite_VTable =
static HRESULT GetTargetInterface(IFilterGraphImpl* pGraph, REFIID riid, LPVOID* ppvObj)
{
+ struct filter *filter;
HRESULT hr;
- int i;
int entry;
/* Check if the interface type is already registered */
@@ -3140,13 +3128,13 @@ static HRESULT GetTargetInterface(IFilterGraphImpl* pGraph, REFIID riid, LPVOID*
}
/* Find a filter supporting the requested interface */
- for (i = 0; i < pGraph->nFilters; i++)
+ LIST_FOR_EACH_ENTRY(filter, &pGraph->filters, struct filter, entry)
{
- hr = IBaseFilter_QueryInterface(pGraph->ppFiltersInGraph[i], riid, ppvObj);
+ hr = IBaseFilter_QueryInterface(filter->filter, riid, ppvObj);
if (hr == S_OK)
{
pGraph->ItfCacheEntries[entry].riid = riid;
- pGraph->ItfCacheEntries[entry].filter = pGraph->ppFiltersInGraph[i];
+ pGraph->ItfCacheEntries[entry].filter = filter->filter;
pGraph->ItfCacheEntries[entry].iface = *ppvObj;
if (entry >= pGraph->nItfCacheEntries)
pGraph->nItfCacheEntries++;
@@ -5471,24 +5459,24 @@ static HRESULT WINAPI MediaFilter_GetState(IMediaFilter *iface, DWORD dwMsTimeou
static HRESULT WINAPI MediaFilter_SetSyncSource(IMediaFilter *iface, IReferenceClock *pClock)
{
IFilterGraphImpl *This = impl_from_IMediaFilter(iface);
+ struct filter *filter;
HRESULT hr = S_OK;
- int i;
TRACE("(%p/%p)->(%p)\n", This, iface, pClock);
EnterCriticalSection(&This->cs);
{
- for (i = 0;i < This->nFilters;i++)
+ LIST_FOR_EACH_ENTRY(filter, &This->filters, struct filter, entry)
{
- hr = IBaseFilter_SetSyncSource(This->ppFiltersInGraph[i], pClock);
+ hr = IBaseFilter_SetSyncSource(filter->filter, pClock);
if (FAILED(hr))
break;
}
if (FAILED(hr))
{
- for(;i >= 0;i--)
- IBaseFilter_SetSyncSource(This->ppFiltersInGraph[i], This->refClock);
+ LIST_FOR_EACH_ENTRY(filter, &This->filters, struct filter, entry)
+ IBaseFilter_SetSyncSource(filter->filter, This->refClock);
}
else
{
@@ -5865,10 +5853,7 @@ HRESULT FilterGraph_create(IUnknown *pUnkOuter, LPVOID *ppObj)
fimpl->IObjectWithSite_iface.lpVtbl = &IObjectWithSite_VTable;
fimpl->IGraphVersion_iface.lpVtbl = &IGraphVersion_VTable;
fimpl->ref = 1;
- fimpl->ppFiltersInGraph = NULL;
- fimpl->pFilterNames = NULL;
- fimpl->nFilters = 0;
- fimpl->filterCapacity = 0;
+ list_init(&fimpl->filters);
fimpl->nameIndex = 1;
fimpl->refClock = NULL;
fimpl->hEventCompletion = CreateEventW(0, TRUE, FALSE, 0);
diff --git a/dlls/quartz/tests/filtergraph.c b/dlls/quartz/tests/filtergraph.c
index 4f1e9cf..51196c1 100644
--- a/dlls/quartz/tests/filtergraph.c
+++ b/dlls/quartz/tests/filtergraph.c
@@ -622,14 +622,12 @@ static void test_enum_filters(void)
hr = IEnumFilters_Next(enum1, 1, filters, NULL);
ok(hr == S_OK, "Got hr %#x.\n", hr);
-todo_wine
ok(filters[0] == filter2, "Got filter %p.\n", filters[0]);
IBaseFilter_Release(filters[0]);
hr = IEnumFilters_Next(enum1, 1, filters, &count);
ok(hr == S_OK, "Got hr %#x.\n", hr);
ok(count == 1, "Got count %u.\n", count);
-todo_wine
ok(filters[0] == filter1, "Got filter %p.\n", filters[0]);
IBaseFilter_Release(filters[0]);
@@ -643,10 +641,8 @@ todo_wine
hr = IEnumFilters_Next(enum1, 2, filters, &count);
ok(hr == S_OK, "Got hr %#x.\n", hr);
ok(count == 2, "Got count %u.\n", count);
-todo_wine {
ok(filters[0] == filter2, "Got filter %p.\n", filters[0]);
ok(filters[1] == filter1, "Got filter %p.\n", filters[1]);
-}
IBaseFilter_Release(filters[0]);
IBaseFilter_Release(filters[1]);
@@ -662,10 +658,8 @@ todo_wine {
hr = IEnumFilters_Next(enum1, 2, filters, &count);
ok(hr == S_OK, "Got hr %#x.\n", hr);
ok(count == 2, "Got count %u.\n", count);
-todo_wine {
ok(filters[0] == filter1, "Got filter %p.\n", filters[0]);
ok(filters[1] == filter2, "Got filter %p.\n", filters[1]);
-}
IBaseFilter_Release(filters[0]);
IBaseFilter_Release(filters[1]);
@@ -681,7 +675,6 @@ todo_wine {
hr = IEnumFilters_Next(enum2, 2, filters, &count);
ok(hr == S_FALSE, "Got hr %#x.\n", hr);
ok(count == 1, "Got count %u.\n", count);
-todo_wine
ok(filters[0] == filter2, "Got filter %p.\n", filters[0]);
IBaseFilter_Release(filters[0]);
--
2.7.4
Sept. 18, 2018
[PATCH v2 4/6] quartz/filtergraph: Pass an IFilterGraphImpl to create_enum_filters().
by Zebediah Figura
Signed-off-by: Zebediah Figura <z.figura12(a)gmail.com>
---
dlls/quartz/filtergraph.c | 43 ++++++++++++++-----------------------------
1 file changed, 14 insertions(+), 29 deletions(-)
diff --git a/dlls/quartz/filtergraph.c b/dlls/quartz/filtergraph.c
index f0e91cb..76cc0c7 100644
--- a/dlls/quartz/filtergraph.c
+++ b/dlls/quartz/filtergraph.c
@@ -211,15 +211,12 @@ struct enum_filters
{
IEnumFilters IEnumFilters_iface;
LONG ref;
- IGraphVersion *version_source;
+ IFilterGraphImpl *graph;
LONG version;
- IBaseFilter ***filters;
- ULONG *count;
ULONG index;
};
-static HRESULT create_enum_filters(IGraphVersion *version_source,
- IBaseFilter ***filters, ULONG *count, IEnumFilters **out);
+static HRESULT create_enum_filters(IFilterGraphImpl *graph, IEnumFilters **out);
static inline struct enum_filters *impl_from_IEnumFilters(IEnumFilters *iface)
{
@@ -261,7 +258,7 @@ static ULONG WINAPI EnumFilters_Release(IEnumFilters *iface)
if (!ref)
{
- IGraphVersion_Release(enum_filters->version_source);
+ IUnknown_Release(enum_filters->graph->outer_unk);
heap_free(enum_filters);
}
@@ -273,16 +270,13 @@ static HRESULT WINAPI EnumFilters_Next(IEnumFilters *iface, ULONG count,
{
struct enum_filters *enum_filters = impl_from_IEnumFilters(iface);
unsigned int i, cFetched;
- LONG version;
- HRESULT hr;
TRACE("enum_filters %p, count %u, filters %p, fetched %p.\n",
enum_filters, count, filters, fetched);
- cFetched = min(*enum_filters->count, enum_filters->index + count) - enum_filters->index;
+ cFetched = min(enum_filters->graph->nFilters, enum_filters->index + count) - enum_filters->index;
- hr = IGraphVersion_QueryVersion(enum_filters->version_source, &version);
- if (hr == S_OK && enum_filters->version != version)
+ if (enum_filters->version != enum_filters->graph->version)
return VFW_E_ENUM_OUT_OF_SYNC;
if (!filters)
@@ -290,7 +284,7 @@ static HRESULT WINAPI EnumFilters_Next(IEnumFilters *iface, ULONG count,
for (i = 0; i < cFetched; i++)
{
- filters[i] = (*enum_filters->filters)[enum_filters->index + i];
+ filters[i] = enum_filters->graph->ppFiltersInGraph[enum_filters->index + i];
IBaseFilter_AddRef(filters[i]);
}
@@ -310,7 +304,7 @@ static HRESULT WINAPI EnumFilters_Skip(IEnumFilters *iface, ULONG count)
TRACE("enum_filters %p, count %u.\n", enum_filters, count);
- if (enum_filters->index + count < *enum_filters->count)
+ if (enum_filters->index + count < enum_filters->graph->nFilters)
{
enum_filters->index += count;
return S_OK;
@@ -321,15 +315,11 @@ static HRESULT WINAPI EnumFilters_Skip(IEnumFilters *iface, ULONG count)
static HRESULT WINAPI EnumFilters_Reset(IEnumFilters *iface)
{
struct enum_filters *enum_filters = impl_from_IEnumFilters(iface);
- LONG version;
- HRESULT hr;
TRACE("enum_filters %p.\n", enum_filters);
enum_filters->index = 0;
- hr = IGraphVersion_QueryVersion(enum_filters->version_source, &version);
- if (hr == S_OK)
- enum_filters->version = version;
+ enum_filters->version = enum_filters->graph->version;
return S_OK;
}
@@ -340,7 +330,7 @@ static HRESULT WINAPI EnumFilters_Clone(IEnumFilters *iface, IEnumFilters **out)
TRACE("enum_filters %p, out %p.\n", enum_filters, out);
- hr = create_enum_filters(enum_filters->version_source, enum_filters->filters, enum_filters->count, out);
+ hr = create_enum_filters(enum_filters->graph, out);
if (FAILED(hr))
return hr;
return IEnumFilters_Skip(*out, enum_filters->index);
@@ -357,12 +347,9 @@ static const IEnumFiltersVtbl EnumFilters_vtbl =
EnumFilters_Clone,
};
-static HRESULT create_enum_filters(IGraphVersion *version_source,
- IBaseFilter ***filters, ULONG *count, IEnumFilters **out)
+static HRESULT create_enum_filters(IFilterGraphImpl *graph, IEnumFilters **out)
{
struct enum_filters *enum_filters;
- LONG version;
- HRESULT hr;
if (!(enum_filters = heap_alloc(sizeof(*enum_filters))))
return E_OUTOFMEMORY;
@@ -370,11 +357,9 @@ static HRESULT create_enum_filters(IGraphVersion *version_source,
enum_filters->IEnumFilters_iface.lpVtbl = &EnumFilters_vtbl;
enum_filters->ref = 1;
enum_filters->index = 0;
- enum_filters->filters = filters;
- enum_filters->count = count;
- IGraphVersion_AddRef(enum_filters->version_source = version_source);
- hr = IGraphVersion_QueryVersion(version_source, &version);
- enum_filters->version = (hr == S_OK) ? version : 0;
+ enum_filters->graph = graph;
+ IUnknown_AddRef(graph->outer_unk);
+ enum_filters->version = graph->version;
*out = &enum_filters->IEnumFilters_iface;
return S_OK;
@@ -738,7 +723,7 @@ static HRESULT WINAPI FilterGraph2_EnumFilters(IFilterGraph2 *iface, IEnumFilter
TRACE("graph %p, out %p.\n", graph, out);
- return create_enum_filters(&graph->IGraphVersion_iface, &graph->ppFiltersInGraph, &graph->nFilters, out);
+ return create_enum_filters(graph, out);
}
static HRESULT WINAPI FilterGraph2_FindFilterByName(IFilterGraph2 *iface,
--
2.7.4
Sept. 18, 2018
[PATCH v2 3/6] quartz: Merge enumfilters.c into filtergraph.c.
by Zebediah Figura
Signed-off-by: Zebediah Figura <z.figura12(a)gmail.com>
---
dlls/quartz/Makefile.in | 1 -
dlls/quartz/enumfilters.c | 215 -------------------------------------------
dlls/quartz/filtergraph.c | 182 +++++++++++++++++++++++++++++++++++-
dlls/quartz/quartz_private.h | 1 -
4 files changed, 178 insertions(+), 221 deletions(-)
delete mode 100644 dlls/quartz/enumfilters.c
diff --git a/dlls/quartz/Makefile.in b/dlls/quartz/Makefile.in
index 5eb8d44..147d395 100644
--- a/dlls/quartz/Makefile.in
+++ b/dlls/quartz/Makefile.in
@@ -7,7 +7,6 @@ C_SRCS = \
avidec.c \
avisplit.c \
dsoundrender.c \
- enumfilters.c \
enummedia.c \
enummoniker.c \
enumregfilters.c \
diff --git a/dlls/quartz/enumfilters.c b/dlls/quartz/enumfilters.c
deleted file mode 100644
index 331991b..0000000
--- a/dlls/quartz/enumfilters.c
+++ /dev/null
@@ -1,215 +0,0 @@
-/*
- * Implementation of IEnumFilters Interface
- *
- * Copyright 2004 Christian Costa
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
- */
-
-#include "quartz_private.h"
-
-#include "wine/debug.h"
-
-WINE_DEFAULT_DEBUG_CHANNEL(quartz);
-
-typedef struct IEnumFiltersImpl
-{
- IEnumFilters IEnumFilters_iface;
- LONG refCount;
- IGraphVersion * pVersionSource;
- LONG Version;
- IBaseFilter *** pppFilters;
- ULONG * pNumFilters;
- ULONG uIndex;
-} IEnumFiltersImpl;
-
-static const struct IEnumFiltersVtbl IEnumFiltersImpl_Vtbl;
-
-static inline IEnumFiltersImpl *impl_from_IEnumFilters(IEnumFilters *iface)
-{
- return CONTAINING_RECORD(iface, IEnumFiltersImpl, IEnumFilters_iface);
-}
-
-HRESULT IEnumFiltersImpl_Construct(IGraphVersion * pVersionSource, IBaseFilter *** pppFilters, ULONG * pNumFilters, IEnumFilters ** ppEnum)
-{
- /* Note: The incoming IBaseFilter interfaces are not AddRef'd here as in Windows,
- * they should have been previously AddRef'd. */
- IEnumFiltersImpl * pEnumFilters = CoTaskMemAlloc(sizeof(IEnumFiltersImpl));
- HRESULT hr;
- LONG currentVersion;
-
- TRACE("(%p, %p, %p)\n", pppFilters, pNumFilters, ppEnum);
-
- *ppEnum = NULL;
-
- if (!pEnumFilters)
- {
- return E_OUTOFMEMORY;
- }
-
- pEnumFilters->IEnumFilters_iface.lpVtbl = &IEnumFiltersImpl_Vtbl;
- pEnumFilters->refCount = 1;
- pEnumFilters->uIndex = 0;
- pEnumFilters->pNumFilters = pNumFilters;
- pEnumFilters->pppFilters = pppFilters;
- IGraphVersion_AddRef(pVersionSource);
- pEnumFilters->pVersionSource = pVersionSource;
-
- /* Store the current version of the graph */
- hr = IGraphVersion_QueryVersion(pVersionSource, ¤tVersion);
- pEnumFilters->Version = (hr==S_OK) ? currentVersion : 0;
-
- *ppEnum = &pEnumFilters->IEnumFilters_iface;
- return S_OK;
-}
-
-static HRESULT WINAPI IEnumFiltersImpl_QueryInterface(IEnumFilters * iface, REFIID riid, LPVOID * ppv)
-{
- TRACE("(%p)->(%s, %p)\n", iface, qzdebugstr_guid(riid), ppv);
-
- *ppv = NULL;
-
- if (IsEqualIID(riid, &IID_IUnknown))
- *ppv = iface;
- else if (IsEqualIID(riid, &IID_IEnumFilters))
- *ppv = iface;
-
- if (*ppv)
- {
- IUnknown_AddRef((IUnknown *)(*ppv));
- return S_OK;
- }
-
- FIXME("No interface for %s!\n", qzdebugstr_guid(riid));
-
- return E_NOINTERFACE;
-}
-
-static ULONG WINAPI IEnumFiltersImpl_AddRef(IEnumFilters * iface)
-{
- IEnumFiltersImpl *This = impl_from_IEnumFilters(iface);
- ULONG refCount = InterlockedIncrement(&This->refCount);
-
- TRACE("(%p)->()\n", iface);
-
- return refCount;
-}
-
-static ULONG WINAPI IEnumFiltersImpl_Release(IEnumFilters * iface)
-{
- IEnumFiltersImpl *This = impl_from_IEnumFilters(iface);
- ULONG refCount = InterlockedDecrement(&This->refCount);
-
- TRACE("(%p)->()\n", iface);
-
- if (!refCount)
- {
- IGraphVersion_Release(This->pVersionSource);
- CoTaskMemFree(This);
- return 0;
- }
- else
- return refCount;
-}
-
-static HRESULT WINAPI IEnumFiltersImpl_Next(IEnumFilters * iface, ULONG cFilters, IBaseFilter ** ppFilters, ULONG * pcFetched)
-{
- ULONG cFetched;
- ULONG i;
- LONG currentVersion;
- IEnumFiltersImpl *This = impl_from_IEnumFilters(iface);
- HRESULT hr;
-
- cFetched = min(*This->pNumFilters, This->uIndex + cFilters) - This->uIndex;
-
- TRACE("(%p)->(%u, %p, %p)\n", iface, cFilters, ppFilters, pcFetched);
-
- /* First of all check if the graph has changed */
- hr = IGraphVersion_QueryVersion(This->pVersionSource, ¤tVersion);
- if (hr==S_OK && This->Version != currentVersion)
- return VFW_E_ENUM_OUT_OF_SYNC;
-
-
- if (!ppFilters)
- return E_POINTER;
-
- for (i = 0; i < cFetched; i++)
- {
- ppFilters[i] = (*This->pppFilters)[This->uIndex + i];
- IBaseFilter_AddRef(ppFilters[i]);
- }
-
- This->uIndex += cFetched;
-
- if (pcFetched)
- *pcFetched = cFetched;
-
- if (cFetched != cFilters)
- return S_FALSE;
- return S_OK;
-}
-
-static HRESULT WINAPI IEnumFiltersImpl_Skip(IEnumFilters * iface, ULONG cFilters)
-{
- IEnumFiltersImpl *This = impl_from_IEnumFilters(iface);
-
- TRACE("(%p)->(%u)\n", iface, cFilters);
-
- if (This->uIndex + cFilters < *This->pNumFilters)
- {
- This->uIndex += cFilters;
- return S_OK;
- }
- return S_FALSE;
-}
-
-static HRESULT WINAPI IEnumFiltersImpl_Reset(IEnumFilters * iface)
-{
- IEnumFiltersImpl *This = impl_from_IEnumFilters(iface);
- HRESULT hr;
- LONG currentVersion;
-
- TRACE("(%p)->()\n", iface);
-
- This->uIndex = 0;
- hr = IGraphVersion_QueryVersion(This->pVersionSource, ¤tVersion);
- if (hr == S_OK)
- This->Version = currentVersion;
- return S_OK;
-}
-
-static HRESULT WINAPI IEnumFiltersImpl_Clone(IEnumFilters * iface, IEnumFilters ** ppEnum)
-{
- HRESULT hr;
- IEnumFiltersImpl *This = impl_from_IEnumFilters(iface);
-
- TRACE("(%p)->(%p)\n", iface, ppEnum);
-
- hr = IEnumFiltersImpl_Construct(This->pVersionSource, This->pppFilters, This->pNumFilters, ppEnum);
- if (FAILED(hr))
- return hr;
- return IEnumFilters_Skip(*ppEnum, This->uIndex);
-}
-
-static const IEnumFiltersVtbl IEnumFiltersImpl_Vtbl =
-{
- IEnumFiltersImpl_QueryInterface,
- IEnumFiltersImpl_AddRef,
- IEnumFiltersImpl_Release,
- IEnumFiltersImpl_Next,
- IEnumFiltersImpl_Skip,
- IEnumFiltersImpl_Reset,
- IEnumFiltersImpl_Clone
-};
diff --git a/dlls/quartz/filtergraph.c b/dlls/quartz/filtergraph.c
index 983e2c0..f0e91cb 100644
--- a/dlls/quartz/filtergraph.c
+++ b/dlls/quartz/filtergraph.c
@@ -36,6 +36,7 @@
#include "strmif.h"
#include "vfwmsgs.h"
#include "evcode.h"
+#include "wine/heap.h"
#include "wine/unicode.h"
@@ -206,6 +207,179 @@ typedef struct _IFilterGraphImpl {
LONG version;
} IFilterGraphImpl;
+struct enum_filters
+{
+ IEnumFilters IEnumFilters_iface;
+ LONG ref;
+ IGraphVersion *version_source;
+ LONG version;
+ IBaseFilter ***filters;
+ ULONG *count;
+ ULONG index;
+};
+
+static HRESULT create_enum_filters(IGraphVersion *version_source,
+ IBaseFilter ***filters, ULONG *count, IEnumFilters **out);
+
+static inline struct enum_filters *impl_from_IEnumFilters(IEnumFilters *iface)
+{
+ return CONTAINING_RECORD(iface, struct enum_filters, IEnumFilters_iface);
+}
+
+static HRESULT WINAPI EnumFilters_QueryInterface(IEnumFilters *iface, REFIID iid, void **out)
+{
+ struct enum_filters *enum_filters = impl_from_IEnumFilters(iface);
+ TRACE("enum_filters %p, iid %s, out %p.\n", enum_filters, qzdebugstr_guid(iid), out);
+
+ if (IsEqualGUID(iid, &IID_IUnknown) || IsEqualGUID(iid, &IID_IEnumFilters))
+ {
+ IEnumFilters_AddRef(*out = iface);
+ return S_OK;
+ }
+
+ WARN("%s not implemented, returning E_NOINTERFACE.\n", qzdebugstr_guid(iid));
+ *out = NULL;
+ return E_NOINTERFACE;
+}
+
+static ULONG WINAPI EnumFilters_AddRef(IEnumFilters *iface)
+{
+ struct enum_filters *enum_filters = impl_from_IEnumFilters(iface);
+ ULONG ref = InterlockedIncrement(&enum_filters->ref);
+
+ TRACE("%p increasing refcount to %u.\n", enum_filters, ref);
+
+ return ref;
+}
+
+static ULONG WINAPI EnumFilters_Release(IEnumFilters *iface)
+{
+ struct enum_filters *enum_filters = impl_from_IEnumFilters(iface);
+ ULONG ref = InterlockedDecrement(&enum_filters->ref);
+
+ TRACE("%p decreasing refcount to %u.\n", enum_filters, ref);
+
+ if (!ref)
+ {
+ IGraphVersion_Release(enum_filters->version_source);
+ heap_free(enum_filters);
+ }
+
+ return ref;
+}
+
+static HRESULT WINAPI EnumFilters_Next(IEnumFilters *iface, ULONG count,
+ IBaseFilter **filters, ULONG *fetched)
+{
+ struct enum_filters *enum_filters = impl_from_IEnumFilters(iface);
+ unsigned int i, cFetched;
+ LONG version;
+ HRESULT hr;
+
+ TRACE("enum_filters %p, count %u, filters %p, fetched %p.\n",
+ enum_filters, count, filters, fetched);
+
+ cFetched = min(*enum_filters->count, enum_filters->index + count) - enum_filters->index;
+
+ hr = IGraphVersion_QueryVersion(enum_filters->version_source, &version);
+ if (hr == S_OK && enum_filters->version != version)
+ return VFW_E_ENUM_OUT_OF_SYNC;
+
+ if (!filters)
+ return E_POINTER;
+
+ for (i = 0; i < cFetched; i++)
+ {
+ filters[i] = (*enum_filters->filters)[enum_filters->index + i];
+ IBaseFilter_AddRef(filters[i]);
+ }
+
+ enum_filters->index += cFetched;
+
+ if (fetched)
+ *fetched = cFetched;
+
+ if (cFetched != count)
+ return S_FALSE;
+ return S_OK;
+}
+
+static HRESULT WINAPI EnumFilters_Skip(IEnumFilters *iface, ULONG count)
+{
+ struct enum_filters *enum_filters = impl_from_IEnumFilters(iface);
+
+ TRACE("enum_filters %p, count %u.\n", enum_filters, count);
+
+ if (enum_filters->index + count < *enum_filters->count)
+ {
+ enum_filters->index += count;
+ return S_OK;
+ }
+ return S_FALSE;
+}
+
+static HRESULT WINAPI EnumFilters_Reset(IEnumFilters *iface)
+{
+ struct enum_filters *enum_filters = impl_from_IEnumFilters(iface);
+ LONG version;
+ HRESULT hr;
+
+ TRACE("enum_filters %p.\n", enum_filters);
+
+ enum_filters->index = 0;
+ hr = IGraphVersion_QueryVersion(enum_filters->version_source, &version);
+ if (hr == S_OK)
+ enum_filters->version = version;
+ return S_OK;
+}
+
+static HRESULT WINAPI EnumFilters_Clone(IEnumFilters *iface, IEnumFilters **out)
+{
+ struct enum_filters *enum_filters = impl_from_IEnumFilters(iface);
+ HRESULT hr;
+
+ TRACE("enum_filters %p, out %p.\n", enum_filters, out);
+
+ hr = create_enum_filters(enum_filters->version_source, enum_filters->filters, enum_filters->count, out);
+ if (FAILED(hr))
+ return hr;
+ return IEnumFilters_Skip(*out, enum_filters->index);
+}
+
+static const IEnumFiltersVtbl EnumFilters_vtbl =
+{
+ EnumFilters_QueryInterface,
+ EnumFilters_AddRef,
+ EnumFilters_Release,
+ EnumFilters_Next,
+ EnumFilters_Skip,
+ EnumFilters_Reset,
+ EnumFilters_Clone,
+};
+
+static HRESULT create_enum_filters(IGraphVersion *version_source,
+ IBaseFilter ***filters, ULONG *count, IEnumFilters **out)
+{
+ struct enum_filters *enum_filters;
+ LONG version;
+ HRESULT hr;
+
+ if (!(enum_filters = heap_alloc(sizeof(*enum_filters))))
+ return E_OUTOFMEMORY;
+
+ enum_filters->IEnumFilters_iface.lpVtbl = &EnumFilters_vtbl;
+ enum_filters->ref = 1;
+ enum_filters->index = 0;
+ enum_filters->filters = filters;
+ enum_filters->count = count;
+ IGraphVersion_AddRef(enum_filters->version_source = version_source);
+ hr = IGraphVersion_QueryVersion(version_source, &version);
+ enum_filters->version = (hr == S_OK) ? version : 0;
+
+ *out = &enum_filters->IEnumFilters_iface;
+ return S_OK;
+}
+
static inline IFilterGraphImpl *impl_from_IUnknown(IUnknown *iface)
{
return CONTAINING_RECORD(iface, IFilterGraphImpl, IUnknown_inner);
@@ -558,13 +732,13 @@ static HRESULT WINAPI FilterGraph2_RemoveFilter(IFilterGraph2 *iface, IBaseFilte
return hr; /* FIXME: check this error code */
}
-static HRESULT WINAPI FilterGraph2_EnumFilters(IFilterGraph2 *iface, IEnumFilters **ppEnum)
+static HRESULT WINAPI FilterGraph2_EnumFilters(IFilterGraph2 *iface, IEnumFilters **out)
{
- IFilterGraphImpl *This = impl_from_IFilterGraph2(iface);
+ IFilterGraphImpl *graph = impl_from_IFilterGraph2(iface);
- TRACE("(%p/%p)->(%p)\n", This, iface, ppEnum);
+ TRACE("graph %p, out %p.\n", graph, out);
- return IEnumFiltersImpl_Construct(&This->IGraphVersion_iface, &This->ppFiltersInGraph, &This->nFilters, ppEnum);
+ return create_enum_filters(&graph->IGraphVersion_iface, &graph->ppFiltersInGraph, &graph->nFilters, out);
}
static HRESULT WINAPI FilterGraph2_FindFilterByName(IFilterGraph2 *iface,
diff --git a/dlls/quartz/quartz_private.h b/dlls/quartz/quartz_private.h
index a9855e9..db9c3bd 100644
--- a/dlls/quartz/quartz_private.h
+++ b/dlls/quartz/quartz_private.h
@@ -61,7 +61,6 @@ HRESULT VMR9Impl_create(IUnknown *pUnkOuter, LPVOID *ppv) DECLSPEC_HIDDEN;
HRESULT EnumMonikerImpl_Create(IMoniker ** ppMoniker, ULONG nMonikerCount, IEnumMoniker ** ppEnum) DECLSPEC_HIDDEN;
HRESULT IEnumRegFiltersImpl_Construct(REGFILTER * pInRegFilters, const ULONG size, IEnumRegFilters ** ppEnum) DECLSPEC_HIDDEN;
-HRESULT IEnumFiltersImpl_Construct(IGraphVersion * pVersionSource, IBaseFilter *** pppFilters, ULONG * pNumFilters, IEnumFilters ** ppEnum) DECLSPEC_HIDDEN;
extern const char * qzdebugstr_guid(const GUID * id) DECLSPEC_HIDDEN;
extern void video_unregister_windowclass(void) DECLSPEC_HIDDEN;
--
2.7.4
Sept. 18, 2018
[PATCH v2 2/6] quartz/filtergraph: Factor out find_filter_by_name().
by Zebediah Figura
Signed-off-by: Zebediah Figura <z.figura12(a)gmail.com>
---
dlls/quartz/filtergraph.c | 60 +++++++++++++++++++++--------------------------
1 file changed, 27 insertions(+), 33 deletions(-)
diff --git a/dlls/quartz/filtergraph.c b/dlls/quartz/filtergraph.c
index 59b7124..983e2c0 100644
--- a/dlls/quartz/filtergraph.c
+++ b/dlls/quartz/filtergraph.c
@@ -365,13 +365,26 @@ static ULONG WINAPI FilterGraph2_Release(IFilterGraph2 *iface)
return IUnknown_Release(This->outer_unk);
}
+static IBaseFilter *find_filter_by_name(IFilterGraphImpl *graph, const WCHAR *name)
+{
+ unsigned int i;
+
+ for (i = 0; i < graph->nFilters; ++i)
+ {
+ if (!strcmpW(graph->pFilterNames[i], name))
+ return graph->ppFiltersInGraph[i];
+ }
+
+ return NULL;
+}
+
/*** IFilterGraph methods ***/
static HRESULT WINAPI FilterGraph2_AddFilter(IFilterGraph2 *iface, IBaseFilter *pFilter,
LPCWSTR pName)
{
IFilterGraphImpl *This = impl_from_IFilterGraph2(iface);
HRESULT hr;
- int i,j;
+ int j;
WCHAR* wszFilterName = NULL;
BOOL duplicate_name = FALSE;
@@ -382,16 +395,8 @@ static HRESULT WINAPI FilterGraph2_AddFilter(IFilterGraph2 *iface, IBaseFilter *
wszFilterName = CoTaskMemAlloc( (pName ? strlenW(pName) + 6 : 5) * sizeof(WCHAR) );
- if (pName)
- {
- /* Check if name already exists */
- for(i = 0; i < This->nFilters; i++)
- if (!strcmpW(This->pFilterNames[i], pName))
- {
- duplicate_name = TRUE;
- break;
- }
- }
+ if (pName && find_filter_by_name(This, pName))
+ duplicate_name = TRUE;
/* If no name given or name already existing, generate one */
if (!pName || duplicate_name)
@@ -408,16 +413,11 @@ static HRESULT WINAPI FilterGraph2_AddFilter(IFilterGraph2 *iface, IBaseFilter *
sprintfW(wszFilterName, wszFmt2, This->nameIndex);
TRACE("Generated name %s\n", debugstr_w(wszFilterName));
- /* Check if the generated name already exists */
- for(i = 0; i < This->nFilters; i++)
- if (!strcmpW(This->pFilterNames[i], wszFilterName))
- break;
-
- /* Compute next index and exit if generated name is suitable */
if (This->nameIndex++ == 10000)
This->nameIndex = 1;
- if (i == This->nFilters)
- break;
+
+ if (!find_filter_by_name(This, wszFilterName))
+ break;
}
/* Unable to find a suitable name */
if (j == 10000)
@@ -567,28 +567,22 @@ static HRESULT WINAPI FilterGraph2_EnumFilters(IFilterGraph2 *iface, IEnumFilter
return IEnumFiltersImpl_Construct(&This->IGraphVersion_iface, &This->ppFiltersInGraph, &This->nFilters, ppEnum);
}
-static HRESULT WINAPI FilterGraph2_FindFilterByName(IFilterGraph2 *iface, LPCWSTR pName,
- IBaseFilter **ppFilter)
+static HRESULT WINAPI FilterGraph2_FindFilterByName(IFilterGraph2 *iface,
+ const WCHAR *name, IBaseFilter **filter)
{
- IFilterGraphImpl *This = impl_from_IFilterGraph2(iface);
- int i;
+ IFilterGraphImpl *graph = impl_from_IFilterGraph2(iface);
- TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_w(pName), pName, ppFilter);
+ TRACE("graph %p, name %s, filter %p.\n", graph, debugstr_w(name), filter);
- if (!ppFilter)
+ if (!filter)
return E_POINTER;
- for (i = 0; i < This->nFilters; i++)
+ if ((*filter = find_filter_by_name(graph, name)))
{
- if (!strcmpW(pName, This->pFilterNames[i]))
- {
- *ppFilter = This->ppFiltersInGraph[i];
- IBaseFilter_AddRef(*ppFilter);
- return S_OK;
- }
+ IBaseFilter_AddRef(*filter);
+ return S_OK;
}
- *ppFilter = NULL;
return VFW_E_NOT_FOUND;
}
--
2.7.4
Sept. 18, 2018
[PATCH v2 1/6] quartz/tests: Add some tests for IFilterGraph_EnumFilters().
by Zebediah Figura
Signed-off-by: Zebediah Figura <z.figura12(a)gmail.com>
---
dlls/quartz/tests/filtergraph.c | 103 ++++++++++++++++++++++++++++++++++++++++
1 file changed, 103 insertions(+)
diff --git a/dlls/quartz/tests/filtergraph.c b/dlls/quartz/tests/filtergraph.c
index 6a8afb3..4f1e9cf 100644
--- a/dlls/quartz/tests/filtergraph.c
+++ b/dlls/quartz/tests/filtergraph.c
@@ -592,6 +592,108 @@ todo_wine
DeleteFileW(filename);
}
+static void test_enum_filters(void)
+{
+ IBaseFilter *filter1, *filter2, *filters[2];
+ IFilterGraph2 *graph = create_graph();
+ IEnumFilters *enum1, *enum2;
+ ULONG count, ref;
+ HRESULT hr;
+
+ CoCreateInstance(&CLSID_AsyncReader, NULL, CLSCTX_INPROC_SERVER,
+ &IID_IBaseFilter, (void **)&filter1);
+ CoCreateInstance(&CLSID_AsyncReader, NULL, CLSCTX_INPROC_SERVER,
+ &IID_IBaseFilter, (void **)&filter2);
+
+ hr = IFilterGraph2_EnumFilters(graph, &enum1);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IEnumFilters_Next(enum1, 1, filters, NULL);
+ ok(hr == S_FALSE, "Got hr %#x.\n", hr);
+
+ IFilterGraph2_AddFilter(graph, filter1, NULL);
+ IFilterGraph2_AddFilter(graph, filter2, NULL);
+
+ hr = IEnumFilters_Next(enum1, 1, filters, NULL);
+ ok(hr == VFW_E_ENUM_OUT_OF_SYNC, "Got hr %#x.\n", hr);
+
+ hr = IEnumFilters_Reset(enum1);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IEnumFilters_Next(enum1, 1, filters, NULL);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+todo_wine
+ ok(filters[0] == filter2, "Got filter %p.\n", filters[0]);
+ IBaseFilter_Release(filters[0]);
+
+ hr = IEnumFilters_Next(enum1, 1, filters, &count);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(count == 1, "Got count %u.\n", count);
+todo_wine
+ ok(filters[0] == filter1, "Got filter %p.\n", filters[0]);
+ IBaseFilter_Release(filters[0]);
+
+ hr = IEnumFilters_Next(enum1, 1, filters, &count);
+ ok(hr == S_FALSE, "Got hr %#x.\n", hr);
+ ok(count == 0, "Got count %u.\n", count);
+
+ hr = IEnumFilters_Reset(enum1);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IEnumFilters_Next(enum1, 2, filters, &count);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(count == 2, "Got count %u.\n", count);
+todo_wine {
+ ok(filters[0] == filter2, "Got filter %p.\n", filters[0]);
+ ok(filters[1] == filter1, "Got filter %p.\n", filters[1]);
+}
+ IBaseFilter_Release(filters[0]);
+ IBaseFilter_Release(filters[1]);
+
+ IFilterGraph2_RemoveFilter(graph, filter1);
+ IFilterGraph2_AddFilter(graph, filter1, NULL);
+
+ hr = IEnumFilters_Next(enum1, 2, filters, &count);
+ ok(hr == VFW_E_ENUM_OUT_OF_SYNC, "Got hr %#x.\n", hr);
+
+ hr = IEnumFilters_Reset(enum1);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IEnumFilters_Next(enum1, 2, filters, &count);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(count == 2, "Got count %u.\n", count);
+todo_wine {
+ ok(filters[0] == filter1, "Got filter %p.\n", filters[0]);
+ ok(filters[1] == filter2, "Got filter %p.\n", filters[1]);
+}
+ IBaseFilter_Release(filters[0]);
+ IBaseFilter_Release(filters[1]);
+
+ hr = IEnumFilters_Reset(enum1);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IEnumFilters_Clone(enum1, &enum2);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IEnumFilters_Skip(enum2, 1);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IEnumFilters_Next(enum2, 2, filters, &count);
+ ok(hr == S_FALSE, "Got hr %#x.\n", hr);
+ ok(count == 1, "Got count %u.\n", count);
+todo_wine
+ ok(filters[0] == filter2, "Got filter %p.\n", filters[0]);
+ IBaseFilter_Release(filters[0]);
+
+ hr = IEnumFilters_Skip(enum1, 3);
+ ok(hr == S_FALSE, "Got hr %#x.\n", hr);
+
+ IEnumFilters_Release(enum2);
+ IEnumFilters_Release(enum1);
+ ref = IFilterGraph2_Release(graph);
+ ok(!ref, "Got outstanding refcount %d.\n", ref);
+}
+
static DWORD WINAPI call_RenderFile_multithread(LPVOID lParam)
{
WCHAR *filename = load_resource(avifile);
@@ -2402,6 +2504,7 @@ START_TEST(filtergraph)
test_render_run(avifile);
test_render_run(mpegfile);
+ test_enum_filters();
test_graph_builder();
test_render_filter_priority();
test_aggregate_filter_graph();
--
2.7.4
Sept. 18, 2018
Re: [PATCH] msi: Fix a typo.
by Zebediah Figura
On 18/09/18 09:29, Dmitry Timoshkov wrote:
> Zebediah Figura <z.figura12(a)gmail.com> wrote:
>
>> *facepalm*
>>
>> Thanks for finding that;
>
> You're welcome.
>
>> I can't *believe* it got past the tests.
>
> Probably it's the proper time to add some :)
>
That particular function does have tests; I suspect that the allocated
handle numbers just ended up being the same on the local and remote sides...
Sept. 18, 2018
Re: [PATCH] msi: Fix a typo.
by Dmitry Timoshkov
Zebediah Figura <z.figura12(a)gmail.com> wrote:
> *facepalm*
>
> Thanks for finding that;
You're welcome.
> I can't *believe* it got past the tests.
Probably it's the proper time to add some :)
--
Dmitry.
Sept. 18, 2018
Re: [PATCH] msi: Fix a typo.
by Zebediah Figura
On 18/09/18 00:59, Dmitry Timoshkov wrote:
> This patch should fix the regresion introduced by baea371c3d4153bc4a718c07f46971d4d39aa9f3.
>
> Signed-off-by: Dmitry Timoshkov <dmitry(a)baikal.ru>
> ---
> dlls/msi/package.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/dlls/msi/package.c b/dlls/msi/package.c
> index 3374964078..8e9ae6dd90 100644
> --- a/dlls/msi/package.c
> +++ b/dlls/msi/package.c
> @@ -1742,7 +1742,7 @@ MSIHANDLE WINAPI MsiGetActiveDatabase(MSIHANDLE hInstall)
> {
> __TRY
> {
> - handle = remote_GetActiveDatabase(hInstall);
> + handle = remote_GetActiveDatabase(remote);
> handle = alloc_msi_remote_handle(handle);
> }
> __EXCEPT(rpc_filter)
>
*facepalm*
Thanks for finding that; I can't *believe* it got past the tests.
Sept. 18, 2018