quartz: Make the EnumPins interface dynamic.

Take a reference to the ibasefilter and request it for the pins and a
cookie. This seems to be the easiest way to ensure correctness.
diff --git a/dlls/quartz/dsoundrender.c b/dlls/quartz/dsoundrender.c
index af98c52..3e465a0 100644
--- a/dlls/quartz/dsoundrender.c
+++ b/dlls/quartz/dsoundrender.c
@@ -61,7 +61,6 @@
     FILTER_INFO filterInfo;
 
     InputPin * pInputPin;
-    IPin ** ppPins;
 
     LPDIRECTSOUND dsound;
     LPDIRECTSOUNDBUFFER dsbuffer;
@@ -334,15 +333,6 @@
     pDSoundRender->csFilter.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": DSoundRenderImpl.csFilter");
     pDSoundRender->state = State_Stopped;
 
-    pDSoundRender->ppPins = CoTaskMemAlloc(1 * sizeof(IPin *));
-    if (!pDSoundRender->ppPins)
-    {
-        pDSoundRender->csFilter.DebugInfo->Spare[0] = 0;
-        DeleteCriticalSection(&pDSoundRender->csFilter);
-        CoTaskMemFree(pDSoundRender);
-        return E_OUTOFMEMORY;
-    }
-
     /* construct input pin */
     piInput.dir = PINDIR_INPUT;
     piInput.pFilter = (IBaseFilter *)pDSoundRender;
@@ -361,14 +351,12 @@
         MediaSeekingImpl_Init((IBaseFilter*)pDSoundRender, sound_mod_stop, sound_mod_start, sound_mod_rate, &pDSoundRender->mediaSeeking, &pDSoundRender->csFilter);
         pDSoundRender->mediaSeeking.lpVtbl = &IMediaSeeking_Vtbl;
 
