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