strmbase: Add the EnumMediaTypes base implementation.
diff --git a/dlls/qcap/enummedia.c b/dlls/qcap/enummedia.c
index 94b2907..b291a9e 100644
--- a/dlls/qcap/enummedia.c
+++ b/dlls/qcap/enummedia.c
@@ -32,7 +32,6 @@
 #include "qcap_main.h"
 
 #include "wine/debug.h"
-#include "wine/strmbase.h"
 
 WINE_DEFAULT_DEBUG_CHANNEL(qcap);
 
@@ -58,183 +57,3 @@
     TRACE("\t%s\n\t%s\n\t...\n\t%s\n", debugstr_guid(&pmt->majortype),
           debugstr_guid(&pmt->subtype), debugstr_guid(&pmt->formattype));
 }
-
-typedef struct IEnumMediaTypesImpl
-{
-    const IEnumMediaTypesVtbl * lpVtbl;
-    LONG refCount;
-    ENUMMEDIADETAILS enumMediaDetails;
-    ULONG uIndex;
-} IEnumMediaTypesImpl;
-
-static const struct IEnumMediaTypesVtbl IEnumMediaTypesImpl_Vtbl;
-
-HRESULT IEnumMediaTypesImpl_Construct(const ENUMMEDIADETAILS * pDetails,
-                                      IEnumMediaTypes ** ppEnum)
-{
-    ULONG i;
-    IEnumMediaTypesImpl * pEnumMediaTypes = CoTaskMemAlloc(sizeof(IEnumMediaTypesImpl));
-
-    if (!pEnumMediaTypes)
-    {
-        *ppEnum = NULL;
-        return E_OUTOFMEMORY;
-    }
-    ObjectRefCount(TRUE);
-    pEnumMediaTypes->lpVtbl = &IEnumMediaTypesImpl_Vtbl;
-    pEnumMediaTypes->refCount = 1;
-    pEnumMediaTypes->uIndex = 0;
-    pEnumMediaTypes->enumMediaDetails.cMediaTypes = pDetails->cMediaTypes;
-    pEnumMediaTypes->enumMediaDetails.pMediaTypes =
-                      CoTaskMemAlloc(sizeof(AM_MEDIA_TYPE) * pDetails->cMediaTypes);
-    for (i = 0; i < pDetails->cMediaTypes; i++)
-        if (FAILED(CopyMediaType(&pEnumMediaTypes->enumMediaDetails.pMediaTypes[i], &pDetails->pMediaTypes[i]))) {
-           while (i--) CoTaskMemFree(pEnumMediaTypes->enumMediaDetails.pMediaTypes[i].pbFormat);
-           CoTaskMemFree(pEnumMediaTypes->enumMediaDetails.pMediaTypes);
-           return E_OUTOFMEMORY;
-        }
-    *ppEnum = (IEnumMediaTypes *)(&pEnumMediaTypes->lpVtbl);
-    return S_OK;
-}
-
-static HRESULT WINAPI IEnumMediaTypesImpl_QueryInterface(IEnumMediaTypes * iface,
-                                                         REFIID riid,
-                                                         LPVOID * ppv)
-{
-    TRACE("(%s, %p)\n", debugstr_guid(riid), ppv);
-
-    *ppv = NULL;
-
-    if (IsEqualIID(riid, &IID_IUnknown))
-        *ppv = iface;
-    else if (IsEqualIID(riid, &IID_IEnumMediaTypes))
-        *ppv = iface;
-
-    if (*ppv)
-    {
-        IUnknown_AddRef((IUnknown *)(*ppv));
-        return S_OK;
-    }
-
-    FIXME("No interface for %s!\n", debugstr_guid(riid));
-
-    return E_NOINTERFACE;
-}
-
-static ULONG WINAPI IEnumMediaTypesImpl_AddRef(IEnumMediaTypes * iface)
-{
-    IEnumMediaTypesImpl *This = (IEnumMediaTypesImpl *)iface;
-    ULONG refCount = InterlockedIncrement(&This->refCount);
-
-    TRACE("()\n");
-
-    return refCount;
-}
-
-static ULONG WINAPI IEnumMediaTypesImpl_Release(IEnumMediaTypes * iface)
-{
-    IEnumMediaTypesImpl *This = (IEnumMediaTypesImpl *)iface;
-    ULONG refCount = InterlockedDecrement(&This->refCount);
-
-    TRACE("()\n");
-
-    if (!refCount)
-    {
-        ULONG 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);
-        ObjectRefCount(FALSE);
-    }
-    return refCount;
-}
-
-static HRESULT WINAPI IEnumMediaTypesImpl_Next(IEnumMediaTypes * iface,
-                                               ULONG cMediaTypes,
-                                               AM_MEDIA_TYPE ** ppMediaTypes,
-                                               ULONG * pcFetched)
-{
-    ULONG cFetched;
-    IEnumMediaTypesImpl *This = (IEnumMediaTypesImpl *)iface;
-
-    cFetched = min(This->enumMediaDetails.cMediaTypes,
-                   This->uIndex + cMediaTypes) - This->uIndex;
-
-    TRACE("(%u, %p, %p)\n", cMediaTypes, ppMediaTypes, pcFetched);
-    TRACE("Next uIndex: %u, cFetched: %u\n", This->uIndex, cFetched);
-
-    if (cFetched > 0)
-    {
-        ULONG i;
-        *ppMediaTypes = CoTaskMemAlloc(sizeof(AM_MEDIA_TYPE) * cFetched);
-        for (i = 0; i < cFetched; 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)
-        *pcFetched = cFetched;
-
-    This->uIndex += cFetched;
-
-    if (cFetched != cMediaTypes)
-        return S_FALSE;
-    return S_OK;
-}
-
-static HRESULT WINAPI IEnumMediaTypesImpl_Skip(IEnumMediaTypes * iface,
-                                               ULONG cMediaTypes)
-{
-    IEnumMediaTypesImpl *This = (IEnumMediaTypesImpl *)iface;
-
-    TRACE("(%u)\n", cMediaTypes);
-
-    if (This->uIndex + cMediaTypes < This->enumMediaDetails.cMediaTypes)
-    {
-        This->uIndex += cMediaTypes;
-        return S_OK;
-    }
-    return S_FALSE;
-}
-
-static HRESULT WINAPI IEnumMediaTypesImpl_Reset(IEnumMediaTypes * iface)
-{
-    IEnumMediaTypesImpl *This = (IEnumMediaTypesImpl *)iface;
-
-    TRACE("()\n");
-
-    This->uIndex = 0;
-    return S_OK;
-}
-
-static HRESULT WINAPI IEnumMediaTypesImpl_Clone(IEnumMediaTypes * iface,
-                                                IEnumMediaTypes ** ppEnum)
-{
-    HRESULT hr;
-    IEnumMediaTypesImpl *This = (IEnumMediaTypesImpl *)iface;
-
-    TRACE("(%p)\n", ppEnum);
-
-    hr = IEnumMediaTypesImpl_Construct(&This->enumMediaDetails, ppEnum);
-    if (FAILED(hr))
-        return hr;
-    return IEnumMediaTypes_Skip(*ppEnum, This->uIndex);
-}
-
-static const IEnumMediaTypesVtbl IEnumMediaTypesImpl_Vtbl =
-{
-    IEnumMediaTypesImpl_QueryInterface,
-    IEnumMediaTypesImpl_AddRef,
-    IEnumMediaTypesImpl_Release,
-    IEnumMediaTypesImpl_Next,
-    IEnumMediaTypesImpl_Skip,
-    IEnumMediaTypesImpl_Reset,
-    IEnumMediaTypesImpl_Clone
-};
diff --git a/dlls/qcap/pin.h b/dlls/qcap/pin.h
index 68d3e28..e738b58 100644
--- a/dlls/qcap/pin.h
+++ b/dlls/qcap/pin.h
@@ -43,7 +43,6 @@
 	PIN_INFO pinInfo;
 	IPin * pConnectedTo;
 	AM_MEDIA_TYPE mtCurrent;
-	ENUMMEDIADETAILS enumMediaDetails;
 	QUERYACCEPTPROC fnQueryAccept;
 	LPVOID pUserData;
 } IPinImpl;