-        pDSoundRender->ppPins[0] = (IPin *)pDSoundRender->pInputPin;
         *ppv = (LPVOID)pDSoundRender;
     }
     else
     {
         if (pDSoundRender->pInputPin)
             IPin_Release((IPin*)pDSoundRender->pInputPin);
-        CoTaskMemFree(pDSoundRender->ppPins);
         pDSoundRender->csFilter.DebugInfo->Spare[0] = 0;
         DeleteCriticalSection(&pDSoundRender->csFilter);
         CoTaskMemFree(pDSoundRender);
@@ -442,16 +430,15 @@
             IDirectSound_Release(This->dsound);
         This->dsound = NULL;
        
-        if (SUCCEEDED(IPin_ConnectedTo(This->ppPins[0], &pConnectedTo)))
+        if (SUCCEEDED(IPin_ConnectedTo((IPin *)This->pInputPin, &pConnectedTo)))
         {
             IPin_Disconnect(pConnectedTo);
             IPin_Release(pConnectedTo);
         }
-        IPin_Disconnect(This->ppPins[0]);
+        IPin_Disconnect((IPin *)This->pInputPin);
 
-        IPin_Release(This->ppPins[0]);
-        
-        CoTaskMemFree(This->ppPins);
+        IPin_Release((IPin *)This->pInputPin);
+
         This->lpVtbl = NULL;
         This->IBasicAudio_vtbl = NULL;
         
@@ -609,16 +596,28 @@
 
 /** IBaseFilter implementation **/
 
+static HRESULT DSoundRender_GetPin(IBaseFilter *iface, ULONG pos, IPin **pin, DWORD *lastsynctick)
+{
+    DSoundRenderImpl *This = (DSoundRenderImpl *)iface;
+
+    /* Our pins are static, not changing so setting static tick count is ok */
+    *lastsynctick = 0;
+
+    if (pos >= 1)
+        return S_FALSE;
+
+    *pin = (IPin *)This->pInputPin;
+    IPin_AddRef(*pin);
+    return S_OK;
+}
+
 static HRESULT WINAPI DSoundRender_EnumPins(IBaseFilter * iface, IEnumPins **ppEnum)
 {
-    ENUMPINDETAILS epd;
     DSoundRenderImpl *This = (DSoundRenderImpl *)iface;
 
     TRACE("(%p/%p)->(%p)\n", This, iface, ppEnum);
 
-    epd.cPins = 1; /* input pin */
-    epd.ppPins = This->ppPins;
-    return IEnumPinsImpl_Construct(&epd, ppEnum);
+    return IEnumPinsImpl_Construct(ppEnum, DSoundRender_GetPin, iface);
 }
 
 static HRESULT WINAPI DSoundRender_FindPin(IBaseFilter * iface, LPCWSTR Id, IPin **ppPin)
diff --git a/dlls/quartz/enumpins.c b/dlls/quartz/enumpins.c
index 675ef5c..82dac9d 100644
--- a/dlls/quartz/enumpins.c
+++ b/dlls/quartz/enumpins.c
@@ -28,13 +28,15 @@
 {
     const IEnumPinsVtbl * lpVtbl;
     LONG refCount;
-    ENUMPINDETAILS enumPinDetails;
     ULONG uIndex;
+    IBaseFilter *base;
+    FNOBTAINPIN receive_pin;
+    DWORD synctime;
 } IEnumPinsImpl;
 
 static const struct IEnumPinsVtbl IEnumPinsImpl_Vtbl;
 
-HRESULT IEnumPinsImpl_Construct(const ENUMPINDETAILS * pDetails, IEnumPins ** ppEnum)
+HRESULT IEnumPinsImpl_Construct(IEnumPins ** ppEnum, FNOBTAINPIN receive_pin, IBaseFilter *base)
 {
     IEnumPinsImpl * pEnumPins;
 
@@ -50,9 +52,13 @@
     pEnumPins->lpVtbl = &IEnumPinsImpl_Vtbl;
     pEnumPins->refCount = 1;
     pEnumPins->uIndex = 0;
-    pEnumPins->enumPinDetails = *pDetails;
+    pEnumPins->receive_pin = receive_pin;
+    pEnumPins->base = base;
+    IBaseFilter_AddRef(base);
     *ppEnum = (IEnumPins *)(&pEnumPins->lpVtbl);
 
+    receive_pin(base, ~0, NULL, &pEnumPins->synctime);
+
     TRACE("Created new enumerator (%p)\n", *ppEnum);
     return S_OK;
 }
@@ -95,9 +101,10 @@
     ULONG refCount = InterlockedDecrement(&This->refCount);
 
     TRACE("(%p)->() Release from %d\n", This, refCount + 1);
-    
+
     if (!refCount)
     {
+        IBaseFilter_Release(This->base);
         CoTaskMemFree(This);
         return 0;
     }
@@ -107,10 +114,10 @@
 
 static HRESULT WINAPI IEnumPinsImpl_Next(IEnumPins * iface, ULONG cPins, IPin ** ppPins, ULONG * pcFetched)
 {
-    ULONG cFetched; 
     IEnumPinsImpl *This = (IEnumPinsImpl *)iface;
-
-    cFetched = min(This->enumPinDetails.cPins, This->uIndex + cPins) - This->uIndex;
+    DWORD synctime = This->synctime;
+    HRESULT hr = S_OK;
+    ULONG i = 0;
 
     TRACE("(%u, %p, %p)\n", cPins, ppPins, pcFetched);
 
@@ -120,21 +127,28 @@
     if (cPins > 1 && !pcFetched)
         return E_INVALIDARG;
 
-    if (cFetched > 0)
+    if (pcFetched)
+        *pcFetched = 0;
+
+    while (i < cPins && hr == S_OK)
     {
-        ULONG i;
-        for (i = 0; i < cFetched; i++) {
-            IPin_AddRef(This->enumPinDetails.ppPins[This->uIndex + i]);
-            ppPins[i] = This->enumPinDetails.ppPins[This->uIndex + i];
-        }
+        hr = This->receive_pin(This->base, This->uIndex + i, &ppPins[i], &synctime);
+
+        if (hr == S_OK)
+            ++i;
+
+        if (synctime != This->synctime)
+            break;
     }
 
-    if ((cPins != 1) || pcFetched)
-        *pcFetched = cFetched;
+    if (!i && synctime != This->synctime)
+        return VFW_E_ENUM_OUT_OF_SYNC;
 
-    This->uIndex += cFetched;
+    if (pcFetched)
+        *pcFetched = i;
+    This->uIndex += i;
 
-    if (cFetched != cPins)
+    if (i < cPins)
         return S_FALSE;
     return S_OK;
 }
@@ -142,15 +156,23 @@
 static HRESULT WINAPI IEnumPinsImpl_Skip(IEnumPins * iface, ULONG cPins)
 {
     IEnumPinsImpl *This = (IEnumPinsImpl *)iface;
+    DWORD synctime = This->synctime;
+    HRESULT hr;
+    IPin *pin = NULL;
 
     TRACE("(%u)\n", cPins);
 
-    if (This->uIndex + cPins < This->enumPinDetails.cPins)
-    {
+    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 S_OK;
-    }
-    return S_FALSE;
+
+    return hr;
 }
 
 static HRESULT WINAPI IEnumPinsImpl_Reset(IEnumPins * iface)
@@ -158,6 +180,7 @@
     IEnumPinsImpl *This = (IEnumPinsImpl *)iface;
 
     TRACE("IEnumPinsImpl::Reset()\n");
+    This->receive_pin(This->base, ~0, NULL, &This->synctime);
 
     This->uIndex = 0;
     return S_OK;
@@ -170,7 +193,7 @@
 
     TRACE("(%p)\n", ppEnum);
 
-    hr = IEnumPinsImpl_Construct(&This->enumPinDetails, ppEnum);
+    hr = IEnumPinsImpl_Construct(ppEnum, This->receive_pin, This->base);
     if (FAILED(hr))
         return hr;
     return IEnumPins_Skip(*ppEnum, This->uIndex);
diff --git a/dlls/quartz/filesource.c b/dlls/quartz/filesource.c
index 4519fdf..a44de7a 100644
--- a/dlls/quartz/filesource.c
+++ b/dlls/quartz/filesource.c
@@ -46,6 +46,7 @@
     FILTER_INFO filterInfo;
     FILTER_STATE state;
     CRITICAL_SECTION csFilter;
+    DWORD lastpinchange;
 
     IPin * pOutputPin;
     LPOLESTR pszFileName;
@@ -353,6 +354,7 @@
     pAsyncRead->filterInfo.achName[0] = '\0';
     pAsyncRead->filterInfo.pGraph = NULL;
     pAsyncRead->pOutputPin = NULL;
+    pAsyncRead->lastpinchange = GetTickCount();
 
     InitializeCriticalSection(&pAsyncRead->csFilter);
     pAsyncRead->csFilter.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": AsyncReader.csFilter");
