strmbase: Move InputPin implementation to strmbase.
This commit is contained in:
parent
5c1409b55f
commit
66e1ad8a96
|
@ -52,8 +52,9 @@ typedef struct ACMWrapperImpl
|
||||||
LONGLONG lasttime_sent;
|
LONGLONG lasttime_sent;
|
||||||
} ACMWrapperImpl;
|
} ACMWrapperImpl;
|
||||||
|
|
||||||
static HRESULT ACMWrapper_ProcessSampleData(InputPin *pin, IMediaSample *pSample)
|
static HRESULT WINAPI ACMWrapper_ProcessSampleData(IPin *iface, IMediaSample *pSample)
|
||||||
{
|
{
|
||||||
|
BaseInputPin *pin = (BaseInputPin*) iface;
|
||||||
ACMWrapperImpl* This = (ACMWrapperImpl*)pin->pin.pinInfo.pFilter;
|
ACMWrapperImpl* This = (ACMWrapperImpl*)pin->pin.pinInfo.pFilter;
|
||||||
AM_MEDIA_TYPE amt;
|
AM_MEDIA_TYPE amt;
|
||||||
IMediaSample* pOutSample = NULL;
|
IMediaSample* pOutSample = NULL;
|
||||||
|
@ -234,7 +235,7 @@ error:
|
||||||
return hr;
|
return hr;
|
||||||
}
|
}
|
||||||
|
|
||||||
static HRESULT ACMWrapper_ConnectInput(InputPin *pin, const AM_MEDIA_TYPE * pmt)
|
static HRESULT ACMWrapper_ConnectInput(BaseInputPin *pin, const AM_MEDIA_TYPE * pmt)
|
||||||
{
|
{
|
||||||
ACMWrapperImpl* This = (ACMWrapperImpl *)pin->pin.pinInfo.pFilter;
|
ACMWrapperImpl* This = (ACMWrapperImpl *)pin->pin.pinInfo.pFilter;
|
||||||
MMRESULT res;
|
MMRESULT res;
|
||||||
|
@ -286,7 +287,7 @@ static HRESULT ACMWrapper_ConnectInput(InputPin *pin, const AM_MEDIA_TYPE * pmt)
|
||||||
return VFW_E_TYPE_NOT_ACCEPTED;
|
return VFW_E_TYPE_NOT_ACCEPTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
static HRESULT ACMWrapper_Cleanup(InputPin *pin)
|
static HRESULT ACMWrapper_Cleanup(BaseInputPin *pin)
|
||||||
{
|
{
|
||||||
ACMWrapperImpl *This = (ACMWrapperImpl *)pin->pin.pinInfo.pFilter;
|
ACMWrapperImpl *This = (ACMWrapperImpl *)pin->pin.pinInfo.pFilter;
|
||||||
|
|
||||||
|
|
|
@ -66,8 +66,9 @@ static HRESULT AVIDec_ProcessBegin(TransformFilterImpl* pTransformFilter)
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static HRESULT AVIDec_ProcessSampleData(InputPin *pin, IMediaSample *pSample)
|
static HRESULT WINAPI AVIDec_ProcessSampleData(IPin *iface, IMediaSample *pSample)
|
||||||
{
|
{
|
||||||
|
BaseInputPin *pin = (BaseInputPin*)iface;
|
||||||
AVIDecImpl* This = (AVIDecImpl *)pin->pin.pinInfo.pFilter;
|
AVIDecImpl* This = (AVIDecImpl *)pin->pin.pinInfo.pFilter;
|
||||||
AM_MEDIA_TYPE amt;
|
AM_MEDIA_TYPE amt;
|
||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
|
@ -182,7 +183,7 @@ static HRESULT AVIDec_ProcessEnd(TransformFilterImpl* pTransformFilter)
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static HRESULT AVIDec_ConnectInput(InputPin *pin, const AM_MEDIA_TYPE * pmt)
|
static HRESULT AVIDec_ConnectInput(BaseInputPin *pin, const AM_MEDIA_TYPE * pmt)
|
||||||
{
|
{
|
||||||
AVIDecImpl* This = (AVIDecImpl*)pin->pin.pinInfo.pFilter;
|
AVIDecImpl* This = (AVIDecImpl*)pin->pin.pinInfo.pFilter;
|
||||||
HRESULT hr = VFW_E_TYPE_NOT_ACCEPTED;
|
HRESULT hr = VFW_E_TYPE_NOT_ACCEPTED;
|
||||||
|
@ -283,7 +284,7 @@ failed:
|
||||||
return hr;
|
return hr;
|
||||||
}
|
}
|
||||||
|
|
||||||
static HRESULT AVIDec_Cleanup(InputPin *pin)
|
static HRESULT AVIDec_Cleanup(BaseInputPin *pin)
|
||||||
{
|
{
|
||||||
AVIDecImpl *This = (AVIDecImpl *)pin->pin.pinInfo.pFilter;
|
AVIDecImpl *This = (AVIDecImpl *)pin->pin.pinInfo.pFilter;
|
||||||
|
|
||||||
|
|
|
@ -63,7 +63,7 @@ typedef struct DSoundRenderImpl
|
||||||
IReferenceClock * pClock;
|
IReferenceClock * pClock;
|
||||||
FILTER_INFO filterInfo;
|
FILTER_INFO filterInfo;
|
||||||
|
|
||||||
InputPin * pInputPin;
|
BaseInputPin * pInputPin;
|
||||||
|
|
||||||
IDirectSound8 *dsound;
|
IDirectSound8 *dsound;
|
||||||
LPDIRECTSOUNDBUFFER dsbuffer;
|
LPDIRECTSOUNDBUFFER dsbuffer;
|
||||||
|
@ -211,9 +211,10 @@ static HRESULT DSoundRender_SendSampleData(DSoundRenderImpl* This, const BYTE *d
|
||||||
return hr;
|
return hr;
|
||||||
}
|
}
|
||||||
|
|
||||||
static HRESULT DSoundRender_Sample(LPVOID iface, IMediaSample * pSample)
|
static HRESULT WINAPI DSoundRender_Receive(IPin *iface, IMediaSample * pSample)
|
||||||
{
|
{
|
||||||
DSoundRenderImpl *This = iface;
|
BaseInputPin *pin = (BaseInputPin*)iface;
|
||||||
|
DSoundRenderImpl *This = (DSoundRenderImpl*)pin->pin.pinInfo.pFilter;
|
||||||
LPBYTE pbSrcStream = NULL;
|
LPBYTE pbSrcStream = NULL;
|
||||||
LONG cbSrcStream = 0;
|
LONG cbSrcStream = 0;
|
||||||
REFERENCE_TIME tStart, tStop;
|
REFERENCE_TIME tStart, tStop;
|
||||||
|
@ -344,7 +345,7 @@ static HRESULT DSoundRender_Sample(LPVOID iface, IMediaSample * pSample)
|
||||||
return hr;
|
return hr;
|
||||||
}
|
}
|
||||||
|
|
||||||
static HRESULT DSoundRender_QueryAccept(LPVOID iface, const AM_MEDIA_TYPE * pmt)
|
static HRESULT WINAPI DSoundRender_CheckMediaType(IPin *iface, const AM_MEDIA_TYPE * pmt)
|
||||||
{
|
{
|
||||||
WAVEFORMATEX* format;
|
WAVEFORMATEX* format;
|
||||||
|
|
||||||
|
@ -397,7 +398,7 @@ HRESULT DSoundRender_create(IUnknown * pUnkOuter, LPVOID * ppv)
|
||||||
piInput.dir = PINDIR_INPUT;
|
piInput.dir = PINDIR_INPUT;
|
||||||
piInput.pFilter = (IBaseFilter *)pDSoundRender;
|
piInput.pFilter = (IBaseFilter *)pDSoundRender;
|
||||||
lstrcpynW(piInput.achName, wcsInputPinName, sizeof(piInput.achName) / sizeof(piInput.achName[0]));
|
lstrcpynW(piInput.achName, wcsInputPinName, sizeof(piInput.achName) / sizeof(piInput.achName[0]));
|
||||||
hr = InputPin_Construct(&DSoundRender_InputPin_Vtbl, &piInput, DSoundRender_Sample, pDSoundRender, DSoundRender_QueryAccept, NULL, &pDSoundRender->csFilter, NULL, (IPin **)&pDSoundRender->pInputPin);
|
hr = BaseInputPin_Construct(&DSoundRender_InputPin_Vtbl, &piInput, DSoundRender_CheckMediaType, DSoundRender_Receive, &pDSoundRender->csFilter, NULL, (IPin **)&pDSoundRender->pInputPin);
|
||||||
|
|
||||||
if (SUCCEEDED(hr))
|
if (SUCCEEDED(hr))
|
||||||
{
|
{
|
||||||
|
@ -809,7 +810,7 @@ static const IBaseFilterVtbl DSoundRender_Vtbl =
|
||||||
|
|
||||||
static HRESULT WINAPI DSoundRender_InputPin_ReceiveConnection(IPin * iface, IPin * pReceivePin, const AM_MEDIA_TYPE * pmt)
|
static HRESULT WINAPI DSoundRender_InputPin_ReceiveConnection(IPin * iface, IPin * pReceivePin, const AM_MEDIA_TYPE * pmt)
|
||||||
{
|
{
|
||||||
InputPin *This = (InputPin *)iface;
|
BaseInputPin *This = (BaseInputPin *)iface;
|
||||||
PIN_DIRECTION pindirReceive;
|
PIN_DIRECTION pindirReceive;
|
||||||
DSoundRenderImpl *DSImpl;
|
DSoundRenderImpl *DSImpl;
|
||||||
HRESULT hr = S_OK;
|
HRESULT hr = S_OK;
|
||||||
|
@ -825,7 +826,7 @@ static HRESULT WINAPI DSoundRender_InputPin_ReceiveConnection(IPin * iface, IPin
|
||||||
if (This->pin.pConnectedTo)
|
if (This->pin.pConnectedTo)
|
||||||
hr = VFW_E_ALREADY_CONNECTED;
|
hr = VFW_E_ALREADY_CONNECTED;
|
||||||
|
|
||||||
if (SUCCEEDED(hr) && This->fnQueryAccept(This->pUserData, pmt) != S_OK)
|
if (SUCCEEDED(hr) && This->fnCheckMediaType(iface, pmt) != S_OK)
|
||||||
hr = VFW_E_TYPE_NOT_ACCEPTED;
|
hr = VFW_E_TYPE_NOT_ACCEPTED;
|
||||||
|
|
||||||
if (SUCCEEDED(hr))
|
if (SUCCEEDED(hr))
|
||||||
|
@ -914,7 +915,7 @@ static HRESULT WINAPI DSoundRender_InputPin_Disconnect(IPin * iface)
|
||||||
|
|
||||||
static HRESULT WINAPI DSoundRender_InputPin_EndOfStream(IPin * iface)
|
static HRESULT WINAPI DSoundRender_InputPin_EndOfStream(IPin * iface)
|
||||||
{
|
{
|
||||||
InputPin* This = (InputPin*)iface;
|
BaseInputPin* This = (BaseInputPin*)iface;
|
||||||
DSoundRenderImpl *me = (DSoundRenderImpl*)This->pin.pinInfo.pFilter;
|
DSoundRenderImpl *me = (DSoundRenderImpl*)This->pin.pinInfo.pFilter;
|
||||||
IMediaEventSink* pEventSink;
|
IMediaEventSink* pEventSink;
|
||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
|
@ -922,7 +923,7 @@ static HRESULT WINAPI DSoundRender_InputPin_EndOfStream(IPin * iface)
|
||||||
EnterCriticalSection(This->pin.pCritSec);
|
EnterCriticalSection(This->pin.pCritSec);
|
||||||
|
|
||||||
TRACE("(%p/%p)->()\n", This, iface);
|
TRACE("(%p/%p)->()\n", This, iface);
|
||||||
hr = InputPin_EndOfStream(iface);
|
hr = BaseInputPinImpl_EndOfStream(iface);
|
||||||
if (hr != S_OK)
|
if (hr != S_OK)
|
||||||
{
|
{
|
||||||
ERR("%08x\n", hr);
|
ERR("%08x\n", hr);
|
||||||
|
@ -954,14 +955,14 @@ static HRESULT WINAPI DSoundRender_InputPin_EndOfStream(IPin * iface)
|
||||||
|
|
||||||
static HRESULT WINAPI DSoundRender_InputPin_BeginFlush(IPin * iface)
|
static HRESULT WINAPI DSoundRender_InputPin_BeginFlush(IPin * iface)
|
||||||
{
|
{
|
||||||
InputPin *This = (InputPin *)iface;
|
BaseInputPin *This = (BaseInputPin *)iface;
|
||||||
DSoundRenderImpl *pFilter = (DSoundRenderImpl *)This->pin.pinInfo.pFilter;
|
DSoundRenderImpl *pFilter = (DSoundRenderImpl *)This->pin.pinInfo.pFilter;
|
||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
|
|
||||||
TRACE("\n");
|
TRACE("\n");
|
||||||
|
|
||||||
EnterCriticalSection(This->pin.pCritSec);
|
EnterCriticalSection(This->pin.pCritSec);
|
||||||
hr = InputPin_BeginFlush(iface);
|
hr = BaseInputPinImpl_BeginFlush(iface);
|
||||||
SetEvent(pFilter->blocked);
|
SetEvent(pFilter->blocked);
|
||||||
LeaveCriticalSection(This->pin.pCritSec);
|
LeaveCriticalSection(This->pin.pCritSec);
|
||||||
|
|
||||||
|
@ -970,7 +971,7 @@ static HRESULT WINAPI DSoundRender_InputPin_BeginFlush(IPin * iface)
|
||||||
|
|
||||||
static HRESULT WINAPI DSoundRender_InputPin_EndFlush(IPin * iface)
|
static HRESULT WINAPI DSoundRender_InputPin_EndFlush(IPin * iface)
|
||||||
{
|
{
|
||||||
InputPin *This = (InputPin *)iface;
|
BaseInputPin *This = (BaseInputPin *)iface;
|
||||||
DSoundRenderImpl *pFilter = (DSoundRenderImpl *)This->pin.pinInfo.pFilter;
|
DSoundRenderImpl *pFilter = (DSoundRenderImpl *)This->pin.pinInfo.pFilter;
|
||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
|
|
||||||
|
@ -1002,7 +1003,7 @@ static HRESULT WINAPI DSoundRender_InputPin_EndFlush(IPin * iface)
|
||||||
memset(buffer, 0, size);
|
memset(buffer, 0, size);
|
||||||
IDirectSoundBuffer_Unlock(pFilter->dsbuffer, buffer, size, NULL, 0);
|
IDirectSoundBuffer_Unlock(pFilter->dsbuffer, buffer, size, NULL, 0);
|
||||||
}
|
}
|
||||||
hr = InputPin_EndFlush(iface);
|
hr = BaseInputPinImpl_EndFlush(iface);
|
||||||
LeaveCriticalSection(This->pin.pCritSec);
|
LeaveCriticalSection(This->pin.pCritSec);
|
||||||
MediaSeekingPassThru_ResetMediaTime(pFilter->seekthru_unk);
|
MediaSeekingPassThru_ResetMediaTime(pFilter->seekthru_unk);
|
||||||
|
|
||||||
|
@ -1011,10 +1012,10 @@ static HRESULT WINAPI DSoundRender_InputPin_EndFlush(IPin * iface)
|
||||||
|
|
||||||
static const IPinVtbl DSoundRender_InputPin_Vtbl =
|
static const IPinVtbl DSoundRender_InputPin_Vtbl =
|
||||||
{
|
{
|
||||||
InputPin_QueryInterface,
|
BaseInputPinImpl_QueryInterface,
|
||||||
BasePinImpl_AddRef,
|
BasePinImpl_AddRef,
|
||||||
InputPin_Release,
|
BaseInputPinImpl_Release,
|
||||||
InputPin_Connect,
|
BaseInputPinImpl_Connect,
|
||||||
DSoundRender_InputPin_ReceiveConnection,
|
DSoundRender_InputPin_ReceiveConnection,
|
||||||
DSoundRender_InputPin_Disconnect,
|
DSoundRender_InputPin_Disconnect,
|
||||||
BasePinImpl_ConnectedTo,
|
BasePinImpl_ConnectedTo,
|
||||||
|
@ -1022,13 +1023,13 @@ static const IPinVtbl DSoundRender_InputPin_Vtbl =
|
||||||
BasePinImpl_QueryPinInfo,
|
BasePinImpl_QueryPinInfo,
|
||||||
BasePinImpl_QueryDirection,
|
BasePinImpl_QueryDirection,
|
||||||
BasePinImpl_QueryId,
|
BasePinImpl_QueryId,
|
||||||
InputPin_QueryAccept,
|
BaseInputPinImpl_QueryAccept,
|
||||||
BasePinImpl_EnumMediaTypes,
|
BasePinImpl_EnumMediaTypes,
|
||||||
BasePinImpl_QueryInternalConnections,
|
BasePinImpl_QueryInternalConnections,
|
||||||
DSoundRender_InputPin_EndOfStream,
|
DSoundRender_InputPin_EndOfStream,
|
||||||
DSoundRender_InputPin_BeginFlush,
|
DSoundRender_InputPin_BeginFlush,
|
||||||
DSoundRender_InputPin_EndFlush,
|
DSoundRender_InputPin_EndFlush,
|
||||||
InputPin_NewSegment
|
BaseInputPinImpl_NewSegment
|
||||||
};
|
};
|
||||||
|
|
||||||
/*** IUnknown methods ***/
|
/*** IUnknown methods ***/
|
||||||
|
|
|
@ -62,15 +62,16 @@ typedef struct NullRendererImpl
|
||||||
IReferenceClock * pClock;
|
IReferenceClock * pClock;
|
||||||
FILTER_INFO filterInfo;
|
FILTER_INFO filterInfo;
|
||||||
|
|
||||||
InputPin *pInputPin;
|
BaseInputPin *pInputPin;
|
||||||
IUnknown * pUnkOuter;
|
IUnknown * pUnkOuter;
|
||||||
BOOL bUnkOuterValid;
|
BOOL bUnkOuterValid;
|
||||||
BOOL bAggregatable;
|
BOOL bAggregatable;
|
||||||
} NullRendererImpl;
|
} NullRendererImpl;
|
||||||
|
|
||||||
static HRESULT NullRenderer_Sample(LPVOID iface, IMediaSample * pSample)
|
static HRESULT WINAPI NullRenderer_Receive(IPin *iface, IMediaSample * pSample)
|
||||||
{
|
{
|
||||||
NullRendererImpl *This = iface;
|
BaseInputPin *pin = (BaseInputPin*)iface;
|
||||||
|
NullRendererImpl *This = ((NullRendererImpl*)pin->pin.pinInfo.pFilter);
|
||||||
HRESULT hr = S_OK;
|
HRESULT hr = S_OK;
|
||||||
REFERENCE_TIME start, stop;
|
REFERENCE_TIME start, stop;
|
||||||
|
|
||||||
|
@ -86,7 +87,7 @@ static HRESULT NullRenderer_Sample(LPVOID iface, IMediaSample * pSample)
|
||||||
return hr;
|
return hr;
|
||||||
}
|
}
|
||||||
|
|
||||||
static HRESULT NullRenderer_QueryAccept(LPVOID iface, const AM_MEDIA_TYPE * pmt)
|
static HRESULT WINAPI NullRenderer_CheckMediaType(IPin *iface, const AM_MEDIA_TYPE * pmt)
|
||||||
{
|
{
|
||||||
TRACE("Not a stub!\n");
|
TRACE("Not a stub!\n");
|
||||||
return S_OK;
|
return S_OK;
|
||||||
|
@ -121,7 +122,7 @@ HRESULT NullRenderer_create(IUnknown * pUnkOuter, LPVOID * ppv)
|
||||||
piInput.pFilter = (IBaseFilter *)pNullRenderer;
|
piInput.pFilter = (IBaseFilter *)pNullRenderer;
|
||||||
lstrcpynW(piInput.achName, wcsInputPinName, sizeof(piInput.achName) / sizeof(piInput.achName[0]));
|
lstrcpynW(piInput.achName, wcsInputPinName, sizeof(piInput.achName) / sizeof(piInput.achName[0]));
|
||||||
|
|
||||||
hr = InputPin_Construct(&NullRenderer_InputPin_Vtbl, &piInput, NullRenderer_Sample, (LPVOID)pNullRenderer, NullRenderer_QueryAccept, NULL, &pNullRenderer->csFilter, NULL, (IPin **)&pNullRenderer->pInputPin);
|
hr = BaseInputPin_Construct(&NullRenderer_InputPin_Vtbl, &piInput, NullRenderer_CheckMediaType, NullRenderer_Receive, &pNullRenderer->csFilter, NULL, (IPin **)&pNullRenderer->pInputPin);
|
||||||
|
|
||||||
if (SUCCEEDED(hr))
|
if (SUCCEEDED(hr))
|
||||||
{
|
{
|
||||||
|
@ -511,7 +512,7 @@ static const IBaseFilterVtbl NullRenderer_Vtbl =
|
||||||
|
|
||||||
static HRESULT WINAPI NullRenderer_InputPin_EndOfStream(IPin * iface)
|
static HRESULT WINAPI NullRenderer_InputPin_EndOfStream(IPin * iface)
|
||||||
{
|
{
|
||||||
InputPin* This = (InputPin*)iface;
|
BaseInputPin* This = (BaseInputPin*)iface;
|
||||||
IMediaEventSink* pEventSink;
|
IMediaEventSink* pEventSink;
|
||||||
NullRendererImpl *pNull;
|
NullRendererImpl *pNull;
|
||||||
IFilterGraph *graph;
|
IFilterGraph *graph;
|
||||||
|
@ -519,7 +520,7 @@ static HRESULT WINAPI NullRenderer_InputPin_EndOfStream(IPin * iface)
|
||||||
|
|
||||||
TRACE("(%p/%p)->()\n", This, iface);
|
TRACE("(%p/%p)->()\n", This, iface);
|
||||||
|
|
||||||
InputPin_EndOfStream(iface);
|
BaseInputPinImpl_EndOfStream(iface);
|
||||||
pNull = (NullRendererImpl*)This->pin.pinInfo.pFilter;
|
pNull = (NullRendererImpl*)This->pin.pinInfo.pFilter;
|
||||||
graph = pNull->filterInfo.pGraph;
|
graph = pNull->filterInfo.pGraph;
|
||||||
if (graph)
|
if (graph)
|
||||||
|
@ -538,13 +539,13 @@ static HRESULT WINAPI NullRenderer_InputPin_EndOfStream(IPin * iface)
|
||||||
|
|
||||||
static HRESULT WINAPI NullRenderer_InputPin_EndFlush(IPin * iface)
|
static HRESULT WINAPI NullRenderer_InputPin_EndFlush(IPin * iface)
|
||||||
{
|
{
|
||||||
InputPin* This = (InputPin*)iface;
|
BaseInputPin* This = (BaseInputPin*)iface;
|
||||||
NullRendererImpl *pNull;
|
NullRendererImpl *pNull;
|
||||||
HRESULT hr = S_OK;
|
HRESULT hr = S_OK;
|
||||||
|
|
||||||
TRACE("(%p/%p)->()\n", This, iface);
|
TRACE("(%p/%p)->()\n", This, iface);
|
||||||
|
|
||||||
hr = InputPin_EndOfStream(iface);
|
hr = BaseInputPinImpl_EndOfStream(iface);
|
||||||
pNull = (NullRendererImpl*)This->pin.pinInfo.pFilter;
|
pNull = (NullRendererImpl*)This->pin.pinInfo.pFilter;
|
||||||
MediaSeekingPassThru_ResetMediaTime(pNull->seekthru_unk);
|
MediaSeekingPassThru_ResetMediaTime(pNull->seekthru_unk);
|
||||||
return hr;
|
return hr;
|
||||||
|
@ -552,22 +553,22 @@ static HRESULT WINAPI NullRenderer_InputPin_EndFlush(IPin * iface)
|
||||||
|
|
||||||
static const IPinVtbl NullRenderer_InputPin_Vtbl =
|
static const IPinVtbl NullRenderer_InputPin_Vtbl =
|
||||||
{
|
{
|
||||||
InputPin_QueryInterface,
|
BaseInputPinImpl_QueryInterface,
|
||||||
BasePinImpl_AddRef,
|
BasePinImpl_AddRef,
|
||||||
InputPin_Release,
|
BaseInputPinImpl_Release,
|
||||||
InputPin_Connect,
|
BaseInputPinImpl_Connect,
|
||||||
InputPin_ReceiveConnection,
|
BaseInputPinImpl_ReceiveConnection,
|
||||||
BasePinImpl_Disconnect,
|
BasePinImpl_Disconnect,
|
||||||
BasePinImpl_ConnectedTo,
|
BasePinImpl_ConnectedTo,
|
||||||
BasePinImpl_ConnectionMediaType,
|
BasePinImpl_ConnectionMediaType,
|
||||||
BasePinImpl_QueryPinInfo,
|
BasePinImpl_QueryPinInfo,
|
||||||
BasePinImpl_QueryDirection,
|
BasePinImpl_QueryDirection,
|
||||||
BasePinImpl_QueryId,
|
BasePinImpl_QueryId,
|
||||||
InputPin_QueryAccept,
|
BaseInputPinImpl_QueryAccept,
|
||||||
BasePinImpl_EnumMediaTypes,
|
BasePinImpl_EnumMediaTypes,
|
||||||
BasePinImpl_QueryInternalConnections,
|
BasePinImpl_QueryInternalConnections,
|
||||||
NullRenderer_InputPin_EndOfStream,
|
NullRenderer_InputPin_EndOfStream,
|
||||||
InputPin_BeginFlush,
|
BaseInputPinImpl_BeginFlush,
|
||||||
NullRenderer_InputPin_EndFlush,
|
NullRenderer_InputPin_EndFlush,
|
||||||
InputPin_NewSegment
|
BaseInputPinImpl_NewSegment
|
||||||
};
|
};
|
||||||
|
|
|
@ -781,7 +781,7 @@ static const IPinVtbl Parser_InputPin_Vtbl =
|
||||||
PullPin_QueryInterface,
|
PullPin_QueryInterface,
|
||||||
BasePinImpl_AddRef,
|
BasePinImpl_AddRef,
|
||||||
PullPin_Release,
|
PullPin_Release,
|
||||||
InputPin_Connect,
|
BaseInputPinImpl_Connect,
|
||||||
Parser_PullPin_ReceiveConnection,
|
Parser_PullPin_ReceiveConnection,
|
||||||
Parser_PullPin_Disconnect,
|
Parser_PullPin_Disconnect,
|
||||||
BasePinImpl_ConnectedTo,
|
BasePinImpl_ConnectedTo,
|
||||||
|
|
|
@ -29,8 +29,6 @@
|
||||||
|
|
||||||
WINE_DEFAULT_DEBUG_CHANNEL(quartz);
|
WINE_DEFAULT_DEBUG_CHANNEL(quartz);
|
||||||
|
|
||||||
static const IPinVtbl InputPin_Vtbl;
|
|
||||||
static const IMemInputPinVtbl MemInputPin_Vtbl;
|
|
||||||
static const IPinVtbl PullPin_Vtbl;
|
static const IPinVtbl PullPin_Vtbl;
|
||||||
|
|
||||||
#define ALIGNDOWN(value,boundary) ((value)/(boundary)*(boundary))
|
#define ALIGNDOWN(value,boundary) ((value)/(boundary)*(boundary))
|
||||||
|
@ -153,184 +151,21 @@ static void Copy_PinInfo(PIN_INFO * pDest, const PIN_INFO * pSrc)
|
||||||
pDest->pFilter = pSrc->pFilter;
|
pDest->pFilter = pSrc->pFilter;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*** IPin implementation for an input pin ***/
|
|
||||||
|
|
||||||
HRESULT WINAPI InputPin_QueryInterface(IPin * iface, REFIID riid, LPVOID * ppv)
|
|
||||||
{
|
|
||||||
InputPin *This = (InputPin *)iface;
|
|
||||||
|
|
||||||
TRACE("(%p)->(%s, %p)\n", iface, qzdebugstr_guid(riid), ppv);
|
|
||||||
|
|
||||||
*ppv = NULL;
|
|
||||||
|
|
||||||
if (IsEqualIID(riid, &IID_IUnknown))
|
|
||||||
*ppv = iface;
|
|
||||||
else if (IsEqualIID(riid, &IID_IPin))
|
|
||||||
*ppv = iface;
|
|
||||||
else if (IsEqualIID(riid, &IID_IMemInputPin))
|
|
||||||
*ppv = &This->lpVtblMemInput;
|
|
||||||
else if (IsEqualIID(riid, &IID_IMediaSeeking))
|
|
||||||
{
|
|
||||||
return IBaseFilter_QueryInterface(This->pin.pinInfo.pFilter, &IID_IMediaSeeking, ppv);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (*ppv)
|
|
||||||
{
|
|
||||||
IUnknown_AddRef((IUnknown *)(*ppv));
|
|
||||||
return S_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
FIXME("No interface for %s!\n", qzdebugstr_guid(riid));
|
|
||||||
|
|
||||||
return E_NOINTERFACE;
|
|
||||||
}
|
|
||||||
|
|
||||||
ULONG WINAPI InputPin_Release(IPin * iface)
|
|
||||||
{
|
|
||||||
InputPin *This = (InputPin *)iface;
|
|
||||||
ULONG refCount = InterlockedDecrement(&This->pin.refCount);
|
|
||||||
|
|
||||||
TRACE("(%p)->() Release from %d\n", iface, refCount + 1);
|
|
||||||
|
|
||||||
if (!refCount)
|
|
||||||
{
|
|
||||||
FreeMediaType(&This->pin.mtCurrent);
|
|
||||||
if (This->pAllocator)
|
|
||||||
IMemAllocator_Release(This->pAllocator);
|
|
||||||
This->pAllocator = NULL;
|
|
||||||
This->pin.lpVtbl = NULL;
|
|
||||||
CoTaskMemFree(This);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
return refCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
HRESULT WINAPI InputPin_Connect(IPin * iface, IPin * pConnector, const AM_MEDIA_TYPE * pmt)
|
|
||||||
{
|
|
||||||
ERR("Outgoing connection on an input pin! (%p, %p)\n", pConnector, pmt);
|
|
||||||
|
|
||||||
return E_UNEXPECTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
HRESULT WINAPI InputPin_ReceiveConnection(IPin * iface, IPin * pReceivePin, const AM_MEDIA_TYPE * pmt)
|
|
||||||
{
|
|
||||||
InputPin *This = (InputPin *)iface;
|
|
||||||
PIN_DIRECTION pindirReceive;
|
|
||||||
HRESULT hr = S_OK;
|
|
||||||
|
|
||||||
TRACE("(%p, %p)\n", pReceivePin, pmt);
|
|
||||||
dump_AM_MEDIA_TYPE(pmt);
|
|
||||||
|
|
||||||
EnterCriticalSection(This->pin.pCritSec);
|
|
||||||
{
|
|
||||||
if (This->pin.pConnectedTo)
|
|
||||||
hr = VFW_E_ALREADY_CONNECTED;
|
|
||||||
|
|
||||||
if (SUCCEEDED(hr) && This->fnQueryAccept(This->pUserData, pmt) != S_OK)
|
|
||||||
hr = VFW_E_TYPE_NOT_ACCEPTED; /* FIXME: shouldn't we just map common errors onto
|
|
||||||
* VFW_E_TYPE_NOT_ACCEPTED and pass the value on otherwise? */
|
|
||||||
|
|
||||||
if (SUCCEEDED(hr))
|
|
||||||
{
|
|
||||||
IPin_QueryDirection(pReceivePin, &pindirReceive);
|
|
||||||
|
|
||||||
if (pindirReceive != PINDIR_OUTPUT)
|
|
||||||
{
|
|
||||||
ERR("Can't connect from non-output pin\n");
|
|
||||||
hr = VFW_E_INVALID_DIRECTION;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (SUCCEEDED(hr))
|
|
||||||
{
|
|
||||||
CopyMediaType(&This->pin.mtCurrent, pmt);
|
|
||||||
This->pin.pConnectedTo = pReceivePin;
|
|
||||||
IPin_AddRef(pReceivePin);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
LeaveCriticalSection(This->pin.pCritSec);
|
|
||||||
|
|
||||||
return hr;
|
|
||||||
}
|
|
||||||
|
|
||||||
static HRESULT deliver_endofstream(IPin* pin, LPVOID unused)
|
static HRESULT deliver_endofstream(IPin* pin, LPVOID unused)
|
||||||
{
|
{
|
||||||
return IPin_EndOfStream( pin );
|
return IPin_EndOfStream( pin );
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT WINAPI InputPin_QueryAccept(IPin * iface, const AM_MEDIA_TYPE * pmt)
|
|
||||||
{
|
|
||||||
InputPin *This = (InputPin *)iface;
|
|
||||||
|
|
||||||
TRACE("(%p/%p)->(%p)\n", This, iface, pmt);
|
|
||||||
|
|
||||||
return (This->fnQueryAccept(This->pUserData, pmt) == S_OK ? S_OK : S_FALSE);
|
|
||||||
}
|
|
||||||
|
|
||||||
HRESULT WINAPI InputPin_EndOfStream(IPin * iface)
|
|
||||||
{
|
|
||||||
HRESULT hr = S_OK;
|
|
||||||
InputPin *This = (InputPin *)iface;
|
|
||||||
|
|
||||||
TRACE("(%p)\n", This);
|
|
||||||
|
|
||||||
EnterCriticalSection(This->pin.pCritSec);
|
|
||||||
if (This->flushing)
|
|
||||||
hr = S_FALSE;
|
|
||||||
else
|
|
||||||
This->end_of_stream = 1;
|
|
||||||
LeaveCriticalSection(This->pin.pCritSec);
|
|
||||||
|
|
||||||
if (hr == S_OK)
|
|
||||||
hr = SendFurther( iface, deliver_endofstream, NULL, NULL );
|
|
||||||
return hr;
|
|
||||||
}
|
|
||||||
|
|
||||||
static HRESULT deliver_beginflush(IPin* pin, LPVOID unused)
|
static HRESULT deliver_beginflush(IPin* pin, LPVOID unused)
|
||||||
{
|
{
|
||||||
return IPin_BeginFlush( pin );
|
return IPin_BeginFlush( pin );
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT WINAPI InputPin_BeginFlush(IPin * iface)
|
|
||||||
{
|
|
||||||
InputPin *This = (InputPin *)iface;
|
|
||||||
HRESULT hr;
|
|
||||||
TRACE("() semi-stub\n");
|
|
||||||
|
|
||||||
EnterCriticalSection(This->pin.pCritSec);
|
|
||||||
This->flushing = 1;
|
|
||||||
|
|
||||||
if (This->fnCleanProc)
|
|
||||||
This->fnCleanProc(This->pUserData);
|
|
||||||
|
|
||||||
hr = SendFurther( iface, deliver_beginflush, NULL, NULL );
|
|
||||||
LeaveCriticalSection(This->pin.pCritSec);
|
|
||||||
|
|
||||||
return hr;
|
|
||||||
}
|
|
||||||
|
|
||||||
static HRESULT deliver_endflush(IPin* pin, LPVOID unused)
|
static HRESULT deliver_endflush(IPin* pin, LPVOID unused)
|
||||||
{
|
{
|
||||||
return IPin_EndFlush( pin );
|
return IPin_EndFlush( pin );
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT WINAPI InputPin_EndFlush(IPin * iface)
|
|
||||||
{
|
|
||||||
InputPin *This = (InputPin *)iface;
|
|
||||||
HRESULT hr;
|
|
||||||
TRACE("(%p)\n", This);
|
|
||||||
|
|
||||||
EnterCriticalSection(This->pin.pCritSec);
|
|
||||||
This->flushing = This->end_of_stream = 0;
|
|
||||||
|
|
||||||
hr = SendFurther( iface, deliver_endflush, NULL, NULL );
|
|
||||||
LeaveCriticalSection(This->pin.pCritSec);
|
|
||||||
|
|
||||||
return hr;
|
|
||||||
}
|
|
||||||
|
|
||||||
typedef struct newsegmentargs
|
typedef struct newsegmentargs
|
||||||
{
|
{
|
||||||
REFERENCE_TIME tStart, tStop;
|
REFERENCE_TIME tStart, tStop;
|
||||||
|
@ -343,172 +178,6 @@ static HRESULT deliver_newsegment(IPin *pin, LPVOID data)
|
||||||
return IPin_NewSegment(pin, args->tStart, args->tStop, args->rate);
|
return IPin_NewSegment(pin, args->tStart, args->tStop, args->rate);
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT WINAPI InputPin_NewSegment(IPin * iface, REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate)
|
|
||||||
{
|
|
||||||
InputPin *This = (InputPin *)iface;
|
|
||||||
newsegmentargs args;
|
|
||||||
|
|
||||||
TRACE("(%x%08x, %x%08x, %e)\n", (ULONG)(tStart >> 32), (ULONG)tStart, (ULONG)(tStop >> 32), (ULONG)tStop, dRate);
|
|
||||||
|
|
||||||
args.tStart = This->tStart = tStart;
|
|
||||||
args.tStop = This->tStop = tStop;
|
|
||||||
args.rate = This->dRate = dRate;
|
|
||||||
|
|
||||||
return SendFurther( iface, deliver_newsegment, &args, NULL );
|
|
||||||
}
|
|
||||||
|
|
||||||
static const IPinVtbl InputPin_Vtbl =
|
|
||||||
{
|
|
||||||
InputPin_QueryInterface,
|
|
||||||
BasePinImpl_AddRef,
|
|
||||||
InputPin_Release,
|
|
||||||
InputPin_Connect,
|
|
||||||
InputPin_ReceiveConnection,
|
|
||||||
BasePinImpl_Disconnect,
|
|
||||||
BasePinImpl_ConnectedTo,
|
|
||||||
BasePinImpl_ConnectionMediaType,
|
|
||||||
BasePinImpl_QueryPinInfo,
|
|
||||||
BasePinImpl_QueryDirection,
|
|
||||||
BasePinImpl_QueryId,
|
|
||||||
InputPin_QueryAccept,
|
|
||||||
BasePinImpl_EnumMediaTypes,
|
|
||||||
BasePinImpl_QueryInternalConnections,
|
|
||||||
InputPin_EndOfStream,
|
|
||||||
InputPin_BeginFlush,
|
|
||||||
InputPin_EndFlush,
|
|
||||||
InputPin_NewSegment
|
|
||||||
};
|
|
||||||
|
|
||||||
/*** IMemInputPin implementation ***/
|
|
||||||
|
|
||||||
static inline InputPin *impl_from_IMemInputPin( IMemInputPin *iface )
|
|
||||||
{
|
|
||||||
return (InputPin *)((char*)iface - FIELD_OFFSET(InputPin, lpVtblMemInput));
|
|
||||||
}
|
|
||||||
|
|
||||||
static HRESULT WINAPI MemInputPin_QueryInterface(IMemInputPin * iface, REFIID riid, LPVOID * ppv)
|
|
||||||
{
|
|
||||||
InputPin *This = impl_from_IMemInputPin(iface);
|
|
||||||
|
|
||||||
return IPin_QueryInterface((IPin *)&This->pin, riid, ppv);
|
|
||||||
}
|
|
||||||
|
|
||||||
static ULONG WINAPI MemInputPin_AddRef(IMemInputPin * iface)
|
|
||||||
{
|
|
||||||
InputPin *This = impl_from_IMemInputPin(iface);
|
|
||||||
|
|
||||||
return IPin_AddRef((IPin *)&This->pin);
|
|
||||||
}
|
|
||||||
|
|
||||||
static ULONG WINAPI MemInputPin_Release(IMemInputPin * iface)
|
|
||||||
{
|
|
||||||
InputPin *This = impl_from_IMemInputPin(iface);
|
|
||||||
|
|
||||||
return IPin_Release((IPin *)&This->pin);
|
|
||||||
}
|
|
||||||
|
|
||||||
static HRESULT WINAPI MemInputPin_GetAllocator(IMemInputPin * iface, IMemAllocator ** ppAllocator)
|
|
||||||
{
|
|
||||||
InputPin *This = impl_from_IMemInputPin(iface);
|
|
||||||
|
|
||||||
TRACE("(%p/%p)->(%p)\n", This, iface, ppAllocator);
|
|
||||||
|
|
||||||
*ppAllocator = This->pAllocator;
|
|
||||||
if (*ppAllocator)
|
|
||||||
IMemAllocator_AddRef(*ppAllocator);
|
|
||||||
|
|
||||||
return *ppAllocator ? S_OK : VFW_E_NO_ALLOCATOR;
|
|
||||||
}
|
|
||||||
|
|
||||||
static HRESULT WINAPI MemInputPin_NotifyAllocator(IMemInputPin * iface, IMemAllocator * pAllocator, BOOL bReadOnly)
|
|
||||||
{
|
|
||||||
InputPin *This = impl_from_IMemInputPin(iface);
|
|
||||||
|
|
||||||
TRACE("(%p/%p)->(%p, %d)\n", This, iface, pAllocator, bReadOnly);
|
|
||||||
|
|
||||||
if (bReadOnly)
|
|
||||||
FIXME("Read only flag not handled yet!\n");
|
|
||||||
|
|
||||||
/* FIXME: Should we release the allocator on disconnection? */
|
|
||||||
if (!pAllocator)
|
|
||||||
{
|
|
||||||
WARN("Null allocator\n");
|
|
||||||
return E_POINTER;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (This->preferred_allocator && pAllocator != This->preferred_allocator)
|
|
||||||
return E_FAIL;
|
|
||||||
|
|
||||||
if (This->pAllocator)
|
|
||||||
IMemAllocator_Release(This->pAllocator);
|
|
||||||
This->pAllocator = pAllocator;
|
|
||||||
if (This->pAllocator)
|
|
||||||
IMemAllocator_AddRef(This->pAllocator);
|
|
||||||
|
|
||||||
return S_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
static HRESULT WINAPI MemInputPin_GetAllocatorRequirements(IMemInputPin * iface, ALLOCATOR_PROPERTIES * pProps)
|
|
||||||
{
|
|
||||||
InputPin *This = impl_from_IMemInputPin(iface);
|
|
||||||
|
|
||||||
TRACE("(%p/%p)->(%p)\n", This, iface, pProps);
|
|
||||||
|
|
||||||
/* override this method if you have any specific requirements */
|
|
||||||
|
|
||||||
return E_NOTIMPL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static HRESULT WINAPI MemInputPin_Receive(IMemInputPin * iface, IMediaSample * pSample)
|
|
||||||
{
|
|
||||||
InputPin *This = impl_from_IMemInputPin(iface);
|
|
||||||
HRESULT hr;
|
|
||||||
|
|
||||||
/* this trace commented out for performance reasons */
|
|
||||||
/*TRACE("(%p/%p)->(%p)\n", This, iface, pSample);*/
|
|
||||||
hr = This->fnSampleProc(This->pUserData, pSample);
|
|
||||||
return hr;
|
|
||||||
}
|
|
||||||
|
|
||||||
static HRESULT WINAPI MemInputPin_ReceiveMultiple(IMemInputPin * iface, IMediaSample ** pSamples, LONG nSamples, LONG *nSamplesProcessed)
|
|
||||||
{
|
|
||||||
HRESULT hr = S_OK;
|
|
||||||
InputPin *This = impl_from_IMemInputPin(iface);
|
|
||||||
|
|
||||||
TRACE("(%p/%p)->(%p, %d, %p)\n", This, iface, pSamples, nSamples, nSamplesProcessed);
|
|
||||||
|
|
||||||
for (*nSamplesProcessed = 0; *nSamplesProcessed < nSamples; (*nSamplesProcessed)++)
|
|
||||||
{
|
|
||||||
hr = IMemInputPin_Receive(iface, pSamples[*nSamplesProcessed]);
|
|
||||||
if (hr != S_OK)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return hr;
|
|
||||||
}
|
|
||||||
|
|
||||||
static HRESULT WINAPI MemInputPin_ReceiveCanBlock(IMemInputPin * iface)
|
|
||||||
{
|
|
||||||
InputPin *This = impl_from_IMemInputPin(iface);
|
|
||||||
|
|
||||||
TRACE("(%p/%p)->()\n", This, iface);
|
|
||||||
|
|
||||||
return S_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
static const IMemInputPinVtbl MemInputPin_Vtbl =
|
|
||||||
{
|
|
||||||
MemInputPin_QueryInterface,
|
|
||||||
MemInputPin_AddRef,
|
|
||||||
MemInputPin_Release,
|
|
||||||
MemInputPin_GetAllocator,
|
|
||||||
MemInputPin_NotifyAllocator,
|
|
||||||
MemInputPin_GetAllocatorRequirements,
|
|
||||||
MemInputPin_Receive,
|
|
||||||
MemInputPin_ReceiveMultiple,
|
|
||||||
MemInputPin_ReceiveCanBlock
|
|
||||||
};
|
|
||||||
|
|
||||||
/*** PullPin implementation ***/
|
/*** PullPin implementation ***/
|
||||||
|
|
||||||
static HRESULT PullPin_Init(const IPinVtbl *PullPin_Vtbl, const PIN_INFO * pPinInfo, SAMPLEPROC_PULL pSampleProc, LPVOID pUserData,
|
static HRESULT PullPin_Init(const IPinVtbl *PullPin_Vtbl, const PIN_INFO * pPinInfo, SAMPLEPROC_PULL pSampleProc, LPVOID pUserData,
|
||||||
|
@ -1119,7 +788,7 @@ static const IPinVtbl PullPin_Vtbl =
|
||||||
PullPin_QueryInterface,
|
PullPin_QueryInterface,
|
||||||
BasePinImpl_AddRef,
|
BasePinImpl_AddRef,
|
||||||
PullPin_Release,
|
PullPin_Release,
|
||||||
InputPin_Connect,
|
BaseInputPinImpl_Connect,
|
||||||
PullPin_ReceiveConnection,
|
PullPin_ReceiveConnection,
|
||||||
PullPin_Disconnect,
|
PullPin_Disconnect,
|
||||||
BasePinImpl_ConnectedTo,
|
BasePinImpl_ConnectedTo,
|
||||||
|
@ -1135,62 +804,3 @@ static const IPinVtbl PullPin_Vtbl =
|
||||||
PullPin_EndFlush,
|
PullPin_EndFlush,
|
||||||
PullPin_NewSegment
|
PullPin_NewSegment
|
||||||
};
|
};
|
||||||
|
|
||||||
/*** The Construct functions ***/
|
|
||||||
|
|
||||||
static HRESULT InputPin_Init(const IPinVtbl *InputPin_Vtbl, const PIN_INFO * pPinInfo, SAMPLEPROC_PUSH pSampleProc, LPVOID pUserData,
|
|
||||||
QUERYACCEPTPROC pQueryAccept, CLEANUPPROC pCleanUp, LPCRITICAL_SECTION pCritSec, IMemAllocator *allocator, InputPin * pPinImpl)
|
|
||||||
{
|
|
||||||
TRACE("\n");
|
|
||||||
|
|
||||||
/* Common attributes */
|
|
||||||
pPinImpl->pin.refCount = 1;
|
|
||||||
pPinImpl->pin.pConnectedTo = NULL;
|
|
||||||
pPinImpl->pin.pCritSec = pCritSec;
|
|
||||||
Copy_PinInfo(&pPinImpl->pin.pinInfo, pPinInfo);
|
|
||||||
ZeroMemory(&pPinImpl->pin.mtCurrent, sizeof(AM_MEDIA_TYPE));
|
|
||||||
|
|
||||||
/* Input pin attributes */
|
|
||||||
pPinImpl->pUserData = pUserData;
|
|
||||||
pPinImpl->fnQueryAccept = pQueryAccept;
|
|
||||||
pPinImpl->fnSampleProc = pSampleProc;
|
|
||||||
pPinImpl->fnCleanProc = pCleanUp;
|
|
||||||
pPinImpl->pAllocator = pPinImpl->preferred_allocator = allocator;
|
|
||||||
if (pPinImpl->preferred_allocator)
|
|
||||||
IMemAllocator_AddRef(pPinImpl->preferred_allocator);
|
|
||||||
pPinImpl->tStart = 0;
|
|
||||||
pPinImpl->tStop = 0;
|
|
||||||
pPinImpl->dRate = 1.0;
|
|
||||||
pPinImpl->pin.lpVtbl = InputPin_Vtbl;
|
|
||||||
pPinImpl->lpVtblMemInput = &MemInputPin_Vtbl;
|
|
||||||
pPinImpl->flushing = pPinImpl->end_of_stream = 0;
|
|
||||||
|
|
||||||
return S_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
HRESULT InputPin_Construct(const IPinVtbl *InputPin_Vtbl, const PIN_INFO * pPinInfo, SAMPLEPROC_PUSH pSampleProc, LPVOID pUserData, QUERYACCEPTPROC pQueryAccept, CLEANUPPROC pCleanUp, LPCRITICAL_SECTION pCritSec, IMemAllocator *allocator, IPin ** ppPin)
|
|
||||||
{
|
|
||||||
InputPin * pPinImpl;
|
|
||||||
|
|
||||||
*ppPin = NULL;
|
|
||||||
|
|
||||||
if (pPinInfo->dir != PINDIR_INPUT)
|
|
||||||
{
|
|
||||||
ERR("Pin direction(%x) != PINDIR_INPUT\n", pPinInfo->dir);
|
|
||||||
return E_INVALIDARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
pPinImpl = CoTaskMemAlloc(sizeof(*pPinImpl));
|
|
||||||
|
|
||||||
if (!pPinImpl)
|
|
||||||
return E_OUTOFMEMORY;
|
|
||||||
|
|
||||||
if (SUCCEEDED(InputPin_Init(InputPin_Vtbl, pPinInfo, pSampleProc, pUserData, pQueryAccept, pCleanUp, pCritSec, allocator, pPinImpl)))
|
|
||||||
{
|
|
||||||
*ppPin = (IPin *)pPinImpl;
|
|
||||||
return S_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
CoTaskMemFree(pPinImpl);
|
|
||||||
return E_FAIL;
|
|
||||||
}
|
|
||||||
|
|
|
@ -24,7 +24,6 @@
|
||||||
* Cookie is the cookie that was set when requesting the buffer, if you don't
|
* Cookie is the cookie that was set when requesting the buffer, if you don't
|
||||||
* implement custom requesting, you can safely ignore this
|
* implement custom requesting, you can safely ignore this
|
||||||
*/
|
*/
|
||||||
typedef HRESULT (* SAMPLEPROC_PUSH)(LPVOID userdata, IMediaSample * pSample);
|
|
||||||
typedef HRESULT (* SAMPLEPROC_PULL)(LPVOID userdata, IMediaSample * pSample, DWORD_PTR cookie);
|
typedef HRESULT (* SAMPLEPROC_PULL)(LPVOID userdata, IMediaSample * pSample, DWORD_PTR cookie);
|
||||||
|
|
||||||
/* This function will determine whether a type is supported or not.
|
/* This function will determine whether a type is supported or not.
|
||||||
|
@ -66,24 +65,6 @@ typedef HRESULT (* STOPPROCESSPROC) (LPVOID userdata);
|
||||||
#define ALIGNDOWN(value,boundary) ((value)/(boundary)*(boundary))
|
#define ALIGNDOWN(value,boundary) ((value)/(boundary)*(boundary))
|
||||||
#define ALIGNUP(value,boundary) (ALIGNDOWN((value)+(boundary)-1, (boundary)))
|
#define ALIGNUP(value,boundary) (ALIGNDOWN((value)+(boundary)-1, (boundary)))
|
||||||
|
|
||||||
typedef struct InputPin
|
|
||||||
{
|
|
||||||
/* inheritance C style! */
|
|
||||||
BasePin pin;
|
|
||||||
LPVOID pUserData;
|
|
||||||
|
|
||||||
const IMemInputPinVtbl * lpVtblMemInput;
|
|
||||||
IMemAllocator * pAllocator;
|
|
||||||
QUERYACCEPTPROC fnQueryAccept;
|
|
||||||
SAMPLEPROC_PUSH fnSampleProc;
|
|
||||||
CLEANUPPROC fnCleanProc;
|
|
||||||
REFERENCE_TIME tStart;
|
|
||||||
REFERENCE_TIME tStop;
|
|
||||||
double dRate;
|
|
||||||
BOOL flushing, end_of_stream;
|
|
||||||
IMemAllocator *preferred_allocator;
|
|
||||||
} InputPin;
|
|
||||||
|
|
||||||
typedef struct PullPin
|
typedef struct PullPin
|
||||||
{
|
{
|
||||||
/* inheritance C style! */
|
/* inheritance C style! */
|
||||||
|
@ -120,23 +101,11 @@ typedef struct PullPin
|
||||||
#define Req_Pause 3
|
#define Req_Pause 3
|
||||||
|
|
||||||
/*** Constructors ***/
|
/*** Constructors ***/
|
||||||
HRESULT InputPin_Construct(const IPinVtbl *InputPin_Vtbl, const PIN_INFO * pPinInfo, SAMPLEPROC_PUSH pSampleProc, LPVOID pUserData, QUERYACCEPTPROC pQueryAccept, CLEANUPPROC pCleanUp, LPCRITICAL_SECTION pCritSec, IMemAllocator *, IPin ** ppPin);
|
|
||||||
HRESULT PullPin_Construct(const IPinVtbl *PullPin_Vtbl, const PIN_INFO * pPinInfo, SAMPLEPROC_PULL pSampleProc, LPVOID pUserData, QUERYACCEPTPROC pQueryAccept, CLEANUPPROC pCleanUp, STOPPROCESSPROC, REQUESTPROC pCustomRequest, LPCRITICAL_SECTION pCritSec, IPin ** ppPin);
|
HRESULT PullPin_Construct(const IPinVtbl *PullPin_Vtbl, const PIN_INFO * pPinInfo, SAMPLEPROC_PULL pSampleProc, LPVOID pUserData, QUERYACCEPTPROC pQueryAccept, CLEANUPPROC pCleanUp, STOPPROCESSPROC, REQUESTPROC pCustomRequest, LPCRITICAL_SECTION pCritSec, IPin ** ppPin);
|
||||||
|
|
||||||
/**************************/
|
/**************************/
|
||||||
/*** Pin Implementation ***/
|
/*** Pin Implementation ***/
|
||||||
|
|
||||||
/* Input Pin */
|
|
||||||
HRESULT WINAPI InputPin_QueryInterface(IPin * iface, REFIID riid, LPVOID * ppv);
|
|
||||||
ULONG WINAPI InputPin_Release(IPin * iface);
|
|
||||||
HRESULT WINAPI InputPin_Connect(IPin * iface, IPin * pConnector, const AM_MEDIA_TYPE * pmt);
|
|
||||||
HRESULT WINAPI InputPin_ReceiveConnection(IPin * iface, IPin * pReceivePin, const AM_MEDIA_TYPE * pmt);
|
|
||||||
HRESULT WINAPI InputPin_QueryAccept(IPin * iface, const AM_MEDIA_TYPE * pmt);
|
|
||||||
HRESULT WINAPI InputPin_EndOfStream(IPin * iface);
|
|
||||||
HRESULT WINAPI InputPin_BeginFlush(IPin * iface);
|
|
||||||
HRESULT WINAPI InputPin_EndFlush(IPin * iface);
|
|
||||||
HRESULT WINAPI InputPin_NewSegment(IPin * iface, REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate);
|
|
||||||
|
|
||||||
/* Pull Pin */
|
/* Pull Pin */
|
||||||
HRESULT WINAPI PullPin_ReceiveConnection(IPin * iface, IPin * pReceivePin, const AM_MEDIA_TYPE * pmt);
|
HRESULT WINAPI PullPin_ReceiveConnection(IPin * iface, IPin * pReceivePin, const AM_MEDIA_TYPE * pmt);
|
||||||
HRESULT WINAPI PullPin_Disconnect(IPin * iface);
|
HRESULT WINAPI PullPin_Disconnect(IPin * iface);
|
||||||
|
|
|
@ -47,7 +47,7 @@ static const IBaseFilterVtbl TransformFilter_Vtbl;
|
||||||
static const IPinVtbl TransformFilter_InputPin_Vtbl;
|
static const IPinVtbl TransformFilter_InputPin_Vtbl;
|
||||||
static const IPinVtbl TransformFilter_OutputPin_Vtbl;
|
static const IPinVtbl TransformFilter_OutputPin_Vtbl;
|
||||||
|
|
||||||
static HRESULT TransformFilter_Input_QueryAccept(LPVOID iface, const AM_MEDIA_TYPE * pmt)
|
static HRESULT WINAPI TransformFilter_Input_CheckMediaType(IPin *iface, const AM_MEDIA_TYPE * pmt)
|
||||||
{
|
{
|
||||||
TransformFilterImpl* This = (TransformFilterImpl *)((BasePin *)iface)->pinInfo.pFilter;
|
TransformFilterImpl* This = (TransformFilterImpl *)((BasePin *)iface)->pinInfo.pFilter;
|
||||||
TRACE("%p\n", iface);
|
TRACE("%p\n", iface);
|
||||||
|
@ -105,7 +105,7 @@ HRESULT TransformFilter_Create(TransformFilterImpl* pTransformFilter, const CLSI
|
||||||
piOutput.pFilter = (IBaseFilter *)pTransformFilter;
|
piOutput.pFilter = (IBaseFilter *)pTransformFilter;
|
||||||
lstrcpynW(piOutput.achName, wcsOutputPinName, sizeof(piOutput.achName) / sizeof(piOutput.achName[0]));
|
lstrcpynW(piOutput.achName, wcsOutputPinName, sizeof(piOutput.achName) / sizeof(piOutput.achName[0]));
|
||||||
|
|
||||||
hr = InputPin_Construct(&TransformFilter_InputPin_Vtbl, &piInput, (SAMPLEPROC_PUSH)pFuncsTable->pfnProcessSampleData, NULL, TransformFilter_Input_QueryAccept, NULL, &pTransformFilter->csFilter, NULL, &pTransformFilter->ppPins[0]);
|
hr = BaseInputPin_Construct(&TransformFilter_InputPin_Vtbl, &piInput, TransformFilter_Input_CheckMediaType, pFuncsTable->pfnProcessSampleData, &pTransformFilter->csFilter, NULL, &pTransformFilter->ppPins[0]);
|
||||||
|
|
||||||
if (SUCCEEDED(hr))
|
if (SUCCEEDED(hr))
|
||||||
{
|
{
|
||||||
|
@ -115,8 +115,6 @@ HRESULT TransformFilter_Create(TransformFilterImpl* pTransformFilter, const CLSI
|
||||||
props.cbBuffer = 0; /* Will be updated at connection time */
|
props.cbBuffer = 0; /* Will be updated at connection time */
|
||||||
props.cBuffers = 1;
|
props.cBuffers = 1;
|
||||||
|
|
||||||
((InputPin *)pTransformFilter->ppPins[0])->pUserData = pTransformFilter->ppPins[0];
|
|
||||||
|
|
||||||
hr = BaseOutputPin_Construct(&TransformFilter_OutputPin_Vtbl, sizeof(BaseOutputPin), &piOutput, &props, NULL, &pTransformFilter->csFilter, &pTransformFilter->ppPins[1]);
|
hr = BaseOutputPin_Construct(&TransformFilter_OutputPin_Vtbl, sizeof(BaseOutputPin), &piOutput, &props, NULL, &pTransformFilter->csFilter, &pTransformFilter->ppPins[1]);
|
||||||
|
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
|
@ -291,7 +289,7 @@ static HRESULT WINAPI TransformFilter_Run(IBaseFilter * iface, REFERENCE_TIME tS
|
||||||
{
|
{
|
||||||
if (This->state == State_Stopped)
|
if (This->state == State_Stopped)
|
||||||
{
|
{
|
||||||
((InputPin *)This->ppPins[0])->end_of_stream = 0;
|
((BaseInputPin *)This->ppPins[0])->end_of_stream = 0;
|
||||||
if (This->pFuncsTable->pfnProcessBegin)
|
if (This->pFuncsTable->pfnProcessBegin)
|
||||||
hr = This->pFuncsTable->pfnProcessBegin(This);
|
hr = This->pFuncsTable->pfnProcessBegin(This);
|
||||||
if (SUCCEEDED(hr))
|
if (SUCCEEDED(hr))
|
||||||
|
@ -467,7 +465,7 @@ static const IBaseFilterVtbl TransformFilter_Vtbl =
|
||||||
|
|
||||||
static HRESULT WINAPI TransformFilter_InputPin_EndOfStream(IPin * iface)
|
static HRESULT WINAPI TransformFilter_InputPin_EndOfStream(IPin * iface)
|
||||||
{
|
{
|
||||||
InputPin* This = (InputPin*) iface;
|
BaseInputPin* This = (BaseInputPin*) iface;
|
||||||
TransformFilterImpl* pTransform;
|
TransformFilterImpl* pTransform;
|
||||||
IPin* ppin;
|
IPin* ppin;
|
||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
|
@ -493,7 +491,7 @@ static HRESULT WINAPI TransformFilter_InputPin_EndOfStream(IPin * iface)
|
||||||
|
|
||||||
static HRESULT WINAPI TransformFilter_InputPin_ReceiveConnection(IPin * iface, IPin * pReceivePin, const AM_MEDIA_TYPE * pmt)
|
static HRESULT WINAPI TransformFilter_InputPin_ReceiveConnection(IPin * iface, IPin * pReceivePin, const AM_MEDIA_TYPE * pmt)
|
||||||
{
|
{
|
||||||
InputPin* This = (InputPin*) iface;
|
BaseInputPin* This = (BaseInputPin*) iface;
|
||||||
TransformFilterImpl* pTransform;
|
TransformFilterImpl* pTransform;
|
||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
|
|
||||||
|
@ -504,7 +502,7 @@ static HRESULT WINAPI TransformFilter_InputPin_ReceiveConnection(IPin * iface, I
|
||||||
hr = pTransform->pFuncsTable->pfnConnectInput(This, pmt);
|
hr = pTransform->pFuncsTable->pfnConnectInput(This, pmt);
|
||||||
if (SUCCEEDED(hr))
|
if (SUCCEEDED(hr))
|
||||||
{
|
{
|
||||||
hr = InputPin_ReceiveConnection(iface, pReceivePin, pmt);
|
hr = BaseInputPinImpl_ReceiveConnection(iface, pReceivePin, pmt);
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
pTransform->pFuncsTable->pfnCleanup(This);
|
pTransform->pFuncsTable->pfnCleanup(This);
|
||||||
}
|
}
|
||||||
|
@ -514,7 +512,7 @@ static HRESULT WINAPI TransformFilter_InputPin_ReceiveConnection(IPin * iface, I
|
||||||
|
|
||||||
static HRESULT WINAPI TransformFilter_InputPin_Disconnect(IPin * iface)
|
static HRESULT WINAPI TransformFilter_InputPin_Disconnect(IPin * iface)
|
||||||
{
|
{
|
||||||
InputPin* This = (InputPin*) iface;
|
BaseInputPin* This = (BaseInputPin*) iface;
|
||||||
TransformFilterImpl* pTransform;
|
TransformFilterImpl* pTransform;
|
||||||
|
|
||||||
TRACE("(%p)->()\n", iface);
|
TRACE("(%p)->()\n", iface);
|
||||||
|
@ -527,7 +525,7 @@ static HRESULT WINAPI TransformFilter_InputPin_Disconnect(IPin * iface)
|
||||||
|
|
||||||
static HRESULT WINAPI TransformFilter_InputPin_BeginFlush(IPin * iface)
|
static HRESULT WINAPI TransformFilter_InputPin_BeginFlush(IPin * iface)
|
||||||
{
|
{
|
||||||
InputPin* This = (InputPin*) iface;
|
BaseInputPin* This = (BaseInputPin*) iface;
|
||||||
TransformFilterImpl* pTransform;
|
TransformFilterImpl* pTransform;
|
||||||
HRESULT hr = S_OK;
|
HRESULT hr = S_OK;
|
||||||
|
|
||||||
|
@ -538,14 +536,14 @@ static HRESULT WINAPI TransformFilter_InputPin_BeginFlush(IPin * iface)
|
||||||
if (pTransform->pFuncsTable->pfnBeginFlush)
|
if (pTransform->pFuncsTable->pfnBeginFlush)
|
||||||
hr = pTransform->pFuncsTable->pfnBeginFlush(This);
|
hr = pTransform->pFuncsTable->pfnBeginFlush(This);
|
||||||
if (SUCCEEDED(hr))
|
if (SUCCEEDED(hr))
|
||||||
hr = InputPin_BeginFlush(iface);
|
hr = BaseInputPinImpl_BeginFlush(iface);
|
||||||
LeaveCriticalSection(&pTransform->csFilter);
|
LeaveCriticalSection(&pTransform->csFilter);
|
||||||
return hr;
|
return hr;
|
||||||
}
|
}
|
||||||
|
|
||||||
static HRESULT WINAPI TransformFilter_InputPin_EndFlush(IPin * iface)
|
static HRESULT WINAPI TransformFilter_InputPin_EndFlush(IPin * iface)
|
||||||
{
|
{
|
||||||
InputPin* This = (InputPin*) iface;
|
BaseInputPin* This = (BaseInputPin*) iface;
|
||||||
TransformFilterImpl* pTransform;
|
TransformFilterImpl* pTransform;
|
||||||
HRESULT hr = S_OK;
|
HRESULT hr = S_OK;
|
||||||
|
|
||||||
|
@ -556,14 +554,14 @@ static HRESULT WINAPI TransformFilter_InputPin_EndFlush(IPin * iface)
|
||||||
if (pTransform->pFuncsTable->pfnEndFlush)
|
if (pTransform->pFuncsTable->pfnEndFlush)
|
||||||
hr = pTransform->pFuncsTable->pfnEndFlush(This);
|
hr = pTransform->pFuncsTable->pfnEndFlush(This);
|
||||||
if (SUCCEEDED(hr))
|
if (SUCCEEDED(hr))
|
||||||
hr = InputPin_EndFlush(iface);
|
hr = BaseInputPinImpl_EndFlush(iface);
|
||||||
LeaveCriticalSection(&pTransform->csFilter);
|
LeaveCriticalSection(&pTransform->csFilter);
|
||||||
return hr;
|
return hr;
|
||||||
}
|
}
|
||||||
|
|
||||||
static HRESULT WINAPI TransformFilter_InputPin_NewSegment(IPin * iface, REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate)
|
static HRESULT WINAPI TransformFilter_InputPin_NewSegment(IPin * iface, REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate)
|
||||||
{
|
{
|
||||||
InputPin* This = (InputPin*) iface;
|
BaseInputPin* This = (BaseInputPin*) iface;
|
||||||
TransformFilterImpl* pTransform;
|
TransformFilterImpl* pTransform;
|
||||||
HRESULT hr = S_OK;
|
HRESULT hr = S_OK;
|
||||||
|
|
||||||
|
@ -574,17 +572,17 @@ static HRESULT WINAPI TransformFilter_InputPin_NewSegment(IPin * iface, REFERENC
|
||||||
if (pTransform->pFuncsTable->pfnNewSegment)
|
if (pTransform->pFuncsTable->pfnNewSegment)
|
||||||
hr = pTransform->pFuncsTable->pfnNewSegment(This, tStart, tStop, dRate);
|
hr = pTransform->pFuncsTable->pfnNewSegment(This, tStart, tStop, dRate);
|
||||||
if (SUCCEEDED(hr))
|
if (SUCCEEDED(hr))
|
||||||
hr = InputPin_NewSegment(iface, tStart, tStop, dRate);
|
hr = BaseInputPinImpl_NewSegment(iface, tStart, tStop, dRate);
|
||||||
LeaveCriticalSection(&pTransform->csFilter);
|
LeaveCriticalSection(&pTransform->csFilter);
|
||||||
return hr;
|
return hr;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const IPinVtbl TransformFilter_InputPin_Vtbl =
|
static const IPinVtbl TransformFilter_InputPin_Vtbl =
|
||||||
{
|
{
|
||||||
InputPin_QueryInterface,
|
BaseInputPinImpl_QueryInterface,
|
||||||
BasePinImpl_AddRef,
|
BasePinImpl_AddRef,
|
||||||
InputPin_Release,
|
BaseInputPinImpl_Release,
|
||||||
InputPin_Connect,
|
BaseInputPinImpl_Connect,
|
||||||
TransformFilter_InputPin_ReceiveConnection,
|
TransformFilter_InputPin_ReceiveConnection,
|
||||||
TransformFilter_InputPin_Disconnect,
|
TransformFilter_InputPin_Disconnect,
|
||||||
BasePinImpl_ConnectedTo,
|
BasePinImpl_ConnectedTo,
|
||||||
|
@ -592,7 +590,7 @@ static const IPinVtbl TransformFilter_InputPin_Vtbl =
|
||||||
BasePinImpl_QueryPinInfo,
|
BasePinImpl_QueryPinInfo,
|
||||||
BasePinImpl_QueryDirection,
|
BasePinImpl_QueryDirection,
|
||||||
BasePinImpl_QueryId,
|
BasePinImpl_QueryId,
|
||||||
InputPin_QueryAccept,
|
BaseInputPinImpl_QueryAccept,
|
||||||
BasePinImpl_EnumMediaTypes,
|
BasePinImpl_EnumMediaTypes,
|
||||||
BasePinImpl_QueryInternalConnections,
|
BasePinImpl_QueryInternalConnections,
|
||||||
TransformFilter_InputPin_EndOfStream,
|
TransformFilter_InputPin_EndOfStream,
|
||||||
|
|
|
@ -24,15 +24,15 @@ typedef struct TransformFilterImpl TransformFilterImpl;
|
||||||
|
|
||||||
typedef struct TransformFuncsTable {
|
typedef struct TransformFuncsTable {
|
||||||
HRESULT (*pfnProcessBegin) (TransformFilterImpl *This);
|
HRESULT (*pfnProcessBegin) (TransformFilterImpl *This);
|
||||||
HRESULT (*pfnProcessSampleData) (InputPin *pin, IMediaSample *pSample);
|
BaseInputPin_Receive pfnProcessSampleData;
|
||||||
HRESULT (*pfnProcessEnd) (TransformFilterImpl *This);
|
HRESULT (*pfnProcessEnd) (TransformFilterImpl *This);
|
||||||
HRESULT (*pfnQueryConnect) (TransformFilterImpl *This, const AM_MEDIA_TYPE * pmt);
|
HRESULT (*pfnQueryConnect) (TransformFilterImpl *This, const AM_MEDIA_TYPE * pmt);
|
||||||
HRESULT (*pfnConnectInput) (InputPin *pin, const AM_MEDIA_TYPE * pmt);
|
HRESULT (*pfnConnectInput) (BaseInputPin *pin, const AM_MEDIA_TYPE * pmt);
|
||||||
HRESULT (*pfnCleanup) (InputPin *pin);
|
HRESULT (*pfnCleanup) (BaseInputPin *pin);
|
||||||
HRESULT (*pfnEndOfStream) (InputPin *pin);
|
HRESULT (*pfnEndOfStream) (BaseInputPin *pin);
|
||||||
HRESULT (*pfnBeginFlush) (InputPin *pin);
|
HRESULT (*pfnBeginFlush) (BaseInputPin *pin);
|
||||||
HRESULT (*pfnEndFlush) (InputPin *pin);
|
HRESULT (*pfnEndFlush) (BaseInputPin *pin);
|
||||||
HRESULT (*pfnNewSegment) (InputPin *pin, REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate);
|
HRESULT (*pfnNewSegment) (BaseInputPin *pin, REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate);
|
||||||
} TransformFuncsTable;
|
} TransformFuncsTable;
|
||||||
|
|
||||||
struct TransformFilterImpl
|
struct TransformFilterImpl
|
||||||
|
|
|
@ -68,7 +68,7 @@ typedef struct VideoRendererImpl
|
||||||
IReferenceClock * pClock;
|
IReferenceClock * pClock;
|
||||||
FILTER_INFO filterInfo;
|
FILTER_INFO filterInfo;
|
||||||
|
|
||||||
InputPin *pInputPin;
|
BaseInputPin *pInputPin;
|
||||||
|
|
||||||
BOOL init;
|
BOOL init;
|
||||||
HANDLE hThread;
|
HANDLE hThread;
|
||||||
|
@ -354,9 +354,10 @@ static DWORD VideoRenderer_SendSampleData(VideoRendererImpl* This, LPBYTE data,
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static HRESULT VideoRenderer_Sample(LPVOID iface, IMediaSample * pSample)
|
static HRESULT WINAPI VideoRenderer_Receive(IPin* iface, IMediaSample * pSample)
|
||||||
{
|
{
|
||||||
VideoRendererImpl *This = iface;
|
BaseInputPin* pin = (BaseInputPin*)iface;
|
||||||
|
VideoRendererImpl *This = (VideoRendererImpl *)pin->pin.pinInfo.pFilter;
|
||||||
LPBYTE pbSrcStream = NULL;
|
LPBYTE pbSrcStream = NULL;
|
||||||
LONG cbSrcStream = 0;
|
LONG cbSrcStream = 0;
|
||||||
REFERENCE_TIME tStart, tStop;
|
REFERENCE_TIME tStart, tStop;
|
||||||
|
@ -491,8 +492,11 @@ static HRESULT VideoRenderer_Sample(LPVOID iface, IMediaSample * pSample)
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static HRESULT VideoRenderer_QueryAccept(LPVOID iface, const AM_MEDIA_TYPE * pmt)
|
static HRESULT WINAPI VideoRenderer_CheckMediaType(IPin *iface, const AM_MEDIA_TYPE * pmt)
|
||||||
{
|
{
|
||||||
|
BaseInputPin* pin = (BaseInputPin*)iface;
|
||||||
|
VideoRendererImpl *This = (VideoRendererImpl *)pin->pin.pinInfo.pFilter;
|
||||||
|
|
||||||
if (!IsEqualIID(&pmt->majortype, &MEDIATYPE_Video))
|
if (!IsEqualIID(&pmt->majortype, &MEDIATYPE_Video))
|
||||||
return S_FALSE;
|
return S_FALSE;
|
||||||
|
|
||||||
|
@ -501,7 +505,6 @@ static HRESULT VideoRenderer_QueryAccept(LPVOID iface, const AM_MEDIA_TYPE * pmt
|
||||||
IsEqualIID(&pmt->subtype, &MEDIASUBTYPE_RGB565) ||
|
IsEqualIID(&pmt->subtype, &MEDIASUBTYPE_RGB565) ||
|
||||||
IsEqualIID(&pmt->subtype, &MEDIASUBTYPE_RGB8))
|
IsEqualIID(&pmt->subtype, &MEDIASUBTYPE_RGB8))
|
||||||
{
|
{
|
||||||
VideoRendererImpl* This = iface;
|
|
||||||
LONG height;
|
LONG height;
|
||||||
|
|
||||||
if (IsEqualIID(&pmt->formattype, &FORMAT_VideoInfo))
|
if (IsEqualIID(&pmt->formattype, &FORMAT_VideoInfo))
|
||||||
|
@ -580,7 +583,7 @@ HRESULT VideoRenderer_create(IUnknown * pUnkOuter, LPVOID * ppv)
|
||||||
piInput.pFilter = (IBaseFilter *)pVideoRenderer;
|
piInput.pFilter = (IBaseFilter *)pVideoRenderer;
|
||||||
lstrcpynW(piInput.achName, wcsInputPinName, sizeof(piInput.achName) / sizeof(piInput.achName[0]));
|
lstrcpynW(piInput.achName, wcsInputPinName, sizeof(piInput.achName) / sizeof(piInput.achName[0]));
|
||||||
|
|
||||||
hr = InputPin_Construct(&VideoRenderer_InputPin_Vtbl, &piInput, VideoRenderer_Sample, (LPVOID)pVideoRenderer, VideoRenderer_QueryAccept, NULL, &pVideoRenderer->csFilter, NULL, (IPin **)&pVideoRenderer->pInputPin);
|
hr = BaseInputPin_Construct(&VideoRenderer_InputPin_Vtbl, &piInput, VideoRenderer_CheckMediaType, VideoRenderer_Receive, &pVideoRenderer->csFilter, NULL, (IPin **)&pVideoRenderer->pInputPin);
|
||||||
|
|
||||||
if (SUCCEEDED(hr))
|
if (SUCCEEDED(hr))
|
||||||
{
|
{
|
||||||
|
@ -1010,7 +1013,7 @@ static const IBaseFilterVtbl VideoRenderer_Vtbl =
|
||||||
|
|
||||||
static HRESULT WINAPI VideoRenderer_InputPin_EndOfStream(IPin * iface)
|
static HRESULT WINAPI VideoRenderer_InputPin_EndOfStream(IPin * iface)
|
||||||
{
|
{
|
||||||
InputPin* This = (InputPin*)iface;
|
BaseInputPin* This = (BaseInputPin*)iface;
|
||||||
VideoRendererImpl *pFilter;
|
VideoRendererImpl *pFilter;
|
||||||
IMediaEventSink* pEventSink;
|
IMediaEventSink* pEventSink;
|
||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
|
@ -1031,7 +1034,7 @@ static HRESULT WINAPI VideoRenderer_InputPin_EndOfStream(IPin * iface)
|
||||||
|
|
||||||
static HRESULT WINAPI VideoRenderer_InputPin_BeginFlush(IPin * iface)
|
static HRESULT WINAPI VideoRenderer_InputPin_BeginFlush(IPin * iface)
|
||||||
{
|
{
|
||||||
InputPin* This = (InputPin*)iface;
|
BaseInputPin* This = (BaseInputPin*)iface;
|
||||||
VideoRendererImpl *pVideoRenderer = (VideoRendererImpl *)This->pin.pinInfo.pFilter;
|
VideoRendererImpl *pVideoRenderer = (VideoRendererImpl *)This->pin.pinInfo.pFilter;
|
||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
|
|
||||||
|
@ -1041,7 +1044,7 @@ static HRESULT WINAPI VideoRenderer_InputPin_BeginFlush(IPin * iface)
|
||||||
if (pVideoRenderer->state == State_Paused)
|
if (pVideoRenderer->state == State_Paused)
|
||||||
SetEvent(pVideoRenderer->blocked);
|
SetEvent(pVideoRenderer->blocked);
|
||||||
|
|
||||||
hr = InputPin_BeginFlush(iface);
|
hr = BaseInputPinImpl_BeginFlush(iface);
|
||||||
LeaveCriticalSection(This->pin.pCritSec);
|
LeaveCriticalSection(This->pin.pCritSec);
|
||||||
|
|
||||||
return hr;
|
return hr;
|
||||||
|
@ -1049,7 +1052,7 @@ static HRESULT WINAPI VideoRenderer_InputPin_BeginFlush(IPin * iface)
|
||||||
|
|
||||||
static HRESULT WINAPI VideoRenderer_InputPin_EndFlush(IPin * iface)
|
static HRESULT WINAPI VideoRenderer_InputPin_EndFlush(IPin * iface)
|
||||||
{
|
{
|
||||||
InputPin* This = (InputPin*)iface;
|
BaseInputPin* This = (BaseInputPin*)iface;
|
||||||
VideoRendererImpl *pVideoRenderer = (VideoRendererImpl *)This->pin.pinInfo.pFilter;
|
VideoRendererImpl *pVideoRenderer = (VideoRendererImpl *)This->pin.pinInfo.pFilter;
|
||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
|
|
||||||
|
@ -1059,7 +1062,7 @@ static HRESULT WINAPI VideoRenderer_InputPin_EndFlush(IPin * iface)
|
||||||
if (pVideoRenderer->state == State_Paused)
|
if (pVideoRenderer->state == State_Paused)
|
||||||
ResetEvent(pVideoRenderer->blocked);
|
ResetEvent(pVideoRenderer->blocked);
|
||||||
|
|
||||||
hr = InputPin_EndFlush(iface);
|
hr = BaseInputPinImpl_EndFlush(iface);
|
||||||
LeaveCriticalSection(This->pin.pCritSec);
|
LeaveCriticalSection(This->pin.pCritSec);
|
||||||
MediaSeekingPassThru_ResetMediaTime(pVideoRenderer->seekthru_unk);
|
MediaSeekingPassThru_ResetMediaTime(pVideoRenderer->seekthru_unk);
|
||||||
|
|
||||||
|
@ -1068,24 +1071,24 @@ static HRESULT WINAPI VideoRenderer_InputPin_EndFlush(IPin * iface)
|
||||||
|
|
||||||
static const IPinVtbl VideoRenderer_InputPin_Vtbl =
|
static const IPinVtbl VideoRenderer_InputPin_Vtbl =
|
||||||
{
|
{
|
||||||
InputPin_QueryInterface,
|
BaseInputPinImpl_QueryInterface,
|
||||||
BasePinImpl_AddRef,
|
BasePinImpl_AddRef,
|
||||||
InputPin_Release,
|
BaseInputPinImpl_Release,
|
||||||
InputPin_Connect,
|
BaseInputPinImpl_Connect,
|
||||||
InputPin_ReceiveConnection,
|
BaseInputPinImpl_ReceiveConnection,
|
||||||
BasePinImpl_Disconnect,
|
BasePinImpl_Disconnect,
|
||||||
BasePinImpl_ConnectedTo,
|
BasePinImpl_ConnectedTo,
|
||||||
BasePinImpl_ConnectionMediaType,
|
BasePinImpl_ConnectionMediaType,
|
||||||
BasePinImpl_QueryPinInfo,
|
BasePinImpl_QueryPinInfo,
|
||||||
BasePinImpl_QueryDirection,
|
BasePinImpl_QueryDirection,
|
||||||
BasePinImpl_QueryId,
|
BasePinImpl_QueryId,
|
||||||
InputPin_QueryAccept,
|
BaseInputPinImpl_QueryAccept,
|
||||||
BasePinImpl_EnumMediaTypes,
|
BasePinImpl_EnumMediaTypes,
|
||||||
BasePinImpl_QueryInternalConnections,
|
BasePinImpl_QueryInternalConnections,
|
||||||
VideoRenderer_InputPin_EndOfStream,
|
VideoRenderer_InputPin_EndOfStream,
|
||||||
VideoRenderer_InputPin_BeginFlush,
|
VideoRenderer_InputPin_BeginFlush,
|
||||||
VideoRenderer_InputPin_EndFlush,
|
VideoRenderer_InputPin_EndFlush,
|
||||||
InputPin_NewSegment
|
BaseInputPinImpl_NewSegment
|
||||||
};
|
};
|
||||||
|
|
||||||
/*** IUnknown methods ***/
|
/*** IUnknown methods ***/
|
||||||
|
|
|
@ -31,7 +31,114 @@
|
||||||
|
|
||||||
WINE_DEFAULT_DEBUG_CHANNEL(strmbase);
|
WINE_DEFAULT_DEBUG_CHANNEL(strmbase);
|
||||||
|
|
||||||
|
static const IPinVtbl InputPin_Vtbl;
|
||||||
static const IPinVtbl OutputPin_Vtbl;
|
static const IPinVtbl OutputPin_Vtbl;
|
||||||
|
static const IMemInputPinVtbl MemInputPin_Vtbl;
|
||||||
|
|
||||||
|
typedef HRESULT (*SendPinFunc)( IPin *to, LPVOID arg );
|
||||||
|
|
||||||
|
/** Helper function, there are a lot of places where the error code is inherited
|
||||||
|
* The following rules apply:
|
||||||
|
*
|
||||||
|
* Return the first received error code (E_NOTIMPL is ignored)
|
||||||
|
* If no errors occur: return the first received non-error-code that isn't S_OK
|
||||||
|
*/
|
||||||
|
static HRESULT updatehres( HRESULT original, HRESULT new )
|
||||||
|
{
|
||||||
|
if (FAILED( original ) || new == E_NOTIMPL)
|
||||||
|
return original;
|
||||||
|
|
||||||
|
if (FAILED( new ) || original == S_OK)
|
||||||
|
return new;
|
||||||
|
|
||||||
|
return original;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Sends a message from a pin further to other, similar pins
|
||||||
|
* fnMiddle is called on each pin found further on the stream.
|
||||||
|
* fnEnd (can be NULL) is called when the message can't be sent any further (this is a renderer or source)
|
||||||
|
*
|
||||||
|
* If the pin given is an input pin, the message will be sent downstream to other input pins
|
||||||
|
* If the pin given is an output pin, the message will be sent upstream to other output pins
|
||||||
|
*/
|
||||||
|
static HRESULT SendFurther( IPin *from, SendPinFunc fnMiddle, LPVOID arg, SendPinFunc fnEnd )
|
||||||
|
{
|
||||||
|
PIN_INFO pin_info;
|
||||||
|
ULONG amount = 0;
|
||||||
|
HRESULT hr = S_OK;
|
||||||
|
HRESULT hr_return = S_OK;
|
||||||
|
IEnumPins *enumpins = NULL;
|
||||||
|
BOOL foundend = TRUE;
|
||||||
|
PIN_DIRECTION from_dir;
|
||||||
|
|
||||||
|
IPin_QueryDirection( from, &from_dir );
|
||||||
|
|
||||||
|
hr = IPin_QueryInternalConnections( from, NULL, &amount );
|
||||||
|
if (hr != E_NOTIMPL && amount)
|
||||||
|
FIXME("Use QueryInternalConnections!\n");
|
||||||
|
hr = S_OK;
|
||||||
|
|
||||||
|
pin_info.pFilter = NULL;
|
||||||
|
hr = IPin_QueryPinInfo( from, &pin_info );
|
||||||
|
if (FAILED(hr))
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
hr = IBaseFilter_EnumPins( pin_info.pFilter, &enumpins );
|
||||||
|
if (FAILED(hr))
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
hr = IEnumPins_Reset( enumpins );
|
||||||
|
while (hr == S_OK) {
|
||||||
|
IPin *pin = NULL;
|
||||||
|
hr = IEnumPins_Next( enumpins, 1, &pin, NULL );
|
||||||
|
if (hr == VFW_E_ENUM_OUT_OF_SYNC)
|
||||||
|
{
|
||||||
|
hr = IEnumPins_Reset( enumpins );
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (pin)
|
||||||
|
{
|
||||||
|
PIN_DIRECTION dir;
|
||||||
|
|
||||||
|
IPin_QueryDirection( pin, &dir );
|
||||||
|
if (dir != from_dir)
|
||||||
|
{
|
||||||
|
IPin *connected = NULL;
|
||||||
|
|
||||||
|
foundend = FALSE;
|
||||||
|
IPin_ConnectedTo( pin, &connected );
|
||||||
|
if (connected)
|
||||||
|
{
|
||||||
|
HRESULT hr_local;
|
||||||
|
|
||||||
|
hr_local = fnMiddle( connected, arg );
|
||||||
|
hr_return = updatehres( hr_return, hr_local );
|
||||||
|
IPin_Release(connected);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
IPin_Release( pin );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
hr = S_OK;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!foundend)
|
||||||
|
hr = hr_return;
|
||||||
|
else if (fnEnd) {
|
||||||
|
HRESULT hr_local;
|
||||||
|
|
||||||
|
hr_local = fnEnd( from, arg );
|
||||||
|
hr_return = updatehres( hr_return, hr_local );
|
||||||
|
}
|
||||||
|
|
||||||
|
out:
|
||||||
|
if (pin_info.pFilter)
|
||||||
|
IBaseFilter_Release( pin_info.pFilter );
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
|
||||||
static void Copy_PinInfo(PIN_INFO * pDest, const PIN_INFO * pSrc)
|
static void Copy_PinInfo(PIN_INFO * pDest, const PIN_INFO * pSrc)
|
||||||
{
|
{
|
||||||
|
@ -758,3 +865,414 @@ HRESULT WINAPI BaseOutputPin_Construct(const IPinVtbl *OutputPin_Vtbl, LONG outp
|
||||||
CoTaskMemFree(pPinImpl);
|
CoTaskMemFree(pPinImpl);
|
||||||
return E_FAIL;
|
return E_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*** Input Pin implementation ***/
|
||||||
|
|
||||||
|
HRESULT WINAPI BaseInputPinImpl_QueryInterface(IPin * iface, REFIID riid, LPVOID * ppv)
|
||||||
|
{
|
||||||
|
BaseInputPin *This = (BaseInputPin *)iface;
|
||||||
|
|
||||||
|
TRACE("(%p)->(%s, %p)\n", iface, debugstr_guid(riid), ppv);
|
||||||
|
|
||||||
|
*ppv = NULL;
|
||||||
|
|
||||||
|
if (IsEqualIID(riid, &IID_IUnknown))
|
||||||
|
*ppv = iface;
|
||||||
|
else if (IsEqualIID(riid, &IID_IPin))
|
||||||
|
*ppv = iface;
|
||||||
|
else if (IsEqualIID(riid, &IID_IMemInputPin))
|
||||||
|
*ppv = &This->lpVtblMemInput;
|
||||||
|
else if (IsEqualIID(riid, &IID_IMediaSeeking))
|
||||||
|
{
|
||||||
|
return IBaseFilter_QueryInterface(This->pin.pinInfo.pFilter, &IID_IMediaSeeking, ppv);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*ppv)
|
||||||
|
{
|
||||||
|
IUnknown_AddRef((IUnknown *)(*ppv));
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
FIXME("No interface for %s!\n", debugstr_guid(riid));
|
||||||
|
|
||||||
|
return E_NOINTERFACE;
|
||||||
|
}
|
||||||
|
|
||||||
|
ULONG WINAPI BaseInputPinImpl_Release(IPin * iface)
|
||||||
|
{
|
||||||
|
BaseInputPin *This = (BaseInputPin *)iface;
|
||||||
|
ULONG refCount = InterlockedDecrement(&This->pin.refCount);
|
||||||
|
|
||||||
|
TRACE("(%p)->() Release from %d\n", iface, refCount + 1);
|
||||||
|
|
||||||
|
if (!refCount)
|
||||||
|
{
|
||||||
|
FreeMediaType(&This->pin.mtCurrent);
|
||||||
|
if (This->pAllocator)
|
||||||
|
IMemAllocator_Release(This->pAllocator);
|
||||||
|
This->pAllocator = NULL;
|
||||||
|
This->pin.lpVtbl = NULL;
|
||||||
|
CoTaskMemFree(This);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return refCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT WINAPI BaseInputPinImpl_Connect(IPin * iface, IPin * pConnector, const AM_MEDIA_TYPE * pmt)
|
||||||
|
{
|
||||||
|
ERR("Outgoing connection on an input pin! (%p, %p)\n", pConnector, pmt);
|
||||||
|
|
||||||
|
return E_UNEXPECTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
HRESULT WINAPI BaseInputPinImpl_ReceiveConnection(IPin * iface, IPin * pReceivePin, const AM_MEDIA_TYPE * pmt)
|
||||||
|
{
|
||||||
|
BaseInputPin *This = (BaseInputPin *)iface;
|
||||||
|
PIN_DIRECTION pindirReceive;
|
||||||
|
HRESULT hr = S_OK;
|
||||||
|
|
||||||
|
TRACE("(%p, %p)\n", pReceivePin, pmt);
|
||||||
|
dump_AM_MEDIA_TYPE(pmt);
|
||||||
|
|
||||||
|
EnterCriticalSection(This->pin.pCritSec);
|
||||||
|
{
|
||||||
|
if (This->pin.pConnectedTo)
|
||||||
|
hr = VFW_E_ALREADY_CONNECTED;
|
||||||
|
|
||||||
|
if (SUCCEEDED(hr) && This->fnCheckMediaType((IPin*)This, pmt) != S_OK)
|
||||||
|
hr = VFW_E_TYPE_NOT_ACCEPTED; /* FIXME: shouldn't we just map common errors onto
|
||||||
|
* VFW_E_TYPE_NOT_ACCEPTED and pass the value on otherwise? */
|
||||||
|
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
IPin_QueryDirection(pReceivePin, &pindirReceive);
|
||||||
|
|
||||||
|
if (pindirReceive != PINDIR_OUTPUT)
|
||||||
|
{
|
||||||
|
ERR("Can't connect from non-output pin\n");
|
||||||
|
hr = VFW_E_INVALID_DIRECTION;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
CopyMediaType(&This->pin.mtCurrent, pmt);
|
||||||
|
This->pin.pConnectedTo = pReceivePin;
|
||||||
|
IPin_AddRef(pReceivePin);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
LeaveCriticalSection(This->pin.pCritSec);
|
||||||
|
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
|
||||||
|
static HRESULT deliver_endofstream(IPin* pin, LPVOID unused)
|
||||||
|
{
|
||||||
|
return IPin_EndOfStream( pin );
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT WINAPI BaseInputPinImpl_QueryAccept(IPin * iface, const AM_MEDIA_TYPE * pmt)
|
||||||
|
{
|
||||||
|
BaseInputPin *This = (BaseInputPin *)iface;
|
||||||
|
|
||||||
|
TRACE("(%p/%p)->(%p)\n", This, iface, pmt);
|
||||||
|
|
||||||
|
return (This->fnCheckMediaType((IPin*)This, pmt) == S_OK ? S_OK : S_FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT WINAPI BaseInputPinImpl_EndOfStream(IPin * iface)
|
||||||
|
{
|
||||||
|
HRESULT hr = S_OK;
|
||||||
|
BaseInputPin *This = (BaseInputPin *)iface;
|
||||||
|
|
||||||
|
TRACE("(%p)\n", This);
|
||||||
|
|
||||||
|
EnterCriticalSection(This->pin.pCritSec);
|
||||||
|
if (This->flushing)
|
||||||
|
hr = S_FALSE;
|
||||||
|
else
|
||||||
|
This->end_of_stream = 1;
|
||||||
|
LeaveCriticalSection(This->pin.pCritSec);
|
||||||
|
|
||||||
|
if (hr == S_OK)
|
||||||
|
hr = SendFurther( iface, deliver_endofstream, NULL, NULL );
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
|
||||||
|
static HRESULT deliver_beginflush(IPin* pin, LPVOID unused)
|
||||||
|
{
|
||||||
|
return IPin_BeginFlush( pin );
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT WINAPI BaseInputPinImpl_BeginFlush(IPin * iface)
|
||||||
|
{
|
||||||
|
BaseInputPin *This = (BaseInputPin *)iface;
|
||||||
|
HRESULT hr;
|
||||||
|
TRACE("() semi-stub\n");
|
||||||
|
|
||||||
|
EnterCriticalSection(This->pin.pCritSec);
|
||||||
|
This->flushing = 1;
|
||||||
|
|
||||||
|
hr = SendFurther( iface, deliver_beginflush, NULL, NULL );
|
||||||
|
LeaveCriticalSection(This->pin.pCritSec);
|
||||||
|
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
|
||||||
|
static HRESULT deliver_endflush(IPin* pin, LPVOID unused)
|
||||||
|
{
|
||||||
|
return IPin_EndFlush( pin );
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT WINAPI BaseInputPinImpl_EndFlush(IPin * iface)
|
||||||
|
{
|
||||||
|
BaseInputPin *This = (BaseInputPin *)iface;
|
||||||
|
HRESULT hr;
|
||||||
|
TRACE("(%p)\n", This);
|
||||||
|
|
||||||
|
EnterCriticalSection(This->pin.pCritSec);
|
||||||
|
This->flushing = This->end_of_stream = 0;
|
||||||
|
|
||||||
|
hr = SendFurther( iface, deliver_endflush, NULL, NULL );
|
||||||
|
LeaveCriticalSection(This->pin.pCritSec);
|
||||||
|
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef struct newsegmentargs
|
||||||
|
{
|
||||||
|
REFERENCE_TIME tStart, tStop;
|
||||||
|
double rate;
|
||||||
|
} newsegmentargs;
|
||||||
|
|
||||||
|
static HRESULT deliver_newsegment(IPin *pin, LPVOID data)
|
||||||
|
{
|
||||||
|
newsegmentargs *args = data;
|
||||||
|
return IPin_NewSegment(pin, args->tStart, args->tStop, args->rate);
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT WINAPI BaseInputPinImpl_NewSegment(IPin * iface, REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate)
|
||||||
|
{
|
||||||
|
BaseInputPin *This = (BaseInputPin *)iface;
|
||||||
|
newsegmentargs args;
|
||||||
|
|
||||||
|
TRACE("(%x%08x, %x%08x, %e)\n", (ULONG)(tStart >> 32), (ULONG)tStart, (ULONG)(tStop >> 32), (ULONG)tStop, dRate);
|
||||||
|
|
||||||
|
args.tStart = This->tStart = tStart;
|
||||||
|
args.tStop = This->tStop = tStop;
|
||||||
|
args.rate = This->dRate = dRate;
|
||||||
|
|
||||||
|
return SendFurther( iface, deliver_newsegment, &args, NULL );
|
||||||
|
}
|
||||||
|
|
||||||
|
static const IPinVtbl InputPin_Vtbl =
|
||||||
|
{
|
||||||
|
BaseInputPinImpl_QueryInterface,
|
||||||
|
BasePinImpl_AddRef,
|
||||||
|
BaseInputPinImpl_Release,
|
||||||
|
BaseInputPinImpl_Connect,
|
||||||
|
BaseInputPinImpl_ReceiveConnection,
|
||||||
|
BasePinImpl_Disconnect,
|
||||||
|
BasePinImpl_ConnectedTo,
|
||||||
|
BasePinImpl_ConnectionMediaType,
|
||||||
|
BasePinImpl_QueryPinInfo,
|
||||||
|
BasePinImpl_QueryDirection,
|
||||||
|
BasePinImpl_QueryId,
|
||||||
|
BaseInputPinImpl_QueryAccept,
|
||||||
|
BasePinImpl_EnumMediaTypes,
|
||||||
|
BasePinImpl_QueryInternalConnections,
|
||||||
|
BaseInputPinImpl_EndOfStream,
|
||||||
|
BaseInputPinImpl_BeginFlush,
|
||||||
|
BaseInputPinImpl_EndFlush,
|
||||||
|
BaseInputPinImpl_NewSegment
|
||||||
|
};
|
||||||
|
|
||||||
|
/*** IMemInputPin implementation ***/
|
||||||
|
|
||||||
|
static inline BaseInputPin *impl_from_IMemInputPin( IMemInputPin *iface )
|
||||||
|
{
|
||||||
|
return (BaseInputPin *)((char*)iface - FIELD_OFFSET(BaseInputPin, lpVtblMemInput));
|
||||||
|
}
|
||||||
|
|
||||||
|
static HRESULT WINAPI MemInputPin_QueryInterface(IMemInputPin * iface, REFIID riid, LPVOID * ppv)
|
||||||
|
{
|
||||||
|
BaseInputPin *This = impl_from_IMemInputPin(iface);
|
||||||
|
|
||||||
|
return IPin_QueryInterface((IPin *)&This->pin, riid, ppv);
|
||||||
|
}
|
||||||
|
|
||||||
|
static ULONG WINAPI MemInputPin_AddRef(IMemInputPin * iface)
|
||||||
|
{
|
||||||
|
BaseInputPin *This = impl_from_IMemInputPin(iface);
|
||||||
|
|
||||||
|
return IPin_AddRef((IPin *)&This->pin);
|
||||||
|
}
|
||||||
|
|
||||||
|
static ULONG WINAPI MemInputPin_Release(IMemInputPin * iface)
|
||||||
|
{
|
||||||
|
BaseInputPin *This = impl_from_IMemInputPin(iface);
|
||||||
|
|
||||||
|
return IPin_Release((IPin *)&This->pin);
|
||||||
|
}
|
||||||
|
|
||||||
|
static HRESULT WINAPI MemInputPin_GetAllocator(IMemInputPin * iface, IMemAllocator ** ppAllocator)
|
||||||
|
{
|
||||||
|
BaseInputPin *This = impl_from_IMemInputPin(iface);
|
||||||
|
|
||||||
|
TRACE("(%p/%p)->(%p)\n", This, iface, ppAllocator);
|
||||||
|
|
||||||
|
*ppAllocator = This->pAllocator;
|
||||||
|
if (*ppAllocator)
|
||||||
|
IMemAllocator_AddRef(*ppAllocator);
|
||||||
|
|
||||||
|
return *ppAllocator ? S_OK : VFW_E_NO_ALLOCATOR;
|
||||||
|
}
|
||||||
|
|
||||||
|
static HRESULT WINAPI MemInputPin_NotifyAllocator(IMemInputPin * iface, IMemAllocator * pAllocator, BOOL bReadOnly)
|
||||||
|
{
|
||||||
|
BaseInputPin *This = impl_from_IMemInputPin(iface);
|
||||||
|
|
||||||
|
TRACE("(%p/%p)->(%p, %d)\n", This, iface, pAllocator, bReadOnly);
|
||||||
|
|
||||||
|
if (bReadOnly)
|
||||||
|
FIXME("Read only flag not handled yet!\n");
|
||||||
|
|
||||||
|
/* FIXME: Should we release the allocator on disconnection? */
|
||||||
|
if (!pAllocator)
|
||||||
|
{
|
||||||
|
WARN("Null allocator\n");
|
||||||
|
return E_POINTER;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (This->preferred_allocator && pAllocator != This->preferred_allocator)
|
||||||
|
return E_FAIL;
|
||||||
|
|
||||||
|
if (This->pAllocator)
|
||||||
|
IMemAllocator_Release(This->pAllocator);
|
||||||
|
This->pAllocator = pAllocator;
|
||||||
|
if (This->pAllocator)
|
||||||
|
IMemAllocator_AddRef(This->pAllocator);
|
||||||
|
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static HRESULT WINAPI MemInputPin_GetAllocatorRequirements(IMemInputPin * iface, ALLOCATOR_PROPERTIES * pProps)
|
||||||
|
{
|
||||||
|
BaseInputPin *This = impl_from_IMemInputPin(iface);
|
||||||
|
|
||||||
|
TRACE("(%p/%p)->(%p)\n", This, iface, pProps);
|
||||||
|
|
||||||
|
/* override this method if you have any specific requirements */
|
||||||
|
|
||||||
|
return E_NOTIMPL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static HRESULT WINAPI MemInputPin_Receive(IMemInputPin * iface, IMediaSample * pSample)
|
||||||
|
{
|
||||||
|
BaseInputPin *This = impl_from_IMemInputPin(iface);
|
||||||
|
HRESULT hr;
|
||||||
|
|
||||||
|
/* this trace commented out for performance reasons */
|
||||||
|
/*TRACE("(%p/%p)->(%p)\n", This, iface, pSample);*/
|
||||||
|
hr = This->fnReceive((IPin*)This, pSample);
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
|
||||||
|
static HRESULT WINAPI MemInputPin_ReceiveMultiple(IMemInputPin * iface, IMediaSample ** pSamples, LONG nSamples, LONG *nSamplesProcessed)
|
||||||
|
{
|
||||||
|
HRESULT hr = S_OK;
|
||||||
|
BaseInputPin *This = impl_from_IMemInputPin(iface);
|
||||||
|
|
||||||
|
TRACE("(%p/%p)->(%p, %d, %p)\n", This, iface, pSamples, nSamples, nSamplesProcessed);
|
||||||
|
|
||||||
|
for (*nSamplesProcessed = 0; *nSamplesProcessed < nSamples; (*nSamplesProcessed)++)
|
||||||
|
{
|
||||||
|
hr = IMemInputPin_Receive(iface, pSamples[*nSamplesProcessed]);
|
||||||
|
if (hr != S_OK)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
|
||||||
|
static HRESULT WINAPI MemInputPin_ReceiveCanBlock(IMemInputPin * iface)
|
||||||
|
{
|
||||||
|
BaseInputPin *This = impl_from_IMemInputPin(iface);
|
||||||
|
|
||||||
|
TRACE("(%p/%p)->()\n", This, iface);
|
||||||
|
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const IMemInputPinVtbl MemInputPin_Vtbl =
|
||||||
|
{
|
||||||
|
MemInputPin_QueryInterface,
|
||||||
|
MemInputPin_AddRef,
|
||||||
|
MemInputPin_Release,
|
||||||
|
MemInputPin_GetAllocator,
|
||||||
|
MemInputPin_NotifyAllocator,
|
||||||
|
MemInputPin_GetAllocatorRequirements,
|
||||||
|
MemInputPin_Receive,
|
||||||
|
MemInputPin_ReceiveMultiple,
|
||||||
|
MemInputPin_ReceiveCanBlock
|
||||||
|
};
|
||||||
|
|
||||||
|
static HRESULT InputPin_Init(const IPinVtbl *InputPin_Vtbl, const PIN_INFO * pPinInfo,
|
||||||
|
BasePin_CheckMediaType pCheckMediaType, BaseInputPin_Receive pReceive,
|
||||||
|
LPCRITICAL_SECTION pCritSec, IMemAllocator *allocator, BaseInputPin * pPinImpl)
|
||||||
|
{
|
||||||
|
TRACE("\n");
|
||||||
|
|
||||||
|
/* Common attributes */
|
||||||
|
pPinImpl->pin.refCount = 1;
|
||||||
|
pPinImpl->pin.pConnectedTo = NULL;
|
||||||
|
pPinImpl->pin.pCritSec = pCritSec;
|
||||||
|
Copy_PinInfo(&pPinImpl->pin.pinInfo, pPinInfo);
|
||||||
|
ZeroMemory(&pPinImpl->pin.mtCurrent, sizeof(AM_MEDIA_TYPE));
|
||||||
|
|
||||||
|
/* Input pin attributes */
|
||||||
|
pPinImpl->fnCheckMediaType = pCheckMediaType;
|
||||||
|
pPinImpl->fnReceive = pReceive;
|
||||||
|
pPinImpl->pAllocator = pPinImpl->preferred_allocator = allocator;
|
||||||
|
if (pPinImpl->preferred_allocator)
|
||||||
|
IMemAllocator_AddRef(pPinImpl->preferred_allocator);
|
||||||
|
pPinImpl->tStart = 0;
|
||||||
|
pPinImpl->tStop = 0;
|
||||||
|
pPinImpl->dRate = 1.0;
|
||||||
|
pPinImpl->pin.lpVtbl = InputPin_Vtbl;
|
||||||
|
pPinImpl->lpVtblMemInput = &MemInputPin_Vtbl;
|
||||||
|
pPinImpl->flushing = pPinImpl->end_of_stream = 0;
|
||||||
|
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT BaseInputPin_Construct(const IPinVtbl *InputPin_Vtbl, const PIN_INFO * pPinInfo,
|
||||||
|
BasePin_CheckMediaType pCheckMediaType, BaseInputPin_Receive pReceive,
|
||||||
|
LPCRITICAL_SECTION pCritSec, IMemAllocator *allocator, IPin ** ppPin)
|
||||||
|
{
|
||||||
|
BaseInputPin * pPinImpl;
|
||||||
|
|
||||||
|
*ppPin = NULL;
|
||||||
|
|
||||||
|
if (pPinInfo->dir != PINDIR_INPUT)
|
||||||
|
{
|
||||||
|
ERR("Pin direction(%x) != PINDIR_INPUT\n", pPinInfo->dir);
|
||||||
|
return E_INVALIDARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
pPinImpl = CoTaskMemAlloc(sizeof(*pPinImpl));
|
||||||
|
|
||||||
|
if (!pPinImpl)
|
||||||
|
return E_OUTOFMEMORY;
|
||||||
|
|
||||||
|
if (SUCCEEDED(InputPin_Init(InputPin_Vtbl, pPinInfo, pCheckMediaType, pReceive, pCritSec, allocator, pPinImpl)))
|
||||||
|
{
|
||||||
|
*ppPin = (IPin *)pPinImpl;
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
CoTaskMemFree(pPinImpl);
|
||||||
|
return E_FAIL;
|
||||||
|
}
|
||||||
|
|
|
@ -27,11 +27,14 @@ void WINAPI DeleteMediaType(AM_MEDIA_TYPE * pMediaType);
|
||||||
typedef HRESULT (WINAPI *BasePin_GetMediaType)(IPin* iface, int iPosition, AM_MEDIA_TYPE *amt);
|
typedef HRESULT (WINAPI *BasePin_GetMediaType)(IPin* iface, int iPosition, AM_MEDIA_TYPE *amt);
|
||||||
typedef LONG (WINAPI *BasePin_GetMediaTypeVersion)(IPin* iface);
|
typedef LONG (WINAPI *BasePin_GetMediaTypeVersion)(IPin* iface);
|
||||||
typedef HRESULT (WINAPI *BasePin_AttemptConnection)(IPin *iface, IPin *pReceivePin, const AM_MEDIA_TYPE *pmt);
|
typedef HRESULT (WINAPI *BasePin_AttemptConnection)(IPin *iface, IPin *pReceivePin, const AM_MEDIA_TYPE *pmt);
|
||||||
|
typedef HRESULT (WINAPI *BasePin_CheckMediaType)(IPin *iface, const AM_MEDIA_TYPE *pmt);
|
||||||
|
|
||||||
typedef IPin* (WINAPI *BaseFilter_GetPin)(IBaseFilter* iface, int iPosition);
|
typedef IPin* (WINAPI *BaseFilter_GetPin)(IBaseFilter* iface, int iPosition);
|
||||||
typedef LONG (WINAPI *BaseFilter_GetPinCount)(IBaseFilter* iface);
|
typedef LONG (WINAPI *BaseFilter_GetPinCount)(IBaseFilter* iface);
|
||||||
typedef LONG (WINAPI *BaseFilter_GetPinVersion)(IBaseFilter* iface);
|
typedef LONG (WINAPI *BaseFilter_GetPinVersion)(IBaseFilter* iface);
|
||||||
|
|
||||||
|
typedef HRESULT (WINAPI *BaseInputPin_Receive)(IPin *This, IMediaSample *pSample);
|
||||||
|
|
||||||
HRESULT WINAPI EnumMediaTypes_Construct(IPin *iface, BasePin_GetMediaType enumFunc, BasePin_GetMediaTypeVersion versionFunc, IEnumMediaTypes ** ppEnum);
|
HRESULT WINAPI EnumMediaTypes_Construct(IPin *iface, BasePin_GetMediaType enumFunc, BasePin_GetMediaTypeVersion versionFunc, IEnumMediaTypes ** ppEnum);
|
||||||
|
|
||||||
HRESULT WINAPI EnumPins_Construct(IBaseFilter *base, BaseFilter_GetPin receive_pin, BaseFilter_GetPinCount receive_pincount, BaseFilter_GetPinVersion receive_version, IEnumPins ** ppEnum);
|
HRESULT WINAPI EnumPins_Construct(IBaseFilter *base, BaseFilter_GetPin receive_pin, BaseFilter_GetPinCount receive_pincount, BaseFilter_GetPinVersion receive_version, IEnumPins ** ppEnum);
|
||||||
|
@ -61,6 +64,22 @@ typedef struct BaseOutputPin
|
||||||
ALLOCATOR_PROPERTIES allocProps;
|
ALLOCATOR_PROPERTIES allocProps;
|
||||||
} BaseOutputPin;
|
} BaseOutputPin;
|
||||||
|
|
||||||
|
typedef struct BaseInputPin
|
||||||
|
{
|
||||||
|
/* inheritance C style! */
|
||||||
|
BasePin pin;
|
||||||
|
|
||||||
|
const IMemInputPinVtbl * lpVtblMemInput;
|
||||||
|
IMemAllocator * pAllocator;
|
||||||
|
BaseInputPin_Receive fnReceive;
|
||||||
|
BasePin_CheckMediaType fnCheckMediaType;
|
||||||
|
REFERENCE_TIME tStart;
|
||||||
|
REFERENCE_TIME tStop;
|
||||||
|
double dRate;
|
||||||
|
BOOL flushing, end_of_stream;
|
||||||
|
IMemAllocator *preferred_allocator;
|
||||||
|
} BaseInputPin;
|
||||||
|
|
||||||
/* Base Pin */
|
/* Base Pin */
|
||||||
HRESULT WINAPI BasePinImpl_GetMediaType(IPin *iface, int iPosition, AM_MEDIA_TYPE *pmt);
|
HRESULT WINAPI BasePinImpl_GetMediaType(IPin *iface, int iPosition, AM_MEDIA_TYPE *pmt);
|
||||||
LONG WINAPI BasePinImpl_GetMediaTypeVersion(IPin *iface);
|
LONG WINAPI BasePinImpl_GetMediaTypeVersion(IPin *iface);
|
||||||
|
@ -92,3 +111,16 @@ HRESULT WINAPI BaseOutputPinImpl_BreakConnect(BaseOutputPin * This);
|
||||||
HRESULT WINAPI BaseOutputPinImpl_Active(BaseOutputPin * This);
|
HRESULT WINAPI BaseOutputPinImpl_Active(BaseOutputPin * This);
|
||||||
HRESULT WINAPI BaseOutputPinImpl_Inactive(BaseOutputPin * This);
|
HRESULT WINAPI BaseOutputPinImpl_Inactive(BaseOutputPin * This);
|
||||||
HRESULT WINAPI BaseOutputPin_Construct(const IPinVtbl *OutputPin_Vtbl, LONG outputpin_size, const PIN_INFO * pPinInfo, ALLOCATOR_PROPERTIES *props, BasePin_AttemptConnection pConnectProc, LPCRITICAL_SECTION pCritSec, IPin ** ppPin);
|
HRESULT WINAPI BaseOutputPin_Construct(const IPinVtbl *OutputPin_Vtbl, LONG outputpin_size, const PIN_INFO * pPinInfo, ALLOCATOR_PROPERTIES *props, BasePin_AttemptConnection pConnectProc, LPCRITICAL_SECTION pCritSec, IPin ** ppPin);
|
||||||
|
|
||||||
|
/* Base Input Pin */
|
||||||
|
HRESULT WINAPI BaseInputPinImpl_QueryInterface(IPin * iface, REFIID riid, LPVOID * ppv);
|
||||||
|
ULONG WINAPI BaseInputPinImpl_Release(IPin * iface);
|
||||||
|
HRESULT WINAPI BaseInputPinImpl_Connect(IPin * iface, IPin * pConnector, const AM_MEDIA_TYPE * pmt);
|
||||||
|
HRESULT WINAPI BaseInputPinImpl_ReceiveConnection(IPin * iface, IPin * pReceivePin, const AM_MEDIA_TYPE * pmt);
|
||||||
|
HRESULT WINAPI BaseInputPinImpl_QueryAccept(IPin * iface, const AM_MEDIA_TYPE * pmt);
|
||||||
|
HRESULT WINAPI BaseInputPinImpl_EndOfStream(IPin * iface);
|
||||||
|
HRESULT WINAPI BaseInputPinImpl_BeginFlush(IPin * iface);
|
||||||
|
HRESULT WINAPI BaseInputPinImpl_EndFlush(IPin * iface);
|
||||||
|
HRESULT WINAPI BaseInputPinImpl_NewSegment(IPin * iface, REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate);
|
||||||
|
|
||||||
|
HRESULT BaseInputPin_Construct(const IPinVtbl *InputPin_Vtbl, const PIN_INFO * pPinInfo, BasePin_CheckMediaType pQueryAccept, BaseInputPin_Receive pSampleProc, LPCRITICAL_SECTION pCritSec, IMemAllocator *, IPin ** ppPin);
|
||||||
|
|
Loading…
Reference in New Issue