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