This is not correct, you must connect all pins, not just the first that succeeds.
Asleep? ;) You can't connect an input pin more then once (VFW_E_ALREADY_CONNECTED), anyway this function always returned S_OK, I fixed that too now... If you still think multiple connects should happen http://msdn.microsoft.com/library/en-us/directshow/htm/ipinconnect.asp ;)
No, no. It's not necessary. I'm convinced. :-)
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;
SendTheFilterAMessage(iface, SendPause);
This->state = State_Paused;
return S_OK;
}
Shouldn't S_FALSE be returned in the last statement?
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;
if (This->state == State_Running) SendTheFilterAMessage(iface, SendPause);
SendTheFilterAMessage(iface, SendStop);
This->state = State_Stopped;
return S_OK;
}
I think you should move the critical section out of SendTheFilterAMessage and put it in Run, Pause and Stop methods.
Bye, Christian
PS: SendTheFilterAMessage and FoundFilter are really odd names, no?
Added critical section around the mediacontrols, also added a release for the attached filters when the filtergraph gets released, so ref count leak has decreased.. I also submitted a patch to devenum to fix another release error, as a matter of fact:
fixme:quartz:ReadThread 0x7d331c20 -> Frame 4: 0 fixme:quartz:ReadThread 0x7d331c20 -> Frame 5: 0 fixme:quartz:Capture_Pause 0x7d331c20 -> (0x7d331d60) stub fixme:quartz:Capture_Stop 0x7d331c20 -> (0x7d331d60) stub fixme:quartz:CaptureGraphBuilder_Release Release IGraphFilter or w/e fixme:quartz:VfwCapture_Release (0x7d331c18/0x7d331c18)->() Old refcount: 2 fixme:quartz:VfwCapture_Release (0x7d331c18/0x7d331c18)->() Old refcount: 1
with those patches, VfwCapture is now being released normally, without reference leaks :):):)
Actually, 1 fix has to be made in pin.c Copy_PinInfo is used by QueryPinInfo and internally, in QueryPinInfo, the basefilter needs an addref there, but other internal functions shouldn't, a pin SHOULDN'T need to add an addref to it's filter, it will cause a deadrefcount (or something like that)
Because: IFilter created, refcount 1, IPin created, refcount 1, IPin adds refcount to ifilter, ifilter refcount 2 IFilter released, refcount 1, continues existing, pin not being destroyed, nobody ever knew it existed
I also added a fix for dlls/devenum/mediacatenum.c, which also has a refcount leak when querying an interface
I hope these patches get applied, because they should.. and I don't want to spend any more minute to them...
Index: filtergraph.c =================================================================== RCS file: /home/wine/wine/dlls/quartz/filtergraph.c,v retrieving revision 1.27 diff -u -p -r1.27 filtergraph.c --- filtergraph.c 24 Mar 2005 21:01:37 -0000 1.27 +++ filtergraph.c 25 Apr 2005 15:33:51 -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 */ @@ -648,7 +650,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 +679,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 +706,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 +1175,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 +1186,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 +1212,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 +1247,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 +1268,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 +1282,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 25 Apr 2005 15:45:29 -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 +314,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; }
Index: mediacatenum.c =================================================================== RCS file: /home/wine/wine/dlls/devenum/mediacatenum.c,v retrieving revision 1.14 diff -u -p -r1.14 mediacatenum.c --- mediacatenum.c 10 Jan 2005 12:25:29 -0000 1.14 +++ mediacatenum.c 25 Apr 2005 15:52:01 -0000 @@ -434,6 +434,8 @@ static HRESULT WINAPI DEVENUM_IMediaCatM res= IUnknown_QueryInterface(pObj,riidResult,ppvResult); }
+ if (pmkToLeft == NULL && pObj != NULL) IUnknown_Release(pObj); + if (pProp) { IPropertyBag_Release(pProp);