diff --git a/dlls/qcap/qcap_main.h b/dlls/qcap/qcap_main.h
index 59a172f..535b7ff 100644
--- a/dlls/qcap/qcap_main.h
+++ b/dlls/qcap/qcap_main.h
@@ -43,14 +43,7 @@
        IPin ** ppPins;
 } ENUMPINDETAILS;
 
-typedef struct tagENUMEDIADETAILS
-{
-       ULONG cMediaTypes;
-       AM_MEDIA_TYPE * pMediaTypes;
-} ENUMMEDIADETAILS;
-
 HRESULT IEnumPinsImpl_Construct(const ENUMPINDETAILS * pDetails, IEnumPins ** ppEnum);
-HRESULT IEnumMediaTypesImpl_Construct(const ENUMMEDIADETAILS * pDetails, IEnumMediaTypes ** ppEnum);
 
 BOOL CompareMediaTypes(const AM_MEDIA_TYPE * pmt1, const AM_MEDIA_TYPE * pmt2, BOOL bWildcards); 
 void dump_AM_MEDIA_TYPE(const AM_MEDIA_TYPE * pmt);
diff --git a/dlls/qcap/vfwcapture.c b/dlls/qcap/vfwcapture.c
index d851836..c4e5c54 100644
--- a/dlls/qcap/vfwcapture.c
+++ b/dlls/qcap/vfwcapture.c
@@ -741,6 +741,29 @@
    KSP_QuerySupported
 };
 
