os/mm/mmdevicefw/mdf/src/video/hwdevicevideoutils/mdfvideodecoderbuffermanager.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) 2006-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 #include <fbs.h>
    17 #include <mmf/server/mmfdatabuffer.h>
    18 #include "mdfvideodecoderbuffermanager.h"
    19 
    20 #define MDFVIDEODECODERBUFFERMANAGER_DEBUG 1
    21 
    22 #if defined (SYMBIAN_MDFVIDEODECODERBUFFERMANAGER_DEBUG)
    23 #define DEBUG_PRINT( x ) ( RDebug::Print( x ) )
    24 #define DEBUG_PRINT2( x,y ) ( RDebug::Print( x,y ) )
    25 #define DEBUG_PRINT3( x,y,z ) ( RDebug::Print( x,y,z ) )
    26 
    27 #else
    28 #define DEBUG_PRINT( x )
    29 #define DEBUG_PRINT2( x,y ) 
    30 #define DEBUG_PRINT3( x,y,z ) 
    31 #endif // defined (SYMBIAN_MDFVIDEODECODERBUFFERMANAGER_DEBUG)
    32 
    33 CVideoDataBuffer::CVideoDataBuffer()
    34 	{
    35 	}
    36 	
    37 TUint CVideoDataBuffer::Length()
    38 	{
    39 	return iSize;
    40 	}
    41 
    42 CVideoDataBuffer* CVideoDataBuffer::NewL(TUint aSize)
    43 	{
    44 	CVideoDataBuffer* self = new (ELeave) CVideoDataBuffer;
    45 	CleanupStack::PushL(self);
    46 	self->ConstructL(aSize);
    47 	CleanupStack::Pop(self);
    48 	return self;
    49 	}
    50 	
    51 void CVideoDataBuffer::ConstructL(TUint aBufferSize)
    52 	{
    53 	iSize = aBufferSize;
    54 	CMMFDescriptorBuffer* buffer = CMMFDescriptorBuffer::NewL(aBufferSize);
    55 	TDes8& des = buffer->Data();
    56 	TUint8* ptr = const_cast<TUint8*>(des.Ptr());
    57 	iVideoInputBuffer.iData.Set(ptr, des.Length(), des.MaxLength());
    58 	iMmfBuffer = buffer;
    59 	}
    60 
    61 CVideoDataBuffer::operator CMMFBuffer*()
    62 	{
    63 	return iMmfBuffer;
    64 	}
    65 	
    66 CVideoDataBuffer::operator TVideoInputBuffer&()
    67 	{
    68 	return iVideoInputBuffer;
    69 	}
    70 	
    71 
    72 
    73 TBool CVideoDataBuffer::operator== (const CMMFBuffer* aBuffer) const
    74 	{
    75 	return (aBuffer == iMmfBuffer); 	
    76 	}
    77 
    78 TBool CVideoDataBuffer::operator== (const TVideoInputBuffer& aVideoInputBuffer) const
    79 	{
    80 	// compare the data pointers
    81 	return iVideoInputBuffer.iData == aVideoInputBuffer.iData;
    82 	}
    83 
    84 CVideoDataBuffer::~CVideoDataBuffer()
    85 	{
    86 	delete iMmfBuffer;
    87 	}
    88 
    89 
    90 CVideoFrameBuffer::CVideoFrameBuffer(TSize aFrameSize, 
    91 											TUncompressedVideoFormat aFormat, 
    92 											TDisplayMode aDisplayMode) 
    93 	: iRawPtr(0,0),
    94 	iFrameSize(aFrameSize),
    95 	iVideoFormat(aFormat),
    96 	iDisplayMode(aDisplayMode)
    97 	{
    98 	
    99 	}
   100 
   101 CVideoFrameBuffer* CVideoFrameBuffer::NewL(TSize aFrameSize, 
   102 													TUncompressedVideoFormat aFormat,		
   103 													TDisplayMode aDisplayMode)
   104 	{
   105 	CVideoFrameBuffer* self = new (ELeave) CVideoFrameBuffer(aFrameSize, aFormat, aDisplayMode);
   106 	CleanupStack::PushL(self);
   107 	self->ConstructL();
   108 	CleanupStack::Pop(self);
   109 	return self;
   110 	}
   111 	
   112 void CVideoFrameBuffer::SetLastBuffer(TBool aLastBuffer)
   113 	{
   114 	iLastBuffer = aLastBuffer;
   115 	}
   116 	
   117 TBool CVideoFrameBuffer::LastBuffer()
   118 	{
   119 	return iLastBuffer;
   120 	}
   121 	
   122 void CVideoFrameBuffer::ConstructL()
   123 	{
   124 	iFrameBufferSize = CFbsBitmap::ScanLineLength(iFrameSize.iWidth, iDisplayMode) *
   125 														iFrameSize.iHeight;
   126 	Mem::FillZ(&iVideoPicture, sizeof(TVideoPicture));
   127 	if(iVideoFormat.iDataFormat == ERgbFbsBitmap) 
   128 		{
   129 		iBitmap = new(ELeave)CFbsBitmap;
   130 		User::LeaveIfError(iBitmap->Create(iFrameSize, iDisplayMode));				
   131 		DEBUG_PRINT2(_L("BufferManager: Created bitmap at 0x%08x"), iBitmap);
   132 		
   133 		iVideoPicture.iData.iRgbBitmap = iBitmap;
   134 		iBitmap->LockHeap();
   135 		TRAPD(err, iMmfBuffer = CMMFPtrBuffer::NewL(TPtr8(reinterpret_cast<TUint8*>(iBitmap->DataAddress()),
   136 												iFrameBufferSize,
   137 												iFrameBufferSize)) );
   138 		iBitmap->UnlockHeap();
   139 		User::LeaveIfError(err);
   140 		}
   141 	else if((iVideoFormat.iDataFormat == ERgbRawData) || (iVideoFormat.iDataFormat == EYuvRawData))
   142 		{
   143 		iRawBuffer  = HBufC8::NewMaxL(iFrameBufferSize);
   144 		iRawPtr.Set(iRawBuffer->Des());
   145 		iMmfBuffer = CMMFPtrBuffer::NewL(iRawPtr);
   146 		iVideoPicture.iData.iRawData = &iRawPtr;
   147 		}
   148 	iVideoPicture.iData.iDataFormat = iVideoFormat.iDataFormat;
   149 	iVideoPicture.iData.iDataSize = iFrameSize;
   150 	}
   151 
   152 CVideoFrameBuffer::operator CMMFBuffer*()
   153 	{
   154 	return iMmfBuffer;
   155 	}
   156 	
   157 CVideoFrameBuffer::operator TVideoPicture&()
   158 	{
   159 	return iVideoPicture;
   160 	}
   161 
   162 CVideoFrameBuffer::operator CMMFBuffer&()
   163 	{
   164 	return *iMmfBuffer;
   165 	}
   166 	
   167 CVideoFrameBuffer::operator TVideoPicture*()
   168 	{
   169 	return &iVideoPicture;
   170 	}
   171 	
   172 void CVideoFrameBuffer::LockFrameBufferHeap()
   173 	{
   174 	iBitmap->LockHeap();
   175 	iHeapLocked = ETrue;
   176 	}
   177 
   178 void CVideoFrameBuffer::UnlockFrameBufferHeap()
   179 	{
   180 	if (iHeapLocked)
   181 		{
   182 		iBitmap->UnlockHeap();
   183 		iHeapLocked = EFalse;
   184 		}
   185 	}
   186 
   187 
   188 TBool CVideoFrameBuffer::operator== (const CMMFBuffer* aBuffer) const
   189 	{
   190 	return (aBuffer == iMmfBuffer); 	
   191 	}
   192 
   193 TBool CVideoFrameBuffer::operator== (const TVideoPicture& aVideoInputBuffer) const
   194 	{
   195 	// compare the data pointers - cheat, it is the same pointer for the bitmap and 
   196 	// raw data
   197 	return iVideoPicture.iData.iRawData == aVideoInputBuffer.iData.iRawData;
   198 	}
   199 
   200 CVideoFrameBuffer::~CVideoFrameBuffer()
   201 	{
   202 	UnlockFrameBufferHeap();
   203 	delete iMmfBuffer;
   204 	delete iBitmap;
   205 	delete iRawBuffer;
   206 	}
   207 
   208 
   209 /** 
   210  Constructs a new instance of CMDFVideoDecoderBufferManager.
   211  @return    "CMDFVideoDecoderBufferManager*"
   212             A pointer to the newly constructed CMDFVideoDecoderBufferManager
   213  */
   214 CMdfVideoDecoderBufferManager* CMdfVideoDecoderBufferManager::NewL()
   215 	{
   216 	CMdfVideoDecoderBufferManager* s = new(ELeave) CMdfVideoDecoderBufferManager;
   217 	CleanupStack::PushL(s);
   218 	s->ConstructL();
   219 	CleanupStack::Pop(s);
   220 	return (static_cast<CMdfVideoDecoderBufferManager*>(s));
   221 	}
   222 
   223 CMdfVideoDecoderBufferManager::CMdfVideoDecoderBufferManager()
   224 	{
   225 	}
   226 void CMdfVideoDecoderBufferManager::ConstructL()
   227 	{
   228 	RFbsSession::Connect();
   229 	}
   230 
   231 /**
   232  Default destructor
   233  */
   234 CMdfVideoDecoderBufferManager::~CMdfVideoDecoderBufferManager()
   235 	{
   236 	// get rid of input buffers
   237 	delete iInputBuffer;
   238 	// cleanup frame buffer arrays	
   239 	iEmptyFrameBuffers.ResetAndDestroy();
   240 	iFilledFrameBuffers.ResetAndDestroy();
   241 	iFrameBuffersInUse.ResetAndDestroy();
   242 	RFbsSession::Disconnect();
   243 	
   244 	DEBUG_PRINT(_L("BufferManager: Closing down"));
   245 	}
   246 
   247 /** 
   248  Initializes the decoder buffer manager.
   249  @param		"const TUncompressedVideoFormat& aFormat"
   250  			The image format to decode into
   251  */
   252 void CMdfVideoDecoderBufferManager::Init(const TUncompressedVideoFormat& aFormat)
   253 	{
   254 	DEBUG_PRINT(_L("BufferManager: Initializing"));
   255 
   256 	iFormat = aFormat;
   257 	// The actual frame size will come from the VOL headers.
   258 	// Set an initial value for iFrameBufferSize so we can get
   259 	// the VOL headers themselves.
   260 	// Also ensure we allow one free output buffer.
   261 	iFrameBufferSize = 1024; // 1k
   262 	iMaxFrameBuffers = 1;
   263 	
   264 	iInputBufferInUse = EFalse;
   265 	}
   266 
   267 /** 
   268  Creates a new empty input buffer.
   269  @param		"TUint aBufferSize"
   270  			The requested buffer size.
   271  @return	"TVideoInputBuffer&"
   272  			An empty input buffer.
   273  @leave		May leave with KErrInUse if no input buffer is available, or with KErrNoMemory
   274  			if a buffer cannot be created or adjusted. 			 			
   275  */
   276 CVideoDataBuffer& CMdfVideoDecoderBufferManager::CreateDataBufferL(TUint aBufferSize)
   277 	{
   278 	// We use one input buffer and one overflow buffer.
   279 
   280 	// If the app requests another buffer before this one has been processed, then leave.
   281 	if(iInputBufferInUse) 
   282 		{
   283 		User::Leave(KErrInUse);
   284 		}
   285 		
   286 	if(aBufferSize < 1)
   287 		{
   288 		User::Leave(KErrArgument);
   289 		}
   290 	
   291 	// Create or adjust the input buffer
   292 	
   293 	if(!iInputBuffer) 
   294 		{
   295 		iInputBuffer = CVideoDataBuffer::NewL(aBufferSize);
   296 		}	
   297 	else if(iInputBuffer->Length() != aBufferSize)
   298 		{
   299 		// NB don't use ReAllocL() as it will panic if the buffer is shrinking
   300 		// Use temp variable		
   301 		CVideoDataBuffer* tempBuffer = CVideoDataBuffer::NewL(aBufferSize);
   302 
   303 		// Coverity reports a leave_without_push error here because
   304 		// CVideoDataBuffer contains a frame buffer member which could contain
   305 		// a CFbsBitmap member which can panic during its destructor. The panic
   306 		// has a trapped leave and for some reason coverity does not recognise it.
   307 		// Mark as false positive
   308 		// coverity[leave_without_push : FALSE]
   309 		delete iInputBuffer;
   310 		iInputBuffer = NULL;
   311 		iInputBuffer = tempBuffer;		
   312 		}
   313 	return *iInputBuffer;	
   314 	}
   315 
   316 void CMdfVideoDecoderBufferManager::ReturnDataBufferL(TVideoInputBuffer& aInputBuffer)
   317 	{
   318 	if (!iInputBuffer)
   319 		{
   320 		User::Leave(KErrNotFound);
   321 		}	
   322 	// if this buffer isn't the input buffer, leave
   323 	if(! (*iInputBuffer == aInputBuffer) )
   324 		{
   325 		User::Leave(KErrNotFound);	
   326 		}
   327 	// if the buffer is not in use, leave
   328 	if(!iInputBufferInUse)
   329 		{
   330 		User::Leave(KErrInUse);	
   331 		}
   332 	
   333 	// finished with input buffer - mark it unused
   334 	iInputBufferInUse = EFalse;
   335 	}
   336 	
   337 CVideoDataBuffer& CMdfVideoDecoderBufferManager::GetDataBufferL()
   338 	{
   339 	if (!iInputBuffer)
   340 		{
   341 		User::Leave(KErrNotFound);
   342 		}
   343 	if (iInputBufferInUse)
   344 		{
   345 		User::Leave(KErrInUse);
   346 		}
   347 	iInputBufferInUse = ETrue;
   348 	return *iInputBuffer;
   349 	}
   350 
   351 /** 
   352  Gets the number of available input buffers.
   353  @return	"TInt"
   354  			The number of available input buffers.
   355  */
   356 TInt CMdfVideoDecoderBufferManager::DataBuffersAvailable() const
   357 	{
   358 	// this plugin has one input buffer. if it is in use (i.e. the client hasn't been
   359 	// notified with MdvppNewBuffers()) then return 0.
   360 	return ((iInputBufferInUse) ? 0 : 1);
   361 	}
   362 
   363 /** 
   364  Sets the frame size.
   365  @param		"const TSize& aSize"
   366  			The frame size.
   367  */
   368 void CMdfVideoDecoderBufferManager::SetFrameSize(const TSize& aSize)
   369 	{
   370 	iFrameSize = aSize;
   371 	}
   372 
   373 /** 
   374  Gets the frame size.
   375  @return	"const TSize&"
   376  			The frame size.
   377  */
   378 const TSize& CMdfVideoDecoderBufferManager::FrameSize() const
   379 	{
   380 	return iFrameSize;
   381 	}
   382 
   383 /** 
   384  Sets the frame buffer size.
   385  @param		"TInt aSize"
   386  			The frame buffer size.
   387  */
   388 void CMdfVideoDecoderBufferManager::SetFrameBufferSize(TInt aSize)
   389 	{
   390 	iFrameBufferSize = aSize;
   391 	}
   392 
   393 /** 
   394  Gets the frame buffer size.
   395  @return	"TInt"
   396  			The frame buffer size.
   397  */
   398 TInt CMdfVideoDecoderBufferManager::FrameBufferSize() const
   399 	{
   400 	return iFrameBufferSize;
   401 	}
   402 
   403 /** 
   404  Gets the maximum number of frame buffers.
   405  @return	"TInt"
   406  			The maximum number of frame buffers.
   407  */
   408 TInt CMdfVideoDecoderBufferManager::MaxFrameBuffers() const
   409 	{
   410 	return iMaxFrameBuffers;
   411 	}
   412 
   413 /** 
   414  Gets the number of available pictures (full output buffers).
   415  @return	"TInt"
   416  			The number of available pictures.
   417  */
   418 TInt CMdfVideoDecoderBufferManager::FilledFrameBuffersAvailable() const
   419 	{
   420 	return ((iFilledFrameBuffers.Count() > 0) ? 1 : 0);
   421 	}
   422 
   423 /** 
   424  Gets the number of available frame buffers.
   425  @return	"TInt"
   426  			The number of available frame buffers.
   427  */
   428 TInt CMdfVideoDecoderBufferManager::EmptyFrameBuffersAvailable() const
   429 	{
   430 	return ((iEmptyFrameBuffers.Count() < iMaxFrameBuffers) ? 1 : 0);
   431 	}
   432 	
   433 	
   434 /** 
   435  Gets the first available framebuffer
   436  @return	"TVideoPicture&"
   437  			A picture.
   438  @leave		May leave with KErrNotReady if no picture is available. 			
   439  */
   440 CVideoFrameBuffer& CMdfVideoDecoderBufferManager::GetEmptyFrameBufferL(TBool aLockHeap)
   441 	{
   442 	DEBUG_PRINT2(_L("Get Empty Frame Buffer avail: %d"),iEmptyFrameBuffers.Count());
   443 
   444 	if(iEmptyFrameBuffers.Count() == 0) 
   445 		{
   446 		User::Leave(KErrNotReady);
   447 		}
   448 	CVideoFrameBuffer* frameBuf = iEmptyFrameBuffers[0];
   449 	iFrameBuffersInUse.AppendL(frameBuf);
   450 	iEmptyFrameBuffers.Remove(0);
   451 	if (aLockHeap)
   452 		{
   453 		frameBuf->LockFrameBufferHeap();
   454 		}
   455 	return *frameBuf;
   456 	}
   457 
   458 
   459 
   460 /** 
   461  Gets the first available picture (full frame buffer).
   462  @return	"TVideoPicture&"
   463  			A picture.
   464  @leave		May leave with KErrNotReady if no picture is available. 			
   465  */
   466 CVideoFrameBuffer& CMdfVideoDecoderBufferManager::GetFilledFrameBufferL(TBool aLockHeap)
   467 	{
   468 	DEBUG_PRINT2(_L("Get Filled Frame Buffer avail: %d"),iFilledFrameBuffers.Count());
   469 
   470 	if(iFilledFrameBuffers.Count() == 0) 
   471 		{		
   472 		User::Leave(KErrNotReady);
   473 		}
   474 	CVideoFrameBuffer* frameBuf = iFilledFrameBuffers[0];
   475 	iFilledFrameBuffers.Remove(0);
   476 	iFrameBuffersInUse.AppendL(frameBuf);
   477 	
   478 	if (aLockHeap)
   479 		{
   480 		frameBuf->LockFrameBufferHeap();
   481 		}
   482 	return *frameBuf;
   483 	}
   484 
   485 /** 
   486  Gets the last displayed picture.
   487  Used by Direct Screen Access to redraw.
   488  @return	"TPictureData&"
   489  			The last displayed picture.
   490  @leave		May leave with KErrNotReady if no picture is available. 			
   491  */
   492 const TPictureData& CMdfVideoDecoderBufferManager::LastPictureL() const
   493 	{
   494 	// it's a union, so we can check either iRgbBitmap or iRawData
   495 	if(!iLastDisplayedFrame.iRgbBitmap) 
   496 		{
   497 		User::Leave(KErrNotReady);
   498 		}
   499 	return iLastDisplayedFrame;
   500 	}
   501 
   502 /** 
   503  Gets a new empty frame buffer.
   504  @param		aDisplayMode
   505  			The display mode of the bitmap to be created.
   506  @return	"TVideoPicture&"
   507  			A frame buffer.
   508  @leave		May leave with KErrNotReady if no frame buffer is available, or if there
   509  			is no memory to create a new one. 
   510  */
   511 CVideoFrameBuffer& CMdfVideoDecoderBufferManager::CreateFrameBufferL(TDisplayMode aDisplayMode) 
   512 	{
   513 	CVideoFrameBuffer* frameBuffer = CVideoFrameBuffer::NewL(iFrameSize, iFormat, aDisplayMode);
   514 	CleanupStack::PushL(frameBuffer);
   515 	iEmptyFrameBuffers.AppendL(frameBuffer);
   516 	CleanupStack::Pop(frameBuffer);
   517 	
   518 	DEBUG_PRINT2(_L("BufferManager: Created frame buffer; %d buffers in use"), iEmptyFrameBuffers.Count());
   519 	return *frameBuffer;
   520 	}
   521 
   522 /** 
   523  Returns a used picture to the buffer manager for disposal.
   524  @param		"TVideoPicture* aFrameBuffer"
   525  			A used picture.
   526  @param		"TBool aSaveLast"
   527  			Save this picture as the last displayed (for redraw).
   528  @leave		May leave with KErrNotFound if the picture does not exist. 			
   529  */
   530 void CMdfVideoDecoderBufferManager::ReturnFrameBufferL(TVideoPicture& aFrameBuffer, CVideoFrameBuffer::TFrameBufferState aState)
   531 	{
   532 	DEBUG_PRINT(_L("Return Frame Buffer from TVideoPicture"));
   533 
   534 	TInt bufIndex;
   535 	User::LeaveIfError(bufIndex = FindFrameBuffer(aFrameBuffer));
   536 	// remove from the list of avaible buffers
   537 	CVideoFrameBuffer* frameBuf = iFrameBuffersInUse[bufIndex];
   538 	frameBuf->UnlockFrameBufferHeap();
   539 	if (aState == CVideoFrameBuffer::EEmptied)
   540 		{
   541 		DEBUG_PRINT(_L("Added to empty pool"));
   542 		iEmptyFrameBuffers.AppendL(frameBuf);
   543 		}
   544 	else
   545 		{
   546 		DEBUG_PRINT(_L("Added to filled pool"));
   547 		iFilledFrameBuffers.AppendL(frameBuf);
   548 		}
   549 	iFrameBuffersInUse.Remove(bufIndex);
   550 	
   551 	}
   552 
   553 void CMdfVideoDecoderBufferManager::ReturnFrameBufferL(CMMFBuffer* aBuffer, 
   554 									CVideoFrameBuffer::TFrameBufferState aState,
   555 									TBool aLastBuffer)
   556 	{
   557 	DEBUG_PRINT(_L("Return Frame buffer from CMMFBuffer"));
   558 	TInt bufIndex;
   559 	User::LeaveIfError(bufIndex = FindFrameBuffer(aBuffer));
   560 	// remove from the list of avaible buffers
   561 	CVideoFrameBuffer* frameBuf = iFrameBuffersInUse[bufIndex];
   562 	frameBuf->SetLastBuffer(aLastBuffer);
   563 	frameBuf->UnlockFrameBufferHeap();
   564 	if (aState == CVideoFrameBuffer::EEmptied)
   565 		{
   566 		DEBUG_PRINT(_L("Added to empty pool"));
   567 		iEmptyFrameBuffers.AppendL(frameBuf);
   568 		}
   569 	else
   570 		{
   571 		DEBUG_PRINT(_L("Added to filled pool"));
   572 		iFilledFrameBuffers.AppendL(frameBuf);
   573 		}
   574 	iFrameBuffersInUse.Remove(bufIndex);
   575 	
   576 	}
   577 
   578 // private methods
   579 
   580 TInt CMdfVideoDecoderBufferManager::FindFrameBuffer(const TVideoPicture& aFrameBuffer) const
   581 	{
   582 	TInt theCount = iFrameBuffersInUse.Count();
   583 	TInt found = KErrNotFound;
   584 	for(TInt i = 0; i < theCount; i++) 
   585 		{
   586 		if(*iFrameBuffersInUse[i] == aFrameBuffer) 
   587 			{
   588 			found = i;
   589 			break;
   590 			}
   591 		}
   592 	return found;
   593 	}
   594 
   595 
   596 TInt CMdfVideoDecoderBufferManager::FindFrameBuffer(const CMMFBuffer* aBuffer) const
   597 	{
   598 	TInt theCount = iFrameBuffersInUse.Count();
   599 	TInt found = KErrNotFound;
   600 	for(TInt i = 0; i < theCount; i++) 
   601 		{
   602 		if(*iFrameBuffersInUse[i] == aBuffer) 
   603 			{
   604 			found = i;
   605 			break;
   606 			}
   607 		}
   608 	return found;
   609 	}
   610 
   611 // end