@@ -520,16 +522,28 @@
 
 /** IBaseFilter methods **/
 
-static HRESULT WINAPI AsyncReader_EnumPins(IBaseFilter * iface, IEnumPins **ppEnum)
+static HRESULT AsyncReader_GetPin(IBaseFilter *iface, ULONG pos, IPin **pin, DWORD *lastsynctick)
 {
-    ENUMPINDETAILS epd;
     AsyncReader *This = (AsyncReader *)iface;
 
-    TRACE("(%p)\n", ppEnum);
+    /* Our pins are almost static, not changing so setting static tick count is ok */
+    *lastsynctick = This->lastpinchange;
 
-    epd.cPins = This->pOutputPin ? 1 : 0;
-    epd.ppPins = &This->pOutputPin;
-    return IEnumPinsImpl_Construct(&epd, ppEnum);
+    if (pos >= 1)
+        return S_FALSE;
+
+    *pin = (IPin *)This->pOutputPin;
+    IPin_AddRef(*pin);
+    return S_OK;
+}
+
+static HRESULT WINAPI AsyncReader_EnumPins(IBaseFilter * iface, IEnumPins **ppEnum)
+{
+    AsyncReader *This = (AsyncReader *)iface;
+
+    TRACE("(%p/%p)->(%p)\n", This, iface, ppEnum);
+
+    return IEnumPinsImpl_Construct(ppEnum, AsyncReader_GetPin, iface);
 }
 
 static HRESULT WINAPI AsyncReader_FindPin(IBaseFilter * iface, LPCWSTR Id, IPin **ppPin)
@@ -636,6 +650,7 @@
 
     /* create pin */
     hr = FileAsyncReader_Construct(hFile, (IBaseFilter *)&This->lpVtbl, &This->csFilter, &This->pOutputPin);
