os/mm/mmdevicefw/mdf/src/video/hwdevicevideoutils/mdfvideodecoderbuffermanager.cpp
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".
8 // Initial Contributors:
9 // Nokia Corporation - initial contribution.
17 #include <mmf/server/mmfdatabuffer.h>
18 #include "mdfvideodecoderbuffermanager.h"
20 #define MDFVIDEODECODERBUFFERMANAGER_DEBUG 1
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 ) )
28 #define DEBUG_PRINT( x )
29 #define DEBUG_PRINT2( x,y )
30 #define DEBUG_PRINT3( x,y,z )
31 #endif // defined (SYMBIAN_MDFVIDEODECODERBUFFERMANAGER_DEBUG)
33 CVideoDataBuffer::CVideoDataBuffer()
37 TUint CVideoDataBuffer::Length()
42 CVideoDataBuffer* CVideoDataBuffer::NewL(TUint aSize)
44 CVideoDataBuffer* self = new (ELeave) CVideoDataBuffer;
45 CleanupStack::PushL(self);
46 self->ConstructL(aSize);
47 CleanupStack::Pop(self);
51 void CVideoDataBuffer::ConstructL(TUint 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());
61 CVideoDataBuffer::operator CMMFBuffer*()
66 CVideoDataBuffer::operator TVideoInputBuffer&()
68 return iVideoInputBuffer;
73 TBool CVideoDataBuffer::operator== (const CMMFBuffer* aBuffer) const
75 return (aBuffer == iMmfBuffer);
78 TBool CVideoDataBuffer::operator== (const TVideoInputBuffer& aVideoInputBuffer) const
80 // compare the data pointers
81 return iVideoInputBuffer.iData == aVideoInputBuffer.iData;
84 CVideoDataBuffer::~CVideoDataBuffer()
90 CVideoFrameBuffer::CVideoFrameBuffer(TSize aFrameSize,
91 TUncompressedVideoFormat aFormat,
92 TDisplayMode aDisplayMode)
94 iFrameSize(aFrameSize),
95 iVideoFormat(aFormat),
96 iDisplayMode(aDisplayMode)
101 CVideoFrameBuffer* CVideoFrameBuffer::NewL(TSize aFrameSize,
102 TUncompressedVideoFormat aFormat,
103 TDisplayMode aDisplayMode)
105 CVideoFrameBuffer* self = new (ELeave) CVideoFrameBuffer(aFrameSize, aFormat, aDisplayMode);
106 CleanupStack::PushL(self);
108 CleanupStack::Pop(self);
112 void CVideoFrameBuffer::SetLastBuffer(TBool aLastBuffer)
114 iLastBuffer = aLastBuffer;
117 TBool CVideoFrameBuffer::LastBuffer()
122 void CVideoFrameBuffer::ConstructL()
124 iFrameBufferSize = CFbsBitmap::ScanLineLength(iFrameSize.iWidth, iDisplayMode) *
126 Mem::FillZ(&iVideoPicture, sizeof(TVideoPicture));
127 if(iVideoFormat.iDataFormat == ERgbFbsBitmap)
129 iBitmap = new(ELeave)CFbsBitmap;
130 User::LeaveIfError(iBitmap->Create(iFrameSize, iDisplayMode));
131 DEBUG_PRINT2(_L("BufferManager: Created bitmap at 0x%08x"), iBitmap);
133 iVideoPicture.iData.iRgbBitmap = iBitmap;
135 TRAPD(err, iMmfBuffer = CMMFPtrBuffer::NewL(TPtr8(reinterpret_cast<TUint8*>(iBitmap->DataAddress()),
137 iFrameBufferSize)) );
138 iBitmap->UnlockHeap();
139 User::LeaveIfError(err);
141 else if((iVideoFormat.iDataFormat == ERgbRawData) || (iVideoFormat.iDataFormat == EYuvRawData))
143 iRawBuffer = HBufC8::NewMaxL(iFrameBufferSize);
144 iRawPtr.Set(iRawBuffer->Des());
145 iMmfBuffer = CMMFPtrBuffer::NewL(iRawPtr);
146 iVideoPicture.iData.iRawData = &iRawPtr;
148 iVideoPicture.iData.iDataFormat = iVideoFormat.iDataFormat;
149 iVideoPicture.iData.iDataSize = iFrameSize;
152 CVideoFrameBuffer::operator CMMFBuffer*()
157 CVideoFrameBuffer::operator TVideoPicture&()
159 return iVideoPicture;
162 CVideoFrameBuffer::operator CMMFBuffer&()
167 CVideoFrameBuffer::operator TVideoPicture*()
169 return &iVideoPicture;
172 void CVideoFrameBuffer::LockFrameBufferHeap()
178 void CVideoFrameBuffer::UnlockFrameBufferHeap()
182 iBitmap->UnlockHeap();
183 iHeapLocked = EFalse;
188 TBool CVideoFrameBuffer::operator== (const CMMFBuffer* aBuffer) const
190 return (aBuffer == iMmfBuffer);
193 TBool CVideoFrameBuffer::operator== (const TVideoPicture& aVideoInputBuffer) const
195 // compare the data pointers - cheat, it is the same pointer for the bitmap and
197 return iVideoPicture.iData.iRawData == aVideoInputBuffer.iData.iRawData;
200 CVideoFrameBuffer::~CVideoFrameBuffer()
202 UnlockFrameBufferHeap();
210 Constructs a new instance of CMDFVideoDecoderBufferManager.
211 @return "CMDFVideoDecoderBufferManager*"
212 A pointer to the newly constructed CMDFVideoDecoderBufferManager
214 CMdfVideoDecoderBufferManager* CMdfVideoDecoderBufferManager::NewL()
216 CMdfVideoDecoderBufferManager* s = new(ELeave) CMdfVideoDecoderBufferManager;
217 CleanupStack::PushL(s);
219 CleanupStack::Pop(s);
220 return (static_cast<CMdfVideoDecoderBufferManager*>(s));
223 CMdfVideoDecoderBufferManager::CMdfVideoDecoderBufferManager()
226 void CMdfVideoDecoderBufferManager::ConstructL()
228 RFbsSession::Connect();
234 CMdfVideoDecoderBufferManager::~CMdfVideoDecoderBufferManager()
236 // get rid of input buffers
238 // cleanup frame buffer arrays
239 iEmptyFrameBuffers.ResetAndDestroy();
240 iFilledFrameBuffers.ResetAndDestroy();
241 iFrameBuffersInUse.ResetAndDestroy();
242 RFbsSession::Disconnect();
244 DEBUG_PRINT(_L("BufferManager: Closing down"));
248 Initializes the decoder buffer manager.
249 @param "const TUncompressedVideoFormat& aFormat"
250 The image format to decode into
252 void CMdfVideoDecoderBufferManager::Init(const TUncompressedVideoFormat& aFormat)
254 DEBUG_PRINT(_L("BufferManager: Initializing"));
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;
264 iInputBufferInUse = EFalse;
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.
276 CVideoDataBuffer& CMdfVideoDecoderBufferManager::CreateDataBufferL(TUint aBufferSize)
278 // We use one input buffer and one overflow buffer.
280 // If the app requests another buffer before this one has been processed, then leave.
281 if(iInputBufferInUse)
283 User::Leave(KErrInUse);
288 User::Leave(KErrArgument);
291 // Create or adjust the input buffer
295 iInputBuffer = CVideoDataBuffer::NewL(aBufferSize);
297 else if(iInputBuffer->Length() != aBufferSize)
299 // NB don't use ReAllocL() as it will panic if the buffer is shrinking
301 CVideoDataBuffer* tempBuffer = CVideoDataBuffer::NewL(aBufferSize);
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]
311 iInputBuffer = tempBuffer;
313 return *iInputBuffer;
316 void CMdfVideoDecoderBufferManager::ReturnDataBufferL(TVideoInputBuffer& aInputBuffer)
320 User::Leave(KErrNotFound);
322 // if this buffer isn't the input buffer, leave
323 if(! (*iInputBuffer == aInputBuffer) )
325 User::Leave(KErrNotFound);
327 // if the buffer is not in use, leave
328 if(!iInputBufferInUse)
330 User::Leave(KErrInUse);
333 // finished with input buffer - mark it unused
334 iInputBufferInUse = EFalse;
337 CVideoDataBuffer& CMdfVideoDecoderBufferManager::GetDataBufferL()
341 User::Leave(KErrNotFound);
343 if (iInputBufferInUse)
345 User::Leave(KErrInUse);
347 iInputBufferInUse = ETrue;
348 return *iInputBuffer;
352 Gets the number of available input buffers.
354 The number of available input buffers.
356 TInt CMdfVideoDecoderBufferManager::DataBuffersAvailable() const
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);
365 @param "const TSize& aSize"
368 void CMdfVideoDecoderBufferManager::SetFrameSize(const TSize& aSize)
375 @return "const TSize&"
378 const TSize& CMdfVideoDecoderBufferManager::FrameSize() const
384 Sets the frame buffer size.
386 The frame buffer size.
388 void CMdfVideoDecoderBufferManager::SetFrameBufferSize(TInt aSize)
390 iFrameBufferSize = aSize;
394 Gets the frame buffer size.
396 The frame buffer size.
398 TInt CMdfVideoDecoderBufferManager::FrameBufferSize() const
400 return iFrameBufferSize;
404 Gets the maximum number of frame buffers.
406 The maximum number of frame buffers.
408 TInt CMdfVideoDecoderBufferManager::MaxFrameBuffers() const
410 return iMaxFrameBuffers;
414 Gets the number of available pictures (full output buffers).
416 The number of available pictures.
418 TInt CMdfVideoDecoderBufferManager::FilledFrameBuffersAvailable() const
420 return ((iFilledFrameBuffers.Count() > 0) ? 1 : 0);
424 Gets the number of available frame buffers.
426 The number of available frame buffers.
428 TInt CMdfVideoDecoderBufferManager::EmptyFrameBuffersAvailable() const
430 return ((iEmptyFrameBuffers.Count() < iMaxFrameBuffers) ? 1 : 0);
435 Gets the first available framebuffer
436 @return "TVideoPicture&"
438 @leave May leave with KErrNotReady if no picture is available.
440 CVideoFrameBuffer& CMdfVideoDecoderBufferManager::GetEmptyFrameBufferL(TBool aLockHeap)
442 DEBUG_PRINT2(_L("Get Empty Frame Buffer avail: %d"),iEmptyFrameBuffers.Count());
444 if(iEmptyFrameBuffers.Count() == 0)
446 User::Leave(KErrNotReady);
448 CVideoFrameBuffer* frameBuf = iEmptyFrameBuffers[0];
449 iFrameBuffersInUse.AppendL(frameBuf);
450 iEmptyFrameBuffers.Remove(0);
453 frameBuf->LockFrameBufferHeap();
461 Gets the first available picture (full frame buffer).
462 @return "TVideoPicture&"
464 @leave May leave with KErrNotReady if no picture is available.
466 CVideoFrameBuffer& CMdfVideoDecoderBufferManager::GetFilledFrameBufferL(TBool aLockHeap)
468 DEBUG_PRINT2(_L("Get Filled Frame Buffer avail: %d"),iFilledFrameBuffers.Count());
470 if(iFilledFrameBuffers.Count() == 0)
472 User::Leave(KErrNotReady);
474 CVideoFrameBuffer* frameBuf = iFilledFrameBuffers[0];
475 iFilledFrameBuffers.Remove(0);
476 iFrameBuffersInUse.AppendL(frameBuf);
480 frameBuf->LockFrameBufferHeap();
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.
492 const TPictureData& CMdfVideoDecoderBufferManager::LastPictureL() const
494 // it's a union, so we can check either iRgbBitmap or iRawData
495 if(!iLastDisplayedFrame.iRgbBitmap)
497 User::Leave(KErrNotReady);
499 return iLastDisplayedFrame;
503 Gets a new empty frame buffer.
505 The display mode of the bitmap to be created.
506 @return "TVideoPicture&"
508 @leave May leave with KErrNotReady if no frame buffer is available, or if there
509 is no memory to create a new one.
511 CVideoFrameBuffer& CMdfVideoDecoderBufferManager::CreateFrameBufferL(TDisplayMode aDisplayMode)
513 CVideoFrameBuffer* frameBuffer = CVideoFrameBuffer::NewL(iFrameSize, iFormat, aDisplayMode);
514 CleanupStack::PushL(frameBuffer);
515 iEmptyFrameBuffers.AppendL(frameBuffer);
516 CleanupStack::Pop(frameBuffer);
518 DEBUG_PRINT2(_L("BufferManager: Created frame buffer; %d buffers in use"), iEmptyFrameBuffers.Count());
523 Returns a used picture to the buffer manager for disposal.
524 @param "TVideoPicture* aFrameBuffer"
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.
530 void CMdfVideoDecoderBufferManager::ReturnFrameBufferL(TVideoPicture& aFrameBuffer, CVideoFrameBuffer::TFrameBufferState aState)
532 DEBUG_PRINT(_L("Return Frame Buffer from TVideoPicture"));
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)
541 DEBUG_PRINT(_L("Added to empty pool"));
542 iEmptyFrameBuffers.AppendL(frameBuf);
546 DEBUG_PRINT(_L("Added to filled pool"));
547 iFilledFrameBuffers.AppendL(frameBuf);
549 iFrameBuffersInUse.Remove(bufIndex);
553 void CMdfVideoDecoderBufferManager::ReturnFrameBufferL(CMMFBuffer* aBuffer,
554 CVideoFrameBuffer::TFrameBufferState aState,
557 DEBUG_PRINT(_L("Return Frame buffer from CMMFBuffer"));
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)
566 DEBUG_PRINT(_L("Added to empty pool"));
567 iEmptyFrameBuffers.AppendL(frameBuf);
571 DEBUG_PRINT(_L("Added to filled pool"));
572 iFilledFrameBuffers.AppendL(frameBuf);
574 iFrameBuffersInUse.Remove(bufIndex);
580 TInt CMdfVideoDecoderBufferManager::FindFrameBuffer(const TVideoPicture& aFrameBuffer) const
582 TInt theCount = iFrameBuffersInUse.Count();
583 TInt found = KErrNotFound;
584 for(TInt i = 0; i < theCount; i++)
586 if(*iFrameBuffersInUse[i] == aFrameBuffer)
596 TInt CMdfVideoDecoderBufferManager::FindFrameBuffer(const CMMFBuffer* aBuffer) const
598 TInt theCount = iFrameBuffersInUse.Count();
599 TInt found = KErrNotFound;
600 for(TInt i = 0; i < theCount; i++)
602 if(*iFrameBuffersInUse[i] == aBuffer)