Enummedia patch

Maarten Lankhorst m.b.lankhorst at gmail.com
Thu May 5 12:07:29 CDT 2005


EnumMedia:
Fixed {Copy/Delete/Free}MediaType functions to show proper behaviour
Fixed EnumMediaTypes to copy pbFormat too.
Added FreeMediaType

pin.c & filtergraph.c:
Fixed a dozen of reference (and some memory) leaks
Implemented filtergraph_pause/stop (Adding it like this saves 
copy/pasting + possible associated bugs)

This does not fix whole quartz, although I think most reference leaks in 
filtergraph.c are gone now, (VfwCapture ends nicely with 0 refcounts on 
filter and pin), some other bugs might exist:
- memcpy(am_media_type1, am_media_type2, sizeof(AM_MEDIATYPE)); should 
be CopyMediaType(am_media_type1, am_media_type2); so pbFormat gets 
copied too
- because deletemediatype uses cotaskmemfree now, all code should be 
inspected so that code that uses deletemediatype incorrectly should use 
freemediatype (Incorrectly means: in DeleteMediaType(xxx); xxx should 
not be freed
- cotaskmemfree(am_media_type1); is evil, it's better to use deletemediatype
-------------- next part --------------
Index: enummedia.c
===================================================================
RCS file: /home/wine/wine/dlls/quartz/enummedia.c,v
retrieving revision 1.5
diff -u -p -r1.5 enummedia.c
--- enummedia.c	6 Jan 2005 19:36:47 -0000	1.5
+++ enummedia.c	5 May 2005 16:53:10 -0000
@@ -27,13 +27,14 @@ WINE_DEFAULT_DEBUG_CHANNEL(quartz);
 HRESULT CopyMediaType(AM_MEDIA_TYPE * pDest, const AM_MEDIA_TYPE *pSrc)
 {
     memcpy(pDest, pSrc, sizeof(AM_MEDIA_TYPE));
+    if (!pSrc->pbFormat) return S_OK;
     if (!(pDest->pbFormat = CoTaskMemAlloc(pSrc->cbFormat)))
         return E_OUTOFMEMORY;
     memcpy(pDest->pbFormat, pSrc->pbFormat, pSrc->cbFormat);
     return S_OK;
 }
 
-void DeleteMediaType(AM_MEDIA_TYPE * pMediaType)
+void FreeMediaType(AM_MEDIA_TYPE * pMediaType)
 {
     if (pMediaType->pbFormat)
     {
@@ -47,6 +48,13 @@ void DeleteMediaType(AM_MEDIA_TYPE * pMe
     }
 }
 
+void DeleteMediaType(AM_MEDIA_TYPE * pMediaType)
+{
+    FreeMediaType(pMediaType);
+    CoTaskMemFree(pMediaType);
+}
+
+
 BOOL CompareMediaTypes(const AM_MEDIA_TYPE * pmt1, const AM_MEDIA_TYPE * pmt2, BOOL bWildcards)
 {
     TRACE("pmt1: ");
@@ -90,7 +98,11 @@ HRESULT IEnumMediaTypesImpl_Construct(co
     pEnumMediaTypes->enumMediaDetails.cMediaTypes = pDetails->cMediaTypes;
     pEnumMediaTypes->enumMediaDetails.pMediaTypes = CoTaskMemAlloc(sizeof(AM_MEDIA_TYPE) * pDetails->cMediaTypes);
     for (i = 0; i < pDetails->cMediaTypes; i++)
-        pEnumMediaTypes->enumMediaDetails.pMediaTypes[i] = pDetails->pMediaTypes[i];
+        if (FAILED(CopyMediaType(&pEnumMediaTypes->enumMediaDetails.pMediaTypes[i], &pDetails->pMediaTypes[i]))) {
+           while (--i > 0) CoTaskMemFree(pEnumMediaTypes->enumMediaDetails.pMediaTypes[i].pbFormat);
+           CoTaskMemFree(pEnumMediaTypes->enumMediaDetails.pMediaTypes);
+           return E_OUTOFMEMORY;
+        }
     *ppEnum = (IEnumMediaTypes *)(&pEnumMediaTypes->lpVtbl);
     return S_OK;
 }
@@ -136,12 +148,14 @@ static ULONG WINAPI IEnumMediaTypesImpl_
 
     if (!refCount)
     {
+        int i;
+        for (i = 0; i < This->enumMediaDetails.cMediaTypes; i++)
+            if (This->enumMediaDetails.pMediaTypes[i].pbFormat)
+                CoTaskMemFree(This->enumMediaDetails.pMediaTypes[i].pbFormat);
         CoTaskMemFree(This->enumMediaDetails.pMediaTypes);
         CoTaskMemFree(This);
-        return 0;
     }
-    else
-        return refCount;
+    return refCount;
 }
 
 static HRESULT WINAPI IEnumMediaTypesImpl_Next(IEnumMediaTypes * iface, ULONG cMediaTypes, AM_MEDIA_TYPE ** ppMediaTypes, ULONG * pcFetched)
@@ -159,7 +173,13 @@ static HRESULT WINAPI IEnumMediaTypesImp
         ULONG i;
         *ppMediaTypes = CoTaskMemAlloc(sizeof(AM_MEDIA_TYPE) * cFetched);
         for (i = 0; i < cFetched; i++)
-            (*ppMediaTypes)[i] = This->enumMediaDetails.pMediaTypes[This->uIndex + i];
+            if (FAILED(CopyMediaType(&(*ppMediaTypes)[i], &This->enumMediaDetails.pMediaTypes[This->uIndex + i]))) {
+                while (--i)
+                    CoTaskMemFree((*ppMediaTypes)[i].pbFormat);
+                CoTaskMemFree(*ppMediaTypes);
+                *ppMediaTypes = NULL;
+                return E_OUTOFMEMORY;
+            }
     }
 
     if ((cMediaTypes != 1) || pcFetched)
Index: quartz_private.h
===================================================================
RCS file: /home/wine/wine/dlls/quartz/quartz_private.h,v
retrieving revision 1.23
diff -u -p -r1.23 quartz_private.h
--- quartz_private.h	5 May 2005 09:50:35 -0000	1.23
+++ quartz_private.h	5 May 2005 16:53:10 -0000
@@ -77,6 +77,7 @@ extern const char * qzdebugstr_guid(cons
 extern const char * qzdebugstr_State(FILTER_STATE state);
 
 HRESULT CopyMediaType(AM_MEDIA_TYPE * pDest, const AM_MEDIA_TYPE *pSrc);
+void FreeMediaType(AM_MEDIA_TYPE * pmt);
 void DeleteMediaType(AM_MEDIA_TYPE * pmt);
 BOOL CompareMediaTypes(const AM_MEDIA_TYPE * pmt1, const AM_MEDIA_TYPE * pmt2, BOOL bWildcards);
 void dump_AM_MEDIA_TYPE(const AM_MEDIA_TYPE * pmt);
-------------- next part --------------
Index: filtergraph.c
===================================================================
RCS file: /home/wine/wine/dlls/quartz/filtergraph.c,v
retrieving revision 1.28
diff -u -p -r1.28 filtergraph.c
--- filtergraph.c	5 May 2005 09:50:35 -0000	1.28
+++ filtergraph.c	5 May 2005 17:00:28 -0000
@@ -245,6 +245,9 @@ static ULONG Filtergraph_Release(IFilter
     TRACE("(%p)->(): new ref = %ld\n", This, ref);
     
     if (ref == 0) {
+        int i;
+        for (i = 0; i < This->nFilters; i++)
+           IBaseFilter_Release(This->ppFiltersInGraph[i]);
 	IFilterMapper2_Release(This->pFilterMapper2);
 	CloseHandle(This->hEventCompletion);
 	EventsQueue_Destroy(&This->evqueue);
@@ -556,8 +559,7 @@ static HRESULT GetInternalConnections(IB
             IPin_QueryDirection(ppin, &pindir);
             if (pindir == PINDIR_OUTPUT)
                 i++;
-            else
-                IPin_Release(ppin);
+            IPin_Release(ppin);
         }
         *pppins = CoTaskMemAlloc(sizeof(IPin*)*i);
         /* Retrieve output pins */
@@ -605,10 +607,8 @@ static HRESULT WINAPI Graphbuilder_Conne
     TRACE("(%p/%p)->(%p, %p)\n", This, iface, ppinOut, ppinIn);
 
     /* Try direct connection first */
-    TRACE("Try direct connection first\n");
     hr = IPin_Connect(ppinOut, ppinIn, NULL);
     if (SUCCEEDED(hr)) {
-        TRACE("Direct connection successful\n");
         return S_OK;
     }
     TRACE("Direct connection failed, trying to insert other filters\n");
@@ -648,7 +648,7 @@ static HRESULT WINAPI Graphbuilder_Conne
         VARIANT var;
         GUID clsid;
         IPin** ppins;
-        IPin* ppinfilter;
+        IPin* ppinfilter = NULL;
         IBaseFilter* pfilter = NULL;
 
         hr = GetFilterInfo(pMoniker, &clsid, &var);
@@ -677,6 +677,7 @@ static HRESULT WINAPI Graphbuilder_Conne
             ERR("Enumpins (%lx)\n", hr);
             goto error;
         }
+
         hr = IEnumPins_Next(penumpins, 1, &ppinfilter, &pin);
         if (FAILED(hr)) {
             ERR("Next (%lx)\n", hr);
@@ -703,17 +704,22 @@ static HRESULT WINAPI Graphbuilder_Conne
             TRACE("pins to consider: %ld\n", nb);
             for(i = 0; i < nb; i++) {
                 TRACE("Processing pin %d\n", i);
-                hr = IGraphBuilder_Connect(iface, ppins[0], ppinIn);
+                hr = IGraphBuilder_Connect(iface, ppins[i], ppinIn);
                 if (FAILED(hr)) {
-                    TRACE("Cannot render pin %p (%lx)\n", ppinfilter, hr);
-                    return hr;
+                   TRACE("Cannot render pin %p (%lx)\n", ppinfilter, hr);
                 }
+                IPin_Release(ppins[i]);
+                if (SUCCEEDED(hr)) break;
             }
+            while (++i < nb) IPin_Release(ppins[i]);
             CoTaskMemFree(ppins);
+            IBaseFilter_Release(pfilter);
+            IPin_Release(ppinfilter);
+            break;
         }
-        break;
 
 error:
+        if (ppinfilter) IPin_Release(ppinfilter);
         if (pfilter) {
             IGraphBuilder_RemoveFilter(iface, pfilter);
             IBaseFilter_Release(pfilter);
@@ -1167,7 +1173,9 @@ static HRESULT WINAPI Mediacontrol_Invok
     return S_OK;
 }
 
-static HRESULT ExploreGraph(IFilterGraphImpl* pGraph, IPin* pOutputPin, REFERENCE_TIME tStart)
+typedef HRESULT(WINAPI *fnFoundFilter)(IBaseFilter *);
+
+static HRESULT ExploreGraph(IFilterGraphImpl* pGraph, IPin* pOutputPin, fnFoundFilter FoundFilter)
 {
     HRESULT hr;
     IPin* pInputPin;
@@ -1176,7 +1184,8 @@ static HRESULT ExploreGraph(IFilterGraph
     ULONG i;
     PIN_INFO PinInfo;
 
-    TRACE("%p %p %lld\n", pGraph, pOutputPin, tStart);
+    TRACE("%p %p\n", pGraph, pOutputPin);
+    PinInfo.pFilter = NULL;
 
     hr = IPin_ConnectedTo(pOutputPin, &pInputPin);
 
@@ -1201,20 +1210,33 @@ static HRESULT ExploreGraph(IFilterGraph
                 /* Explore the graph downstream from this pin
 		 * FIXME: We should prevent exploring from a pin more than once. This can happens when
 		 * several input pins are connected to the same output (a MUX for instance). */
-                ExploreGraph(pGraph, ppPins[i], tStart);
+                ExploreGraph(pGraph, ppPins[i], FoundFilter);
+                IPin_Release(ppPins[i]);
             }
 
             CoTaskMemFree(ppPins);
         }
-        TRACE("Run filter %p\n", PinInfo.pFilter);
-        IBaseFilter_Run(PinInfo.pFilter, tStart);
+        TRACE("Doing stuff with filter %p\n", PinInfo.pFilter);
+        FoundFilter(PinInfo.pFilter);
     }
 
+    if (PinInfo.pFilter) IBaseFilter_Release(PinInfo.pFilter);
     return hr;
 }
 
-/*** IMediaControl methods ***/
-static HRESULT WINAPI Mediacontrol_Run(IMediaControl *iface) {
+static HRESULT WINAPI SendRun(IBaseFilter *pFilter) {
+   return IBaseFilter_Run(pFilter, 0);
+}
+
+static HRESULT WINAPI SendPause(IBaseFilter *pFilter) {
+   return IBaseFilter_Pause(pFilter);
+}
+
+static HRESULT WINAPI SendStop(IBaseFilter *pFilter) {
+   return IBaseFilter_Stop(pFilter);
+}
+
+static HRESULT WINAPI SendTheFilterAMessage(IMediaControl *iface, fnFoundFilter FoundFilter) {
     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaControl_vtbl, iface);
     int i;
     IBaseFilter* pfilter;
@@ -1223,19 +1245,10 @@ static HRESULT WINAPI Mediacontrol_Run(I
     IPin* pPin;
     LONG dummy;
     PIN_DIRECTION dir;
-
     TRACE("(%p/%p)->()\n", This, iface);
 
-    EnterCriticalSection(&This->cs);
-
-    if (This->state == State_Running)
-    {
-        LeaveCriticalSection(&This->cs);
-        return S_OK;
-    }
-
-    /* Explorer the graph from source filters to renderers, determine renderers number and
-     * run filters from renderers to source filters */
+    /* Explorer the graph from source filters to renderers, determine renderers
+     * number and run filters from renderers to source filters */
     This->nRenderers = 0;  
     ResetEvent(This->hEventCompletion);
 
@@ -1253,6 +1266,7 @@ static HRESULT WINAPI Mediacontrol_Run(I
         while(IEnumPins_Next(pEnum, 1, &pPin, &dummy) == S_OK)
         {
             IPin_QueryDirection(pPin, &dir);
+            IPin_Release(pPin);
             if (dir == PINDIR_INPUT)
             {
                 source = FALSE;
@@ -1266,34 +1280,56 @@ static HRESULT WINAPI Mediacontrol_Run(I
             while(IEnumPins_Next(pEnum, 1, &pPin, &dummy) == S_OK)
             {
                 /* Explore the graph downstream from this pin */
-                ExploreGraph(This, pPin, 0);
+                ExploreGraph(This, pPin, FoundFilter);
+                IPin_Release(pPin);
             }
-            IBaseFilter_Run(pfilter, 0);
+            FoundFilter(pfilter);
         }
         IEnumPins_Release(pEnum);
     }
 
-    This->state = State_Running;
+    return S_FALSE;
+}
+
+/*** IMediaControl methods ***/
+static HRESULT WINAPI Mediacontrol_Run(IMediaControl *iface) {
+    ICOM_THIS_MULTI(IFilterGraphImpl, IMediaControl_vtbl, iface);
+    TRACE("(%p/%p)->()\n", This, iface);
+
+    if (This->state == State_Running) return S_OK;
 
+    EnterCriticalSection(&This->cs);
+    SendTheFilterAMessage(iface, SendRun);
+    This->state = State_Running;
     LeaveCriticalSection(&This->cs);
-    
     return S_FALSE;
 }
 
 static HRESULT WINAPI Mediacontrol_Pause(IMediaControl *iface) {
     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaControl_vtbl, iface);
+    TRACE("(%p/%p)->()\n", This, iface);
 
-    TRACE("(%p/%p)->(): stub !!!\n", This, iface);
+    if (This->state == State_Paused) return S_OK;
 
-    return S_OK;
+    EnterCriticalSection(&This->cs);
+    SendTheFilterAMessage(iface, SendPause);
+    This->state = State_Paused;
+    LeaveCriticalSection(&This->cs);
+    return S_FALSE;
 }
 
 static HRESULT WINAPI Mediacontrol_Stop(IMediaControl *iface) {
     ICOM_THIS_MULTI(IFilterGraphImpl, IMediaControl_vtbl, iface);
+    TRACE("(%p/%p)->()\n", This, iface);
 
-    TRACE("(%p/%p)->(): stub !!!\n", This, iface);
+    if (This->state == State_Stopped) return S_OK;
 
-    return S_OK;
+    EnterCriticalSection(&This->cs);
+    if (This->state == State_Running) SendTheFilterAMessage(iface, SendPause);
+    SendTheFilterAMessage(iface, SendStop);
+    This->state = State_Stopped;
+    LeaveCriticalSection(&This->cs);
+    return S_FALSE;
 }
 
 static HRESULT WINAPI Mediacontrol_GetState(IMediaControl *iface,
Index: pin.c
===================================================================
RCS file: /home/wine/wine/dlls/quartz/pin.c,v
retrieving revision 1.13
diff -u -p -r1.13 pin.c
--- pin.c	2 Mar 2005 10:12:12 -0000	1.13
+++ pin.c	5 May 2005 17:00:28 -0000
@@ -49,7 +49,6 @@ static void Copy_PinInfo(PIN_INFO * pDes
     strcpyW(pDest->achName, pSrc->achName);
     pDest->dir = pSrc->dir;
     pDest->pFilter = pSrc->pFilter;
-    IBaseFilter_AddRef(pDest->pFilter);
 }
 
 /* Function called as a helper to IPin_Connect */
@@ -311,6 +310,7 @@ HRESULT WINAPI IPinImpl_QueryPinInfo(IPi
     TRACE("(%p/%p)->(%p)\n", This, iface, pInfo);
 
     Copy_PinInfo(pInfo, &This->pinInfo);
+    IBaseFilter_AddRef(pInfo->pFilter);
 
     return S_OK;
 }


More information about the wine-patches mailing list