+static HRESULT WINAPI VfwPin_GetMediaType(IPin *iface, int iPosition, AM_MEDIA_TYPE *pmt)
+{
+    VfwPinImpl *This = (VfwPinImpl *)iface;
+    AM_MEDIA_TYPE *vfw_pmt;
+    HRESULT hr;
+
+    if (iPosition < 0)
+        return E_INVALIDARG;
+    if (iPosition > 0)
+        return VFW_S_NO_MORE_ITEMS;
+
+    hr = qcap_driver_get_format(This->driver_info, &vfw_pmt);
+    CopyMediaType(pmt, vfw_pmt);
+    DeleteMediaType(vfw_pmt);
+
+    return hr;
+}
+
+LONG WINAPI VfwPin_GetMediaTypeVersion(IPin *iface)
+{
+    return 1;
+}
+
 static HRESULT
 VfwPin_Construct( IBaseFilter * pBaseFilter, LPCRITICAL_SECTION pCritSec,
                   IPin ** ppPin )
@@ -833,18 +856,16 @@
 static HRESULT WINAPI
 VfwPin_EnumMediaTypes(IPin * iface, IEnumMediaTypes ** ppEnum)
 {
-    ENUMMEDIADETAILS emd;
     AM_MEDIA_TYPE *pmt;
     HRESULT hr;
 
     VfwPinImpl *This = (VfwPinImpl *)iface;
-    emd.cMediaTypes = 1;
     hr = qcap_driver_get_format(This->driver_info, &pmt);
-    emd.pMediaTypes = pmt;
     if (SUCCEEDED(hr))
-        hr = IEnumMediaTypesImpl_Construct(&emd, ppEnum);
+        hr = EnumMediaTypes_Construct(iface, VfwPin_GetMediaType, VfwPin_GetMediaTypeVersion, ppEnum);
     TRACE("%p -- %x\n", This, hr);
     DeleteMediaType(pmt);
+
     return hr;
 }
 
diff --git a/dlls/quartz/enummedia.c b/dlls/quartz/enummedia.c
index db78965..8c564b6 100644
--- a/dlls/quartz/enummedia.c
+++ b/dlls/quartz/enummedia.c
@@ -40,172 +40,3 @@
         return;
     TRACE("\t%s\n\t%s\n\t...\n\t%s\n", qzdebugstr_guid(&pmt->majortype), qzdebugstr_guid(&pmt->subtype), qzdebugstr_guid(&pmt->formattype));
 }
