Signed-off-by: Zebediah Figura z.figura12@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..c0e5250 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", hr); +} + 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();
Signed-off-by: Zebediah Figura z.figura12@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; }
Signed-off-by: Zebediah Figura z.figura12@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;
Signed-off-by: Zebediah Figura z.figura12@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,
Signed-off-by: Zebediah Figura z.figura12@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 c0e5250..0e1e04a 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]);
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.
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- 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 0e1e04a..6fe564f 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();
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.