+    This->lastpinchange = GetTickCount();
 
     if (SUCCEEDED(hr))
         hr = IPin_QueryInterface(This->pOutputPin, &IID_IAsyncReader, (LPVOID *)&pReader);
diff --git a/dlls/quartz/nullrenderer.c b/dlls/quartz/nullrenderer.c
index f511a7b..4bf2c84 100644
--- a/dlls/quartz/nullrenderer.c
+++ b/dlls/quartz/nullrenderer.c
@@ -61,7 +61,6 @@
     FILTER_INFO filterInfo;
 
     InputPin *pInputPin;
-    IPin ** ppPins;
     IUnknown * pUnkOuter;
     BOOL bUnkOuterValid;
     BOOL bAggregatable;
@@ -194,8 +193,6 @@
     pNullRenderer->pClock = NULL;
     ZeroMemory(&pNullRenderer->filterInfo, sizeof(FILTER_INFO));
 
-    pNullRenderer->ppPins = CoTaskMemAlloc(1 * sizeof(IPin *));
-
     /* construct input pin */
     piInput.dir = PINDIR_INPUT;
     piInput.pFilter = (IBaseFilter *)pNullRenderer;
@@ -205,7 +202,6 @@
 
     if (SUCCEEDED(hr))
     {
-        pNullRenderer->ppPins[0] = (IPin *)pNullRenderer->pInputPin;
         MediaSeekingImpl_Init((IBaseFilter*)pNullRenderer, NullRendererImpl_Change, NullRendererImpl_Change, NullRendererImpl_Change, &pNullRenderer->mediaSeeking, &pNullRenderer->csFilter);
         pNullRenderer->mediaSeeking.lpVtbl = &TransformFilter_Seeking_Vtbl;
 
@@ -213,7 +209,6 @@
     }
     else
     {
-        CoTaskMemFree(pNullRenderer->ppPins);
         pNullRenderer->csFilter.DebugInfo->Spare[0] = 0;
         DeleteCriticalSection(&pNullRenderer->csFilter);
         CoTaskMemFree(pNullRenderer);
@@ -279,15 +274,15 @@
         if (This->pClock)
             IReferenceClock_Release(This->pClock);
 
-        if (SUCCEEDED(IPin_ConnectedTo(This->ppPins[0], &pConnectedTo)))
+        if (SUCCEEDED(IPin_ConnectedTo((IPin *)This->pInputPin, &pConnectedTo)))
         {
             IPin_Disconnect(pConnectedTo);
             IPin_Release(pConnectedTo);
         }
-        IPin_Disconnect(This->ppPins[0]);
-        IPin_Release(This->ppPins[0]);
+        IPin_Disconnect((IPin *)This->pInputPin);
+        IPin_Release((IPin *)This->pInputPin);
 
-        CoTaskMemFree(This->ppPins);
+        CoTaskMemFree((IPin *)This->pInputPin);
         This->lpVtbl = NULL;
 
         This->csFilter.DebugInfo->Spare[0] = 0;
@@ -473,16 +468,28 @@
 
 /** IBaseFilter implementation **/
 
+static HRESULT NullRenderer_GetPin(IBaseFilter *iface, ULONG pos, IPin **pin, DWORD *lastsynctick)
+{
+    NullRendererImpl *This = (NullRendererImpl *)iface;
+
+    /* Our pins are static, not changing so setting static tick count is ok */
+    *lastsynctick = 0;
+
+    if (pos >= 1)
+        return S_FALSE;
+
+    *pin = (IPin *)This->pInputPin;
+    IPin_AddRef(*pin);
+    return S_OK;
+}
+
 static HRESULT WINAPI NullRenderer_EnumPins(IBaseFilter * iface, IEnumPins **ppEnum)
 {
-    ENUMPINDETAILS epd;
     NullRendererImpl *This = (NullRendererImpl *)iface;
 
     TRACE("(%p/%p)->(%p)\n", This, iface, ppEnum);
 
-    epd.cPins = 1; /* input pin */
-    epd.ppPins = This->ppPins;
-    return IEnumPinsImpl_Construct(&epd, ppEnum);
+    return IEnumPinsImpl_Construct(ppEnum, NullRenderer_GetPin, iface);
 }
 
 static HRESULT WINAPI NullRenderer_FindPin(IBaseFilter * iface, LPCWSTR Id, IPin **ppPin)
diff --git a/dlls/quartz/parser.c b/dlls/quartz/parser.c
index 23eb9f2..7a7f9ba 100644
--- a/dlls/quartz/parser.c
+++ b/dlls/quartz/parser.c
@@ -68,6 +68,7 @@
     pParser->fnDisconnect = fnDisconnect;
     ZeroMemory(&pParser->filterInfo, sizeof(FILTER_INFO));
 
+    pParser->lastpinchange = GetTickCount();
     pParser->cStreams = 0;
     pParser->ppPins = CoTaskMemAlloc(1 * sizeof(IPin *));
 
@@ -377,16 +378,30 @@
 
 /** IBaseFilter implementation **/
 
-HRESULT WINAPI Parser_EnumPins(IBaseFilter * iface, IEnumPins **ppEnum)
+static HRESULT Parser_GetPin(IBaseFilter *iface, ULONG pos, IPin **pin, DWORD *lastsynctick)
 {
-    ENUMPINDETAILS epd;
     ParserImpl *This = (ParserImpl *)iface;
 
-    TRACE("(%p)\n", ppEnum);
+    *lastsynctick = This->lastpinchange;
 
-    epd.cPins = This->cStreams + 1; /* +1 for input pin */
-    epd.ppPins = This->ppPins;
-    return IEnumPinsImpl_Construct(&epd, ppEnum);
+    TRACE("Asking for pos %x\n", pos);
+
+    /* Input pin also has a pin, hence the > and not >= */
+    if (pos > This->cStreams)
+        return S_FALSE;
+
+    *pin = This->ppPins[pos];
+    IPin_AddRef(*pin);
+    return S_OK;
+}
+
+HRESULT WINAPI Parser_EnumPins(IBaseFilter * iface, IEnumPins **ppEnum)
+{
+    ParserImpl *This = (ParserImpl *)iface;
+
+    TRACE("(%p/%p)->(%p)\n", This, iface, ppEnum);
+
+    return IEnumPinsImpl_Construct(ppEnum, Parser_GetPin, iface);
 }
 
 HRESULT WINAPI Parser_FindPin(IBaseFilter * iface, LPCWSTR Id, IPin **ppPin)
@@ -463,6 +478,7 @@
         pin->pin.pin.pinInfo.pFilter = (LPVOID)This;
         pin->pin.custom_allocator = 1;
         This->cStreams++;
+        This->lastpinchange = GetTickCount();
         CoTaskMemFree(ppOldPins);
     }
     else