-
-typedef struct IEnumMediaTypesImpl
-{
-    const IEnumMediaTypesVtbl * lpVtbl;
-    LONG refCount;
-    ENUMMEDIADETAILS enumMediaDetails;
-    ULONG uIndex;
-} IEnumMediaTypesImpl;
-
-static const struct IEnumMediaTypesVtbl IEnumMediaTypesImpl_Vtbl;
-
-HRESULT IEnumMediaTypesImpl_Construct(const ENUMMEDIADETAILS * pDetails, IEnumMediaTypes ** ppEnum)
-{
-    ULONG i;
-    IEnumMediaTypesImpl * pEnumMediaTypes = CoTaskMemAlloc(sizeof(IEnumMediaTypesImpl));
-
-    if (!pEnumMediaTypes)
-    {
-        *ppEnum = NULL;
-        return E_OUTOFMEMORY;
-    }
-    pEnumMediaTypes->lpVtbl = &IEnumMediaTypesImpl_Vtbl;
-    pEnumMediaTypes->refCount = 1;
-    pEnumMediaTypes->uIndex = 0;
-    pEnumMediaTypes->enumMediaDetails.cMediaTypes = pDetails->cMediaTypes;
-    pEnumMediaTypes->enumMediaDetails.pMediaTypes = CoTaskMemAlloc(sizeof(AM_MEDIA_TYPE) * pDetails->cMediaTypes);
-    for (i = 0; i < pDetails->cMediaTypes; i++)
-        if (FAILED(CopyMediaType(&pEnumMediaTypes->enumMediaDetails.pMediaTypes[i], &pDetails->pMediaTypes[i])))
-        {
-           while (i--)
-              CoTaskMemFree(pEnumMediaTypes->enumMediaDetails.pMediaTypes[i].pbFormat);
-           CoTaskMemFree(pEnumMediaTypes->enumMediaDetails.pMediaTypes);
-           return E_OUTOFMEMORY;
-        }
-    *ppEnum = (IEnumMediaTypes *)(&pEnumMediaTypes->lpVtbl);
-    return S_OK;
-}
-
-static HRESULT WINAPI IEnumMediaTypesImpl_QueryInterface(IEnumMediaTypes * iface, REFIID riid, LPVOID * ppv)
-{
-    TRACE("(%s, %p)\n", qzdebugstr_guid(riid), ppv);
-
-    *ppv = NULL;
-
-    if (IsEqualIID(riid, &IID_IUnknown))
-        *ppv = iface;
-    else if (IsEqualIID(riid, &IID_IEnumMediaTypes))
-        *ppv = iface;
-
-    if (*ppv)
-    {
-        IUnknown_AddRef((IUnknown *)(*ppv));
-        return S_OK;
-    }
-
-    FIXME("No interface for %s!\n", qzdebugstr_guid(riid));
-
-    return E_NOINTERFACE;
-}
-
-static ULONG WINAPI IEnumMediaTypesImpl_AddRef(IEnumMediaTypes * iface)
-{
-    IEnumMediaTypesImpl *This = (IEnumMediaTypesImpl *)iface;
-    ULONG refCount = InterlockedIncrement(&This->refCount);
-
-    TRACE("(%p)->() AddRef from %d\n", iface, refCount - 1);
-
-    return refCount;
-}
-
-static ULONG WINAPI IEnumMediaTypesImpl_Release(IEnumMediaTypes * iface)
-{
-    IEnumMediaTypesImpl *This = (IEnumMediaTypesImpl *)iface;
-    ULONG refCount = InterlockedDecrement(&This->refCount);
-
-    TRACE("(%p)->() Release from %d\n", iface, refCount + 1);
-
-    if (!refCount)
-    {
-        ULONG 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 refCount;
-}
-
-static HRESULT WINAPI IEnumMediaTypesImpl_Next(IEnumMediaTypes * iface, ULONG cMediaTypes, AM_MEDIA_TYPE ** ppMediaTypes, ULONG * pcFetched)
-{
-    ULONG cFetched; 
-    IEnumMediaTypesImpl *This = (IEnumMediaTypesImpl *)iface;
-
-    cFetched = min(This->enumMediaDetails.cMediaTypes, This->uIndex + cMediaTypes) - This->uIndex;
-
-    TRACE("(%u, %p, %p)\n", cMediaTypes, ppMediaTypes, pcFetched);
-    TRACE("Next uIndex: %u, cFetched: %u\n", This->uIndex, cFetched);
-
-    if (cFetched > 0)
-    {
-        ULONG i;
-        for (i = 0; i < cFetched; i++)
-            if (!(ppMediaTypes[i] = CreateMediaType(&This->enumMediaDetails.pMediaTypes[This->uIndex + i])))
-            {
-                while (i--)
-                    DeleteMediaType(ppMediaTypes[i]);
-                *pcFetched = 0;
-                return E_OUTOFMEMORY;
-            }
-    }
-
-    if ((cMediaTypes != 1) || pcFetched)
-        *pcFetched = cFetched;
-
-    This->uIndex += cFetched;
-
-    if (cFetched != cMediaTypes)
-        return S_FALSE;
-    return S_OK;
-}
-
-static HRESULT WINAPI IEnumMediaTypesImpl_Skip(IEnumMediaTypes * iface, ULONG cMediaTypes)
-{
-    IEnumMediaTypesImpl *This = (IEnumMediaTypesImpl *)iface;
-
-    TRACE("(%u)\n", cMediaTypes);
-
-    if (This->uIndex + cMediaTypes < This->enumMediaDetails.cMediaTypes)
-    {
-        This->uIndex += cMediaTypes;
-        return S_OK;
-    }
-    return S_FALSE;
-}
-
-static HRESULT WINAPI IEnumMediaTypesImpl_Reset(IEnumMediaTypes * iface)
-{
-    IEnumMediaTypesImpl *This = (IEnumMediaTypesImpl *)iface;
-
-    TRACE("()\n");
-
-    This->uIndex = 0;
-    return S_OK;
-}
-
-static HRESULT WINAPI IEnumMediaTypesImpl_Clone(IEnumMediaTypes * iface, IEnumMediaTypes ** ppEnum)
-{
-    HRESULT hr;
-    IEnumMediaTypesImpl *This = (IEnumMediaTypesImpl *)iface;
-
-    TRACE("(%p)\n", ppEnum);
-
-    hr = IEnumMediaTypesImpl_Construct(&This->enumMediaDetails, ppEnum);
-    if (FAILED(hr))
-        return hr;
-    return IEnumMediaTypes_Skip(*ppEnum, This->uIndex);
-}
-
-static const IEnumMediaTypesVtbl IEnumMediaTypesImpl_Vtbl =
-{
-    IEnumMediaTypesImpl_QueryInterface,
-    IEnumMediaTypesImpl_AddRef,
-    IEnumMediaTypesImpl_Release,
-    IEnumMediaTypesImpl_Next,
-    IEnumMediaTypesImpl_Skip,
-    IEnumMediaTypesImpl_Reset,
-    IEnumMediaTypesImpl_Clone
-};
diff --git a/dlls/quartz/filesource.c b/dlls/quartz/filesource.c
index 110415d..3430cb3 100644
--- a/dlls/quartz/filesource.c
+++ b/dlls/quartz/filesource.c
@@ -794,6 +794,17 @@
     return S_FALSE;
 }
 
