os/mm/mmswadaptation/videorenderer/src/buffermanager.cpp
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200
changeset 0 bde4ae8d615e
permissions -rw-r--r--
First public contribution.
     1 // Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
     2 // All rights reserved.
     3 // This component and the accompanying materials are made available
     4 // under the terms of "Eclipse Public License v1.0"
     5 // which accompanies this distribution, and is available
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
     7 //
     8 // Initial Contributors:
     9 // Nokia Corporation - initial contribution.
    10 //
    11 // Contributors:
    12 //
    13 // Description:
    14 //
    15 
    16 /**
    17  @file
    18  @internalComponent
    19 */
    20 
    21 #include <mmf/devvideo/devvideobase.h>
    22 #include "buffermanager.h"
    23 #include "videoframebuffer.h"
    24 #include "rendererutil.h"
    25 
    26 /** Constructor for performing 1st stage construction */
    27 CRendererBufferManager::CRendererBufferManager(const RChunk& aChunk, TBool aTimed)
    28 : iChunk(aChunk),
    29   iTimed(aTimed),
    30   iAvailBuffers(TVideoFrameBuffer::iOffset), 
    31   iWaitingBuffers(TVideoFrameBuffer::iOffset), 
    32   iWaitingBuffersIter(iWaitingBuffers)
    33 	{}
    34 
    35 /** Destructor.	*/
    36 CRendererBufferManager::~CRendererBufferManager()
    37 	{
    38 	if (iTimed)
    39 		{
    40 		iMutex.Close();
    41 		}
    42 	iAvailBuffers.Reset();
    43 	iWaitingBuffers.Reset();
    44 	iBuffers.ResetAndDestroy();
    45 	iChunk.Close();
    46 	}
    47 
    48 /** Two-phased constructor. */
    49 CRendererBufferManager* CRendererBufferManager::NewL(const RSurfaceManager::TSurfaceInfoV01& aSurfaceInfo, const RArray<TInt>& aBufferOffsets, const RChunk& aChunk, TBool aTimed)
    50 	{
    51 	CRendererBufferManager* self = new (ELeave) CRendererBufferManager(aChunk, aTimed);
    52 	CleanupStack::PushL(self);
    53 	self->ConstructL(aSurfaceInfo, aBufferOffsets);
    54 	CleanupStack::Pop(); // self;
    55 	return self;
    56 	}
    57 
    58 /** Constructor for performing 2nd stage construction */
    59 void CRendererBufferManager::ConstructL(const RSurfaceManager::TSurfaceInfoV01& aSurfaceInfo, const RArray<TInt>& aBufferOffsets)
    60 	{
    61 	if (iTimed)
    62 		{
    63 		User::LeaveIfError(iMutex.CreateLocal());
    64 		}
    65 	
    66 	TUncompressedVideoFormat format = VideoRendererUtil::ConvertUidPixelFormatToUncompressedVideoFormatL(aSurfaceInfo.iPixelFormat);
    67 	
    68 	TVideoFrameBuffer* buffer = NULL;
    69 	for (TInt i = 0; i < aSurfaceInfo.iBuffers; ++i)
    70 		{
    71 		buffer = new (ELeave) TVideoFrameBuffer(format, aSurfaceInfo.iStride, i, iChunk, aBufferOffsets[i]);
    72 		buffer->SetBufferStatus(TVideoFrameBuffer::EAvailable);
    73 		CleanupStack::PushL(buffer);
    74 		iBuffers.AppendL(buffer);
    75 		CleanupStack::Pop(buffer);
    76 		
    77 		iAvailBuffers.AddLast(*buffer);
    78 		}
    79 	}
    80 
    81 /** Lock buffer table on timed mode */
    82 void CRendererBufferManager::Lock()
    83 	{
    84 	if (iTimed)
    85 		{
    86 		iMutex.Wait();
    87 		}
    88 	}
    89 
    90 /** Unlock buffer table on timed mode */
    91 void CRendererBufferManager::Unlock()
    92 	{
    93 	if (iTimed)
    94 		{
    95 		iMutex.Signal();
    96 		}
    97 	}
    98 
    99 /** Get the next available buffer */
   100 TVideoFrameBuffer* CRendererBufferManager::NextBuffer()
   101 	{
   102 	Lock();
   103 	
   104 	TVideoFrameBuffer* buffer = NULL;
   105 	if (!iAvailBuffers.IsEmpty())
   106 		{
   107 		buffer = iAvailBuffers.First();
   108 		
   109 		__ASSERT_DEBUG(buffer->BufferStatus() == TVideoFrameBuffer::EAvailable,
   110 				User::Panic(_L("CRBM::NextBuffer"), KErrCorrupt));
   111 		buffer->SetBufferStatus(TVideoFrameBuffer::EUsedByClient);
   112 		buffer->DblQueLink().Deque();
   113 		}
   114 
   115 	Unlock();
   116 	return buffer;
   117 	}
   118 
   119 /** Check if a buffer was previously sent to client */
   120 TBool CRendererBufferManager::BufferUsedByClient(TVideoFrameBuffer* aBuffer)
   121 	{
   122 	TVideoFrameBuffer* buffer = iBuffers[aBuffer->BufferId()];
   123 	if (buffer->BufferStatus() == TVideoFrameBuffer::EUsedByClient && aBuffer == buffer)
   124 		{
   125 		return ETrue;
   126 		}
   127 	return EFalse;
   128 	}
   129 
   130 /** Release the buffer for reuse */
   131 TBool CRendererBufferManager::ReleaseBuffer(TVideoFrameBuffer* aBuffer)
   132 	{
   133 	TBool released = EFalse;
   134 	Lock();
   135 	
   136 	if (BufferUsedByClient(aBuffer))
   137 		{
   138 		// release the buffer if it was previously sent to client
   139 		aBuffer->SetBufferStatus(TVideoFrameBuffer::EAvailable);
   140 		iAvailBuffers.AddLast(*aBuffer);		
   141 		released = ETrue;
   142 		}
   143 
   144 	Unlock();
   145 	return released;
   146 	}
   147 
   148 /** Received notification that buffer become available */
   149 void CRendererBufferManager::BufferAvailable(TInt aBufferId)
   150 	{
   151 	Lock();
   152 
   153 	TVideoFrameBuffer* buffer = iBuffers[aBufferId];
   154 
   155 	__ASSERT_DEBUG(buffer->BufferStatus() == TVideoFrameBuffer::EWaiting || buffer->BufferStatus() == TVideoFrameBuffer::ESubmitted,
   156 			User::Panic(_L("CRBM::BufferAvailable"), KErrCorrupt));
   157 
   158 	buffer->SetBufferStatus(TVideoFrameBuffer::EAvailable);
   159 	buffer->DblQueLink().Deque();
   160 	iAvailBuffers.AddLast(*buffer);
   161 	
   162 	Unlock();
   163 	}
   164 
   165 /** Get the next waiting buffer to submit
   166  @param aRemoveFromList If true, mark the buffer as submitted and deque from waiting list
   167  @param aIsLast ETrue on result if the returned buffer is the last buffer in waiting list
   168  */
   169 TVideoFrameBuffer* CRendererBufferManager::WaitingBuffer(TBool aRemoveFromList, TBool& aIsLast)
   170 	{
   171 	Lock();
   172 	
   173 	TVideoFrameBuffer* buf = NULL;
   174 	if (iWaitingBuffers.IsEmpty() == EFalse)
   175 		{
   176 		buf = iWaitingBuffers.First();
   177 
   178 		__ASSERT_DEBUG(buf->BufferStatus() == TVideoFrameBuffer::EWaiting,
   179 				User::Panic(_L("CRBM::WaitingBuffer"), KErrCorrupt));
   180 		aIsLast = iWaitingBuffers.IsLast(buf);
   181 
   182 		if (aRemoveFromList)
   183 			{
   184 			buf->SetBufferStatus(TVideoFrameBuffer::ESubmitted);
   185 			buf->DblQueLink().Deque();
   186 			}
   187 		}
   188 
   189 	Unlock();
   190 	return buf;
   191 	}
   192 
   193 /** Mark the buffer as submitted and deque from waiting list */
   194 void CRendererBufferManager::BufferSubmitted(TVideoFrameBuffer* aBuffer)
   195 	{
   196 	Lock();
   197 
   198 	__ASSERT_DEBUG(aBuffer->BufferStatus() == TVideoFrameBuffer::EWaiting,
   199 			User::Panic(_L("CRBM::BufferSubmitted"), KErrArgument));
   200 
   201 	aBuffer->SetBufferStatus(TVideoFrameBuffer::ESubmitted);
   202 	aBuffer->DblQueLink().Deque();
   203 
   204 	Unlock();
   205 	}
   206 
   207 /** Return ETrue if the waiting list is empty */
   208 TBool CRendererBufferManager::WaitingListIsEmpty()
   209 	{
   210 	Lock();
   211 	
   212 	TBool ret = iWaitingBuffers.IsEmpty();
   213 	
   214 	Unlock();
   215 	return ret;
   216 	}
   217 
   218 /** 
   219 Mark a buffer as waiting for update and add to waiting list, return ETrue 
   220 if rescheduled is needed (i.e. head of waiting list has changed and the list wasn't empty) */
   221 TBool CRendererBufferManager::UpdateBuffer(TVideoFrameBuffer* aBuffer, const TTime& aTime)
   222 	{
   223 	Lock();
   224 	
   225 	TBool headChanged = EFalse;
   226 	if (BufferUsedByClient(aBuffer))
   227 		{
   228 		aBuffer->SetBufferStatus(TVideoFrameBuffer::EWaiting);
   229 		aBuffer->SetPresentationTime(aTime);
   230 		
   231 		// add buffer to waiting buffer list according to presentation time
   232 		if (iWaitingBuffers.IsEmpty())
   233 			{
   234 			iWaitingBuffers.AddLast(*aBuffer);
   235 			}
   236 		else
   237 			{
   238 			TVideoFrameBuffer* buf = iWaitingBuffers.Last();
   239 			if (aTime >= buf->PresentationTime())
   240 				{
   241 				iWaitingBuffers.AddLast(*aBuffer);
   242 				}
   243 			else
   244 				{
   245 				// client tried to insert a older frame, search for the right position to insert
   246 				iWaitingBuffersIter.SetToFirst();
   247 				while ((buf = iWaitingBuffersIter++) != NULL)
   248 					{
   249 					if (aTime < buf->PresentationTime())
   250 						{
   251 						// Found the slot
   252 						if (iWaitingBuffers.IsFirst(buf))
   253 							{
   254 							iWaitingBuffers.AddFirst(*aBuffer);
   255 							headChanged = ETrue;
   256 							}
   257 						else
   258 							{
   259 							aBuffer->DblQueLink().AddBefore(&(buf->DblQueLink()));
   260 							}
   261 						}
   262 					}
   263 				}
   264 			}
   265 		}
   266 	else
   267 		{
   268 		DEBUGPRINT1(_L("CRendererBufferManager::UpdateBuffer receive buffer not usable by client"));
   269 		__ASSERT_DEBUG(EFalse, User::Panic(_L("CRBM::UpdateBuf"), KErrBadHandle));
   270 		}
   271 	
   272 	Unlock();
   273 	
   274 	return headChanged;
   275 	}