Aric Stewart : strmbase: Add OutputQueue_EOS implementation.

Alexandre Julliard julliard at winehq.org
Wed Apr 6 11:36:36 CDT 2011


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

Author: Aric Stewart <aric at codeweavers.com>
Date:   Tue Apr  5 12:55:50 2011 -0500

strmbase: Add OutputQueue_EOS implementation.

---

 dlls/strmbase/outputqueue.c |  136 +++++++++++++++++++++++++++++++++++--------
 include/wine/strmbase.h     |    3 +
 2 files changed, 115 insertions(+), 24 deletions(-)

diff --git a/dlls/strmbase/outputqueue.c b/dlls/strmbase/outputqueue.c
index 100b845..200e2da 100644
--- a/dlls/strmbase/outputqueue.c
+++ b/dlls/strmbase/outputqueue.c
@@ -31,7 +31,10 @@
 
 WINE_DEFAULT_DEBUG_CHANNEL(strmbase);
 
+enum {SAMPLE_PACKET, EOS_PACKET};
+
 typedef struct tagQueuedEvent {
+    int type;
     struct list entry;
 
     IMediaSample *pSample;
@@ -163,6 +166,7 @@ HRESULT WINAPI OutputQueue_ReceiveMultiple(OutputQueue *pOutputQueue, IMediaSamp
                 hr = E_OUTOFMEMORY;
                 break;
             }
+            qev->type = SAMPLE_PACKET;
             qev->pSample = ppSamples[i];
             IMediaSample_AddRef(ppSamples[i]);
             list_add_tail(pOutputQueue->SampleList, &qev->entry);
@@ -182,40 +186,124 @@ HRESULT WINAPI OutputQueue_Receive(OutputQueue *pOutputQueue, IMediaSample *pSam
     return OutputQueue_ReceiveMultiple(pOutputQueue,&pSample,1,&processed);
 }
 
+VOID WINAPI OutputQueue_SendAnyway(OutputQueue *pOutputQueue)
+{
+    if (pOutputQueue->hThread)
+    {
+        EnterCriticalSection(&pOutputQueue->csQueue);
+        if (list_count(pOutputQueue->SampleList) > 0)
+        {
+            pOutputQueue->bSendAnyway = TRUE;
+            SetEvent(pOutputQueue->hProcessQueue);
+        }
+        LeaveCriticalSection(&pOutputQueue->csQueue);
+    }
+}
+
+VOID WINAPI OutputQueue_EOS(OutputQueue *pOutputQueue)
+{
+    EnterCriticalSection(&pOutputQueue->csQueue);
+    if (pOutputQueue->hThread)
+    {
+        QueuedEvent *qev = HeapAlloc(GetProcessHeap(),0,sizeof(QueuedEvent));
+        if (!qev)
+        {
+            ERR("Out of Memory\n");
+            LeaveCriticalSection(&pOutputQueue->csQueue);
+            return;
+        }
+        qev->type = EOS_PACKET;
+        qev->pSample = NULL;
+        list_add_tail(pOutputQueue->SampleList, &qev->entry);
+    }
+    else
+    {
+        IPin* ppin = NULL;
+        IPin_ConnectedTo((IPin*)pOutputQueue->pInputPin, &ppin);
+        if (ppin)
+        {
+            IPin_EndOfStream(ppin);
+            IPin_Release(ppin);
+        }
+    }
+    LeaveCriticalSection(&pOutputQueue->csQueue);
+    /* Covers sending the Event to the worker Thread */
+    OutputQueue_SendAnyway(pOutputQueue);
+}
+
 DWORD WINAPI OutputQueueImpl_ThreadProc(OutputQueue *pOutputQueue)
 {
     do
     {
         EnterCriticalSection(&pOutputQueue->csQueue);
         if (list_count(pOutputQueue->SampleList) > 0 &&
-             (!pOutputQueue->bBatchExact ||
-              list_count(pOutputQueue->SampleList) >= pOutputQueue->lBatchSize))
+            (!pOutputQueue->bBatchExact ||
+            list_count(pOutputQueue->SampleList) >= pOutputQueue->lBatchSize ||
+            pOutputQueue->bSendAnyway
+            )
+           )
         {
-            IMediaSample **ppSamples;
-            LONG nSamples;
-            LONG nSamplesProcessed;
-            struct list *cursor, *cursor2;
-            int i = 0;
-
-            nSamples = list_count(pOutputQueue->SampleList);
-            ppSamples = HeapAlloc(GetProcessHeap(),0,sizeof(IMediaSample*) * nSamples);
-            LIST_FOR_EACH_SAFE(cursor, cursor2, pOutputQueue->SampleList)
+            while (list_count(pOutputQueue->SampleList) > 0)
             {
-                QueuedEvent *qev = LIST_ENTRY(cursor, QueuedEvent, entry);
-                list_remove(cursor);
-                ppSamples[i++] = qev->pSample;
-                HeapFree(GetProcessHeap(),0,qev);
-            }
+                IMediaSample **ppSamples;
+                LONG nSamples;
+                LONG nSamplesProcessed;
+                struct list *cursor, *cursor2;
+                int i = 0;
 
-            if (pOutputQueue->pInputPin->pin.pConnectedTo && pOutputQueue->pInputPin->pMemInputPin)
-            {
-                IMemInputPin_AddRef(pOutputQueue->pInputPin->pMemInputPin);
-                IMemInputPin_ReceiveMultiple(pOutputQueue->pInputPin->pMemInputPin, ppSamples, nSamples, &nSamplesProcessed);
-                IMemInputPin_Release(pOutputQueue->pInputPin->pMemInputPin);
+                /* First Pass Process Samples */
+                i = list_count(pOutputQueue->SampleList);
+                ppSamples = HeapAlloc(GetProcessHeap(),0,sizeof(IMediaSample*) * i);
+                nSamples = 0;
+                LIST_FOR_EACH_SAFE(cursor, cursor2, pOutputQueue->SampleList)
+                {
+                    QueuedEvent *qev = LIST_ENTRY(cursor, QueuedEvent, entry);
+                    if (qev->type == SAMPLE_PACKET)
+                        ppSamples[nSamples++] = qev->pSample;
+                    else
+                        break;
+                    list_remove(cursor);
+                    HeapFree(GetProcessHeap(),0,qev);
+                }
+
+                if (pOutputQueue->pInputPin->pin.pConnectedTo && pOutputQueue->pInputPin->pMemInputPin)
+                {
+                    IMemInputPin_AddRef(pOutputQueue->pInputPin->pMemInputPin);
+                    LeaveCriticalSection(&pOutputQueue->csQueue);
+                    IMemInputPin_ReceiveMultiple(pOutputQueue->pInputPin->pMemInputPin, ppSamples, nSamples, &nSamplesProcessed);
+                    EnterCriticalSection(&pOutputQueue->csQueue);
+                    IMemInputPin_Release(pOutputQueue->pInputPin->pMemInputPin);
+                }
+                for (i = 0; i < nSamples; i++)
+                    IUnknown_Release(ppSamples[i]);
+                HeapFree(GetProcessHeap(),0,ppSamples);
+
+                /* Process Non-Samples */
+                if (list_count(pOutputQueue->SampleList) > 0)
+                {
+                    LIST_FOR_EACH_SAFE(cursor, cursor2, pOutputQueue->SampleList)
+                    {
+                        QueuedEvent *qev = LIST_ENTRY(cursor, QueuedEvent, entry);
+                        if (qev->type == EOS_PACKET)
+                        {
+                            IPin* ppin = NULL;
+                            IPin_ConnectedTo((IPin*)pOutputQueue->pInputPin, &ppin);
+                            if (ppin)
+                            {
+                                IPin_EndOfStream(ppin);
+                                IPin_Release(ppin);
+                            }
+                        }
+                        else if (qev->type == SAMPLE_PACKET)
+                            break;
+                        else
+                            FIXME("Unhandled Event type %i\n",qev->type);
+                        list_remove(cursor);
+                        HeapFree(GetProcessHeap(),0,qev);
+                    }
+                }
             }
-            for (i = 0; i < nSamples; i++)
-                IUnknown_Release(ppSamples[i]);
-            HeapFree(GetProcessHeap(),0,ppSamples);
+            pOutputQueue->bSendAnyway = FALSE;
         }
         LeaveCriticalSection(&pOutputQueue->csQueue);
         WaitForSingleObject(pOutputQueue->hProcessQueue, INFINITE);
diff --git a/include/wine/strmbase.h b/include/wine/strmbase.h
index 7063e79..3d06bf8 100644
--- a/include/wine/strmbase.h
+++ b/include/wine/strmbase.h
@@ -358,6 +358,7 @@ typedef struct tagOutputQueue {
     LONG lBatchSize;
     BOOL bBatchExact;
     BOOL bTerminate;
+    BOOL bSendAnyway;
 
     struct list *SampleList;
 
@@ -377,6 +378,8 @@ HRESULT WINAPI OutputQueue_Construct( BaseOutputPin *pInputPin, BOOL bAuto,
 HRESULT WINAPI OutputQueue_Destroy(OutputQueue *pOutputQueue);
 HRESULT WINAPI OutputQueue_ReceiveMultiple(OutputQueue *pOutputQueue, IMediaSample **ppSamples, LONG nSamples, LONG *nSamplesProcessed);
 HRESULT WINAPI OutputQueue_Receive(OutputQueue *pOutputQueue, IMediaSample *pSample);
+VOID WINAPI OutputQueue_EOS(OutputQueue *pOutputQueue);
+VOID WINAPI OutputQueue_SendAnyway(OutputQueue *pOutputQueue);
 DWORD WINAPI OutputQueueImpl_ThreadProc(OutputQueue *pOutputQueue);
 
 /* Dll Functions */




More information about the wine-cvs mailing list