diff -r 000000000000 -r 40261b775718 omxil/mmilapi/refomxil/src/omxilgenericilif/omxilgenericilifbodyimpl.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/omxil/mmilapi/refomxil/src/omxilgenericilif/omxilgenericilifbodyimpl.cpp Tue Feb 02 01:56:55 2010 +0200 @@ -0,0 +1,441 @@ +// 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: +// omxilgenericifilbodyimpl.cpp +// +// + +#include "omxilgenericilifbodyimpl.h" +#include "omxilcoreutils.h" +#include +#include +#include + + +const TInt KMaxMsgQueueEntries = 10; + +COmxBufferManager::COmxBufferManager(OMX_COMPONENTTYPE* aHandle) + : iHandle(aHandle) + { + } + +COmxBufferManager::COmxBuffer::COmxBuffer() + { + } + + +COmxBufferManager::COmxBuffer* COmxBufferManager::COmxBuffer::NewL(OMX_BUFFERHEADERTYPE* aBufferHeader, + CMMFBuffer* aBuffer) + { + COmxBuffer* self = new (ELeave) COmxBuffer; + CleanupStack::PushL(self); + self->ConstructL(aBufferHeader, aBuffer); + CleanupStack::Pop(self); + return self; + } + +COmxBufferManager::COmxBuffer::~COmxBuffer() + { + if (iOwnsMmfBuffer) + { + delete iMmfBuffer; + } + } + +CMMFBuffer* COmxBufferManager::COmxBuffer::MmfBuffer() const + { + return iMmfBuffer; + } + +OMX_BUFFERHEADERTYPE* COmxBufferManager::COmxBuffer::BufferHeader() const + { + return iBufferHeader; + } + +void COmxBufferManager::COmxBuffer::SetPortObserver(MOmxILComponentIfObserver* aObserver) + { + iPortObserver = aObserver; + } + +MOmxILComponentIfObserver* COmxBufferManager::COmxBuffer::PortObserver() const + { + return iPortObserver; + } + +COmxBufferManager::COmxBuffer* COmxBufferManager::FindBuffer(const CMMFBuffer* aBuffer) const + { + COmxBuffer* buffer = NULL; + for (TInt i=0;iMmfBuffer() == aBuffer) + { + buffer = iBuffers[i]; + } + } + return buffer; + } + +COmxBufferManager::COmxBuffer* COmxBufferManager::FindBuffer(OMX_BUFFERHEADERTYPE* aBuffer) const + { + return reinterpret_cast(aBuffer->pAppPrivate); + } + + TInt COmxBufferManager::UseBuffer(CMMFBuffer& aBuffer, TUint aPortIndex) + { + if (CMMFBuffer::IsSupportedDataBuffer(aBuffer.Type())) + { + OMX_BUFFERHEADERTYPE* buffer; + CMMFDataBuffer& dataBuffer = static_cast(aBuffer); + + TDes8& aBufferDes = dataBuffer.Data(); + OMX_ERRORTYPE error = iHandle->UseBuffer(static_cast(iHandle), &buffer, aPortIndex, (void*)&aBuffer, aBufferDes.MaxLength(), const_cast(aBufferDes.Ptr())); + if (error != OMX_ErrorNone) + { + return ConvertOmxErrorType(error); + } + TRAPD(err, StoreBufferL(buffer, &aBuffer)); + return err; + } + else + { + return KErrNotSupported; + } + } + + + CMMFBuffer* COmxBufferManager::AllocateBufferL(TUint aPortIndex, + TUint aSizeBytes) + { + OMX_BUFFERHEADERTYPE* buffer; + OMX_ERRORTYPE error = iHandle->AllocateBuffer(static_cast(iHandle), &buffer, aPortIndex, NULL, aSizeBytes); + User::LeaveIfError(ConvertOmxErrorType(error)); + + StoreBufferL(buffer,NULL); // transfers ownership + + return FindBuffer(buffer)->MmfBuffer(); + } + + + TInt COmxBufferManager::FreeBuffer(CMMFBuffer* aBuffer) + { + COmxBuffer* buffer; + for (TInt i=0;iMmfBuffer() == aBuffer) + { + iBuffers.Remove(i); + OMX_ERRORTYPE err = iHandle->FreeBuffer(static_cast(iHandle), 0, buffer->BufferHeader()); + delete buffer; + return err; + } + } + return KErrNotFound; + } + +void COmxBufferManager::COmxBuffer::ConstructL(OMX_BUFFERHEADERTYPE* aBufferHeader, + CMMFBuffer* aBuffer) + { + + // Now if CMMFBuffer is NULL, this is been called from allocate buffer, and we need to + // Allocate a ptr buffer to correspond to the buffer created by OMX + ASSERT(aBufferHeader); + iBufferHeader = aBufferHeader; + if (aBuffer == NULL) + { + TPtr8 ptr(iBufferHeader->pBuffer, iBufferHeader->nFilledLen, iBufferHeader->nAllocLen); + CMMFBuffer* mmfBuffer = CMMFPtrBuffer::NewL(ptr); + iMmfBuffer = mmfBuffer; + iOwnsMmfBuffer = ETrue; + } + else + { + iMmfBuffer = aBuffer; + } + + // store pointer to element in array + iBufferHeader->pAppPrivate = this; + } + +void COmxBufferManager::StoreBufferL(OMX_BUFFERHEADERTYPE* aBufferHeader, + CMMFBuffer* aBuffer) + { + COmxBuffer* buf = COmxBuffer::NewL(aBufferHeader, aBuffer); + CleanupStack::PushL(buf); + iBuffers.AppendL(buf); + CleanupStack::Pop(buf); + } + + TInt COmxBufferManager::EmptyThisBuffer(const CMMFBuffer* aBuffer, + MOmxILComponentIfObserver* aObserver) + { + if (CMMFBuffer::IsSupportedDataBuffer(aBuffer->Type())) + { + COmxBuffer* omxBuffer = FindBuffer(aBuffer); + if (!omxBuffer) + { + return KErrNotFound; + } + + omxBuffer->SetPortObserver(aObserver); + OMX_BUFFERHEADERTYPE* bufferHeader = omxBuffer->BufferHeader(); + const CMMFDataBuffer* buf = static_cast(aBuffer); + const TDesC8& des = buf->Data(); + bufferHeader->nFilledLen = des.Length(); + bufferHeader->nFlags = 0; + if (aBuffer->LastBuffer()) + { + bufferHeader->nFlags |= OMX_BUFFERFLAG_EOS; + } + else + { + bufferHeader->nFlags &= ~OMX_BUFFERFLAG_EOS; + } + return ConvertOmxErrorType(iHandle->EmptyThisBuffer(static_cast(iHandle), bufferHeader)); + } + else + { + return KErrNotSupported; + } + } + + + TInt COmxBufferManager::FillThisBuffer(CMMFBuffer* aBuffer, + MOmxILComponentIfObserver* aObserver) + { + if (CMMFBuffer::IsSupportedDataBuffer(aBuffer->Type())) + { + COmxBuffer* omxBuffer = FindBuffer(aBuffer); + if (!omxBuffer) + { + return KErrNotFound; + } + omxBuffer->SetPortObserver(aObserver); + OMX_BUFFERHEADERTYPE* bufferHeader = omxBuffer->BufferHeader(); + + bufferHeader->nFilledLen = 0; + // clear last buffer flag + bufferHeader->nFlags &= ~OMX_BUFFERFLAG_EOS; + return ConvertOmxErrorType(iHandle->FillThisBuffer(static_cast(iHandle), bufferHeader)); + } + else + { + return KErrNotSupported; + } + } + + + +COmxBufferManager::~COmxBufferManager() + { + for (TInt i=0;iFreeBuffer(static_cast(iHandle), 0, omxBuffer->BufferHeader()); + delete omxBuffer; + } + iBuffers.Close(); + } + + +COmxCallbacks* COmxCallbacks::NewL(MOmxILComponentIfObserver& aObserver) + { + COmxCallbacks* self = new (ELeave) COmxCallbacks(aObserver); + CleanupStack::PushL(self); + self->ConstructL(); + CleanupStack::Pop(self); + return self; + } + + +void COmxCallbacks::ConstructL() + { + OMX_CALLBACKTYPE h = + { + &::EventHandler, + &::EmptyBufferDone, + &::FillBufferDone + }; + + iHandle = h; + CActiveScheduler::Add(this); + + User::LeaveIfError(iMsgQueue.CreateLocal(KMaxMsgQueueEntries)); + iMsgQueue.NotifyDataAvailable(iStatus); + SetActive(); + } + +COmxCallbacks::COmxCallbacks(MOmxILComponentIfObserver& aObserver) + : CActive(EPriorityStandard), + iParent(aObserver) + { + } + + +COmxCallbacks::operator OMX_CALLBACKTYPE*() + { + return &iHandle; + } + + +void COmxCallbacks::RunL() + { + TOmxMessage msg; + + while (iMsgQueue.Receive(msg)==KErrNone) + { + switch (msg.iType) + { + case EEmptyBufferCallback: + { + MOmxILComponentIfObserver* callback = msg.iBuffer->PortObserver(); + const CMMFBuffer* buffer = msg.iBuffer->MmfBuffer(); + OMX_BUFFERHEADERTYPE* bufferHeader = msg.iBuffer->BufferHeader(); + TInt portIndex = static_cast(bufferHeader->nInputPortIndex); + User::LeaveIfError(callback->EmptyBufferDone(buffer, portIndex)); + break; + } + + case EFillBufferCallback: + { + CMMFBuffer* mmfBuffer = msg.iBuffer->MmfBuffer(); + OMX_BUFFERHEADERTYPE* bufferHeader = msg.iBuffer->BufferHeader(); + + if (CMMFBuffer::IsSupportedDataBuffer(mmfBuffer->Type())) + { + CMMFDataBuffer* dataBuffer = static_cast(mmfBuffer); + TDes8& aBufferDes = dataBuffer->Data(); + aBufferDes.SetLength(bufferHeader->nFilledLen); + mmfBuffer->SetLastBuffer(bufferHeader->nFlags & OMX_BUFFERFLAG_EOS); + } + else + { + ASSERT(EFalse); + } + MOmxILComponentIfObserver* callback = msg.iBuffer->PortObserver(); + bufferHeader = msg.iBuffer->BufferHeader(); + TInt portIndex = static_cast(bufferHeader->nOutputPortIndex); + User::LeaveIfError(callback->FillBufferDone(mmfBuffer, portIndex)); + break; + } + case EEventCallback: + { + TInt err = KErrNone; + err = iParent.EventHandler(msg.iEventParams.iEvent, + msg.iEventParams.iData1, + msg.iEventParams.iData2, + msg.iEventParams.iExtraData); + if (err != KErrNone) + { + // Very possible the event is not supported by the IL Client. + // Ignore for now + // ASSERT(EFalse); // Uncomment this line if interested in catching this case on debug mode. + } + break; + } + default: + { + // This is an invalid state + ASSERT(EFalse); + } + }; + } + + // setup for next callbacks + iStatus = KRequestPending; + iMsgQueue.NotifyDataAvailable(iStatus); + SetActive(); + } + +COmxCallbacks::~COmxCallbacks() + { + Cancel(); + iMsgQueue.Close(); + } + + +void COmxCallbacks::DoCancel() + { + if (iMsgQueue.Handle()!=NULL) + { + iMsgQueue.CancelDataAvailable(); + } + } + + +TInt COmxCallbacks::FillBufferDone(OMX_HANDLETYPE aComponent, + COmxBufferManager::COmxBuffer* aBuffer) + { + TOmxMessage message; + message.iType = EFillBufferCallback; + message.iComponent = aComponent; + message.iBuffer = aBuffer; + return iMsgQueue.Send(message); + } + +TInt COmxCallbacks::EmptyBufferDone(OMX_HANDLETYPE aComponent, + COmxBufferManager::COmxBuffer* aBuffer) + { + TOmxMessage message; + message.iType = EEmptyBufferCallback; + message.iComponent = aComponent; + message.iBuffer = aBuffer; + return iMsgQueue.Send(message); + } + +TInt COmxCallbacks::EventHandler(OMX_HANDLETYPE aComponent, + const TEventParams& aEventParams) + { + TOmxMessage message; + message.iType = EEventCallback; + message.iComponent = aComponent; + message.iEventParams = aEventParams; + return iMsgQueue.Send(message); + } + + + +OMX_ERRORTYPE EventHandler(OMX_OUT OMX_HANDLETYPE aComponent, + OMX_OUT TAny* aAppData, + OMX_OUT OMX_EVENTTYPE aEvent, + OMX_OUT TUint32 aData1, + OMX_OUT TUint32 aData2, + OMX_OUT TAny* aExtra) + { + COmxCallbacks::TEventParams eventParams; + eventParams.iEvent = aEvent; + eventParams.iData1 = aData1; + eventParams.iData2 = aData2; + eventParams.iExtraData = aExtra; + TInt error = static_cast(aAppData)->EventHandler(aComponent, eventParams); + return ConvertSymbianErrorType(error); + } + +OMX_ERRORTYPE EmptyBufferDone(OMX_HANDLETYPE aComponent, + TAny* aAppData, + OMX_BUFFERHEADERTYPE* aBuffer) + { + COmxBufferManager::COmxBuffer* buffer = static_cast(aBuffer->pAppPrivate); + TInt error = static_cast(aAppData)->EmptyBufferDone(aComponent, buffer); + return ConvertSymbianErrorType(error); + } + +OMX_ERRORTYPE FillBufferDone(OMX_HANDLETYPE aComponent, + TAny* aAppData, + OMX_BUFFERHEADERTYPE* aBuffer) + { + COmxBufferManager::COmxBuffer* buffer = static_cast(aBuffer->pAppPrivate); + TInt error = static_cast(aAppData)->FillBufferDone(aComponent, buffer); + return ConvertSymbianErrorType(error); + } +