• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2023 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "camera_napi_utils.h"
17 
18 #include "camera_error_code.h"
19 #include "camera_log.h"
20 #include "napi/native_api.h"
21 
22 namespace OHOS {
23 namespace CameraStandard {
24 bool CameraNapiUtils::mEnableSecure = false;
CreateNapiErrorObject(napi_env env,int32_t errorCode,const char * errString,std::unique_ptr<JSAsyncContextOutput> & jsContext)25 void CameraNapiUtils::CreateNapiErrorObject(napi_env env, int32_t errorCode, const char* errString,
26     std::unique_ptr<JSAsyncContextOutput> &jsContext)
27 {
28     napi_get_undefined(env, &jsContext->data);
29     napi_value napiErrorCode = nullptr;
30     napi_value napiErrorMsg = nullptr;
31 
32     std::string errorCodeStr = std::to_string(errorCode);
33     napi_create_string_utf8(env, errorCodeStr.c_str(), NAPI_AUTO_LENGTH, &napiErrorCode);
34     napi_create_string_utf8(env, errString, NAPI_AUTO_LENGTH, &napiErrorMsg);
35 
36     napi_create_object(env, &jsContext->error);
37     napi_set_named_property(env, jsContext->error, "code", napiErrorCode);
38     napi_set_named_property(env, jsContext->error, "message", napiErrorMsg);
39 
40     jsContext->status = false;
41 }
42 
InvokeJSAsyncMethod(napi_env env,napi_deferred deferred,napi_ref callbackRef,napi_async_work work,const JSAsyncContextOutput & asyncContext)43 void CameraNapiUtils::InvokeJSAsyncMethod(napi_env env, napi_deferred deferred,
44     napi_ref callbackRef, napi_async_work work, const JSAsyncContextOutput &asyncContext)
45 {
46     napi_value retVal;
47     napi_value callback = nullptr;
48     std::string funcName = asyncContext.funcName;
49     MEDIA_INFO_LOG("%{public}s, context->InvokeJSAsyncMethod start", funcName.c_str());
50     /* Deferred is used when JS Callback method expects a promise value */
51     if (deferred) {
52         if (asyncContext.status) {
53             napi_resolve_deferred(env, deferred, asyncContext.data);
54             MEDIA_INFO_LOG("%{public}s, InvokeJSAsyncMethod napi_resolve_deferred", funcName.c_str());
55         } else {
56             napi_reject_deferred(env, deferred, asyncContext.error);
57             MEDIA_ERR_LOG("%{public}s, InvokeJSAsyncMethod napi_reject_deferred", funcName.c_str());
58         }
59         MEDIA_INFO_LOG("%{public}s, InvokeJSAsyncMethod end deferred", funcName.c_str());
60     } else {
61         MEDIA_INFO_LOG("%{public}s, InvokeJSAsyncMethod callback", funcName.c_str());
62         napi_value result[ARGS_TWO];
63         result[PARAM0] = asyncContext.error;
64         result[PARAM1] = asyncContext.data;
65         napi_get_reference_value(env, callbackRef, &callback);
66         MEDIA_INFO_LOG("%{public}s, InvokeJSAsyncMethod napi_call_function start", funcName.c_str());
67         napi_call_function(env, nullptr, callback, ARGS_TWO, result, &retVal);
68         MEDIA_INFO_LOG("%{public}s, InvokeJSAsyncMethod napi_call_function end", funcName.c_str());
69         napi_delete_reference(env, callbackRef);
70     }
71     napi_delete_async_work(env, work);
72     MEDIA_INFO_LOG("%{public}s, InvokeJSAsyncMethod inner end", funcName.c_str());
73 }
74 
IncrementAndGet(uint32_t & num)75 int32_t CameraNapiUtils::IncrementAndGet(uint32_t& num)
76 {
77     int32_t temp = num & 0x00ffffff;
78     if (temp >= 0xffff) {
79         num = num & 0xff000000;
80     }
81     num++;
82     return num;
83 }
84 
GetEnableSecureCamera()85 bool CameraNapiUtils::GetEnableSecureCamera()
86 {
87     return mEnableSecure;
88 }
89 
IsEnableSecureCamera(bool isEnable)90 void CameraNapiUtils::IsEnableSecureCamera(bool isEnable)
91 {
92     mEnableSecure = isEnable;
93 }
94 
CheckInvalidArgument(napi_env env,size_t argc,int32_t length,napi_value * argv,CameraSteps step)95 bool CameraNapiUtils::CheckInvalidArgument(napi_env env, size_t argc, int32_t length,
96     napi_value *argv, CameraSteps step)
97 {
98     bool isPass = true;
99     napi_valuetype valueTypeArray[length];
100     for (int32_t i = 0; i < length; i++) {
101         napi_typeof(env, argv[i], &valueTypeArray[i]);
102     }
103     switch (step) {
104         case CREATE_CAMERA_INPUT_INSTANCE:
105             if (argc == ARGS_ONE) {
106                 isPass = valueTypeArray[0] == napi_object;
107             } else if (argc == ARGS_TWO) {
108                 isPass = (valueTypeArray[0] == napi_number) && (valueTypeArray[1] == napi_number);
109             } else {
110                 isPass = false;
111             }
112             break;
113 
114         case CREATE_PREVIEW_OUTPUT_INSTANCE:
115             isPass = (argc == ARGS_TWO) &&
116                         (valueTypeArray[0] == napi_object) && (valueTypeArray[1] == napi_string);
117             break;
118 
119         case CREATE_PHOTO_OUTPUT_INSTANCE:
120             isPass = (argc >= ARGS_ONE) && (valueTypeArray[0] == napi_object);
121             break;
122 
123         case CREATE_VIDEO_OUTPUT_INSTANCE:
124             isPass = (argc == ARGS_TWO) &&
125                         (valueTypeArray[0] == napi_object) && (valueTypeArray[1] == napi_string);
126             break;
127 
128         case CREATE_METADATA_OUTPUT_INSTANCE:
129             isPass = argc == ARGS_ONE;
130             if (argc == ARGS_ONE) {
131                 napi_is_array(env, argv[0], &isPass);
132             } else {
133                 isPass = false;
134             }
135             break;
136 
137         case ADD_INPUT:
138             isPass = (argc == ARGS_ONE) && (valueTypeArray[0] == napi_object);
139             break;
140 
141         case REMOVE_INPUT:
142             isPass = (argc == ARGS_ONE) && (valueTypeArray[0] == napi_object);
143             break;
144 
145         case ADD_OUTPUT:
146             isPass = (argc == ARGS_ONE) && (valueTypeArray[0] == napi_object);
147             break;
148 
149         case REMOVE_OUTPUT:
150             isPass = (argc == ARGS_ONE) && (valueTypeArray[0] == napi_object);
151             break;
152 
153         case PHOTO_OUT_CAPTURE:
154             if (argc == ARGS_ZERO) {
155                 isPass = true;
156             } else if (argc == ARGS_ONE) {
157                 isPass = (valueTypeArray[0] == napi_object) || (valueTypeArray[0] == napi_function) ||
158                     (valueTypeArray[0] == napi_undefined);
159             } else if (argc == ARGS_TWO) {
160                 isPass = (valueTypeArray[0] == napi_object) && (valueTypeArray[1] == napi_function);
161             } else {
162                 isPass = false;
163             }
164             break;
165 
166         case PHOTO_OUT_BURST_CAPTURE:
167             if (argc == ARGS_ONE) {
168                 isPass = valueTypeArray[0] == napi_object;
169             }  else {
170                 isPass = false;
171             }
172             break;
173 
174         case ADD_DEFERRED_SURFACE:
175             if (argc == ARGS_ONE) {
176                 isPass = valueTypeArray[0] == napi_string;
177             } else if (argc == ARGS_TWO) {
178                 isPass = (valueTypeArray[0] == napi_string) && (valueTypeArray[1] == napi_function);
179             } else {
180                 isPass = false;
181             }
182             break;
183 
184         case CREATE_DEFERRED_PREVIEW_OUTPUT:
185             if (argc == ARGS_ONE) {
186                 isPass = valueTypeArray[0] == napi_object;
187             }  else {
188                 isPass = false;
189             }
190             break;
191 
192         default:
193             break;
194     }
195     if (!isPass) {
196         std::string errorCode = std::to_string(CameraErrorCode::INVALID_ARGUMENT);
197         napi_throw_type_error(env, errorCode.c_str(), "");
198     }
199     return isPass;
200 }
201 
CheckError(napi_env env,int32_t retCode)202 bool CameraNapiUtils::CheckError(napi_env env, int32_t retCode)
203 {
204     if ((retCode != 0)) {
205         std::string errorCode = std::to_string(retCode);
206         napi_throw_error(env, errorCode.c_str(), "");
207         return false;
208     }
209     return true;
210 }
211 
FloatToDouble(float val)212 double CameraNapiUtils::FloatToDouble(float val)
213 {
214     const double precision = 1000000.0;
215     return std::round(val * precision) / precision;
216 }
217 
GetStringArgument(napi_env env,napi_value value)218 std::string CameraNapiUtils::GetStringArgument(napi_env env, napi_value value)
219 {
220     napi_valuetype valueNapiType = napi_undefined;
221     napi_typeof(env, value, &valueNapiType);
222     CHECK_ERROR_RETURN_RET(valueNapiType != napi_string, "");
223     size_t stringSize = 0;
224     napi_status status = napi_get_value_string_utf8(env, value, nullptr, 0, &stringSize);
225     CHECK_ERROR_RETURN_RET(status != napi_ok || stringSize == 0, "");
226     std::string strValue = std::string(stringSize, '\0');
227     status = napi_get_value_string_utf8(env, value, strValue.data(), stringSize + 1, &stringSize);
228     CHECK_ERROR_RETURN_RET(status != napi_ok || stringSize == 0, "");
229     return strValue;
230 }
231 
IsSameNapiValue(napi_env env,napi_value valueSrc,napi_value valueDst)232 bool CameraNapiUtils::IsSameNapiValue(napi_env env, napi_value valueSrc, napi_value valueDst)
233 {
234     CHECK_ERROR_RETURN_RET(valueSrc == nullptr && valueDst == nullptr, true);
235     CHECK_ERROR_RETURN_RET(valueSrc == nullptr || valueDst == nullptr, false);
236     bool isEquals = false;
237     CHECK_ERROR_RETURN_RET_LOG(napi_strict_equals(env, valueSrc, valueDst, &isEquals) != napi_ok, false,
238         "get napi_strict_equals failed");
239     return isEquals;
240 }
241 
CallPromiseFun(napi_env env,napi_value promiseValue,void * data,napi_callback thenCallback,napi_callback catchCallback)242 napi_status CameraNapiUtils::CallPromiseFun(
243     napi_env env, napi_value promiseValue, void* data, napi_callback thenCallback, napi_callback catchCallback)
244 {
245     MEDIA_DEBUG_LOG("CallPromiseFun Start");
246     bool isPromise = false;
247     napi_is_promise(env, promiseValue, &isPromise);
248     CHECK_ERROR_RETURN_RET_LOG(!isPromise, napi_invalid_arg, "CallPromiseFun promiseValue is not promise");
249     // Create promiseThen
250     napi_value promiseThen = nullptr;
251     napi_get_named_property(env, promiseValue, "then", &promiseThen);
252     CHECK_ERROR_RETURN_RET_LOG(promiseThen == nullptr, napi_invalid_arg, "CallPromiseFun get promiseThen failed");
253     napi_value thenValue;
254     napi_status ret = napi_create_function(env, "thenCallback", NAPI_AUTO_LENGTH, thenCallback, data, &thenValue);
255     CHECK_ERROR_RETURN_RET_LOG(ret != napi_ok, ret, "CallPromiseFun thenCallback got exception");
256     napi_value catchValue;
257     ret = napi_create_function(env, "catchCallback", NAPI_AUTO_LENGTH, catchCallback, data, &catchValue);
258     CHECK_ERROR_RETURN_RET_LOG(ret != napi_ok, ret, "CallPromiseFun catchCallback got exception");
259     napi_value thenReturnValue;
260     constexpr uint32_t THEN_ARGC = 2;
261     napi_value thenArgv[THEN_ARGC] = { thenValue, catchValue };
262     ret = napi_call_function(env, promiseValue, promiseThen, THEN_ARGC, thenArgv, &thenReturnValue);
263     CHECK_ERROR_RETURN_RET_LOG(ret != napi_ok, ret, "CallPromiseFun PromiseThen got exception");
264     MEDIA_DEBUG_LOG("CallPromiseFun End");
265     return napi_ok;
266 }
267 
GetPropertyDescriptor(std::vector<std::vector<napi_property_descriptor>> descriptors)268 std::vector<napi_property_descriptor> CameraNapiUtils::GetPropertyDescriptor(
269     std::vector<std::vector<napi_property_descriptor>> descriptors)
270 {
271     MEDIA_DEBUG_LOG("GetPropertyDescriptor Start %zu", descriptors.size());
272     std::vector<napi_property_descriptor> properties = {};
273     std::for_each(descriptors.begin(), descriptors.end(),
274                   [&properties](const std::vector<napi_property_descriptor> descriptor) {
275                       properties.insert(properties.end(), descriptor.begin(), descriptor.end());
276                   });
277     return properties;
278 };
279 
CreateObjectWithPropName(napi_env env,napi_value * result,size_t property_count,const char ** keys)280 napi_status CameraNapiUtils::CreateObjectWithPropName(
281     napi_env env, napi_value* result, size_t property_count, const char** keys)
282 {
283     napi_value values[property_count];
284     for (size_t i = 0; i < property_count; i++) {
285         napi_get_undefined(env, &values[i]);
286     }
287     return napi_create_object_with_named_properties(env, result, property_count, keys, values);
288 }
289 
CreateObjectWithPropNameAndValues(napi_env env,napi_value * result,size_t property_count,const char ** keys,const std::vector<std::string> values)290 napi_status CameraNapiUtils::CreateObjectWithPropNameAndValues(
291     napi_env env, napi_value* result, size_t property_count, const char** keys, const std::vector<std::string> values)
292 {
293     napi_value napiValues[property_count];
294     for (size_t i = 0; i < property_count; i++) {
295         napi_create_string_utf8(env, values[i].data(), values[i].size(), &napiValues[i]);
296     }
297     return napi_create_object_with_named_properties(env, result, property_count, keys, napiValues);
298 }
299 
GetNapiArgs(napi_env env,napi_callback_info callbackInfo)300 size_t CameraNapiUtils::GetNapiArgs(napi_env env, napi_callback_info callbackInfo)
301 {
302     size_t argsSize = 0;
303     napi_get_cb_info(env, callbackInfo, &argsSize, nullptr, nullptr, nullptr);
304     return argsSize;
305 }
306 
CreateFrameRateJSArray(napi_env env,std::vector<int32_t> frameRateRange,napi_value & result)307 void CameraNapiUtils::CreateFrameRateJSArray(napi_env env, std::vector<int32_t> frameRateRange, napi_value &result)
308 {
309     MEDIA_DEBUG_LOG("CreateFrameRateJSArray called");
310     CHECK_ERROR_PRINT_LOG(frameRateRange.empty(), "frameRateRange is empty");
311 
312     napi_status status = napi_create_object(env, &result);
313     if (status == napi_ok) {
314         napi_value minRate;
315         status = napi_create_int32(env, frameRateRange[0], &minRate);
316         napi_value maxRate;
317         status = napi_create_int32(env, frameRateRange[1], &maxRate);
318         CHECK_ERROR_PRINT_LOG(status != napi_ok || napi_set_named_property(env, result, "min", minRate) != napi_ok ||
319             napi_set_named_property(env, result, "max", maxRate) != napi_ok,
320             "Failed to create frameRateArray with napi wrapper object.");
321     }
322 }
323 
CreateSupportFrameRatesJSArray(napi_env env,std::vector<std::vector<int32_t>> supportedFrameRatesRange)324 napi_value CameraNapiUtils::CreateSupportFrameRatesJSArray(
325     napi_env env, std::vector<std::vector<int32_t>> supportedFrameRatesRange)
326 {
327     MEDIA_DEBUG_LOG("CreateFrameRateJSArray called");
328     napi_value supportedFrameRateArray = nullptr;
329     CHECK_ERROR_PRINT_LOG(supportedFrameRatesRange.empty(), "frameRateRange is empty");
330 
331     napi_status status = napi_create_array(env, &supportedFrameRateArray);
332     if (status == napi_ok) {
333         for (size_t i = 0; i < supportedFrameRatesRange.size(); i++) {
334             napi_value supportedFrameRateItem;
335             CreateFrameRateJSArray(env, supportedFrameRatesRange[i], supportedFrameRateItem);
336             CHECK_ERROR_RETURN_RET_LOG(napi_set_element(env, supportedFrameRateArray, i, supportedFrameRateItem) !=
337                 napi_ok, nullptr, "Failed to create supportedFrameRateArray with napi wrapper object.");
338         }
339     }
340     return supportedFrameRateArray;
341 }
342 
ProcessingPhysicalApertures(napi_env env,std::vector<std::vector<float>> physicalApertures)343 napi_value CameraNapiUtils::ProcessingPhysicalApertures(napi_env env, std::vector<std::vector<float>> physicalApertures)
344 {
345     napi_value result = nullptr;
346     napi_create_array(env, &result);
347     size_t zoomRangeSize = 2;
348     size_t zoomMinIndex = 0;
349     size_t zoomMaxIndex = 1;
350     for (size_t i = 0; i < physicalApertures.size(); i++) {
351         if (physicalApertures[i].size() <= zoomRangeSize) {
352             continue;
353         }
354         napi_value zoomRange;
355         napi_create_array(env, &zoomRange);
356         napi_value physicalApertureRange;
357         napi_create_array(env, &physicalApertureRange);
358         for (size_t y = 0; y < physicalApertures[i].size(); y++) {
359             napi_value value;
360             napi_create_double(env, CameraNapiUtils::FloatToDouble(physicalApertures[i][y]), &value);
361             if (y == zoomMinIndex) {
362                 napi_set_element(env, zoomRange, y, value);
363                 napi_set_named_property(env, zoomRange, "min", value);
364                 continue;
365             }
366             if (y == zoomMaxIndex) {
367                 napi_set_element(env, zoomRange, y, value);
368                 napi_set_named_property(env, zoomRange, "max", value);
369                 continue;
370             }
371             napi_set_element(env, physicalApertureRange, y - zoomRangeSize, value);
372         }
373         napi_value obj;
374         napi_create_object(env, &obj);
375         napi_set_named_property(env, obj, "zoomRange", zoomRange);
376         napi_set_named_property(env, obj, "apertures", physicalApertureRange);
377         napi_set_element(env, result, i, obj);
378     }
379     return result;
380 }
381 
CreateJSArray(napi_env env,napi_status & status,std::vector<int32_t> nativeArray)382 napi_value CameraNapiUtils::CreateJSArray(napi_env env, napi_status &status,
383     std::vector<int32_t> nativeArray)
384 {
385     MEDIA_DEBUG_LOG("CreateJSArray is called");
386     napi_value jsArray = nullptr;
387     napi_value item = nullptr;
388 
389     CHECK_ERROR_PRINT_LOG(nativeArray.empty(), "nativeArray is empty");
390 
391     status = napi_create_array(env, &jsArray);
392     if (status == napi_ok) {
393         for (size_t i = 0; i < nativeArray.size(); i++) {
394             napi_create_int32(env, nativeArray[i], &item);
395             CHECK_ERROR_RETURN_RET_LOG(napi_set_element(env, jsArray, i, item) != napi_ok, nullptr,
396                 "Failed to create profile napi wrapper object");
397         }
398     }
399     return jsArray;
400 }
401 
ParseMetadataObjectTypes(napi_env env,napi_value arrayParam,std::vector<MetadataObjectType> & metadataObjectTypes)402 napi_value CameraNapiUtils::ParseMetadataObjectTypes(napi_env env, napi_value arrayParam,
403     std::vector<MetadataObjectType> &metadataObjectTypes)
404 {
405     MEDIA_DEBUG_LOG("ParseMetadataObjectTypes is called");
406     napi_value result;
407     uint32_t length = 0;
408     napi_value value;
409     int32_t metadataType = 0;
410     napi_get_array_length(env, arrayParam, &length);
411     napi_valuetype type = napi_undefined;
412     const int32_t invalidType = -1;
413     for (uint32_t i = 0; i < length; i++) {
414         napi_get_element(env, arrayParam, i, &value);
415         napi_typeof(env, value, &type);
416         CHECK_ERROR_RETURN_RET(type != napi_number, nullptr);
417         if (metadataType < static_cast<int32_t>(MetadataObjectType::INVALID) &&
418             metadataType > static_cast<int32_t>(MetadataObjectType::BAR_CODE_DETECTION)) {
419             metadataType = invalidType;
420         }
421         napi_get_value_int32(env, value, &metadataType);
422         metadataObjectTypes.push_back(static_cast<MetadataObjectType>(metadataType));
423     }
424     napi_get_boolean(env, true, &result);
425     return result;
426 }
427 } // namespace CameraStandard
428 } // namespace OHOS
429