+static HRESULT WINAPI FileAsyncReaderPin_GetMediaType(IPin *iface, int iPosition, AM_MEDIA_TYPE *pmt)
+{
+    FileAsyncReader *This = (FileAsyncReader *)iface;
+    if (iPosition < 0)
+        return E_INVALIDARG;
+    if (iPosition > 0)
+        return VFW_S_NO_MORE_ITEMS;
+    CopyMediaType(pmt, ((AsyncReader *)This->pin.pin.pinInfo.pFilter)->pmt);
+    return S_OK;
+}
+
 /* overridden pin functions */
 
 static HRESULT WINAPI FileAsyncReaderPin_QueryInterface(IPin * iface, REFIID riid, LPVOID * ppv)
@@ -850,15 +861,9 @@
 
 static HRESULT WINAPI FileAsyncReaderPin_EnumMediaTypes(IPin * iface, IEnumMediaTypes ** ppEnum)
 {
-    ENUMMEDIADETAILS emd;
-    FileAsyncReader *This = (FileAsyncReader *)iface;
-
     TRACE("(%p)\n", ppEnum);
 
-    emd.cMediaTypes = 1;
-    emd.pMediaTypes = ((AsyncReader *)This->pin.pin.pinInfo.pFilter)->pmt;
-
-    return IEnumMediaTypesImpl_Construct(&emd, ppEnum);
+    return EnumMediaTypes_Construct(iface, FileAsyncReaderPin_GetMediaType, BasePinImpl_GetMediaTypeVersion, ppEnum);
 }
 
 static const IPinVtbl FileAsyncReaderPin_Vtbl = 
diff --git a/dlls/quartz/parser.c b/dlls/quartz/parser.c
index f95d3e7..979a18c 100644
--- a/dlls/quartz/parser.c
+++ b/dlls/quartz/parser.c
@@ -599,6 +599,17 @@
     MediaSeekingImpl_GetPreroll
 };
 
+static HRESULT WINAPI Parser_OutputPin_GetMediaType(IPin *iface, int iPosition, AM_MEDIA_TYPE *pmt)
+{
+    Parser_OutputPin *This = (Parser_OutputPin *)iface;
+    if (iPosition < 0)
+        return E_INVALIDARG;
+    if (iPosition > 0)
+        return VFW_S_NO_MORE_ITEMS;
+    CopyMediaType(pmt, This->pmt);
+    return S_OK;
+}
+
 static HRESULT WINAPI Parser_OutputPin_QueryInterface(IPin * iface, REFIID riid, LPVOID * ppv)
 {
     Parser_OutputPin *This = (Parser_OutputPin *)iface;
@@ -647,16 +658,11 @@
 
 static HRESULT WINAPI Parser_OutputPin_EnumMediaTypes(IPin * iface, IEnumMediaTypes ** ppEnum)
 {
-    ENUMMEDIADETAILS emd;
-    Parser_OutputPin *This = (Parser_OutputPin *)iface;
-
     TRACE("(%p)\n", ppEnum);
 
     /* override this method to allow enumeration of your types */
-    emd.cMediaTypes = 1;
-    emd.pMediaTypes = This->pmt;
 
-    return IEnumMediaTypesImpl_Construct(&emd, ppEnum);
+    return EnumMediaTypes_Construct(iface, Parser_OutputPin_GetMediaType, BasePinImpl_GetMediaTypeVersion, ppEnum);
 }
 
 static HRESULT WINAPI Parser_OutputPin_Connect(IPin * iface, IPin * pReceivePin, const AM_MEDIA_TYPE * pmt)
diff --git a/dlls/quartz/pin.c b/dlls/quartz/pin.c
index fd0d5a2..25dff17 100644
--- a/dlls/quartz/pin.c
+++ b/dlls/quartz/pin.c
@@ -154,6 +154,19 @@
     pDest->pFilter = pSrc->pFilter;
 }
 
+/*** Common Base Pin function */
+HRESULT WINAPI BasePinImpl_GetMediaType(IPin *iface, int iPosition, AM_MEDIA_TYPE *pmt)
+{
+    if (iPosition < 0)
+        return E_INVALIDARG;
+    return VFW_S_NO_MORE_ITEMS;
+}
+
+LONG WINAPI BasePinImpl_GetMediaTypeVersion(IPin *iface)
+{
+    return 1;
+}
+
 /*** Common pin functions ***/
 
 ULONG WINAPI IPinImpl_AddRef(IPin * iface)
@@ -292,15 +305,12 @@
 HRESULT WINAPI IPinImpl_EnumMediaTypes(IPin * iface, IEnumMediaTypes ** ppEnum)
 {
     IPinImpl *This = (IPinImpl *)iface;
-    ENUMMEDIADETAILS emd;
 
     TRACE("(%p/%p)->(%p)\n", This, iface, ppEnum);
 
     /* override this method to allow enumeration of your types */
-    emd.cMediaTypes = 0;
-    emd.pMediaTypes = NULL;
 
-    return IEnumMediaTypesImpl_Construct(&emd, ppEnum);
+    return EnumMediaTypes_Construct(iface, BasePinImpl_GetMediaType, BasePinImpl_GetMediaTypeVersion , ppEnum);
 }
 
 HRESULT WINAPI IPinImpl_QueryInternalConnections(IPin * iface, IPin ** apPin, ULONG * cPin)
