omxil/mmilapi/refomxil/src/omxilgenericilif/omxilgenericilifbodyimpl.cpp
changeset 0 40261b775718
child 16 eedf2dcd43c6
--- /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);
+	}
+