|
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 |