Aric Stewart : strmbase: Create OutputQueue for queuing outgoing samples.

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


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

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

strmbase: Create OutputQueue for queuing outgoing samples.

---

 dlls/strmbase/Makefile.in   |    1 +
 dlls/strmbase/outputqueue.c |  225 +++++++++++++++++++++++++++++++++++++++++++
 include/wine/strmbase.h     |   33 +++++++
 3 files changed, 259 insertions(+), 0 deletions(-)

diff --git a/dlls/strmbase/Makefile.in b/dlls/strmbase/Makefile.in
index 9ecb169..8c19a56 100644
--- a/dlls/strmbase/Makefile.in
+++ b/dlls/strmbase/Makefile.in
@@ -5,6 +5,7 @@ C_SRCS = \
 	enumpins.c \
 	filter.c \
 	mediatype.c \
+	outputqueue.c \
 	pin.c \
 	qualitycontrol.c \
 	seeking.c \
diff --git a/dlls/strmbase/outputqueue.c b/dlls/strmbase/outputqueue.c
new file mode 100644
index 0000000..100b845
--- /dev/null
+++ b/dlls/strmbase/outputqueue.c
@@ -0,0 +1,225 @@
+/*
+ * Generic Implementation of COutputQueue
+ *
+ * Copyright 2011 Aric Stewart, CodeWeavers
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#define COBJMACROS
+
+#include "dshow.h"
+#include "wine/debug.h"
+#include "wine/unicode.h"
+#include "wine/list.h"
+#include "wine/strmbase.h"
+#include "uuids.h"
+#include "vfwmsgs.h"
+#include <assert.h>
+
+WINE_DEFAULT_DEBUG_CHANNEL(strmbase);
+
+typedef struct tagQueuedEvent {
+    struct list entry;
+
+    IMediaSample *pSample;
+} QueuedEvent;
+
+static DWORD WINAPI OutputQueue_InitialThreadProc(LPVOID data)
+{
+    OutputQueue *This = (OutputQueue *)data;
+    return This->pFuncsTable->pfnThreadProc(This);
+}
+
+static void OutputQueue_FreeSamples(OutputQueue *pOutputQueue)
+{
+    struct list *cursor, *cursor2;
+    LIST_FOR_EACH_SAFE(cursor, cursor2, pOutputQueue->SampleList)
+    {
+        QueuedEvent *qev = LIST_ENTRY(cursor, QueuedEvent, entry);
+        list_remove(cursor);
+        HeapFree(GetProcessHeap(),0,qev);
+    }
+}
+
+HRESULT WINAPI OutputQueue_Construct(
+    BaseOutputPin *pInputPin,
+    BOOL bAuto,
+    BOOL bQueue,
+    LONG lBatchSize,
+    BOOL bBatchExact,
+    DWORD dwPriority,
+    const OutputQueueFuncTable* pFuncsTable,
+    OutputQueue **ppOutputQueue )
+
+{
+    HRESULT hr = S_OK;
+    BOOL threaded = FALSE;
+    DWORD tid;
+
+    OutputQueue *This;
+
+    if (!pInputPin || !pFuncsTable || !ppOutputQueue)
+        return E_INVALIDARG;
+
+    *ppOutputQueue = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(OutputQueue));
+    if (!*ppOutputQueue)
+        return E_OUTOFMEMORY;
+
+    This = *ppOutputQueue;
+    This->pFuncsTable = pFuncsTable;
+    This->lBatchSize = lBatchSize;
+    This->bBatchExact = bBatchExact;
+    InitializeCriticalSection(&This->csQueue);
+    This->csQueue.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": OutputQueue.csQueue");
+    This->SampleList = HeapAlloc(GetProcessHeap(),0,sizeof(struct list));
+    if (!This->SampleList)
+    {
+        OutputQueue_Destroy(This);
+        *ppOutputQueue = NULL;
+        return E_OUTOFMEMORY;
+    }
+    list_init(This->SampleList);
+
+    This->pInputPin = pInputPin;
+    IPin_AddRef((IPin*)pInputPin);
+
+    EnterCriticalSection(&This->csQueue);
+    if (bAuto && pInputPin->pMemInputPin)
+        threaded = IMemInputPin_ReceiveCanBlock(pInputPin->pMemInputPin);
+    else
+        threaded = bQueue;
+
+    if (threaded)
+    {
+        This->hThread = CreateThread(NULL, 0, OutputQueue_InitialThreadProc, This, 0, &tid);
+        if (This->hThread)
+        {
+            SetThreadPriority(This->hThread, dwPriority);
+            This->hProcessQueue = CreateEventW(NULL, 0, 0, NULL);
+        }
+    }
+    LeaveCriticalSection(&This->csQueue);
+
+    return hr;
+}
+
+HRESULT WINAPI OutputQueue_Destroy(OutputQueue *pOutputQueue)
+{
+    EnterCriticalSection(&pOutputQueue->csQueue);
+    OutputQueue_FreeSamples(pOutputQueue);
+    pOutputQueue->bTerminate = TRUE;
+    SetEvent(pOutputQueue->hProcessQueue);
+    LeaveCriticalSection(&pOutputQueue->csQueue);
+
+    DeleteCriticalSection(&pOutputQueue->csQueue);
+    CloseHandle(pOutputQueue->hProcessQueue);
+
+    if (pOutputQueue->SampleList)
+        HeapFree(GetProcessHeap(),0,pOutputQueue->SampleList);
+
+    IPin_Release((IPin*)pOutputQueue->pInputPin);
+    HeapFree(GetProcessHeap(),0,pOutputQueue);
+    return S_OK;
+}
+
+HRESULT WINAPI OutputQueue_ReceiveMultiple(OutputQueue *pOutputQueue, IMediaSample **ppSamples, LONG nSamples, LONG *nSamplesProcessed)
+{
+    HRESULT hr = S_OK;
+    int i;
+
+    if (!pOutputQueue->pInputPin->pin.pConnectedTo || !pOutputQueue->pInputPin->pMemInputPin)
+        return VFW_E_NOT_CONNECTED;
+
+    if (!pOutputQueue->hThread)
+    {
+        IMemInputPin_AddRef(pOutputQueue->pInputPin->pMemInputPin);
+        hr = IMemInputPin_ReceiveMultiple(pOutputQueue->pInputPin->pMemInputPin,ppSamples, nSamples, nSamplesProcessed);
+        IMemInputPin_Release(pOutputQueue->pInputPin->pMemInputPin);
+    }
+    else
+    {
+        EnterCriticalSection(&pOutputQueue->csQueue);
+        *nSamplesProcessed = 0;
+
+        for (i = 0; i < nSamples; i++)
+        {
+            QueuedEvent *qev = HeapAlloc(GetProcessHeap(),0,sizeof(QueuedEvent));
+            if (!qev)
+            {
+                ERR("Out of Memory\n");
+                hr = E_OUTOFMEMORY;
+                break;
+            }
+            qev->pSample = ppSamples[i];
+            IMediaSample_AddRef(ppSamples[i]);
+            list_add_tail(pOutputQueue->SampleList, &qev->entry);
+            (*nSamplesProcessed)++;
+        }
+        LeaveCriticalSection(&pOutputQueue->csQueue);
+
+        if (!pOutputQueue->bBatchExact || list_count(pOutputQueue->SampleList) >= pOutputQueue->lBatchSize)
+            SetEvent(pOutputQueue->hProcessQueue);
+    }
+    return hr;
+}
+
+HRESULT WINAPI OutputQueue_Receive(OutputQueue *pOutputQueue, IMediaSample *pSample)
+{
+    LONG processed;
+    return OutputQueue_ReceiveMultiple(pOutputQueue,&pSample,1,&processed);
+}
+
+DWORD WINAPI OutputQueueImpl_ThreadProc(OutputQueue *pOutputQueue)
+{
+    do
+    {
+        EnterCriticalSection(&pOutputQueue->csQueue);
+        if (list_count(pOutputQueue->SampleList) > 0 &&
+             (!pOutputQueue->bBatchExact ||
+              list_count(pOutputQueue->SampleList) >= pOutputQueue->lBatchSize))
+        {
+            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)
+            {
+                QueuedEvent *qev = LIST_ENTRY(cursor, QueuedEvent, entry);
+                list_remove(cursor);
+                ppSamples[i++] = qev->pSample;
+                HeapFree(GetProcessHeap(),0,qev);
+            }
+
+            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);
+            }
+            for (i = 0; i < nSamples; i++)
+                IUnknown_Release(ppSamples[i]);
+            HeapFree(GetProcessHeap(),0,ppSamples);
+        }
+        LeaveCriticalSection(&pOutputQueue->csQueue);
+        WaitForSingleObject(pOutputQueue->hProcessQueue, INFINITE);
+    }
+    while (!pOutputQueue->bTerminate);
+    return S_OK;
+}
diff --git a/include/wine/strmbase.h b/include/wine/strmbase.h
index 6b96c78..7063e79 100644
--- a/include/wine/strmbase.h
+++ b/include/wine/strmbase.h
@@ -346,6 +346,39 @@ typedef struct tagFactoryTemplate {
 HRESULT WINAPI AMovieDllRegisterServer2(BOOL bRegister);
 HRESULT WINAPI AMovieSetupRegisterFilter2(const AMOVIESETUP_FILTER *pFilter, IFilterMapper2  *pIFM2, BOOL  bRegister);
 
+/* Output Queue */
+typedef struct tagOutputQueue {
+    CRITICAL_SECTION csQueue;
+
+    BaseOutputPin * pInputPin;
+
+    HANDLE hThread;
+    HANDLE hProcessQueue;
+
+    LONG lBatchSize;
+    BOOL bBatchExact;
+    BOOL bTerminate;
+
+    struct list *SampleList;
+
+    const struct OutputQueueFuncTable* pFuncsTable;
+} OutputQueue;
+
+typedef DWORD (WINAPI *OutputQueue_ThreadProc)(OutputQueue *This);
+
+typedef struct OutputQueueFuncTable
+{
+    OutputQueue_ThreadProc pfnThreadProc;
+} OutputQueueFuncTable;
+
+HRESULT WINAPI OutputQueue_Construct( BaseOutputPin *pInputPin, BOOL bAuto,
+    BOOL bQueue, LONG lBatchSize, BOOL bBatchExact, DWORD dwPriority,
+    const OutputQueueFuncTable* pFuncsTable, OutputQueue **ppOutputQueue );
+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);
+DWORD WINAPI OutputQueueImpl_ThreadProc(OutputQueue *pOutputQueue);
+
 /* Dll Functions */
 BOOL WINAPI STRMBASE_DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpv);
 HRESULT WINAPI STRMBASE_DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv);




More information about the wine-cvs mailing list