• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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