videoeditorengine/vedengine/videoprocessor/src/activequeue.cpp
changeset 0 951a5db380a0
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/videoeditorengine/vedengine/videoprocessor/src/activequeue.cpp	Fri Jan 29 14:08:33 2010 +0200
@@ -0,0 +1,583 @@
+/*
+* Copyright (c) 2010 Ixonos Plc.
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of the "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - Initial contribution
+*
+* Contributors:
+* Ixonos Plc
+*
+* Description:  
+* Data buffering and queuing support definitions, class CActiveQueue.
+*
+*/
+
+
+//  EXTERNAL RESOURCES  
+
+
+//  Include Files  
+
+#include "dataprocessor.h"
+#include "activequeue.h"
+
+
+//  MEMBER FUNCTIONS
+
+
+//=============================================================================
+
+
+/*
+-----------------------------------------------------------------------------
+
+    CActiveQueue
+
+    CActiveQueue()
+
+    Standard C++ constructor
+
+-----------------------------------------------------------------------------
+*/
+
+CActiveQueue::CActiveQueue(TUint aNumberOfBlocks, TUint aBlockLength)
+{
+    // Remember the number of blocks and initial new block length
+    iInitialBlocks = aNumberOfBlocks;
+    iNewBlockLength = aBlockLength;   
+    iStreamEnd = EFalse;
+}
+
+
+
+/*
+-----------------------------------------------------------------------------
+
+    CActiveQueue
+
+    ~CActiveQueue()
+
+    Standard C++ destructor
+
+-----------------------------------------------------------------------------
+*/
+
+CActiveQueue::~CActiveQueue()
+{
+    // Deallocate all blocks:
+    while ( iBlocks )
+    {
+        TRAPD( error, FreeBlockL(iBlocks) );
+        if (error != KErrNone) { }
+    }
+
+    __ASSERT_DEBUG(iNumBlocks == 0,
+                   User::Panic(_L("CActiveQueue"), EInternalAssertionFailure));
+}
+
+
+
+/*
+-----------------------------------------------------------------------------
+
+    CActiveQueue
+
+    ConstructL()
+
+    Standard Symbian OS second-phase constructor, prepares the object for use
+
+-----------------------------------------------------------------------------
+*/
+
+void CActiveQueue::ConstructL()
+{
+    // Allocate initial blocks
+    while ( iInitialBlocks-- )
+    {
+        // Get block
+        TActiveQueueBlock *block = AllocateBlockL();
+
+        // Add it to the free block list
+        block->iNextList = iFreeList;
+        iFreeList = block;
+        iNumFreeBlocks++;
+    }
+}
+
+
+
+/*
+-----------------------------------------------------------------------------
+
+    CActiveQueue
+
+    SetReader()
+
+    Sets a reader for the queue
+
+-----------------------------------------------------------------------------
+*/
+
+void CActiveQueue::SetReader(CDataProcessor *aReader, TAny *aUserPointer)
+{
+    iReader = aReader;
+    iReaderUserPointer = aUserPointer;
+}
+
+
+
+/*
+-----------------------------------------------------------------------------
+
+    CActiveQueue
+
+    RemoveReader()
+
+    Removes a reader from the queue
+
+-----------------------------------------------------------------------------
+*/
+
+void CActiveQueue::RemoveReader()
+{
+    __ASSERT_DEBUG(iReader, User::Panic(_L("CActiveQueue"), ENoReader));
+    iReader = 0;
+}
+
+
+
+/*
+-----------------------------------------------------------------------------
+
+    CActiveQueue
+
+    SetWriter()
+
+    Sets a writer for the queue
+
+-----------------------------------------------------------------------------
+*/
+
+void CActiveQueue::SetWriter(CDataProcessor *aWriter, TAny *aUserPointer)
+{
+    iWriter = aWriter;
+    iWriterUserPointer = aUserPointer;
+}
+
+
+
+/*
+-----------------------------------------------------------------------------
+
+    CActiveQueue
+
+    RemoveWriter()
+
+    Removes a writer from the queue
+
+-----------------------------------------------------------------------------
+*/
+
+void CActiveQueue::RemoveWriter()
+{
+    __ASSERT_DEBUG(iWriter, User::Panic(_L("CActiveQueue"), ENoWriter));
+    iWriter = 0;
+}
+
+/*
+-----------------------------------------------------------------------------
+
+    CActiveQueue
+
+    ResetStreamEnd()
+
+    Reset the status of the queue
+
+-----------------------------------------------------------------------------
+*/
+
+void CActiveQueue::ResetStreamEnd()
+{
+    iStreamEnd = EFalse;
+    // we should not have any blocks in full queue if we have reached stream end
+}
+
+
+
+/*
+-----------------------------------------------------------------------------
+
+    CActiveQueue
+
+    NumFreeBlocks()
+
+    Get the number of free blocks available for new data
+
+-----------------------------------------------------------------------------
+*/
+
+TUint CActiveQueue::NumFreeBlocks()
+{
+    return iNumFreeBlocks;
+}
+
+
+
+/*
+-----------------------------------------------------------------------------
+
+    CActiveQueue
+
+    NumDataBlocks()
+
+    Get the number of blocks with data queued
+
+-----------------------------------------------------------------------------
+*/
+
+TUint CActiveQueue::NumDataBlocks()
+{
+    return iNumDataBlocks;
+}
+
+
+
+/*
+-----------------------------------------------------------------------------
+
+    CActiveQueue
+
+    GetFreeBlockL()
+
+    Get a free block for writing data into the queue (writer)
+
+-----------------------------------------------------------------------------
+*/
+
+TPtr8 *CActiveQueue::GetFreeBlockL(TUint aBlockLength)
+{
+    __ASSERT_DEBUG(iWriter, User::Panic(_L("CActiveQueue"), ENoWriter));
+    TActiveQueueBlock *block = 0;
+    
+    // If the requested block size is larger than the currently used length
+    // for new blocks, use the new size for all new blocks
+    if ( aBlockLength > iNewBlockLength )
+        iNewBlockLength = aBlockLength;
+
+    // Do we have free blocks?
+    if ( iNumFreeBlocks )
+    {
+        // Yes, get a block from the queue:
+        __ASSERT_DEBUG(iFreeList != 0,
+                       User::Panic(_L("CActiveQueue"), EInternalAssertionFailure));
+        block = iFreeList;
+        iFreeList = block->iNextList;
+        iNumFreeBlocks--;
+
+        // If the block isn't large enough, discard it so that we'll allocate a
+        // new one. Don't discard more than one block to keep the number of
+        // blocks allocated constant.
+        if ( block->MaxLength() < (TInt) aBlockLength )
+        {
+            FreeBlockL(block);
+            block = 0;
+        }
+    }
+
+    // If we didn't get a suitable block, allocate a new one
+    if ( !block )
+        block = AllocateBlockL();
+
+    __ASSERT_DEBUG(block->MaxLength() >= (TInt) aBlockLength,
+                   User::Panic(_L("CActiveQueue"), EInternalAssertionFailure));
+
+    block->SetLength(0);
+
+    return block;
+}
+
+
+
+/*
+-----------------------------------------------------------------------------
+
+    CActiveQueue
+
+    WriteBlock()
+
+    Add a data block to the queue (writer)
+
+-----------------------------------------------------------------------------
+*/
+
+void CActiveQueue::WriteBlock(TPtr8 *aBlock)
+{
+    __ASSERT_DEBUG(iWriter, User::Panic(_L("CActiveQueue"), ENoWriter));
+    __ASSERT_DEBUG(!iStreamEnd,
+                   User::Panic(_L("CActiveQueue"), EWriteAfterStreamEnd));
+                   
+    // The block is really a TActiveQueueBlock
+    TActiveQueueBlock *block = (TActiveQueueBlock*) aBlock;
+
+
+    // Add the block to the queue:
+    if ( iDataQueueTail )
+    {
+        // The queue is not empty
+        __ASSERT_DEBUG(iDataQueueHead && iNumDataBlocks,
+                       User::Panic(_L("CActiveQueue"), EInternalAssertionFailure));
+        iDataQueueTail->iNextList = block;
+        iDataQueueTail = block;
+        block->iNextList = 0;
+    }
+    else
+    {
+        // The queue is empty -> this will be the first block
+        __ASSERT_DEBUG((!iDataQueueHead) && (!iNumDataBlocks),
+                       User::Panic(_L("CActiveQueue"), EInternalAssertionFailure));
+        iDataQueueHead = block;
+        iDataQueueTail = block;
+        block->iNextList = 0;
+    }
+    iNumDataBlocks++;
+
+    // If we have a reader, notify it about the new data
+    if ( iReader )
+        iReader->InputDataAvailable(iReaderUserPointer);
+}
+
+
+
+/*
+-----------------------------------------------------------------------------
+
+    CActiveQueue
+
+    ReadBlock()
+
+    Read a data block from the queue (reader)
+
+-----------------------------------------------------------------------------
+*/
+
+TPtr8 *CActiveQueue::ReadBlock()
+{
+    __ASSERT_DEBUG(iReader, User::Panic(_L("CActiveQueue"), ENoReader));
+    __ASSERT_DEBUG(((iNumDataBlocks && iDataQueueHead) ||
+                    ((!iNumDataBlocks) && (!iDataQueueHead))),
+                   User::Panic(_L("CActiveQueue"), EInternalAssertionFailure));
+
+    // If we don't have a block, return NULL
+    if ( !iNumDataBlocks )
+        return 0;
+
+    // Get the block from the queue head
+    TActiveQueueBlock *block = iDataQueueHead;
+    iDataQueueHead = block->iNextList;
+    iNumDataBlocks--;
+    if ( !iNumDataBlocks )
+    {
+        // It was the only block in the queue
+        __ASSERT_DEBUG((!iDataQueueHead) && (iDataQueueTail == block),
+                       User::Panic(_L("CActiveQueue"), EInternalAssertionFailure));
+        iDataQueueTail = 0;                       
+    }
+    __ASSERT_DEBUG((iDataQueueHead != block) && (iDataQueueTail != block),
+                   User::Panic(_L("CActiveQueue"), EInternalAssertionFailure));
+
+    // If it was the last block and the stream end has been signaled, notify
+    // the reader
+    if ( iStreamEnd && (!iNumDataBlocks) )
+        iReader->StreamEndReached(iReaderUserPointer);
+
+    // Return the block
+    return ((TPtr8*) block);
+}
+
+
+/*
+-----------------------------------------------------------------------------
+
+    CActiveQueue
+
+    ReturnBlock()
+
+    Return a read block back to the empty block list (reader)
+
+-----------------------------------------------------------------------------
+*/
+
+void CActiveQueue::ReturnBlock(TPtr8 *aBlock)
+{
+    __ASSERT_DEBUG(iReader, User::Panic(_L("CActiveQueue"), ENoReader));
+                   
+    // The block is really a TActiveQueueBlock
+    TActiveQueueBlock *block = (TActiveQueueBlock*) aBlock;
+
+
+    // Add it to the free list:
+    __ASSERT_DEBUG((((!iNumFreeBlocks) && (!iFreeList)) ||
+                    (iNumFreeBlocks && iFreeList)),
+                   User::Panic(_L("CActiveQueue"), EInternalAssertionFailure));
+
+    if ( block->MaxLength() == 0 )
+    {
+        block->MaxLength();
+    }
+
+    block->iNextList = iFreeList;
+    iFreeList = block;
+    iNumFreeBlocks++;
+
+    // If we have a writer, notify it about the empty block
+    if ( iWriter )
+        iWriter->OutputSpaceAvailable(iWriterUserPointer);
+}
+
+
+
+/*
+-----------------------------------------------------------------------------
+
+    CActiveQueue
+
+    WriteStreamEnd()
+
+    Notify that the stream has ended (writer)
+
+-----------------------------------------------------------------------------
+*/
+
+void CActiveQueue::WriteStreamEnd()
+{
+    __ASSERT_DEBUG(iWriter, User::Panic(_L("CActiveQueue"), ENoWriter));
+
+    // Mark that the stream has ended
+    iStreamEnd = ETrue;
+
+    // If we have a reader and there are no more blocks in the queue, signal
+    // the reader
+    if ( iReader && (!iNumDataBlocks) )
+        iReader->StreamEndReached(iReaderUserPointer);
+}
+
+
+
+/*
+-----------------------------------------------------------------------------
+
+    CActiveQueue
+
+    StreamEnded()
+
+    Check if the writer has notified that the stream has ended (reader)
+
+-----------------------------------------------------------------------------
+*/
+
+TBool CActiveQueue::StreamEnded()
+{
+    return iStreamEnd;
+}
+
+
+
+/*
+-----------------------------------------------------------------------------
+
+    CActiveQueue
+
+    AllocateBlockL()
+
+    Allocates a new data block of size iNewBlockLengh
+
+-----------------------------------------------------------------------------
+*/
+
+TActiveQueueBlock *CActiveQueue::AllocateBlockL()
+{
+    // Allocate the data area for the block
+    TUint8 *data = (TUint8*) User::AllocLC(iNewBlockLength);    
+
+    // Allocate the block
+    TActiveQueueBlock *block = new (ELeave) TActiveQueueBlock(data,
+                                                              iNewBlockLength);
+
+    CleanupStack::Pop(data);
+
+    // Add the block to the list of all blocks:
+    if ( iBlocks )
+    {
+        block->iNextBlock = iBlocks;
+        block->iPrevBlock = 0;
+        iBlocks->iPrevBlock = block;
+        iBlocks = block;
+    }
+    else
+    {
+        block->iNextBlock = 0;
+        block->iPrevBlock = 0;
+        iBlocks = block;
+    }
+
+    __ASSERT_DEBUG((iBlocks &&
+                    ((iBlocks->iNextBlock == 0) ||
+                     (iBlocks->iNextBlock != iBlocks))),
+                   User::Panic(_L("CActiveQueue"), EInternalAssertionFailure));
+
+    return block;
+}
+
+
+
+/*
+-----------------------------------------------------------------------------
+
+    CActiveQueue
+
+    FreeBlockL()
+
+    Deallocates a block allocated with AllocateBlockL()
+
+-----------------------------------------------------------------------------
+*/
+
+void CActiveQueue::FreeBlockL(TActiveQueueBlock *aBlock)
+{
+    __ASSERT_DEBUG((((aBlock->iPrevBlock != aBlock->iNextBlock) ||
+                     (aBlock->iNextBlock == 0)) &&
+                    ((aBlock == iBlocks) || (aBlock->iPrevBlock != 0))),
+                   User::Panic(_L("CActiveQueue"), EInternalAssertionFailure));
+    
+    // Remove the block from the list of all blocks:
+    if ( aBlock->iPrevBlock )
+        aBlock->iPrevBlock->iNextBlock = aBlock->iNextBlock;
+    else
+        iBlocks = aBlock->iNextBlock;
+    if ( aBlock->iNextBlock )
+        aBlock->iNextBlock->iPrevBlock = aBlock->iPrevBlock;
+
+    // Free the data area
+    TUint8 *data = (TUint8*) aBlock->Ptr();    
+    User::Free(data);
+
+    // Free the block:
+    delete aBlock;
+
+    __ASSERT_DEBUG(((!iBlocks) ||
+                    (((iBlocks->iNextBlock == 0) ||
+                      (iBlocks->iNextBlock != iBlocks)) &&
+                     (iBlocks->iPrevBlock == 0))),
+                   User::Panic(_L("CActiveQueue"), EInternalAssertionFailure));
+}
+
+
+
+
+
+// End of File