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