From 89ea07f7d0c344afe5f32afbe49bde6cea31b91c Mon Sep 17 00:00:00 2001 From: Aric Stewart Date: Tue, 5 Oct 2010 14:37:30 -0500 Subject: [PATCH] strmbase: Add the EnumMediaTypes base implementation. --- dlls/qcap/enummedia.c | 181 ---------------------------- dlls/qcap/pin.h | 1 - dlls/qcap/qcap_main.h | 7 -- dlls/qcap/vfwcapture.c | 29 ++++- dlls/quartz/enummedia.c | 169 -------------------------- dlls/quartz/filesource.c | 19 +-- dlls/quartz/parser.c | 18 ++- dlls/quartz/pin.c | 18 ++- dlls/quartz/pin.h | 1 - dlls/quartz/quartz_private.h | 11 +- dlls/quartz/transform.c | 19 ++- dlls/strmbase/mediatype.c | 224 +++++++++++++++++++++++++++++++++++ include/wine/strmbase.h | 5 + 13 files changed, 309 insertions(+), 393 deletions(-) diff --git a/dlls/qcap/enummedia.c b/dlls/qcap/enummedia.c index 94b29073c53..b291a9e4e45 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 @@ void dump_AM_MEDIA_TYPE(const AM_MEDIA_TYPE * pmt) 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 68d3e28123c..e738b5877f3 100644 --- a/dlls/qcap/pin.h +++ b/dlls/qcap/pin.h @@ -43,7 +43,6 @@ typedef struct IPinImpl 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 59a172fb99b..535b7ff2be4 100644 --- a/dlls/qcap/qcap_main.h +++ b/dlls/qcap/qcap_main.h @@ -43,14 +43,7 @@ typedef struct tagENUMPINDETAILS 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 d85183669a1..c4e5c542f03 100644 --- a/dlls/qcap/vfwcapture.c +++ b/dlls/qcap/vfwcapture.c @@ -741,6 +741,29 @@ static const IKsPropertySetVtbl KSP_VTable = 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 @@ VfwPin_Release(IPin * iface) 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 db78965f0e2..8c564b699fe 100644 --- a/dlls/quartz/enummedia.c +++ b/dlls/quartz/enummedia.c @@ -40,172 +40,3 @@ void dump_AM_MEDIA_TYPE(const AM_MEDIA_TYPE * pmt) 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 110415df57e..3430cb39595 100644 --- a/dlls/quartz/filesource.c +++ b/dlls/quartz/filesource.c @@ -794,6 +794,17 @@ static HRESULT AcceptProcAFR(LPVOID iface, const AM_MEDIA_TYPE *pmt) 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 ULONG WINAPI FileAsyncReaderPin_Release(IPin * iface) 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 f95d3e7c25a..979a18c4ba8 100644 --- a/dlls/quartz/parser.c +++ b/dlls/quartz/parser.c @@ -599,6 +599,17 @@ static const IMediaSeekingVtbl Parser_Seeking_Vtbl = 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 ULONG WINAPI Parser_OutputPin_Release(IPin * iface) 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 fd0d5a2e522..25dff174e8c 100644 --- a/dlls/quartz/pin.c +++ b/dlls/quartz/pin.c @@ -154,6 +154,19 @@ static void Copy_PinInfo(PIN_INFO * pDest, const PIN_INFO * pSrc) 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_QueryAccept(IPin * iface, const AM_MEDIA_TYPE * pmt) 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 e356ef32f53..38af040271d 100644 --- a/dlls/quartz/pin.h +++ b/dlls/quartz/pin.h @@ -74,7 +74,6 @@ typedef struct IPinImpl 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 b6dfcfa0320..6dbf8c128ce 100644 --- a/dlls/quartz/quartz_private.h +++ b/dlls/quartz/quartz_private.h @@ -63,16 +63,9 @@ HRESULT SeekingPassThru_create(IUnknown *pUnkOuter, LPVOID *ppObj); 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 @@ typedef struct StdMediaSample2 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 e8056b0b341..d907a3db84e 100644 --- a/dlls/quartz/transform.c +++ b/dlls/quartz/transform.c @@ -591,18 +591,25 @@ static const IPinVtbl TransformFilter_InputPin_Vtbl = 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 6de3e7a08fd..380583e20c7 100644 --- a/dlls/strmbase/mediatype.c +++ b/dlls/strmbase/mediatype.c @@ -76,3 +76,227 @@ void WINAPI DeleteMediaType(AM_MEDIA_TYPE * pMediaType) 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 885a9760a72..4177a04e47a 100644 --- a/include/wine/strmbase.h +++ b/include/wine/strmbase.h @@ -23,3 +23,8 @@ HRESULT WINAPI CopyMediaType(AM_MEDIA_TYPE * pDest, const AM_MEDIA_TYPE *pSrc); 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);