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