diff -r 000000000000 -r 58be5850fb6c omxilcomp/omxiltestcomp/md5sink/src/omxiltestmd5sinkprocessingfunction.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/omxilcomp/omxiltestcomp/md5sink/src/omxiltestmd5sinkprocessingfunction.cpp Thu Sep 02 20:13:57 2010 +0300 @@ -0,0 +1,296 @@ +/* +* Copyright (c) 2009-2010 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 +#include "omxiltestmd5sinkprocessingfunction.h" +#include "omxiltestmd5sinkconfigmanager.h" +#include +#include "omxiltestmd5sinkconst.h" + +enum { KMsgQueueSize = 10 }; + +COmxILTestMD5SinkProcessingFunction* COmxILTestMD5SinkProcessingFunction::NewL(MOmxILCallbackNotificationIf& aCallbacks) + { + COmxILTestMD5SinkProcessingFunction* self = new (ELeave) COmxILTestMD5SinkProcessingFunction(aCallbacks); + CleanupStack::PushL(self); + self->ConstructL(aCallbacks); + CleanupStack::Pop(self); + return self; + } + +COmxILTestMD5SinkProcessingFunction::COmxILTestMD5SinkProcessingFunction(MOmxILCallbackNotificationIf& aCallbacks) +: COmxILProcessingFunction(aCallbacks) + { + } + +void COmxILTestMD5SinkProcessingFunction::ConstructL(MOmxILCallbackNotificationIf& aCallback) + { + iMD5Active = CMD5Active::NewL(aCallback); + iFlushHandler = CFlushActive::NewL(*iMD5Active); + } + +COmxILTestMD5SinkProcessingFunction::~COmxILTestMD5SinkProcessingFunction() + { + delete iFlushHandler; + delete iMD5Active; + } + +void COmxILTestMD5SinkProcessingFunction::SetConfigManager(COmxILTestMD5SinkConfigManager* aConfigManager) + { + iMD5Active->SetConfigManager(aConfigManager); + } + +OMX_ERRORTYPE COmxILTestMD5SinkProcessingFunction::StateTransitionIndication(TStateIndex /*aNewState*/) + { + return OMX_ErrorNone; + } + +OMX_ERRORTYPE COmxILTestMD5SinkProcessingFunction::BufferFlushingIndication(TUint32 aPortIndex, OMX_DIRTYPE aDirection) + { + if ((aPortIndex != OMX_ALL) && ((aPortIndex != KMD5SINK_OPB0PORT_INDEX) || (aDirection != OMX_DirInput))) + { + return OMX_ErrorNone; + } + + iFlushHandler->Flush(); + + return OMX_ErrorNone; + } + +OMX_ERRORTYPE COmxILTestMD5SinkProcessingFunction::ParamIndication(OMX_INDEXTYPE /*aParamIndex*/, + const TAny* /*apComponentParameterStructure*/) + { + return OMX_ErrorNone; + } + +OMX_ERRORTYPE COmxILTestMD5SinkProcessingFunction::ConfigIndication(OMX_INDEXTYPE /*aConfigIndex*/, + const TAny* /*apComponentConfigStructure*/) + { + return OMX_ErrorNone; + } + +OMX_ERRORTYPE COmxILTestMD5SinkProcessingFunction::BufferIndication(OMX_BUFFERHEADERTYPE* apBufferHeader, + OMX_DIRTYPE aDirection) + { + __ASSERT_ALWAYS(aDirection == OMX_DirInput, User::Invariant()); + return iMD5Active->DeliverBuffer(apBufferHeader); + } + +OMX_BOOL COmxILTestMD5SinkProcessingFunction::BufferRemovalIndication(OMX_BUFFERHEADERTYPE* apBufferHeader, OMX_DIRTYPE aDirection) + { + __ASSERT_ALWAYS(aDirection == OMX_DirInput, User::Invariant()); + return iMD5Active->RemoveBuffer(apBufferHeader); + } + +/////////////////////////////////////////////////////////////////////////////////////////// + +CMD5Active* CMD5Active::NewL(MOmxILCallbackNotificationIf& aCallback) + { + CMD5Active* self = new(ELeave) CMD5Active(aCallback); + CleanupStack::PushL(self); + self->ConstructL(); + CleanupStack::Pop(self); + return self; + } + +CMD5Active::CMD5Active(MOmxILCallbackNotificationIf& aCallback): +CActive(CActive::EPriorityStandard), +iCallback(aCallback) + { + CActiveScheduler::Add(this); + } + +void CMD5Active::ConstructL() + { + iMD5 = CMD5::NewL(); + User::LeaveIfError(iBuffers.CreateLocal(KMsgQueueSize)); + iBuffers.NotifyDataAvailable(iStatus); + SetActive(); + } + +CMD5Active::~CMD5Active() + { + Cancel(); + delete iMD5; + } + +void CMD5Active::SetConfigManager(COmxILTestMD5SinkConfigManager* aConfigManager) + { + iConfigManager = aConfigManager; + } + +OMX_ERRORTYPE CMD5Active::DeliverBuffer(OMX_BUFFERHEADERTYPE* aBuffer) + { + TInt aErr = iBuffers.Send(aBuffer); + if(aErr == KErrNone) + { + return OMX_ErrorNone; + } + else if(aErr == KErrOverflow) + { + return OMX_ErrorInsufficientResources; + } + else + { + return OMX_ErrorUndefined; + } + } + +OMX_BOOL CMD5Active::RemoveBuffer(OMX_BUFFERHEADERTYPE* aBuffer) + { + TBool removed = EFalse; + TRAPD(err, removed = RemoveFromQueueL(iBuffers, aBuffer)); + if(err) + { + User::Invariant(); + } + return removed ? OMX_TRUE : OMX_FALSE; + } + +TBool CMD5Active::RemoveFromQueueL(RMsgQueue& aQueue, OMX_BUFFERHEADERTYPE* aBufferHeader) + { + TBool removed = EFalse; + RMsgQueue tempQueue; + User::LeaveIfError(tempQueue.CreateLocal(KMsgQueueSize)); + OMX_BUFFERHEADERTYPE* bufferHeader = NULL; + while(aQueue.Receive(bufferHeader) != KErrUnderflow) + { + if(bufferHeader != aBufferHeader) + { + __ASSERT_ALWAYS(tempQueue.Send(bufferHeader) == KErrNone, User::Invariant()); + } + else + { + removed = ETrue; + } + } + while(tempQueue.Receive(bufferHeader) != KErrUnderflow) + { + __ASSERT_ALWAYS(aQueue.Send(bufferHeader) == KErrNone, User::Invariant()); + } + tempQueue.Close(); + return removed; + } + +void CMD5Active::RunL() + { + OMX_BUFFERHEADERTYPE* aBuff; + // may have an empty queue despite being notified if a RemoveBuffer() occured in the meantime + if(iBuffers.Receive(aBuff) != KErrUnderflow) + { + // hash the buffer + TPtrC8 aDes(aBuff->pBuffer + aBuff->nOffset, aBuff->nFilledLen); + TPtrC8 aHash = iMD5->Hash(aDes); + iConfigManager->SetHash(aHash); + aBuff->nFilledLen = 0; + OMX_U32 flags = aBuff->nFlags; + iCallback.BufferDoneNotification(aBuff, KMD5SINK_OPB0PORT_INDEX, OMX_DirInput); + if(flags) + { + iCallback.EventNotification(OMX_EventBufferFlag, 0, flags, NULL); + } + } + iBuffers.NotifyDataAvailable(iStatus); + SetActive(); + } + +void CMD5Active::FlushHeaders() + { + OMX_BUFFERHEADERTYPE* aBuff; + + while(iBuffers.Receive(aBuff) == KErrNone) + { + aBuff->nFilledLen = 0; + iCallback.BufferDoneNotification(aBuff, KMD5SINK_OPB0PORT_INDEX, OMX_DirInput); + } + } + +void CMD5Active::DoCancel() + { + iBuffers.CancelDataAvailable(); + } + +/////////////////////////////////////////////////////////////////////////////////////////// + +CFlushActive* CFlushActive::NewL(CMD5Active& aBufferHandler) + { + CFlushActive* self = new (ELeave) CFlushActive(aBufferHandler); + CleanupStack::PushL(self); + self->ConstructL(); + CleanupStack::Pop(self); + return self; + } + +CFlushActive::CFlushActive(CMD5Active& aBufferHandler): +CActive(CActive::EPriorityHigh), // Higher priority than CMD5Active to ensure we run before them when the Active Scheduler is picking who to run next +iBufferHandler(aBufferHandler) + { + CActiveScheduler::Add(this); + iRunLContext = RThread(); + iStatus = KRequestPending; + SetActive(); + } + +void CFlushActive::ConstructL() + { + User::LeaveIfError(iWaitSemaphore.CreateLocal(0)); + } + +CFlushActive::~CFlushActive() + { + Cancel(); + iRunLContext.Close(); + iWaitSemaphore.Close(); + } + +void CFlushActive::Flush() + { + RThread currentContext; + if (currentContext.Id() == iRunLContext.Id()) + { + // The same context so cannot be running concurrently with CMD5Active::RunL() so safe to drain buffer queue + iBufferHandler.FlushHeaders(); + return; + } + + // Different thread to the one in which the Active objects are running, + TRequestStatus* selfStatus = &iStatus; + iRunLContext.RequestComplete(selfStatus, KErrNone); + iWaitSemaphore.Wait(); + } + +void CFlushActive::RunL() + { + // Now sure we are not running concurrently with CMD5Active::RunL() + iBufferHandler.FlushHeaders(); + iStatus = KRequestPending; + SetActive(); + iWaitSemaphore.Signal(); + } + +void CFlushActive::DoCancel() + { + iWaitSemaphore.Signal(); // Only happens as part of deletion so irrelevant whether we are blocked or not + TRequestStatus* selfStatus = &iStatus; + User::RequestComplete(selfStatus, KErrNone); + }