Files
palemoon27/dom/camera/GonkCameraParameters.cpp
T
roytam1 7f8ba9c1d7 import changes from `dev' branch of rmottola/Arctic-Fox:
- Bug 1236786 - [WebGL2] pass getVertexAttrib in gl-object-get-calls.html, r=jgilbert (60a2c91a38)
- Bug 1233046 - Fix OES_texture_float on OSX. - r=jrmuizel (4bc0059f5f)
- Bug 1233557 - Allow RGB8 to be renderable again for web-compat. - r=jrmuizel (4c13bfd8e8)
- Bug 1233549. Disallow ES3 compressed texture formats. r=jgilbert (1073033161)
- Bug 1241702 - Allow unsized DEPTH_STENCIL for RBs in WebGL 2. - r=kamidphish (87d17d2cf9)
- Bug 1239126. Handle gl_InstanceID attribute with no location. r=jgilbert (4894997e98)
- Bug 1236782 - [WebGL2] pass getProgramParameter in gl-object-get-calls.html; r=jgilbert (2136fcce48)
- Bug 1232462. Only ask for a higher version of GLSL when using WebGL2. r=jgilbert (0317be4eb4)
- Bug 1242330 - "Four extensions were promoted to core in WebGL 2 and should no longer be available as extensions." r=jgilbert r=jmuizelaar (6df020b8d4)
- Bug 1233626 - Default MaxDrawingBuffers to 1 unless ext/webgl2. - r=jrmuizel (a7580d661c)
- Bug 1231657. Don't allow linking different versions shaders. r=jgilbert (e610f98066)
- Bug 1241777 - TexCompareFunc should be stored in ascending order. r=jgilbert (b6151a0076)
- Bug 1228885 - Implement WebGLTexture::MemoryUsage. - r=kamidphish (ea06815414)
- Bug 1239259 - Fix WebGL2 generateMipmap checking. r=jgilbert (39f587c421)
- Bug 1242347 - Allow unsized internal format when generate mipmap. r=jgilbert (b203a8898c)
- Bug 1232502. Use the correct internalFormat when calling CopyTexImage2D. r=jgilbert (eeaef3215e)
- Bug 1243663 - Max uniform and attribute location lengths in WebGL2 should be 1024. r=jgilbert (c4ec6de507)
- Bug 1239488 - Add int/uint to vertex attrib data type. r=jgilbert (11b4968025)
- Bug 1184242 - Remove aTabParent != sActiveTabParent warning from IMEStateManager::SetInputContextForChildProcess. r=masayuki (0fcda10e15)
- Bug 1178652 - Send NOTIFY_IME_OF_COMPOSITION_UPDATE to parent process correctly. r=masayuki (bce28e2c91)
- Bug 1107782 - Only accept certain mouse, gamepad events as user-active. r=smaug (00542c80b9)
- Bug 1247850 - Shrink NameTableKey in nsStaticCaseInsensitiveNameTable. r=froydnj,erahm. (ce3cb3edfb)
- Bug 1247359 - micro-optimize the common case of String{Begins,End}With; r=erahm (333e042b31)
- Bug 1239125. Add operator!=(char_type*) to nsTSubstring. r=froydnj (0cc047a9a1)
- Bug 1213862 - Align nsString whitespace handling with web specs; r=froydnj (db5b11ca52)
- Bug 1141884 - Trigger compositor smooth scrolling to snap points when APZ is enabled. r=mstange,kip (593af59f2a)
- Bug 1244582: Add back in a null check that was accidentally removed. r=smaug (76bff1b01f)
- Bug 1234176 - Introduce and use the WriteSysFile() helper function. r=dhylands (22a46fbe8b)
- missing bit of Bug 1198124 - Enable -Wshadow (f84535a7a2)
- Bug 1249171 - Simplify nsCOMArray::SizeOfExcludingThis(). r=erahm. (57efdce1c6)
- Bug 1156416 - Validate camera parameters supplied by the application. r=mikeh (f8b4b84ccf)
- Bug 1186808 - Replace nsBaseHashtable::EnumerateRead() calls in dom/camera/ with iterators. r=mikeh. (7b1db5f6a1)
- Bug 1158378 - Fix how a failed set configuration call would try to shutdown the camera after release. (9d5e323bca)
- Bug 1171374 - Permit software video codecs with the emulated camera. r=sotaro (c1ae26ea0d)
- Bug 1234458 P1 Allow the CacheChild to be "locked" into memory so it will delay destruction. r=ehsan a=ritu (9e46185779)
- Bug 1234458 P2 Lock the CacheChild actor while Cache DOM methods are running. r=ehsan a=ritu (038342a6e2)
- Bug 1244764 P1 Make Cache .add()/.addAll() fail if a Response.ok() is false. r=ehsan (ae26ca9ef1)
- Bug 1172562 - Clear QuotaManager storage when uninstalling an app. Test. r=bkelly (b07311a3b7)
- Bug 1172629 - Use the caches global property from an iframe loaded after setting the pref in order to make the tests pass with the pref disabled; r=bkelly a=RyanVM (e7c05d8b79)
- Bug 1244764 P2 Make dom/cache mochitests pass with new add()/addAll() behavior. r=ehsan (e1f667c1b4)
- Bug 1244764 P3 Make service worker tests pass with new Cache add()/addAll() behavior. r=ehsan (1518ae5225)
- Bug 1003860 - Simplify storage setup tasks in storage inspector tests. r=mratcliffe (249a8bdb2b)
- Bug 1003860 - Service worker cache for storage actor. r=mratcliffe (5c3d1ecd0c)
- Bug 1244764 P5 Fix devtools test to work with new Cache add()/addAll() behavior. r=ehsan (bf85405de8)
- Bug 1232901 - Use channel.asyncOpen2 within dom/browser-element/BrowserElementParent.js (r=sicking,aus) (2a228ed551)
- Bug 1180330 - http auth prompt shown when opening browser if prompt canceled/dismissed earlier. r=fabrice (ba3666f4bd)
- Bug 1234118 - Delete code for supporting 'do-command' and 'copypaste-docommand'. r=mtseng, r=smaug (b1b575d3c5)
- Bug 1238883 - [TV Browser] It shows "The page cannot be displayed" when user browse some webpages. r=roc (e6d7739dd6)
- Bug 1238440 - FileReader should throw an error when the blob changed size when reading, r=khuey (b006adba10)
- Bug 1230422 - FileReader should handle nested ReadAs*() calls. r=khuey (5a3ff84a31)
- Bug 1225202, part 3 - Create files in test_fileapi_slice.html using SpecialPowers.createFiles. r=baku (1137975548)
- Bug 1241171 - FormData should not force 'blob' as filename, r=smaug (748055f751)
- Bug 1246375 - Restore the previous spec version of FormData, r=smaug (3586af2b88)
- Bug 1237183 - Modify implementation of reading preference. r=seanlin (a132bc7246)
- Bug 801545 - Remove DocumentType.internalSubset, r=bz (ea30c9b5ee)
- Bug 1226440 - Expose a method to get a node's immediate dominator; r=bz,sfink (f77ae44037)
- Bug 825318 - Implement adoptDownload for mozDownloadManager, r=aus, r=sicking (e98cb05210)
- Bug 1237370 - Always log the reason for remote AppRep lookup failures. r=gcp (2c804e68fc)
- Bug 1167493 - Application Reputation: disable remote lookup of zip files on Mac/Linux, r=gcp (517459e064)
- Bug 1195519 - Use channel->ascynOpen2 toolkit/components/downloads/ApplicationReputation.cpp (r=sicking) (2856e5213a)
- Bug 1237856 - Add prefs to honor/ignore Application Reputation verdicts. r=gcp (54ee06264f)
- Bug 1243643 - Deprecate unsafe CPOW usage in contentAreaUtils' saveImage. r=jld (6ae790f1ef)
- Bug 1229224: Add an eslint plugin for importing all browser.js globals for browser-chrome tests. r=miker (9df52a7f3b)
- Bug 1245916: Add additional browser window scripts to eslint globals. r=felipe (92d316ca5e)
- Bug 1246244 - Allow non-CPOW documents to pass through saveImageURL properly. r=jaws,Margaret (c8d4ca241d)
- some missing bits after world fix (c0439eebb0)
- add some missing stuff (ddbd47dc03)
- bissing bit of 1229519 (4e255c3dae)
- Bug 1199662 - Crash ping environment block is broken when any string field contains a quotation mark. Unescape INI fields properly using the library that already exists for the purpose. r=ted (874a999edc)
- Bug 1216150 - Turn on the experimental Intl.DateTimeFormat.prototype.formatToParts in b2g certified apps. r=fabrice (40eeb1a4d4)
- Bug 1216150 - Mini-bustage fix for something I think I unintentionally qref'd into the final patch. r=bustage in a CLOSED TREE (36d9b21a67)
- Bug 1141311 - Add async mode support to GonkNativeWindow on Lollipop Gonk r=pchang (39d9d56326)
- Bug 1146671 - Ensure camera not already released when performing operations. r=dhylands (71b59caa1f)
- Bug 1248737. Improve documentation for WorkerRunnable and associated classes. r=khuey (4ff57790c5)
- Bug 1235629 - Remove dead code in WorkerFeature.h, r=smaug (75a51fcf03)
- Bug 1212333 - WorkerDebuggerManager should live on the main thread;r=khuey (11fdfbbae6)
- Bug 1226443 P3 Re-enable service worker update wpt tests. r=ehsan (605dac5f9e)
- Bug 1226443 P4 Cleanup ServiceWorkerScriptCache objects when initialization fails. r=ehsan (43de3429a2)
- Bug 1234127: Change |BluetoothAdapter.pairingReqs| as a nullable object; r=btian, r=mrbkap (45d2038f6a)
- Bug 1188487 - BrowserElement webidl changes for muting and setting volume. r=ehsan (21bea70a07)
- Bug 1238210 - Correct the Promise return types on two Clients methods; r=baku (fa41b25df0)
- Bug 1246784 - Expose Console to the WorkerDebuggerGlobalScope - part 2, r=khuey (0da9ce8ff6)
- Bug 1228702. Don't expose the 'location' property of Exception/DOMException on workers. r=bholley (0fe86ea586)
- Bug 1223825 - Change Directory.path to include the directory's name. r=baku (0cdae4c2f0)
- Bug 1238225 - Mark ExtendableMessageEvent.ports as SameObject; r=baku (45b9a9746f)
- Bug 1236933 - Return null from FetchEvent.clientId for non-subresource network requests; r=bkelly (4a9c4b40cb)
- Bug 1238213 - Make FetchEvent.request non-nullable; r=baku (751082c8ba)
- Bug 1193125 - Avoid corrupting image data in test_fetch_event.html. r=bkelly (9f6bff232f)
- Bug 1201664 - Avoid using Request's constructor when creating FetchEvent.request; r=bkelly (7a3401e345)
- Bug 1175944 - Packaged app's (app://) JS files are not loaded and do not trigger "onfetch" handler. r=jdm (62df139153)
- Bug 1233644 - use pattern matching when listening clear-origin-data. r=baku (ea2594f50e)
- Bug 1237363 - Part 1: Unregister all service workers registered in mochitests at the end of the test; r=jdm (5be97e5bb0)
- Bug 1237363 - Part 2: Fail mochitests which register a service worker without unregistering it; r=jdm (c4160ffd5f)
- Bug 1237363 - Part 3: Add a test for a mochitest finishing without unregistering its service worker; r=jdm (911d37291b)
- Bug 1174078 - Calling "fetch" inside Service Worker's "onfetch" handler in b2g causes "onfetch" again that leads to an infinite loop. Test. r=nsm (208451f346)
- Bug 1197379 - Remove support for intercepting app:// URIs using service workers; r=jdm (3cbdd725f1)
- Bug 1179399 - Part 1: Relax the ShouldIntercept checks when overriding JAR channel info; r=jdm (850bb2bdb8)
- Bug 1238213 follow-up: Mark the FetchEventInit dictionary argument to FetchEvent's constructor optional too; r=bzbarsky (356cbe6db7)
- Bug 1232732 - modify NS_WARNING in MOZ_WIN_MEM_TRY_CATCH; r=aklotz (e2be4d6919)
- Bug 1247658 - Expose a method to JS for find the shortest retaining paths of some nodes in a heap snapshot; r=bz r=jimb (2c82198808)
- Bug 1188115: Expose IDBCursorWithValue in workers. r=baku (e1c40aeb6e)
- Bug 1162680 - Notify Keyboard.jsm to send blur event when the message manager is closed first. r=timdream (53727ab300)
- Bug 1192986 Also mark Cache/CacheStorage as release interfaces on workers. r=ehsan a=bustage (25cf83c154)
- Bug 1159742. Get rid of the pref annotation from test_interfaces, since it basically corresponds to disabling the test. r=jst (c229e3f881)
- Bug 1203160 - Part 2: Fix the interfaces tests to allow SW interfaces for non-release Fennec; r=baku (072840db1f)
- Bug 1197700 - Correct mistakes in InputMethod.webidl. r=kanru, r=janjongboom, sr=smaug (4edb6f201f)
- Bug 1206970 - Stop expecting AnimationPlaybackEvent to be exposed on release branches, where it's disabled by pref, r=smaug (30ae2b13db)
- Bug 1177276 - Pref on canvas.captureStream by default. r=smaug,mt (0cfe0f72f2)
- Bug 1215147 - Enable VR API's on FF for Android by default. r=snorp, r=vlad, r=bz (5ff3725318)
- Bug 1218482 - Enable WebVR By Default,r=bz (f26111ed82)
- Bug 1159755. Stop forcing the media.eme.apiVisible preference to be true in our test harness. r=cpearce (09f7887917)
- Bug 1149312 - Obtain test coverage for the file-backed case of MediaRecorder. r=roc (bd2e7e40f0)
- Bug 1154559 - Remove flaky timeouts from manifest.js and register SimpleTest.registerCleanupFunction() to report unfinished tests. r=cpearce. (eb68db0fb2)
- Bug 1154564 - Add the ability to notify timeouts to MediaTestManager and remove flaky timeouts from test_playback.html. r=cpearce. (c89b4e58d9)
- Bug 1135170 - Fix up racey test_seek-1.html. rpending=mattwoodrow (b3a7d0dcd6)
- Bug 902686 - Change manifest.js to use SpecialPowers.pushPrefEnv. r=edwin (636b0edc1a)
- Bug 1183502 - give androidVersion a correct value in manifest.js. r=sotaro. (933e9ea712)
- Bug 1235588 - add null check to SimpleTest. r=bechen. (958ede68de)
- misspatch (c8922447ff)
- Bug 1151740 - pass the callback object as-is to SpecialPowers.exactGC(). r=edwin (99ca873bce)
- Bug 1197682 - InputMethodManager#setSupportsSwitchingTypes, r=janjongboom, sr=smaug (e7eb54e491)
- Bug 1201407 - Add input-manage-only events for InputMethod API. r=janjongboom, sr=smaug (776d064bd1)
- Bug 1234459 - Expose full text in the input box to InputMethod API, r=masayuki, sr=smaug (4fa0554356)
- Bug 1198163 - Workaround Mochitest app and assign frame proper permissions, r=kanru (c3bcf8ecc1)
- Bug 990250 - Fold nsIStyleSheet into CSSStyleSheet. r=dbaron (23579cb300)
2024-01-16 11:25:53 +08:00

1077 lines
31 KiB
C++

/*
* Copyright (C) 2013-2015 Mozilla Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "GonkCameraParameters.h"
#include "CameraPreferences.h"
#include "ICameraControl.h"
#include "CameraCommon.h"
#include "mozilla/Hal.h"
#include "nsDataHashtable.h"
#include "nsPrintfCString.h"
using namespace mozilla;
using namespace android;
/* static */ bool
GonkCameraParameters::IsLowMemoryPlatform()
{
bool testIsLowMem = false;
CameraPreferences::GetPref("camera.control.test.is_low_memory", testIsLowMem);
if (testIsLowMem) {
NS_WARNING("Forcing low-memory platform camera preferences");
return true;
}
uint32_t lowMemoryThresholdBytes = 0;
CameraPreferences::GetPref("camera.control.low_memory_thresholdMB",
lowMemoryThresholdBytes);
lowMemoryThresholdBytes *= 1024 * 1024;
if (lowMemoryThresholdBytes) {
uint32_t totalMemoryBytes = hal::GetTotalSystemMemory();
if (totalMemoryBytes < lowMemoryThresholdBytes) {
DOM_CAMERA_LOGI("Low-memory platform with %d bytes of RAM (threshold: <%d bytes)\n",
totalMemoryBytes, lowMemoryThresholdBytes);
return true;
}
}
return false;
}
const char*
GonkCameraParameters::FindVendorSpecificKey(const char* aPotentialKeys[],
size_t aPotentialKeyCount)
{
const char* val;
for (size_t i = 0; i < aPotentialKeyCount; ++i) {
GetImpl(aPotentialKeys[i], val);
if (val) {
// We received a value (potentially an empty-string one),
// which indicates that this key exists.
return aPotentialKeys[i];
}
}
return nullptr;
}
String8
GonkCameraParameters::Flatten() const
{
MutexAutoLock lock(mLock);
nsCString data;
for (auto iter = mParams.ConstIter(); !iter.Done(); iter.Next()) {
if (!data.IsEmpty()) {
data.Append(';');
}
data.Append(iter.Key());
data.Append('=');
data.Append(*iter.UserData());
}
return String8(data.Data());
}
nsresult
GonkCameraParameters::Unflatten(const String8& aFlatParameters)
{
MutexAutoLock lock(mLock);
mParams.Clear();
const char* data = aFlatParameters.string();
while (data && *data) {
const char* pos = strchr(data, '=');
if (!pos) {
break;
}
nsDependentCSubstring key(data, pos - data);
data = pos + 1;
nsCString* value;
pos = strchr(data, ';');
if (pos) {
value = new nsCString(data, pos - data);
data = pos + 1;
} else {
value = new nsCString(data);
data = nullptr;
}
mParams.Put(key, value);
}
if (mInitialized) {
return NS_OK;
}
// We call Initialize() once when the parameter set is first loaded,
// to set up any constant values this class requires internally,
// e.g. the exposure compensation step and limits.
return Initialize();
}
const char*
GonkCameraParameters::GetTextKey(uint32_t aKey)
{
switch (aKey) {
case CAMERA_PARAM_PREVIEWSIZE:
return CameraParameters::KEY_PREVIEW_SIZE;
case CAMERA_PARAM_PREVIEWFORMAT:
return CameraParameters::KEY_PREVIEW_FORMAT;
case CAMERA_PARAM_PREVIEWFRAMERATE:
return CameraParameters::KEY_PREVIEW_FRAME_RATE;
case CAMERA_PARAM_EFFECT:
return CameraParameters::KEY_EFFECT;
case CAMERA_PARAM_WHITEBALANCE:
return CameraParameters::KEY_WHITE_BALANCE;
case CAMERA_PARAM_SCENEMODE:
return CameraParameters::KEY_SCENE_MODE;
case CAMERA_PARAM_FLASHMODE:
return CameraParameters::KEY_FLASH_MODE;
case CAMERA_PARAM_FOCUSMODE:
return CameraParameters::KEY_FOCUS_MODE;
case CAMERA_PARAM_ZOOM:
return CameraParameters::KEY_ZOOM;
case CAMERA_PARAM_METERINGAREAS:
return CameraParameters::KEY_METERING_AREAS;
case CAMERA_PARAM_FOCUSAREAS:
return CameraParameters::KEY_FOCUS_AREAS;
case CAMERA_PARAM_FOCALLENGTH:
return CameraParameters::KEY_FOCAL_LENGTH;
case CAMERA_PARAM_FOCUSDISTANCENEAR:
return CameraParameters::KEY_FOCUS_DISTANCES;
case CAMERA_PARAM_FOCUSDISTANCEOPTIMUM:
return CameraParameters::KEY_FOCUS_DISTANCES;
case CAMERA_PARAM_FOCUSDISTANCEFAR:
return CameraParameters::KEY_FOCUS_DISTANCES;
case CAMERA_PARAM_EXPOSURECOMPENSATION:
return CameraParameters::KEY_EXPOSURE_COMPENSATION;
case CAMERA_PARAM_THUMBNAILQUALITY:
return CameraParameters::KEY_JPEG_THUMBNAIL_QUALITY;
case CAMERA_PARAM_PICTURE_SIZE:
return CameraParameters::KEY_PICTURE_SIZE;
case CAMERA_PARAM_PICTURE_FILEFORMAT:
return CameraParameters::KEY_PICTURE_FORMAT;
case CAMERA_PARAM_PICTURE_ROTATION:
return CameraParameters::KEY_ROTATION;
case CAMERA_PARAM_PICTURE_DATETIME:
// Not every platform defines a CameraParameters::EXIF_DATETIME;
// for those that don't, we use the raw string key, and if the platform
// doesn't support it, it will be ignored.
//
// See bug 832494.
return "exif-datetime";
case CAMERA_PARAM_VIDEOSIZE:
return CameraParameters::KEY_VIDEO_SIZE;
case CAMERA_PARAM_ISOMODE:
if (!mVendorSpecificKeyIsoMode) {
const char* isoModeKeys[] = {
"iso",
"sony-iso"
};
mVendorSpecificKeyIsoMode =
FindVendorSpecificKey(isoModeKeys, MOZ_ARRAY_LENGTH(isoModeKeys));
}
return mVendorSpecificKeyIsoMode;
case CAMERA_PARAM_LUMINANCE:
return "luminance-condition";
case CAMERA_PARAM_SCENEMODE_HDR_RETURNNORMALPICTURE:
// Not every platform defines CameraParameters::QC_HDR_NEED_1X;
// for those that don't, we use the raw string key.
return "hdr-need-1x";
case CAMERA_PARAM_RECORDINGHINT:
return CameraParameters::KEY_RECORDING_HINT;
case CAMERA_PARAM_PICTURE_QUALITY:
return CameraParameters::KEY_JPEG_QUALITY;
case CAMERA_PARAM_PREFERRED_PREVIEWSIZE_FOR_VIDEO:
return CameraParameters::KEY_PREFERRED_PREVIEW_SIZE_FOR_VIDEO;
case CAMERA_PARAM_METERINGMODE:
// Not every platform defines CameraParameters::AUTO_EXPOSURE.
return "auto-exposure";
case CAMERA_PARAM_SUPPORTED_PREVIEWSIZES:
return CameraParameters::KEY_SUPPORTED_PREVIEW_SIZES;
case CAMERA_PARAM_SUPPORTED_PICTURESIZES:
return CameraParameters::KEY_SUPPORTED_PICTURE_SIZES;
case CAMERA_PARAM_SUPPORTED_VIDEOSIZES:
return CameraParameters::KEY_SUPPORTED_VIDEO_SIZES;
case CAMERA_PARAM_SUPPORTED_PICTUREFORMATS:
return CameraParameters::KEY_SUPPORTED_PICTURE_FORMATS;
case CAMERA_PARAM_SUPPORTED_WHITEBALANCES:
return CameraParameters::KEY_SUPPORTED_WHITE_BALANCE;
case CAMERA_PARAM_SUPPORTED_SCENEMODES:
return CameraParameters::KEY_SUPPORTED_SCENE_MODES;
case CAMERA_PARAM_SUPPORTED_EFFECTS:
return CameraParameters::KEY_SUPPORTED_EFFECTS;
case CAMERA_PARAM_SUPPORTED_FLASHMODES:
return CameraParameters::KEY_SUPPORTED_FLASH_MODES;
case CAMERA_PARAM_SUPPORTED_FOCUSMODES:
return CameraParameters::KEY_SUPPORTED_FOCUS_MODES;
case CAMERA_PARAM_SUPPORTED_MAXFOCUSAREAS:
return CameraParameters::KEY_MAX_NUM_FOCUS_AREAS;
case CAMERA_PARAM_SUPPORTED_MAXMETERINGAREAS:
return CameraParameters::KEY_MAX_NUM_METERING_AREAS;
case CAMERA_PARAM_SUPPORTED_MINEXPOSURECOMPENSATION:
return CameraParameters::KEY_MIN_EXPOSURE_COMPENSATION;
case CAMERA_PARAM_SUPPORTED_MAXEXPOSURECOMPENSATION:
return CameraParameters::KEY_MAX_EXPOSURE_COMPENSATION;
case CAMERA_PARAM_SUPPORTED_EXPOSURECOMPENSATIONSTEP:
return CameraParameters::KEY_EXPOSURE_COMPENSATION_STEP;
case CAMERA_PARAM_SUPPORTED_ZOOM:
return CameraParameters::KEY_ZOOM_SUPPORTED;
case CAMERA_PARAM_SUPPORTED_ZOOMRATIOS:
return CameraParameters::KEY_ZOOM_RATIOS;
case CAMERA_PARAM_SUPPORTED_MAXDETECTEDFACES:
return CameraParameters::KEY_MAX_NUM_DETECTED_FACES_HW;
case CAMERA_PARAM_SUPPORTED_JPEG_THUMBNAIL_SIZES:
return CameraParameters::KEY_SUPPORTED_JPEG_THUMBNAIL_SIZES;
case CAMERA_PARAM_SUPPORTED_ISOMODES:
if (!mVendorSpecificKeySupportedIsoModes) {
const char* supportedIsoModesKeys[] = {
"iso-values",
"sony-iso-values"
};
mVendorSpecificKeySupportedIsoModes =
FindVendorSpecificKey(supportedIsoModesKeys,
MOZ_ARRAY_LENGTH(supportedIsoModesKeys));
}
return mVendorSpecificKeySupportedIsoModes;
case CAMERA_PARAM_SUPPORTED_METERINGMODES:
// Not every platform defines CameraParameters::SUPPORTED_AUTO_EXPOSURE.
return "auto-exposure-values";
default:
DOM_CAMERA_LOGE("Unhandled camera parameter value %u\n", aKey);
return nullptr;
}
}
GonkCameraParameters::GonkCameraParameters()
: mLock("mozilla::camera::GonkCameraParameters")
, mDirty(false)
, mInitialized(false)
, mExposureCompensationStep(0.0)
, mVendorSpecificKeyIsoMode(nullptr)
, mVendorSpecificKeySupportedIsoModes(nullptr)
{
MOZ_COUNT_CTOR(GonkCameraParameters);
}
GonkCameraParameters::~GonkCameraParameters()
{
MOZ_COUNT_DTOR(GonkCameraParameters);
mIsoModeMap.Clear();
}
nsresult
GonkCameraParameters::MapIsoToGonk(const nsAString& aIso, nsACString& aIsoOut)
{
nsCString* s;
if (mIsoModeMap.Get(aIso, &s)) {
if (!s) {
DOM_CAMERA_LOGE("ISO mode '%s' maps to null Gonk ISO value\n",
NS_LossyConvertUTF16toASCII(aIso).get());
return NS_ERROR_FAILURE;
}
aIsoOut = *s;
return NS_OK;
}
return NS_ERROR_INVALID_ARG;
}
nsresult
GonkCameraParameters::MapIsoFromGonk(const char* aIso, nsAString& aIsoOut)
{
if (!aIso) {
return NS_ERROR_NOT_AVAILABLE;
}
if (strcmp(aIso, "ISO_HJR") == 0) {
aIsoOut.AssignASCII("hjr");
} else if (strcmp(aIso, "auto") == 0) {
aIsoOut.AssignASCII("auto");
} else {
unsigned int iso;
char ignored;
// Some camera libraries return ISO modes as "ISO100", others as "100".
if (sscanf(aIso, "ISO%u%c", &iso, &ignored) != 1 &&
sscanf(aIso, "%u%c", &iso, &ignored) != 1) {
return NS_ERROR_INVALID_ARG;
}
aIsoOut.Truncate(0);
aIsoOut.AppendInt(iso);
}
return NS_OK;
}
// Any members that need to be initialized on the first parameter pull
// need to get handled in here.
nsresult
GonkCameraParameters::Initialize()
{
nsresult rv;
rv = GetImpl(CameraParameters::KEY_EXPOSURE_COMPENSATION_STEP, mExposureCompensationStep);
if (NS_FAILED(rv)) {
NS_WARNING("Failed to initialize exposure compensation step size");
mExposureCompensationStep = 0.0;
}
rv = GetImpl(CameraParameters::KEY_MIN_EXPOSURE_COMPENSATION, mExposureCompensationMinIndex);
if (NS_FAILED(rv)) {
NS_WARNING("Failed to initialize minimum exposure compensation index");
mExposureCompensationMinIndex = 0;
}
rv = GetImpl(CameraParameters::KEY_MAX_EXPOSURE_COMPENSATION, mExposureCompensationMaxIndex);
if (NS_FAILED(rv)) {
NS_WARNING("Failed to initialize maximum exposure compensation index");
mExposureCompensationMaxIndex = 0;
}
rv = GetListAsArray(CAMERA_PARAM_SUPPORTED_ZOOMRATIOS, mZoomRatios);
if (NS_FAILED(rv)) {
// zoom is not supported
mZoomRatios.Clear();
}
for (uint32_t i = 1; i < mZoomRatios.Length(); ++i) {
// Make sure the camera gave us a properly sorted zoom ratio list!
if (mZoomRatios[i] < mZoomRatios[i - 1]) {
NS_WARNING("Zoom ratios list is out of order, discarding");
DOM_CAMERA_LOGE("zoom[%d]=%fx < zoom[%d]=%fx is out of order\n",
i, mZoomRatios[i] / 100.0, i - 1, mZoomRatios[i - 1] / 100.0);
mZoomRatios.Clear();
break;
}
}
if (mZoomRatios.Length() == 0) {
// Always report that we support at least 1.0x zoom.
*mZoomRatios.AppendElement() = 100;
}
// The return code from GetListAsArray() doesn't matter. If it fails,
// the isoModes array will be empty, and the subsequent loop won't
// execute.
nsString s;
nsTArray<nsCString> isoModes;
GetListAsArray(CAMERA_PARAM_SUPPORTED_ISOMODES, isoModes);
for (nsTArray<nsCString>::index_type i = 0; i < isoModes.Length(); ++i) {
rv = MapIsoFromGonk(isoModes[i].get(), s);
if (NS_FAILED(rv)) {
DOM_CAMERA_LOGW("Unrecognized ISO mode value '%s'\n", isoModes[i].get());
continue;
}
*mIsoModes.AppendElement() = s;
mIsoModeMap.Put(s, new nsCString(isoModes[i]));
}
GetListAsArray(CAMERA_PARAM_SUPPORTED_SCENEMODES, mSceneModes);
if (IsLowMemoryPlatform()) {
bool hdrRemoved = false;
while (mSceneModes.RemoveElement(NS_LITERAL_STRING("hdr"))) {
hdrRemoved = true;
}
if (hdrRemoved) {
DOM_CAMERA_LOGI("Disabling HDR support due to low memory\n");
}
}
// Some platforms have strange duplicate metering mode values.
// We filter any out here.
nsDataHashtable<nsStringHashKey, bool> uniqueModes;
GetListAsArray(CAMERA_PARAM_SUPPORTED_METERINGMODES, mMeteringModes);
nsTArray<nsCString>::index_type i = mMeteringModes.Length();
while (i > 0) {
--i;
if (!uniqueModes.Get(mMeteringModes[i])) {
uniqueModes.Put(mMeteringModes[i], true);
} else {
DOM_CAMERA_LOGW("Dropped duplicate metering mode '%s' (index=%u)\n",
NS_ConvertUTF16toUTF8(mMeteringModes[i]).get(), i);
mMeteringModes.RemoveElementAt(i);
}
}
mInitialized = true;
return NS_OK;
}
// Handle nsAStrings
nsresult
GonkCameraParameters::SetTranslated(uint32_t aKey, const nsAString& aValue)
{
switch (aKey) {
case CAMERA_PARAM_ISOMODE:
{
nsAutoCString v;
nsresult rv = MapIsoToGonk(aValue, v);
if (NS_FAILED(rv)) {
return rv;
}
return SetImpl(aKey, v.get());
}
case CAMERA_PARAM_SCENEMODE:
if (mSceneModes.IndexOf(aValue) == nsTArray<nsString>::NoIndex) {
return NS_ERROR_INVALID_ARG;
}
// fallthrough
default:
return SetImpl(aKey, NS_ConvertUTF16toUTF8(aValue).get());
}
}
nsresult
GonkCameraParameters::GetTranslated(uint32_t aKey, nsAString& aValue)
{
const char* val;
nsresult rv = GetImpl(aKey, val);
if (NS_FAILED(rv)) {
return rv;
}
if (val) {
if (aKey == CAMERA_PARAM_ISOMODE) {
rv = MapIsoFromGonk(val, aValue);
} else {
aValue.AssignASCII(val);
}
} else {
aValue.Truncate(0);
}
return rv;
}
// Handle ICameraControl::Sizes
nsresult
GonkCameraParameters::SetTranslated(uint32_t aKey, const ICameraControl::Size& aSize)
{
if (aSize.width > INT_MAX || aSize.height > INT_MAX) {
// AOSP can only handle signed ints.
DOM_CAMERA_LOGE("Camera parameter aKey=%d out of bounds (width=%u, height=%u)\n",
aKey, aSize.width, aSize.height);
return NS_ERROR_INVALID_ARG;
}
nsresult rv;
switch (aKey) {
case CAMERA_PARAM_THUMBNAILSIZE:
// This is a special case--for some reason the thumbnail size
// is accessed as two separate values instead of a tuple.
// XXXmikeh - make this restore the original values on error
rv = SetImpl(CameraParameters::KEY_JPEG_THUMBNAIL_WIDTH, static_cast<int>(aSize.width));
if (NS_SUCCEEDED(rv)) {
rv = SetImpl(CameraParameters::KEY_JPEG_THUMBNAIL_HEIGHT, static_cast<int>(aSize.height));
}
break;
case CAMERA_PARAM_VIDEOSIZE:
// "record-size" is probably deprecated in later ICS;
// might need to set "video-size" instead of "record-size";
// for the time being, set both. See bug 795332.
rv = SetImpl("record-size", nsPrintfCString("%ux%u", aSize.width, aSize.height).get());
if (NS_FAILED(rv)) {
break;
}
// intentional fallthrough
default:
rv = SetImpl(aKey, nsPrintfCString("%ux%u", aSize.width, aSize.height).get());
break;
}
if (NS_FAILED(rv)) {
DOM_CAMERA_LOGE("Camera parameter aKey=%d failed to set (0x%x)\n", aKey, rv);
}
return rv;
}
nsresult
GonkCameraParameters::GetTranslated(uint32_t aKey, ICameraControl::Size& aSize)
{
nsresult rv;
if (aKey == CAMERA_PARAM_THUMBNAILSIZE) {
int width;
int height;
rv = GetImpl(CameraParameters::KEY_JPEG_THUMBNAIL_WIDTH, width);
if (NS_FAILED(rv)) {
return rv;
}
if (width < 0) {
return NS_ERROR_NOT_AVAILABLE;
}
rv = GetImpl(CameraParameters::KEY_JPEG_THUMBNAIL_HEIGHT, height);
if (NS_FAILED(rv)) {
return rv;
}
if (height < 0) {
return NS_ERROR_NOT_AVAILABLE;
}
aSize.width = static_cast<uint32_t>(width);
aSize.height = static_cast<uint32_t>(height);
return NS_OK;
}
const char* value;
rv = GetImpl(aKey, value);
if (NS_FAILED(rv)) {
return rv;
}
if (!value || *value == '\0') {
DOM_CAMERA_LOGW("Camera parameter aKey=%d not available\n", aKey);
return NS_ERROR_NOT_AVAILABLE;
}
if (sscanf(value, "%ux%u", &aSize.width, &aSize.height) != 2) {
DOM_CAMERA_LOGE("Camera parameter aKey=%d size tuple '%s' is invalid\n", aKey, value);
return NS_ERROR_NOT_AVAILABLE;
}
return NS_OK;
}
// Handle arrays of ICameraControl::Regions
nsresult
GonkCameraParameters::SetTranslated(uint32_t aKey, const nsTArray<ICameraControl::Region>& aRegions)
{
uint32_t length = aRegions.Length();
if (!length) {
// This tells the camera driver to revert to automatic regioning.
return SetImpl(aKey, "(0,0,0,0,0)");
}
nsCString s;
for (uint32_t i = 0; i < length; ++i) {
const ICameraControl::Region* r = &aRegions[i];
s.AppendPrintf("(%d,%d,%d,%d,%d),", r->left, r->top, r->right, r->bottom, r->weight);
}
// remove the trailing comma
s.Trim(",", false, true, true);
return SetImpl(aKey, s.get());
}
nsresult
GonkCameraParameters::GetTranslated(uint32_t aKey, nsTArray<ICameraControl::Region>& aRegions)
{
aRegions.Clear();
const char* value;
nsresult rv = GetImpl(aKey, value);
if (NS_FAILED(rv)) {
return rv;
}
if (!value || *value == '\0') {
DOM_CAMERA_LOGW("Camera parameter aKey=%d not available\n", aKey);
return NS_ERROR_NOT_AVAILABLE;
}
const char* p = value;
uint32_t count = 1;
// count the number of regions in the string
while ((p = strstr(p, "),("))) {
++count;
p += 3;
}
aRegions.SetCapacity(count);
ICameraControl::Region* r;
// parse all of the region sets
uint32_t i;
for (i = 0, p = value; p && i < count; ++i, p = strchr(p + 1, '(')) {
r = aRegions.AppendElement();
if (sscanf(p, "(%d,%d,%d,%d,%u)", &r->left, &r->top, &r->right, &r->bottom, &r->weight) != 5) {
DOM_CAMERA_LOGE("Camera parameter aKey=%d region tuple has bad format: '%s'\n", aKey, p);
aRegions.Clear();
return NS_ERROR_NOT_AVAILABLE;
}
}
return NS_OK;
}
// Handle ICameraControl::Positions
nsresult
GonkCameraParameters::SetTranslated(uint32_t aKey, const ICameraControl::Position& aPosition)
{
MOZ_ASSERT(aKey == CAMERA_PARAM_PICTURE_LOCATION);
// Add any specified location information -- we don't care if these fail.
if (!isnan(aPosition.latitude)) {
DOM_CAMERA_LOGI("setting picture latitude to %lf\n", aPosition.latitude);
SetImpl(CameraParameters::KEY_GPS_LATITUDE, nsPrintfCString("%lf", aPosition.latitude).get());
} else {
ClearImpl(CameraParameters::KEY_GPS_LATITUDE);
}
if (!isnan(aPosition.longitude)) {
DOM_CAMERA_LOGI("setting picture longitude to %lf\n", aPosition.longitude);
SetImpl(CameraParameters::KEY_GPS_LONGITUDE, nsPrintfCString("%lf", aPosition.longitude).get());
} else {
ClearImpl(CameraParameters::KEY_GPS_LONGITUDE);
}
if (!isnan(aPosition.altitude)) {
DOM_CAMERA_LOGI("setting picture altitude to %lf\n", aPosition.altitude);
SetImpl(CameraParameters::KEY_GPS_ALTITUDE, nsPrintfCString("%lf", aPosition.altitude).get());
} else {
ClearImpl(CameraParameters::KEY_GPS_ALTITUDE);
}
if (!isnan(aPosition.timestamp)) {
DOM_CAMERA_LOGI("setting picture timestamp to %lf\n", aPosition.timestamp);
SetImpl(CameraParameters::KEY_GPS_TIMESTAMP, nsPrintfCString("%lf", aPosition.timestamp).get());
} else {
ClearImpl(CameraParameters::KEY_GPS_TIMESTAMP);
}
return NS_OK;
}
// Handle int64_ts
nsresult
GonkCameraParameters::SetTranslated(uint32_t aKey, const int64_t& aValue)
{
switch (aKey) {
case CAMERA_PARAM_PICTURE_DATETIME:
{
// Add the non-GPS timestamp. The EXIF date/time field is formatted as
// "YYYY:MM:DD HH:MM:SS", without room for a time-zone; as such, the time
// is meant to be stored as a local time. Since we are given seconds from
// Epoch GMT, we use localtime_r() to handle the conversion.
time_t time = aValue;
if (time != aValue) {
DOM_CAMERA_LOGE("picture date/time '%llu' is too far in the future\n", aValue);
return NS_ERROR_INVALID_ARG;
}
struct tm t;
if (!localtime_r(&time, &t)) {
DOM_CAMERA_LOGE("picture date/time couldn't be converted to local time: (%d) %s\n", errno, strerror(errno));
return NS_ERROR_FAILURE;
}
char dateTime[20];
if (!strftime(dateTime, sizeof(dateTime), "%Y:%m:%d %T", &t)) {
DOM_CAMERA_LOGE("picture date/time couldn't be converted to string\n");
return NS_ERROR_FAILURE;
}
DOM_CAMERA_LOGI("setting picture date/time to %s\n", dateTime);
return SetImpl(CAMERA_PARAM_PICTURE_DATETIME, dateTime);
}
case CAMERA_PARAM_ISOMODE:
{
if (aValue > INT32_MAX) {
DOM_CAMERA_LOGW("Can't set ISO mode = %lld, too big\n", aValue);
return NS_ERROR_INVALID_ARG;
}
nsString s;
s.AppendInt(aValue);
return SetTranslated(CAMERA_PARAM_ISOMODE, s);
}
}
// You can't actually pass 64-bit parameters to Gonk. :(
int32_t v = static_cast<int32_t>(aValue);
if (static_cast<int64_t>(v) != aValue) {
return NS_ERROR_INVALID_ARG;;
}
return SetImpl(aKey, v);
}
nsresult
GonkCameraParameters::GetTranslated(uint32_t aKey, int64_t& aValue)
{
int val;
nsresult rv = GetImpl(aKey, val);
if (NS_FAILED(rv)) {
return rv;
}
aValue = val;
return NS_OK;
}
// Handle doubles
nsresult
GonkCameraParameters::SetTranslated(uint32_t aKey, const double& aValue)
{
int index;
int value;
switch (aKey) {
case CAMERA_PARAM_EXPOSURECOMPENSATION:
if (mExposureCompensationStep == 0.0) {
DOM_CAMERA_LOGE("Exposure compensation not supported, can't set EV=%f\n", aValue);
return NS_ERROR_NOT_AVAILABLE;
}
/**
* Convert from real value to a Gonk index, round
* to the nearest step; index is 1-based.
*/
{
double i = round(aValue / mExposureCompensationStep);
if (i < mExposureCompensationMinIndex) {
index = mExposureCompensationMinIndex;
} else if (i > mExposureCompensationMaxIndex) {
index = mExposureCompensationMaxIndex;
} else {
index = i;
}
}
DOM_CAMERA_LOGI("Exposure compensation = %f --> index = %d\n", aValue, index);
return SetImpl(CAMERA_PARAM_EXPOSURECOMPENSATION, index);
case CAMERA_PARAM_ZOOM:
{
/**
* Convert from a real zoom multipler (e.g. 2.5x) to
* the index of the nearest supported value.
*/
value = aValue * 100.0;
if (value <= mZoomRatios[0]) {
index = 0;
} else if (value >= mZoomRatios.LastElement()) {
index = mZoomRatios.Length() - 1;
} else {
// mZoomRatios is sorted, so we can binary search it
int bottom = 0;
int top = mZoomRatios.Length() - 1;
while (top >= bottom) {
index = (top + bottom) / 2;
if (value == mZoomRatios[index]) {
// exact match
break;
}
if (value > mZoomRatios[index] && value < mZoomRatios[index + 1]) {
// the specified zoom value lies in this interval
break;
}
if (value > mZoomRatios[index]) {
bottom = index + 1;
} else {
top = index - 1;
}
}
}
DOM_CAMERA_LOGI("Zoom = %fx --> index = %d\n", aValue, index);
}
return SetImpl(CAMERA_PARAM_ZOOM, index);
case CAMERA_PARAM_PICTURE_QUALITY:
{
// Convert aValue [0.0..1.0] to nearest index in the range [1..100].
index = (aValue + 0.005) * 99.0 + 1.0;
if (aValue < 0.0) {
index = 1;
} else if (aValue > 1.0) {
index = 100;
}
DOM_CAMERA_LOGI("Picture quality = %f --> index = %d\n", aValue, index);
}
return SetImpl(CAMERA_PARAM_PICTURE_QUALITY, index);
}
return SetImpl(aKey, aValue);
}
nsresult
GonkCameraParameters::GetTranslated(uint32_t aKey, double& aValue)
{
double val = 0.0; // initialize to keep the compiler happy [-Wmaybe-uninitialized]
int index = 0;
double focusDistance[3];
const char* s;
nsresult rv;
switch (aKey) {
case CAMERA_PARAM_ZOOM:
rv = GetImpl(aKey, index);
if (NS_SUCCEEDED(rv) && index >= 0) {
val = mZoomRatios[index] / 100.0;
} else {
// return 1x when zooming is not supported
val = 1.0;
rv = NS_OK;
}
break;
/**
* The gonk camera parameters API only exposes one focus distance property
* that contains "Near,Optimum,Far" distances, in metres, where 'Far' may
* be 'Infinity'.
*/
case CAMERA_PARAM_FOCUSDISTANCEFAR:
++index;
// intentional fallthrough
case CAMERA_PARAM_FOCUSDISTANCEOPTIMUM:
++index;
// intentional fallthrough
case CAMERA_PARAM_FOCUSDISTANCENEAR:
rv = GetImpl(aKey, s);
if (NS_SUCCEEDED(rv)) {
if (sscanf(s, "%lf,%lf,%lf", &focusDistance[0], &focusDistance[1], &focusDistance[2]) == 3) {
val = focusDistance[index];
} else {
val = 0.0;
}
}
break;
case CAMERA_PARAM_EXPOSURECOMPENSATION:
case CAMERA_PARAM_SUPPORTED_MINEXPOSURECOMPENSATION:
case CAMERA_PARAM_SUPPORTED_MAXEXPOSURECOMPENSATION:
if (mExposureCompensationStep == 0.0) {
DOM_CAMERA_LOGE("Exposure compensation not supported, can't get EV\n");
return NS_ERROR_NOT_AVAILABLE;
}
rv = GetImpl(aKey, index);
if (NS_SUCCEEDED(rv)) {
val = index * mExposureCompensationStep;
DOM_CAMERA_LOGI("exposure compensation (aKey=%d): index=%d --> EV=%f\n", aKey, index, val);
}
break;
case CAMERA_PARAM_PICTURE_QUALITY:
// Convert index [1..100] to a quality value [0.0..1.0].
rv = GetImpl(aKey, index);
if (index < 2) {
val = 0.0;
} else if (index > 99) {
val = 1.0;
} else {
val = static_cast<double>(index - 1) / 99.0;
}
DOM_CAMERA_LOGI("index = %d --> picture quality = %f\n", index, val);
break;
default:
rv = GetImpl(aKey, val);
break;
}
if (NS_SUCCEEDED(rv)) {
aValue = val;
}
return rv;
}
// Handle ints
nsresult
GonkCameraParameters::SetTranslated(uint32_t aKey, const int& aValue)
{
return SetImpl(aKey, aValue);
}
nsresult
GonkCameraParameters::GetTranslated(uint32_t aKey, int& aValue)
{
return GetImpl(aKey, aValue);
}
// Handle uint32_ts -- Gonk only speaks int
nsresult
GonkCameraParameters::SetTranslated(uint32_t aKey, const uint32_t& aValue)
{
if (aValue > INT_MAX) {
return NS_ERROR_INVALID_ARG;
}
int val = static_cast<int>(aValue);
return SetImpl(aKey, val);
}
nsresult
GonkCameraParameters::GetTranslated(uint32_t aKey, uint32_t& aValue)
{
int val;
nsresult rv = GetImpl(aKey, val);
if (NS_FAILED(rv)) {
return rv;
}
if (val < 0) {
return NS_ERROR_NOT_AVAILABLE;
}
aValue = val;
return NS_OK;
}
// Handle bools
nsresult
GonkCameraParameters::SetTranslated(uint32_t aKey, const bool& aValue)
{
return SetImpl(aKey, aValue);
}
nsresult
GonkCameraParameters::GetTranslated(uint32_t aKey, bool& aValue)
{
return GetImpl(aKey, aValue);
}
nsresult
ParseItem(const char* aStart, const char* aEnd, ICameraControl::Size* aItem)
{
if (sscanf(aStart, "%ux%u", &aItem->width, &aItem->height) == 2) {
return NS_OK;
}
DOM_CAMERA_LOGE("Size tuple has bad format: '%s'\n", aStart);
return NS_ERROR_NOT_AVAILABLE;
}
nsresult
ParseItem(const char* aStart, const char* aEnd, nsAString* aItem)
{
if (aEnd) {
aItem->AssignASCII(aStart, aEnd - aStart);
} else {
aItem->AssignASCII(aStart);
}
return NS_OK;
}
nsresult
ParseItem(const char* aStart, const char* aEnd, nsACString* aItem)
{
if (aEnd) {
aItem->AssignASCII(aStart, aEnd - aStart);
} else {
aItem->AssignASCII(aStart);
}
return NS_OK;
}
nsresult
ParseItem(const char* aStart, const char* aEnd, double* aItem)
{
if (sscanf(aStart, "%lf", aItem) == 1) {
return NS_OK;
}
return NS_ERROR_NOT_AVAILABLE;
}
nsresult
ParseItem(const char* aStart, const char* aEnd, int* aItem)
{
if (sscanf(aStart, "%d", aItem) == 1) {
return NS_OK;
}
return NS_ERROR_NOT_AVAILABLE;
}
template<class T> nsresult
GonkCameraParameters::GetListAsArray(uint32_t aKey, nsTArray<T>& aArray)
{
const char* p;
nsresult rv = GetImpl(aKey, p);
if (NS_FAILED(rv)) {
return rv;
}
aArray.Clear();
// If there is no value available, just return the empty array.
if (!p) {
DOM_CAMERA_LOGI("Camera parameter %d not available (value is null)\n", aKey);
return NS_OK;
}
if (*p == '\0') {
DOM_CAMERA_LOGI("Camera parameter %d not available (value is empty string)\n", aKey);
return NS_OK;
}
const char* comma;
while (p) {
// nsTArray::AppendElement() is infallible
T* v = aArray.AppendElement();
comma = strchr(p, ',');
if (comma != p) {
rv = ParseItem(p, comma, v);
if (NS_FAILED(rv)) {
aArray.Clear();
return rv;
}
p = comma;
}
if (p) {
++p;
}
}
return NS_OK;
}
nsresult
GonkCameraParameters::GetTranslated(uint32_t aKey, nsTArray<nsString>& aValues)
{
switch (aKey) {
case CAMERA_PARAM_SUPPORTED_ISOMODES:
aValues = mIsoModes;
return NS_OK;
case CAMERA_PARAM_SUPPORTED_SCENEMODES:
aValues = mSceneModes;
return NS_OK;
case CAMERA_PARAM_SUPPORTED_METERINGMODES:
aValues = mMeteringModes;
return NS_OK;
default:
return GetListAsArray(aKey, aValues);
}
}
nsresult
GonkCameraParameters::GetTranslated(uint32_t aKey, nsTArray<double>& aValues)
{
if (aKey == CAMERA_PARAM_SUPPORTED_ZOOMRATIOS) {
aValues.Clear();
for (uint32_t i = 0; i < mZoomRatios.Length(); ++i) {
*aValues.AppendElement() = mZoomRatios[i] / 100.0;
}
return NS_OK;
}
return GetListAsArray(aKey, aValues);
}
nsresult
GonkCameraParameters::GetTranslated(uint32_t aKey, nsTArray<ICameraControl::Size>& aSizes)
{
return GetListAsArray(aKey, aSizes);
}