Maarten Lankhorst : quartz: Implement state transitions in video renderer.

Alexandre Julliard julliard at winehq.org
Fri Jul 4 13:59:19 CDT 2008


Module: wine
Branch: master
Commit: 9985f2efc9d1e92932dd3d7f351ded3ae1db0b80
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=9985f2efc9d1e92932dd3d7f351ded3ae1db0b80

Author: Maarten Lankhorst <m.b.lankhorst at gmail.com>
Date:   Fri Jul  4 01:33:04 2008 -0700

quartz: Implement state transitions in video renderer.

---

 dlls/quartz/videorenderer.c |  101 +++++++++++++++++++++++++++++++++---------
 1 files changed, 79 insertions(+), 22 deletions(-)

diff --git a/dlls/quartz/videorenderer.c b/dlls/quartz/videorenderer.c
index 23a5cd9..1ade1c8 100644
--- a/dlls/quartz/videorenderer.c
+++ b/dlls/quartz/videorenderer.c
@@ -71,6 +71,8 @@ typedef struct VideoRendererImpl
 
     BOOL init;
     HANDLE hThread;
+    HANDLE blocked;
+
     DWORD ThreadID;
     HANDLE hEvent;
     BOOL ThreadResult;
@@ -231,7 +233,7 @@ static DWORD WINAPI MessageLoop(LPVOID lpParameter)
 
 static BOOL CreateRenderingSubsystem(VideoRendererImpl* This)
 {
-    This->hEvent = CreateEventW(NULL, FALSE, FALSE, NULL);
+    This->hEvent = CreateEventW(NULL, TRUE, FALSE, NULL);
     if (!This->hEvent)
         return FALSE;
 
@@ -243,10 +245,10 @@ static BOOL CreateRenderingSubsystem(VideoRendererImpl* This)
     }
 
     WaitForSingleObject(This->hEvent, INFINITE);
-    CloseHandle(This->hEvent);
 
     if (!This->ThreadResult)
     {
+        CloseHandle(This->hEvent);
         CloseHandle(This->hThread);
         return FALSE;
     }
@@ -411,13 +413,19 @@ static HRESULT VideoRenderer_Sample(LPVOID iface, IMediaSample * pSample)
     }
 #endif
 
+    SetEvent(This->hEvent);
     if (This->state == State_Paused)
     {
-        if (This->sample_held)
-            IMediaSample_Release(This->sample_held);
-
         This->sample_held = pSample;
-        IMediaSample_AddRef(pSample);
+        LeaveCriticalSection(&This->csFilter);
+        WaitForSingleObject(This->blocked, INFINITE);
+        EnterCriticalSection(&This->csFilter);
+        This->sample_held = NULL;
+        if (This->state == State_Paused)
+            /* Flushing */
+            return S_OK;
+        if (This->state == State_Stopped)
+            return VFW_E_WRONG_STATE;
     }
 
     if (This->pClock && This->state == State_Running)
@@ -611,7 +619,14 @@ HRESULT VideoRenderer_create(IUnknown * pUnkOuter, LPVOID * ppv)
 
     if (!CreateRenderingSubsystem(pVideoRenderer))
         return E_FAIL;
-    
+
+    pVideoRenderer->blocked = CreateEventW(NULL, FALSE, FALSE, NULL);
+    if (!pVideoRenderer->blocked)
+    {
+        hr = HRESULT_FROM_WIN32(GetLastError());
+        IUnknown_Release((IUnknown *)pVideoRenderer);
+    }
+
     return hr;
 }
 
@@ -683,6 +698,7 @@ static ULONG WINAPI VideoRendererInner_Release(IUnknown * iface)
         PostThreadMessageA(This->ThreadID, WM_QUIT, 0, 0);
         WaitForSingleObject(This->hThread, INFINITE);
         CloseHandle(This->hThread);
+        CloseHandle(This->hEvent);
 
         if (This->pClock)
             IReferenceClock_Release(This->pClock);
@@ -789,12 +805,8 @@ static HRESULT WINAPI VideoRenderer_Stop(IBaseFilter * iface)
     EnterCriticalSection(&This->csFilter);
     {
         This->state = State_Stopped;
-
-        if (This->sample_held)
-        {
-            IMediaSample_Release(This->sample_held);
-            This->sample_held = NULL;
-        }
+        SetEvent(This->hEvent);
+        SetEvent(This->blocked);
     }
     LeaveCriticalSection(&This->csFilter);
 
