diff -r c1e808730d6c -r eedf2dcd43c6 omxil/omxilcomponentcommon/src/common/omxilfsm.cpp --- a/omxil/omxilcomponentcommon/src/common/omxilfsm.cpp Mon May 03 13:56:28 2010 +0300 +++ b/omxil/omxilcomponentcommon/src/common/omxilfsm.cpp Fri May 07 16:25:23 2010 +0100 @@ -1,783 +1,783 @@ -// Copyright (c) 2008-2009 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 "log.h" -#include "omxilfsm.h" -#include "omxilstate.h" -#include "omxilportmanager.h" -#include "omxilconfigmanager.h" -#include "omxilcallbackmanager.h" -#include "omxilprocessingfunction.h" - -#define RETURN_OMX_ERROR_AND_EVENT_IF_NEEDED(_a) \ - { \ - const OMX_ERRORTYPE _err = _a; \ - if (OMX_ErrorNone == _err) return _err; \ - else return SendOmxErrorEventIfNeeded(_err); \ - } - - -const TInt COmxILFsm::KMaxMsgQueueEntries; - -EXPORT_C COmxILFsm* -COmxILFsm::NewL(COmxILComponent& aComponent, - COmxILProcessingFunction& aProcFunction, - COmxILPortManager& aPortManager, - COmxILConfigManager& aConfigManager, - MOmxILCallbackManagerIf& aCallbacks) - { - DEBUG_PRINTF(_L8("COmxILFsm::NewLC")); - - COmxILFsm* self = new (ELeave) COmxILFsm(aComponent, - aProcFunction, - aPortManager, - aConfigManager, - aCallbacks); - CleanupStack::PushL(self); - self->ConstructL(); - CleanupStack::Pop(self); - return (self); - } - -void -COmxILFsm::ConstructL() - { - DEBUG_PRINTF(_L8("COmxILFsm::ConstructL")); - - // Create the FSM states - - // Init the array - for (TUint i=0; i < EStateMax; ++i) - { - iStates.AppendL(NULL); - } - - // Add the standard states... - iStates[EStateInvalid] = new (ELeave)COmxILStateInvalid; - iStates[EStateLoaded] = new (ELeave)COmxILStateLoaded; - iStates[EStateIdle] = new (ELeave)COmxILStateIdle; - iStates[EStateExecuting] = new (ELeave)COmxILStateExecuting; - iStates[EStatePause] = new (ELeave)COmxILStatePause; - iStates[EStateWaitForResources] = new (ELeave)COmxILStateWaitForResources; - - // Now add the substates - iStates[ESubStateLoadedToIdle] = new (ELeave)COmxILStateLoadedToIdle; - iStates[ESubStateIdleToLoaded] = new (ELeave)COmxILStateIdleToLoaded; - iStates[ESubStateExecutingToIdle] = new (ELeave)COmxILStateExecutingToIdle; - iStates[ESubStatePauseToIdle] = new (ELeave)COmxILStatePauseToIdle; - - iCallbacks.SetPortManager(iPortManager); - iCallbacks.SetFsm(*this); - - } - -COmxILFsm::COmxILFsm(COmxILComponent& aComponent, - COmxILProcessingFunction& aProcFunction, - COmxILPortManager& aPortManager, - COmxILConfigManager& aConfigManager, - MOmxILCallbackManagerIf& aCallbacks) - : - iComponent(aComponent), - iProcFunction(aProcFunction), - iPortManager(aPortManager), - iConfigManager(aConfigManager), - iCallbacks(aCallbacks), - iStates(), - iCurrentStateIndex(EStateMax), - ipCurrentState(0) - { - DEBUG_PRINTF(_L8("COmxILFsm::COmxILFsm")); - } - -COmxILFsm::~COmxILFsm() - { - DEBUG_PRINTF(_L8("COmxILFsm::~COmxILFsm")); - - iCurrentStateIndex = EStateMax; - ipCurrentState = 0; - iStates.ResetAndDestroy(); - - } - -OMX_ERRORTYPE -COmxILFsm::InitFsm() - { - DEBUG_PRINTF(_L8("COmxILFsm::InitFsm")); - - // Let's get ready to handle API calls... - iCurrentStateIndex = EStateLoaded; - ipCurrentState = iStates[iCurrentStateIndex]; - return OMX_ErrorNone; - - } - -COmxILComponent* -COmxILFsm::GetComponent() const - { - return &iComponent; - } - -OMX_ERRORTYPE -COmxILFsm::PopulateBuffer(OMX_BUFFERHEADERTYPE** appBufferHdr, - OMX_U32 aPortIndex, - OMX_PTR apAppPrivate, - OMX_U32 aSizeBytes, - OMX_U8* apBuffer) - { - DEBUG_PRINTF(_L8("COmxILFsm::PopulateBuffer")); - - TBool portPopulationCompleted = EFalse; - OMX_ERRORTYPE omxRetValue = - ipCurrentState->PopulateBuffer(*this, - appBufferHdr, - aPortIndex, - apAppPrivate, - aSizeBytes, - apBuffer, - portPopulationCompleted); - - if (OMX_ErrorNone == omxRetValue) - { - if (portPopulationCompleted && - ESubStateLoadedToIdle == iCurrentStateIndex && - iPortManager.AllPortsPopulated()) - { - // Complete here the transition to OMX_StateIdle - omxRetValue = FsmTransition(EStateIdle); - if (OMX_ErrorNone == omxRetValue) - { - // Notify the IL client that port population has - // completed sucessfully - omxRetValue = iCallbacks.TransitionCompleteNotification( - OMX_StateIdle); - - } - } - } - - if (OMX_ErrorNone == omxRetValue || - OMX_ErrorInsufficientResources == omxRetValue) - { - // OMX_ErrorInsufficientResources is allowed in OMX_EmptyThisBuffer and - // OMX_FillThisBuffer - return omxRetValue; - } - else - { - return SendOmxErrorEventIfNeeded(omxRetValue); - } - - } - -OMX_ERRORTYPE -COmxILFsm::FsmTransition(TStateIndex aNewState) - { - DEBUG_PRINTF2(_L8("COmxILFsm::FsmTransition : %d"), aNewState); - - __ASSERT_ALWAYS(aNewState < EStateMax, - User::Panic(KOmxILFsmPanicCategory, 1)); - - if (aNewState != iCurrentStateIndex) - { - // We notify the processing function of all the state transitions, even - // if they are not to a final OpenMAX IL state. - OMX_ERRORTYPE omxRetValue; - if (OMX_ErrorNone != - (omxRetValue = - iProcFunction.StateTransitionIndication(aNewState))) - { - // No need of propagating further error codes if the component is - // transitioning to OMX_StateInvalid or if the PF itself is - // invalidating the component... - if (EStateInvalid != aNewState && - OMX_ErrorInvalidState != omxRetValue) - { - return omxRetValue; - } - } - - iCurrentStateIndex = aNewState; - ipCurrentState = iStates[iCurrentStateIndex]; - - } - - return OMX_ErrorNone; - - } - -OMX_ERRORTYPE -COmxILFsm::FsmTransition(TUint32 aNewState) - { - - return FsmTransition(static_cast(aNewState)); - - } - - -OMX_ERRORTYPE -COmxILFsm::GetComponentVersion(OMX_STRING aComponentName, - OMX_VERSIONTYPE* apComponentVersion, - OMX_VERSIONTYPE* apSpecVersion, - OMX_UUIDTYPE* apComponentUUID) const - { - DEBUG_PRINTF(_L8("COmxILFsm::GetComponentVersion")); - - __ASSERT_DEBUG(iCurrentStateIndex != EStateMax, - User::Panic(KOmxILFsmPanicCategory, 1)); - - // This api should not be allowed in OMX_StateInvalid - if (EStateInvalid == iCurrentStateIndex) - { - return SendOmxErrorEventIfNeeded(OMX_ErrorInvalidState); - } - - if (!aComponentName || - !apComponentVersion || - !apSpecVersion || - !apComponentUUID) - { - return OMX_ErrorBadParameter; - } - - // This API call is independent of the current state. Its handled by the - // the config manager - - RETURN_OMX_ERROR_AND_EVENT_IF_NEEDED( - iConfigManager.GetComponentVersion( - aComponentName, - apComponentVersion, - apSpecVersion, - apComponentUUID)); - } - - -OMX_ERRORTYPE -COmxILFsm::SendCommand(OMX_COMMANDTYPE aCommand, - TUint32 anParam1, - TAny* apCmdData) - { - DEBUG_PRINTF3(_L8("COmxILFsm::SendCommand : command [%d] Param1 [%d]"), aCommand, anParam1); - - __ASSERT_DEBUG(iCurrentStateIndex != EStateMax, - User::Panic(KOmxILFsmPanicCategory, 1)); - - // Do some very minor error checking here to try to save some time... - if (OMX_CommandStateSet == aCommand && - anParam1 > OMX_StateWaitForResources) - { - return OMX_ErrorBadParameter; - } - - TOmxILCommand command(aCommand, anParam1, apCmdData); - OMX_ERRORTYPE sendCommandError; - switch (aCommand) - { - case OMX_CommandStateSet: - { - sendCommandError = ipCurrentState->CommandStateSet(*this, command); - } - break; - case OMX_CommandFlush: - { - sendCommandError = ipCurrentState->CommandFlush(*this, command); - } - break; - case OMX_CommandPortDisable: - { - sendCommandError = ipCurrentState->CommandPortDisable(*this, command); - } - break; - case OMX_CommandPortEnable: - { - sendCommandError = ipCurrentState->CommandPortEnable(*this, command); - } - break; - case OMX_CommandMarkBuffer: - { - sendCommandError = ipCurrentState->CommandMarkBuffer(*this, command); - } - break; - default: - { - // This is an invalid command type - return OMX_ErrorBadParameter; - } - }; - - if (OMX_ErrorNone == sendCommandError || - OMX_ErrorInsufficientResources == sendCommandError) - { - // OMX_ErrorInsufficientResources is allowed in OMX_SendCommand - return sendCommandError; - } - else - { - return SendOmxErrorEventIfNeeded(sendCommandError); - } - - } - - -OMX_ERRORTYPE -COmxILFsm::GetParameter(OMX_INDEXTYPE aParamIndex, - TAny* apComponentParameterStructure) const - { - DEBUG_PRINTF(_L8("COmxILFsm::GetParameter")); - - __ASSERT_DEBUG(iCurrentStateIndex != EStateMax, - User::Panic(KOmxILFsmPanicCategory, 1)); - - if (!apComponentParameterStructure) - { - return OMX_ErrorBadParameter; - } - - RETURN_OMX_ERROR_AND_EVENT_IF_NEEDED( - ipCurrentState->GetParameter(*this, aParamIndex, - apComponentParameterStructure)); - } - - -OMX_ERRORTYPE -COmxILFsm::SetParameter(OMX_INDEXTYPE aParamIndex, - const TAny* apComponentParameterStructure) - { - DEBUG_PRINTF(_L8("COmxILFsm::SetParameter")); - - __ASSERT_DEBUG(iCurrentStateIndex != EStateMax, - User::Panic(KOmxILFsmPanicCategory, 1)); - - if (!apComponentParameterStructure) - { - return OMX_ErrorBadParameter; - } - - RETURN_OMX_ERROR_AND_EVENT_IF_NEEDED( - ipCurrentState->SetParameter(*this, aParamIndex, - apComponentParameterStructure)); - } - - -OMX_ERRORTYPE -COmxILFsm::GetConfig(OMX_INDEXTYPE aConfigIndex, - TAny* apComponentConfigStructure) const - { - DEBUG_PRINTF(_L8("COmxILFsm::GetConfig")); - - __ASSERT_DEBUG(iCurrentStateIndex != EStateMax, - User::Panic(KOmxILFsmPanicCategory, 1)); - - if (!apComponentConfigStructure) - { - return OMX_ErrorBadParameter; - } - - RETURN_OMX_ERROR_AND_EVENT_IF_NEEDED( - ipCurrentState->GetConfig(*this, - aConfigIndex, - apComponentConfigStructure)); - - } - - -OMX_ERRORTYPE -COmxILFsm::SetConfig(OMX_INDEXTYPE aIndex, - const TAny* apComponentConfigStructure) - { - DEBUG_PRINTF(_L8("COmxILFsm::SetConfig")); - - __ASSERT_DEBUG(iCurrentStateIndex != EStateMax, - User::Panic(KOmxILFsmPanicCategory, 1)); - - if (!apComponentConfigStructure) - { - return OMX_ErrorBadParameter; - } - - RETURN_OMX_ERROR_AND_EVENT_IF_NEEDED( - ipCurrentState->SetConfig(*this, aIndex, apComponentConfigStructure)); - - } - - -OMX_ERRORTYPE -COmxILFsm::GetExtensionIndex( - OMX_STRING aParameterName, - OMX_INDEXTYPE* apIndexType) const - { - DEBUG_PRINTF(_L8("COmxILFsm::GetExtensionIndex")); - - __ASSERT_DEBUG(iCurrentStateIndex != EStateMax, - User::Panic(KOmxILFsmPanicCategory, 1)); - - if (!apIndexType || !aParameterName) - { - return OMX_ErrorBadParameter; - } - - RETURN_OMX_ERROR_AND_EVENT_IF_NEEDED( - ipCurrentState->GetExtensionIndex(*this, - aParameterName, - apIndexType)); - } - - -OMX_ERRORTYPE -COmxILFsm::GetState(OMX_STATETYPE* apState) const - { - DEBUG_PRINTF(_L8("COmxILFsm::GetState")); - - __ASSERT_DEBUG(iCurrentStateIndex != EStateMax, - User::Panic(KOmxILFsmPanicCategory, 1)); - - if (!apState) - { - return OMX_ErrorBadParameter; - } - - *apState = ipCurrentState->GetState(); - - return OMX_ErrorNone; - - } - - -OMX_ERRORTYPE -COmxILFsm::ComponentTunnelRequest(OMX_U32 aPort, - OMX_HANDLETYPE aTunneledComp, - OMX_U32 aTunneledPort, - OMX_TUNNELSETUPTYPE* apTunnelSetup) - { - DEBUG_PRINTF(_L8("COmxILFsm::ComponentTunnelRequest")); - - __ASSERT_DEBUG(iCurrentStateIndex != EStateMax, - User::Panic(KOmxILFsmPanicCategory, 1)); - - // Here, since NULL is a valid parameter for aTunneledComp, checking of - // input parameters is completely done by the ports. - RETURN_OMX_ERROR_AND_EVENT_IF_NEEDED( - ipCurrentState->ComponentTunnelRequest(*this, - aPort, - aTunneledComp, - aTunneledPort, - apTunnelSetup)); - - } - - -OMX_ERRORTYPE -COmxILFsm::UseBuffer(OMX_BUFFERHEADERTYPE** appBufferHdr, - OMX_U32 aPortIndex, - OMX_PTR apAppPrivate, - OMX_U32 aSizeBytes, - OMX_U8* apBuffer) - { - DEBUG_PRINTF(_L8("COmxILFsm::UseBuffer")); - - __ASSERT_DEBUG(iCurrentStateIndex != EStateMax, - User::Panic(KOmxILFsmPanicCategory, 1)); - - if (!appBufferHdr || !aSizeBytes || !apBuffer) - { - return OMX_ErrorBadParameter; - } - - return PopulateBuffer(appBufferHdr, - aPortIndex, - apAppPrivate, - aSizeBytes, - apBuffer); - - } - - -OMX_ERRORTYPE -COmxILFsm::AllocateBuffer(OMX_BUFFERHEADERTYPE** appBufferHdr, - OMX_U32 aPortIndex, - OMX_PTR apAppPrivate, - OMX_U32 aSizeBytes) - { - DEBUG_PRINTF(_L8("COmxILFsm::AllocateBuffer")); - - __ASSERT_DEBUG(iCurrentStateIndex != EStateMax, - User::Panic(KOmxILFsmPanicCategory, 1)); - - if (!appBufferHdr || !aSizeBytes) - { - return OMX_ErrorBadParameter; - } - - - return PopulateBuffer(appBufferHdr, - aPortIndex, - apAppPrivate, - aSizeBytes, - 0); - - } - - -OMX_ERRORTYPE -COmxILFsm::FreeBuffer(OMX_U32 aPortIndex, - OMX_BUFFERHEADERTYPE* apBuffer) - { - DEBUG_PRINTF(_L8("COmxILFsm::FreeBuffer")); - - __ASSERT_DEBUG(iCurrentStateIndex != EStateMax, - User::Panic(KOmxILFsmPanicCategory, 1)); - - if (!apBuffer) - { - return OMX_ErrorBadParameter; - } - - TBool portDepopulationCompleted = EFalse; - OMX_ERRORTYPE omxRetValue = - ipCurrentState->FreeBuffer(*this, - aPortIndex, - apBuffer, - portDepopulationCompleted); - - if (OMX_ErrorNone == omxRetValue) - { - if (portDepopulationCompleted) - { - if (ESubStateIdleToLoaded == iCurrentStateIndex) - { - if (iPortManager.AllPortsDePopulated()) - { - // Complete here the transition to OMX_StateLoaded - omxRetValue = FsmTransition(EStateLoaded); - if (OMX_ErrorNone == omxRetValue) - { - // Notify the IL client that port depopulation has - // completed sucessfully - omxRetValue = - iCallbacks.TransitionCompleteNotification( - OMX_StateLoaded); - } - } - } - } - } - - if (OMX_ErrorNone == omxRetValue) - { - return OMX_ErrorNone; - } - else - { - return SendOmxErrorEventIfNeeded(omxRetValue); - } - - } - - -OMX_ERRORTYPE -COmxILFsm::EmptyThisBuffer(OMX_BUFFERHEADERTYPE* apBuffer) - { - DEBUG_PRINTF2(_L8("COmxILFsm::EmptyThisBuffer : BUFFER [%X]"), apBuffer); - - __ASSERT_DEBUG(iCurrentStateIndex != EStateMax, - User::Panic(KOmxILFsmPanicCategory, 1)); - - if (!apBuffer) - { - return OMX_ErrorBadParameter; - } - - RETURN_OMX_ERROR_AND_EVENT_IF_NEEDED( - ipCurrentState->EmptyThisBuffer(*this, apBuffer)); - - } - - -OMX_ERRORTYPE -COmxILFsm::FillThisBuffer(OMX_BUFFERHEADERTYPE* apBuffer) - { - DEBUG_PRINTF2(_L8("COmxILFsm::FillThisBuffer : BUFFER [%X]"), apBuffer); - - __ASSERT_DEBUG(iCurrentStateIndex != EStateMax, - User::Panic(KOmxILFsmPanicCategory, 1)); - - if (!apBuffer) - { - return OMX_ErrorBadParameter; - } - - RETURN_OMX_ERROR_AND_EVENT_IF_NEEDED( - ipCurrentState->FillThisBuffer(*this, apBuffer)); - - } - - -OMX_ERRORTYPE -COmxILFsm::SetCallbacks(const OMX_CALLBACKTYPE* apCallbacks, - const OMX_PTR apAppData) - { - DEBUG_PRINTF(_L8("COmxILFsm::SetCallbacks")); - - __ASSERT_DEBUG(iCurrentStateIndex != EStateMax, - User::Panic(KOmxILFsmPanicCategory, 1)); - - if (!apCallbacks) - { - return OMX_ErrorBadParameter; - } - - // This api should only be allowed in OMX_StateLoaded - if (EStateLoaded != iCurrentStateIndex) - { - return OMX_ErrorIncorrectStateOperation; - } - - RETURN_OMX_ERROR_AND_EVENT_IF_NEEDED( - iCallbacks.RegisterILClientCallbacks(apCallbacks, apAppData)); - - } - - -OMX_ERRORTYPE -COmxILFsm::UseEGLImage(OMX_BUFFERHEADERTYPE** /*appBufferHdr*/, - OMX_U32 /*aPortIndex*/, - OMX_PTR /*aAppPrivate*/, - void* /*eglImage*/) - { - DEBUG_PRINTF(_L8("COmxILFsm::UseEGLImage")); - - __ASSERT_DEBUG(iCurrentStateIndex != EStateMax, - User::Panic(KOmxILFsmPanicCategory, 1)); - - return OMX_ErrorNotImplemented; - } - -OMX_ERRORTYPE -COmxILFsm::ComponentRoleEnum(OMX_U8* aRole, - OMX_U32 aIndex) const - { - DEBUG_PRINTF(_L8("COmxILFsm::ComponentRoleEnum")); - - __ASSERT_DEBUG(iCurrentStateIndex != EStateMax, - User::Panic(KOmxILFsmPanicCategory, 1)); - - // This api should not be allowed in OMX_StateInvalid - if (EStateInvalid == iCurrentStateIndex) - { - return SendOmxErrorEventIfNeeded(OMX_ErrorInvalidState); - } - - if (!aRole) - { - return OMX_ErrorBadParameter; - } - - RETURN_OMX_ERROR_AND_EVENT_IF_NEEDED( - iConfigManager.ComponentRoleEnum(aRole, - aIndex)); - - } - -/** - This method is here to fullfill the following functionalities: - - -# It is used to make sure that the component error codes are returned to - the IL Client in a way that conforms with Table 3-9 of the OpenMAX IL - 1.1.1 spec. This table specifies which error codes must be sent with - EventHandler. If an error code is to be sent via EventHandler, the API - return code must be OMX_ErrorNone. - - -# This method is also used to invalidate the component whenever an internal - component action returns OMX_ErrorInvalidState. For example, this is - useful when code executed by a port or by the processing function cannot - recover from an internal error. Returning OMX_ErrorInvalidState in that - kind of situation will invalidate the component in - SendOmxErrorEventIfNeeded and the event will be conveyed to the IL Client - as mandated by the spec. - - @param aError An OpenMAX IL error code. - */ -OMX_ERRORTYPE -COmxILFsm::SendOmxErrorEventIfNeeded(OMX_ERRORTYPE aError) - { - DEBUG_PRINTF2(_L8("COmxILFsm::SendOmxErrorEventIfNeeded - aError = 0x%X"), aError); - - OMX_ERRORTYPE returnError = aError; - switch(aError) - { - case OMX_ErrorInsufficientResources: - { - DEBUG_PRINTF(_L8("COmxILFsm::SendOmxErrorEventIfNeeded aError[OMX_ErrorInsufficientResources]")); - iCallbacks.ErrorEventNotification(aError); - } - break; - case OMX_ErrorInvalidState: - { - DEBUG_PRINTF(_L8("COmxILFsm::SendOmxErrorEventIfNeeded aError[OMX_ErrorInvalidState]")); - iCallbacks.ErrorEventNotification(aError); - if (EStateInvalid != iCurrentStateIndex) - { - returnError = OMX_ErrorNone; - } - } - break; - case OMX_ErrorUnderflow: - case OMX_ErrorOverflow: - case OMX_ErrorHardware: - case OMX_ErrorStreamCorrupt: - case OMX_ErrorResourcesLost: - case OMX_ErrorSameState: - case OMX_ErrorResourcesPreempted: - case OMX_ErrorPortUnresponsiveDuringAllocation: - case OMX_ErrorPortUnresponsiveDuringDeallocation: - case OMX_ErrorPortUnresponsiveDuringStop: - case OMX_ErrorIncorrectStateTransition: - case OMX_ErrorPortUnpopulated: - case OMX_ErrorDynamicResourcesUnavailable: - case OMX_ErrorMbErrorsInFrame: - case OMX_ErrorFormatNotDetected: - { - DEBUG_PRINTF2(_L8("COmxILFsm::SendOmxErrorEventIfNeeded aError[%X]"), aError); - iCallbacks.ErrorEventNotification(aError); - returnError = OMX_ErrorNone; - } - break; - }; - - if(OMX_ErrorInvalidState == aError && - EStateInvalid != iCurrentStateIndex) - { - // Invalidate this component. This instance of the component should be - // destroyed by the IL Client after this. No need to check error code. - FsmTransition(EStateInvalid); - } - - return returnError; - - } - -OMX_ERRORTYPE -COmxILFsm::SendOmxErrorEventIfNeeded(OMX_ERRORTYPE aError) const - { - DEBUG_PRINTF(_L8("COmxILFsm::SendOmxErrorEventIfNeeded")); - - return const_cast(this)->SendOmxErrorEventIfNeeded(aError); - - } +// Copyright (c) 2008-2009 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 "log.h" +#include "omxilfsm.h" +#include "omxilstate.h" +#include "omxilconfigmanager.h" +#include "omxilcallbackmanager.h" +#include "omxilprocessingfunction.h" +#include "omxilportmanagerif.h" + +#define RETURN_OMX_ERROR_AND_EVENT_IF_NEEDED(_a) \ + { \ + const OMX_ERRORTYPE _err = _a; \ + if (OMX_ErrorNone == _err) return _err; \ + else return SendOmxErrorEventIfNeeded(_err); \ + } + + +const TInt COmxILFsm::KMaxMsgQueueEntries; + +EXPORT_C COmxILFsm* +COmxILFsm::NewL(COmxILComponent& aComponent, + COmxILProcessingFunction& aProcFunction, + MOmxILPortManagerIf& aPortManager, + COmxILConfigManager& aConfigManager, + MOmxILCallbackManagerIf& aCallbacks) + { + DEBUG_PRINTF(_L8("COmxILFsm::NewLC")); + + COmxILFsm* self = new (ELeave) COmxILFsm(aComponent, + aProcFunction, + aPortManager, + aConfigManager, + aCallbacks); + CleanupStack::PushL(self); + self->ConstructL(); + CleanupStack::Pop(self); + return (self); + } + +void +COmxILFsm::ConstructL() + { + DEBUG_PRINTF(_L8("COmxILFsm::ConstructL")); + + // Create the FSM states + + // Init the array + for (TUint i=0; i < EStateMax; ++i) + { + iStates.AppendL(NULL); + } + + // Add the standard states... + iStates[EStateInvalid] = new (ELeave)COmxILStateInvalid; + iStates[EStateLoaded] = new (ELeave)COmxILStateLoaded; + iStates[EStateIdle] = new (ELeave)COmxILStateIdle; + iStates[EStateExecuting] = new (ELeave)COmxILStateExecuting; + iStates[EStatePause] = new (ELeave)COmxILStatePause; + iStates[EStateWaitForResources] = new (ELeave)COmxILStateWaitForResources; + + // Now add the substates + iStates[ESubStateLoadedToIdle] = new (ELeave)COmxILStateLoadedToIdle; + iStates[ESubStateIdleToLoaded] = new (ELeave)COmxILStateIdleToLoaded; + iStates[ESubStateExecutingToIdle] = new (ELeave)COmxILStateExecutingToIdle; + iStates[ESubStatePauseToIdle] = new (ELeave)COmxILStatePauseToIdle; + + iCallbacks.SetPortManager(iPortManager); + iCallbacks.SetFsm(*this); + + } + +COmxILFsm::COmxILFsm(COmxILComponent& aComponent, + COmxILProcessingFunction& aProcFunction, + MOmxILPortManagerIf& aPortManager, + COmxILConfigManager& aConfigManager, + MOmxILCallbackManagerIf& aCallbacks) + : + iComponent(aComponent), + iProcFunction(aProcFunction), + iPortManager(aPortManager), + iConfigManager(aConfigManager), + iCallbacks(aCallbacks), + iStates(), + iCurrentStateIndex(EStateMax), + ipCurrentState(0) + { + DEBUG_PRINTF(_L8("COmxILFsm::COmxILFsm")); + } + +COmxILFsm::~COmxILFsm() + { + DEBUG_PRINTF(_L8("COmxILFsm::~COmxILFsm")); + + iCurrentStateIndex = EStateMax; + ipCurrentState = 0; + iStates.ResetAndDestroy(); + + } + +OMX_ERRORTYPE +COmxILFsm::InitFsm() + { + DEBUG_PRINTF(_L8("COmxILFsm::InitFsm")); + + // Let's get ready to handle API calls... + iCurrentStateIndex = EStateLoaded; + ipCurrentState = iStates[iCurrentStateIndex]; + return OMX_ErrorNone; + + } + +COmxILComponent* +COmxILFsm::GetComponent() const + { + return &iComponent; + } + +OMX_ERRORTYPE +COmxILFsm::PopulateBuffer(OMX_BUFFERHEADERTYPE** appBufferHdr, + OMX_U32 aPortIndex, + OMX_PTR apAppPrivate, + OMX_U32 aSizeBytes, + OMX_U8* apBuffer) + { + DEBUG_PRINTF(_L8("COmxILFsm::PopulateBuffer")); + + TBool portPopulationCompleted = EFalse; + OMX_ERRORTYPE omxRetValue = + ipCurrentState->PopulateBuffer(*this, + appBufferHdr, + aPortIndex, + apAppPrivate, + aSizeBytes, + apBuffer, + portPopulationCompleted); + + if (OMX_ErrorNone == omxRetValue) + { + if (portPopulationCompleted && + ESubStateLoadedToIdle == iCurrentStateIndex && + iPortManager.AllPortsPopulated()) + { + // Complete here the transition to OMX_StateIdle + omxRetValue = FsmTransition(EStateIdle); + if (OMX_ErrorNone == omxRetValue) + { + // Notify the IL client that port population has + // completed sucessfully + omxRetValue = iCallbacks.TransitionCompleteNotification( + OMX_StateIdle); + + } + } + } + + if (OMX_ErrorNone == omxRetValue || + OMX_ErrorInsufficientResources == omxRetValue) + { + // OMX_ErrorInsufficientResources is allowed in OMX_EmptyThisBuffer and + // OMX_FillThisBuffer + return omxRetValue; + } + else + { + return SendOmxErrorEventIfNeeded(omxRetValue); + } + + } + +OMX_ERRORTYPE +COmxILFsm::FsmTransition(TStateIndex aNewState) + { + DEBUG_PRINTF2(_L8("COmxILFsm::FsmTransition : %d"), aNewState); + + __ASSERT_ALWAYS(aNewState < EStateMax, + User::Panic(KOmxILFsmPanicCategory, 1)); + + if (aNewState != iCurrentStateIndex) + { + // We notify the processing function of all the state transitions, even + // if they are not to a final OpenMAX IL state. + OMX_ERRORTYPE omxRetValue; + if (OMX_ErrorNone != + (omxRetValue = + iProcFunction.StateTransitionIndication(aNewState))) + { + // No need of propagating further error codes if the component is + // transitioning to OMX_StateInvalid or if the PF itself is + // invalidating the component... + if (EStateInvalid != aNewState && + OMX_ErrorInvalidState != omxRetValue) + { + return omxRetValue; + } + } + + iCurrentStateIndex = aNewState; + ipCurrentState = iStates[iCurrentStateIndex]; + + } + + return OMX_ErrorNone; + + } + +OMX_ERRORTYPE +COmxILFsm::FsmTransition(TUint32 aNewState) + { + + return FsmTransition(static_cast(aNewState)); + + } + + +OMX_ERRORTYPE +COmxILFsm::GetComponentVersion(OMX_STRING aComponentName, + OMX_VERSIONTYPE* apComponentVersion, + OMX_VERSIONTYPE* apSpecVersion, + OMX_UUIDTYPE* apComponentUUID) const + { + DEBUG_PRINTF(_L8("COmxILFsm::GetComponentVersion")); + + __ASSERT_DEBUG(iCurrentStateIndex != EStateMax, + User::Panic(KOmxILFsmPanicCategory, 1)); + + // This api should not be allowed in OMX_StateInvalid + if (EStateInvalid == iCurrentStateIndex) + { + return SendOmxErrorEventIfNeeded(OMX_ErrorInvalidState); + } + + if (!aComponentName || + !apComponentVersion || + !apSpecVersion || + !apComponentUUID) + { + return OMX_ErrorBadParameter; + } + + // This API call is independent of the current state. Its handled by the + // the config manager + + RETURN_OMX_ERROR_AND_EVENT_IF_NEEDED( + iConfigManager.GetComponentVersion( + aComponentName, + apComponentVersion, + apSpecVersion, + apComponentUUID)); + } + + +OMX_ERRORTYPE +COmxILFsm::SendCommand(OMX_COMMANDTYPE aCommand, + TUint32 anParam1, + TAny* apCmdData) + { + DEBUG_PRINTF3(_L8("COmxILFsm::SendCommand : command [%d] Param1 [%d]"), aCommand, anParam1); + + __ASSERT_DEBUG(iCurrentStateIndex != EStateMax, + User::Panic(KOmxILFsmPanicCategory, 1)); + + // Do some very minor error checking here to try to save some time... + if (OMX_CommandStateSet == aCommand && + anParam1 > OMX_StateWaitForResources) + { + return OMX_ErrorBadParameter; + } + + TOmxILCommand command(aCommand, anParam1, apCmdData); + OMX_ERRORTYPE sendCommandError; + switch (aCommand) + { + case OMX_CommandStateSet: + { + sendCommandError = ipCurrentState->CommandStateSet(*this, command); + } + break; + case OMX_CommandFlush: + { + sendCommandError = ipCurrentState->CommandFlush(*this, command); + } + break; + case OMX_CommandPortDisable: + { + sendCommandError = ipCurrentState->CommandPortDisable(*this, command); + } + break; + case OMX_CommandPortEnable: + { + sendCommandError = ipCurrentState->CommandPortEnable(*this, command); + } + break; + case OMX_CommandMarkBuffer: + { + sendCommandError = ipCurrentState->CommandMarkBuffer(*this, command); + } + break; + default: + { + // This is an invalid command type + return OMX_ErrorBadParameter; + } + }; + + if (OMX_ErrorNone == sendCommandError || + OMX_ErrorInsufficientResources == sendCommandError) + { + // OMX_ErrorInsufficientResources is allowed in OMX_SendCommand + return sendCommandError; + } + else + { + return SendOmxErrorEventIfNeeded(sendCommandError); + } + + } + + +OMX_ERRORTYPE +COmxILFsm::GetParameter(OMX_INDEXTYPE aParamIndex, + TAny* apComponentParameterStructure) const + { + DEBUG_PRINTF(_L8("COmxILFsm::GetParameter")); + + __ASSERT_DEBUG(iCurrentStateIndex != EStateMax, + User::Panic(KOmxILFsmPanicCategory, 1)); + + if (!apComponentParameterStructure) + { + return OMX_ErrorBadParameter; + } + + RETURN_OMX_ERROR_AND_EVENT_IF_NEEDED( + ipCurrentState->GetParameter(*this, aParamIndex, + apComponentParameterStructure)); + } + + +OMX_ERRORTYPE +COmxILFsm::SetParameter(OMX_INDEXTYPE aParamIndex, + const TAny* apComponentParameterStructure) + { + DEBUG_PRINTF(_L8("COmxILFsm::SetParameter")); + + __ASSERT_DEBUG(iCurrentStateIndex != EStateMax, + User::Panic(KOmxILFsmPanicCategory, 1)); + + if (!apComponentParameterStructure) + { + return OMX_ErrorBadParameter; + } + + RETURN_OMX_ERROR_AND_EVENT_IF_NEEDED( + ipCurrentState->SetParameter(*this, aParamIndex, + apComponentParameterStructure)); + } + + +OMX_ERRORTYPE +COmxILFsm::GetConfig(OMX_INDEXTYPE aConfigIndex, + TAny* apComponentConfigStructure) const + { + DEBUG_PRINTF(_L8("COmxILFsm::GetConfig")); + + __ASSERT_DEBUG(iCurrentStateIndex != EStateMax, + User::Panic(KOmxILFsmPanicCategory, 1)); + + if (!apComponentConfigStructure) + { + return OMX_ErrorBadParameter; + } + + RETURN_OMX_ERROR_AND_EVENT_IF_NEEDED( + ipCurrentState->GetConfig(*this, + aConfigIndex, + apComponentConfigStructure)); + + } + + +OMX_ERRORTYPE +COmxILFsm::SetConfig(OMX_INDEXTYPE aIndex, + const TAny* apComponentConfigStructure) + { + DEBUG_PRINTF(_L8("COmxILFsm::SetConfig")); + + __ASSERT_DEBUG(iCurrentStateIndex != EStateMax, + User::Panic(KOmxILFsmPanicCategory, 1)); + + if (!apComponentConfigStructure) + { + return OMX_ErrorBadParameter; + } + + RETURN_OMX_ERROR_AND_EVENT_IF_NEEDED( + ipCurrentState->SetConfig(*this, aIndex, apComponentConfigStructure)); + + } + + +OMX_ERRORTYPE +COmxILFsm::GetExtensionIndex( + OMX_STRING aParameterName, + OMX_INDEXTYPE* apIndexType) const + { + DEBUG_PRINTF(_L8("COmxILFsm::GetExtensionIndex")); + + __ASSERT_DEBUG(iCurrentStateIndex != EStateMax, + User::Panic(KOmxILFsmPanicCategory, 1)); + + if (!apIndexType || !aParameterName) + { + return OMX_ErrorBadParameter; + } + + RETURN_OMX_ERROR_AND_EVENT_IF_NEEDED( + ipCurrentState->GetExtensionIndex(*this, + aParameterName, + apIndexType)); + } + + +OMX_ERRORTYPE +COmxILFsm::GetState(OMX_STATETYPE* apState) const + { + DEBUG_PRINTF(_L8("COmxILFsm::GetState")); + + __ASSERT_DEBUG(iCurrentStateIndex != EStateMax, + User::Panic(KOmxILFsmPanicCategory, 1)); + + if (!apState) + { + return OMX_ErrorBadParameter; + } + + *apState = ipCurrentState->GetState(); + + return OMX_ErrorNone; + + } + + +OMX_ERRORTYPE +COmxILFsm::ComponentTunnelRequest(OMX_U32 aPort, + OMX_HANDLETYPE aTunneledComp, + OMX_U32 aTunneledPort, + OMX_TUNNELSETUPTYPE* apTunnelSetup) + { + DEBUG_PRINTF(_L8("COmxILFsm::ComponentTunnelRequest")); + + __ASSERT_DEBUG(iCurrentStateIndex != EStateMax, + User::Panic(KOmxILFsmPanicCategory, 1)); + + // Here, since NULL is a valid parameter for aTunneledComp, checking of + // input parameters is completely done by the ports. + RETURN_OMX_ERROR_AND_EVENT_IF_NEEDED( + ipCurrentState->ComponentTunnelRequest(*this, + aPort, + aTunneledComp, + aTunneledPort, + apTunnelSetup)); + + } + + +OMX_ERRORTYPE +COmxILFsm::UseBuffer(OMX_BUFFERHEADERTYPE** appBufferHdr, + OMX_U32 aPortIndex, + OMX_PTR apAppPrivate, + OMX_U32 aSizeBytes, + OMX_U8* apBuffer) + { + DEBUG_PRINTF(_L8("COmxILFsm::UseBuffer")); + + __ASSERT_DEBUG(iCurrentStateIndex != EStateMax, + User::Panic(KOmxILFsmPanicCategory, 1)); + + if (!appBufferHdr || !aSizeBytes || !apBuffer) + { + return OMX_ErrorBadParameter; + } + + return PopulateBuffer(appBufferHdr, + aPortIndex, + apAppPrivate, + aSizeBytes, + apBuffer); + + } + + +OMX_ERRORTYPE +COmxILFsm::AllocateBuffer(OMX_BUFFERHEADERTYPE** appBufferHdr, + OMX_U32 aPortIndex, + OMX_PTR apAppPrivate, + OMX_U32 aSizeBytes) + { + DEBUG_PRINTF(_L8("COmxILFsm::AllocateBuffer")); + + __ASSERT_DEBUG(iCurrentStateIndex != EStateMax, + User::Panic(KOmxILFsmPanicCategory, 1)); + + if (!appBufferHdr || !aSizeBytes) + { + return OMX_ErrorBadParameter; + } + + + return PopulateBuffer(appBufferHdr, + aPortIndex, + apAppPrivate, + aSizeBytes, + 0); + + } + + +OMX_ERRORTYPE +COmxILFsm::FreeBuffer(OMX_U32 aPortIndex, + OMX_BUFFERHEADERTYPE* apBuffer) + { + DEBUG_PRINTF(_L8("COmxILFsm::FreeBuffer")); + + __ASSERT_DEBUG(iCurrentStateIndex != EStateMax, + User::Panic(KOmxILFsmPanicCategory, 1)); + + if (!apBuffer) + { + return OMX_ErrorBadParameter; + } + + TBool portDepopulationCompleted = EFalse; + OMX_ERRORTYPE omxRetValue = + ipCurrentState->FreeBuffer(*this, + aPortIndex, + apBuffer, + portDepopulationCompleted); + + if (OMX_ErrorNone == omxRetValue) + { + if (portDepopulationCompleted) + { + if (ESubStateIdleToLoaded == iCurrentStateIndex) + { + if (iPortManager.AllPortsDePopulated()) + { + // Complete here the transition to OMX_StateLoaded + omxRetValue = FsmTransition(EStateLoaded); + if (OMX_ErrorNone == omxRetValue) + { + // Notify the IL client that port depopulation has + // completed sucessfully + omxRetValue = + iCallbacks.TransitionCompleteNotification( + OMX_StateLoaded); + } + } + } + } + } + + if (OMX_ErrorNone == omxRetValue) + { + return OMX_ErrorNone; + } + else + { + return SendOmxErrorEventIfNeeded(omxRetValue); + } + + } + + +OMX_ERRORTYPE +COmxILFsm::EmptyThisBuffer(OMX_BUFFERHEADERTYPE* apBuffer) + { + DEBUG_PRINTF2(_L8("COmxILFsm::EmptyThisBuffer : BUFFER [%X]"), apBuffer); + + __ASSERT_DEBUG(iCurrentStateIndex != EStateMax, + User::Panic(KOmxILFsmPanicCategory, 1)); + + if (!apBuffer) + { + return OMX_ErrorBadParameter; + } + + RETURN_OMX_ERROR_AND_EVENT_IF_NEEDED( + ipCurrentState->EmptyThisBuffer(*this, apBuffer)); + + } + + +OMX_ERRORTYPE +COmxILFsm::FillThisBuffer(OMX_BUFFERHEADERTYPE* apBuffer) + { + DEBUG_PRINTF2(_L8("COmxILFsm::FillThisBuffer : BUFFER [%X]"), apBuffer); + + __ASSERT_DEBUG(iCurrentStateIndex != EStateMax, + User::Panic(KOmxILFsmPanicCategory, 1)); + + if (!apBuffer) + { + return OMX_ErrorBadParameter; + } + + RETURN_OMX_ERROR_AND_EVENT_IF_NEEDED( + ipCurrentState->FillThisBuffer(*this, apBuffer)); + + } + + +OMX_ERRORTYPE +COmxILFsm::SetCallbacks(const OMX_CALLBACKTYPE* apCallbacks, + const OMX_PTR apAppData) + { + DEBUG_PRINTF(_L8("COmxILFsm::SetCallbacks")); + + __ASSERT_DEBUG(iCurrentStateIndex != EStateMax, + User::Panic(KOmxILFsmPanicCategory, 1)); + + if (!apCallbacks) + { + return OMX_ErrorBadParameter; + } + + // This api should only be allowed in OMX_StateLoaded + if (EStateLoaded != iCurrentStateIndex) + { + return OMX_ErrorIncorrectStateOperation; + } + + RETURN_OMX_ERROR_AND_EVENT_IF_NEEDED( + iCallbacks.RegisterILClientCallbacks(apCallbacks, apAppData)); + + } + + +OMX_ERRORTYPE +COmxILFsm::UseEGLImage(OMX_BUFFERHEADERTYPE** /*appBufferHdr*/, + OMX_U32 /*aPortIndex*/, + OMX_PTR /*aAppPrivate*/, + void* /*eglImage*/) + { + DEBUG_PRINTF(_L8("COmxILFsm::UseEGLImage")); + + __ASSERT_DEBUG(iCurrentStateIndex != EStateMax, + User::Panic(KOmxILFsmPanicCategory, 1)); + + return OMX_ErrorNotImplemented; + } + +OMX_ERRORTYPE +COmxILFsm::ComponentRoleEnum(OMX_U8* aRole, + OMX_U32 aIndex) const + { + DEBUG_PRINTF(_L8("COmxILFsm::ComponentRoleEnum")); + + __ASSERT_DEBUG(iCurrentStateIndex != EStateMax, + User::Panic(KOmxILFsmPanicCategory, 1)); + + // This api should not be allowed in OMX_StateInvalid + if (EStateInvalid == iCurrentStateIndex) + { + return SendOmxErrorEventIfNeeded(OMX_ErrorInvalidState); + } + + if (!aRole) + { + return OMX_ErrorBadParameter; + } + + RETURN_OMX_ERROR_AND_EVENT_IF_NEEDED( + iConfigManager.ComponentRoleEnum(aRole, + aIndex)); + + } + +/** + This method is here to fullfill the following functionalities: + + -# It is used to make sure that the component error codes are returned to + the IL Client in a way that conforms with Table 3-9 of the OpenMAX IL + 1.1.1 spec. This table specifies which error codes must be sent with + EventHandler. If an error code is to be sent via EventHandler, the API + return code must be OMX_ErrorNone. + + -# This method is also used to invalidate the component whenever an internal + component action returns OMX_ErrorInvalidState. For example, this is + useful when code executed by a port or by the processing function cannot + recover from an internal error. Returning OMX_ErrorInvalidState in that + kind of situation will invalidate the component in + SendOmxErrorEventIfNeeded and the event will be conveyed to the IL Client + as mandated by the spec. + + @param aError An OpenMAX IL error code. + */ +OMX_ERRORTYPE +COmxILFsm::SendOmxErrorEventIfNeeded(OMX_ERRORTYPE aError) + { + DEBUG_PRINTF2(_L8("COmxILFsm::SendOmxErrorEventIfNeeded - aError = 0x%X"), aError); + + OMX_ERRORTYPE returnError = aError; + switch(aError) + { + case OMX_ErrorInsufficientResources: + { + DEBUG_PRINTF(_L8("COmxILFsm::SendOmxErrorEventIfNeeded aError[OMX_ErrorInsufficientResources]")); + iCallbacks.ErrorEventNotification(aError); + } + break; + case OMX_ErrorInvalidState: + { + DEBUG_PRINTF(_L8("COmxILFsm::SendOmxErrorEventIfNeeded aError[OMX_ErrorInvalidState]")); + iCallbacks.ErrorEventNotification(aError); + if (EStateInvalid != iCurrentStateIndex) + { + returnError = OMX_ErrorNone; + } + } + break; + case OMX_ErrorUnderflow: + case OMX_ErrorOverflow: + case OMX_ErrorHardware: + case OMX_ErrorStreamCorrupt: + case OMX_ErrorResourcesLost: + case OMX_ErrorSameState: + case OMX_ErrorResourcesPreempted: + case OMX_ErrorPortUnresponsiveDuringAllocation: + case OMX_ErrorPortUnresponsiveDuringDeallocation: + case OMX_ErrorPortUnresponsiveDuringStop: + case OMX_ErrorIncorrectStateTransition: + case OMX_ErrorPortUnpopulated: + case OMX_ErrorDynamicResourcesUnavailable: + case OMX_ErrorMbErrorsInFrame: + case OMX_ErrorFormatNotDetected: + { + DEBUG_PRINTF2(_L8("COmxILFsm::SendOmxErrorEventIfNeeded aError[%X]"), aError); + iCallbacks.ErrorEventNotification(aError); + returnError = OMX_ErrorNone; + } + break; + }; + + if(OMX_ErrorInvalidState == aError && + EStateInvalid != iCurrentStateIndex) + { + // Invalidate this component. This instance of the component should be + // destroyed by the IL Client after this. No need to check error code. + FsmTransition(EStateInvalid); + } + + return returnError; + + } + +OMX_ERRORTYPE +COmxILFsm::SendOmxErrorEventIfNeeded(OMX_ERRORTYPE aError) const + { + DEBUG_PRINTF(_L8("COmxILFsm::SendOmxErrorEventIfNeeded")); + + return const_cast(this)->SendOmxErrorEventIfNeeded(aError); + + }