--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/omxilvideocomps/omxilvideoscheduler/src/buffercopier.cpp Fri Oct 08 22:09:17 2010 +0100
@@ -0,0 +1,200 @@
+/*
+* Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "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:
+*
+* Description:
+*
+*/
+
+
+/**
+@file
+@internalComponent
+*/
+
+#include "buffercopier.h"
+
+_LIT(KBufferCopierPanic, "CBufferCopier");
+
+CBufferCopier* CBufferCopier::NewL(MBufferCopierIf& aCallback, TInt aMaxBuffers)
+ {
+ CBufferCopier* self = new(ELeave) CBufferCopier(aCallback);
+ CleanupStack::PushL(self);
+ self->ConstructL(aMaxBuffers);
+ CleanupStack::Pop(self);
+ return self;
+ }
+
+CBufferCopier::CBufferCopier(MBufferCopierIf& aCallback):
+CActive(EPriorityNormal),
+iCallback(aCallback)
+ {
+ CActiveScheduler::Add(this);
+ }
+
+void CBufferCopier::ConstructL(TInt aMaxBuffers)
+ {
+ User::LeaveIfError(iInQueue.CreateLocal(aMaxBuffers));
+ User::LeaveIfError(iOutQueue.CreateLocal(aMaxBuffers));
+ User::LeaveIfError(iRemoveQueue.CreateLocal(aMaxBuffers));
+ SetActive();
+ iInQueue.NotifyDataAvailable(iStatus);
+ }
+
+CBufferCopier::~CBufferCopier()
+ {
+ Cancel();
+ iInQueue.Close();
+ iOutQueue.Close();
+ iRemoveQueue.Close();
+ }
+
+void CBufferCopier::DeliverBuffer(OMX_BUFFERHEADERTYPE* aBuffer, OMX_DIRTYPE aDirection)
+ {
+ RMsgQueue<OMX_BUFFERHEADERTYPE*>& queue = aDirection == OMX_DirInput ? iInQueue : iOutQueue;
+ TInt err = queue.Send(aBuffer);
+ // do not expect error as maximum buffer count already allocated
+ if(err != KErrNone)
+ {
+ User::Panic(KBufferCopierPanic, err);
+ }
+ }
+
+void CBufferCopier::RunL()
+ {
+ if(iInBuffer == NULL)
+ {
+ // ignore error, if KErrUnderflow then we go back to waiting on iInQueue
+ iInQueue.Receive(iInBuffer);
+ }
+ else
+ {
+ OMX_BUFFERHEADERTYPE* outBuffer = NULL;
+ TInt err = iOutQueue.Receive(outBuffer);
+ // if KErrUnderflow then we go back to waiting on iOutQueue
+ if(err == KErrNone)
+ {
+ CopyBuffer(iInBuffer, outBuffer);
+ iInBuffer = NULL;
+ }
+ }
+
+ SetActive();
+ if(iInBuffer == NULL)
+ {
+ iInQueue.NotifyDataAvailable(iStatus);
+ }
+ else
+ {
+ iOutQueue.NotifyDataAvailable(iStatus);
+ }
+ }
+
+void CBufferCopier::DoCancel()
+ {
+ iInQueue.CancelDataAvailable();
+ iOutQueue.CancelDataAvailable();
+ }
+
+void CBufferCopier::CopyBuffer(OMX_BUFFERHEADERTYPE* aInBuffer, OMX_BUFFERHEADERTYPE* aOutBuffer)
+ {
+ aOutBuffer->nOffset = 0;
+ TPtr8 desPtr(aOutBuffer->pBuffer, aOutBuffer->nAllocLen);
+ desPtr.Copy(aInBuffer->pBuffer + aInBuffer->nOffset, aInBuffer->nFilledLen);
+
+ aOutBuffer->nFilledLen = aInBuffer->nFilledLen;
+ aOutBuffer->hMarkTargetComponent = aInBuffer->hMarkTargetComponent;
+ aOutBuffer->pMarkData = aInBuffer->pMarkData;
+ aOutBuffer->nTickCount = aInBuffer->nTickCount;
+ aOutBuffer->nTimeStamp = aInBuffer->nTimeStamp;
+ aOutBuffer->nFlags = aInBuffer->nFlags;
+
+ iCallback.MbcBufferCopied(aInBuffer, aOutBuffer);
+ }
+
+TBool CBufferCopier::RemoveBuffer(OMX_BUFFERHEADERTYPE* aBuffer, OMX_DIRTYPE aDirection)
+ {
+ switch(aDirection)
+ {
+ case OMX_DirInput:
+ {
+ if(aBuffer == iInBuffer)
+ {
+ // also check the slot used for storing the input buffer when waiting for an output buffer
+ iInBuffer = NULL;
+ return ETrue;
+ }
+ else
+ {
+ return RemoveFromQueue(iInQueue, aBuffer);
+ }
+ }
+ case OMX_DirOutput:
+ return RemoveFromQueue(iOutQueue, aBuffer);
+ default:
+ User::Panic(KBufferCopierPanic, KErrArgument);
+ return EFalse; // prevent compiler warning
+ }
+ }
+
+void CBufferCopier::FlushBuffers(OMX_DIRTYPE aDirection)
+ {
+ OMX_BUFFERHEADERTYPE* buffer;
+ if(aDirection == OMX_DirInput)
+ {
+ if(iInBuffer)
+ {
+ iCallback.MbcBufferFlushed(iInBuffer, OMX_DirInput);
+ iInBuffer = NULL;
+ }
+
+ while(iInQueue.Receive(buffer) != KErrUnderflow)
+ {
+ iCallback.MbcBufferFlushed(buffer, OMX_DirInput);
+ }
+ }
+ else if(aDirection == OMX_DirOutput)
+ {
+ while(iOutQueue.Receive(buffer) != KErrUnderflow)
+ {
+ iCallback.MbcBufferFlushed(buffer, OMX_DirOutput);
+ }
+ }
+ else
+ {
+ User::Panic(KBufferCopierPanic, KErrArgument);
+ }
+ }
+
+TBool CBufferCopier::RemoveFromQueue(RMsgQueue<OMX_BUFFERHEADERTYPE*>& aQueue, OMX_BUFFERHEADERTYPE* aBufferHeader)
+ {
+ TBool removed = EFalse;
+ OMX_BUFFERHEADERTYPE* bufferHeader = NULL;
+ while(aQueue.Receive(bufferHeader) != KErrUnderflow)
+ {
+ if(bufferHeader != aBufferHeader)
+ {
+ TInt err = iRemoveQueue.Send(bufferHeader);
+ __ASSERT_DEBUG(err == KErrNone, User::Panic(KBufferCopierPanic, err));
+ }
+ else
+ {
+ removed = ETrue;
+ }
+ }
+ while(iRemoveQueue.Receive(bufferHeader) != KErrUnderflow)
+ {
+ TInt err = aQueue.Send(bufferHeader);
+ __ASSERT_DEBUG(err == KErrNone, User::Panic(KBufferCopierPanic, err));
+ }
+ return removed;
+ }