From a2613024fdbe75303ded0285363a3f0022e192d1 Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Fri, 4 Jul 2008 00:09:07 -0700 Subject: [PATCH] quartz: Implement state transitions in directsound renderer and make it block on pause Some tests on video renderer indicate that it's the renderer that blocks --- dlls/quartz/dsoundrender.c | 81 ++++++++++++++++++++++++++++++++++++++++++-- 1 files changed, 78 insertions(+), 3 deletions(-) diff --git a/dlls/quartz/dsoundrender.c b/dlls/quartz/dsoundrender.c index e81acfb..9e6e7ed 100644 --- a/dlls/quartz/dsoundrender.c +++ b/dlls/quartz/dsoundrender.c @@ -73,6 +73,8 @@ typedef struct DSoundRenderImpl REFERENCE_TIME play_time; MediaSeekingImpl mediaSeeking; + HANDLE state_change, blocked; + long volume; long pan; } DSoundRenderImpl; @@ -246,6 +248,8 @@ static HRESULT DSoundRender_Sample(LPVOID iface, IMediaSample * pSample) if (This->state == State_Stopped) return VFW_E_WRONG_STATE; + SetEvent(This->state_change); + hr = IMediaSample_GetPointer(pSample, &pbSrcStream); if (FAILED(hr)) { @@ -270,7 +274,19 @@ static HRESULT DSoundRender_Sample(LPVOID iface, IMediaSample * pSample) } if (This->state == State_Paused) - return S_OK; + { + LeaveCriticalSection(&This->csFilter); + WaitForSingleObject(This->blocked, INFINITE); + EnterCriticalSection(&This->csFilter); + if (This->state == State_Stopped) + return VFW_E_WRONG_STATE; + + if (This->state == State_Paused) + { + /* Assuming we return because of flushing */ + return S_OK; + } + } cbSrcStream = IMediaSample_GetActualDataLength(pSample); TRACE("Sample data ptr = %p, size = %ld\n", pbSrcStream, cbSrcStream); @@ -359,6 +375,15 @@ HRESULT DSoundRender_create(IUnknown * pUnkOuter, LPVOID * ppv) MediaSeekingImpl_Init((IBaseFilter*)pDSoundRender, sound_mod_stop, sound_mod_start, sound_mod_rate, &pDSoundRender->mediaSeeking, &pDSoundRender->csFilter); pDSoundRender->mediaSeeking.lpVtbl = &IMediaSeeking_Vtbl; + pDSoundRender->state_change = CreateEventW(NULL, TRUE, TRUE, NULL); + pDSoundRender->blocked = CreateEventW(NULL, FALSE, FALSE, NULL); + + if (!pDSoundRender->state_change || !pDSoundRender->blocked) + { + IUnknown_Release((IUnknown *)pDSoundRender); + return HRESULT_FROM_WIN32(GetLastError()); + } + *ppv = (LPVOID)pDSoundRender; } else @@ -453,6 +478,9 @@ static ULONG WINAPI DSoundRender_Release(IBaseFilter * iface) This->csFilter.DebugInfo->Spare[0] = 0; DeleteCriticalSection(&This->csFilter); + CloseHandle(This->state_change); + CloseHandle(This->blocked); + TRACE("Destroying Audio Renderer\n"); CoTaskMemFree(This); @@ -497,6 +525,10 @@ static HRESULT WINAPI DSoundRender_Stop(IBaseFilter * iface) } if (SUCCEEDED(hr)) This->state = State_Stopped; + + /* Complete our transition */ + SetEvent(This->state_change); + SetEvent(This->blocked); } LeaveCriticalSection(&This->csFilter); @@ -511,10 +543,13 @@ static HRESULT WINAPI DSoundRender_Pause(IBaseFilter * iface) TRACE("(%p/%p)->()\n", This, iface); EnterCriticalSection(&This->csFilter); + if (This->state != State_Paused) { DWORD state = 0; if (This->state == State_Stopped) + { This->pInputPin->end_of_stream = 0; + } if (This->dsbuffer) { @@ -527,6 +562,9 @@ static HRESULT WINAPI DSoundRender_Pause(IBaseFilter * iface) } if (SUCCEEDED(hr)) This->state = State_Paused; + + ResetEvent(This->blocked); + ResetEvent(This->state_change); } LeaveCriticalSection(&This->csFilter); @@ -543,8 +581,18 @@ static HRESULT WINAPI DSoundRender_Run(IBaseFilter * iface, REFERENCE_TIME tStar EnterCriticalSection(&This->csFilter); { This->rtStreamStart = tStart; + if (This->state == State_Paused) + { + /* Unblock our thread, state changing from paused to running doesn't need a reset for state change */ + SetEvent(This->blocked); + } + else if (This->state == State_Stopped) + { + ResetEvent(This->state_change); + This->pInputPin->end_of_stream = 0; + } + This->state = State_Running; - This->pInputPin->end_of_stream = 0; } LeaveCriticalSection(&This->csFilter); @@ -553,10 +601,16 @@ static HRESULT WINAPI DSoundRender_Run(IBaseFilter * iface, REFERENCE_TIME tStar static HRESULT WINAPI DSoundRender_GetState(IBaseFilter * iface, DWORD dwMilliSecsTimeout, FILTER_STATE *pState) { + HRESULT hr; DSoundRenderImpl *This = (DSoundRenderImpl *)iface; TRACE("(%p/%p)->(%d, %p)\n", This, iface, dwMilliSecsTimeout, pState); + if (WaitForSingleObject(This->state_change, dwMilliSecsTimeout) == WAIT_TIMEOUT) + hr = VFW_S_STATE_INTERMEDIATE; + else + hr = S_OK; + EnterCriticalSection(&This->csFilter); { *pState = This->state; @@ -866,6 +920,27 @@ static HRESULT WINAPI DSoundRender_InputPin_BeginFlush(IPin * iface) memset(buffer, 0, size); IDirectSoundBuffer_Unlock(pFilter->dsbuffer, buffer, size, NULL, 0); } + + if (pFilter->state == State_Paused) + SetEvent(pFilter->blocked); + LeaveCriticalSection(This->pin.pCritSec); + + return hr; +} + +static HRESULT WINAPI DSoundRender_InputPin_EndFlush(IPin * iface) +{ + InputPin *This = (InputPin *)iface; + DSoundRenderImpl *pFilter = (DSoundRenderImpl *)This->pin.pinInfo.pFilter; + HRESULT hr; + + TRACE("\n"); + + EnterCriticalSection(This->pin.pCritSec); + hr = InputPin_EndFlush(iface); + + if (pFilter->state == State_Paused) + SetEvent(pFilter->blocked); LeaveCriticalSection(This->pin.pCritSec); return hr; @@ -889,7 +964,7 @@ static const IPinVtbl DSoundRender_InputPin_Vtbl = IPinImpl_QueryInternalConnections, DSoundRender_InputPin_EndOfStream, DSoundRender_InputPin_BeginFlush, - InputPin_EndFlush, + DSoundRender_InputPin_EndFlush, InputPin_NewSegment }; -- 1.5.4.1