Maarten Lankhorst : quartz: Fix parser/ pullpin to only care about the state transition stopped<->playing.
Alexandre Julliard
julliard at winehq.org
Mon Jul 7 09:19:09 CDT 2008
Module: wine
Branch: master
Commit: 53782ca47acfa8e5d7ae72b59602840e3b35cd81
URL: http://source.winehq.org/git/wine.git/?a=commit;h=53782ca47acfa8e5d7ae72b59602840e3b35cd81
Author: Maarten Lankhorst <m.b.lankhorst at gmail.com>
Date: Fri Jul 4 18:43:05 2008 -0700
quartz: Fix parser/pullpin to only care about the state transition stopped<->playing.
---
dlls/quartz/parser.c | 36 +++++++++++++++-----
dlls/quartz/pin.c | 88 ++++++++++++++++++++++++++++++++++++-------------
dlls/quartz/pin.h | 3 +-
3 files changed, 93 insertions(+), 34 deletions(-)
diff --git a/dlls/quartz/parser.c b/dlls/quartz/parser.c
index 97be991..0848e84 100644
--- a/dlls/quartz/parser.c
+++ b/dlls/quartz/parser.c
@@ -219,15 +219,35 @@ HRESULT WINAPI Parser_Stop(IBaseFilter * iface)
{
ParserImpl *This = (ParserImpl *)iface;
PullPin *pin = (PullPin *)This->ppPins[0];
+ int i;
TRACE("()\n");
EnterCriticalSection(&pin->thread_lock);
+
+ IAsyncReader_BeginFlush(This->pInputPin->pReader);
EnterCriticalSection(&This->csFilter);
+
+ if (This->state == State_Stopped)
{
- This->state = State_Stopped;
+ LeaveCriticalSection(&This->csFilter);
+ LeaveCriticalSection(&pin->thread_lock);
+ return S_OK;
}
+
+ This->state = State_Stopped;
+
+ for (i = 1; i < (This->cStreams + 1); i++)
+ {
+ OutputPin_DecommitAllocator((OutputPin *)This->ppPins[i]);
+ }
+
LeaveCriticalSection(&This->csFilter);
+
+ PullPin_PauseProcessing(This->pInputPin);
+ PullPin_WaitForStateChange(This->pInputPin, INFINITE);
+ IAsyncReader_EndFlush(This->pInputPin->pReader);
+
LeaveCriticalSection(&pin->thread_lock);
return S_OK;
}
@@ -260,8 +280,6 @@ HRESULT WINAPI Parser_Pause(IBaseFilter * iface)
This->state = State_Paused;
LeaveCriticalSection(&This->csFilter);
- if (SUCCEEDED(hr))
- hr = PullPin_PauseProcessing(This->pInputPin);
LeaveCriticalSection(&pin->thread_lock);
return hr;
@@ -280,8 +298,9 @@ HRESULT WINAPI Parser_Run(IBaseFilter * iface, REFERENCE_TIME tStart)
EnterCriticalSection(&pin->thread_lock);
EnterCriticalSection(&This->csFilter);
{
- if (This->state == State_Running)
+ if (This->state == State_Running || This->state == State_Paused)
{
+ This->state = State_Running;
LeaveCriticalSection(&This->csFilter);
LeaveCriticalSection(&pin->thread_lock);
return S_OK;
@@ -289,12 +308,11 @@ HRESULT WINAPI Parser_Run(IBaseFilter * iface, REFERENCE_TIME tStart)
This->rtStreamStart = tStart;
- if (SUCCEEDED(hr) && (This->state == State_Stopped))
+ for (i = 1; i < (This->cStreams + 1); i++)
{
- for (i = 1; i < (This->cStreams + 1); i++)
- {
- OutputPin_CommitAllocator((OutputPin *)This->ppPins[i]);
- }
+ hr = OutputPin_CommitAllocator((OutputPin *)This->ppPins[i]);
+ if (FAILED(hr))
+ break;
}
if (SUCCEEDED(hr))
diff --git a/dlls/quartz/pin.c b/dlls/quartz/pin.c
index 5bce9bb..0ecf055 100644
--- a/dlls/quartz/pin.c
+++ b/dlls/quartz/pin.c
@@ -1175,6 +1175,35 @@ HRESULT OutputPin_CommitAllocator(OutputPin * This)
return hr;
}
+HRESULT OutputPin_DecommitAllocator(OutputPin * This)
+{
+ HRESULT hr = S_OK;
+
+ TRACE("(%p)->()\n", This);
+
+ EnterCriticalSection(This->pin.pCritSec);
+ {
+ if (!This->pin.pConnectedTo || !This->pMemInputPin)
+ hr = VFW_E_NOT_CONNECTED;
+ else
+ {
+ IMemAllocator * pAlloc = NULL;
+
+ hr = IMemInputPin_GetAllocator(This->pMemInputPin, &pAlloc);
+
+ if (SUCCEEDED(hr))
+ hr = IMemAllocator_Decommit(pAlloc);
+
+ if (pAlloc)
+ IMemAllocator_Release(pAlloc);
+ }
+ }
+ LeaveCriticalSection(This->pin.pCritSec);
+
+ TRACE("--> %08x\n", hr);
+ return hr;
+}
+
HRESULT OutputPin_DeliverDisconnect(OutputPin * This)
{
HRESULT hr;
@@ -1416,11 +1445,11 @@ static void CALLBACK PullPin_Flush(PullPin *This)
IMediaSample *pSample;
TRACE("Flushing!\n");
- EnterCriticalSection(This->pin.pCritSec);
if (This->pReader)
{
/* Flush outstanding samples */
IAsyncReader_BeginFlush(This->pReader);
+
for (;;)
{
DWORD_PTR dwUser;
@@ -1437,10 +1466,9 @@ static void CALLBACK PullPin_Flush(PullPin *This)
IAsyncReader_EndFlush(This->pReader);
}
- LeaveCriticalSection(This->pin.pCritSec);
}
-static void CALLBACK PullPin_Thread_Process(PullPin *This, BOOL pause)
+static void CALLBACK PullPin_Thread_Process(PullPin *This)
{
HRESULT hr;
IMediaSample * pSample = NULL;
@@ -1467,12 +1495,9 @@ static void CALLBACK PullPin_Thread_Process(PullPin *This, BOOL pause)
if (FAILED(hr))
ERR("Request error: %x\n", hr);
- if (!pause)
- {
- EnterCriticalSection(This->pin.pCritSec);
- SetEvent(This->hEventStateChanged);
- LeaveCriticalSection(This->pin.pCritSec);
- }
+ EnterCriticalSection(This->pin.pCritSec);
+ SetEvent(This->hEventStateChanged);
+ LeaveCriticalSection(This->pin.pCritSec);
if (SUCCEEDED(hr))
do
@@ -1510,23 +1535,20 @@ static void CALLBACK PullPin_Thread_Process(PullPin *This, BOOL pause)
/* Can't reset state to Sleepy here because that might race, instead PauseProcessing will do that for us
* Flush remaining samples
*/
- TRACE("Almost done..\n");
-
if (This->fnDone)
This->fnDone(This->pin.pUserData);
- if (pause)
- {
- EnterCriticalSection(This->pin.pCritSec);
- This->state = Req_Sleepy;
- SetEvent(This->hEventStateChanged);
- LeaveCriticalSection(This->pin.pCritSec);
- }
-
-
TRACE("End: %08x, %d\n", hr, This->stop_playback);
}
+static void CALLBACK PullPin_Thread_Pause(PullPin *This)
+{
+ EnterCriticalSection(This->pin.pCritSec);
+ This->state = Req_Sleepy;
+ SetEvent(This->hEventStateChanged);
+ LeaveCriticalSection(This->pin.pCritSec);
+}
+
static void CALLBACK PullPin_Thread_Stop(PullPin *This)
{
TRACE("(%p)->()\n", This);
@@ -1545,6 +1567,16 @@ static void CALLBACK PullPin_Thread_Stop(PullPin *This)
ExitThread(0);
}
+static void CALLBACK PullPin_Thread_Flush(PullPin *This)
+{
+ PullPin_Flush(This);
+
+ EnterCriticalSection(This->pin.pCritSec);
+ This->state = Req_Sleepy;
+ SetEvent(This->hEventStateChanged);
+ LeaveCriticalSection(This->pin.pCritSec);
+}
+
static DWORD WINAPI PullPin_Thread_Main(LPVOID pv)
{
PullPin *This = pv;
@@ -1561,8 +1593,9 @@ static DWORD WINAPI PullPin_Thread_Main(LPVOID pv)
switch (This->state)
{
case Req_Die: PullPin_Thread_Stop(This); break;
- case Req_Run: PullPin_Thread_Process(This, FALSE); break;
- case Req_Pause: PullPin_Thread_Process(This, TRUE); break;
+ case Req_Run: PullPin_Thread_Process(This); break;
+ case Req_Pause: PullPin_Thread_Pause(This); break;
+ case Req_Flush: PullPin_Thread_Flush(This); break;
case Req_Sleepy: ERR("Should not be signalled with SLEEPY!\n"); break;
default: ERR("Unknown state request: %d\n", This->state); break;
}
@@ -1710,13 +1743,20 @@ HRESULT WINAPI PullPin_BeginFlush(IPin * iface)
EnterCriticalSection(&This->thread_lock);
{
+ if (This->pReader)
+ IAsyncReader_BeginFlush(This->pReader);
PullPin_WaitForStateChange(This, INFINITE);
- if (This->hThread && !This->stop_playback)
+ if (This->hThread && This->state == Req_Run)
{
PullPin_PauseProcessing(This);
PullPin_WaitForStateChange(This, INFINITE);
}
+
+ This->state = Req_Flush;
+ ResetEvent(This->hEventStateChanged);
+ SetEvent(This->thread_sleepy);
+ PullPin_WaitForStateChange(This, INFINITE);
}
LeaveCriticalSection(&This->thread_lock);
@@ -1740,7 +1780,7 @@ HRESULT WINAPI PullPin_EndFlush(IPin * iface)
FILTER_STATE state;
IBaseFilter_GetState(This->pin.pinInfo.pFilter, INFINITE, &state);
- if (This->stop_playback && state == State_Running)
+ if (This->stop_playback && state != State_Stopped)
PullPin_StartProcessing(This);
PullPin_WaitForStateChange(This, INFINITE);
diff --git a/dlls/quartz/pin.h b/dlls/quartz/pin.h
index b67ff1b..4170ca5 100644
--- a/dlls/quartz/pin.h
+++ b/dlls/quartz/pin.h
@@ -52,7 +52,6 @@ typedef HRESULT (* CLEANUPPROC) (LPVOID userdata);
* If you implement it (it can be NULL for default behavior), you have to
* call IMemAllocator_GetBuffer and IMemAllocator_RequestBuffer
* This is useful if you want to request more than 1 buffer at simultaneously
- * If PullPin->flushed is set, it means that all buffers queued previously are gone
*
* This will also cause the Sample Proc to be called with empty buffers to indicate
* failure in retrieving the sample.
@@ -141,6 +140,7 @@ typedef struct PullPin
#define Req_Die 1
#define Req_Run 2
#define Req_Pause 3
+#define Req_Flush 4
/*** 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);
@@ -184,6 +184,7 @@ HRESULT WINAPI OutputPin_EndFlush(IPin * iface);
HRESULT WINAPI OutputPin_NewSegment(IPin * iface, REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate);
HRESULT OutputPin_CommitAllocator(OutputPin * This);
+HRESULT OutputPin_DecommitAllocator(OutputPin * This);
HRESULT OutputPin_GetDeliveryBuffer(OutputPin * This, IMediaSample ** ppSample, REFERENCE_TIME * tStart, REFERENCE_TIME * tStop, DWORD dwFlags);
HRESULT OutputPin_SendSample(OutputPin * This, IMediaSample * pSample);
HRESULT OutputPin_DeliverDisconnect(OutputPin * This);
More information about the wine-cvs
mailing list