dom/camera/GonkCameraParameters.cpp

branch
TOR_BUG_3246
changeset 7
129ffea94266
equal deleted inserted replaced
-1:000000000000 0:d8c94ba7ff2a
1 /*
2 * Copyright (C) 2013-2014 Mozilla Foundation
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "GonkCameraParameters.h"
18 #include "camera/CameraParameters.h"
19 #include "ICameraControl.h"
20 #include "CameraCommon.h"
21
22 using namespace mozilla;
23 using namespace android;
24
25 /* static */ const char*
26 GonkCameraParameters::Parameters::GetTextKey(uint32_t aKey)
27 {
28 switch (aKey) {
29 case CAMERA_PARAM_PREVIEWSIZE:
30 return KEY_PREVIEW_SIZE;
31 case CAMERA_PARAM_PREVIEWFORMAT:
32 return KEY_PREVIEW_FORMAT;
33 case CAMERA_PARAM_PREVIEWFRAMERATE:
34 return KEY_PREVIEW_FRAME_RATE;
35 case CAMERA_PARAM_EFFECT:
36 return KEY_EFFECT;
37 case CAMERA_PARAM_WHITEBALANCE:
38 return KEY_WHITE_BALANCE;
39 case CAMERA_PARAM_SCENEMODE:
40 return KEY_SCENE_MODE;
41 case CAMERA_PARAM_FLASHMODE:
42 return KEY_FLASH_MODE;
43 case CAMERA_PARAM_FOCUSMODE:
44 return KEY_FOCUS_MODE;
45 case CAMERA_PARAM_ZOOM:
46 return KEY_ZOOM;
47 case CAMERA_PARAM_METERINGAREAS:
48 return KEY_METERING_AREAS;
49 case CAMERA_PARAM_FOCUSAREAS:
50 return KEY_FOCUS_AREAS;
51 case CAMERA_PARAM_FOCALLENGTH:
52 return KEY_FOCAL_LENGTH;
53 case CAMERA_PARAM_FOCUSDISTANCENEAR:
54 return KEY_FOCUS_DISTANCES;
55 case CAMERA_PARAM_FOCUSDISTANCEOPTIMUM:
56 return KEY_FOCUS_DISTANCES;
57 case CAMERA_PARAM_FOCUSDISTANCEFAR:
58 return KEY_FOCUS_DISTANCES;
59 case CAMERA_PARAM_EXPOSURECOMPENSATION:
60 return KEY_EXPOSURE_COMPENSATION;
61 case CAMERA_PARAM_THUMBNAILQUALITY:
62 return KEY_JPEG_THUMBNAIL_QUALITY;
63 case CAMERA_PARAM_PICTURE_SIZE:
64 return KEY_PICTURE_SIZE;
65 case CAMERA_PARAM_PICTURE_FILEFORMAT:
66 return KEY_PICTURE_FORMAT;
67 case CAMERA_PARAM_PICTURE_ROTATION:
68 return KEY_ROTATION;
69 case CAMERA_PARAM_PICTURE_DATETIME:
70 // Not every platform defines a KEY_EXIF_DATETIME;
71 // for those that don't, we use the raw string key, and if the platform
72 // doesn't support it, it will be ignored.
73 //
74 // See bug 832494.
75 return "exif-datetime";
76 case CAMERA_PARAM_VIDEOSIZE:
77 return KEY_VIDEO_SIZE;
78 case CAMERA_PARAM_ISOMODE:
79 // Not every platform defines KEY_ISO_MODE;
80 // for those that don't, we use the raw string key.
81 return "iso";
82 case CAMERA_PARAM_LUMINANCE:
83 return "luminance-condition";
84 case CAMERA_PARAM_SCENEMODE_HDR_RETURNNORMALPICTURE:
85 // Not every platform defines KEY_QC_HDR_NEED_1X;
86 // for those that don't, we use the raw string key.
87 return "hdr-need-1x";
88
89 case CAMERA_PARAM_SUPPORTED_PREVIEWSIZES:
90 return KEY_SUPPORTED_PREVIEW_SIZES;
91 case CAMERA_PARAM_SUPPORTED_PICTURESIZES:
92 return KEY_SUPPORTED_PICTURE_SIZES;
93 case CAMERA_PARAM_SUPPORTED_VIDEOSIZES:
94 return KEY_SUPPORTED_VIDEO_SIZES;
95 case CAMERA_PARAM_SUPPORTED_PICTUREFORMATS:
96 return KEY_SUPPORTED_PICTURE_FORMATS;
97 case CAMERA_PARAM_SUPPORTED_WHITEBALANCES:
98 return KEY_SUPPORTED_WHITE_BALANCE;
99 case CAMERA_PARAM_SUPPORTED_SCENEMODES:
100 return KEY_SUPPORTED_SCENE_MODES;
101 case CAMERA_PARAM_SUPPORTED_EFFECTS:
102 return KEY_SUPPORTED_EFFECTS;
103 case CAMERA_PARAM_SUPPORTED_FLASHMODES:
104 return KEY_SUPPORTED_FLASH_MODES;
105 case CAMERA_PARAM_SUPPORTED_FOCUSMODES:
106 return KEY_SUPPORTED_FOCUS_MODES;
107 case CAMERA_PARAM_SUPPORTED_MAXFOCUSAREAS:
108 return KEY_MAX_NUM_FOCUS_AREAS;
109 case CAMERA_PARAM_SUPPORTED_MAXMETERINGAREAS:
110 return KEY_MAX_NUM_METERING_AREAS;
111 case CAMERA_PARAM_SUPPORTED_MINEXPOSURECOMPENSATION:
112 return KEY_MIN_EXPOSURE_COMPENSATION;
113 case CAMERA_PARAM_SUPPORTED_MAXEXPOSURECOMPENSATION:
114 return KEY_MAX_EXPOSURE_COMPENSATION;
115 case CAMERA_PARAM_SUPPORTED_EXPOSURECOMPENSATIONSTEP:
116 return KEY_EXPOSURE_COMPENSATION_STEP;
117 case CAMERA_PARAM_SUPPORTED_ZOOM:
118 return KEY_ZOOM_SUPPORTED;
119 case CAMERA_PARAM_SUPPORTED_ZOOMRATIOS:
120 return KEY_ZOOM_RATIOS;
121 case CAMERA_PARAM_SUPPORTED_MAXDETECTEDFACES:
122 return KEY_MAX_NUM_DETECTED_FACES_HW;
123 case CAMERA_PARAM_SUPPORTED_JPEG_THUMBNAIL_SIZES:
124 return KEY_SUPPORTED_JPEG_THUMBNAIL_SIZES;
125 case CAMERA_PARAM_SUPPORTED_ISOMODES:
126 // Not every platform defines KEY_SUPPORTED_ISO_MODES;
127 // for those that don't, we use the raw string key.
128 return "iso-values";
129 default:
130 DOM_CAMERA_LOGE("Unhandled camera parameter value %u\n", aKey);
131 return nullptr;
132 }
133 }
134
135 GonkCameraParameters::GonkCameraParameters()
136 : mLock(PR_NewRWLock(PR_RWLOCK_RANK_NONE, "GonkCameraParameters.Lock"))
137 , mDirty(false)
138 , mInitialized(false)
139 {
140 MOZ_COUNT_CTOR(GonkCameraParameters);
141 if (!mLock) {
142 MOZ_CRASH("OOM getting new PRRWLock");
143 }
144 }
145
146 GonkCameraParameters::~GonkCameraParameters()
147 {
148 MOZ_COUNT_DTOR(GonkCameraParameters);
149 if (mLock) {
150 PR_DestroyRWLock(mLock);
151 mLock = nullptr;
152 }
153 }
154
155 nsresult
156 GonkCameraParameters::MapIsoToGonk(const nsAString& aIso, nsACString& aIsoOut)
157 {
158 if (aIso.EqualsASCII("hjr")) {
159 aIsoOut = "ISO_HJR";
160 } else if (aIso.EqualsASCII("auto")) {
161 aIsoOut = "auto";
162 } else {
163 nsAutoCString v = NS_LossyConvertUTF16toASCII(aIso);
164 unsigned int iso;
165 if (sscanf(v.get(), "%u", &iso) != 1) {
166 return NS_ERROR_FAILURE;
167 }
168 aIsoOut = nsPrintfCString("ISO%u", iso);
169 }
170
171 return NS_OK;
172 }
173
174 nsresult
175 GonkCameraParameters::MapIsoFromGonk(const char* aIso, nsAString& aIsoOut)
176 {
177 if (strcmp(aIso, "ISO_HJR") == 0) {
178 aIsoOut.AssignASCII("hjr");
179 } else if (strcmp(aIso, "auto") == 0) {
180 aIsoOut.AssignASCII("auto");
181 } else {
182 unsigned int iso;
183 if (sscanf(aIso, "ISO%u", &iso) != 1) {
184 return NS_ERROR_FAILURE;
185 }
186 aIsoOut.AppendInt(iso);
187 }
188
189 return NS_OK;
190 }
191
192 // Any members that need to be initialized on the first parameter pull
193 // need to get handled in here.
194 nsresult
195 GonkCameraParameters::Initialize()
196 {
197 nsresult rv;
198
199 rv = GetImpl(CAMERA_PARAM_SUPPORTED_MINEXPOSURECOMPENSATION, mExposureCompensationMin);
200 if (NS_FAILED(rv)) {
201 NS_WARNING("Failed to initialize minimum exposure compensation");
202 mExposureCompensationMin = 0;
203 }
204 rv = GetImpl(CAMERA_PARAM_SUPPORTED_EXPOSURECOMPENSATIONSTEP, mExposureCompensationStep);
205 if (NS_FAILED(rv)) {
206 NS_WARNING("Failed to initialize exposure compensation step size");
207 mExposureCompensationStep = 0;
208 }
209
210 rv = GetListAsArray(CAMERA_PARAM_SUPPORTED_ZOOMRATIOS, mZoomRatios);
211 if (NS_FAILED(rv)) {
212 // zoom is not supported
213 mZoomRatios.Clear();
214 }
215 for (uint32_t i = 1; i < mZoomRatios.Length(); ++i) {
216 // Make sure the camera gave us a properly sorted zoom ratio list!
217 if (mZoomRatios[i] < mZoomRatios[i - 1]) {
218 NS_WARNING("Zoom ratios list is out of order, discarding");
219 DOM_CAMERA_LOGE("zoom[%d]=%fx < zoom[%d]=%fx is out of order\n",
220 i, mZoomRatios[i] / 100.0, i - 1, mZoomRatios[i - 1] / 100.0);
221 mZoomRatios.Clear();
222 break;
223 }
224 }
225 if (mZoomRatios.Length() == 0) {
226 // Always report that we support at least 1.0x zoom.
227 *mZoomRatios.AppendElement() = 100;
228 }
229
230 // The return code from GetListAsArray() doesn't matter. If it fails,
231 // the isoModes array will be empty, and the subsequent loop won't
232 // execute.
233 nsTArray<nsCString> isoModes;
234 GetListAsArray(CAMERA_PARAM_SUPPORTED_ISOMODES, isoModes);
235 for (uint32_t i = 0; i < isoModes.Length(); ++i) {
236 nsString v;
237 rv = MapIsoFromGonk(isoModes[i].get(), v);
238 if (NS_SUCCEEDED(rv)) {
239 *mIsoModes.AppendElement() = v;
240 }
241 }
242
243 mInitialized = true;
244 return NS_OK;
245 }
246
247 // Handle nsAStrings
248 nsresult
249 GonkCameraParameters::SetTranslated(uint32_t aKey, const nsAString& aValue)
250 {
251 if (aKey == CAMERA_PARAM_ISOMODE) {
252 nsAutoCString v;
253 nsresult rv = MapIsoToGonk(aValue, v);
254 if (NS_FAILED(rv)) {
255 return rv;
256 }
257 return SetImpl(aKey, v.get());
258 }
259
260 return SetImpl(aKey, NS_ConvertUTF16toUTF8(aValue).get());
261 }
262
263 nsresult
264 GonkCameraParameters::GetTranslated(uint32_t aKey, nsAString& aValue)
265 {
266 const char* val;
267 nsresult rv = GetImpl(aKey, val);
268 if (NS_FAILED(rv)) {
269 return rv;
270 }
271 if (aKey == CAMERA_PARAM_ISOMODE) {
272 rv = MapIsoFromGonk(val, aValue);
273 } else if(val) {
274 aValue.AssignASCII(val);
275 } else {
276 aValue.Truncate(0);
277 }
278 return rv;
279 }
280
281 // Handle ICameraControl::Sizes
282 nsresult
283 GonkCameraParameters::SetTranslated(uint32_t aKey, const ICameraControl::Size& aSize)
284 {
285 if (aSize.width > INT_MAX || aSize.height > INT_MAX) {
286 // AOSP can only handle signed ints.
287 DOM_CAMERA_LOGE("Camera parameter aKey=%d out of bounds (width=%u, height=%u)\n",
288 aSize.width, aSize.height);
289 return NS_ERROR_INVALID_ARG;
290 }
291
292 nsresult rv;
293
294 switch (aKey) {
295 case CAMERA_PARAM_THUMBNAILSIZE:
296 // This is a special case--for some reason the thumbnail size
297 // is accessed as two separate values instead of a tuple.
298 // XXXmikeh - make this restore the original values on error
299 rv = SetImpl(Parameters::KEY_JPEG_THUMBNAIL_WIDTH, static_cast<int>(aSize.width));
300 if (NS_SUCCEEDED(rv)) {
301 rv = SetImpl(Parameters::KEY_JPEG_THUMBNAIL_HEIGHT, static_cast<int>(aSize.height));
302 }
303 break;
304
305 case CAMERA_PARAM_VIDEOSIZE:
306 // "record-size" is probably deprecated in later ICS;
307 // might need to set "video-size" instead of "record-size";
308 // for the time being, set both. See bug 795332.
309 rv = SetImpl("record-size", nsPrintfCString("%ux%u", aSize.width, aSize.height).get());
310 if (NS_FAILED(rv)) {
311 break;
312 }
313 // intentional fallthrough
314
315 default:
316 rv = SetImpl(aKey, nsPrintfCString("%ux%u", aSize.width, aSize.height).get());
317 break;
318 }
319
320 if (NS_FAILED(rv)) {
321 DOM_CAMERA_LOGE("Camera parameter aKey=%d failed to set (0x%x)\n", aKey, rv);
322 }
323 return rv;
324 }
325
326 nsresult
327 GonkCameraParameters::GetTranslated(uint32_t aKey, ICameraControl::Size& aSize)
328 {
329 nsresult rv;
330
331 if (aKey == CAMERA_PARAM_THUMBNAILSIZE) {
332 int width;
333 int height;
334
335 rv = GetImpl(Parameters::KEY_JPEG_THUMBNAIL_WIDTH, width);
336 if (NS_FAILED(rv) || width < 0) {
337 return NS_ERROR_FAILURE;
338 }
339 rv = GetImpl(Parameters::KEY_JPEG_THUMBNAIL_HEIGHT, height);
340 if (NS_FAILED(rv) || height < 0) {
341 return NS_ERROR_FAILURE;
342 }
343
344 aSize.width = static_cast<uint32_t>(width);
345 aSize.height = static_cast<uint32_t>(height);
346 return NS_OK;
347 }
348
349 const char* value;
350 rv = GetImpl(aKey, value);
351 if (NS_FAILED(rv) || !value || *value == '\0') {
352 DOM_CAMERA_LOGW("Camera parameter aKey=%d not available (0x%x)\n", aKey, rv);
353 return NS_ERROR_NOT_AVAILABLE;
354 }
355 if (sscanf(value, "%ux%u", &aSize.width, &aSize.height) != 2) {
356 DOM_CAMERA_LOGE("Camera parameter aKey=%d size tuple '%s' is invalid\n", aKey, value);
357 return NS_ERROR_FAILURE;
358 }
359 return NS_OK;
360 }
361
362 // Handle arrays of ICameraControl::Regions
363 nsresult
364 GonkCameraParameters::SetTranslated(uint32_t aKey, const nsTArray<ICameraControl::Region>& aRegions)
365 {
366 uint32_t length = aRegions.Length();
367
368 if (!length) {
369 // This tells the camera driver to revert to automatic regioning.
370 return SetImpl(aKey, "(0,0,0,0,0)");
371 }
372
373 nsCString s;
374
375 for (uint32_t i = 0; i < length; ++i) {
376 const ICameraControl::Region* r = &aRegions[i];
377 s.AppendPrintf("(%d,%d,%d,%d,%d),", r->top, r->left, r->bottom, r->right, r->weight);
378 }
379
380 // remove the trailing comma
381 s.Trim(",", false, true, true);
382
383 return SetImpl(aKey, s.get());
384 }
385
386 nsresult
387 GonkCameraParameters::GetTranslated(uint32_t aKey, nsTArray<ICameraControl::Region>& aRegions)
388 {
389 aRegions.Clear();
390
391 const char* value;
392 nsresult rv = GetImpl(aKey, value);
393 if (NS_FAILED(rv) || !value || *value == '\0') {
394 return NS_ERROR_FAILURE;
395 }
396
397 const char* p = value;
398 uint32_t count = 1;
399
400 // count the number of regions in the string
401 while ((p = strstr(p, "),("))) {
402 ++count;
403 p += 3;
404 }
405
406 aRegions.SetCapacity(count);
407 ICameraControl::Region* r;
408
409 // parse all of the region sets
410 uint32_t i;
411 for (i = 0, p = value; p && i < count; ++i, p = strchr(p + 1, '(')) {
412 r = aRegions.AppendElement();
413 if (sscanf(p, "(%d,%d,%d,%d,%u)", &r->top, &r->left, &r->bottom, &r->right, &r->weight) != 5) {
414 DOM_CAMERA_LOGE("%s:%d : region tuple has bad format: '%s'\n", __func__, __LINE__, p);
415 aRegions.Clear();
416 return NS_ERROR_FAILURE;
417 }
418 }
419
420 return NS_OK;
421 }
422
423 // Handle ICameraControl::Positions
424 nsresult
425 GonkCameraParameters::SetTranslated(uint32_t aKey, const ICameraControl::Position& aPosition)
426 {
427 MOZ_ASSERT(aKey == CAMERA_PARAM_PICTURE_LOCATION);
428
429 // Add any specified location information -- we don't care if these fail.
430 if (!isnan(aPosition.latitude)) {
431 DOM_CAMERA_LOGI("setting picture latitude to %lf\n", aPosition.latitude);
432 SetImpl(Parameters::KEY_GPS_LATITUDE, nsPrintfCString("%lf", aPosition.latitude).get());
433 }
434 if (!isnan(aPosition.longitude)) {
435 DOM_CAMERA_LOGI("setting picture longitude to %lf\n", aPosition.longitude);
436 SetImpl(Parameters::KEY_GPS_LONGITUDE, nsPrintfCString("%lf", aPosition.longitude).get());
437 }
438 if (!isnan(aPosition.altitude)) {
439 DOM_CAMERA_LOGI("setting picture altitude to %lf\n", aPosition.altitude);
440 SetImpl(Parameters::KEY_GPS_ALTITUDE, nsPrintfCString("%lf", aPosition.altitude).get());
441 }
442 if (!isnan(aPosition.timestamp)) {
443 DOM_CAMERA_LOGI("setting picture timestamp to %lf\n", aPosition.timestamp);
444 SetImpl(Parameters::KEY_GPS_TIMESTAMP, nsPrintfCString("%lf", aPosition.timestamp).get());
445 }
446 return NS_OK;
447 }
448
449 // Handle int64_ts
450 nsresult
451 GonkCameraParameters::SetTranslated(uint32_t aKey, const int64_t& aValue)
452 {
453 switch (aKey) {
454 case CAMERA_PARAM_PICTURE_DATETIME:
455 {
456 // Add the non-GPS timestamp. The EXIF date/time field is formatted as
457 // "YYYY:MM:DD HH:MM:SS", without room for a time-zone; as such, the time
458 // is meant to be stored as a local time. Since we are given seconds from
459 // Epoch GMT, we use localtime_r() to handle the conversion.
460 time_t time = aValue;
461 if (time != aValue) {
462 DOM_CAMERA_LOGE("picture date/time '%llu' is too far in the future\n", aValue);
463 return NS_ERROR_INVALID_ARG;
464 }
465
466 struct tm t;
467 if (!localtime_r(&time, &t)) {
468 DOM_CAMERA_LOGE("picture date/time couldn't be converted to local time: (%d) %s\n", errno, strerror(errno));
469 return NS_ERROR_FAILURE;
470 }
471
472 char dateTime[20];
473 if (!strftime(dateTime, sizeof(dateTime), "%Y:%m:%d %T", &t)) {
474 DOM_CAMERA_LOGE("picture date/time couldn't be converted to string\n");
475 return NS_ERROR_FAILURE;
476 }
477
478 DOM_CAMERA_LOGI("setting picture date/time to %s\n", dateTime);
479
480 return SetImpl(CAMERA_PARAM_PICTURE_DATETIME, dateTime);
481 }
482
483 case CAMERA_PARAM_ISOMODE:
484 {
485 if (aValue > INT32_MAX) {
486 DOM_CAMERA_LOGW("Can't set ISO mode = %lld, too big\n", aValue);
487 return NS_ERROR_INVALID_ARG;
488 }
489
490 nsString s;
491 s.AppendInt(aValue);
492 return SetTranslated(CAMERA_PARAM_ISOMODE, s);
493 }
494 }
495
496 // You can't actually pass 64-bit parameters to Gonk. :(
497 int32_t v = static_cast<int32_t>(aValue);
498 if (static_cast<int64_t>(v) != aValue) {
499 return NS_ERROR_INVALID_ARG;;
500 }
501 return SetImpl(aKey, v);
502 }
503
504 nsresult
505 GonkCameraParameters::GetTranslated(uint32_t aKey, int64_t& aValue)
506 {
507 int val;
508 nsresult rv = GetImpl(aKey, val);
509 if (NS_FAILED(rv)) {
510 return rv;
511 }
512 aValue = val;
513 return NS_OK;
514 }
515
516 // Handle doubles
517 nsresult
518 GonkCameraParameters::SetTranslated(uint32_t aKey, const double& aValue)
519 {
520 int index;
521 int value;
522
523 switch (aKey) {
524 case CAMERA_PARAM_EXPOSURECOMPENSATION:
525 if (mExposureCompensationStep == 0) {
526 DOM_CAMERA_LOGE("Exposure compensation not supported, can't set %f\n", aValue);
527 return NS_ERROR_NOT_AVAILABLE;
528 }
529
530 /**
531 * Convert from real value to a Gonk index, round
532 * to the nearest step; index is 1-based.
533 */
534 index =
535 (aValue - mExposureCompensationMin + mExposureCompensationStep / 2) /
536 mExposureCompensationStep + 1;
537 DOM_CAMERA_LOGI("Exposure compensation = %f --> index = %d\n", aValue, index);
538 return SetImpl(CAMERA_PARAM_EXPOSURECOMPENSATION, index);
539
540 case CAMERA_PARAM_ZOOM:
541 {
542 /**
543 * Convert from a real zoom multipler (e.g. 2.5x) to
544 * the index of the nearest supported value.
545 */
546 value = aValue * 100.0;
547
548 if (value <= mZoomRatios[0]) {
549 index = 0;
550 } else if (value >= mZoomRatios.LastElement()) {
551 index = mZoomRatios.Length() - 1;
552 } else {
553 // mZoomRatios is sorted, so we can binary search it
554 int bottom = 0;
555 int top = mZoomRatios.Length() - 1;
556
557 while (top >= bottom) {
558 index = (top + bottom) / 2;
559 if (value == mZoomRatios[index]) {
560 // exact match
561 break;
562 }
563 if (value > mZoomRatios[index] && value < mZoomRatios[index + 1]) {
564 // the specified zoom value lies in this interval
565 break;
566 }
567 if (value > mZoomRatios[index]) {
568 bottom = index + 1;
569 } else {
570 top = index - 1;
571 }
572 }
573 }
574 DOM_CAMERA_LOGI("Zoom = %fx --> index = %d\n", aValue, index);
575 }
576 return SetImpl(CAMERA_PARAM_ZOOM, index);
577 }
578
579 return SetImpl(aKey, aValue);
580 }
581
582 nsresult
583 GonkCameraParameters::GetTranslated(uint32_t aKey, double& aValue)
584 {
585 double val;
586 int index = 0;
587 double focusDistance[3];
588 const char* s;
589 nsresult rv;
590
591 switch (aKey) {
592 case CAMERA_PARAM_ZOOM:
593 rv = GetImpl(aKey, index);
594 if (NS_SUCCEEDED(rv) && index >= 0) {
595 val = mZoomRatios[index] / 100.0;
596 } else {
597 // return 1x when zooming is not supported
598 val = 1.0;
599 rv = NS_OK;
600 }
601 break;
602
603 /**
604 * The gonk camera parameters API only exposes one focus distance property
605 * that contains "Near,Optimum,Far" distances, in metres, where 'Far' may
606 * be 'Infinity'.
607 */
608 case CAMERA_PARAM_FOCUSDISTANCEFAR:
609 ++index;
610 // intentional fallthrough
611
612 case CAMERA_PARAM_FOCUSDISTANCEOPTIMUM:
613 ++index;
614 // intentional fallthrough
615
616 case CAMERA_PARAM_FOCUSDISTANCENEAR:
617 rv = GetImpl(aKey, s);
618 if (NS_SUCCEEDED(rv)) {
619 if (sscanf(s, "%lf,%lf,%lf", &focusDistance[0], &focusDistance[1], &focusDistance[2]) == 3) {
620 val = focusDistance[index];
621 } else {
622 val = 0.0;
623 }
624 }
625 break;
626
627 case CAMERA_PARAM_EXPOSURECOMPENSATION:
628 rv = GetImpl(aKey, index);
629 if (NS_SUCCEEDED(rv)) {
630 if (!index) {
631 // NaN indicates automatic exposure compensation
632 val = NAN;
633 } else {
634 val = (index - 1) * mExposureCompensationStep + mExposureCompensationMin;
635 DOM_CAMERA_LOGI("index = %d --> compensation = %f\n", index, val);
636 }
637 }
638 break;
639
640 default:
641 rv = GetImpl(aKey, val);
642 break;
643 }
644
645 if (NS_SUCCEEDED(rv)) {
646 aValue = val;
647 }
648 return rv;
649 }
650
651 // Handle ints
652 nsresult
653 GonkCameraParameters::SetTranslated(uint32_t aKey, const int& aValue)
654 {
655 return SetImpl(aKey, aValue);
656 }
657
658 nsresult
659 GonkCameraParameters::GetTranslated(uint32_t aKey, int& aValue)
660 {
661 return GetImpl(aKey, aValue);
662 }
663
664 // Handle uint32_ts -- Gonk only speaks int
665 nsresult
666 GonkCameraParameters::SetTranslated(uint32_t aKey, const uint32_t& aValue)
667 {
668 if (aValue > INT_MAX) {
669 return NS_ERROR_INVALID_ARG;
670 }
671
672 int val = static_cast<int>(aValue);
673 return SetImpl(aKey, val);
674 }
675
676 nsresult
677 GonkCameraParameters::GetTranslated(uint32_t aKey, uint32_t& aValue)
678 {
679 int val;
680 nsresult rv = GetImpl(aKey, val);
681 if (NS_FAILED(rv)) {
682 return rv;
683 }
684 if (val < 0) {
685 return NS_ERROR_FAILURE;
686 }
687
688 aValue = val;
689 return NS_OK;
690 }
691
692 // Handle bools
693 nsresult
694 GonkCameraParameters::SetTranslated(uint32_t aKey, const bool& aValue)
695 {
696 return SetImpl(aKey, aValue);
697 }
698
699 nsresult
700 GonkCameraParameters::GetTranslated(uint32_t aKey, bool& aValue)
701 {
702 return GetImpl(aKey, aValue);
703 }
704
705 nsresult
706 ParseItem(const char* aStart, const char* aEnd, ICameraControl::Size* aItem)
707 {
708 if (sscanf(aStart, "%ux%u", &aItem->width, &aItem->height) == 2) {
709 return NS_OK;
710 }
711
712 DOM_CAMERA_LOGE("Size tuple has bad format: '%s'\n", __func__, __LINE__, aStart);
713 return NS_ERROR_FAILURE;
714 }
715
716 nsresult
717 ParseItem(const char* aStart, const char* aEnd, nsAString* aItem)
718 {
719 if (aEnd) {
720 aItem->AssignASCII(aStart, aEnd - aStart);
721 } else {
722 aItem->AssignASCII(aStart);
723 }
724 return NS_OK;
725 }
726
727 nsresult
728 ParseItem(const char* aStart, const char* aEnd, nsACString* aItem)
729 {
730 if (aEnd) {
731 aItem->AssignASCII(aStart, aEnd - aStart);
732 } else {
733 aItem->AssignASCII(aStart);
734 }
735 return NS_OK;
736 }
737
738 nsresult
739 ParseItem(const char* aStart, const char* aEnd, double* aItem)
740 {
741 if (sscanf(aStart, "%lf", aItem) == 1) {
742 return NS_OK;
743 }
744
745 return NS_ERROR_FAILURE;
746 }
747
748 nsresult
749 ParseItem(const char* aStart, const char* aEnd, int* aItem)
750 {
751 if (sscanf(aStart, "%d", aItem) == 1) {
752 return NS_OK;
753 }
754
755 return NS_ERROR_FAILURE;
756 }
757
758 template<class T> nsresult
759 GonkCameraParameters::GetListAsArray(uint32_t aKey, nsTArray<T>& aArray)
760 {
761 const char* p;
762 nsresult rv = GetImpl(aKey, p);
763 if (NS_FAILED(rv)) {
764 return rv;
765 }
766
767 aArray.Clear();
768
769 // If there is no value available, just return the empty array.
770 if (!p) {
771 DOM_CAMERA_LOGI("Camera parameter %d not available (value is null)\n", aKey);
772 return NS_OK;
773 }
774 if (*p == '\0') {
775 DOM_CAMERA_LOGI("Camera parameter %d not available (value is empty string)\n", aKey);
776 return NS_OK;
777 }
778
779 const char* comma;
780
781 while (p) {
782 T* v = aArray.AppendElement();
783 if (!v) {
784 aArray.Clear();
785 return NS_ERROR_OUT_OF_MEMORY;
786 }
787 comma = strchr(p, ',');
788 if (comma != p) {
789 rv = ParseItem(p, comma, v);
790 if (NS_FAILED(rv)) {
791 aArray.Clear();
792 return rv;
793 }
794 p = comma;
795 }
796 if (p) {
797 ++p;
798 }
799 }
800
801 return NS_OK;
802 }
803
804 nsresult
805 GonkCameraParameters::GetTranslated(uint32_t aKey, nsTArray<nsString>& aValues)
806 {
807 if (aKey == CAMERA_PARAM_SUPPORTED_ISOMODES) {
808 aValues = mIsoModes;
809 return NS_OK;
810 }
811
812 return GetListAsArray(aKey, aValues);
813 }
814
815 nsresult
816 GonkCameraParameters::GetTranslated(uint32_t aKey, nsTArray<double>& aValues)
817 {
818 if (aKey == CAMERA_PARAM_SUPPORTED_ZOOMRATIOS) {
819 aValues.Clear();
820 for (uint32_t i = 0; i < mZoomRatios.Length(); ++i) {
821 *aValues.AppendElement() = mZoomRatios[i] / 100.0;
822 }
823 return NS_OK;
824 }
825
826 return GetListAsArray(aKey, aValues);
827 }
828
829 nsresult
830 GonkCameraParameters::GetTranslated(uint32_t aKey, nsTArray<ICameraControl::Size>& aSizes)
831 {
832 return GetListAsArray(aKey, aSizes);
833 }
834

mercurial