--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/videditor/VideoEditorCommon/src/VeiImageClipGenerator.cpp Fri Jan 29 14:08:33 2010 +0200
@@ -0,0 +1,999 @@
+/*
+* Copyright (c) 2010 Ixonos Plc.
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of the "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:
+* Ixonos Plc
+*
+* Description:
+*
+*/
+
+
+
+#include "VeiImageClipGenerator.h"
+
+#include <VedMovie.h>
+#include <fbs.h>
+#include <bitdev.h>
+#include <gdi.h>
+#include <aknutils.h>
+#include <ImageConversion.h>
+#include <BitmapTransforms.h>
+
+#define KMiddleFrameDuration TTimeIntervalMicroSeconds(1000000)
+
+const TInt KNumberOfTransitionFrames = 10;
+
+EXPORT_C CVeiImageClipGenerator* CVeiImageClipGenerator::NewL(const TDesC& aFilename,
+ const TSize& aMaxResolution,
+ const TTimeIntervalMicroSeconds& aDuration,
+ const TRgb& aBackgroundColor,
+ TDisplayMode aMaxDisplayMode,
+ RFs& aFs,
+ MVeiImageClipGeneratorObserver& aObserver)
+ {
+ CVeiImageClipGenerator* self =
+ CVeiImageClipGenerator::NewLC(aFilename, aMaxResolution, aDuration, aBackgroundColor, aMaxDisplayMode, aFs, aObserver);
+ CleanupStack::Pop(self);
+ return self;
+ }
+
+
+EXPORT_C CVeiImageClipGenerator* CVeiImageClipGenerator::NewLC(const TDesC& aFilename,
+ const TSize& aMaxResolution,
+ const TTimeIntervalMicroSeconds& aDuration,
+ const TRgb& aBackgroundColor,
+ TDisplayMode aMaxDisplayMode,
+ RFs& aFs,
+ MVeiImageClipGeneratorObserver& aObserver)
+ {
+ CVeiImageClipGenerator* self = new (ELeave) CVeiImageClipGenerator(aDuration, aBackgroundColor, aMaxResolution);
+ CleanupStack::PushL(self);
+ self->ConstructL(aFilename, aObserver, aMaxDisplayMode, aFs);
+ return self;
+ }
+
+
+CVeiImageClipGenerator::CVeiImageClipGenerator(const TTimeIntervalMicroSeconds& aDuration,
+ const TRgb& aBackgroundColor,
+ const TSize& aMaxResolution)
+ : iReady(EFalse), iMaxResolution(aMaxResolution), iBackgroundColor(aBackgroundColor), iInitializing(ETrue)
+ {
+ __ASSERT_ALWAYS(iMaxResolution.iHeight >= 0, TVedPanic::Panic(TVedPanic::EImageClipGeneratorIllegalMaxResolution));
+ __ASSERT_ALWAYS(iMaxResolution.iWidth >= 0, TVedPanic::Panic(TVedPanic::EImageClipGeneratorIllegalMaxResolution));
+
+ SetDuration(aDuration);
+
+ iInitializing = EFalse;
+ }
+
+
+void CVeiImageClipGenerator::ConstructL(const TDesC& aFilename,
+ MVeiImageClipGeneratorObserver& aObserver,
+ TDisplayMode aMaxDisplayMode, RFs& aFs)
+ {
+ iDecodeOperation = CVeiImageClipDecodeOperation::NewL(*this, aFilename, aObserver, aFs);
+ iFrameOperation = CVeiImageClipFrameOperation::NewL(*this);
+
+ iFilename = aFilename.AllocL();
+
+ TParse parse;
+ parse.Set(aFilename, 0, 0);
+ iDescriptiveName = parse.Name().AllocL();
+
+ iDecodeOperation->StartOperationL(iMaxResolution, aMaxDisplayMode);
+ }
+
+
+EXPORT_C CVeiImageClipGenerator::~CVeiImageClipGenerator()
+ {
+ delete iDecodeOperation;
+ delete iFrameOperation;
+ delete iDescriptiveName;
+ delete iBitmap;
+ delete iMask;
+ delete iFilename;
+ }
+
+
+EXPORT_C TPtrC CVeiImageClipGenerator::DescriptiveName() const
+ {
+ __ASSERT_ALWAYS(iReady,
+ TVedPanic::Panic(TVedPanic::EImageClipGeneratorNotReady));
+
+ return *iDescriptiveName;
+ }
+
+
+EXPORT_C TUid CVeiImageClipGenerator::Uid() const
+ {
+ return KUidImageClipGenerator;
+ }
+
+EXPORT_C TTimeIntervalMicroSeconds CVeiImageClipGenerator::Duration() const
+ {
+ __ASSERT_ALWAYS(iReady,
+ TVedPanic::Panic(TVedPanic::EImageClipGeneratorNotReady));
+
+ return iDuration;
+ }
+
+
+EXPORT_C TInt CVeiImageClipGenerator::VideoFrameCount() const
+ {
+ __ASSERT_ALWAYS(iReady,
+ TVedPanic::Panic(TVedPanic::EImageClipGeneratorNotReady));
+
+ TInt frameCount = 0;
+
+ TInt maxFramerate = 10;
+ if (IsInserted())
+ {
+ maxFramerate = Movie()->MaximumFramerate();
+ }
+
+ TTimeIntervalMicroSeconds frameDuration(TInt64(1000000 / maxFramerate));
+ if (iDuration.Int64() < (TInt64(KNumberOfTransitionFrames * 2 + 1) * frameDuration.Int64()))
+ {
+ frameCount = (static_cast<TInt>(iDuration.Int64() / frameDuration.Int64()));
+ if ((iDuration.Int64() % frameDuration.Int64()) != 0)
+ {
+ frameCount++;
+ }
+ }
+ else
+ {
+ frameCount = KNumberOfTransitionFrames * 2;
+ TTimeIntervalMicroSeconds middleTime(iDuration.Int64() - (TInt64(KNumberOfTransitionFrames * 2) * frameDuration.Int64()));
+ frameCount += (static_cast<TInt32>(middleTime.Int64() / KMiddleFrameDuration.Int64()));
+ if ((middleTime.Int64() % KMiddleFrameDuration.Int64()) != 0)
+ {
+ frameCount++;
+ }
+ }
+ return frameCount;
+ }
+
+
+EXPORT_C TTimeIntervalMicroSeconds CVeiImageClipGenerator::VideoFrameStartTime(TInt aIndex) const
+ {
+ __ASSERT_ALWAYS(iReady,
+ TVedPanic::Panic(TVedPanic::EImageClipGeneratorNotReady));
+ __ASSERT_ALWAYS(aIndex >= 0 && aIndex < VideoFrameCount(), TVedPanic::Panic(TVedPanic::EVideoClipGeneratorIllegalVideoFrameIndex));
+
+ TInt maxFramerate = 10;
+ if (IsInserted())
+ {
+ maxFramerate = Movie()->MaximumFramerate();
+ }
+
+ TTimeIntervalMicroSeconds frameDuration(TInt64(1000000 / maxFramerate));
+ TTimeIntervalMicroSeconds finalThreshold(iDuration.Int64() - TInt64(KNumberOfTransitionFrames) * frameDuration.Int64());
+ TTimeIntervalMicroSeconds startThreshold(TInt64(KNumberOfTransitionFrames) * frameDuration.Int64());
+ TTimeIntervalMicroSeconds startTime(-1);
+ TInt frameCount = VideoFrameCount();
+
+
+ if (frameCount < (KNumberOfTransitionFrames * 2 + 1))
+ {
+ // Special case: less than KNumberOfTransitionFrames frames in the movie
+ startTime = TTimeIntervalMicroSeconds(TInt64(aIndex) * frameDuration.Int64());
+ }
+ else if (aIndex < KNumberOfTransitionFrames)
+ {
+ // Start frames
+ startTime = TTimeIntervalMicroSeconds(TInt64(aIndex) * frameDuration.Int64());
+ }
+ else if (aIndex >= (frameCount - KNumberOfTransitionFrames))
+ {
+ // End frames
+ startTime = TTimeIntervalMicroSeconds(
+ static_cast<TInt64>((aIndex - frameCount) + KNumberOfTransitionFrames)
+ * frameDuration.Int64() + finalThreshold.Int64() );
+ }
+ else
+ {
+ // Middle frames
+ startTime = TTimeIntervalMicroSeconds(startThreshold.Int64()
+ + TInt64(aIndex- KNumberOfTransitionFrames) * KMiddleFrameDuration.Int64());
+ }
+
+ return startTime;
+ }
+
+
+EXPORT_C TTimeIntervalMicroSeconds CVeiImageClipGenerator::VideoFrameEndTime(TInt aIndex) const
+ {
+ __ASSERT_ALWAYS(iReady,
+ TVedPanic::Panic(TVedPanic::EImageClipGeneratorNotReady));
+ __ASSERT_ALWAYS(aIndex >= 0 && aIndex < VideoFrameCount(), TVedPanic::Panic(TVedPanic::EVideoClipGeneratorIllegalVideoFrameIndex));
+
+ if (aIndex == VideoFrameCount() - 1)
+ {
+ return iDuration;
+ }
+
+ TInt maxFramerate = 10;
+ if (IsInserted())
+ {
+ maxFramerate = Movie()->MaximumFramerate();
+ }
+
+ TTimeIntervalMicroSeconds frameDuration(TInt64(1000000 / maxFramerate));
+ TTimeIntervalMicroSeconds finalThreshold(iDuration.Int64() - TInt64(KNumberOfTransitionFrames) * frameDuration.Int64());
+ TTimeIntervalMicroSeconds startThreshold(TInt64(KNumberOfTransitionFrames) * frameDuration.Int64());
+ TTimeIntervalMicroSeconds endTime(-1);
+
+
+ TInt frameCount = VideoFrameCount();
+
+ if (frameCount < (KNumberOfTransitionFrames * 2 + 1))
+ {
+ // Special case: less than KNumberOfTransitionFrames frames in the movie
+ endTime = TTimeIntervalMicroSeconds(TInt64(aIndex + 1) * frameDuration.Int64());
+ }
+ else if (aIndex < KNumberOfTransitionFrames)
+ {
+ // start frames
+ endTime = TTimeIntervalMicroSeconds(TInt64(aIndex + 1) * frameDuration.Int64());
+ }
+ else if (aIndex > (frameCount - KNumberOfTransitionFrames))
+ {
+ // end frames
+ endTime = TTimeIntervalMicroSeconds(TInt64((aIndex - frameCount)
+ + KNumberOfTransitionFrames) * frameDuration.Int64()
+ + finalThreshold.Int64());
+ }
+ else
+ {
+ // middle frames
+ endTime = TTimeIntervalMicroSeconds(startThreshold.Int64()
+ + TInt64(aIndex - (KNumberOfTransitionFrames - 1))
+ * KMiddleFrameDuration.Int64());
+
+ if (endTime.Int64() >= finalThreshold.Int64())
+ {
+ // last of the middle frames may be shorter than normal
+ endTime = finalThreshold;
+ }
+ }
+ return endTime;
+ }
+
+
+EXPORT_C TTimeIntervalMicroSeconds CVeiImageClipGenerator::VideoFrameDuration(TInt aIndex) const
+ {
+ __ASSERT_ALWAYS(iReady,
+ TVedPanic::Panic(TVedPanic::EImageClipGeneratorNotReady));
+ __ASSERT_ALWAYS(aIndex >= 0 && aIndex < VideoFrameCount(), TVedPanic::Panic(TVedPanic::EVideoClipGeneratorIllegalVideoFrameIndex));
+
+
+ // check maximum framerate
+ TInt maxFramerate = 10;
+ if (IsInserted())
+ {
+ maxFramerate = Movie()->MaximumFramerate();
+ }
+
+ // calculate some timing values.
+ TTimeIntervalMicroSeconds frameDuration(TInt64(1000000 / maxFramerate));
+ TTimeIntervalMicroSeconds finalThreshold(iDuration.Int64() - TInt64(KNumberOfTransitionFrames) * frameDuration.Int64());
+ TTimeIntervalMicroSeconds startThreshold(TInt64(KNumberOfTransitionFrames) * frameDuration.Int64());
+
+
+ TInt frameCount = VideoFrameCount();
+ TInt finalThresholdIndex = GetVideoFrameIndex(finalThreshold);
+
+ if ((frameCount < (KNumberOfTransitionFrames * 2 + 1)) && (aIndex == (frameCount - 1)))
+ {
+ // Special case: short clip with only frames that have max framerate
+ // - all of the frames are of equal duration (frameDuration) except
+ // the last one.
+ frameDuration = TTimeIntervalMicroSeconds(iDuration.Int64() - (TInt64(frameCount - 1) * frameDuration.Int64()));
+ }
+ else if (aIndex >= KNumberOfTransitionFrames && aIndex < finalThresholdIndex)
+ {
+ if (aIndex == (finalThresholdIndex - 1))
+ {
+ // Last one of the middle frames
+ frameDuration = TTimeIntervalMicroSeconds(finalThreshold.Int64() - VideoFrameStartTime(aIndex).Int64());
+ }
+ else
+ {
+ // Ordinary middle frame
+ frameDuration = KMiddleFrameDuration;
+ }
+ }
+ return frameDuration;
+ }
+
+EXPORT_C TBool CVeiImageClipGenerator::VideoFrameIsIntra(TInt aIndex) const
+ {
+ __ASSERT_ALWAYS(iReady,
+ TVedPanic::Panic(TVedPanic::EImageClipGeneratorNotReady));
+ if (aIndex == 0)
+ {
+ return ETrue;
+ }
+ return EFalse;
+ }
+
+EXPORT_C TInt CVeiImageClipGenerator::VideoFirstFrameComplexityFactor() const
+ {
+ __ASSERT_ALWAYS(iReady,
+ TVedPanic::Panic(TVedPanic::EImageClipGeneratorNotReady));
+ return iFirstFrameComplexityFactor;
+ }
+
+EXPORT_C TInt CVeiImageClipGenerator::VideoFrameDifferenceFactor(TInt aIndex) const
+ {
+ __ASSERT_ALWAYS(iReady,
+ TVedPanic::Panic(TVedPanic::EImageClipGeneratorNotReady));
+ __ASSERT_ALWAYS(aIndex >= 0 && aIndex < VideoFrameCount(), TVedPanic::Panic(TVedPanic::EVideoClipGeneratorIllegalVideoFrameIndex));
+
+ if (aIndex == 0)
+ {
+ return 1000;
+ }
+ else
+ {
+ return 0;
+ }
+ }
+
+
+EXPORT_C TInt CVeiImageClipGenerator::GetVideoFrameIndex(TTimeIntervalMicroSeconds aTime) const
+ {
+ __ASSERT_ALWAYS(iReady,
+ TVedPanic::Panic(TVedPanic::EImageClipGeneratorNotReady));
+ __ASSERT_ALWAYS(aTime.Int64() >= 0, TVedPanic::Panic(TVedPanic::EVideoClipInfoIllegalVideoFrameTime));
+ __ASSERT_ALWAYS(aTime.Int64() <= iDuration.Int64(), TVedPanic::Panic(TVedPanic::EVideoClipInfoIllegalVideoFrameTime));
+
+ TInt index = -1;
+
+ TInt maxFramerate = 10;
+ if (IsInserted())
+ {
+ maxFramerate = Movie()->MaximumFramerate();
+ }
+
+ TTimeIntervalMicroSeconds frameDuration(TInt64(1000000 / maxFramerate));
+ TTimeIntervalMicroSeconds finalThreshold(
+ iDuration.Int64() - TInt64(KNumberOfTransitionFrames) * frameDuration.Int64());
+ TTimeIntervalMicroSeconds startThreshold(
+ TInt64(KNumberOfTransitionFrames) * frameDuration.Int64());
+
+ if (iDuration <= (TInt64(KNumberOfTransitionFrames * 2) * frameDuration.Int64()))
+ {
+ index = static_cast<TInt>(aTime.Int64() / frameDuration.Int64());
+ }
+ else if (aTime < startThreshold)
+ {
+ index = static_cast<TInt>(aTime.Int64() / frameDuration.Int64());
+ }
+ else if (aTime >= finalThreshold)
+ {
+ TTimeIntervalMicroSeconds middleDuration(finalThreshold.Int64() - startThreshold.Int64());
+ TInt numberOfMiddleFrames =
+ static_cast<TInt32>(middleDuration.Int64() / KMiddleFrameDuration.Int64());
+ if (middleDuration.Int64() % KMiddleFrameDuration.Int64() != 0)
+ {
+ numberOfMiddleFrames++;
+ }
+
+ index = KNumberOfTransitionFrames + numberOfMiddleFrames
+ + static_cast<TInt>((aTime.Int64() - finalThreshold.Int64()) / frameDuration.Int64());
+ }
+ else
+ {
+ index = KNumberOfTransitionFrames
+ + static_cast<TInt>((aTime.Int64() - startThreshold.Int64()) / KMiddleFrameDuration.Int64());
+ }
+
+ return index;
+ }
+
+
+EXPORT_C void CVeiImageClipGenerator::GetFrameL(MVedVideoClipGeneratorFrameObserver& aObserver,
+ TInt aIndex, TSize* const aResolution,
+ TDisplayMode aDisplayMode, TBool aEnhance,
+ TInt aPriority)
+ {
+ __ASSERT_ALWAYS(iReady,
+ TVedPanic::Panic(TVedPanic::EImageClipGeneratorNotReady));
+ __ASSERT_ALWAYS((aIndex >= 0 && aIndex < VideoFrameCount()) ||
+ aIndex == KFrameIndexBestThumb,
+ TVedPanic::Panic(TVedPanic::EVideoClipGeneratorIllegalVideoFrameIndex));
+ __ASSERT_ALWAYS((aResolution->iHeight <= iMaxResolution.iHeight &&
+ aResolution->iWidth <= iMaxResolution.iWidth),
+ TVedPanic::Panic(TVedPanic::EVideoClipGeneratorIllegalFrameResolution));
+ __ASSERT_ALWAYS((aResolution->iHeight >= 0 && aResolution->iWidth >= 0),
+ TVedPanic::Panic(TVedPanic::EVideoClipGeneratorIllegalFrameResolution));
+
+
+ TDisplayMode displayMode = aDisplayMode;
+
+ // check validity of thumbnail and associated operation
+ if(aEnhance) // for saving to file
+ {
+ if(displayMode == ENone) // if no preference
+ {
+ displayMode = EColor16M; // 24-bit color image for enhancement
+ }
+ else if(displayMode != EColor16M) // invalid combination
+ {
+ User::Leave(KErrNotSupported);
+ }
+ }
+ else // for screen display
+ {
+ if(displayMode == ENone) // if no preference
+ {
+ displayMode = EColor64K; // 16-bit image
+ }
+ }
+
+ CFbsBitmap* destBitmap = new (ELeave) CFbsBitmap;
+ CleanupStack::PushL(destBitmap);
+ User::LeaveIfError(destBitmap->Create(*aResolution, displayMode));
+ CleanupStack::Pop(destBitmap);
+
+ iFrameOperation->StartOperationL(&aObserver, aIndex, aEnhance, iBitmap,
+ destBitmap, iMask, aPriority);
+ }
+
+
+EXPORT_C void CVeiImageClipGenerator::CancelFrame()
+ {
+ iFrameOperation->Cancel();
+ }
+
+
+EXPORT_C void CVeiImageClipGenerator::SetDuration(const TTimeIntervalMicroSeconds& aDuration)
+ {
+ __ASSERT_ALWAYS(iReady || iInitializing,
+ TVedPanic::Panic(TVedPanic::EImageClipGeneratorNotReady));
+ __ASSERT_ALWAYS(aDuration.Int64() > 0,
+ TVedPanic::Panic(TVedPanic::EVideoClipGeneratorIllegalDuration));
+
+ iDuration = aDuration;
+
+ if (!iInitializing)
+ {
+ ReportDurationChanged();
+ }
+ }
+
+
+EXPORT_C void CVeiImageClipGenerator::SetBackgroundColor(const TRgb& aBackgroundColor)
+ {
+ __ASSERT_ALWAYS(iReady,
+ TVedPanic::Panic(TVedPanic::EImageClipGeneratorNotReady));
+
+ iBackgroundColor = aBackgroundColor;
+ ReportSettingsChanged();
+ }
+
+EXPORT_C const TRgb& CVeiImageClipGenerator::BackgroundColor() const
+ {
+ __ASSERT_ALWAYS(iReady,
+ TVedPanic::Panic(TVedPanic::EImageClipGeneratorNotReady));
+
+ return iBackgroundColor;
+ }
+
+EXPORT_C TPtrC CVeiImageClipGenerator::ImageFilename() const
+ {
+ __ASSERT_ALWAYS(iReady,
+ TVedPanic::Panic(TVedPanic::EImageClipGeneratorNotReady));
+ return *iFilename;
+ }
+
+void CVeiImageClipGenerator::UpdateFirstFrameComplexityFactorL()
+ {
+ iFirstFrameComplexityFactor = CalculateFrameComplexityFactor(iBitmap);
+ }
+
+//////////////////////////////////////////////////////////////////////////
+// Decode operation
+//////////////////////////////////////////////////////////////////////////
+
+
+CVeiImageClipDecodeOperation* CVeiImageClipDecodeOperation::NewL(CVeiImageClipGenerator& aGenerator,
+ const TDesC& aFilename,
+ MVeiImageClipGeneratorObserver& aObserver,
+ RFs& aFs,
+ TInt aPriority)
+ {
+ CVeiImageClipDecodeOperation* self =
+ new (ELeave) CVeiImageClipDecodeOperation(aGenerator, aObserver, aPriority);
+ CleanupStack::PushL(self);
+ self->ConstructL(aFilename, aFs);
+ CleanupStack::Pop(self);
+ return self;
+ }
+
+
+CVeiImageClipDecodeOperation::CVeiImageClipDecodeOperation(CVeiImageClipGenerator& aGenerator,
+ MVeiImageClipGeneratorObserver& aObserver,
+ TInt aPriority)
+ : CActive(aPriority), iGenerator(aGenerator), iObserver(aObserver)
+ {
+ CActiveScheduler::Add(this);
+ }
+
+
+void CVeiImageClipDecodeOperation::ConstructL(const TDesC& aFilename, RFs& aFs)
+ {
+ iDecoder = CImageDecoder::FileNewL(aFs, aFilename);
+ }
+
+
+CVeiImageClipDecodeOperation::~CVeiImageClipDecodeOperation()
+ {
+ Cancel();
+
+ delete iDecoder;
+ iDecoder = 0;
+ delete iBitmap;
+ iBitmap = 0;
+ delete iMask;
+ iMask = 0;
+ }
+
+
+void CVeiImageClipDecodeOperation::DoCancel()
+ {
+ if (iDecoder)
+ {
+ iDecoder->Cancel();
+ }
+
+ delete iDecoder;
+ iDecoder = 0;
+
+ delete iBitmap;
+ iBitmap = 0;
+
+ delete iMask;
+ iMask = 0;
+
+ iObserver.NotifyImageClipGeneratorInitializationComplete(iGenerator, KErrCancel);
+ }
+
+
+void CVeiImageClipDecodeOperation::RunL()
+ {
+ /* Transfer ownership of iBitmap to generator. */
+ iGenerator.iBitmap = iBitmap;
+ iBitmap = 0;
+ iGenerator.iMask = iMask;
+ iMask = 0;
+ iGenerator.iReady = ETrue;
+ iGenerator.UpdateFirstFrameComplexityFactorL();
+
+ /* Notify observer. */
+ iObserver.NotifyImageClipGeneratorInitializationComplete(iGenerator, KErrNone);
+ delete iDecoder;
+ iDecoder = 0;
+ }
+
+TInt CVeiImageClipDecodeOperation::RunError(TInt aError)
+ {
+ if (iDecoder)
+ {
+ iDecoder->Cancel();
+ }
+ delete iDecoder;
+ iDecoder = 0;
+ delete iBitmap;
+ iBitmap = 0;
+ delete iMask;
+ iMask = 0;
+
+ iObserver.NotifyImageClipGeneratorInitializationComplete(iGenerator, aError);
+ return KErrNone;
+ }
+
+
+
+void CVeiImageClipDecodeOperation::StartOperationL(const TSize& aMaxResolution, TDisplayMode aDisplayMode)
+ {
+ __ASSERT_ALWAYS(!IsActive(), TVedPanic::Panic(TVedPanic::EInternal));
+
+ const TFrameInfo& info = iDecoder->FrameInfo();
+ TSize targetResolution(0, 0);
+ const TSize sourceResolution(info.iOverallSizeInPixels);
+
+ /* Calculate resolution. */
+
+ if ((sourceResolution.iWidth <= aMaxResolution.iWidth)
+ && (sourceResolution.iHeight <= aMaxResolution.iHeight))
+ {
+ targetResolution.iWidth = sourceResolution.iWidth;
+ targetResolution.iHeight = sourceResolution.iHeight;
+ }
+ else if (info.iFlags & TFrameInfo::EFullyScaleable)
+ {
+ if ((sourceResolution.iWidth * aMaxResolution.iHeight) >
+ (sourceResolution.iHeight * aMaxResolution.iWidth))
+ {
+ targetResolution.iWidth = aMaxResolution.iWidth;
+ targetResolution.iHeight =
+ (targetResolution.iWidth * sourceResolution.iHeight) / sourceResolution.iWidth;
+ }
+ else
+ {
+ targetResolution.iHeight = aMaxResolution.iHeight;
+ targetResolution.iWidth =
+ (targetResolution.iHeight * sourceResolution.iWidth) / sourceResolution.iHeight;
+ }
+ }
+ else
+ {
+ targetResolution.iWidth = (sourceResolution.iWidth / 8) + 1;
+ targetResolution.iHeight = (sourceResolution.iHeight / 8) + 1;
+
+ if ((targetResolution.iWidth < aMaxResolution.iWidth)
+ && (targetResolution.iHeight < aMaxResolution.iHeight))
+ {
+ targetResolution.iWidth = (sourceResolution.iWidth / 4) + 1;
+ targetResolution.iHeight = (sourceResolution.iHeight / 4) + 1;
+ }
+
+ if ((targetResolution.iWidth < aMaxResolution.iWidth)
+ && (targetResolution.iHeight < aMaxResolution.iHeight))
+ {
+ targetResolution.iWidth = (sourceResolution.iWidth / 2) + 1;
+ targetResolution.iHeight = (sourceResolution.iHeight / 2) + 1;
+ }
+
+ if ((targetResolution.iWidth < aMaxResolution.iWidth)
+ && (targetResolution.iHeight < aMaxResolution.iHeight))
+ {
+ targetResolution.iWidth = (sourceResolution.iWidth);
+ targetResolution.iHeight = (sourceResolution.iHeight);
+ }
+ }
+
+
+ iBitmap = new (ELeave) CFbsBitmap;
+ TInt err = iBitmap->Create(targetResolution, aDisplayMode);
+
+ if (err != KErrNone)
+ {
+ delete iBitmap;
+ iBitmap = 0;
+ iObserver.NotifyImageClipGeneratorInitializationComplete(iGenerator, err);
+ return;
+ }
+
+ if (info.iFlags & TFrameInfo::ETransparencyPossible)
+ {
+ iMask = new (ELeave) CFbsBitmap;
+ if (info.iFlags & TFrameInfo::EAlphaChannel)
+ {
+ err = iMask->Create(targetResolution, EGray256);
+ }
+ else
+ {
+ err = iMask->Create(targetResolution, EGray2);
+ }
+ }
+
+ if (err != KErrNone)
+ {
+ delete iBitmap;
+ iBitmap = 0;
+ delete iMask;
+ iMask = 0;
+ iObserver.NotifyImageClipGeneratorInitializationComplete(iGenerator, err);
+ return;
+ }
+
+ if (iMask != 0)
+ {
+ iDecoder->Convert(&iStatus, *iBitmap, *iMask);
+ }
+ else
+ {
+ iDecoder->Convert(&iStatus, *iBitmap);
+ }
+
+ SetActive();
+ }
+
+
+//////////////////////////////////////////////////////////////////////////
+// Frame operation
+//////////////////////////////////////////////////////////////////////////
+
+CVeiImageClipFrameOperation* CVeiImageClipFrameOperation::NewL(CVeiImageClipGenerator& aGenerator)
+ {
+ CVeiImageClipFrameOperation* self =
+ new (ELeave) CVeiImageClipFrameOperation(aGenerator);
+ CleanupStack::PushL(self);
+ self->ConstructL();
+ CleanupStack::Pop(self);
+ return self;
+ }
+
+
+CVeiImageClipFrameOperation::CVeiImageClipFrameOperation(CVeiImageClipGenerator& aGenerator)
+ : CActive(EPriorityStandard), iGenerator(aGenerator)
+ {
+ CActiveScheduler::Add(this);
+ }
+
+
+void CVeiImageClipFrameOperation::ConstructL()
+ {
+ }
+
+
+CVeiImageClipFrameOperation::~CVeiImageClipFrameOperation()
+ {
+ Cancel();
+ delete iScaler;
+ iScaler = 0;
+ delete iDestBitmap;
+ iDestBitmap = 0;
+ delete iScaledBitmap;
+ iScaledBitmap = 0;
+ delete iScaledMask;
+ iScaledMask = 0;
+
+ iSourceBitmap = 0;
+ iSourceMask = 0;
+ iObserver = 0;
+ }
+
+
+void CVeiImageClipFrameOperation::StartOperationL(MVedVideoClipGeneratorFrameObserver* aObserver,
+ TInt aIndex, TBool aEnhance,
+ CFbsBitmap* aSourceBitmap, CFbsBitmap* aDestBitmap,
+ CFbsBitmap* aSourceMask, TInt aPriority)
+ {
+ __ASSERT_ALWAYS(!IsActive(), TVedPanic::Panic(TVedPanic::EImageClipGeneratorFrameOperationAlreadyRunning));
+
+ iObserver = aObserver;
+ iSourceBitmap = aSourceBitmap;
+ iDestBitmap = aDestBitmap;
+ iSourceMask = aSourceMask;
+ iIndex = aIndex;
+ iEnhance = aEnhance;
+
+ SetPriority(aPriority);
+
+
+ TSize sourceRes = iSourceBitmap->SizeInPixels();
+ TSize destRes = iDestBitmap->SizeInPixels();
+ TSize movieRes = iGenerator.Movie()->Resolution();
+
+ TSize imageResInMovie(0,0);
+ if ((sourceRes.iWidth >= movieRes.iWidth) || (sourceRes.iHeight >= movieRes.iHeight))
+ {
+ // Downscaling
+ if ((sourceRes.iWidth * movieRes.iHeight) >
+ (sourceRes.iHeight * movieRes.iWidth))
+ {
+ imageResInMovie.iWidth = movieRes.iWidth;
+ imageResInMovie.iHeight =
+ (movieRes.iWidth * sourceRes.iHeight) / sourceRes.iWidth;
+ }
+ else
+ {
+ imageResInMovie.iHeight = movieRes.iHeight;
+ imageResInMovie.iWidth =
+ (movieRes.iHeight * sourceRes.iWidth) / sourceRes.iHeight;
+ }
+ }
+ else
+ {
+ // Upscaling - limit to a factor of two
+ if ((sourceRes.iWidth * movieRes.iHeight) >
+ (sourceRes.iHeight * movieRes.iWidth))
+ {
+ imageResInMovie.iWidth = Min(movieRes.iWidth, (sourceRes.iWidth * 2));
+ imageResInMovie.iHeight = (imageResInMovie.iWidth * sourceRes.iHeight) / sourceRes.iWidth;
+ }
+ else
+ {
+ imageResInMovie.iHeight = Min((sourceRes.iHeight * 2), movieRes.iHeight);
+ imageResInMovie.iWidth = (imageResInMovie.iHeight * sourceRes.iWidth) / sourceRes.iHeight;
+ }
+ }
+
+ TSize movieResInDestBitmap(-1,-1);
+ if ((movieRes.iWidth * destRes.iHeight) >
+ (movieRes.iHeight * destRes.iWidth))
+ {
+ movieResInDestBitmap.iWidth = destRes.iWidth;
+ movieResInDestBitmap.iHeight =
+ (movieResInDestBitmap.iWidth * movieRes.iHeight) / movieRes.iWidth;
+ }
+ else
+ {
+ movieResInDestBitmap.iHeight = destRes.iHeight;
+ movieResInDestBitmap.iWidth =
+ (movieResInDestBitmap.iHeight * movieRes.iWidth) / movieRes.iHeight;
+ }
+
+
+ TSize targetRes(imageResInMovie);
+ targetRes.iWidth = imageResInMovie.iWidth * movieResInDestBitmap.iWidth / movieRes.iWidth;
+ targetRes.iHeight = imageResInMovie.iHeight * movieResInDestBitmap.iHeight / movieRes.iHeight;
+
+ TSize cachedRes(-1, -1);
+ if (iScaledBitmap)
+ {
+ cachedRes = iScaledBitmap->SizeInPixels();
+ }
+
+ /* Check if we already have scaled this bitmap.*/
+ if ((cachedRes.iWidth == targetRes.iWidth) ||
+ (cachedRes.iHeight == targetRes.iHeight))
+ {
+ SetActive();
+ TRequestStatus* status = &iStatus;
+ User::RequestComplete(status, KErrNone);
+ return;
+ }
+ else if (iScaledBitmap)
+ {
+ delete iScaledBitmap;
+ iScaledBitmap = 0;
+ delete iScaledMask;
+ iScaledMask = 0;
+ }
+
+ delete iScaler;
+ iScaler = NULL;
+ iScaler = CBitmapScaler::NewL();
+
+ iScaledBitmap = new (ELeave) CFbsBitmap;
+ User::LeaveIfError(iScaledBitmap->Create(targetRes, iDestBitmap->DisplayMode()));
+ iScaler->Scale(&iStatus, *iSourceBitmap, *iScaledBitmap, ETrue);
+ SetActive();
+ }
+
+
+
+void CVeiImageClipFrameOperation::RunL()
+ {
+ if (!iNoScaling && iSourceMask && !iScaledMask)
+ {
+ /* Scale the mask. */
+ iScaledMask = new (ELeave) CFbsBitmap;
+ User::LeaveIfError(iScaledMask->Create(iScaledBitmap->SizeInPixels(), iSourceMask->DisplayMode()));
+ iScaler->Scale(&iStatus, *iSourceMask, *iScaledMask, ETrue);
+ SetActive();
+ return;
+ }
+
+ /* Select source. */
+ CFbsBitmap* bitmap = 0;
+ CFbsBitmap* mask = 0;
+
+ if (iScaledBitmap)
+ {
+ bitmap = iScaledBitmap;
+ }
+ else
+ {
+ bitmap = iSourceBitmap;
+ }
+
+ if (iScaledMask)
+ {
+ mask = iScaledMask;
+ }
+ else
+ {
+ mask = iSourceMask;
+ }
+
+
+ /* Initialize context. */
+ CFbsDevice* device = CFbsBitmapDevice::NewL(iDestBitmap);
+ CleanupStack::PushL(device);
+ CFbsBitGc* gc = NULL;
+ User::LeaveIfError(device->CreateContext(gc));
+
+ /* Calculate source point. */
+ TSize destRes = iDestBitmap->SizeInPixels();
+ TSize sourceRes = bitmap->SizeInPixels();
+ TPoint sourcePoint((destRes.iWidth - sourceRes.iWidth) / 2,
+ (destRes.iHeight - sourceRes.iHeight) / 2);
+
+ /* Draw background (this is relevant for scaled images and transparency). */
+ gc->SetBrushColor(iGenerator.BackgroundColor());
+ gc->SetBrushStyle(CGraphicsContext::ESolidBrush);
+ gc->DrawRect(TRect(TPoint(0, 0), destRes));
+
+ if (mask)
+ {
+ TRect sourceRect(bitmap->SizeInPixels());
+ gc->BitBltMasked(sourcePoint, bitmap, sourceRect, mask, EFalse);
+ }
+ else
+ {
+ gc->BitBlt(sourcePoint, bitmap);
+ }
+
+ delete gc;
+ CleanupStack::PopAndDestroy(device);
+
+ /* This transfers the bitmap ownership to the observer. */
+ iObserver->NotifyVideoClipGeneratorFrameCompleted(iGenerator, KErrNone, iDestBitmap);
+
+ delete iScaler;
+ iScaler = 0;
+
+ iSourceBitmap = 0;
+ iSourceMask = 0;
+ iDestBitmap = 0;
+ iObserver = 0;
+ iIndex = -1;
+ iNoScaling = EFalse;
+ }
+
+TInt CVeiImageClipFrameOperation::RunError(TInt aError)
+ {
+ iObserver->NotifyVideoClipGeneratorFrameCompleted(iGenerator, aError, NULL);
+
+ if (iScaler)
+ {
+ iScaler->Cancel();
+ }
+
+ delete iScaler;
+ iScaler = 0;
+ delete iScaledBitmap;
+ iScaledBitmap = 0;
+ delete iScaledMask;
+ iScaledMask = 0;
+ delete iDestBitmap;
+ iDestBitmap = 0;
+ iSourceBitmap = 0;
+ iSourceMask = 0;
+ iObserver = 0;
+ iIndex = -1;
+
+ return KErrNone;
+ }
+
+
+void CVeiImageClipFrameOperation::DoCancel()
+ {
+ iObserver->NotifyVideoClipGeneratorFrameCompleted(iGenerator, KErrCancel, 0);
+
+ if (iScaler)
+ {
+ iScaler->Cancel();
+ }
+
+ delete iScaler;
+ iScaler = 0;
+ delete iScaledBitmap;
+ iScaledBitmap = 0;
+ delete iScaledMask;
+ iScaledMask = 0;
+
+ delete iDestBitmap;
+ iDestBitmap = 0;
+ iSourceBitmap = 0;
+ iSourceMask = 0;
+ iObserver = 0;
+ iIndex = -1;
+ }
+// End of File
+