1 /*
2 * Copyright (c) 2021-2022 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 "output/metadata_output_napi.h"
17
18 #include <uv.h>
19
20 #include "camera_log.h"
21 #include "camera_napi_metadata_utils.h"
22 #include "camera_napi_object_types.h"
23 #include "camera_napi_param_parser.h"
24 #include "camera_napi_template_utils.h"
25 #include "camera_napi_utils.h"
26 #include "camera_napi_worker_queue_keeper.h"
27 #include "camera_security_utils.h"
28 #include "hilog/log.h"
29 #include "napi/native_api.h"
30 #include "napi/native_common.h"
31 #include "napi/native_node_api.h"
32
33 namespace OHOS {
34 namespace CameraStandard {
35 thread_local uint32_t MetadataOutputNapi::metadataOutputTaskId = CAMERA_METADATA_OUTPUT_TASKID;
36 namespace {
AsyncCompleteCallback(napi_env env,napi_status status,void * data)37 void AsyncCompleteCallback(napi_env env, napi_status status, void* data)
38 {
39 auto context = static_cast<MetadataOutputAsyncContext*>(data);
40 CHECK_ERROR_RETURN_LOG(context == nullptr, "MetadataOutputNapi AsyncCompleteCallback context is null");
41 MEDIA_INFO_LOG("MetadataOutputNapi AsyncCompleteCallback %{public}s, status = %{public}d",
42 context->funcName.c_str(), context->status);
43 std::unique_ptr<JSAsyncContextOutput> jsContext = std::make_unique<JSAsyncContextOutput>();
44 jsContext->status = context->status;
45 if (!context->status) {
46 CameraNapiUtils::CreateNapiErrorObject(
47 env, context->errorCode, "No Metadata object Types or create array failed!", jsContext);
48 } else {
49 napi_get_undefined(env, &jsContext->data);
50 }
51 if (!context->funcName.empty() && context->taskId > 0) {
52 // Finish async trace
53 CAMERA_FINISH_ASYNC_TRACE(context->funcName, context->taskId);
54 jsContext->funcName = context->funcName;
55 }
56 CHECK_EXECUTE(context->work != nullptr,
57 CameraNapiUtils::InvokeJSAsyncMethod(env, context->deferred, context->callbackRef, context->work, *jsContext));
58 context->FreeHeldNapiValue(env);
59 delete context;
60 }
61 } // namespace
62
63 thread_local napi_ref MetadataOutputNapi::sConstructor_ = nullptr;
64 thread_local sptr<MetadataOutput> MetadataOutputNapi::sMetadataOutput_ = nullptr;
65
MetadataOutputCallback(napi_env env)66 MetadataOutputCallback::MetadataOutputCallback(napi_env env) : ListenerBase(env) {}
67
OnMetadataObjectsAvailable(const std::vector<sptr<MetadataObject>> metadataObjList) const68 void MetadataOutputCallback::OnMetadataObjectsAvailable(const std::vector<sptr<MetadataObject>> metadataObjList) const
69 {
70 MEDIA_DEBUG_LOG("OnMetadataObjectsAvailable is called");
71 std::unique_ptr<MetadataOutputCallbackInfo> callbackInfo =
72 std::make_unique<MetadataOutputCallbackInfo>(metadataObjList, shared_from_this());
73 MetadataOutputCallbackInfo *event = callbackInfo.get();
74 auto task = [event]() {
75 MetadataOutputCallbackInfo* callbackInfo = reinterpret_cast<MetadataOutputCallbackInfo *>(event);
76 if (callbackInfo) {
77 auto listener = callbackInfo->listener_.lock();
78 CHECK_EXECUTE(listener, listener->OnMetadataObjectsAvailableCallback(callbackInfo->info_));
79 delete callbackInfo;
80 }
81 };
82 if (napi_ok != napi_send_event(env_, task, napi_eprio_immediate)) {
83 MEDIA_ERR_LOG("failed to execute work");
84 } else {
85 callbackInfo.release();
86 }
87 }
88
CreateMetadataObjJSArray(napi_env env,const std::vector<sptr<MetadataObject>> metadataObjList) const89 napi_value MetadataOutputCallback::CreateMetadataObjJSArray(napi_env env,
90 const std::vector<sptr<MetadataObject>> metadataObjList) const
91 {
92 napi_value metadataObjArray = nullptr;
93 napi_value metadataObj = nullptr;
94 napi_status status;
95
96 CHECK_ERROR_PRINT_LOG(metadataObjList.empty(), "CreateMetadataObjJSArray: metadataObjList is empty");
97
98 status = napi_create_array(env, &metadataObjArray);
99 CHECK_ERROR_RETURN_RET_LOG(status != napi_ok, metadataObjArray,
100 "CreateMetadataObjJSArray: napi_create_array failed");
101
102 size_t j = 0;
103 bool isSystemApp = CameraSecurity::CheckSystemApp();
104 for (size_t i = 0; i < metadataObjList.size(); i++) {
105 metadataObj = CameraNapiObjMetadataObject(*metadataObjList[i]).GenerateNapiValue(env);
106 CHECK_EXECUTE(isSystemApp, AddMetadataObjExtending(env, metadataObjList[i], metadataObj));
107 CHECK_ERROR_RETURN_RET_LOG((metadataObj == nullptr) ||
108 napi_set_element(env, metadataObjArray, j++, metadataObj) != napi_ok, nullptr,
109 "CreateMetadataObjJSArray: Failed to create metadata face object napi wrapper object");
110 }
111 return metadataObjArray;
112 }
113
AddMetadataObjExtending(napi_env env,sptr<MetadataObject> metadataObj,napi_value & metadataNapiObj) const114 void MetadataOutputCallback::AddMetadataObjExtending(napi_env env, sptr<MetadataObject> metadataObj,
115 napi_value &metadataNapiObj) const
116 {
117 CHECK_ERROR_RETURN_LOG(metadataObj == nullptr, "AddMetadataObjExtending got null metadataObj");
118 auto type = metadataObj->GetType();
119 switch (type) {
120 case MetadataObjectType::FACE:
121 CreateHumanFaceMetaData(env, metadataObj, metadataNapiObj);
122 break;
123 case MetadataObjectType::CAT_FACE:
124 CreateCatFaceMetaData(env, metadataObj, metadataNapiObj);
125 break;
126 case MetadataObjectType::DOG_FACE:
127 CreateDogFaceMetaData(env, metadataObj, metadataNapiObj);
128 break;
129 default:
130 return;
131 }
132 }
133
CreateHumanFaceMetaData(napi_env env,sptr<MetadataObject> metadataObj,napi_value & metadataNapiObj) const134 void MetadataOutputCallback::CreateHumanFaceMetaData(napi_env env, sptr<MetadataObject> metadataObj,
135 napi_value &metadataNapiObj) const
136 {
137 napi_value metadataObjResult = nullptr;
138 napi_value numberNapiObj = nullptr;
139
140 napi_get_undefined(env, &metadataObjResult);
141 CHECK_ERROR_RETURN(metadataObj == nullptr && metadataNapiObj == nullptr);
142 MetadataFaceObject* faceObjectPtr = static_cast<MetadataFaceObject*>(metadataObj.GetRefPtr());
143 Rect boundingBox = faceObjectPtr->GetLeftEyeBoundingBox();
144 metadataObjResult = CameraNapiBoundingBox(boundingBox).GenerateNapiValue(env);
145 napi_set_named_property(env, metadataNapiObj, "leftEyeBoundingBox", metadataObjResult);
146 boundingBox = faceObjectPtr->GetRightEyeBoundingBox();
147 metadataObjResult = CameraNapiBoundingBox(boundingBox).GenerateNapiValue(env);
148 napi_set_named_property(env, metadataNapiObj, "rightEyeBoundingBox", metadataObjResult);
149
150 napi_create_int32(env, faceObjectPtr->GetEmotion(), &numberNapiObj);
151 napi_set_named_property(env, metadataNapiObj, "emotion", numberNapiObj);
152 napi_create_int32(env, faceObjectPtr->GetEmotionConfidence(), &numberNapiObj);
153 napi_set_named_property(env, metadataNapiObj, "emotionConfidence", numberNapiObj);
154 napi_create_int32(env, faceObjectPtr->GetPitchAngle(), &numberNapiObj);
155 napi_set_named_property(env, metadataNapiObj, "pitchAngle", numberNapiObj);
156 napi_create_int32(env, faceObjectPtr->GetYawAngle(), &numberNapiObj);
157 napi_set_named_property(env, metadataNapiObj, "yawAngle", numberNapiObj);
158 napi_create_int32(env, faceObjectPtr->GetRollAngle(), &numberNapiObj);
159 napi_set_named_property(env, metadataNapiObj, "rollAngle", numberNapiObj);
160 }
161
CreateCatFaceMetaData(napi_env env,sptr<MetadataObject> metadataObj,napi_value & metadataNapiObj) const162 void MetadataOutputCallback::CreateCatFaceMetaData(napi_env env, sptr<MetadataObject> metadataObj,
163 napi_value &metadataNapiObj) const
164 {
165 napi_value metadataObjResult = nullptr;
166
167 napi_get_undefined(env, &metadataObjResult);
168 CHECK_ERROR_RETURN(metadataObj == nullptr && metadataNapiObj == nullptr);
169 MetadataCatFaceObject* faceObjectPtr = static_cast<MetadataCatFaceObject*>(metadataObj.GetRefPtr());
170 Rect boundingBox = faceObjectPtr->GetLeftEyeBoundingBox();
171 metadataObjResult = CameraNapiBoundingBox(boundingBox).GenerateNapiValue(env);
172 napi_set_named_property(env, metadataNapiObj, "leftEyeBoundingBox", metadataObjResult);
173 boundingBox = faceObjectPtr->GetRightEyeBoundingBox();
174 metadataObjResult = CameraNapiBoundingBox(boundingBox).GenerateNapiValue(env);
175 napi_set_named_property(env, metadataNapiObj, "rightEyeBoundingBox", metadataObjResult);
176 }
177
CreateDogFaceMetaData(napi_env env,sptr<MetadataObject> metadataObj,napi_value & metadataNapiObj) const178 void MetadataOutputCallback::CreateDogFaceMetaData(napi_env env, sptr<MetadataObject> metadataObj,
179 napi_value &metadataNapiObj) const
180 {
181 napi_value metadataObjResult = nullptr;
182
183 napi_get_undefined(env, &metadataObjResult);
184 CHECK_ERROR_RETURN(metadataObj == nullptr && metadataNapiObj == nullptr);
185 MetadataDogFaceObject* faceObjectPtr = static_cast<MetadataDogFaceObject*>(metadataObj.GetRefPtr());
186 Rect boundingBox = faceObjectPtr->GetLeftEyeBoundingBox();
187 metadataObjResult = CameraNapiBoundingBox(boundingBox).GenerateNapiValue(env);
188 napi_set_named_property(env, metadataNapiObj, "leftEyeBoundingBox", metadataObjResult);
189 boundingBox = faceObjectPtr->GetRightEyeBoundingBox();
190 metadataObjResult = CameraNapiBoundingBox(boundingBox).GenerateNapiValue(env);
191 napi_set_named_property(env, metadataNapiObj, "rightEyeBoundingBox", metadataObjResult);
192 }
193
OnMetadataObjectsAvailableCallback(const std::vector<sptr<MetadataObject>> metadataObjList) const194 void MetadataOutputCallback::OnMetadataObjectsAvailableCallback(
195 const std::vector<sptr<MetadataObject>> metadataObjList) const
196 {
197 MEDIA_DEBUG_LOG("OnMetadataObjectsAvailableCallback is called");
198 napi_value result[ARGS_TWO];
199 napi_value retVal;
200
201 napi_get_undefined(env_, &result[PARAM0]);
202 napi_get_undefined(env_, &result[PARAM1]);
203 result[PARAM1] = CreateMetadataObjJSArray(env_, metadataObjList);
204 MEDIA_INFO_LOG("OnMetadataObjectsAvailableCallback metadataObjList size = %{public}zu", metadataObjList.size());
205 CHECK_ERROR_RETURN_LOG(result[PARAM1] == nullptr, "invoke CreateMetadataObjJSArray failed");
206
207 ExecuteCallbackNapiPara callbackNapiPara { .recv = nullptr, .argc = ARGS_TWO, .argv = result, .result = &retVal };
208 ExecuteCallback("metadataObjectsAvailable", callbackNapiPara);
209 }
210
MetadataStateCallbackNapi(napi_env env)211 MetadataStateCallbackNapi::MetadataStateCallbackNapi(napi_env env) : ListenerBase(env) {}
212
OnErrorCallbackAsync(const int32_t errorType) const213 void MetadataStateCallbackNapi::OnErrorCallbackAsync(const int32_t errorType) const
214 {
215 MEDIA_DEBUG_LOG("OnErrorCallbackAsync is called");
216 std::unique_ptr<MetadataStateCallbackInfo> callbackInfo =
217 std::make_unique<MetadataStateCallbackInfo>(errorType, shared_from_this());
218 MetadataStateCallbackInfo *event = callbackInfo.get();
219 auto task = [event]() {
220 MetadataStateCallbackInfo* callbackInfo = reinterpret_cast<MetadataStateCallbackInfo *>(event);
221 if (callbackInfo) {
222 auto listener = callbackInfo->listener_.lock();
223 CHECK_EXECUTE(listener, listener->OnErrorCallback(callbackInfo->errorType_));
224 delete callbackInfo;
225 }
226 };
227 if (napi_ok != napi_send_event(env_, task, napi_eprio_immediate)) {
228 MEDIA_ERR_LOG("failed to execute work");
229 } else {
230 callbackInfo.release();
231 }
232 }
233
OnErrorCallback(const int32_t errorType) const234 void MetadataStateCallbackNapi::OnErrorCallback(const int32_t errorType) const
235 {
236 MEDIA_DEBUG_LOG("OnErrorCallback is called");
237 napi_value result;
238 napi_value retVal;
239 napi_value propValue;
240
241 napi_create_int32(env_, errorType, &propValue);
242 napi_create_object(env_, &result);
243 napi_set_named_property(env_, result, "code", propValue);
244 ExecuteCallbackNapiPara callbackNapiPara { .recv = nullptr, .argc = ARGS_ONE, .argv = &result, .result = &retVal };
245 ExecuteCallback("error", callbackNapiPara);
246 }
247
OnError(const int32_t errorType) const248 void MetadataStateCallbackNapi::OnError(const int32_t errorType) const
249 {
250 MEDIA_DEBUG_LOG("OnError is called!, errorType: %{public}d", errorType);
251 OnErrorCallbackAsync(errorType);
252 }
253
MetadataOutputNapi()254 MetadataOutputNapi::MetadataOutputNapi() : env_(nullptr) {}
255
~MetadataOutputNapi()256 MetadataOutputNapi::~MetadataOutputNapi()
257 {
258 MEDIA_DEBUG_LOG("~MetadataOutputNapi is called");
259 }
260
MetadataOutputNapiDestructor(napi_env env,void * nativeObject,void * finalize_hint)261 void MetadataOutputNapi::MetadataOutputNapiDestructor(napi_env env, void* nativeObject, void* finalize_hint)
262 {
263 MEDIA_DEBUG_LOG("MetadataOutputNapiDestructor is called");
264 MetadataOutputNapi* metadataOutput = reinterpret_cast<MetadataOutputNapi*>(nativeObject);
265 if (metadataOutput != nullptr) {
266 delete metadataOutput;
267 }
268 }
269
Init(napi_env env,napi_value exports)270 napi_value MetadataOutputNapi::Init(napi_env env, napi_value exports)
271 {
272 MEDIA_DEBUG_LOG("Init is called");
273 napi_status status;
274 napi_value ctorObj;
275 int32_t refCount = 1;
276
277 napi_property_descriptor metadata_output_props[] = {
278 DECLARE_NAPI_FUNCTION("addMetadataObjectTypes", AddMetadataObjectTypes),
279 DECLARE_NAPI_FUNCTION("removeMetadataObjectTypes", RemoveMetadataObjectTypes),
280 DECLARE_NAPI_FUNCTION("start", Start),
281 DECLARE_NAPI_FUNCTION("stop", Stop),
282 DECLARE_NAPI_FUNCTION("release", Release),
283 DECLARE_NAPI_FUNCTION("on", On),
284 DECLARE_NAPI_FUNCTION("once", Once),
285 DECLARE_NAPI_FUNCTION("off", Off)
286 };
287
288 status = napi_define_class(env, CAMERA_METADATA_OUTPUT_NAPI_CLASS_NAME, NAPI_AUTO_LENGTH,
289 MetadataOutputNapiConstructor, nullptr,
290 sizeof(metadata_output_props) / sizeof(metadata_output_props[PARAM0]),
291 metadata_output_props, &ctorObj);
292 if (status == napi_ok) {
293 status = napi_create_reference(env, ctorObj, refCount, &sConstructor_);
294 if (status == napi_ok) {
295 status = napi_set_named_property(env, exports, CAMERA_METADATA_OUTPUT_NAPI_CLASS_NAME, ctorObj);
296 CHECK_ERROR_RETURN_RET(status == napi_ok, exports);
297 }
298 }
299 MEDIA_ERR_LOG("Init call Failed!");
300 return nullptr;
301 }
302
MetadataOutputNapiConstructor(napi_env env,napi_callback_info info)303 napi_value MetadataOutputNapi::MetadataOutputNapiConstructor(napi_env env, napi_callback_info info)
304 {
305 MEDIA_DEBUG_LOG("MetadataOutputNapiConstructor is called");
306 napi_status status;
307 napi_value result = nullptr;
308 napi_value thisVar = nullptr;
309
310 napi_get_undefined(env, &result);
311 CAMERA_NAPI_GET_JS_OBJ_WITH_ZERO_ARGS(env, info, status, thisVar);
312
313 if (status == napi_ok && thisVar != nullptr) {
314 std::unique_ptr<MetadataOutputNapi> obj = std::make_unique<MetadataOutputNapi>();
315 obj->env_ = env;
316 obj->metadataOutput_ = sMetadataOutput_;
317 status = napi_wrap(env, thisVar, reinterpret_cast<void*>(obj.get()),
318 MetadataOutputNapi::MetadataOutputNapiDestructor, nullptr, nullptr);
319 if (status == napi_ok) {
320 obj.release();
321 return thisVar;
322 } else {
323 MEDIA_ERR_LOG("Failure wrapping js to native napi");
324 }
325 }
326 MEDIA_ERR_LOG("MetadataOutputNapiConstructor call Failed!");
327 return result;
328 }
329
IsMetadataOutput(napi_env env,napi_value obj)330 bool MetadataOutputNapi::IsMetadataOutput(napi_env env, napi_value obj)
331 {
332 MEDIA_DEBUG_LOG("IsMetadataOutput is called");
333 bool result = false;
334 napi_status status;
335 napi_value constructor = nullptr;
336
337 status = napi_get_reference_value(env, sConstructor_, &constructor);
338 if (status == napi_ok) {
339 status = napi_instanceof(env, obj, constructor, &result);
340 if (status != napi_ok) {
341 result = false;
342 }
343 }
344 MEDIA_INFO_LOG("IsMetadataOutput(%{public}d)", result);
345 return result;
346 }
347
GetMetadataOutput()348 sptr<MetadataOutput> MetadataOutputNapi::GetMetadataOutput()
349 {
350 return metadataOutput_;
351 }
352
CreateMetadataOutput(napi_env env,std::vector<MetadataObjectType> metadataObjectTypes)353 napi_value MetadataOutputNapi::CreateMetadataOutput(napi_env env, std::vector<MetadataObjectType> metadataObjectTypes)
354 {
355 MEDIA_DEBUG_LOG("CreateMetadataOutput is called");
356 CAMERA_SYNC_TRACE;
357 napi_status status;
358 napi_value result = nullptr;
359 napi_value constructor;
360
361 status = napi_get_reference_value(env, sConstructor_, &constructor);
362 if (status == napi_ok) {
363 int retCode = CameraManager::GetInstance()->CreateMetadataOutput(sMetadataOutput_, metadataObjectTypes);
364 CHECK_ERROR_RETURN_RET(!CameraNapiUtils::CheckError(env, retCode), nullptr);
365 CHECK_ERROR_RETURN_RET_LOG(sMetadataOutput_ == nullptr, result, "failed to create MetadataOutput");
366 status = napi_new_instance(env, constructor, 0, nullptr, &result);
367 sMetadataOutput_ = nullptr;
368 if (status == napi_ok && result != nullptr) {
369 return result;
370 } else {
371 MEDIA_ERR_LOG("Failed to create metadata output instance");
372 }
373 }
374 MEDIA_ERR_LOG("CreateMetadataOutput call Failed!");
375 napi_get_undefined(env, &result);
376 return result;
377 }
378
AddMetadataObjectTypes(napi_env env,napi_callback_info info)379 napi_value MetadataOutputNapi::AddMetadataObjectTypes(napi_env env, napi_callback_info info)
380 {
381 MEDIA_INFO_LOG("AddMetadataObjectTypes is called");
382 napi_status status;
383 napi_value result = nullptr;
384 size_t argc = ARGS_ONE;
385 napi_value argv[ARGS_ONE] = {0};
386 napi_value thisVar = nullptr;
387
388 CAMERA_NAPI_GET_JS_ARGS(env, info, argc, argv, thisVar);
389 NAPI_ASSERT(env, argc <= ARGS_ONE, "requires 1 parameter maximum");
390
391 napi_get_undefined(env, &result);
392 MetadataOutputNapi* metadataOutputNapi = nullptr;
393 status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&metadataOutputNapi));
394 CHECK_ERROR_RETURN_RET_LOG(status != napi_ok || metadataOutputNapi == nullptr, result, "napi_unwrap failure!");
395 std::vector<MetadataObjectType> metadataObjectType;
396 CameraNapiUtils::ParseMetadataObjectTypes(env, argv[PARAM0], metadataObjectType);
397 int32_t retCode = metadataOutputNapi->metadataOutput_->AddMetadataObjectTypes(metadataObjectType);
398 CHECK_ERROR_PRINT_LOG(!CameraNapiUtils::CheckError(env, retCode), "AddMetadataObjectTypes failure!");
399 return result;
400 }
401
RemoveMetadataObjectTypes(napi_env env,napi_callback_info info)402 napi_value MetadataOutputNapi::RemoveMetadataObjectTypes(napi_env env, napi_callback_info info)
403 {
404 MEDIA_INFO_LOG("RemoveMetadataObjectTypes is called");
405 napi_status status;
406 napi_value result = nullptr;
407 size_t argc = ARGS_ONE;
408 napi_value argv[ARGS_ONE] = {0};
409 napi_value thisVar = nullptr;
410
411 CAMERA_NAPI_GET_JS_ARGS(env, info, argc, argv, thisVar);
412 NAPI_ASSERT(env, argc <= ARGS_ONE, "requires 1 parameter maximum");
413
414 napi_get_undefined(env, &result);
415 MetadataOutputNapi* metadataOutputNapi = nullptr;
416 status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&metadataOutputNapi));
417 CHECK_ERROR_RETURN_RET_LOG(status != napi_ok || metadataOutputNapi == nullptr, result, "napi_unwrap failure!");
418 std::vector<MetadataObjectType> metadataObjectType;
419 CameraNapiUtils::ParseMetadataObjectTypes(env, argv[PARAM0], metadataObjectType);
420 int32_t retCode = metadataOutputNapi->metadataOutput_->RemoveMetadataObjectTypes(metadataObjectType);
421 CHECK_ERROR_PRINT_LOG(!CameraNapiUtils::CheckError(env, retCode), "RemoveMetadataObjectTypes failure!");
422 return result;
423 }
424
Start(napi_env env,napi_callback_info info)425 napi_value MetadataOutputNapi::Start(napi_env env, napi_callback_info info)
426 {
427 MEDIA_INFO_LOG("Start is called");
428 std::unique_ptr<MetadataOutputAsyncContext> asyncContext = std::make_unique<MetadataOutputAsyncContext>(
429 "MetadataOutputNapi::Start", CameraNapiUtils::IncrementAndGet(metadataOutputTaskId));
430 auto asyncFunction =
431 std::make_shared<CameraNapiAsyncFunction>(env, "Start", asyncContext->callbackRef, asyncContext->deferred);
432 CameraNapiParamParser jsParamParser(env, info, asyncContext->objectInfo, asyncFunction);
433 CHECK_ERROR_RETURN_RET_LOG(!jsParamParser.AssertStatus(INVALID_ARGUMENT, "invalid argument"), nullptr,
434 "MetadataOutputNapi::Start invalid argument");
435 asyncContext->HoldNapiValue(env, jsParamParser.GetThisVar());
436 napi_status status = napi_create_async_work(
437 env, nullptr, asyncFunction->GetResourceName(),
438 [](napi_env env, void* data) {
439 MEDIA_INFO_LOG("MetadataOutputNapi::Start running on worker");
440 auto context = static_cast<MetadataOutputAsyncContext*>(data);
441 CHECK_ERROR_RETURN_LOG(context->objectInfo == nullptr, "MetadataOutputNapi::Start async info is nullptr");
442 CAMERA_START_ASYNC_TRACE(context->funcName, context->taskId);
443 CameraNapiWorkerQueueKeeper::GetInstance()->ConsumeWorkerQueueTask(context->queueTask, [&context]() {
444 context->errorCode = context->objectInfo->metadataOutput_->Start();
445 context->status = context->errorCode == CameraErrorCode::SUCCESS;
446 MEDIA_INFO_LOG("MetadataOutputNapi::Start errorCode:%{public}d", context->errorCode);
447 });
448 },
449 AsyncCompleteCallback, static_cast<void*>(asyncContext.get()), &asyncContext->work);
450 if (status != napi_ok) {
451 MEDIA_ERR_LOG("Failed to create napi_create_async_work for MetadataOutputNapi::Start");
452 asyncFunction->Reset();
453 } else {
454 asyncContext->queueTask =
455 CameraNapiWorkerQueueKeeper::GetInstance()->AcquireWorkerQueueTask("MetadataOutputNapi::Start");
456 napi_queue_async_work_with_qos(env, asyncContext->work, napi_qos_user_initiated);
457 asyncContext.release();
458 }
459 CHECK_ERROR_RETURN_RET(asyncFunction->GetAsyncFunctionType() == ASYNC_FUN_TYPE_PROMISE,
460 asyncFunction->GetPromise());
461 return CameraNapiUtils::GetUndefinedValue(env);
462 }
463
Stop(napi_env env,napi_callback_info info)464 napi_value MetadataOutputNapi::Stop(napi_env env, napi_callback_info info)
465 {
466 MEDIA_INFO_LOG("Stop is called");
467 std::unique_ptr<MetadataOutputAsyncContext> asyncContext = std::make_unique<MetadataOutputAsyncContext>(
468 "MetadataOutputNapi::Stop", CameraNapiUtils::IncrementAndGet(metadataOutputTaskId));
469 auto asyncFunction =
470 std::make_shared<CameraNapiAsyncFunction>(env, "Stop", asyncContext->callbackRef, asyncContext->deferred);
471 CameraNapiParamParser jsParamParser(env, info, asyncContext->objectInfo, asyncFunction);
472 CHECK_ERROR_RETURN_RET_LOG(!jsParamParser.AssertStatus(INVALID_ARGUMENT, "invalid argument"), nullptr,
473 "MetadataOutputNapi::Stop invalid argument");
474 asyncContext->HoldNapiValue(env, jsParamParser.GetThisVar());
475 napi_status status = napi_create_async_work(
476 env, nullptr, asyncFunction->GetResourceName(),
477 [](napi_env env, void* data) {
478 MEDIA_INFO_LOG("MetadataOutputNapi::Stop running on worker");
479 auto context = static_cast<MetadataOutputAsyncContext*>(data);
480 CHECK_ERROR_RETURN_LOG(context->objectInfo == nullptr, "MetadataOutputNapi::Stop async info is nullptr");
481 CAMERA_START_ASYNC_TRACE(context->funcName, context->taskId);
482 CameraNapiWorkerQueueKeeper::GetInstance()->ConsumeWorkerQueueTask(context->queueTask, [&context]() {
483 context->errorCode = context->objectInfo->metadataOutput_->Stop();
484 // Always true, ignore error code
485 context->status = true;
486 MEDIA_INFO_LOG("MetadataOutputNapi::Stop errorCode:%{public}d", context->errorCode);
487 });
488 },
489 AsyncCompleteCallback, static_cast<void*>(asyncContext.get()), &asyncContext->work);
490 if (status != napi_ok) {
491 MEDIA_ERR_LOG("Failed to create napi_create_async_work for MetadataOutputNapi::Stop");
492 asyncFunction->Reset();
493 } else {
494 asyncContext->queueTask =
495 CameraNapiWorkerQueueKeeper::GetInstance()->AcquireWorkerQueueTask("MetadataOutputNapi::Stop");
496 napi_queue_async_work_with_qos(env, asyncContext->work, napi_qos_user_initiated);
497 asyncContext.release();
498 }
499 CHECK_ERROR_RETURN_RET(asyncFunction->GetAsyncFunctionType() == ASYNC_FUN_TYPE_PROMISE,
500 asyncFunction->GetPromise());
501 return CameraNapiUtils::GetUndefinedValue(env);
502 }
503
Release(napi_env env,napi_callback_info info)504 napi_value MetadataOutputNapi::Release(napi_env env, napi_callback_info info)
505 {
506 MEDIA_INFO_LOG("MetadataOutputNapi::Release is called");
507 std::unique_ptr<MetadataOutputAsyncContext> asyncContext = std::make_unique<MetadataOutputAsyncContext>(
508 "MetadataOutputNapi::Release", CameraNapiUtils::IncrementAndGet(metadataOutputTaskId));
509 auto asyncFunction =
510 std::make_shared<CameraNapiAsyncFunction>(env, "Release", asyncContext->callbackRef, asyncContext->deferred);
511 CameraNapiParamParser jsParamParser(env, info, asyncContext->objectInfo, asyncFunction);
512 CHECK_ERROR_RETURN_RET_LOG(!jsParamParser.AssertStatus(INVALID_ARGUMENT, "invalid argument"), nullptr,
513 "MetadataOutputNapi::Release invalid argument");
514 asyncContext->HoldNapiValue(env, jsParamParser.GetThisVar());
515 napi_status status = napi_create_async_work(
516 env, nullptr, asyncFunction->GetResourceName(),
517 [](napi_env env, void* data) {
518 MEDIA_INFO_LOG("MetadataOutputNapi::Release running on worker");
519 auto context = static_cast<MetadataOutputAsyncContext*>(data);
520 CHECK_ERROR_RETURN_LOG(context->objectInfo == nullptr, "MetadataOutputNapi::Release async info is nullptr");
521 CAMERA_START_ASYNC_TRACE(context->funcName, context->taskId);
522 CameraNapiWorkerQueueKeeper::GetInstance()->ConsumeWorkerQueueTask(context->queueTask, [&context]() {
523 context->errorCode = context->objectInfo->metadataOutput_->Release();
524 context->status = context->errorCode == CameraErrorCode::SUCCESS;
525 });
526 },
527 AsyncCompleteCallback, static_cast<void*>(asyncContext.get()), &asyncContext->work);
528 if (status != napi_ok) {
529 MEDIA_ERR_LOG("Failed to create napi_create_async_work for MetadataOutputNapi::Release");
530 asyncFunction->Reset();
531 } else {
532 asyncContext->queueTask =
533 CameraNapiWorkerQueueKeeper::GetInstance()->AcquireWorkerQueueTask("MetadataOutputNapi::Release");
534 napi_queue_async_work_with_qos(env, asyncContext->work, napi_qos_user_initiated);
535 asyncContext.release();
536 }
537 CHECK_ERROR_RETURN_RET(asyncFunction->GetAsyncFunctionType() == ASYNC_FUN_TYPE_PROMISE,
538 asyncFunction->GetPromise());
539 return CameraNapiUtils::GetUndefinedValue(env);
540 }
541
RegisterMetadataObjectsAvailableCallbackListener(const std::string & eventName,napi_env env,napi_value callback,const std::vector<napi_value> & args,bool isOnce)542 void MetadataOutputNapi::RegisterMetadataObjectsAvailableCallbackListener(
543 const std::string& eventName, napi_env env, napi_value callback, const std::vector<napi_value>& args, bool isOnce)
544 {
545 if (metadataOutputCallback_ == nullptr) {
546 metadataOutputCallback_ = make_shared<MetadataOutputCallback>(env);
547 metadataOutput_->SetCallback(metadataOutputCallback_);
548 }
549 metadataOutputCallback_->SaveCallbackReference(eventName, callback, isOnce);
550 }
551
UnregisterMetadataObjectsAvailableCallbackListener(const std::string & eventName,napi_env env,napi_value callback,const std::vector<napi_value> & args)552 void MetadataOutputNapi::UnregisterMetadataObjectsAvailableCallbackListener(
553 const std::string& eventName, napi_env env, napi_value callback, const std::vector<napi_value>& args)
554 {
555 if (metadataOutputCallback_ == nullptr) {
556 MEDIA_ERR_LOG("metadataOutputCallback is null");
557 } else {
558 metadataOutputCallback_->RemoveCallbackRef(eventName, callback);
559 }
560 }
561
RegisterErrorCallbackListener(const std::string & eventName,napi_env env,napi_value callback,const std::vector<napi_value> & args,bool isOnce)562 void MetadataOutputNapi::RegisterErrorCallbackListener(
563 const std::string& eventName, napi_env env, napi_value callback, const std::vector<napi_value>& args, bool isOnce)
564 {
565 if (metadataStateCallback_ == nullptr) {
566 metadataStateCallback_ = make_shared<MetadataStateCallbackNapi>(env);
567 metadataOutput_->SetCallback(metadataStateCallback_);
568 }
569 metadataStateCallback_->SaveCallbackReference(eventName, callback, isOnce);
570 }
571
UnregisterErrorCallbackListener(const std::string & eventName,napi_env env,napi_value callback,const std::vector<napi_value> & args)572 void MetadataOutputNapi::UnregisterErrorCallbackListener(
573 const std::string& eventName, napi_env env, napi_value callback, const std::vector<napi_value>& args)
574 {
575 if (metadataStateCallback_ == nullptr) {
576 MEDIA_ERR_LOG("metadataStateCallback is null");
577 } else {
578 metadataStateCallback_->RemoveCallbackRef(eventName, callback);
579 }
580 }
581
GetEmitterFunctions()582 const MetadataOutputNapi::EmitterFunctions& MetadataOutputNapi::GetEmitterFunctions()
583 {
584 const static EmitterFunctions funMap = {
585 { "metadataObjectsAvailable", {
586 &MetadataOutputNapi::RegisterMetadataObjectsAvailableCallbackListener,
587 &MetadataOutputNapi::UnregisterMetadataObjectsAvailableCallbackListener } },
588 { "error", {
589 &MetadataOutputNapi::RegisterErrorCallbackListener,
590 &MetadataOutputNapi::UnregisterErrorCallbackListener } } };
591 return funMap;
592 }
593
On(napi_env env,napi_callback_info info)594 napi_value MetadataOutputNapi::On(napi_env env, napi_callback_info info)
595 {
596 return ListenerTemplate<MetadataOutputNapi>::On(env, info);
597 }
598
Once(napi_env env,napi_callback_info info)599 napi_value MetadataOutputNapi::Once(napi_env env, napi_callback_info info)
600 {
601 return ListenerTemplate<MetadataOutputNapi>::Once(env, info);
602 }
603
Off(napi_env env,napi_callback_info info)604 napi_value MetadataOutputNapi::Off(napi_env env, napi_callback_info info)
605 {
606 return ListenerTemplate<MetadataOutputNapi>::Off(env, info);
607 }
608 } // namespace CameraStandard
609 } // namespace OHOS