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