strmbase: Add the EnumMediaTypes base implementation.

This commit is contained in:
Aric Stewart 2010-10-05 14:37:30 -05:00 committed by Alexandre Julliard
parent ee18ead545
commit 89ea07f7d0
13 changed files with 309 additions and 393 deletions

View File

@ -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
};

View File

@ -43,7 +43,6 @@ typedef struct IPinImpl
PIN_INFO pinInfo;
IPin * pConnectedTo;
AM_MEDIA_TYPE mtCurrent;
ENUMMEDIADETAILS enumMediaDetails;
QUERYACCEPTPROC fnQueryAccept;
LPVOID pUserData;
} IPinImpl;

View File

@ -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);

View File

@ -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;
}

View File

@ -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
};

View File

@ -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 =

View File

@ -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)

View File

@ -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)

View File

@ -74,7 +74,6 @@ typedef struct IPinImpl
PIN_INFO pinInfo;
IPin * pConnectedTo;
AM_MEDIA_TYPE mtCurrent;
ENUMMEDIADETAILS enumMediaDetails;
QUERYACCEPTPROC fnQueryAccept;
LPVOID pUserData;
} IPinImpl;

View File

@ -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__ */

View File

@ -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 =

View File

@ -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
};

View File

@ -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);