1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/mm/mmswadaptation/videorenderer/src/buffermanager.cpp Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,275 @@
1.4 +// Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
1.5 +// All rights reserved.
1.6 +// This component and the accompanying materials are made available
1.7 +// under the terms of "Eclipse Public License v1.0"
1.8 +// which accompanies this distribution, and is available
1.9 +// at the URL "http://www.eclipse.org/legal/epl-v10.html".
1.10 +//
1.11 +// Initial Contributors:
1.12 +// Nokia Corporation - initial contribution.
1.13 +//
1.14 +// Contributors:
1.15 +//
1.16 +// Description:
1.17 +//
1.18 +
1.19 +/**
1.20 + @file
1.21 + @internalComponent
1.22 +*/
1.23 +
1.24 +#include <mmf/devvideo/devvideobase.h>
1.25 +#include "buffermanager.h"
1.26 +#include "videoframebuffer.h"
1.27 +#include "rendererutil.h"
1.28 +
1.29 +/** Constructor for performing 1st stage construction */
1.30 +CRendererBufferManager::CRendererBufferManager(const RChunk& aChunk, TBool aTimed)
1.31 +: iChunk(aChunk),
1.32 + iTimed(aTimed),
1.33 + iAvailBuffers(TVideoFrameBuffer::iOffset),
1.34 + iWaitingBuffers(TVideoFrameBuffer::iOffset),
1.35 + iWaitingBuffersIter(iWaitingBuffers)
1.36 + {}
1.37 +
1.38 +/** Destructor. */
1.39 +CRendererBufferManager::~CRendererBufferManager()
1.40 + {
1.41 + if (iTimed)
1.42 + {
1.43 + iMutex.Close();
1.44 + }
1.45 + iAvailBuffers.Reset();
1.46 + iWaitingBuffers.Reset();
1.47 + iBuffers.ResetAndDestroy();
1.48 + iChunk.Close();
1.49 + }
1.50 +
1.51 +/** Two-phased constructor. */
1.52 +CRendererBufferManager* CRendererBufferManager::NewL(const RSurfaceManager::TSurfaceInfoV01& aSurfaceInfo, const RArray<TInt>& aBufferOffsets, const RChunk& aChunk, TBool aTimed)
1.53 + {
1.54 + CRendererBufferManager* self = new (ELeave) CRendererBufferManager(aChunk, aTimed);
1.55 + CleanupStack::PushL(self);
1.56 + self->ConstructL(aSurfaceInfo, aBufferOffsets);
1.57 + CleanupStack::Pop(); // self;
1.58 + return self;
1.59 + }
1.60 +
1.61 +/** Constructor for performing 2nd stage construction */
1.62 +void CRendererBufferManager::ConstructL(const RSurfaceManager::TSurfaceInfoV01& aSurfaceInfo, const RArray<TInt>& aBufferOffsets)
1.63 + {
1.64 + if (iTimed)
1.65 + {
1.66 + User::LeaveIfError(iMutex.CreateLocal());
1.67 + }
1.68 +
1.69 + TUncompressedVideoFormat format = VideoRendererUtil::ConvertUidPixelFormatToUncompressedVideoFormatL(aSurfaceInfo.iPixelFormat);
1.70 +
1.71 + TVideoFrameBuffer* buffer = NULL;
1.72 + for (TInt i = 0; i < aSurfaceInfo.iBuffers; ++i)
1.73 + {
1.74 + buffer = new (ELeave) TVideoFrameBuffer(format, aSurfaceInfo.iStride, i, iChunk, aBufferOffsets[i]);
1.75 + buffer->SetBufferStatus(TVideoFrameBuffer::EAvailable);
1.76 + CleanupStack::PushL(buffer);
1.77 + iBuffers.AppendL(buffer);
1.78 + CleanupStack::Pop(buffer);
1.79 +
1.80 + iAvailBuffers.AddLast(*buffer);
1.81 + }
1.82 + }
1.83 +
1.84 +/** Lock buffer table on timed mode */
1.85 +void CRendererBufferManager::Lock()
1.86 + {
1.87 + if (iTimed)
1.88 + {
1.89 + iMutex.Wait();
1.90 + }
1.91 + }
1.92 +
1.93 +/** Unlock buffer table on timed mode */
1.94 +void CRendererBufferManager::Unlock()
1.95 + {
1.96 + if (iTimed)
1.97 + {
1.98 + iMutex.Signal();
1.99 + }
1.100 + }
1.101 +
1.102 +/** Get the next available buffer */
1.103 +TVideoFrameBuffer* CRendererBufferManager::NextBuffer()
1.104 + {
1.105 + Lock();
1.106 +
1.107 + TVideoFrameBuffer* buffer = NULL;
1.108 + if (!iAvailBuffers.IsEmpty())
1.109 + {
1.110 + buffer = iAvailBuffers.First();
1.111 +
1.112 + __ASSERT_DEBUG(buffer->BufferStatus() == TVideoFrameBuffer::EAvailable,
1.113 + User::Panic(_L("CRBM::NextBuffer"), KErrCorrupt));
1.114 + buffer->SetBufferStatus(TVideoFrameBuffer::EUsedByClient);
1.115 + buffer->DblQueLink().Deque();
1.116 + }
1.117 +
1.118 + Unlock();
1.119 + return buffer;
1.120 + }
1.121 +
1.122 +/** Check if a buffer was previously sent to client */
1.123 +TBool CRendererBufferManager::BufferUsedByClient(TVideoFrameBuffer* aBuffer)
1.124 + {
1.125 + TVideoFrameBuffer* buffer = iBuffers[aBuffer->BufferId()];
1.126 + if (buffer->BufferStatus() == TVideoFrameBuffer::EUsedByClient && aBuffer == buffer)
1.127 + {
1.128 + return ETrue;
1.129 + }
1.130 + return EFalse;
1.131 + }
1.132 +
1.133 +/** Release the buffer for reuse */
1.134 +TBool CRendererBufferManager::ReleaseBuffer(TVideoFrameBuffer* aBuffer)
1.135 + {
1.136 + TBool released = EFalse;
1.137 + Lock();
1.138 +
1.139 + if (BufferUsedByClient(aBuffer))
1.140 + {
1.141 + // release the buffer if it was previously sent to client
1.142 + aBuffer->SetBufferStatus(TVideoFrameBuffer::EAvailable);
1.143 + iAvailBuffers.AddLast(*aBuffer);
1.144 + released = ETrue;
1.145 + }
1.146 +
1.147 + Unlock();
1.148 + return released;
1.149 + }
1.150 +
1.151 +/** Received notification that buffer become available */
1.152 +void CRendererBufferManager::BufferAvailable(TInt aBufferId)
1.153 + {
1.154 + Lock();
1.155 +
1.156 + TVideoFrameBuffer* buffer = iBuffers[aBufferId];
1.157 +
1.158 + __ASSERT_DEBUG(buffer->BufferStatus() == TVideoFrameBuffer::EWaiting || buffer->BufferStatus() == TVideoFrameBuffer::ESubmitted,
1.159 + User::Panic(_L("CRBM::BufferAvailable"), KErrCorrupt));
1.160 +
1.161 + buffer->SetBufferStatus(TVideoFrameBuffer::EAvailable);
1.162 + buffer->DblQueLink().Deque();
1.163 + iAvailBuffers.AddLast(*buffer);
1.164 +
1.165 + Unlock();
1.166 + }
1.167 +
1.168 +/** Get the next waiting buffer to submit
1.169 + @param aRemoveFromList If true, mark the buffer as submitted and deque from waiting list
1.170 + @param aIsLast ETrue on result if the returned buffer is the last buffer in waiting list
1.171 + */
1.172 +TVideoFrameBuffer* CRendererBufferManager::WaitingBuffer(TBool aRemoveFromList, TBool& aIsLast)
1.173 + {
1.174 + Lock();
1.175 +
1.176 + TVideoFrameBuffer* buf = NULL;
1.177 + if (iWaitingBuffers.IsEmpty() == EFalse)
1.178 + {
1.179 + buf = iWaitingBuffers.First();
1.180 +
1.181 + __ASSERT_DEBUG(buf->BufferStatus() == TVideoFrameBuffer::EWaiting,
1.182 + User::Panic(_L("CRBM::WaitingBuffer"), KErrCorrupt));
1.183 + aIsLast = iWaitingBuffers.IsLast(buf);
1.184 +
1.185 + if (aRemoveFromList)
1.186 + {
1.187 + buf->SetBufferStatus(TVideoFrameBuffer::ESubmitted);
1.188 + buf->DblQueLink().Deque();
1.189 + }
1.190 + }
1.191 +
1.192 + Unlock();
1.193 + return buf;
1.194 + }
1.195 +
1.196 +/** Mark the buffer as submitted and deque from waiting list */
1.197 +void CRendererBufferManager::BufferSubmitted(TVideoFrameBuffer* aBuffer)
1.198 + {
1.199 + Lock();
1.200 +
1.201 + __ASSERT_DEBUG(aBuffer->BufferStatus() == TVideoFrameBuffer::EWaiting,
1.202 + User::Panic(_L("CRBM::BufferSubmitted"), KErrArgument));
1.203 +
1.204 + aBuffer->SetBufferStatus(TVideoFrameBuffer::ESubmitted);
1.205 + aBuffer->DblQueLink().Deque();
1.206 +
1.207 + Unlock();
1.208 + }
1.209 +
1.210 +/** Return ETrue if the waiting list is empty */
1.211 +TBool CRendererBufferManager::WaitingListIsEmpty()
1.212 + {
1.213 + Lock();
1.214 +
1.215 + TBool ret = iWaitingBuffers.IsEmpty();
1.216 +
1.217 + Unlock();
1.218 + return ret;
1.219 + }
1.220 +
1.221 +/**
1.222 +Mark a buffer as waiting for update and add to waiting list, return ETrue
1.223 +if rescheduled is needed (i.e. head of waiting list has changed and the list wasn't empty) */
1.224 +TBool CRendererBufferManager::UpdateBuffer(TVideoFrameBuffer* aBuffer, const TTime& aTime)
1.225 + {
1.226 + Lock();
1.227 +
1.228 + TBool headChanged = EFalse;
1.229 + if (BufferUsedByClient(aBuffer))
1.230 + {
1.231 + aBuffer->SetBufferStatus(TVideoFrameBuffer::EWaiting);
1.232 + aBuffer->SetPresentationTime(aTime);
1.233 +
1.234 + // add buffer to waiting buffer list according to presentation time
1.235 + if (iWaitingBuffers.IsEmpty())
1.236 + {
1.237 + iWaitingBuffers.AddLast(*aBuffer);
1.238 + }
1.239 + else
1.240 + {
1.241 + TVideoFrameBuffer* buf = iWaitingBuffers.Last();
1.242 + if (aTime >= buf->PresentationTime())
1.243 + {
1.244 + iWaitingBuffers.AddLast(*aBuffer);
1.245 + }
1.246 + else
1.247 + {
1.248 + // client tried to insert a older frame, search for the right position to insert
1.249 + iWaitingBuffersIter.SetToFirst();
1.250 + while ((buf = iWaitingBuffersIter++) != NULL)
1.251 + {
1.252 + if (aTime < buf->PresentationTime())
1.253 + {
1.254 + // Found the slot
1.255 + if (iWaitingBuffers.IsFirst(buf))
1.256 + {
1.257 + iWaitingBuffers.AddFirst(*aBuffer);
1.258 + headChanged = ETrue;
1.259 + }
1.260 + else
1.261 + {
1.262 + aBuffer->DblQueLink().AddBefore(&(buf->DblQueLink()));
1.263 + }
1.264 + }
1.265 + }
1.266 + }
1.267 + }
1.268 + }
1.269 + else
1.270 + {
1.271 + DEBUGPRINT1(_L("CRendererBufferManager::UpdateBuffer receive buffer not usable by client"));
1.272 + __ASSERT_DEBUG(EFalse, User::Panic(_L("CRBM::UpdateBuf"), KErrBadHandle));
1.273 + }
1.274 +
1.275 + Unlock();
1.276 +
1.277 + return headChanged;
1.278 + }