@@ -493,6 +509,7 @@
     }
 
     This->cStreams = 0;
+    This->lastpinchange = GetTickCount();
     CoTaskMemFree(ppOldPins);
 
     return S_OK;
diff --git a/dlls/quartz/parser.h b/dlls/quartz/parser.h
index 5e056d5..6fda5e3 100644
--- a/dlls/quartz/parser.h
+++ b/dlls/quartz/parser.h
@@ -43,6 +43,7 @@
     PullPin * pInputPin;
     IPin ** ppPins;
     ULONG cStreams;
+    DWORD lastpinchange;
     MediaSeekingImpl mediaSeeking;
 };
 
diff --git a/dlls/quartz/quartz_private.h b/dlls/quartz/quartz_private.h
index 9f92ad6..9eb1630 100644
--- a/dlls/quartz/quartz_private.h
+++ b/dlls/quartz/quartz_private.h
@@ -61,19 +61,15 @@
 
 HRESULT EnumMonikerImpl_Create(IMoniker ** ppMoniker, ULONG nMonikerCount, IEnumMoniker ** ppEnum);
 
-typedef struct tagENUMPINDETAILS
-{
-	ULONG cPins;
-	IPin ** ppPins;
-} ENUMPINDETAILS;
-
 typedef struct tagENUMEDIADETAILS
 {
 	ULONG cMediaTypes;
 	AM_MEDIA_TYPE * pMediaTypes;
 } ENUMMEDIADETAILS;
 