diff --git a/dlls/quartz/pin.h b/dlls/quartz/pin.h
index e356ef3..38af040 100644
--- a/dlls/quartz/pin.h
+++ b/dlls/quartz/pin.h
@@ -74,7 +74,6 @@
 	PIN_INFO pinInfo;
 	IPin * pConnectedTo;
 	AM_MEDIA_TYPE mtCurrent;
-	ENUMMEDIADETAILS enumMediaDetails;
 	QUERYACCEPTPROC fnQueryAccept;
 	LPVOID pUserData;
 } IPinImpl;
diff --git a/dlls/quartz/quartz_private.h b/dlls/quartz/quartz_private.h
index b6dfcfa..6dbf8c1 100644
--- a/dlls/quartz/quartz_private.h
+++ b/dlls/quartz/quartz_private.h
@@ -63,16 +63,9 @@
 
 HRESULT EnumMonikerImpl_Create(IMoniker ** ppMoniker, ULONG nMonikerCount, IEnumMoniker ** ppEnum);
 
-typedef struct tagENUMEDIADETAILS
-{
-	ULONG cMediaTypes;
-	AM_MEDIA_TYPE * pMediaTypes;
-} ENUMMEDIADETAILS;
-
 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);
 
@@ -94,4 +87,8 @@
     LONGLONG tMediaEnd;
 } StdMediaSample2;
 
+
+HRESULT WINAPI BasePinImpl_GetMediaType(IPin *iface, int iPosition, AM_MEDIA_TYPE *pmt);
+LONG WINAPI BasePinImpl_GetMediaTypeVersion(IPin *iface);
+
 #endif /* __QUARTZ_PRIVATE_INCLUDED__ */
diff --git a/dlls/quartz/transform.c b/dlls/quartz/transform.c
index e8056b0..d907a3d 100644
--- a/dlls/quartz/transform.c
+++ b/dlls/quartz/transform.c
@@ -591,18 +591,25 @@
     TransformFilter_InputPin_NewSegment
 };
 
-static HRESULT WINAPI TransformFilter_Output_EnumMediaTypes(IPin * iface, IEnumMediaTypes ** ppEnum)
+static HRESULT WINAPI TransformFilter_Output_GetMediaType(IPin *iface, int iPosition, AM_MEDIA_TYPE *pmt)
 {
     IPinImpl *This = (IPinImpl *)iface;
     TransformFilterImpl *pTransform = (TransformFilterImpl *)This->pinInfo.pFilter;
-    ENUMMEDIADETAILS emd;
 
+    if (iPosition < 0)
+        return E_INVALIDARG;
+    if (iPosition > 0)
+        return VFW_S_NO_MORE_ITEMS;
+    CopyMediaType(pmt, &pTransform->pmt);
+    return S_OK;
+}
+
+static HRESULT WINAPI TransformFilter_Output_EnumMediaTypes(IPin * iface, IEnumMediaTypes ** ppEnum)
+{
+    IPinImpl *This = (IPinImpl *)iface;
     TRACE("(%p/%p)->(%p)\n", This, iface, ppEnum);
 
-    emd.cMediaTypes = 1;
-    emd.pMediaTypes = &pTransform->pmt;
-
-    return IEnumMediaTypesImpl_Construct(&emd, ppEnum);
+    return EnumMediaTypes_Construct(iface, TransformFilter_Output_GetMediaType, BasePinImpl_GetMediaTypeVersion, ppEnum);
 }
 
 static const IPinVtbl TransformFilter_OutputPin_Vtbl =
diff --git a/dlls/strmbase/mediatype.c b/dlls/strmbase/mediatype.c
index 6de3e7a..380583e 100644
--- a/dlls/strmbase/mediatype.c
+++ b/dlls/strmbase/mediatype.c
@@ -76,3 +76,227 @@
     FreeMediaType(pMediaType);
     CoTaskMemFree(pMediaType);
 }
