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".
8 // Initial Contributors:
9 // Nokia Corporation - initial contribution.
21 #include <mmf/devvideo/devvideobase.h>
22 #include "buffermanager.h"
23 #include "videoframebuffer.h"
24 #include "rendererutil.h"
26 /** Constructor for performing 1st stage construction */
27 CRendererBufferManager::CRendererBufferManager(const RChunk& aChunk, TBool aTimed)
30 iAvailBuffers(TVideoFrameBuffer::iOffset),
31 iWaitingBuffers(TVideoFrameBuffer::iOffset),
32 iWaitingBuffersIter(iWaitingBuffers)
36 CRendererBufferManager::~CRendererBufferManager()
42 iAvailBuffers.Reset();
43 iWaitingBuffers.Reset();
44 iBuffers.ResetAndDestroy();
48 /** Two-phased constructor. */
49 CRendererBufferManager* CRendererBufferManager::NewL(const RSurfaceManager::TSurfaceInfoV01& aSurfaceInfo, const RArray<TInt>& aBufferOffsets, const RChunk& aChunk, TBool aTimed)
51 CRendererBufferManager* self = new (ELeave) CRendererBufferManager(aChunk, aTimed);
52 CleanupStack::PushL(self);
53 self->ConstructL(aSurfaceInfo, aBufferOffsets);
54 CleanupStack::Pop(); // self;
58 /** Constructor for performing 2nd stage construction */
59 void CRendererBufferManager::ConstructL(const RSurfaceManager::TSurfaceInfoV01& aSurfaceInfo, const RArray<TInt>& aBufferOffsets)
63 User::LeaveIfError(iMutex.CreateLocal());
66 TUncompressedVideoFormat format = VideoRendererUtil::ConvertUidPixelFormatToUncompressedVideoFormatL(aSurfaceInfo.iPixelFormat);
68 TVideoFrameBuffer* buffer = NULL;
69 for (TInt i = 0; i < aSurfaceInfo.iBuffers; ++i)
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);
77 iAvailBuffers.AddLast(*buffer);
81 /** Lock buffer table on timed mode */
82 void CRendererBufferManager::Lock()
90 /** Unlock buffer table on timed mode */
91 void CRendererBufferManager::Unlock()
99 /** Get the next available buffer */
100 TVideoFrameBuffer* CRendererBufferManager::NextBuffer()
104 TVideoFrameBuffer* buffer = NULL;
105 if (!iAvailBuffers.IsEmpty())
107 buffer = iAvailBuffers.First();
109 __ASSERT_DEBUG(buffer->BufferStatus() == TVideoFrameBuffer::EAvailable,
110 User::Panic(_L("CRBM::NextBuffer"), KErrCorrupt));
111 buffer->SetBufferStatus(TVideoFrameBuffer::EUsedByClient);
112 buffer->DblQueLink().Deque();
119 /** Check if a buffer was previously sent to client */
120 TBool CRendererBufferManager::BufferUsedByClient(TVideoFrameBuffer* aBuffer)
122 TVideoFrameBuffer* buffer = iBuffers[aBuffer->BufferId()];
123 if (buffer->BufferStatus() == TVideoFrameBuffer::EUsedByClient && aBuffer == buffer)
130 /** Release the buffer for reuse */
131 TBool CRendererBufferManager::ReleaseBuffer(TVideoFrameBuffer* aBuffer)
133 TBool released = EFalse;
136 if (BufferUsedByClient(aBuffer))
138 // release the buffer if it was previously sent to client
139 aBuffer->SetBufferStatus(TVideoFrameBuffer::EAvailable);
140 iAvailBuffers.AddLast(*aBuffer);
148 /** Received notification that buffer become available */
149 void CRendererBufferManager::BufferAvailable(TInt aBufferId)
153 TVideoFrameBuffer* buffer = iBuffers[aBufferId];
155 __ASSERT_DEBUG(buffer->BufferStatus() == TVideoFrameBuffer::EWaiting || buffer->BufferStatus() == TVideoFrameBuffer::ESubmitted,
156 User::Panic(_L("CRBM::BufferAvailable"), KErrCorrupt));
158 buffer->SetBufferStatus(TVideoFrameBuffer::EAvailable);
159 buffer->DblQueLink().Deque();
160 iAvailBuffers.AddLast(*buffer);
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
169 TVideoFrameBuffer* CRendererBufferManager::WaitingBuffer(TBool aRemoveFromList, TBool& aIsLast)
173 TVideoFrameBuffer* buf = NULL;
174 if (iWaitingBuffers.IsEmpty() == EFalse)
176 buf = iWaitingBuffers.First();
178 __ASSERT_DEBUG(buf->BufferStatus() == TVideoFrameBuffer::EWaiting,
179 User::Panic(_L("CRBM::WaitingBuffer"), KErrCorrupt));
180 aIsLast = iWaitingBuffers.IsLast(buf);
184 buf->SetBufferStatus(TVideoFrameBuffer::ESubmitted);
185 buf->DblQueLink().Deque();
193 /** Mark the buffer as submitted and deque from waiting list */
194 void CRendererBufferManager::BufferSubmitted(TVideoFrameBuffer* aBuffer)
198 __ASSERT_DEBUG(aBuffer->BufferStatus() == TVideoFrameBuffer::EWaiting,
199 User::Panic(_L("CRBM::BufferSubmitted"), KErrArgument));
201 aBuffer->SetBufferStatus(TVideoFrameBuffer::ESubmitted);
202 aBuffer->DblQueLink().Deque();
207 /** Return ETrue if the waiting list is empty */
208 TBool CRendererBufferManager::WaitingListIsEmpty()
212 TBool ret = iWaitingBuffers.IsEmpty();
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)
225 TBool headChanged = EFalse;
226 if (BufferUsedByClient(aBuffer))
228 aBuffer->SetBufferStatus(TVideoFrameBuffer::EWaiting);
229 aBuffer->SetPresentationTime(aTime);
231 // add buffer to waiting buffer list according to presentation time
232 if (iWaitingBuffers.IsEmpty())
234 iWaitingBuffers.AddLast(*aBuffer);
238 TVideoFrameBuffer* buf = iWaitingBuffers.Last();
239 if (aTime >= buf->PresentationTime())
241 iWaitingBuffers.AddLast(*aBuffer);
245 // client tried to insert a older frame, search for the right position to insert
246 iWaitingBuffersIter.SetToFirst();
247 while ((buf = iWaitingBuffersIter++) != NULL)
249 if (aTime < buf->PresentationTime())
252 if (iWaitingBuffers.IsFirst(buf))
254 iWaitingBuffers.AddFirst(*aBuffer);
259 aBuffer->DblQueLink().AddBefore(&(buf->DblQueLink()));
268 DEBUGPRINT1(_L("CRendererBufferManager::UpdateBuffer receive buffer not usable by client"));
269 __ASSERT_DEBUG(EFalse, User::Panic(_L("CRBM::UpdateBuf"), KErrBadHandle));