videditor/VideoEditorCommon/src/VeiImageClipGenerator.cpp
changeset 9 d87d32eab1a9
parent 0 951a5db380a0
equal deleted inserted replaced
0:951a5db380a0 9:d87d32eab1a9
     1 /*
       
     2 * Copyright (c) 2010 Ixonos Plc.
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of the "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - Initial contribution
       
    11 *
       
    12 * Contributors:
       
    13 * Ixonos Plc
       
    14 *
       
    15 * Description:  
       
    16 *
       
    17 */
       
    18 
       
    19 
       
    20 
       
    21 #include "VeiImageClipGenerator.h"
       
    22 
       
    23 #include <VedMovie.h>
       
    24 #include <fbs.h>
       
    25 #include <bitdev.h>
       
    26 #include <gdi.h>
       
    27 #include <aknutils.h>
       
    28 #include <ImageConversion.h>
       
    29 #include <BitmapTransforms.h>
       
    30 
       
    31 #define KMiddleFrameDuration TTimeIntervalMicroSeconds(1000000)
       
    32 
       
    33 const TInt KNumberOfTransitionFrames = 10;
       
    34 
       
    35 EXPORT_C CVeiImageClipGenerator* CVeiImageClipGenerator::NewL(const TDesC& aFilename,
       
    36 												     const TSize& aMaxResolution,
       
    37 													 const TTimeIntervalMicroSeconds& aDuration, 
       
    38 													 const TRgb& aBackgroundColor,
       
    39 													 TDisplayMode aMaxDisplayMode,
       
    40 													 RFs& aFs,
       
    41 													 MVeiImageClipGeneratorObserver& aObserver)
       
    42 	{
       
    43 	CVeiImageClipGenerator* self = 
       
    44 		CVeiImageClipGenerator::NewLC(aFilename, aMaxResolution, aDuration, aBackgroundColor, aMaxDisplayMode, aFs, aObserver);
       
    45 	CleanupStack::Pop(self);
       
    46 	return self;
       
    47 	}
       
    48 
       
    49 
       
    50 EXPORT_C CVeiImageClipGenerator* CVeiImageClipGenerator::NewLC(const TDesC& aFilename,
       
    51 													  const TSize& aMaxResolution,
       
    52 													  const TTimeIntervalMicroSeconds& aDuration,
       
    53 													  const TRgb& aBackgroundColor,
       
    54 													  TDisplayMode aMaxDisplayMode,
       
    55 													  RFs& aFs,
       
    56 													  MVeiImageClipGeneratorObserver& aObserver)
       
    57 	{
       
    58 	CVeiImageClipGenerator* self = new (ELeave) CVeiImageClipGenerator(aDuration, aBackgroundColor, aMaxResolution);
       
    59 	CleanupStack::PushL(self);
       
    60 	self->ConstructL(aFilename, aObserver, aMaxDisplayMode, aFs);
       
    61 	return self;
       
    62 	}
       
    63 
       
    64 
       
    65 CVeiImageClipGenerator::CVeiImageClipGenerator(const TTimeIntervalMicroSeconds& aDuration, 
       
    66 											   const TRgb& aBackgroundColor,
       
    67 											   const TSize& aMaxResolution)
       
    68    : iReady(EFalse), iMaxResolution(aMaxResolution), iBackgroundColor(aBackgroundColor), iInitializing(ETrue)
       
    69 	{
       
    70 	__ASSERT_ALWAYS(iMaxResolution.iHeight >= 0, TVedPanic::Panic(TVedPanic::EImageClipGeneratorIllegalMaxResolution));
       
    71 	__ASSERT_ALWAYS(iMaxResolution.iWidth >= 0, TVedPanic::Panic(TVedPanic::EImageClipGeneratorIllegalMaxResolution));
       
    72 
       
    73 	SetDuration(aDuration);
       
    74 
       
    75 	iInitializing = EFalse;
       
    76 	}
       
    77 
       
    78 
       
    79 void CVeiImageClipGenerator::ConstructL(const TDesC& aFilename, 
       
    80 										MVeiImageClipGeneratorObserver& aObserver, 
       
    81 										TDisplayMode aMaxDisplayMode, RFs& aFs)
       
    82 	{
       
    83 	iDecodeOperation = CVeiImageClipDecodeOperation::NewL(*this, aFilename, aObserver, aFs);
       
    84 	iFrameOperation = CVeiImageClipFrameOperation::NewL(*this);
       
    85 	
       
    86 	iFilename = aFilename.AllocL();
       
    87 
       
    88 	TParse parse;
       
    89 	parse.Set(aFilename, 0, 0);
       
    90 	iDescriptiveName = parse.Name().AllocL();
       
    91 
       
    92 	iDecodeOperation->StartOperationL(iMaxResolution, aMaxDisplayMode);
       
    93 	}
       
    94 
       
    95 
       
    96 EXPORT_C CVeiImageClipGenerator::~CVeiImageClipGenerator()
       
    97 	{
       
    98 	delete iDecodeOperation;
       
    99 	delete iFrameOperation;
       
   100 	delete iDescriptiveName;
       
   101 	delete iBitmap;
       
   102 	delete iMask;
       
   103 	delete iFilename;
       
   104 	}
       
   105 
       
   106 
       
   107 EXPORT_C TPtrC CVeiImageClipGenerator::DescriptiveName() const
       
   108 	{
       
   109 	__ASSERT_ALWAYS(iReady,
       
   110 		TVedPanic::Panic(TVedPanic::EImageClipGeneratorNotReady));
       
   111 
       
   112 	return *iDescriptiveName;
       
   113 	}
       
   114 
       
   115 
       
   116 EXPORT_C TUid CVeiImageClipGenerator::Uid() const
       
   117 	{
       
   118 	return KUidImageClipGenerator;
       
   119 	}
       
   120 
       
   121 EXPORT_C TTimeIntervalMicroSeconds CVeiImageClipGenerator::Duration() const
       
   122 	{
       
   123 	__ASSERT_ALWAYS(iReady,
       
   124 		TVedPanic::Panic(TVedPanic::EImageClipGeneratorNotReady));
       
   125 
       
   126 	return iDuration;
       
   127 	}
       
   128 
       
   129 
       
   130 EXPORT_C TInt CVeiImageClipGenerator::VideoFrameCount() const
       
   131 	{
       
   132 	__ASSERT_ALWAYS(iReady,
       
   133 		TVedPanic::Panic(TVedPanic::EImageClipGeneratorNotReady));
       
   134 
       
   135 	TInt frameCount = 0;
       
   136 
       
   137 	TInt maxFramerate = 10;
       
   138 	if (IsInserted()) 
       
   139 		{
       
   140 		maxFramerate = Movie()->MaximumFramerate();
       
   141 		}
       
   142 
       
   143 	TTimeIntervalMicroSeconds frameDuration(TInt64(1000000 / maxFramerate));
       
   144 	if (iDuration.Int64() < (TInt64(KNumberOfTransitionFrames * 2 + 1) * frameDuration.Int64()))
       
   145 		{
       
   146 		frameCount = (static_cast<TInt>(iDuration.Int64() / frameDuration.Int64()));
       
   147 		if ((iDuration.Int64() % frameDuration.Int64()) != 0)
       
   148 			{
       
   149 			frameCount++;
       
   150 			}
       
   151 		}
       
   152 	else
       
   153 		{
       
   154 		frameCount = KNumberOfTransitionFrames * 2; 
       
   155 		TTimeIntervalMicroSeconds middleTime(iDuration.Int64() - (TInt64(KNumberOfTransitionFrames * 2) * frameDuration.Int64()));
       
   156 		frameCount += (static_cast<TInt32>(middleTime.Int64() / KMiddleFrameDuration.Int64()));
       
   157 		if ((middleTime.Int64() % KMiddleFrameDuration.Int64()) != 0)
       
   158 			{
       
   159 			frameCount++;
       
   160 			}
       
   161 		}
       
   162 	return frameCount;
       
   163 	}
       
   164 
       
   165 
       
   166 EXPORT_C TTimeIntervalMicroSeconds CVeiImageClipGenerator::VideoFrameStartTime(TInt aIndex) const
       
   167 	{
       
   168 	__ASSERT_ALWAYS(iReady,
       
   169 		TVedPanic::Panic(TVedPanic::EImageClipGeneratorNotReady));
       
   170 	__ASSERT_ALWAYS(aIndex >= 0 && aIndex < VideoFrameCount(), TVedPanic::Panic(TVedPanic::EVideoClipGeneratorIllegalVideoFrameIndex));
       
   171 	
       
   172 	TInt maxFramerate = 10;
       
   173 	if (IsInserted()) 
       
   174 		{
       
   175 		maxFramerate = Movie()->MaximumFramerate();
       
   176 		}
       
   177 
       
   178 	TTimeIntervalMicroSeconds frameDuration(TInt64(1000000 / maxFramerate));
       
   179 	TTimeIntervalMicroSeconds finalThreshold(iDuration.Int64() - TInt64(KNumberOfTransitionFrames) * frameDuration.Int64());
       
   180 	TTimeIntervalMicroSeconds startThreshold(TInt64(KNumberOfTransitionFrames) * frameDuration.Int64());
       
   181 	TTimeIntervalMicroSeconds startTime(-1);
       
   182 	TInt frameCount = VideoFrameCount();
       
   183 
       
   184 
       
   185 	if (frameCount < (KNumberOfTransitionFrames * 2 + 1))
       
   186 		{		
       
   187 		// Special case: less than KNumberOfTransitionFrames frames in the movie
       
   188 		startTime = TTimeIntervalMicroSeconds(TInt64(aIndex) * frameDuration.Int64());
       
   189 		}
       
   190 	else if (aIndex < KNumberOfTransitionFrames) 
       
   191 		{
       
   192 		// Start frames
       
   193 		startTime = TTimeIntervalMicroSeconds(TInt64(aIndex) * frameDuration.Int64());
       
   194 		}
       
   195 	else if (aIndex >= (frameCount - KNumberOfTransitionFrames))
       
   196 		{
       
   197 		// End frames
       
   198 		startTime = TTimeIntervalMicroSeconds(
       
   199 			static_cast<TInt64>((aIndex - frameCount) + KNumberOfTransitionFrames) 
       
   200 			* frameDuration.Int64() + finalThreshold.Int64() );
       
   201 		}
       
   202 	else  
       
   203 		{
       
   204 		// Middle frames
       
   205 		startTime = TTimeIntervalMicroSeconds(startThreshold.Int64() 
       
   206 			+ TInt64(aIndex- KNumberOfTransitionFrames) * KMiddleFrameDuration.Int64());
       
   207 		}
       
   208 
       
   209 	return startTime;
       
   210 	}
       
   211 
       
   212 
       
   213 EXPORT_C TTimeIntervalMicroSeconds CVeiImageClipGenerator::VideoFrameEndTime(TInt aIndex) const
       
   214 	{
       
   215 	__ASSERT_ALWAYS(iReady,
       
   216 		TVedPanic::Panic(TVedPanic::EImageClipGeneratorNotReady));
       
   217 	__ASSERT_ALWAYS(aIndex >= 0 && aIndex < VideoFrameCount(), TVedPanic::Panic(TVedPanic::EVideoClipGeneratorIllegalVideoFrameIndex));
       
   218 	
       
   219 	if (aIndex == VideoFrameCount() - 1) 
       
   220 		{
       
   221 		return iDuration;
       
   222 		}
       
   223 
       
   224 	TInt maxFramerate = 10;
       
   225 	if (IsInserted()) 
       
   226 		{
       
   227 		maxFramerate = Movie()->MaximumFramerate();
       
   228 		}
       
   229 
       
   230 	TTimeIntervalMicroSeconds frameDuration(TInt64(1000000 / maxFramerate));
       
   231 	TTimeIntervalMicroSeconds finalThreshold(iDuration.Int64() - TInt64(KNumberOfTransitionFrames) * frameDuration.Int64());
       
   232 	TTimeIntervalMicroSeconds startThreshold(TInt64(KNumberOfTransitionFrames) * frameDuration.Int64());
       
   233 	TTimeIntervalMicroSeconds endTime(-1);
       
   234 
       
   235 
       
   236 	TInt frameCount = VideoFrameCount();
       
   237 
       
   238 	if (frameCount < (KNumberOfTransitionFrames * 2 + 1))
       
   239 		{
       
   240 		// Special case: less than KNumberOfTransitionFrames frames in the movie
       
   241 		endTime = TTimeIntervalMicroSeconds(TInt64(aIndex + 1) * frameDuration.Int64());
       
   242 		}
       
   243 	else if (aIndex < KNumberOfTransitionFrames) 
       
   244 		{
       
   245 		// start frames
       
   246 		endTime = TTimeIntervalMicroSeconds(TInt64(aIndex + 1) * frameDuration.Int64());
       
   247 		}
       
   248 	else if (aIndex > (frameCount - KNumberOfTransitionFrames))
       
   249 		{
       
   250 		// end frames
       
   251 		endTime = TTimeIntervalMicroSeconds(TInt64((aIndex - frameCount) 
       
   252 			+ KNumberOfTransitionFrames) * frameDuration.Int64() 
       
   253 			+ finalThreshold.Int64());
       
   254 		}
       
   255 	else  
       
   256 		{
       
   257 		// middle frames
       
   258 		endTime = TTimeIntervalMicroSeconds(startThreshold.Int64() 
       
   259 			+ TInt64(aIndex - (KNumberOfTransitionFrames - 1)) 
       
   260 			* KMiddleFrameDuration.Int64());
       
   261 
       
   262 		if (endTime.Int64() >= finalThreshold.Int64())
       
   263 			{
       
   264 			// last of the middle frames may be shorter than normal
       
   265 			endTime = finalThreshold;
       
   266 			}
       
   267 		}
       
   268 	return endTime;
       
   269 	}
       
   270 
       
   271 
       
   272 EXPORT_C TTimeIntervalMicroSeconds CVeiImageClipGenerator::VideoFrameDuration(TInt aIndex) const
       
   273 	{
       
   274 	__ASSERT_ALWAYS(iReady,
       
   275 		TVedPanic::Panic(TVedPanic::EImageClipGeneratorNotReady));
       
   276 	__ASSERT_ALWAYS(aIndex >= 0 && aIndex < VideoFrameCount(), TVedPanic::Panic(TVedPanic::EVideoClipGeneratorIllegalVideoFrameIndex));
       
   277 
       
   278 
       
   279 	// check maximum framerate
       
   280 	TInt maxFramerate = 10;
       
   281 	if (IsInserted()) 
       
   282 		{
       
   283 		maxFramerate = Movie()->MaximumFramerate();
       
   284 		}
       
   285 
       
   286 	// calculate some timing values. 
       
   287 	TTimeIntervalMicroSeconds frameDuration(TInt64(1000000 / maxFramerate));
       
   288 	TTimeIntervalMicroSeconds finalThreshold(iDuration.Int64() - TInt64(KNumberOfTransitionFrames) * frameDuration.Int64());
       
   289 	TTimeIntervalMicroSeconds startThreshold(TInt64(KNumberOfTransitionFrames) * frameDuration.Int64());
       
   290 
       
   291 
       
   292 	TInt frameCount = VideoFrameCount();
       
   293 	TInt finalThresholdIndex = GetVideoFrameIndex(finalThreshold);
       
   294 
       
   295 	if ((frameCount < (KNumberOfTransitionFrames * 2 + 1)) && (aIndex == (frameCount - 1)))
       
   296 		{
       
   297 		// Special case: short clip with only frames that have max framerate 
       
   298 		// - all of the frames are of equal duration (frameDuration) except 
       
   299 		// the last one.
       
   300 		frameDuration = TTimeIntervalMicroSeconds(iDuration.Int64() - (TInt64(frameCount - 1) * frameDuration.Int64()));
       
   301 		}
       
   302 	else if (aIndex >= KNumberOfTransitionFrames && aIndex < finalThresholdIndex) 
       
   303 		{
       
   304 		if (aIndex == (finalThresholdIndex - 1)) 
       
   305 			{
       
   306 			// Last one of the middle frames
       
   307 			frameDuration = TTimeIntervalMicroSeconds(finalThreshold.Int64() - VideoFrameStartTime(aIndex).Int64());
       
   308 			}
       
   309 		else
       
   310 			{
       
   311 			// Ordinary middle frame
       
   312 			frameDuration = KMiddleFrameDuration;
       
   313 			}
       
   314 		}
       
   315 	return frameDuration;
       
   316 	}
       
   317 
       
   318 EXPORT_C TBool CVeiImageClipGenerator::VideoFrameIsIntra(TInt aIndex) const
       
   319 	{
       
   320 	__ASSERT_ALWAYS(iReady,
       
   321 		TVedPanic::Panic(TVedPanic::EImageClipGeneratorNotReady));
       
   322 	if (aIndex == 0) 
       
   323 		{
       
   324 		return ETrue;
       
   325 		}
       
   326 	return EFalse;
       
   327 	}
       
   328 
       
   329 EXPORT_C TInt CVeiImageClipGenerator::VideoFirstFrameComplexityFactor() const
       
   330 	{
       
   331 	__ASSERT_ALWAYS(iReady,
       
   332 		TVedPanic::Panic(TVedPanic::EImageClipGeneratorNotReady));
       
   333 	return iFirstFrameComplexityFactor;
       
   334 	}
       
   335 
       
   336 EXPORT_C TInt CVeiImageClipGenerator::VideoFrameDifferenceFactor(TInt aIndex) const
       
   337 	{
       
   338 	__ASSERT_ALWAYS(iReady,
       
   339 		TVedPanic::Panic(TVedPanic::EImageClipGeneratorNotReady));
       
   340 	__ASSERT_ALWAYS(aIndex >= 0 && aIndex < VideoFrameCount(), TVedPanic::Panic(TVedPanic::EVideoClipGeneratorIllegalVideoFrameIndex));
       
   341 
       
   342 	if (aIndex == 0) 
       
   343 		{
       
   344 		return 1000;
       
   345 		}
       
   346 	else 
       
   347 		{
       
   348 		return 0;
       
   349 		}
       
   350 	}
       
   351 
       
   352 
       
   353 EXPORT_C TInt CVeiImageClipGenerator::GetVideoFrameIndex(TTimeIntervalMicroSeconds aTime) const
       
   354 	{
       
   355 	__ASSERT_ALWAYS(iReady,
       
   356 		TVedPanic::Panic(TVedPanic::EImageClipGeneratorNotReady));
       
   357 	__ASSERT_ALWAYS(aTime.Int64() >= 0, TVedPanic::Panic(TVedPanic::EVideoClipInfoIllegalVideoFrameTime));
       
   358 	__ASSERT_ALWAYS(aTime.Int64() <= iDuration.Int64(), TVedPanic::Panic(TVedPanic::EVideoClipInfoIllegalVideoFrameTime));
       
   359 
       
   360 	TInt index = -1;
       
   361 
       
   362 	TInt maxFramerate = 10;
       
   363 	if (IsInserted()) 
       
   364 		{
       
   365 		maxFramerate = Movie()->MaximumFramerate();
       
   366 		}
       
   367 
       
   368 	TTimeIntervalMicroSeconds frameDuration(TInt64(1000000 / maxFramerate));
       
   369 	TTimeIntervalMicroSeconds finalThreshold(
       
   370 		iDuration.Int64() - TInt64(KNumberOfTransitionFrames) * frameDuration.Int64());
       
   371 	TTimeIntervalMicroSeconds startThreshold(
       
   372 		TInt64(KNumberOfTransitionFrames) * frameDuration.Int64());
       
   373 
       
   374 	if (iDuration <= (TInt64(KNumberOfTransitionFrames * 2) * frameDuration.Int64())) 
       
   375 		{
       
   376 		index = static_cast<TInt>(aTime.Int64() / frameDuration.Int64());
       
   377 		}
       
   378 	else if (aTime < startThreshold) 
       
   379 		{
       
   380 		index = static_cast<TInt>(aTime.Int64() / frameDuration.Int64());
       
   381 		}
       
   382 	else if (aTime >= finalThreshold) 
       
   383 		{
       
   384 		TTimeIntervalMicroSeconds middleDuration(finalThreshold.Int64() - startThreshold.Int64());
       
   385 		TInt numberOfMiddleFrames = 
       
   386 		    static_cast<TInt32>(middleDuration.Int64() / KMiddleFrameDuration.Int64());
       
   387 		if (middleDuration.Int64() % KMiddleFrameDuration.Int64() != 0) 
       
   388 			{
       
   389 			numberOfMiddleFrames++;
       
   390 			}
       
   391 
       
   392 		index = KNumberOfTransitionFrames + numberOfMiddleFrames 
       
   393 			+ static_cast<TInt>((aTime.Int64() - finalThreshold.Int64()) / frameDuration.Int64()); 
       
   394 		}
       
   395 	else  
       
   396 		{
       
   397 		index = KNumberOfTransitionFrames 
       
   398 			+ static_cast<TInt>((aTime.Int64() - startThreshold.Int64()) / KMiddleFrameDuration.Int64());
       
   399 		}
       
   400 	
       
   401 	return index;
       
   402 	}
       
   403 
       
   404 
       
   405 EXPORT_C void CVeiImageClipGenerator::GetFrameL(MVedVideoClipGeneratorFrameObserver& aObserver,
       
   406 								  TInt aIndex, TSize* const aResolution,
       
   407 								  TDisplayMode aDisplayMode, TBool aEnhance,
       
   408 								  TInt aPriority)
       
   409 	{
       
   410 	__ASSERT_ALWAYS(iReady,
       
   411 		TVedPanic::Panic(TVedPanic::EImageClipGeneratorNotReady));
       
   412 	__ASSERT_ALWAYS((aIndex >= 0  && aIndex < VideoFrameCount()) || 
       
   413 					 aIndex == KFrameIndexBestThumb, 
       
   414 					TVedPanic::Panic(TVedPanic::EVideoClipGeneratorIllegalVideoFrameIndex));
       
   415 	__ASSERT_ALWAYS((aResolution->iHeight <= iMaxResolution.iHeight &&
       
   416 					 aResolution->iWidth  <= iMaxResolution.iWidth), 
       
   417 					TVedPanic::Panic(TVedPanic::EVideoClipGeneratorIllegalFrameResolution));
       
   418 	__ASSERT_ALWAYS((aResolution->iHeight >= 0 && aResolution->iWidth  >= 0), 
       
   419 					TVedPanic::Panic(TVedPanic::EVideoClipGeneratorIllegalFrameResolution));
       
   420 	
       
   421 
       
   422     TDisplayMode displayMode = aDisplayMode;
       
   423 
       
   424     // check validity of thumbnail and associated operation
       
   425     if(aEnhance)	// for saving to file
       
   426         {
       
   427         if(displayMode == ENone)					// if no preference
       
   428 			{
       
   429             displayMode = EColor16M;				// 24-bit color image for enhancement
       
   430 			}
       
   431         else if(displayMode != EColor16M)	// invalid combination
       
   432 			{
       
   433             User::Leave(KErrNotSupported);
       
   434 			}
       
   435         }
       
   436     else								// for screen display
       
   437         {
       
   438         if(displayMode == ENone)					// if no preference
       
   439 			{
       
   440             displayMode = EColor64K;				// 16-bit image 
       
   441 			}
       
   442         }
       
   443     
       
   444     CFbsBitmap* destBitmap = new (ELeave) CFbsBitmap;
       
   445 	CleanupStack::PushL(destBitmap);
       
   446 	User::LeaveIfError(destBitmap->Create(*aResolution, displayMode));
       
   447 	CleanupStack::Pop(destBitmap);
       
   448 
       
   449 	iFrameOperation->StartOperationL(&aObserver, aIndex, aEnhance, iBitmap,
       
   450 		destBitmap, iMask, aPriority);
       
   451 	}
       
   452 
       
   453 
       
   454 EXPORT_C void CVeiImageClipGenerator::CancelFrame()
       
   455 	{
       
   456 	iFrameOperation->Cancel();
       
   457 	}
       
   458 
       
   459 	
       
   460 EXPORT_C void CVeiImageClipGenerator::SetDuration(const TTimeIntervalMicroSeconds& aDuration)
       
   461 	{
       
   462 	__ASSERT_ALWAYS(iReady || iInitializing,
       
   463 		TVedPanic::Panic(TVedPanic::EImageClipGeneratorNotReady));	
       
   464 	__ASSERT_ALWAYS(aDuration.Int64() > 0, 
       
   465 		TVedPanic::Panic(TVedPanic::EVideoClipGeneratorIllegalDuration));
       
   466 
       
   467 	iDuration = aDuration;
       
   468 
       
   469 	if (!iInitializing) 
       
   470 		{
       
   471 		ReportDurationChanged();
       
   472 		}
       
   473 	}
       
   474 
       
   475 
       
   476 EXPORT_C void CVeiImageClipGenerator::SetBackgroundColor(const TRgb& aBackgroundColor)
       
   477 	{
       
   478 	__ASSERT_ALWAYS(iReady,
       
   479 		TVedPanic::Panic(TVedPanic::EImageClipGeneratorNotReady));	
       
   480 
       
   481 	iBackgroundColor = aBackgroundColor;
       
   482 	ReportSettingsChanged();
       
   483 	}
       
   484 
       
   485 EXPORT_C const TRgb& CVeiImageClipGenerator::BackgroundColor() const
       
   486 	{
       
   487 	__ASSERT_ALWAYS(iReady,
       
   488 		TVedPanic::Panic(TVedPanic::EImageClipGeneratorNotReady));	
       
   489 
       
   490 	return iBackgroundColor;
       
   491 	}
       
   492 
       
   493 EXPORT_C TPtrC CVeiImageClipGenerator::ImageFilename() const
       
   494 	{
       
   495 	__ASSERT_ALWAYS(iReady,
       
   496 		TVedPanic::Panic(TVedPanic::EImageClipGeneratorNotReady));	
       
   497 	return *iFilename;
       
   498 	}
       
   499 
       
   500 void CVeiImageClipGenerator::UpdateFirstFrameComplexityFactorL()
       
   501 	{
       
   502 	iFirstFrameComplexityFactor = CalculateFrameComplexityFactor(iBitmap);
       
   503 	}
       
   504 
       
   505 //////////////////////////////////////////////////////////////////////////
       
   506 //  Decode operation
       
   507 //////////////////////////////////////////////////////////////////////////
       
   508 
       
   509 
       
   510 CVeiImageClipDecodeOperation* CVeiImageClipDecodeOperation::NewL(CVeiImageClipGenerator& aGenerator, 
       
   511 																 const TDesC& aFilename, 
       
   512 																 MVeiImageClipGeneratorObserver& aObserver,
       
   513 																 RFs& aFs,
       
   514 																 TInt aPriority)
       
   515 	{
       
   516     CVeiImageClipDecodeOperation* self = 
       
   517 		new (ELeave) CVeiImageClipDecodeOperation(aGenerator, aObserver, aPriority);
       
   518     CleanupStack::PushL(self);
       
   519     self->ConstructL(aFilename, aFs);
       
   520     CleanupStack::Pop(self);
       
   521     return self;	
       
   522 	}
       
   523 
       
   524 
       
   525 CVeiImageClipDecodeOperation::CVeiImageClipDecodeOperation(CVeiImageClipGenerator& aGenerator, 
       
   526 														   MVeiImageClipGeneratorObserver& aObserver,
       
   527 														   TInt aPriority)
       
   528   : CActive(aPriority), iGenerator(aGenerator), iObserver(aObserver)
       
   529 	{
       
   530 	CActiveScheduler::Add(this);
       
   531 	}
       
   532 
       
   533 
       
   534 void CVeiImageClipDecodeOperation::ConstructL(const TDesC& aFilename, RFs& aFs)
       
   535 	{
       
   536 	iDecoder = CImageDecoder::FileNewL(aFs, aFilename);
       
   537 	}
       
   538 
       
   539 
       
   540 CVeiImageClipDecodeOperation::~CVeiImageClipDecodeOperation()
       
   541 	{
       
   542 	Cancel();
       
   543 
       
   544 	delete iDecoder;
       
   545 	iDecoder = 0;
       
   546 	delete iBitmap;
       
   547 	iBitmap = 0;
       
   548 	delete iMask;
       
   549 	iMask = 0;
       
   550 	}
       
   551 
       
   552 
       
   553 void CVeiImageClipDecodeOperation::DoCancel()
       
   554 	{
       
   555 	if (iDecoder) 
       
   556 		{
       
   557 		iDecoder->Cancel();
       
   558 		}
       
   559 
       
   560 	delete iDecoder;
       
   561 	iDecoder = 0;
       
   562 
       
   563 	delete iBitmap;
       
   564 	iBitmap = 0;
       
   565 
       
   566 	delete iMask;
       
   567 	iMask = 0;
       
   568 
       
   569 	iObserver.NotifyImageClipGeneratorInitializationComplete(iGenerator, KErrCancel);
       
   570 	}
       
   571 
       
   572 
       
   573 void CVeiImageClipDecodeOperation::RunL()
       
   574 	{
       
   575 	/* Transfer ownership of iBitmap to generator. */
       
   576 	iGenerator.iBitmap = iBitmap;
       
   577 	iBitmap = 0;
       
   578 	iGenerator.iMask = iMask;
       
   579 	iMask = 0;
       
   580 	iGenerator.iReady = ETrue;
       
   581 	iGenerator.UpdateFirstFrameComplexityFactorL();
       
   582 
       
   583 	/* Notify observer. */
       
   584 	iObserver.NotifyImageClipGeneratorInitializationComplete(iGenerator, KErrNone);
       
   585 	delete iDecoder;
       
   586 	iDecoder = 0;
       
   587 	}
       
   588 
       
   589 TInt CVeiImageClipDecodeOperation::RunError(TInt aError)
       
   590 	{
       
   591 	if (iDecoder) 
       
   592 		{
       
   593 		iDecoder->Cancel();
       
   594 		}
       
   595 	delete iDecoder;
       
   596 	iDecoder = 0;
       
   597 	delete iBitmap;
       
   598 	iBitmap = 0;
       
   599 	delete iMask;
       
   600 	iMask = 0;
       
   601 
       
   602 	iObserver.NotifyImageClipGeneratorInitializationComplete(iGenerator, aError);
       
   603 	return KErrNone;
       
   604 	}
       
   605 
       
   606 
       
   607 
       
   608 void CVeiImageClipDecodeOperation::StartOperationL(const TSize& aMaxResolution, TDisplayMode aDisplayMode)
       
   609 	{
       
   610 	__ASSERT_ALWAYS(!IsActive(), TVedPanic::Panic(TVedPanic::EInternal));
       
   611 
       
   612 	const TFrameInfo& info = iDecoder->FrameInfo();
       
   613 	TSize targetResolution(0, 0);
       
   614 	const TSize sourceResolution(info.iOverallSizeInPixels);
       
   615 
       
   616 	/* Calculate resolution. */
       
   617 
       
   618 	if ((sourceResolution.iWidth <= aMaxResolution.iWidth) 
       
   619 		&& (sourceResolution.iHeight <= aMaxResolution.iHeight))
       
   620 		{
       
   621 		targetResolution.iWidth = sourceResolution.iWidth;
       
   622 		targetResolution.iHeight = sourceResolution.iHeight;
       
   623 		}
       
   624 	else if (info.iFlags & TFrameInfo::EFullyScaleable) 
       
   625 		{
       
   626 		if ((sourceResolution.iWidth * aMaxResolution.iHeight) > 
       
   627 			(sourceResolution.iHeight * aMaxResolution.iWidth))
       
   628 			{
       
   629 			targetResolution.iWidth = aMaxResolution.iWidth;
       
   630 			targetResolution.iHeight = 
       
   631 				(targetResolution.iWidth * sourceResolution.iHeight) / sourceResolution.iWidth;
       
   632 			}
       
   633 		else
       
   634 			{
       
   635 			targetResolution.iHeight = aMaxResolution.iHeight;
       
   636 			targetResolution.iWidth = 
       
   637 				(targetResolution.iHeight * sourceResolution.iWidth) / sourceResolution.iHeight;
       
   638 			}
       
   639 		}
       
   640 	else 
       
   641 		{
       
   642 		targetResolution.iWidth = (sourceResolution.iWidth / 8) + 1;
       
   643 		targetResolution.iHeight = (sourceResolution.iHeight / 8) + 1;
       
   644 		
       
   645 		if ((targetResolution.iWidth < aMaxResolution.iWidth) 
       
   646 			&& (targetResolution.iHeight < aMaxResolution.iHeight))
       
   647 			{
       
   648 			targetResolution.iWidth = (sourceResolution.iWidth / 4) + 1;
       
   649 			targetResolution.iHeight = (sourceResolution.iHeight / 4) + 1;
       
   650 			}
       
   651 
       
   652 		if ((targetResolution.iWidth < aMaxResolution.iWidth) 
       
   653 			&& (targetResolution.iHeight < aMaxResolution.iHeight))
       
   654 			{
       
   655 			targetResolution.iWidth = (sourceResolution.iWidth / 2) + 1;
       
   656 			targetResolution.iHeight = (sourceResolution.iHeight / 2) + 1;
       
   657 			}
       
   658 
       
   659 		if ((targetResolution.iWidth < aMaxResolution.iWidth) 
       
   660 			&& (targetResolution.iHeight < aMaxResolution.iHeight))
       
   661 			{
       
   662 			targetResolution.iWidth = (sourceResolution.iWidth);
       
   663 			targetResolution.iHeight = (sourceResolution.iHeight);
       
   664 			}
       
   665 		}
       
   666 
       
   667 
       
   668 	iBitmap = new (ELeave) CFbsBitmap;
       
   669 	TInt err = iBitmap->Create(targetResolution, aDisplayMode);
       
   670 
       
   671 	if (err != KErrNone) 
       
   672 		{
       
   673 		delete iBitmap;
       
   674 		iBitmap = 0;
       
   675 		iObserver.NotifyImageClipGeneratorInitializationComplete(iGenerator, err);
       
   676 		return;
       
   677 		}
       
   678 
       
   679 	if (info.iFlags & TFrameInfo::ETransparencyPossible)
       
   680 		{
       
   681 		iMask = new (ELeave) CFbsBitmap;
       
   682 		if (info.iFlags & TFrameInfo::EAlphaChannel) 
       
   683 			{
       
   684 			err = iMask->Create(targetResolution, EGray256);
       
   685 			}
       
   686 		else 
       
   687 			{
       
   688 			err = iMask->Create(targetResolution, EGray2);
       
   689 			}
       
   690 		}
       
   691 	
       
   692 	if (err != KErrNone) 
       
   693 		{
       
   694 		delete iBitmap;
       
   695 		iBitmap = 0;
       
   696 		delete iMask;
       
   697 		iMask = 0;
       
   698 		iObserver.NotifyImageClipGeneratorInitializationComplete(iGenerator, err);
       
   699 		return;
       
   700 		}
       
   701 
       
   702 	if (iMask != 0)
       
   703 		{
       
   704 		iDecoder->Convert(&iStatus, *iBitmap, *iMask);
       
   705 		}
       
   706 	else
       
   707 		{
       
   708 		iDecoder->Convert(&iStatus, *iBitmap);
       
   709 		}
       
   710 
       
   711 	SetActive();
       
   712 	}
       
   713 
       
   714 
       
   715 //////////////////////////////////////////////////////////////////////////
       
   716 // Frame operation
       
   717 //////////////////////////////////////////////////////////////////////////
       
   718 
       
   719 CVeiImageClipFrameOperation* CVeiImageClipFrameOperation::NewL(CVeiImageClipGenerator& aGenerator)
       
   720     {
       
   721     CVeiImageClipFrameOperation* self = 
       
   722 		new (ELeave) CVeiImageClipFrameOperation(aGenerator);
       
   723     CleanupStack::PushL(self);
       
   724     self->ConstructL();
       
   725     CleanupStack::Pop(self);
       
   726     return self;
       
   727     }
       
   728 
       
   729 
       
   730 CVeiImageClipFrameOperation::CVeiImageClipFrameOperation(CVeiImageClipGenerator& aGenerator)
       
   731 		: CActive(EPriorityStandard), iGenerator(aGenerator)
       
   732     {
       
   733 	CActiveScheduler::Add(this);
       
   734 	}
       
   735 
       
   736 
       
   737 void CVeiImageClipFrameOperation::ConstructL()
       
   738     {
       
   739 	}
       
   740 
       
   741 
       
   742 CVeiImageClipFrameOperation::~CVeiImageClipFrameOperation()
       
   743     {
       
   744 	Cancel();
       
   745 	delete iScaler;
       
   746 	iScaler = 0;
       
   747 	delete iDestBitmap;
       
   748 	iDestBitmap = 0;
       
   749 	delete iScaledBitmap;
       
   750 	iScaledBitmap = 0;
       
   751 	delete iScaledMask;
       
   752 	iScaledMask = 0;
       
   753 
       
   754 	iSourceBitmap = 0;
       
   755 	iSourceMask = 0;
       
   756 	iObserver = 0;
       
   757     }
       
   758 
       
   759 
       
   760 void CVeiImageClipFrameOperation::StartOperationL(MVedVideoClipGeneratorFrameObserver* aObserver,
       
   761 												 TInt aIndex, TBool aEnhance, 
       
   762 												 CFbsBitmap* aSourceBitmap, CFbsBitmap* aDestBitmap, 
       
   763 												 CFbsBitmap* aSourceMask, TInt aPriority)
       
   764 	{
       
   765 	__ASSERT_ALWAYS(!IsActive(), TVedPanic::Panic(TVedPanic::EImageClipGeneratorFrameOperationAlreadyRunning));
       
   766 
       
   767 	iObserver = aObserver;
       
   768 	iSourceBitmap = aSourceBitmap;
       
   769 	iDestBitmap = aDestBitmap;
       
   770 	iSourceMask = aSourceMask;
       
   771 	iIndex = aIndex;
       
   772 	iEnhance = aEnhance;
       
   773 
       
   774 	SetPriority(aPriority);
       
   775 
       
   776 
       
   777 	TSize sourceRes = iSourceBitmap->SizeInPixels();
       
   778 	TSize destRes = iDestBitmap->SizeInPixels();
       
   779 	TSize movieRes = iGenerator.Movie()->Resolution();
       
   780 
       
   781 	TSize imageResInMovie(0,0);
       
   782 	if ((sourceRes.iWidth >= movieRes.iWidth) || (sourceRes.iHeight >= movieRes.iHeight)) 
       
   783 		{
       
   784 		// Downscaling
       
   785 		if ((sourceRes.iWidth * movieRes.iHeight) > 
       
   786 			(sourceRes.iHeight * movieRes.iWidth))
       
   787 			{
       
   788 			imageResInMovie.iWidth = movieRes.iWidth;
       
   789 			imageResInMovie.iHeight =
       
   790 				(movieRes.iWidth * sourceRes.iHeight) / sourceRes.iWidth;
       
   791 			}
       
   792 		else 
       
   793 			{
       
   794 			imageResInMovie.iHeight = movieRes.iHeight;
       
   795 			imageResInMovie.iWidth = 
       
   796 				(movieRes.iHeight * sourceRes.iWidth) / sourceRes.iHeight;
       
   797 			}
       
   798 		}
       
   799 	else
       
   800 		{
       
   801 		// Upscaling - limit to a factor of two
       
   802 		if ((sourceRes.iWidth * movieRes.iHeight) > 
       
   803 			(sourceRes.iHeight * movieRes.iWidth))
       
   804 			{
       
   805 			imageResInMovie.iWidth = Min(movieRes.iWidth, (sourceRes.iWidth * 2));
       
   806 			imageResInMovie.iHeight = (imageResInMovie.iWidth * sourceRes.iHeight) / sourceRes.iWidth;
       
   807 			}
       
   808 		else 
       
   809 			{
       
   810 			imageResInMovie.iHeight = Min((sourceRes.iHeight * 2), movieRes.iHeight);
       
   811 			imageResInMovie.iWidth = (imageResInMovie.iHeight * sourceRes.iWidth) / sourceRes.iHeight;
       
   812 			}
       
   813 		}
       
   814 
       
   815 	TSize movieResInDestBitmap(-1,-1);
       
   816 	if ((movieRes.iWidth * destRes.iHeight) > 
       
   817 		(movieRes.iHeight * destRes.iWidth))
       
   818 		{
       
   819 		movieResInDestBitmap.iWidth = destRes.iWidth;
       
   820 		movieResInDestBitmap.iHeight =
       
   821 			(movieResInDestBitmap.iWidth * movieRes.iHeight) / movieRes.iWidth;
       
   822 		}
       
   823 	else 
       
   824 		{
       
   825 		movieResInDestBitmap.iHeight = destRes.iHeight;
       
   826 		movieResInDestBitmap.iWidth = 
       
   827 			(movieResInDestBitmap.iHeight * movieRes.iWidth) / movieRes.iHeight;
       
   828 		}
       
   829 	
       
   830 
       
   831 	TSize targetRes(imageResInMovie);
       
   832 	targetRes.iWidth = imageResInMovie.iWidth * movieResInDestBitmap.iWidth / movieRes.iWidth;
       
   833 	targetRes.iHeight = imageResInMovie.iHeight * movieResInDestBitmap.iHeight / movieRes.iHeight;
       
   834 
       
   835 	TSize cachedRes(-1, -1);
       
   836 	if (iScaledBitmap) 
       
   837 		{
       
   838 		cachedRes = iScaledBitmap->SizeInPixels();
       
   839 		}
       
   840 
       
   841 	/* Check if we already have scaled this bitmap.*/
       
   842 	if ((cachedRes.iWidth == targetRes.iWidth) || 
       
   843 		(cachedRes.iHeight == targetRes.iHeight))
       
   844 		{
       
   845 		SetActive();
       
   846 		TRequestStatus* status = &iStatus;
       
   847 		User::RequestComplete(status, KErrNone);
       
   848 		return;
       
   849 		}
       
   850 	else if (iScaledBitmap) 
       
   851 		{
       
   852 		delete iScaledBitmap;
       
   853 		iScaledBitmap = 0;
       
   854 		delete iScaledMask;
       
   855 		iScaledMask = 0;
       
   856 		}
       
   857 
       
   858 	delete iScaler;
       
   859 	iScaler = NULL;
       
   860 	iScaler = CBitmapScaler::NewL();
       
   861 
       
   862 	iScaledBitmap = new (ELeave) CFbsBitmap;
       
   863 	User::LeaveIfError(iScaledBitmap->Create(targetRes, iDestBitmap->DisplayMode()));
       
   864 	iScaler->Scale(&iStatus, *iSourceBitmap, *iScaledBitmap, ETrue);
       
   865 	SetActive();
       
   866 	}
       
   867 
       
   868 
       
   869 
       
   870 void CVeiImageClipFrameOperation::RunL()
       
   871 	{
       
   872 	if (!iNoScaling && iSourceMask && !iScaledMask) 
       
   873 		{
       
   874 		/* Scale the mask. */
       
   875 		iScaledMask = new (ELeave) CFbsBitmap;
       
   876 		User::LeaveIfError(iScaledMask->Create(iScaledBitmap->SizeInPixels(), iSourceMask->DisplayMode()));
       
   877 		iScaler->Scale(&iStatus, *iSourceMask, *iScaledMask, ETrue);
       
   878 		SetActive();
       
   879 		return;
       
   880 		}
       
   881 
       
   882 	/* Select source. */
       
   883 	CFbsBitmap* bitmap = 0;
       
   884 	CFbsBitmap* mask = 0;
       
   885 
       
   886 	if (iScaledBitmap) 
       
   887 		{
       
   888 		bitmap = iScaledBitmap;
       
   889 		}
       
   890 	else
       
   891 		{
       
   892 		bitmap = iSourceBitmap;
       
   893 		}
       
   894 
       
   895 	if (iScaledMask) 
       
   896 		{
       
   897 		mask = iScaledMask;
       
   898 		}
       
   899 	else
       
   900 		{
       
   901 		mask = iSourceMask;
       
   902 		}
       
   903 
       
   904 
       
   905 	/* Initialize context. */
       
   906 	CFbsDevice* device = CFbsBitmapDevice::NewL(iDestBitmap);
       
   907 	CleanupStack::PushL(device);
       
   908 	CFbsBitGc* gc = NULL;
       
   909 	User::LeaveIfError(device->CreateContext(gc));
       
   910 
       
   911 	/* Calculate source point. */
       
   912 	TSize destRes = iDestBitmap->SizeInPixels();
       
   913 	TSize sourceRes = bitmap->SizeInPixels();	
       
   914 	TPoint sourcePoint((destRes.iWidth - sourceRes.iWidth) / 2,
       
   915 						(destRes.iHeight - sourceRes.iHeight) / 2);
       
   916 
       
   917 	/* Draw background (this is relevant for scaled images and transparency). */
       
   918 	gc->SetBrushColor(iGenerator.BackgroundColor());
       
   919 	gc->SetBrushStyle(CGraphicsContext::ESolidBrush);
       
   920 	gc->DrawRect(TRect(TPoint(0, 0), destRes));
       
   921 
       
   922 	if (mask) 
       
   923 		{
       
   924 		TRect sourceRect(bitmap->SizeInPixels());
       
   925 		gc->BitBltMasked(sourcePoint, bitmap, sourceRect, mask, EFalse);
       
   926 		}
       
   927 	else
       
   928 		{
       
   929 		gc->BitBlt(sourcePoint, bitmap);
       
   930 		}
       
   931 
       
   932 	delete gc;
       
   933 	CleanupStack::PopAndDestroy(device);
       
   934 
       
   935 	/* This transfers the bitmap ownership to the observer. */
       
   936 	iObserver->NotifyVideoClipGeneratorFrameCompleted(iGenerator, KErrNone, iDestBitmap);
       
   937 
       
   938 	delete iScaler;
       
   939 	iScaler = 0;
       
   940 
       
   941 	iSourceBitmap = 0;
       
   942 	iSourceMask = 0;
       
   943 	iDestBitmap = 0;
       
   944 	iObserver = 0;
       
   945 	iIndex = -1;
       
   946 	iNoScaling = EFalse;
       
   947 	}
       
   948 
       
   949 TInt CVeiImageClipFrameOperation::RunError(TInt aError)
       
   950 	{
       
   951 	iObserver->NotifyVideoClipGeneratorFrameCompleted(iGenerator, aError, NULL);
       
   952 
       
   953 	if (iScaler) 
       
   954 		{
       
   955 		iScaler->Cancel();
       
   956 		}
       
   957 	
       
   958 	delete iScaler;
       
   959 	iScaler = 0;
       
   960 	delete iScaledBitmap;
       
   961 	iScaledBitmap = 0;
       
   962 	delete iScaledMask;
       
   963 	iScaledMask = 0;
       
   964 	delete iDestBitmap;
       
   965 	iDestBitmap = 0;
       
   966 	iSourceBitmap = 0;
       
   967 	iSourceMask = 0;
       
   968 	iObserver = 0;
       
   969 	iIndex = -1;
       
   970 
       
   971 	return KErrNone;
       
   972 	}
       
   973 
       
   974 
       
   975 void CVeiImageClipFrameOperation::DoCancel()
       
   976 	{
       
   977 	iObserver->NotifyVideoClipGeneratorFrameCompleted(iGenerator, KErrCancel, 0);
       
   978 
       
   979 	if (iScaler) 
       
   980 		{
       
   981 		iScaler->Cancel();
       
   982 		}
       
   983 	
       
   984 	delete iScaler;
       
   985 	iScaler = 0;
       
   986 	delete iScaledBitmap;
       
   987 	iScaledBitmap = 0;
       
   988 	delete iScaledMask;
       
   989 	iScaledMask = 0;
       
   990 
       
   991 	delete iDestBitmap;
       
   992 	iDestBitmap = 0;
       
   993 	iSourceBitmap = 0;
       
   994 	iSourceMask = 0;
       
   995 	iObserver = 0;
       
   996 	iIndex = -1;
       
   997 	}
       
   998 // End of File
       
   999