--- /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 <e32base.h>
+#include <e32msgqueue.h>
+#include <mmf/server/mmfdatabuffer.h>
+
+
+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;i<iBuffers.Count() && !buffer;i++)
+ {
+ if (iBuffers[i]->MmfBuffer() == aBuffer)
+ {
+ buffer = iBuffers[i];
+ }
+ }
+ return buffer;
+ }
+
+COmxBufferManager::COmxBuffer* COmxBufferManager::FindBuffer(OMX_BUFFERHEADERTYPE* aBuffer) const
+ {
+ return reinterpret_cast<COmxBuffer*>(aBuffer->pAppPrivate);
+ }
+
+ TInt COmxBufferManager::UseBuffer(CMMFBuffer& aBuffer, TUint aPortIndex)
+ {
+ if (CMMFBuffer::IsSupportedDataBuffer(aBuffer.Type()))
+ {
+ OMX_BUFFERHEADERTYPE* buffer;
+ CMMFDataBuffer& dataBuffer = static_cast<CMMFDataBuffer&>(aBuffer);
+
+ TDes8& aBufferDes = dataBuffer.Data();
+ OMX_ERRORTYPE error = iHandle->UseBuffer(static_cast<OMX_HANDLETYPE>(iHandle), &buffer, aPortIndex, (void*)&aBuffer, aBufferDes.MaxLength(), const_cast<TUint8*>(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<OMX_HANDLETYPE>(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;i<iBuffers.Count();i++)
+ {
+ buffer = iBuffers[i];
+ if (buffer->MmfBuffer() == aBuffer)
+ {
+ iBuffers.Remove(i);
+ OMX_ERRORTYPE err = iHandle->FreeBuffer(static_cast<OMX_HANDLETYPE>(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<const CMMFDataBuffer*>(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<OMX_HANDLETYPE>(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<OMX_HANDLETYPE>(iHandle), bufferHeader));
+ }
+ else
+ {
+ return KErrNotSupported;
+ }
+ }
+
+
+
+COmxBufferManager::~COmxBufferManager()
+ {
+ for (TInt i=0;i<iBuffers.Count();i++)
+ {
+ COmxBuffer* omxBuffer = iBuffers[i];
+ iHandle->FreeBuffer(static_cast<OMX_HANDLETYPE>(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<TInt>(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<CMMFDataBuffer*>(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<TInt>(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<COmxCallbacks*>(aAppData)->EventHandler(aComponent, eventParams);
+ return ConvertSymbianErrorType(error);
+ }
+
+OMX_ERRORTYPE EmptyBufferDone(OMX_HANDLETYPE aComponent,
+ TAny* aAppData,
+ OMX_BUFFERHEADERTYPE* aBuffer)
+ {
+ COmxBufferManager::COmxBuffer* buffer = static_cast<COmxBufferManager::COmxBuffer*>(aBuffer->pAppPrivate);
+ TInt error = static_cast<COmxCallbacks*>(aAppData)->EmptyBufferDone(aComponent, buffer);
+ return ConvertSymbianErrorType(error);
+ }
+
+OMX_ERRORTYPE FillBufferDone(OMX_HANDLETYPE aComponent,
+ TAny* aAppData,
+ OMX_BUFFERHEADERTYPE* aBuffer)
+ {
+ COmxBufferManager::COmxBuffer* buffer = static_cast<COmxBufferManager::COmxBuffer*>(aBuffer->pAppPrivate);
+ TInt error = static_cast<COmxCallbacks*>(aAppData)->FillBufferDone(aComponent, buffer);
+ return ConvertSymbianErrorType(error);
+ }
+