-HRESULT IEnumPinsImpl_Construct(const ENUMPINDETAILS * pDetails, IEnumPins ** ppEnum);
+typedef HRESULT (* FNOBTAINPIN)(IBaseFilter *iface, ULONG pos, IPin **pin, DWORD *lastsynctick);
+
+HRESULT IEnumPinsImpl_Construct(IEnumPins ** ppEnum, FNOBTAINPIN receive_pin, IBaseFilter *base);
 HRESULT IEnumMediaTypesImpl_Construct(const ENUMMEDIADETAILS * pDetails, IEnumMediaTypes ** ppEnum);
 HRESULT IEnumRegFiltersImpl_Construct(REGFILTER * pInRegFilters, const ULONG size, IEnumRegFilters ** ppEnum);
 HRESULT IEnumFiltersImpl_Construct(IBaseFilter ** ppFilters, ULONG nFilters, IEnumFilters ** ppEnum);
diff --git a/dlls/quartz/transform.c b/dlls/quartz/transform.c
index 2596f63..7f50268 100644
--- a/dlls/quartz/transform.c
+++ b/dlls/quartz/transform.c
@@ -434,16 +434,28 @@
 
 /** IBaseFilter implementation **/
 
+static HRESULT TransformFilter_GetPin(IBaseFilter *iface, ULONG pos, IPin **pin, DWORD *lastsynctick)
+{
+    TransformFilterImpl *This = (TransformFilterImpl *)iface;
+
+    /* Our pins are static, not changing so setting static tick count is ok */
+    *lastsynctick = 0;
+
+    if (pos >= 2)
+        return S_FALSE;
+
+    *pin = This->ppPins[pos];
+    IPin_AddRef(*pin);
+    return S_OK;
+}
+
 static HRESULT WINAPI TransformFilter_EnumPins(IBaseFilter * iface, IEnumPins **ppEnum)
 {
-    ENUMPINDETAILS epd;
     TransformFilterImpl *This = (TransformFilterImpl *)iface;
 
     TRACE("(%p/%p)->(%p)\n", This, iface, ppEnum);
 
-    epd.cPins = 2; /* input and output pins */
-    epd.ppPins = This->ppPins;
-    return IEnumPinsImpl_Construct(&epd, ppEnum);
+    return IEnumPinsImpl_Construct(ppEnum, TransformFilter_GetPin, iface);
 }
 
 static HRESULT WINAPI TransformFilter_FindPin(IBaseFilter * iface, LPCWSTR Id, IPin **ppPin)
diff --git a/dlls/quartz/videorenderer.c b/dlls/quartz/videorenderer.c
index 97bb825..f009eda 100644
--- a/dlls/quartz/videorenderer.c
+++ b/dlls/quartz/videorenderer.c
@@ -67,8 +67,7 @@
     IReferenceClock * pClock;
     FILTER_INFO filterInfo;
 
-    InputPin * pInputPin;
-    IPin ** ppPins;
+    InputPin *pInputPin;
 
     BOOL init;
     HANDLE hThread;
