quartz: Add a function that can be called when stopping processing data.
This commit is contained in:
parent
ec87de35af
commit
512ee927cb
|
@ -1080,7 +1080,7 @@ HRESULT AVISplitter_create(IUnknown * pUnkOuter, LPVOID * ppv)
|
|||
This->streams = NULL;
|
||||
This->oldindex = NULL;
|
||||
|
||||
hr = Parser_Create(&(This->Parser), &AVISplitter_Vtbl, &CLSID_AviSplitter, AVISplitter_Sample, AVISplitter_QueryAccept, AVISplitter_InputPin_PreConnect, AVISplitter_Cleanup, AVISplitter_Disconnect, NULL, NULL, NULL, NULL);
|
||||
hr = Parser_Create(&(This->Parser), &AVISplitter_Vtbl, &CLSID_AviSplitter, AVISplitter_Sample, AVISplitter_QueryAccept, AVISplitter_InputPin_PreConnect, AVISplitter_Cleanup, AVISplitter_Disconnect, NULL, NULL, NULL, NULL, NULL);
|
||||
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
|
|
@ -830,7 +830,7 @@ HRESULT MPEGSplitter_create(IUnknown * pUnkOuter, LPVOID * ppv)
|
|||
}
|
||||
This->seek_entries = 64;
|
||||
|
||||
hr = Parser_Create(&(This->Parser), &MPEGSplitter_Vtbl, &CLSID_MPEG1Splitter, MPEGSplitter_process_sample, MPEGSplitter_query_accept, MPEGSplitter_pre_connect, MPEGSplitter_cleanup, MPEGSplitter_disconnect, MPEGSplitter_first_request, NULL, MPEGSplitter_seek, NULL);
|
||||
hr = Parser_Create(&(This->Parser), &MPEGSplitter_Vtbl, &CLSID_MPEG1Splitter, MPEGSplitter_process_sample, MPEGSplitter_query_accept, MPEGSplitter_pre_connect, MPEGSplitter_cleanup, MPEGSplitter_disconnect, MPEGSplitter_first_request, NULL, NULL, MPEGSplitter_seek, NULL);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
CoTaskMemFree(This);
|
||||
|
|
|
@ -52,7 +52,7 @@ static inline ParserImpl *impl_from_IMediaSeeking( IMediaSeeking *iface )
|
|||
}
|
||||
|
||||
|
||||
HRESULT Parser_Create(ParserImpl* pParser, const IBaseFilterVtbl *Parser_Vtbl, const CLSID* pClsid, PFN_PROCESS_SAMPLE fnProcessSample, PFN_QUERY_ACCEPT fnQueryAccept, PFN_PRE_CONNECT fnPreConnect, PFN_CLEANUP fnCleanup, PFN_DISCONNECT fnDisconnect, REQUESTPROC fnRequest, CHANGEPROC stop, CHANGEPROC current, CHANGEPROC rate)
|
||||
HRESULT Parser_Create(ParserImpl* pParser, const IBaseFilterVtbl *Parser_Vtbl, const CLSID* pClsid, PFN_PROCESS_SAMPLE fnProcessSample, PFN_QUERY_ACCEPT fnQueryAccept, PFN_PRE_CONNECT fnPreConnect, PFN_CLEANUP fnCleanup, PFN_DISCONNECT fnDisconnect, REQUESTPROC fnRequest, STOPPROCESSPROC fnDone, CHANGEPROC stop, CHANGEPROC current, CHANGEPROC rate)
|
||||
{
|
||||
HRESULT hr;
|
||||
PIN_INFO piInput;
|
||||
|
@ -67,8 +67,8 @@ HRESULT Parser_Create(ParserImpl* pParser, const IBaseFilterVtbl *Parser_Vtbl, c
|
|||
pParser->pClock = NULL;
|
||||
pParser->fnDisconnect = fnDisconnect;
|
||||
ZeroMemory(&pParser->filterInfo, sizeof(FILTER_INFO));
|
||||
|
||||
pParser->lastpinchange = GetTickCount();
|
||||
|
||||
pParser->cStreams = 0;
|
||||
pParser->ppPins = CoTaskMemAlloc(1 * sizeof(IPin *));
|
||||
|
||||
|
@ -89,7 +89,7 @@ HRESULT Parser_Create(ParserImpl* pParser, const IBaseFilterVtbl *Parser_Vtbl, c
|
|||
MediaSeekingImpl_Init((IBaseFilter*)pParser, stop, current, rate, &pParser->mediaSeeking, &pParser->csFilter);
|
||||
pParser->mediaSeeking.lpVtbl = &Parser_Seeking_Vtbl;
|
||||
|
||||
hr = PullPin_Construct(&Parser_InputPin_Vtbl, &piInput, fnProcessSample, (LPVOID)pParser, fnQueryAccept, fnCleanup, fnRequest, &pParser->csFilter, (IPin **)&pParser->pInputPin);
|
||||
hr = PullPin_Construct(&Parser_InputPin_Vtbl, &piInput, fnProcessSample, (LPVOID)pParser, fnQueryAccept, fnCleanup, fnRequest, fnDone, &pParser->csFilter, (IPin **)&pParser->pInputPin);
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
|
@ -150,6 +150,10 @@ ULONG WINAPI Parser_AddRef(IBaseFilter * iface)
|
|||
void Parser_Destroy(ParserImpl *This)
|
||||
{
|
||||
IPin *connected = NULL;
|
||||
ULONG pinref;
|
||||
|
||||
assert(!This->refCount);
|
||||
PullPin_WaitForStateChange(This->pInputPin, INFINITE);
|
||||
|
||||
if (This->pClock)
|
||||
IReferenceClock_Release(This->pClock);
|
||||
|
@ -158,11 +162,21 @@ void Parser_Destroy(ParserImpl *This)
|
|||
IPin_ConnectedTo((IPin *)This->pInputPin, &connected);
|
||||
if (connected)
|
||||
{
|
||||
IPin_Disconnect(connected);
|
||||
assert(IPin_Disconnect(connected) == S_OK);
|
||||
IPin_Release(connected);
|
||||
IPin_Disconnect((IPin *)This->pInputPin);
|
||||
assert(IPin_Disconnect((IPin *)This->pInputPin) == S_OK);
|
||||
}
|
||||
IPin_Release((IPin *)This->pInputPin);
|
||||
pinref = IPin_Release((IPin *)This->pInputPin);
|
||||
if (pinref)
|
||||
{
|
||||
/* Valgrind could find this, if I kill it here */
|
||||
ERR("pinref should be null, is %u, destroying anyway\n", pinref);
|
||||
assert((LONG)pinref > 0);
|
||||
|
||||
while (pinref)
|
||||
pinref = IPin_Release((IPin *)This->pInputPin);
|
||||
}
|
||||
|
||||
CoTaskMemFree(This->ppPins);
|
||||
This->lpVtbl = NULL;
|
||||
|
||||
|
@ -378,6 +392,7 @@ HRESULT WINAPI Parser_GetSyncSource(IBaseFilter * iface, IReferenceClock **ppClo
|
|||
|
||||
/** IBaseFilter implementation **/
|
||||
|
||||
/* FIXME: WRONG */
|
||||
static HRESULT Parser_GetPin(IBaseFilter *iface, ULONG pos, IPin **pin, DWORD *lastsynctick)
|
||||
{
|
||||
ParserImpl *This = (ParserImpl *)iface;
|
||||
|
@ -464,7 +479,7 @@ HRESULT Parser_AddPin(ParserImpl * This, const PIN_INFO * piOutput, ALLOCATOR_PR
|
|||
This->ppPins = CoTaskMemAlloc((This->cStreams + 2) * sizeof(IPin *));
|
||||
memcpy(This->ppPins, ppOldPins, (This->cStreams + 1) * sizeof(IPin *));
|
||||
|
||||
hr = OutputPin_Construct(&Parser_OutputPin_Vtbl, sizeof(Parser_OutputPin), piOutput, props, NULL, Parser_OutputPin_QueryAccept, &This->csFilter, This->ppPins + This->cStreams + 1);
|
||||
hr = OutputPin_Construct(&Parser_OutputPin_Vtbl, sizeof(Parser_OutputPin), piOutput, props, NULL, Parser_OutputPin_QueryAccept, &This->csFilter, This->ppPins + (This->cStreams + 1));
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
|
@ -494,22 +509,25 @@ HRESULT Parser_AddPin(ParserImpl * This, const PIN_INFO * piOutput, ALLOCATOR_PR
|
|||
static HRESULT Parser_RemoveOutputPins(ParserImpl * This)
|
||||
{
|
||||
/* NOTE: should be in critical section when calling this function */
|
||||
|
||||
HRESULT hr;
|
||||
ULONG i;
|
||||
IPin ** ppOldPins = This->ppPins;
|
||||
|
||||
TRACE("(%p)\n", This);
|
||||
|
||||
/* reduce the pin array down to 1 (just our input pin) */
|
||||
This->ppPins = CoTaskMemAlloc(sizeof(IPin *) * 1);
|
||||
memcpy(This->ppPins, ppOldPins, sizeof(IPin *) * 1);
|
||||
|
||||
for (i = 0; i < This->cStreams; i++)
|
||||
{
|
||||
OutputPin_DeliverDisconnect((OutputPin *)ppOldPins[i + 1]);
|
||||
hr = OutputPin_DeliverDisconnect((OutputPin *)ppOldPins[i + 1]);
|
||||
FIXME("Other side: %08x\n", hr);
|
||||
IPin_Release(ppOldPins[i + 1]);
|
||||
}
|
||||
|
||||
This->cStreams = 0;
|
||||
This->lastpinchange = GetTickCount();
|
||||
This->cStreams = 0;
|
||||
CoTaskMemFree(ppOldPins);
|
||||
|
||||
return S_OK;
|
||||
|
@ -687,27 +705,31 @@ static const IPinVtbl Parser_OutputPin_Vtbl =
|
|||
static HRESULT WINAPI Parser_PullPin_Disconnect(IPin * iface)
|
||||
{
|
||||
HRESULT hr;
|
||||
IPinImpl *This = (IPinImpl *)iface;
|
||||
PullPin *This = (PullPin *)iface;
|
||||
|
||||
TRACE("()\n");
|
||||
|
||||
EnterCriticalSection(This->pCritSec);
|
||||
EnterCriticalSection(&This->thread_lock);
|
||||
EnterCriticalSection(This->pin.pCritSec);
|
||||
{
|
||||
if (This->pConnectedTo)
|
||||
if (This->pin.pConnectedTo)
|
||||
{
|
||||
PullPin *ppin = (PullPin *)This;
|
||||
FILTER_STATE state;
|
||||
ParserImpl *Parser = (ParserImpl *)This->pinInfo.pFilter;
|
||||
ParserImpl *Parser = (ParserImpl *)This->pin.pinInfo.pFilter;
|
||||
|
||||
hr = IBaseFilter_GetState(This->pinInfo.pFilter, 0, &state);
|
||||
LeaveCriticalSection(This->pin.pCritSec);
|
||||
hr = IBaseFilter_GetState(This->pin.pinInfo.pFilter, INFINITE, &state);
|
||||
EnterCriticalSection(This->pin.pCritSec);
|
||||
|
||||
if (SUCCEEDED(hr) && (state == State_Stopped) && SUCCEEDED(Parser->fnDisconnect(Parser)))
|
||||
{
|
||||
IPin_Release(This->pConnectedTo);
|
||||
This->pConnectedTo = NULL;
|
||||
IPin_Release(This->pin.pConnectedTo);
|
||||
This->pin.pConnectedTo = NULL;
|
||||
|
||||
if (FAILED(hr = IMemAllocator_Decommit(ppin->pAlloc)))
|
||||
ERR("Allocator decommit failed with error %x. Possible memory leak\n", hr);
|
||||
hr = Parser_RemoveOutputPins((ParserImpl *)This->pinInfo.pFilter);
|
||||
hr = Parser_RemoveOutputPins((ParserImpl *)This->pin.pinInfo.pFilter);
|
||||
}
|
||||
else
|
||||
hr = VFW_E_NOT_STOPPED;
|
||||
|
@ -715,7 +737,8 @@ static HRESULT WINAPI Parser_PullPin_Disconnect(IPin * iface)
|
|||
else
|
||||
hr = S_FALSE;
|
||||
}
|
||||
LeaveCriticalSection(This->pCritSec);
|
||||
LeaveCriticalSection(This->pin.pCritSec);
|
||||
LeaveCriticalSection(&This->thread_lock);
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
|
|
@ -58,7 +58,7 @@ typedef struct Parser_OutputPin
|
|||
extern HRESULT Parser_AddPin(ParserImpl * This, const PIN_INFO * piOutput, ALLOCATOR_PROPERTIES * props, const AM_MEDIA_TYPE * amt);
|
||||
|
||||
extern HRESULT Parser_Create(ParserImpl*, const IBaseFilterVtbl *, const CLSID*, PFN_PROCESS_SAMPLE, PFN_QUERY_ACCEPT, PFN_PRE_CONNECT,
|
||||
PFN_CLEANUP, PFN_DISCONNECT, REQUESTPROC, CHANGEPROC stop, CHANGEPROC current, CHANGEPROC rate);
|
||||
PFN_CLEANUP, PFN_DISCONNECT, REQUESTPROC, STOPPROCESSPROC, CHANGEPROC stop, CHANGEPROC current, CHANGEPROC rate);
|
||||
|
||||
/* Override the _Release function and call this when releasing */
|
||||
extern void Parser_Destroy(ParserImpl *This);
|
||||
|
|
|
@ -1205,7 +1205,7 @@ HRESULT OutputPin_DeliverDisconnect(OutputPin * This)
|
|||
|
||||
|
||||
static HRESULT PullPin_Init(const IPinVtbl *PullPin_Vtbl, const PIN_INFO * pPinInfo, SAMPLEPROC_PULL pSampleProc, LPVOID pUserData,
|
||||
QUERYACCEPTPROC pQueryAccept, CLEANUPPROC pCleanUp, REQUESTPROC pCustomRequest, LPCRITICAL_SECTION pCritSec, PullPin * pPinImpl)
|
||||
QUERYACCEPTPROC pQueryAccept, CLEANUPPROC pCleanUp, REQUESTPROC pCustomRequest, STOPPROCESSPROC pDone, LPCRITICAL_SECTION pCritSec, PullPin * pPinImpl)
|
||||
{
|
||||
/* Common attributes */
|
||||
pPinImpl->pin.lpVtbl = PullPin_Vtbl;
|
||||
|
@ -1220,6 +1220,7 @@ static HRESULT PullPin_Init(const IPinVtbl *PullPin_Vtbl, const PIN_INFO * pPinI
|
|||
/* Input pin attributes */
|
||||
pPinImpl->fnSampleProc = pSampleProc;
|
||||
pPinImpl->fnCleanProc = pCleanUp;
|
||||
pPinImpl->fnDone = pDone;
|
||||
pPinImpl->fnPreConnect = NULL;
|
||||
pPinImpl->pAlloc = NULL;
|
||||
pPinImpl->pReader = NULL;
|
||||
|
@ -1241,7 +1242,7 @@ static HRESULT PullPin_Init(const IPinVtbl *PullPin_Vtbl, const PIN_INFO * pPinI
|
|||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT PullPin_Construct(const IPinVtbl *PullPin_Vtbl, const PIN_INFO * pPinInfo, SAMPLEPROC_PULL pSampleProc, LPVOID pUserData, QUERYACCEPTPROC pQueryAccept, CLEANUPPROC pCleanUp, 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, REQUESTPROC pCustomRequest, STOPPROCESSPROC pDone, LPCRITICAL_SECTION pCritSec, IPin ** ppPin)
|
||||
{
|
||||
PullPin * pPinImpl;
|
||||
|
||||
|
@ -1258,7 +1259,7 @@ HRESULT PullPin_Construct(const IPinVtbl *PullPin_Vtbl, const PIN_INFO * pPinInf
|
|||
if (!pPinImpl)
|
||||
return E_OUTOFMEMORY;
|
||||
|
||||
if (SUCCEEDED(PullPin_Init(PullPin_Vtbl, pPinInfo, pSampleProc, pUserData, pQueryAccept, pCleanUp, pCustomRequest, pCritSec, pPinImpl)))
|
||||
if (SUCCEEDED(PullPin_Init(PullPin_Vtbl, pPinInfo, pSampleProc, pUserData, pQueryAccept, pCleanUp, pCustomRequest, pDone, pCritSec, pPinImpl)))
|
||||
{
|
||||
*ppPin = (IPin *)(&pPinImpl->pin.lpVtbl);
|
||||
return S_OK;
|
||||
|
@ -1381,6 +1382,9 @@ ULONG WINAPI PullPin_Release(IPin *iface)
|
|||
|
||||
if (!refCount)
|
||||
{
|
||||
WaitForSingleObject(This->hEventStateChanged, INFINITE);
|
||||
assert(!This->hThread);
|
||||
|
||||
if(This->pAlloc)
|
||||
IMemAllocator_Release(This->pAlloc);
|
||||
if(This->pReader)
|
||||
|
@ -1565,6 +1569,8 @@ static void CALLBACK PullPin_Thread_Process(PullPin *This)
|
|||
* Flush remaining samples
|
||||
*/
|
||||
PullPin_Flush(This);
|
||||
if (This->fnDone)
|
||||
This->fnDone(This->pin.pUserData);
|
||||
|
||||
TRACE("End: %08x, %d\n", hr, This->stop_playback);
|
||||
}
|
||||
|
|
|
@ -59,6 +59,11 @@ typedef HRESULT (* CLEANUPPROC) (LPVOID userdata);
|
|||
*/
|
||||
typedef HRESULT (* REQUESTPROC) (LPVOID userdata);
|
||||
|
||||
/* This function is called after processing is done (for whatever reason that is caused)
|
||||
* This is useful if you create processing threads that need to die
|
||||
*/
|
||||
typedef HRESULT (* STOPPROCESSPROC) (LPVOID userdata);
|
||||
|
||||
#define ALIGNDOWN(value,boundary) ((value)/(boundary)*(boundary))
|
||||
#define ALIGNUP(value,boundary) (ALIGNDOWN((value)+(boundary)-1, (boundary)))
|
||||
|
||||
|
@ -115,6 +120,7 @@ typedef struct PullPin
|
|||
PRECONNECTPROC fnPreConnect;
|
||||
REQUESTPROC fnCustomRequest;
|
||||
CLEANUPPROC fnCleanProc;
|
||||
STOPPROCESSPROC fnDone;
|
||||
double dRate;
|
||||
BOOL stop_playback;
|
||||
DWORD cbAlign;
|
||||
|
@ -138,7 +144,7 @@ typedef struct PullPin
|
|||
/*** Constructors ***/
|
||||
HRESULT InputPin_Construct(const IPinVtbl *InputPin_Vtbl, const PIN_INFO * pPinInfo, SAMPLEPROC_PUSH pSampleProc, LPVOID pUserData, QUERYACCEPTPROC pQueryAccept, CLEANUPPROC pCleanUp, LPCRITICAL_SECTION pCritSec, IPin ** ppPin);
|
||||
HRESULT OutputPin_Construct(const IPinVtbl *OutputPin_Vtbl, long outputpin_size, const PIN_INFO * pPinInfo, ALLOCATOR_PROPERTIES *props, LPVOID pUserData, QUERYACCEPTPROC pQueryAccept, 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, 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 ***/
|
||||
|
|
|
@ -459,7 +459,7 @@ HRESULT WAVEParser_create(IUnknown * pUnkOuter, LPVOID * ppv)
|
|||
|
||||
This->pCurrentSample = NULL;
|
||||
|
||||
hr = Parser_Create(&(This->Parser), &WAVEParser_Vtbl, &CLSID_WAVEParser, WAVEParser_Sample, WAVEParser_QueryAccept, WAVEParser_InputPin_PreConnect, WAVEParser_Cleanup, WAVEParser_disconnect, WAVEParser_first_request, NULL, WAVEParserImpl_seek, NULL);
|
||||
hr = Parser_Create(&(This->Parser), &WAVEParser_Vtbl, &CLSID_WAVEParser, WAVEParser_Sample, WAVEParser_QueryAccept, WAVEParser_InputPin_PreConnect, WAVEParser_Cleanup, WAVEParser_disconnect, WAVEParser_first_request, NULL, NULL, WAVEParserImpl_seek, NULL);
|
||||
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
|
Loading…
Reference in New Issue