diff -r 000000000000 -r 951a5db380a0 videoeditorengine/vedengine/videoprocessor/src/activequeue.cpp --- /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