+
+typedef struct tagENUMEDIADETAILS
+{
+    ULONG cMediaTypes;
+    AM_MEDIA_TYPE * pMediaTypes;
+} ENUMMEDIADETAILS;
+
+typedef struct IEnumMediaTypesImpl
+{
+    const IEnumMediaTypesVtbl * lpVtbl;
+    LONG refCount;
+    IPin *basePin;
+    BasePin_GetMediaType enumMediaFunction;
+    BasePin_GetMediaTypeVersion mediaVersionFunction;
+    LONG currentVersion;
+    ENUMMEDIADETAILS enumMediaDetails;
+    ULONG uIndex;
+} IEnumMediaTypesImpl;
+
+static const struct IEnumMediaTypesVtbl IEnumMediaTypesImpl_Vtbl;
+
+HRESULT WINAPI EnumMediaTypes_Construct(IPin *basePin, BasePin_GetMediaType enumFunc, BasePin_GetMediaTypeVersion versionFunc, IEnumMediaTypes ** ppEnum)
+{
+    ULONG i;
+    IEnumMediaTypesImpl * pEnumMediaTypes = CoTaskMemAlloc(sizeof(IEnumMediaTypesImpl));
+    AM_MEDIA_TYPE amt;
+
+    if (!pEnumMediaTypes)
+    {
+        *ppEnum = NULL;
+        return E_OUTOFMEMORY;
+    }
+    pEnumMediaTypes->lpVtbl = &IEnumMediaTypesImpl_Vtbl;
+    pEnumMediaTypes->refCount = 1;
+    pEnumMediaTypes->uIndex = 0;
+    pEnumMediaTypes->enumMediaFunction = enumFunc;
+    pEnumMediaTypes->mediaVersionFunction = versionFunc;
+    IPin_AddRef(basePin);
+    pEnumMediaTypes->basePin = basePin;
+
+    i = 0;
+    while (enumFunc(basePin,i,&amt) == S_OK) i++;
+
+    pEnumMediaTypes->enumMediaDetails.cMediaTypes = i;
+    pEnumMediaTypes->enumMediaDetails.pMediaTypes = CoTaskMemAlloc(sizeof(AM_MEDIA_TYPE) * i);
+    for (i = 0; i < pEnumMediaTypes->enumMediaDetails.cMediaTypes; i++)
+    {
+        enumFunc(basePin,i,&amt);
+        if (FAILED(CopyMediaType(&pEnumMediaTypes->enumMediaDetails.pMediaTypes[i], &amt)))
+        {
+           while (i--)
+              CoTaskMemFree(pEnumMediaTypes->enumMediaDetails.pMediaTypes[i].pbFormat);
+           CoTaskMemFree(pEnumMediaTypes->enumMediaDetails.pMediaTypes);
+           return E_OUTOFMEMORY;
+        }
+    }
+    *ppEnum = (IEnumMediaTypes *)(&pEnumMediaTypes->lpVtbl);
+    pEnumMediaTypes->currentVersion = versionFunc(basePin);
+    return S_OK;
+}
+
+static HRESULT WINAPI IEnumMediaTypesImpl_QueryInterface(IEnumMediaTypes * iface, REFIID riid, LPVOID * ppv)
+{
+    TRACE("(%s, %p)\n", debugstr_guid(riid), ppv);
+
+    *ppv = NULL;
+
+    if (IsEqualIID(riid, &IID_IUnknown))
+        *ppv = iface;
+    else if (IsEqualIID(riid, &IID_IEnumMediaTypes))
+        *ppv = iface;
+
+    if (*ppv)
+    {
+        IUnknown_AddRef((IUnknown *)(*ppv));
+        return S_OK;
+    }
+
+    FIXME("No interface for %s!\n", debugstr_guid(riid));
+
+    return E_NOINTERFACE;
+}
+
+static ULONG WINAPI IEnumMediaTypesImpl_AddRef(IEnumMediaTypes * iface)
+{
+    IEnumMediaTypesImpl *This = (IEnumMediaTypesImpl *)iface;
+    ULONG refCount = InterlockedIncrement(&This->refCount);
+
+    TRACE("(%p)->() AddRef from %d\n", iface, refCount - 1);
+
+    return refCount;
+}
+
+static ULONG WINAPI IEnumMediaTypesImpl_Release(IEnumMediaTypes * iface)
+{
+    IEnumMediaTypesImpl *This = (IEnumMediaTypesImpl *)iface;
+    ULONG refCount = InterlockedDecrement(&This->refCount);
+
+    TRACE("(%p)->() Release from %d\n", iface, refCount + 1);
+
+    if (!refCount)
+    {
+        ULONG 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);
+        IPin_Release(This->basePin);
+        CoTaskMemFree(This);
+    }
+    return refCount;
+}
+
+static HRESULT WINAPI IEnumMediaTypesImpl_Next(IEnumMediaTypes * iface, ULONG cMediaTypes, AM_MEDIA_TYPE ** ppMediaTypes, ULONG * pcFetched)
+{
+    ULONG cFetched;
+    IEnumMediaTypesImpl *This = (IEnumMediaTypesImpl *)iface;
+
+    cFetched = min(This->enumMediaDetails.cMediaTypes, This->uIndex + cMediaTypes) - This->uIndex;
+
+    if (This->currentVersion != This->mediaVersionFunction(This->basePin))
+        return VFW_E_ENUM_OUT_OF_SYNC;
+
+    TRACE("(%u, %p, %p)\n", cMediaTypes, ppMediaTypes, pcFetched);
+    TRACE("Next uIndex: %u, cFetched: %u\n", This->uIndex, cFetched);
+
+    if (cFetched > 0)
+    {
+        ULONG i;
+        for (i = 0; i < cFetched; i++)
+            if (!(ppMediaTypes[i] = CreateMediaType(&This->enumMediaDetails.pMediaTypes[This->uIndex + i])))
+            {
+                while (i--)
+                    DeleteMediaType(ppMediaTypes[i]);
+                *pcFetched = 0;
+                return E_OUTOFMEMORY;
+            }
+    }
+
+    if ((cMediaTypes != 1) || pcFetched)
+        *pcFetched = cFetched;
+
+    This->uIndex += cFetched;
+
+    if (cFetched != cMediaTypes)
+        return S_FALSE;
+    return S_OK;
+}
+
+static HRESULT WINAPI IEnumMediaTypesImpl_Skip(IEnumMediaTypes * iface, ULONG cMediaTypes)
+{
+    IEnumMediaTypesImpl *This = (IEnumMediaTypesImpl *)iface;
+
+    TRACE("(%u)\n", cMediaTypes);
+    if (This->currentVersion != This->mediaVersionFunction(This->basePin))
+        return VFW_E_ENUM_OUT_OF_SYNC;
+
+    if (This->uIndex + cMediaTypes < This->enumMediaDetails.cMediaTypes)
+    {
+        This->uIndex += cMediaTypes;
+        return S_OK;
+    }
+    return S_FALSE;
+}
+
+static HRESULT WINAPI IEnumMediaTypesImpl_Reset(IEnumMediaTypes * iface)
+{
+    ULONG i;
+    AM_MEDIA_TYPE amt;
+    IEnumMediaTypesImpl *This = (IEnumMediaTypesImpl *)iface;
+
+    TRACE("()\n");
+
+    for (i = 0; i < This->enumMediaDetails.cMediaTypes; i++)
+        if (This->enumMediaDetails.pMediaTypes[i].pbFormat)
+            CoTaskMemFree(This->enumMediaDetails.pMediaTypes[i].pbFormat);
+    CoTaskMemFree(This->enumMediaDetails.pMediaTypes);
+
+    i = 0;
+    while (This->enumMediaFunction(This->basePin, i,&amt) == S_OK) i++;
+
+    This->enumMediaDetails.cMediaTypes = i;
+    This->enumMediaDetails.pMediaTypes = CoTaskMemAlloc(sizeof(AM_MEDIA_TYPE) * i);
+    for (i = 0; i < This->enumMediaDetails.cMediaTypes; i++)
+    {
+        This->enumMediaFunction(This->basePin, i,&amt);
+        if (FAILED(CopyMediaType(&This->enumMediaDetails.pMediaTypes[i], &amt)))
+        {
+           while (i--)
+              CoTaskMemFree(This->enumMediaDetails.pMediaTypes[i].pbFormat);
+           CoTaskMemFree(This->enumMediaDetails.pMediaTypes);
+           return E_OUTOFMEMORY;
+        }
+    }
+
+    This->currentVersion = This->mediaVersionFunction(This->basePin);
+    This->uIndex = 0;
+
+    return S_OK;
+}
+
+static HRESULT WINAPI IEnumMediaTypesImpl_Clone(IEnumMediaTypes * iface, IEnumMediaTypes ** ppEnum)
+{
+    HRESULT hr;
+    IEnumMediaTypesImpl *This = (IEnumMediaTypesImpl *)iface;
+
+    TRACE("(%p)\n", ppEnum);
+
+    hr = EnumMediaTypes_Construct(This->basePin, This->enumMediaFunction, This->mediaVersionFunction, ppEnum);
+    if (FAILED(hr))
+        return hr;
+    return IEnumMediaTypes_Skip(*ppEnum, This->uIndex);
+}
+
+static const IEnumMediaTypesVtbl IEnumMediaTypesImpl_Vtbl =
+{
+    IEnumMediaTypesImpl_QueryInterface,
+    IEnumMediaTypesImpl_AddRef,
+    IEnumMediaTypesImpl_Release,
+    IEnumMediaTypesImpl_Next,
+    IEnumMediaTypesImpl_Skip,
+    IEnumMediaTypesImpl_Reset,
+    IEnumMediaTypesImpl_Clone
+};
diff --git a/include/wine/strmbase.h b/include/wine/strmbase.h
index 885a976..4177a04 100644
--- a/include/wine/strmbase.h
+++ b/include/wine/strmbase.h
@@ -23,3 +23,8 @@
 void WINAPI FreeMediaType(AM_MEDIA_TYPE * pMediaType);
 AM_MEDIA_TYPE * WINAPI CreateMediaType(AM_MEDIA_TYPE const * pSrc);
 void WINAPI DeleteMediaType(AM_MEDIA_TYPE * pMediaType);
+
+typedef HRESULT (WINAPI *BasePin_GetMediaType)(IPin* iface, int iPosition, AM_MEDIA_TYPE *amt);
+typedef LONG (WINAPI *BasePin_GetMediaTypeVersion)(IPin* iface);
+
+HRESULT WINAPI EnumMediaTypes_Construct(IPin *iface, BasePin_GetMediaType enumFunc, BasePin_GetMediaTypeVersion versionFunc, IEnumMediaTypes ** ppEnum);