diff -r 000000000000 -r ed9695c8bcbe vtprotocolplugins/VideoSource/src/cmultiframeprovider.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vtprotocolplugins/VideoSource/src/cmultiframeprovider.cpp Mon Nov 23 14:47:47 2009 +0200 @@ -0,0 +1,1019 @@ +/* +* Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies). +* All rights reserved. +* This component and the accompanying materials are made available +* under the terms of "Eclipse Public License v1.0" +* which accompanies this distribution, and is available +* at the URL "http://www.eclipse.org/legal/epl-v10.html". +* +* Initial Contributors: +* Nokia Corporation - initial contribution. +* +* Contributors: +* +* Description: Video Source subsystem. +* +*/ + + +// INCLUDE FILES +#include +#include +#include +#include +#include + +#include "cmultiframeprovider.h" +#include "cmultiframeloopao.h" +#include "cmultiframedataao.h" + +#include "CVSStillImageDataProvider.h" +#include "cvtimagebitmap.h" + +static const TInt KQcifWidth = 176; +static const TInt KQcifHeight = 144; + +// Default bitmap size is VGA +static const TInt KDefaultBitmapSizeWidth = 640; +static const TInt KDefaultBitmapSizeHeight = 480; + +// MACROS + +#ifdef _DEBUG +# define __IF_DEBUG(t) {RDebug::t;} +#else +# define __IF_DEBUG(t) +#endif + +// ============================ TScalingMediator =============================== + +// ----------------------------------------------------------------------------- +// TScalingMediator::TScalingMediator( ) +// ----------------------------------------------------------------------------- +// +TScalingMediator::TScalingMediator() + { + } + +// ----------------------------------------------------------------------------- +// TScalingMediator::ScalingFinished( ) +// ----------------------------------------------------------------------------- +// +void TScalingMediator::ScalingFinished( TInt aError ) + { + __IF_DEBUG(Print(_L("TScalingMediator::ScalingFinished() >>"))); + iWait->Signal( aError ); + __IF_DEBUG(Print(_L("TScalingMediator::ScalingFinished() error %d <<"), aError)); + } +// ----------------------------------------------------------------------------- +// TScalingMediator::ScalingFinished( ) +// ----------------------------------------------------------------------------- +// +void TScalingMediator::SetWaiter( CVSActiveWait< CMultiframeProvider >* aWait ) + { + iWait = aWait; + } + +// ============================ CMultiframeProvider =============================== + +// ----------------------------------------------------------------------------- +// CMultiframeProvider::NewL( ) +// ----------------------------------------------------------------------------- +// +CMultiframeProvider* CMultiframeProvider::NewL( MMultiframeprovider* aObserver, TDisplayMode aDisplayMode ) + { + __IF_DEBUG(Print(_L("VideoSource: [%d] CMultiframeProvider::NewL() >>"), RThread().Id().operator TUint())); + CMultiframeProvider* self = + new (ELeave) CMultiframeProvider( aObserver, aDisplayMode ); + CleanupStack::PushL( self ); + self->ConstructL(); + CleanupStack::Pop( self ); + __IF_DEBUG(Print(_L("VideoSource: [%d] CMultiframeProvider::NewL() <<"), RThread().Id().operator TUint())); + return self; + } +// ----------------------------------------------------------------------------- +// CMultiframeProvider::CMultiframeProvider( +// MVSDataProviderObserver* aObserver ) +// ----------------------------------------------------------------------------- +// +CMultiframeProvider::CMultiframeProvider( + MMultiframeprovider* aObserver , TDisplayMode aDisplayMode ): iDisplayMode( aDisplayMode ), iObserver( aObserver ), iBlank( EFalse ), iGSImage( EFalse ) + { + __IF_DEBUG(Print(_L("VideoSource [%d]: CMultiframeProvider::CMultiframeProvider() >>"), RThread().Id().operator TUint())); + //Set target VF size QCIF as default + iTargetSize.SetSize( KQcifWidth , KQcifHeight ); + iVFSize.SetSize( KQcifWidth , KQcifHeight ); + __IF_DEBUG(Print(_L("VideoSource [%d]: CMultiframeProvider::CMultiframeProvider() <<"), RThread().Id().operator TUint())); + } +// ----------------------------------------------------------------------------- +// CMultiframeProvider::~CMultiframeProvider() +// ----------------------------------------------------------------------------- +// +CMultiframeProvider::~CMultiframeProvider() + { + __IF_DEBUG(Print(_L("VideoSource [%d]: CMultiframeProvider::~CMultiframeProvider() >>"), RThread().Id().operator TUint())); + iFs.Close(); + iFreezeCS.Close(); + delete iImageDecoder; iImageDecoder = 0; + delete iVtImageScalerInit; + delete iVtImageScalerScale; + delete iActiveWaitInit; + delete iActiveWaitScale; + delete iActiveWaitInitScale; + delete iConverted; + delete iMask; + delete iTempBM; + delete iDataTimer; + delete iLoopAo; + if ( iScaled != iBuffer1 && iScaled != iBuffer2 ) + { + delete iScaled; + } + delete iGSBitmap; + if ( !iBlank || !iGSImage ) + { + delete iBuffer1; + delete iBuffer2; + } + delete iFirstVfBuf; + delete iSecondVfBuf; + iFreeQueue.Close(); + iDefaultImageFile.Close(); + __IF_DEBUG(Print(_L("VideoSource [%d]: CMultiframeProvider::~CMultiframeProvider() <<"), RThread().Id().operator TUint())); + } + +// ----------------------------------------------------------------------------- +// CMultiframeProvider::ConstructL() +// ----------------------------------------------------------------------------- +// +void CMultiframeProvider::ConstructL() + { + __IF_DEBUG(Print(_L("VideoSource [%d]: CMultiframeProvider::ConstructL() >>"), RThread().Id().operator TUint())); + User::LeaveIfError( iFs.Connect() ); + User::LeaveIfError( iFreezeCS.CreateLocal() ); + + // Create waiters and mediators for scaling purposes + iActiveWaitInit = new (ELeave) CVSActiveWait< CMultiframeProvider >( this ); + iActiveWaitScale = new (ELeave) CVSActiveWait< CMultiframeProvider >( this ); + iActiveWaitInitScale = new (ELeave) CVSActiveWait< CMultiframeProvider >( this ); + iInitMediator.SetWaiter( iActiveWaitInitScale ); + iScalingMediator.SetWaiter( iActiveWaitScale ); + iVtImageScalerInit = CVtImageScaler::NewL( iInitMediator, CVtImageScaler::EBilinear ); + iVtImageScalerScale = CVtImageScaler::NewL( iScalingMediator, CVtImageScaler::EBilinear ); + iDataTimer = new (ELeave) CMultiframeDataAO( this ); + iDataTimer->SetObserver( iObserver ); + iLoopAo = new (ELeave) CMultiframeloopAO( this ); + iFirstVfBuf = CVtImageBitmap::NewL( TSize( KQcifWidth >> 2, KQcifHeight >> 2 ), iDisplayMode ); + iSecondVfBuf = CVtImageBitmap::NewL( TSize( KQcifWidth >> 2, KQcifHeight >> 2 ), iDisplayMode ); + iSecondVFBuffer = EFalse; + iFirstVFBuffer = ETrue; + iIsVfStopped = EFalse; + iWaitForConverting = EFalse; + __IF_DEBUG(Print(_L("VideoSource [%d]: CMultiframeProvider::ConstructL() <<"), RThread().Id().operator TUint())); + } + +// ----------------------------------------------------------------------------- +// CMultiframeProvider::IniatializeGSL() +// +// ----------------------------------------------------------------------------- +// +void CMultiframeProvider::IniatializeGSL( const TGeneralSettingsImageType aType ) + { + __IF_DEBUG(Print(_L("VideoSource [%d]: CMultiframeProvider::IniatializeGSL() >>"), RThread().Id().operator TUint())); + if ( aType == EGSStillImage ) + { + // Open connection to phone server + RPhCltServer phoneClient; + User::LeaveIfError( phoneClient.Connect() ); + CleanupClosePushL( phoneClient ); + + CPhCltImageHandler* stillH = CPhCltImageHandler::NewL(); + CleanupStack::PushL( stillH ); + + // Load images + CPhCltImageParams* imageParams; + imageParams = stillH->CPhCltBaseImageParamsL( EPhCltTypeVTStill ); + CleanupStack::PushL( imageParams ); + User::LeaveIfError( stillH->LoadImages( imageParams ) ); + + // Duplicate to image + if( imageParams->Count() > 0 ) + { + __IF_DEBUG(Print(_L("iImageCount > 0"))); + iGSBitmap = CVtImageBitmap::NewL( imageParams->GetImageL( 0 ) ); + } + else + { + __IF_DEBUG(Print(_L("iImageCount <= 0 -> User::Leave( KErrNotFound )"))); + User::Leave( KErrNotFound ); + } + // Cleanup + CleanupStack::PopAndDestroy( 3 ); // phoneClient, stillH, imageParams + iScaled = CVtImageBitmap::NewL( TSize( KQcifWidth, KQcifHeight ), iDisplayMode ); + + // If bitmap has different display mode than screen, then new bitmap + // is created and image is converted to screen's display mode + if ( iGSBitmap->Bitmap().DisplayMode() != iDisplayMode || + iGSBitmap->Bitmap().ExtendedBitmapType() != KNullUid ) + { + CVtImageBitmap* temp = CVtImageBitmap::NewL( + iGSBitmap->Bitmap().SizeInPixels(), iDisplayMode ); + CleanupStack::PushL( temp ); + // Color conversion is done by blitting it to other bitmap + CFbsBitmapDevice* fbd = CFbsBitmapDevice::NewL( &temp->Bitmap() ); + CleanupStack::PushL( fbd ); + CFbsBitGc* fgc = NULL; + User::LeaveIfError( fbd->CreateContext( fgc ) ); + CleanupStack::PushL( fgc ); + fgc->BitBlt( TPoint(), &iGSBitmap->Bitmap() ); + CleanupStack::PopAndDestroy( 2 ); // fbd, fgc + CleanupStack::Pop(); // temp + delete iGSBitmap; iGSBitmap = NULL; + iGSBitmap = temp; + } + iGSImage = ETrue; + iCount = 1; + iActiveWaitInit->InitializeWaiter( &ConversionFinished ); + iActiveWaitInit->Signal( KErrNone ); + } + else + { // default still image prepared by using file handle + InitializeL( NULL ); + } + iInitialization = ETrue; + iDelay = 0; + __IF_DEBUG(Print(_L("VideoSource [%d]: CMultiframeProvider::IniatializeGSL() <<"), RThread().Id().operator TUint())); + } +// ----------------------------------------------------------------------------- +// CMultiframeProvider::IniatializeBlank() +// +// ----------------------------------------------------------------------------- +// +void CMultiframeProvider::IniatializeBlankL() + { + __IF_DEBUG(Print(_L("VideoSource [%d]: CMultiframeProvider::IniatializeBlank() >>"), RThread().Id().operator TUint())); + iBlank = ETrue; + iInitialization = ETrue; + iDelay = 0; + iCount = 1; + + CFbsBitmap* tempBitmap = 0; + + CreateBlankBitmapL( + tempBitmap, + TSize( KQcifWidth, KQcifHeight ), + iDisplayMode, +#ifdef _DEBUG + KRgbYellow +#else + KRgbBlack +#endif + ); + + CleanupStack::PushL( tempBitmap ); + iScaled = CVtImageBitmap::NewL( tempBitmap->Handle() ); + CleanupStack::PopAndDestroy(); // tempBitmap + tempBitmap = 0; + + iActiveWaitInit->InitializeWaiter( &BMSScalingFinished ); + iActiveWaitInit->Signal( KErrNone ); + __IF_DEBUG(Print(_L("VideoSource [%d]: CMultiframeProvider::IniatializeBlank() <<"), RThread().Id().operator TUint())); + } + // ----------------------------------------------------------------------------- +// CVSStillImageDataProvider::CreateBlankBitmapL( +// CFbsBitmap*& aBitmap, const TSize& aSize, const TDisplayMode& aMode, +// const TRgb& aColor ) +// ----------------------------------------------------------------------------- +// +void CMultiframeProvider::CreateBlankBitmapL( + CFbsBitmap*& aBitmap, + const TSize& aSize, + const TDisplayMode& aMode, + const TRgb& aColor ) + { + __IF_DEBUG(Print(_L("VideoSource[%d]: CMultiframeProvider::CreateBlankBitmapL() >>"), RThread().Id().operator TUint())); + if( aBitmap ) + { + delete aBitmap; + aBitmap = 0; + } + aBitmap = new (ELeave) CFbsBitmap(); + User::LeaveIfError( aBitmap->Create( aSize, aMode ) ); + CFbsBitmapDevice* fbd = CFbsBitmapDevice::NewL( aBitmap ); + CleanupStack::PushL( fbd ); + CFbsBitGc* fgc = 0; + User::LeaveIfError( fbd->CreateContext( fgc ) ); + CleanupStack::PushL( fgc ); + + fgc->SetPenColor( aColor ); + fgc->SetBrushColor( aColor ); + fgc->SetBrushStyle( CGraphicsContext::ESolidBrush ); + fgc->DrawRect( TRect( aSize ) ); + + CleanupStack::PopAndDestroy( 2 ); // fbd, fgc + __IF_DEBUG(Print(_L("VideoSource[%d]: CMultiframeProvider::CreateBlankBitmapL() <<"), RThread().Id().operator TUint())); + } +// ----------------------------------------------------------------------------- +// CMultiframeProvider::Iniatialize() +// +// ----------------------------------------------------------------------------- +// +void CMultiframeProvider::InitializeL( const TFileName* aFileName ) + { + __IF_DEBUG(Print(_L("VideoSource [%d]: CMultiframeProvider::InitializeL() >>"), RThread().Id().operator TUint())); + // Create bitmaps used for conversion and scaling + iBuffer1 = CVtImageBitmap::NewL( TSize( KQcifWidth, KQcifHeight ), iDisplayMode ); + iBuffer2 = CVtImageBitmap::NewL( TSize( KQcifWidth, KQcifHeight ), iDisplayMode ); + User::LeaveIfError( iFreeQueue.Append( iBuffer1 ) ); + User::LeaveIfError( iFreeQueue.Append( iBuffer2 ) ); + iLoopAo->SetFreeBitmaps( 2 ); + + // Create ICL decoder in its own thread for current file + TInt decodingoptions( + CImageDecoder::TOptions( CImageDecoder::EOptionAlwaysThread | CImageDecoder::EAllowGeneratedMask ) ); + + if ( aFileName ) + { + __IF_DEBUG(Print(_L(" file name exist, creating CImageDecoder"))); + iImageDecoder = CImageDecoder::FileNewL( iFs, *aFileName, (CImageDecoder::TOptions )decodingoptions /*CImageDecoder::EOptionNone*/ ); + } + else + { + __IF_DEBUG(Print(_L(" default vt image file => use phone server"))); + // default VT image file handle obtained from phone server + RPhCltServer phoneClient; + User::LeaveIfError( phoneClient.Connect() ); + __IF_DEBUG(Print(_L(" connected to phone server"))); + CleanupClosePushL( phoneClient ); + CPhCltImageHandler* handler = CPhCltImageHandler::NewL(); + CleanupStack::PushL( handler ); + __IF_DEBUG(Print(_L(" created image handler"))); + User::LeaveIfError( handler->OpenDefaultVtImage( iDefaultImageFile ) ); + decodingoptions &= ~CImageDecoder::EOptionAlwaysThread; + __IF_DEBUG(Print(_L(" creating image decoder"))); + iImageDecoder = CImageDecoder::FileNewL( iDefaultImageFile, ContentAccess::EPlay, (CImageDecoder::TOptions )decodingoptions ); + __IF_DEBUG(Print(_L(" created image decoder"))); + CleanupStack::PopAndDestroy( 2 ); // handler, phoneClient + } + // Use ICL to calculate frame count + iCount = iImageDecoder->FrameCount(); + __IF_DEBUG(Print(_L(" frame count=%d"),iCount)); + //If advanced flags are on show only first frame! + for ( TInt index = 0; index < iCount; ++index ) + { + TFrameInfo frameInfo( iImageDecoder->FrameInfo( index ) ); + __IF_DEBUG(Print(_L("VideoSource [%d]: CMultiframeProvider::InitializeL() frameInfo.iFlags %b >>"), RThread().Id().operator TUint(), frameInfo.iFlags)); + if ( frameInfo.iFlags & TFrameInfo::ELeaveInPlace ) + { + iDelay = 0; + iCount = 1; + } + } + //Set num of frames to viewer AO + iLoopAo->SetFrameCount( iCount ); + //For default loopping frame sequence is disabled + iAnimation = EFalse; + iInitialization = ETrue; + //Start ICL image conversion (decoding) and local scaling + ConvertAndScaleL( KFirstFrameIndx ); + __IF_DEBUG(Print(_L("VideoSource [%d]: CMultiframeProvider::InitializeL() <<"), RThread().Id().operator TUint())); + } + +// ----------------------------------------------------------------------------- +// CMultiframeProvider::SetVFScalingTargetSize() +// +// ----------------------------------------------------------------------------- +// +void CMultiframeProvider::SetVFScalingTargetSize( TSize aSize ) + { + __IF_DEBUG(Print(_L("VideoSource [%d]: CMultiframeProvider::SetVFScalingTargetSize() >>"), RThread().Id().operator TUint())); + iTargetSize = aSize; + __IF_DEBUG(Print(_L("VideoSource [%d]: CMultiframeProvider::SetVFScalingTargetSize() W %d H %d <<"), RThread().Id().operator TUint(), aSize.iWidth , aSize.iHeight )); + } + +// ----------------------------------------------------------------------------- +// CMultiframeProvider::ConvertAndScaleL() +// ----------------------------------------------------------------------------- +// +void CMultiframeProvider::ConvertAndScaleL( TInt aFrameIndex ) + { + // Variables related to Bitmap size + // calculation + __IF_DEBUG(Print(_L("VideoSource [%d]: CMultiframeProvider::ConvertAndScale() aFrameIndex %d>>"), RThread().Id().operator TUint(),aFrameIndex)); + TSize convertedBitmapSize; + TFrameInfo frameInfo( iImageDecoder->FrameInfo( aFrameIndex ) ); + if ( !iInitialization ) + { + TInt delayindex; + delayindex = aFrameIndex - 1; + if ( delayindex < KFirstFrameIndx ) + { + delayindex = ( iCount - 1 ); + } + TFrameInfo delayframeInfo( iImageDecoder->FrameInfo( delayindex ) ); + iDelay = delayframeInfo.iDelay; + } + else + { + iDelay = 1; + } + __IF_DEBUG(Print(_L("VideoSource [%d]: CMultiframeProvider::ConvertAndScale() iDelay %d>>"), RThread().Id().operator TUint(),iDelay.Int64() )); +#ifdef _DEBUG + TUint threadId( RThread().Id() ); + switch ( frameInfo.iFrameDisplayMode ) + { + case EColor4K: + RDebug::Print( _L( "VideoSource [%d]: FrameDPmode = EColor4K" ), + threadId ); + break; + case EColor64K: + RDebug::Print( _L( "VideoSource [%d]: FrameDPmode = EColor64K" ), + threadId ); + break; + case EColor16M: + RDebug::Print( _L( "VideoSource [%d]: FrameDPmode = EColor16M" ), + threadId ); + break; + case EColor16MU: + RDebug::Print( _L( "VideoSource [%d]: FrameDPmode = EColor16MU" ), + threadId ); + break; + default: + RDebug::Print( _L( "VideoSource [%d]: FrameDPmode = %d" ), + threadId, frameInfo.iFrameDisplayMode ); + break; + } + + RDebug::Print( _L( "VideoSource [%d]: CMultiframeProvider:: frameInfo.iFlags %d" ), + threadId,frameInfo.iFlags ); +#endif // _DEBUG + + // Use imagedecoder to calculate how many times source picture needs to be divided by 2 + // to fit in default (VGA) picture + TInt reductionfactor = iImageDecoder->ReductionFactor( frameInfo.iOverallSizeInPixels, + TSize( KDefaultBitmapSizeWidth, KDefaultBitmapSizeHeight ) ); + if ( iImageDecoder->ReducedSize( frameInfo.iOverallSizeInPixels, reductionfactor, convertedBitmapSize ) ) + { + convertedBitmapSize = frameInfo.iOverallSizeInPixels; + } + +#ifdef _DEBUG + RDebug::Print( _L( "VideoSource [%d]: convertedBitmapSize Width = %d convertedBitmapSize Height = %d" ), + threadId, convertedBitmapSize.iWidth, convertedBitmapSize.iHeight ); +#endif // _DEBUG + __IF_DEBUG(Print(_L("VideoSource [%d]: CMultiframeProvider::ConvertAndScale() iConverted"), RThread().Id().operator TUint())); + iConverted = CVtImageBitmap::NewL( convertedBitmapSize, iDisplayMode ); + __IF_DEBUG(Print(_L("VideoSource [%d]: CMultiframeProvider::ConvertAndScale() iConverted"), RThread().Id().operator TUint())); +#ifdef _DEBUG + RDebug::Print( _L( "VideoSource [%d]: convBitmap Width = %d convBitmap Height = %d" ), + threadId, iConverted->Size().iWidth, iConverted->Size().iHeight ); +#endif // _DEBUG + + iStartTime.HomeTime(); + if ( iFreeQueue.Count() < 2 ) + { + __IF_DEBUG(Print(_L("VideoSource[%d]: CMultiframeProvider::ConvertAndScale() iFreeQueue.Count() < 2 "), RThread().Id().operator TUint())); + iOldBM = ETrue; + iOldBitmap = iScaled; + } + iScaled = iFreeQueue[ 0 ]; + iFreeQueue.Remove( 0 ); + iLoopAo->RemoveFreeBitmaps( 1 ); + iActiveWaitInit->InitializeWaiter( &CMultiframeProvider::ConversionFinished ); + // Check if masking is supported + if ( frameInfo.iFlags & TFrameInfo::ETransparencyPossible ) + { + // Create mask for bitmap + iMask = new ( ELeave )CFbsBitmap(); + User::LeaveIfError( iMask->Create( convertedBitmapSize, EGray256 )); + iTempBM = CVtImageBitmap::NewL( convertedBitmapSize, iDisplayMode ); + iImageDecoder->Convert( iActiveWaitInit->RequestStatus(), iTempBM->Bitmap(), *iMask, aFrameIndex ); + } + // No mask + else + { + iImageDecoder->Convert( iActiveWaitInit->RequestStatus(), iConverted->Bitmap(), aFrameIndex ); + } + __IF_DEBUG(Print(_L("VideoSource [%d]: CMultiframeProvider::ConvertAndScale() <<"), RThread().Id().operator TUint())); + } + +// ----------------------------------------------------------------------------- +// CMultiframeProvider::ConversionFinished( TInt aError ) +// ----------------------------------------------------------------------------- +// +void CMultiframeProvider::ConversionFinished( TInt aError ) + { + __IF_DEBUG(Print(_L("VideoSource[%d]: CMultiframeProvider::ConversionFinished() >>"), RThread().Id().operator TUint())); + if ( iCount == 1 || aError ) + { + // delete decoder if not needed any more + // 1) single frame image, no further frames to convert + // 2) error occured, decoder won't be used anyway + __IF_DEBUG(Print(_L(" single frame image => destruct iImageDecoder, err %d"), aError ) ); + delete iImageDecoder; + iImageDecoder = NULL; + } + // no harm done if other than this used, handle would already be 0 + iDefaultImageFile.Close(); + if ( aError == KErrNone ) + { + iActiveWaitInitScale->InitializeWaiter( &BMSScalingFinished ); + if ( iGSImage ) + { + __IF_DEBUG(Print(_L("VideoSource[%d]: CMultiframeProvider::ConversionFinished() scale GS "), RThread().Id().operator TUint())); + iVtImageScalerInit->Scale( *iGSBitmap, *iScaled ); + } + else + { + __IF_DEBUG(Print(_L("VideoSource[%d]: CMultiframeProvider::ConversionFinished() scale "), RThread().Id().operator TUint())); + // Blit mask into a converted bitmap + if ( iMask ) + { + CGraphicsContext* bitmapcontext = NULL; + CFbsBitmapDevice* bitmapdevice = NULL; + // Create bm device + TRAPD( error, bitmapdevice = CFbsBitmapDevice::NewL( &( iConverted->Bitmap() ) ) ); + if ( error != KErrNone ) + { + iObserver->NotifyImageHandlingError( aError ); + delete bitmapdevice; + delete iTempBM; + delete iMask; + iMask = NULL; + iTempBM = NULL; + return; + } + // Create GC for bm + error = bitmapdevice->CreateContext( bitmapcontext ); + if ( error != KErrNone ) + { + iObserver->NotifyImageHandlingError( aError ); + delete bitmapdevice; + delete bitmapcontext; + delete iTempBM; + delete iMask; + iMask = NULL; + iTempBM = NULL; + return; + } + // Fill destination bitmap with white color + TRect rect( iConverted->Size() ); + bitmapcontext->SetBrushStyle( CGraphicsContext:: ESolidBrush ); + bitmapcontext->SetPenStyle( CGraphicsContext::ESolidPen ); + bitmapcontext->SetBrushColor( KRgbWhite ); + bitmapcontext->SetPenColor( KRgbWhite); + bitmapcontext->DrawRect( rect ); + + // Draw mask and data bitmap into a same destination bm + bitmapcontext->DrawBitmapMasked( iConverted->Size(), &( iTempBM->Bitmap() ), iConverted->Size(), iMask, EFalse ); + delete bitmapdevice; + delete bitmapcontext; + delete iTempBM; + delete iMask; + iMask = NULL; + iTempBM = NULL; + __IF_DEBUG(Print(_L("VideoSource [%d]: CMultiframeProvider::ConversionFinished() iMask"), RThread().Id().operator TUint())); + } + iVtImageScalerInit->Scale( *iConverted, *iScaled ); + } + } + // Allways inform Decoding problems + else + { + iObserver->NotifyImageHandlingError( aError ); + delete iTempBM; + delete iMask; + iMask = NULL; + iTempBM = NULL; + } + __IF_DEBUG(Print(_L("VideoSource[%d]: CMultiframeProvider::ConversionFinished() error %d <<"), RThread().Id().operator TUint(), aError)); + } + +// ----------------------------------------------------------------------------- +// CMultiframeProvider::BMSScalingFinished( TInt aError ) +// ----------------------------------------------------------------------------- +// +void CMultiframeProvider::BMSScalingFinished( TInt aError ) + { + __IF_DEBUG(Print(_L("VideoSource[%d]: CMultiframeProvider::BMSScalingFinished() >>"), RThread().Id().operator TUint())); + if ( aError == KErrNone ) + { + VFScalingReady(); + } + else + { +#if 0 + if ( aError != KErrCancel ) // If KErrCancel, then ignore error! + { + iObserver->NotifyImageHandlingError( aError ); + } + //Needs to be deleted also in cancel case + delete iConverted; iConverted = NULL; +#endif + delete iConverted; iConverted = NULL; + iObserver->NotifyImageHandlingError( aError ); + + } + __IF_DEBUG(Print(_L("VideoSource[%d]: CMultiframeProvider::BMSScalingFinished() err %d <<"), RThread().Id().operator TUint(), aError)); + } + +// ----------------------------------------------------------------------------- +// CMultiframeProvider::AddBitmapToFreeQueue( CVtImageBitmap* aBitmap ) +// ----------------------------------------------------------------------------- +// +void CMultiframeProvider::AddBitmapToFreeQueue() + { + __IF_DEBUG(Print(_L("VideoSource[%d]: CMultiframeProvider::AddBitmapToFreeQueue() >>"), RThread().Id().operator TUint())); + if ( iOldBM ) + { + __IF_DEBUG(Print(_L("VideoSource[%d]: CMultiframeProvider::AddBitmapToFreeQueue() OLD BM"), RThread().Id().operator TUint())); + iOldBM = EFalse; + iFreeQueue.Append( iOldBitmap ); + } + else + { + iFreeQueue.Append( iScaled ); + } + iLoopAo->SetFreeBitmaps( 1 ); + __IF_DEBUG(Print(_L("VideoSource[%d]: CMultiframeProvider::AddBitmapToFreeQueue() <<"), RThread().Id().operator TUint())); + } + +// ----------------------------------------------------------------------------- +// CMultiframeProvider::UseSecondVfBuffer() +// ----------------------------------------------------------------------------- +// +void CMultiframeProvider::UseSecondVfBuffer() + { + iSecondVFBuffer = ETrue; + } + +// ----------------------------------------------------------------------------- +// CMultiframeProvider::VFScalingReady() +// ----------------------------------------------------------------------------- +// +void CMultiframeProvider::VFScalingReady() + { + __IF_DEBUG(Print(_L("VideoSource[%d]: CMultiframeProvider::VFScalingReady() >>"), RThread().Id().operator TUint())); + delete iConverted; iConverted = 0; + + // Calculate frame update delay here! + TTime refpointtime; + refpointtime.HomeTime(); + TTimeIntervalMicroSeconds deltaTime = refpointtime.MicroSecondsFrom( iStartTime ); + iFrameUpdateTime = iDelay.Int64() - deltaTime.Int64(); + if ( iFrameUpdateTime < 0 ) + { + iFrameUpdateTime = 1; + } + __IF_DEBUG(Print(_L("VideoSource[%d]: CMultiframeProvider::VFScalingReady() iFrameUpdateTime %d>>"), RThread().Id().operator TUint(), iFrameUpdateTime.Int64())); + // Scale VF to fit in requested size + // size is as default QCIF + if ( iIsVfStopped ) + { + __IF_DEBUG(Print(_L("VideoSource[%d]: CMultiframeProvider::VFScalingReady()VF Stop>>"), RThread().Id().operator TUint())); + if ( iActiveWaitScale->IsActive() ) + { + //ScaleCopy running + //Waiting is OK + __IF_DEBUG(Print(_L("VideoSource[%d]: CMultiframeProvider::VFScalingReady()ScaleCopy running>>"), RThread().Id().operator TUint())); + } + else + { + //ScaleCopy is not running, Jump ScaleCopy + __IF_DEBUG(Print(_L("VideoSource[%d]: CMultiframeProvider::VFScalingReady()jump ScaleCopy>>"), RThread().Id().operator TUint())); + iActiveWaitScale->InitializeWaiter( &VFRescalingFinished ); + iActiveWaitScale->Signal(KErrNone); + } + } + else + { + __IF_DEBUG(Print(_L("VideoSource[%d]: CMultiframeProvider::VFScalingReady()Normal run>>"), RThread().Id().operator TUint())); + iVFUpdate = EFalse; + ScaleCopy( iTargetSize ); + } + __IF_DEBUG(Print(_L("VideoSource[%d]: CMultiframeProvider::VFScalingReady() <<"), RThread().Id().operator TUint())); + } + +// ----------------------------------------------------------------------------- +// CMultiframeProvider::ScaleCopy( TSize& aSize ) +// ----------------------------------------------------------------------------- +// +void CMultiframeProvider::ScaleCopy( TSize& aSize, TBool aVFUpdate ) + { + __IF_DEBUG(Print(_L("VideoSource [%d]: CMultiframeProvider::ScaleCopy() >>"), RThread().Id().operator TUint())); + + iVFUpdate = aVFUpdate; + iVFSize = aSize; + if ( iSecondVFBuffer && !iFirstVFBuffer ) + { + iVFbitmap = iSecondVfBuf; + iSecondVFBuffer = EFalse; + iFirstVFBuffer = ETrue; + } + else + { + iVFbitmap = iFirstVfBuf; + iFirstVFBuffer = EFalse; + } + //If Scaling is ongoing + if ( iActiveWaitScale->IsActive() ) + { + __IF_DEBUG(Print(_L("VideoSource [%d]: CMultiframeProvider::ScaleCopy(): active, storing size"), RThread().Id().operator TUint())); + iWantedVFSize = aSize; + } + else + { + __IF_DEBUG(Print(_L("VideoSource [%d]: CMultiframeProvider::ScaleCopy(): scaling NOW"), RThread().Id().operator TUint())); + iActiveWaitScale->InitializeWaiter( &VFRescalingFinished ); + TInt result( iVFbitmap->Bitmap().Resize( aSize ) ); + __IF_DEBUG(Print(_L("VideoSource [%d]: CMultiframeProvider::ScaleCopy() result %d <<"), RThread().Id().operator TUint(), result)); + if ( result != KErrNone ) + { + iActiveWaitScale->Signal( result ); + } + else + { + iVtImageScalerScale->Scale( *iScaled, *iVFbitmap ); + } + } + } +// ----------------------------------------------------------------------------- +// CMultiframeProvider::NextFrame() +// ----------------------------------------------------------------------------- +// +void CMultiframeProvider::NextFrame() + { + iFreezeCS.Wait(); + iInitialization = EFalse; + __IF_DEBUG(Print(_L("VideoSource[%d]: CMultiframeProvider::NextFrame() >>"), RThread().Id().operator TUint())); + + if ( iNumOfConsumers < 1 ) + { + __IF_DEBUG(Print(_L("VideoSource[%d]: CMultiframeProvider::NextFrame() Consumer < 1>>"), RThread().Id().operator TUint())); + iFreezeCS.Signal(); + return; + } + + if (iCount > 1 && !iActiveWaitInit->IsActive() ) + { + if (iWaitForConverting) + { + __IF_DEBUG(Print(_L("VideoSource[%d]: CMultiframeProvider::NextFrame() Because CMultiframeloopAO::RunL is executing, so Signal is not needed"), RThread().Id().operator TUint())); + } + else + { + iLoopAo->Signal(); + } + } + __IF_DEBUG(Print(_L("VideoSource[%d]: CMultiframeProvider::NextFrame() <<"), RThread().Id().operator TUint())); + iFreezeCS.Signal(); + } + +// ----------------------------------------------------------------------------- +// CMultiframeProvider::IncreaseDataConsumer() +// ----------------------------------------------------------------------------- +// +void CMultiframeProvider::IncreaseDataConsumer() + { + iFreezeCS.Wait(); + __IF_DEBUG(Print(_L("VideoSource[%d]: CMultiframeProvider::IncreaseDataConsumer() >>"), RThread().Id().operator TUint())); + ++iNumOfConsumers; + iFreezeCS.Signal(); + __IF_DEBUG(Print(_L("VideoSource[%d]: CMultiframeProvider::IncreaseDataConsumer() <<"), RThread().Id().operator TUint())); + } + +// ----------------------------------------------------------------------------- +// CMultiframeProvider::DecreaseDataConsumer() +// ----------------------------------------------------------------------------- +// +void CMultiframeProvider::DecreaseDataConsumer() + { + iFreezeCS.Wait(); + __IF_DEBUG(Print(_L("VideoSource[%d]: CMultiframeProvider::DecreaseDataConsumer() >>"), RThread().Id().operator TUint())); + --iNumOfConsumers; + if ( iNumOfConsumers < 1 ) + { + iLoopAo->CancelDataLoop(); + iDataTimer->CancelTimeLoop(); + } + __IF_DEBUG(Print(_L("VideoSource[%d]: CMultiframeProvider::DecreaseDataConsumer() <<"), RThread().Id().operator TUint())); + iFreezeCS.Signal(); + } +// ----------------------------------------------------------------------------- +// CMultiframeProvider::ScaleVF( const TSize& aSize ) +// ----------------------------------------------------------------------------- +// +void CMultiframeProvider::ScaleVF( const TSize& aSize ) + { + __IF_DEBUG(Print(_L("VideoSource[%d]: CMultiframeProvider::ScaleVF() >>"), RThread().Id().operator TUint())); + iActiveWaitScale->InitializeWaiter( &VFRescalingFinished ); + TInt result( iVFbitmap->Bitmap().Resize( aSize ) ); + ClearVFScalingTargetSize(); + if ( result != KErrNone ) + { + iActiveWaitScale->Signal( result ); + } + else + { + iVtImageScalerScale->Scale( *iScaled, *iVFbitmap ); + } + __IF_DEBUG(Print(_L("VideoSource[%d]: CMultiframeProvider::ScaleVF() result %d <<"), RThread().Id().operator TUint(), result)); + } + +// ----------------------------------------------------------------------------- +// CMultiframeProvider::VFRescalingFinished( TInt aError ) +// ----------------------------------------------------------------------------- +// +void CMultiframeProvider::VFRescalingFinished( TInt aError ) + { + __IF_DEBUG(Print(_L("VideoSource[%d]: CMultiframeProvider::VFRescalingFinished() >>"), RThread().Id().operator TUint())); + if ( aError == KErrNone ) + { + if ( iWantedVFSize != TSize() ) + { + __IF_DEBUG(Print(_L("VideoSource[%d]: CMultiframeProvider::VFRescalingFinished() REScaling needed"), RThread().Id().operator TUint())); + ScaleVF( iWantedVFSize ); + ClearVFScalingTargetSize(); + } + else + { + iDataTimer->CancelTimeLoop(); + + if ( !iIsVfStopped && !iVFUpdate ) + { + //Normally, VF and VS work + iVFCurrent = iVFbitmap; + iYUVBitMap = iScaled; + iDataTimer->LocalBuffer(iVFCurrent); + iDataTimer->RemoteBuffer(iYUVBitMap); + __IF_DEBUG(Print(_L("VideoSource[%d]: CMultiframeProvider::ScalecopyRemoteAndUpdate() normal, iFrameUpdateTime %d>>"), RThread().Id().operator TUint(), + iFrameUpdateTime.Int64())); + iDataTimer->Activate(iFrameUpdateTime, iInitialization, iVFUpdate); + } + else if ( iIsVfStopped && !iVFUpdate ) + { + //VF doesn't work. + iYUVBitMap = iScaled; + iDataTimer->RemoteBuffer(iYUVBitMap); + __IF_DEBUG(Print(_L("VideoSource[%d]: CMultiframeProvider::ScalecopyRemoteAndUpdate() VF Stop, iFrameUpdateTime %d>>"), RThread().Id().operator TUint(), + iFrameUpdateTime.Int64())); + iDataTimer->Activate( iFrameUpdateTime, iInitialization, iVFUpdate); + } + else if ( iIsVfStopped && iVFUpdate ) + { + //VF restart + iIsVfStopped = EFalse; + iVFUpdate = EFalse; + iVFCurrent = iVFbitmap; + iYUVBitMap = iScaled; + iDataTimer->LocalBuffer(iVFCurrent); + iDataTimer->RemoteBuffer(iYUVBitMap); + __IF_DEBUG(Print(_L("VideoSource[%d]: CMultiframeProvider::ScalecopyRemoteAndUpdate() VF Restart iFrameUpdateTime 1>>"), + RThread().Id().operator TUint())); + iDataTimer->Activate(1, iInitialization, iVFUpdate); + } + else + { + //maybe this condition never execute. + iVFCurrent = iVFbitmap; + iDataTimer->LocalBuffer(iVFCurrent); + __IF_DEBUG(Print(_L("VideoSource[%d]: CMultiframeProvider::ScalecopyRemoteAndUpdate() last one, iFrameUpdateTime %d>>"), RThread().Id().operator TUint(), + iFrameUpdateTime.Int64())); + iDataTimer->Activate( 1, iInitialization, iVFUpdate); + } + } + } +#if 0 + else if ( ( aError == KErrCancel ) ) + { + __IF_DEBUG(Print(_L("VideoSource[%d]: CMultiframeProvider::VFRescalingFinished() CANCEL"), RThread().Id().operator TUint())); + } + else if( aError != KErrCancel ) // If KErrCancel, then ignore error! + { + iObserver->NotifyImageHandlingError( aError ); + } +#endif + else + { + iObserver->NotifyImageHandlingError( aError ); + } + + __IF_DEBUG(Print(_L("VideoSource[%d]: CMultiframeProvider::VFRescalingFinished() err %d <<"), RThread().Id().operator TUint(), aError)); + } + +// ----------------------------------------------------------------------------- +// CMultiframeProvider::IsVFStopped() +// ----------------------------------------------------------------------------- +// +TBool CMultiframeProvider::IsVFStopped() + { + __IF_DEBUG(Print(_L("VideoSource[%d]: CMultiframeProvider::IsVFStopped() >>"), RThread().Id().operator TUint())); + __IF_DEBUG(Print(_L("VideoSource[%d]: CMultiframeProvider::IsVFStopped() <<"), RThread().Id().operator TUint())); + return iIsVfStopped; + } + +// ----------------------------------------------------------------------------- +// CMultiframeProvider::SetVFStop() +// ----------------------------------------------------------------------------- +// +void CMultiframeProvider::SetVFStop() + { + __IF_DEBUG(Print(_L("VideoSource[%d]: CMultiframeProvider::SetVFStop() >>"), RThread().Id().operator TUint())); + iIsVfStopped = ETrue; + __IF_DEBUG(Print(_L("VideoSource[%d]: CMultiframeProvider::SetVFStop() <<"), RThread().Id().operator TUint())); + } + +// ----------------------------------------------------------------------------- +// CMultiframeProvider::WaitForConverting() +// ----------------------------------------------------------------------------- +// +void CMultiframeProvider::WaitForConverting() + { + __IF_DEBUG(Print(_L("VideoSource[%d]: CMultiframeProvider::WaitForConverting() >>"), RThread().Id().operator TUint())); + iWaitForConverting = ETrue; + __IF_DEBUG(Print(_L("VideoSource[%d]: CMultiframeProvider::WaitForConverting() <<"), RThread().Id().operator TUint())); + } + +// ----------------------------------------------------------------------------- +// CMultiframeProvider::WaitForConverting() +// ----------------------------------------------------------------------------- +// +void CMultiframeProvider::ReleaseForConverting() + { + __IF_DEBUG(Print(_L("VideoSource[%d]: CMultiframeProvider::ReleaseForConverting() >>"), RThread().Id().operator TUint())); + iWaitForConverting = EFalse; + __IF_DEBUG(Print(_L("VideoSource[%d]: CMultiframeProvider::ReleaseForConverting() <<"), RThread().Id().operator TUint())); + } + +// ----------------------------------------------------------------------------- +// CMultiframeProvider::ClearVFScalingTargetSize() +// ----------------------------------------------------------------------------- +// +void CMultiframeProvider::ClearVFScalingTargetSize() + { + __IF_DEBUG(Print(_L("VideoSource[%d]: CMultiframeProvider::ClearVFScalingTargetSize() >>"), RThread().Id().operator TUint())); + iWantedVFSize = TSize(); + __IF_DEBUG(Print(_L("VideoSource[%d]: CMultiframeProvider::ClearVFScalingTargetSize() <<"), RThread().Id().operator TUint())); + } + +// ----------------------------------------------------------------------------- +// CMultiframeProvider::CancelInitializing() +// ----------------------------------------------------------------------------- +// +TBool CMultiframeProvider::CancelInitializing() + { + __IF_DEBUG(Print(_L("VideoSource[%d]: CMultiframeProvider::CancelInitializing() >>"), RThread().Id().operator TUint())); + TBool lResult = EFalse; + + if ( NULL == iImageDecoder ) + { + __IF_DEBUG(Print(_L("VideoSource[%d]: CMultiframeProvider::CancelInitializing() iImageDecoder is NULL ==="), RThread().Id().operator TUint())); + // In this condition, Convert is already finished + if ( iVtImageScalerInit->IsActive() ) + { + __IF_DEBUG(Print(_L("VideoSource[%d] Line[%d]: CMultiframeProvider::CancelInitializing() iVtImageScalerInit->Cancel ==="), + RThread().Id().operator TUint(), __LINE__)); + iVtImageScalerInit->Cancel(); + } + else if ( iActiveWaitInitScale->IsActive() ) + { + __IF_DEBUG(Print(_L("VideoSource[%d] Line[%d]: CMultiframeProvider::CancelInitializing() iActiveWaitInitScale->Cancel ==="), + RThread().Id().operator TUint(), __LINE__)); + iActiveWaitInitScale->Cancel(); + } + else if ( iVtImageScalerScale->IsActive() ) + { + __IF_DEBUG(Print(_L("VideoSource[%d] Line[%d]: CMultiframeProvider::CancelInitializing() iVtImageScalerScale->Cancel ==="), + RThread().Id().operator TUint(), __LINE__)); + iVtImageScalerScale->Cancel(); + } + else if ( iActiveWaitScale->IsActive() ) + { + __IF_DEBUG(Print(_L("VideoSource[%d] Line[%d]: CMultiframeProvider::CancelInitializing() iActiveWaitScale->Cancel ==="), + RThread().Id().operator TUint(), __LINE__)); + iActiveWaitScale->Cancel(); + } + else + { + //In this condition, the convert,scale,copyScale were finished, + //so do nothing, Waiting for InitializeReady() + __IF_DEBUG(Print(_L("VideoSource[%d] Line[%d]: CMultiframeProvider::CancelInitializing() Nothong to do,wait finish ==="), + RThread().Id().operator TUint(), __LINE__)); + } + } + else + { + __IF_DEBUG(Print(_L("VideoSource[%d]: CMultiframeProvider::CancelInitializing() cancel convert ==="), RThread().Id().operator TUint())); + //Convert is not finished, so we can cancel it, and return ETrue + iImageDecoder->Cancel(); + lResult = ETrue; + } + + __IF_DEBUG(Print(_L("VideoSource[%d]: CMultiframeProvider::CancelInitializing() <<"), RThread().Id().operator TUint())); + return lResult; + } + +// ========================== OTHER EXPORTED FUNCTIONS ========================= + +// End of File +