@@ -267,12 +266,17 @@
 {
     AM_MEDIA_TYPE amt;
     HRESULT hr = S_OK;
+    DDSURFACEDESC sdesc;
+    int width;
+    int height;
+    LPBYTE palette = NULL;
     HDC hDC;
     BITMAPINFOHEADER *bmiHeader;
 
     TRACE("%p %p %d\n", This, data, size);
 
-    hr = IPin_ConnectionMediaType(This->ppPins[0], &amt);
+    sdesc.dwSize = sizeof(sdesc);
+    hr = IPin_ConnectionMediaType((IPin *)This->pInputPin, &amt);
     if (FAILED(hr)) {
         ERR("Unable to retrieve media type\n");
         return hr;
@@ -301,6 +305,10 @@
     TRACE("biCompression = %s\n", debugstr_an((LPSTR)&(bmiHeader->biCompression), 4));
     TRACE("biSizeImage = %d\n", bmiHeader->biSizeImage);
 
+    width = bmiHeader->biWidth;
+    height = bmiHeader->biHeight;
+    palette = ((LPBYTE)bmiHeader) + bmiHeader->biSize;
+
     if (!This->init)
     {
         if (!This->WindowPos.right || !This->WindowPos.bottom)
@@ -384,7 +392,7 @@
         TRACE("\n");
     }
 #endif
-    
+
     VideoRenderer_SendSampleData(This, pbSrcStream, cbSrcStream);
 
     return S_OK;
@@ -458,8 +466,6 @@
     pVideoRenderer->AutoShow = 1;
     ZeroMemory(&pVideoRenderer->filterInfo, sizeof(FILTER_INFO));
 
-    pVideoRenderer->ppPins = CoTaskMemAlloc(1 * sizeof(IPin *));
-
     /* construct input pin */
     piInput.dir = PINDIR_INPUT;
     piInput.pFilter = (IBaseFilter *)pVideoRenderer;
@@ -469,12 +475,10 @@
 
     if (SUCCEEDED(hr))
     {
-        pVideoRenderer->ppPins[0] = (IPin *)pVideoRenderer->pInputPin;
         *ppv = (LPVOID)pVideoRenderer;
     }
     else
     {
-        CoTaskMemFree(pVideoRenderer->ppPins);
         pVideoRenderer->csFilter.DebugInfo->Spare[0] = 0;
         DeleteCriticalSection(&pVideoRenderer->csFilter);
         CoTaskMemFree(pVideoRenderer);
@@ -556,16 +560,15 @@
         if (This->pClock)
             IReferenceClock_Release(This->pClock);
         
-        if (SUCCEEDED(IPin_ConnectedTo(This->ppPins[0], &pConnectedTo)))
+        if (SUCCEEDED(IPin_ConnectedTo((IPin *)This->pInputPin, &pConnectedTo)))
         {
             IPin_Disconnect(pConnectedTo);
             IPin_Release(pConnectedTo);
         }
-        IPin_Disconnect(This->ppPins[0]);
+        IPin_Disconnect((IPin *)This->pInputPin);
 
-        IPin_Release(This->ppPins[0]);
-        
-        CoTaskMemFree(This->ppPins);
+        IPin_Release((IPin *)This->pInputPin);
+
         This->lpVtbl = NULL;
         
         This->csFilter.DebugInfo->Spare[0] = 0;
@@ -690,6 +693,7 @@
     TRACE("(%p/%p)->(%s)\n", This, iface, wine_dbgstr_longlong(tStart));
 
     EnterCriticalSection(&This->csFilter);
+    if (This->state != State_Running)
     {
         if (This->state == State_Stopped)
             This->pInputPin->end_of_stream = 0;
@@ -755,16 +759,28 @@
 
 /** IBaseFilter implementation **/
 
+static HRESULT VideoRenderer_GetPin(IBaseFilter *iface, ULONG pos, IPin **pin, DWORD *lastsynctick)
+{
+    VideoRendererImpl *This = (VideoRendererImpl *)iface;
+
+    /* Our pins are static, not changing so setting static tick count is ok */
+    *lastsynctick = 0;
+
+    if (pos >= 1)
+        return S_FALSE;
+
+    *pin = (IPin *)This->pInputPin;
+    IPin_AddRef(*pin);
+    return S_OK;
+}
+
 static HRESULT WINAPI VideoRenderer_EnumPins(IBaseFilter * iface, IEnumPins **ppEnum)
 {
-    ENUMPINDETAILS epd;
     VideoRendererImpl *This = (VideoRendererImpl *)iface;
 
     TRACE("(%p/%p)->(%p)\n", This, iface, ppEnum);
 
-    epd.cPins = 1; /* input pin */
-    epd.ppPins = This->ppPins;
-    return IEnumPinsImpl_Construct(&epd, ppEnum);
+    return IEnumPinsImpl_Construct(ppEnum, VideoRenderer_GetPin, iface);
 }
 
 static HRESULT WINAPI VideoRenderer_FindPin(IBaseFilter * iface, LPCWSTR Id, IPin **ppPin)
@@ -1804,7 +1820,7 @@
     if ((Focus != FALSE) && (Focus != TRUE))
         return E_INVALIDARG;
 
-    hr = IPin_ConnectedTo(This->ppPins[0], &pPin);
+    hr = IPin_ConnectedTo((IPin *)This->pInputPin, &pPin);
     if ((hr != S_OK) || !pPin)
         return VFW_E_NOT_CONNECTED;