@@ -808,11 +820,16 @@ static HRESULT WINAPI VideoRenderer_Pause(IBaseFilter * iface)
     TRACE("(%p/%p)->()\n", This, iface);
 
     EnterCriticalSection(&This->csFilter);
+    if (This->state != State_Paused)
     {
         if (This->state == State_Stopped)
+        {
             This->pInputPin->end_of_stream = 0;
+            ResetEvent(This->hEvent);
+        }
 
         This->state = State_Paused;
+        ResetEvent(This->blocked);
     }
     LeaveCriticalSection(&This->csFilter);
 
@@ -829,16 +846,14 @@ static HRESULT WINAPI VideoRenderer_Run(IBaseFilter * iface, REFERENCE_TIME tSta
     if (This->state != State_Running)
     {
         if (This->state == State_Stopped)
+        {
             This->pInputPin->end_of_stream = 0;
+            ResetEvent(This->hEvent);
+        }
+        SetEvent(This->blocked);
 
         This->rtStreamStart = tStart;
         This->state = State_Running;
-
-        if (This->sample_held)
-        {
-            IMediaSample_Release(This->sample_held);
-            This->sample_held = NULL;
-        }
     }
     LeaveCriticalSection(&This->csFilter);
 
@@ -848,16 +863,22 @@ static HRESULT WINAPI VideoRenderer_Run(IBaseFilter * iface, REFERENCE_TIME tSta
 static HRESULT WINAPI VideoRenderer_GetState(IBaseFilter * iface, DWORD dwMilliSecsTimeout, FILTER_STATE *pState)
 {
     VideoRendererImpl *This = (VideoRendererImpl *)iface;
+    HRESULT hr;
 
     TRACE("(%p/%p)->(%d, %p)\n", This, iface, dwMilliSecsTimeout, pState);
 
+    if (WaitForSingleObject(This->hEvent, dwMilliSecsTimeout) == WAIT_TIMEOUT)
+        hr = VFW_S_STATE_INTERMEDIATE;
+    else
+        hr = S_OK;
+
     EnterCriticalSection(&This->csFilter);
     {
         *pState = This->state;
     }
     LeaveCriticalSection(&This->csFilter);
 
-    return S_OK;
+    return hr;
 }
 
 static HRESULT WINAPI VideoRenderer_SetSyncSource(IBaseFilter * iface, IReferenceClock *pClock)
@@ -1013,6 +1034,42 @@ static HRESULT WINAPI VideoRenderer_InputPin_EndOfStream(IPin * iface)
     return hr;
 }
 
+static HRESULT WINAPI VideoRenderer_InputPin_BeginFlush(IPin * iface)
+{
+    InputPin* This = (InputPin*)iface;
+    VideoRendererImpl *pVideoRenderer = (VideoRendererImpl *)This->pin.pinInfo.pFilter;
+    HRESULT hr;
+
+    TRACE("(%p/%p)->()\n", This, iface);
+
+    EnterCriticalSection(This->pin.pCritSec);
+    if (pVideoRenderer->state == State_Paused)
+        SetEvent(pVideoRenderer->blocked);
+
+    hr = InputPin_BeginFlush(iface);
+    LeaveCriticalSection(This->pin.pCritSec);
+
+    return hr;
+}
+
+static HRESULT WINAPI VideoRenderer_InputPin_EndFlush(IPin * iface)
+{
+    InputPin* This = (InputPin*)iface;
+    VideoRendererImpl *pVideoRenderer = (VideoRendererImpl *)This->pin.pinInfo.pFilter;
+    HRESULT hr;
+
+    TRACE("(%p/%p)->()\n", This, iface);
+
+    EnterCriticalSection(This->pin.pCritSec);
+    if (pVideoRenderer->state == State_Paused)
+        ResetEvent(pVideoRenderer->blocked);
+
+    hr = InputPin_EndFlush(iface);
+    LeaveCriticalSection(This->pin.pCritSec);
+
+    return hr;
+}
+
 static const IPinVtbl VideoRenderer_InputPin_Vtbl = 
 {
     InputPin_QueryInterface,
@@ -1030,8 +1087,8 @@ static const IPinVtbl VideoRenderer_InputPin_Vtbl =
     IPinImpl_EnumMediaTypes,
     IPinImpl_QueryInternalConnections,
     VideoRenderer_InputPin_EndOfStream,
-    InputPin_BeginFlush,
-    InputPin_EndFlush,
+    VideoRenderer_InputPin_BeginFlush,
+    VideoRenderer_InputPin_EndFlush,
     InputPin_NewSegment
 };
 




More information about the wine-cvs mailing list