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