Alexander Dorofeyev : quartz: Aggregate filtermapper in filtergraph.
Alexandre Julliard
julliard at winehq.org
Fri Jul 18 06:46:04 CDT 2008
Module: wine
Branch: master
Commit: 0bea470dfc155f080abed42b5bde1e8af315801f
URL: http://source.winehq.org/git/wine.git/?a=commit;h=0bea470dfc155f080abed42b5bde1e8af315801f
Author: Alexander Dorofeyev <alexd4 at inbox.lv>
Date: Thu Jul 17 20:24:24 2008 +0300
quartz: Aggregate filtermapper in filtergraph.
---
dlls/quartz/filtergraph.c | 47 ++++++++++++++++++++++++++++++++++++++++++--
1 files changed, 44 insertions(+), 3 deletions(-)
diff --git a/dlls/quartz/filtergraph.c b/dlls/quartz/filtergraph.c
index b82cbcd..19dbb8c 100644
--- a/dlls/quartz/filtergraph.c
+++ b/dlls/quartz/filtergraph.c
@@ -176,6 +176,7 @@ typedef struct _IFilterGraphImpl {
/* IVideoFrameStep */
LONG ref;
+ IUnknown *punkFilterMapper2;
IFilterMapper2 * pFilterMapper2;
IBaseFilter ** ppFiltersInGraph;
LPWSTR * pFilterNames;
@@ -260,6 +261,12 @@ static HRESULT WINAPI FilterGraphInner_QueryInterface(IUnknown * iface,
} else if (IsEqualGUID(&IID_IMediaPosition, riid)) {
*ppvObj = &(This->IMediaPosition_vtbl);
TRACE(" returning IMediaPosition interface (%p)\n", *ppvObj);
+ } else if (IsEqualGUID(&IID_IFilterMapper, riid)) {
+ TRACE(" requesting IFilterMapper interface from aggregated filtermapper (%p)\n", *ppvObj);
+ return IUnknown_QueryInterface(This->punkFilterMapper2, riid, ppvObj);
+ } else if (IsEqualGUID(&IID_IFilterMapper2, riid)) {
+ *ppvObj = This->pFilterMapper2;
+ TRACE(" returning IFilterMapper2 interface from aggregated filtermapper (%p)\n", *ppvObj);
} else {
*ppvObj = NULL;
FIXME("unknown interface %s\n", debugstr_guid(riid));
@@ -289,6 +296,8 @@ static ULONG WINAPI FilterGraphInner_Release(IUnknown * iface)
if (ref == 0) {
int i;
+ This->ref = 1; /* guard against reentrancy (aggregation). */
+
IMediaControl_Stop((IMediaControl*)&(This->IMediaControl_vtbl));
while (This->nFilters)
@@ -302,7 +311,19 @@ static ULONG WINAPI FilterGraphInner_Release(IUnknown * iface)
if (This->ItfCacheEntries[i].iface)
IUnknown_Release(This->ItfCacheEntries[i].iface);
}
- IFilterMapper2_Release(This->pFilterMapper2);
+
+ /* AddRef on controlling IUnknown, to compensate for Release of cached IFilterMapper2 interface below.
+
+ * NOTE: Filtergraph_AddRef isn't suitable, because bUnkOuterValid may be FALSE but punkOuter non-NULL
+ * and already passed as punkOuter to filtermapper in FilterGraph_create - this will happen in case of
+ * CoCreateInstance of filtergraph with non-null pUnkOuter and REFIID other than IID_Unknown that is
+ * cleaning up after error. */
+ if (This->pUnkOuter) IUnknown_AddRef(This->pUnkOuter);
+ else IUnknown_AddRef((IUnknown*)&This->IInner_vtbl);
+
+ IFilterMapper2_Release(This->pFilterMapper2);
+ IUnknown_Release(This->punkFilterMapper2);
+
CloseHandle(This->hEventCompletion);
EventsQueue_Destroy(&This->evqueue);
This->cs.DebugInfo->Spare[0] = 0;
@@ -5394,11 +5415,31 @@ HRESULT FilterGraph_create(IUnknown *pUnkOuter, LPVOID *ppObj)
memcpy(&fimpl->timeformatseek, &TIME_FORMAT_MEDIA_TIME, sizeof(GUID));
fimpl->start_time = fimpl->position = 0;
fimpl->stop_position = -1;
+ fimpl->punkFilterMapper2 = NULL;
+
+ /* create Filtermapper aggregated. */
+ hr = CoCreateInstance(&CLSID_FilterMapper2, pUnkOuter ? pUnkOuter : (IUnknown*)&fimpl->IInner_vtbl, CLSCTX_INPROC_SERVER,
+ &IID_IUnknown, (LPVOID*)&fimpl->punkFilterMapper2);
+
+ if (SUCCEEDED(hr)) {
+ hr = IUnknown_QueryInterface(fimpl->punkFilterMapper2, &IID_IFilterMapper2, (LPVOID*)&fimpl->pFilterMapper2);
+ }
+
+ if (SUCCEEDED(hr)) {
+ /* Release controlling IUnknown - compensate refcount increase from caching IFilterMapper2 interface. */
+ if (pUnkOuter) IUnknown_Release(pUnkOuter);
+ else IUnknown_Release((IUnknown*)&fimpl->IInner_vtbl);
+ }
- hr = CoCreateInstance(&CLSID_FilterMapper2, NULL, CLSCTX_INPROC_SERVER, &IID_IFilterMapper2, (LPVOID*)&fimpl->pFilterMapper2);
if (FAILED(hr)) {
ERR("Unable to create filter mapper (%x)\n", hr);
- return hr;
+ if (fimpl->punkFilterMapper2) IUnknown_Release(fimpl->punkFilterMapper2);
+ CloseHandle(fimpl->hEventCompletion);
+ EventsQueue_Destroy(&fimpl->evqueue);
+ fimpl->cs.DebugInfo->Spare[0] = 0;
+ DeleteCriticalSection(&fimpl->cs);
+ CoTaskMemFree(fimpl);
+ return hr;
}
IFilterGraph2_SetDefaultSyncSource((IFilterGraph2*)fimpl);
More information about the wine-cvs
mailing list