1 /* |
|
2 * Copyright (c) 2009-2010 Nokia Corporation and/or its subsidiary(-ies). |
|
3 * All rights reserved. |
|
4 * This component and the accompanying materials are made available |
|
5 * under the terms of "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 and/or its subsidiary(-ies). |
|
11 * |
|
12 * Contributors: |
|
13 * |
|
14 * |
|
15 * Description: |
|
16 * Implementation file for CxeQualityPresetsSymbian class |
|
17 * |
|
18 */ |
|
19 |
|
20 #include <algorithm> |
|
21 #include <e32std.h> // For Symbian types used in mmsenginedomaincrkeys.h |
|
22 #include <MmsEngineDomainCRKeys.h> |
|
23 #include <imagingconfigmanager.h> |
|
24 |
|
25 #include "cxutils.h" |
|
26 #include "cxenamespace.h" |
|
27 #include "cxesettings.h" |
|
28 #include "cxequalitydetails.h" |
|
29 #include "cxequalitypresetssymbian.h" |
|
30 |
|
31 #include "OstTraceDefinitions.h" |
|
32 #ifdef OST_TRACE_COMPILER_IN_USE |
|
33 #include "cxequalitypresetssymbianTraces.h" |
|
34 #endif |
|
35 |
|
36 // constants |
|
37 namespace |
|
38 { |
|
39 // Display IDs for cameras, used when requesting data from ICM |
|
40 const int PRIMARY_CAMERA_DISPLAY_ID = 2; |
|
41 const int SECONDARY_CAMERA_DISPLAY_ID = 3; |
|
42 |
|
43 const int ONE_MILLION = 1000000; |
|
44 |
|
45 const QSize ASPECT_RATIO_SIZE_4BY3 = QSize(4,3); |
|
46 const QSize ASPECT_RATIO_SIZE_16BY9 = QSize(16, 9); |
|
47 const QSize ASPECT_RATIO_SIZE_11BY9 = QSize(11, 9); |
|
48 |
|
49 // ICM "camcorderVisible" parameter value below this means sharing aka mms quality. |
|
50 const int MMS_QUALITY_CAMCORDERVISIBLE_LIMIT = 200; |
|
51 |
|
52 // Average video bit rate scaler |
|
53 const qreal VIDEO_AVG_BITRATE_SCALER = 0.9; |
|
54 // Coefficient to estimate video metadata amount |
|
55 const qreal VIDEO_METADATA_COEFF = 1.03; |
|
56 // Maximum video clip duration in seconds for all qualities |
|
57 const qint64 VIDEO_MAX_DURATION = 5400; |
|
58 } |
|
59 |
|
60 |
|
61 /* ! |
|
62 * Intializes ImagingConfigManager |
|
63 */ |
|
64 CxeQualityPresetsSymbian::CxeQualityPresetsSymbian(CxeSettings &settings) |
|
65 : mSettings(settings) |
|
66 { |
|
67 CX_DEBUG_ENTER_FUNCTION(); |
|
68 OstTrace0(camerax_performance, CXEQUALITYPRESETSSYMBIAN_1, "msg: e_CX_QUALITYPRESETS_NEW 1"); |
|
69 |
|
70 TRAPD(err, mIcm = CImagingConfigManager::NewL()); |
|
71 |
|
72 if (err) { |
|
73 CX_DEBUG(("Error during ICM initialization error code = %d", err)); |
|
74 mIcm = NULL; |
|
75 } |
|
76 |
|
77 OstTrace0(camerax_performance, CXEQUALITYPRESETSSYMBIAN_2, "msg: e_CX_QUALITYPRESETS_NEW 0"); |
|
78 CX_DEBUG_EXIT_FUNCTION(); |
|
79 } |
|
80 |
|
81 /* ! |
|
82 * CxeQualityPresetsSymbian::~CxeQualityPresetsSymbian() |
|
83 */ |
|
84 CxeQualityPresetsSymbian::~CxeQualityPresetsSymbian() |
|
85 { |
|
86 CX_DEBUG_ENTER_FUNCTION(); |
|
87 |
|
88 delete mIcm; |
|
89 |
|
90 CX_DEBUG_EXIT_FUNCTION(); |
|
91 } |
|
92 |
|
93 /*! |
|
94 This function returns sorted list of image qualities from highest to lowest resolution. |
|
95 i.e. first element in the list represent highest supported image resolution and so on. |
|
96 @param cameraId The CameraIndex which defines which camera we are using primary/secondary. |
|
97 Returns sorted list of image qualities in descending order. |
|
98 */ |
|
99 QList<CxeImageDetails> CxeQualityPresetsSymbian::imageQualityPresets(Cxe::CameraIndex cameraId) |
|
100 { |
|
101 CX_DEBUG_ENTER_FUNCTION(); |
|
102 OstTrace0(camerax_performance, CXEQUALITYPRESETSSYMBIAN_GETIMAGEPRESETS_IN, "msg: e_CX_QUALITYPRESETS_GETIMAGEPRESETS 1"); |
|
103 |
|
104 QList<CxeImageDetails> presetList; |
|
105 |
|
106 if (!mIcm) { |
|
107 CX_DEBUG(("ICM not initialized, returning empty image qualities list")); |
|
108 return presetList; |
|
109 } |
|
110 int totalLevels = mIcm->NumberOfImageQualityLevels(); |
|
111 |
|
112 CX_DEBUG(("Total image quality levels = %d", totalLevels)); |
|
113 CArrayFixFlat<TUint>* levels = new CArrayFixFlat<TUint>(totalLevels); |
|
114 |
|
115 // Get camera display id based on camera index |
|
116 int displayId = cameraId == Cxe::SecondaryCameraIndex |
|
117 ? SECONDARY_CAMERA_DISPLAY_ID : PRIMARY_CAMERA_DISPLAY_ID; |
|
118 |
|
119 TRAPD(err, mIcm->GetImageQualityLevelsL(*levels, displayId)); |
|
120 |
|
121 if (err == KErrNone) { |
|
122 CX_DEBUG(( "Reading image quality sets one by one.")); |
|
123 TImageQualitySet set; |
|
124 int numLevels = levels->Count(); |
|
125 for(int i = 0; i < numLevels; i++) { |
|
126 mIcm->GetImageQualitySet(set, levels->At(i), displayId); |
|
127 if (set.iCamcorderVisible > 0) { |
|
128 // create new quality preset based on the quality set values |
|
129 CxeImageDetails newPreset = createImagePreset(set); |
|
130 |
|
131 // print debug prints |
|
132 debugPrints(newPreset); |
|
133 |
|
134 // append to the list of presets |
|
135 presetList.append(newPreset); |
|
136 } |
|
137 } |
|
138 CX_DEBUG(( "Sorting image qualities")); |
|
139 // Sorting result list according to height pixel size from highest to lowest |
|
140 // i.e. descending order keeping the highest resolution first. |
|
141 qSort(presetList.begin(), presetList.end(), qGreater<CxeImageDetails>()); |
|
142 } |
|
143 |
|
144 delete levels; |
|
145 levels = NULL; |
|
146 |
|
147 OstTrace0(camerax_performance, CXEQUALITYPRESETSSYMBIAN_GETIMAGEPRESETS_OUT, "msg: e_CX_QUALITYPRESETS_GETIMAGEPRESETS 0"); |
|
148 CX_DEBUG_EXIT_FUNCTION(); |
|
149 return presetList; |
|
150 } |
|
151 |
|
152 |
|
153 |
|
154 /*! |
|
155 This function returns sorted list of video qualities from highest to lowest resolution. |
|
156 i.e. first element in the list represent highest supported video resolution and so on. |
|
157 @param cameraId The CameraIndex which defines which camera we are using primary/secondary. |
|
158 Returns sorted list if image qualities in descending order. |
|
159 */ |
|
160 QList<CxeVideoDetails> CxeQualityPresetsSymbian::videoQualityPresets(Cxe::CameraIndex cameraId) |
|
161 { |
|
162 CX_DEBUG_ENTER_FUNCTION(); |
|
163 OstTrace0(camerax_performance, CXEQUALITYPRESETSSYMBIAN_GETVIDEOPRESETS_IN, "msg: e_CX_QUALITYPRESETS_GETVIDEOPRESETS 1"); |
|
164 |
|
165 QList<CxeVideoDetails> presetList; |
|
166 |
|
167 if (!mIcm) { |
|
168 CX_DEBUG(("ICM not initialized, returning empty video qualities list")); |
|
169 return presetList; |
|
170 } |
|
171 int totalLevels = mIcm->NumberOfVideoQualityLevels(); |
|
172 |
|
173 CX_DEBUG(("Total video quality levels = %d", totalLevels)); |
|
174 CArrayFixFlat<TUint>* levels= new CArrayFixFlat<TUint>(totalLevels); |
|
175 |
|
176 int displayId = cameraId == Cxe::SecondaryCameraIndex |
|
177 ? SECONDARY_CAMERA_DISPLAY_ID : PRIMARY_CAMERA_DISPLAY_ID; |
|
178 |
|
179 TRAPD(err, mIcm->GetVideoQualityLevelsL(*levels, displayId)); |
|
180 |
|
181 if (err == KErrNone) { |
|
182 CX_DEBUG(( "Reading video quality sets one by one.")); |
|
183 TVideoQualitySet set; |
|
184 int numLevels = levels->Count(); |
|
185 for(int i = 0; i < numLevels; i++) { |
|
186 mIcm->GetVideoQualitySet(set, levels->At(i), displayId); |
|
187 |
|
188 // Disable all video sizes larger than VGA |
|
189 if (set.iCamcorderVisible > 0 && set.iVideoWidth <= 864) { |
|
190 // create new quality preset |
|
191 CxeVideoDetails newPreset = createVideoPreset(set); |
|
192 |
|
193 // print debug prints |
|
194 debugPrints(newPreset); |
|
195 |
|
196 // append to the list of presets |
|
197 presetList.append(newPreset); |
|
198 } |
|
199 } |
|
200 CX_DEBUG(( "Sorting image qualities")); |
|
201 // Sorting result list according to height pixel size from highest to lowest |
|
202 // i.e. descending order keeping the highest resolution first. |
|
203 qSort(presetList.begin(), presetList.end(), qGreater<CxeVideoDetails>()); |
|
204 } |
|
205 |
|
206 delete levels; |
|
207 levels = NULL; |
|
208 |
|
209 // Get the average video bitrate scaler |
|
210 TCamcorderMMFPluginSettings mmfPluginSettings; |
|
211 mIcm->GetCamcorderMMFPluginSettings(mmfPluginSettings); |
|
212 mCMRAvgVideoBitRateScaler = mmfPluginSettings.iCMRAvgVideoBitRateScaler; |
|
213 |
|
214 OstTrace0(camerax_performance, CXEQUALITYPRESETSSYMBIAN_GETVIDEOPRESETS_OUT, "msg: e_CX_QUALITYPRESETS_GETVIDEOPRESETS 0"); |
|
215 CX_DEBUG_EXIT_FUNCTION(); |
|
216 return presetList; |
|
217 } |
|
218 |
|
219 |
|
220 |
|
221 /*! |
|
222 * Creates a new image preset based on TImageQualitySet values from ICM. |
|
223 @ param set contains the ICM configuration data |
|
224 @ returns CxeImageQuality struct |
|
225 */ |
|
226 CxeImageDetails CxeQualityPresetsSymbian::createImagePreset(const TImageQualitySet &set) |
|
227 { |
|
228 CxeImageDetails newPreset; |
|
229 // set setting values from quality set |
|
230 newPreset.mWidth = set.iImageWidth; |
|
231 newPreset.mHeight = set.iImageHeight; |
|
232 newPreset.mEstimatedSize = set.iEstimatedSize; |
|
233 newPreset.mMpxCount = calculateMegaPixelCount(set.iImageWidth, |
|
234 set.iImageHeight); |
|
235 newPreset.mPossibleImages = CxeImageDetails::UNKNOWN; |
|
236 newPreset.mImageFileExtension = toString(set.iImageFileExtension); |
|
237 newPreset.mAspectRatio = calculateAspectRatio(set.iImageWidth, |
|
238 set.iImageHeight); |
|
239 |
|
240 return newPreset; |
|
241 } |
|
242 |
|
243 |
|
244 |
|
245 /*! |
|
246 * Creates a new video preset based on TVideoQualitySet values from ICM. |
|
247 */ |
|
248 CxeVideoDetails CxeQualityPresetsSymbian::createVideoPreset(const TVideoQualitySet &set) |
|
249 { |
|
250 CX_DEBUG_ENTER_FUNCTION(); |
|
251 CxeVideoDetails newPreset; |
|
252 // set setting values from quality set |
|
253 newPreset.mWidth = set.iVideoWidth; |
|
254 newPreset.mHeight = set.iVideoHeight; |
|
255 |
|
256 newPreset.mRemainingTime = CxeVideoDetails::UNKNOWN; |
|
257 |
|
258 // Check if this is a sharing (mms) quality, and set size limit accordingly. |
|
259 if (set.iCamcorderVisible < MMS_QUALITY_CAMCORDERVISIBLE_LIMIT) { |
|
260 QVariant size; |
|
261 mSettings.get(KCRUidMmsEngine.iUid, KMmsEngineMaximumSendSize, Cxe::Repository, size); |
|
262 CX_DEBUG(("CxeQualityPresetsSymbian - Got MMS quality size limit: %d", size.toInt())); |
|
263 newPreset.mMaximumSizeInBytes = size.toInt(); |
|
264 } else { |
|
265 // Zero means no limit. |
|
266 newPreset.mMaximumSizeInBytes = 0; |
|
267 } |
|
268 |
|
269 newPreset.mVideoBitRate = set.iVideoBitRate; |
|
270 newPreset.mAudioBitRate = set.iAudioBitRate; |
|
271 newPreset.mVideoFrameRate = set.iVideoFrameRate; |
|
272 newPreset.mVideoFileMimeType = toString(set.iVideoFileMimeType); |
|
273 newPreset.mPreferredSupplier = toString(set.iPreferredSupplier); |
|
274 newPreset.mVideoCodecMimeType = toString(set.iVideoCodecMimeType); |
|
275 newPreset.mAspectRatio = calculateAspectRatio(set.iVideoWidth, |
|
276 set.iVideoHeight); |
|
277 |
|
278 // Convert FourCC value from TFourCC to ascii string |
|
279 const int KFourCCLength = 5; // 4 characters + '\0' |
|
280 TText8 fourCCBuf[KFourCCLength]; |
|
281 TPtr8 fourCC(fourCCBuf, KFourCCLength); |
|
282 set.iAudioFourCCType.FourCC(&fourCC); |
|
283 fourCC.Append('\0'); |
|
284 |
|
285 // set audiotype |
|
286 newPreset.mAudioType = toString(fourCCBuf); |
|
287 |
|
288 CX_DEBUG_EXIT_FUNCTION(); |
|
289 return newPreset; |
|
290 } |
|
291 |
|
292 |
|
293 /*! |
|
294 * Returns Aspect ratio of the image. |
|
295 */ |
|
296 qreal CxeQualityPresetsSymbian::avgVideoBitRateScaler() |
|
297 { |
|
298 CX_DEBUG_IN_FUNCTION(); |
|
299 // Get the average video bitrate scaler |
|
300 if (mIcm) { |
|
301 TCamcorderMMFPluginSettings mmfPluginSettings; |
|
302 mIcm->GetCamcorderMMFPluginSettings(mmfPluginSettings); |
|
303 mCMRAvgVideoBitRateScaler = mmfPluginSettings.iCMRAvgVideoBitRateScaler; |
|
304 } |
|
305 return mCMRAvgVideoBitRateScaler; |
|
306 } |
|
307 |
|
308 |
|
309 /*! |
|
310 @ param width - image/video quality width |
|
311 @ param height - image/video quality height |
|
312 * Returns Aspect ratio of the image/video. |
|
313 */ |
|
314 Cxe::AspectRatio CxeQualityPresetsSymbian::calculateAspectRatio(int width, int height) const |
|
315 { |
|
316 Cxe::AspectRatio aspectRatio = Cxe::AspectRatio4to3; |
|
317 |
|
318 // calculate delta error for the resolution against supported aspect ratio's |
|
319 int delta16by9 = abs((width * ASPECT_RATIO_SIZE_16BY9.height()) - (height * ASPECT_RATIO_SIZE_16BY9.width())); |
|
320 int delta11by9 = abs((width * ASPECT_RATIO_SIZE_11BY9.height()) - (height * ASPECT_RATIO_SIZE_11BY9.width())); |
|
321 int delta4by3 = abs((width * ASPECT_RATIO_SIZE_4BY3.height()) - (height * ASPECT_RATIO_SIZE_4BY3.width())); |
|
322 |
|
323 // get the closest aspect ratio |
|
324 int minValue = qMin(qMin(delta16by9, delta11by9), delta4by3); |
|
325 |
|
326 if (minValue == delta16by9) { |
|
327 aspectRatio = Cxe::AspectRatio16to9; |
|
328 } else if (minValue == delta11by9) { |
|
329 aspectRatio = Cxe::AspectRatio11to9; |
|
330 } else if (minValue == delta4by3) { |
|
331 aspectRatio = Cxe::AspectRatio4to3; |
|
332 } |
|
333 |
|
334 return aspectRatio; |
|
335 } |
|
336 |
|
337 |
|
338 |
|
339 /*! |
|
340 * CxeQualityPresetsSymbian::calculateMegaPixelCount |
|
341 @ param imageWidth refers to the image resolution width |
|
342 @ param imageHeight refers to the image resolution height |
|
343 @ returns megapixel count string |
|
344 */ |
|
345 QString |
|
346 CxeQualityPresetsSymbian::calculateMegaPixelCount(int imageWidth, int imageHeight) |
|
347 { |
|
348 QString mpxCountString; |
|
349 qreal size = imageWidth * imageHeight * 1.0; |
|
350 int mpxCount = (size/ONE_MILLION) * 10; |
|
351 |
|
352 if ((mpxCount % 10) == 0) { |
|
353 int value = mpxCount / 10; |
|
354 mpxCountString.setNum(value); |
|
355 } else { |
|
356 qreal value = mpxCount / 10.0; |
|
357 if ((mpxCount % 10) < 5) { |
|
358 mpxCountString.setNum(value, 'f', 1); |
|
359 } else { |
|
360 int temp = ceil(value); |
|
361 mpxCountString.setNum(temp); |
|
362 } |
|
363 } |
|
364 |
|
365 return mpxCountString; |
|
366 |
|
367 |
|
368 } |
|
369 |
|
370 /*! |
|
371 * Get the available recording time with given video quality details and disk space. |
|
372 * @param details Video quality details to use in calculation. |
|
373 * @param space Available disk space to use in calculation. |
|
374 * @return Available recording time estimate in seconds. |
|
375 */ |
|
376 int CxeQualityPresetsSymbian::recordingTimeAvailable(const CxeVideoDetails& details, qint64 space) |
|
377 { |
|
378 CX_DEBUG_ENTER_FUNCTION(); |
|
379 int time(0); |
|
380 |
|
381 // Maximum clip size may be limited for mms quality. |
|
382 // If mMaximumSizeInBytes == 0, no limit is specified. |
|
383 if (details.mMaximumSizeInBytes > 0 && details.mMaximumSizeInBytes < space) { |
|
384 space = details.mMaximumSizeInBytes; |
|
385 } |
|
386 |
|
387 // Use average audio/video bitrates to estimate remaining time |
|
388 qreal scaler(avgVideoBitRateScaler()); |
|
389 if (scaler == 0) { |
|
390 // video bit rate scaler is 0, use the constant value |
|
391 scaler = VIDEO_AVG_BITRATE_SCALER; |
|
392 } |
|
393 |
|
394 bool muteSetting = mSettings.get<bool>(CxeSettingIds::VIDEO_MUTE_SETTING, false); // false = audio enabled |
|
395 |
|
396 int avgVideoBitRate = (details.mVideoBitRate * scaler); |
|
397 int avgAudioBitRate = muteSetting ? 0 : details.mAudioBitRate; |
|
398 |
|
399 quint32 averageBitRate = (quint32)((avgVideoBitRate + avgAudioBitRate) * VIDEO_METADATA_COEFF); |
|
400 quint32 averageByteRate = averageBitRate / 8; |
|
401 |
|
402 // 0 <= Remaining time <= KCamCMaxClipDurationInSecs |
|
403 qint64 remaining = std::max(qint64(0), space/averageByteRate); |
|
404 time = std::min(remaining, VIDEO_MAX_DURATION); |
|
405 |
|
406 CX_DEBUG(( "remaining time from algorithm: %d", time )); |
|
407 CX_DEBUG_EXIT_FUNCTION(); |
|
408 return time; |
|
409 } |
|
410 |
|
411 |
|
412 /*! |
|
413 Operator to sort values in ascending order. |
|
414 @param s1 type of data to be sorted. |
|
415 */ |
|
416 bool CxeImageDetails::operator<(const CxeImageDetails& s1) const |
|
417 { |
|
418 return mHeight < s1.mHeight; |
|
419 } |
|
420 |
|
421 |
|
422 /*! |
|
423 Operator to sort values in ascending order. |
|
424 @param s1 type of data to be sorted. |
|
425 */ |
|
426 bool CxeVideoDetails::operator<(const CxeVideoDetails& s1) const |
|
427 { |
|
428 return mHeight < s1.mHeight; |
|
429 } |
|
430 |
|
431 |
|
432 /* |
|
433 * Converts TUint8* to QString |
|
434 */ |
|
435 QString CxeQualityPresetsSymbian::toString(const TUint8* aData) |
|
436 { |
|
437 return QString::fromLatin1((char*)aData); |
|
438 } |
|
439 |
|
440 |
|
441 |
|
442 /*! |
|
443 * Helper method to enable debug prints. |
|
444 @ param Video quality preset values are printed out for debugging |
|
445 */ |
|
446 void CxeQualityPresetsSymbian::debugPrints(const CxeVideoDetails &preset) |
|
447 { |
|
448 CX_DEBUG(("Video quality details")); |
|
449 CX_DEBUG(("Video resolution (%d,%d)", preset.mWidth, preset.mHeight)); |
|
450 CX_DEBUG(("Audio bitrate = %d)", preset.mAudioBitRate)); |
|
451 CX_DEBUG(("Video bitrate = %d)", preset.mVideoBitRate)); |
|
452 CX_DEBUG(("Video frame rate = %f)", preset.mVideoFrameRate)); |
|
453 CX_DEBUG(("Audio type: %s", preset.mAudioType.toAscii().data())); |
|
454 CX_DEBUG(("Video file MIME type: %s", preset.mVideoFileMimeType.toAscii().data())); |
|
455 CX_DEBUG(("Video preferred supplier: %s", preset.mPreferredSupplier.toAscii().data())); |
|
456 CX_DEBUG(("Video codec MIME type: %s", preset.mVideoCodecMimeType.toAscii().data())); |
|
457 QString aspectRatio; |
|
458 if (preset.mAspectRatio == Cxe::AspectRatio4to3) { |
|
459 aspectRatio = QString("4:3"); |
|
460 } else if (preset.mAspectRatio == Cxe::AspectRatio16to9) { |
|
461 aspectRatio = QString("16:9"); |
|
462 } |
|
463 CX_DEBUG(("Video aspect ratio: %s", aspectRatio.toAscii().data())); |
|
464 } |
|
465 |
|
466 |
|
467 /*! |
|
468 * Helper method to enable debug prints. |
|
469 @ param Image quality preset values are printed out for debugging |
|
470 */ |
|
471 void CxeQualityPresetsSymbian::debugPrints(const CxeImageDetails &newPreset) |
|
472 { |
|
473 CX_DEBUG(("Image quality details")); |
|
474 CX_DEBUG(("Image resolution (%d,%d)", newPreset.mWidth, newPreset.mHeight)); |
|
475 CX_DEBUG(("Estimated size in bytes = %d)", newPreset.mEstimatedSize)); |
|
476 CX_DEBUG(("Megapixels: %s", newPreset.mMpxCount.toAscii().data())); |
|
477 CX_DEBUG(("Image file extension: %s", newPreset.mImageFileExtension.toAscii().data())); |
|
478 |
|
479 QString aspectRatio; |
|
480 |
|
481 if (newPreset.mAspectRatio == Cxe::AspectRatio4to3) { |
|
482 aspectRatio = QString("4:3"); |
|
483 } else { |
|
484 aspectRatio = QString("16:9"); |
|
485 } |
|
486 CX_DEBUG(("Image aspect ratio: %s", aspectRatio.toAscii().data())); |
|
487 } |
|