• 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 <uv.h>
17 #include "hilog/log.h"
18 #include "output/metadata_object_napi.h"
19 #include "output/metadata_output_napi.h"
20 
21 namespace OHOS {
22 namespace CameraStandard {
23 using OHOS::HiviewDFX::HiLog;
24 using OHOS::HiviewDFX::HiLogLabel;
25 namespace {
26     constexpr HiLogLabel LABEL = {LOG_CORE, LOG_DOMAIN, "MetadataOutputNapi"};
27 }
28 thread_local napi_ref MetadataOutputNapi::sConstructor_ = nullptr;
29 thread_local sptr<MetadataOutput> MetadataOutputNapi::sMetadataOutput_ = nullptr;
30 
MetadataOutputCallback(napi_env env)31 MetadataOutputCallback::MetadataOutputCallback(napi_env env) : env_(env) {}
32 
OnMetadataObjectsAvailable(const std::vector<sptr<MetadataObject>> metadataObjList) const33 void MetadataOutputCallback::OnMetadataObjectsAvailable(const std::vector<sptr<MetadataObject>> metadataObjList) const
34 {
35     MEDIA_DEBUG_LOG("OnMetadataObjectsAvailable is called");
36     uv_loop_s* loop = nullptr;
37     napi_get_uv_event_loop(env_, &loop);
38     if (!loop) {
39         MEDIA_ERR_LOG("failed to get event loop");
40         return;
41     }
42     uv_work_t* work = new(std::nothrow) uv_work_t;
43     if (!work) {
44         MEDIA_ERR_LOG("failed to allocate work");
45         return;
46     }
47     std::unique_ptr<MetadataOutputCallbackInfo> callbackInfo =
48         std::make_unique<MetadataOutputCallbackInfo>(metadataObjList, this);
49     work->data = reinterpret_cast<void *>(callbackInfo.get());
50     int ret = uv_queue_work(loop, work, [] (uv_work_t* work) {}, [] (uv_work_t* work, int status) {
51         MetadataOutputCallbackInfo* callbackInfo = reinterpret_cast<MetadataOutputCallbackInfo *>(work->data);
52         if (callbackInfo) {
53             callbackInfo->listener_->OnMetadataObjectsAvailableCallback(callbackInfo->info_);
54             delete callbackInfo;
55         }
56         delete work;
57     });
58     if (ret) {
59         MEDIA_ERR_LOG("failed to execute work");
60         delete work;
61     }  else {
62         callbackInfo.release();
63     }
64 }
65 
CreateMetadataObjJSArray(napi_env env,const std::vector<sptr<MetadataObject>> metadataObjList)66 static napi_value CreateMetadataObjJSArray(napi_env env,
67     const std::vector<sptr<MetadataObject>> metadataObjList)
68 {
69     MEDIA_DEBUG_LOG("CreateMetadataObjJSArray is called");
70     napi_value metadataObjArray = nullptr;
71     napi_value metadataObj = nullptr;
72     napi_status status;
73 
74     if (metadataObjList.empty()) {
75         MEDIA_ERR_LOG("CreateMetadataObjJSArray: metadataObjList is empty");
76         return metadataObjArray;
77     }
78 
79     status = napi_create_array(env, &metadataObjArray);
80     if (status != napi_ok) {
81         MEDIA_ERR_LOG("CreateMetadataObjJSArray: napi_create_array failed");
82         return metadataObjArray;
83     }
84 
85     for (size_t i = 0; i < metadataObjList.size(); i++) {
86         size_t j = 0;
87         metadataObj = MetadataObjectNapi::CreateMetaFaceObj(env, metadataObjList[i]);
88         if ((metadataObj == nullptr) || napi_set_element(env, metadataObjArray, j++, metadataObj) != napi_ok) {
89             MEDIA_ERR_LOG("CreateMetadataObjJSArray: Failed to create metadata face object napi wrapper object");
90             return nullptr;
91         }
92     }
93     return metadataObjArray;
94 }
95 
OnMetadataObjectsAvailableCallback(const std::vector<sptr<MetadataObject>> metadataObjList) const96 void MetadataOutputCallback::OnMetadataObjectsAvailableCallback(
97     const std::vector<sptr<MetadataObject>> metadataObjList) const
98 {
99     MEDIA_DEBUG_LOG("OnMetadataObjectsAvailableCallback is called");
100     napi_value result[ARGS_TWO];
101     napi_value callback = nullptr;
102     napi_value retVal;
103     napi_get_undefined(env_, &result[PARAM0]);
104     napi_get_undefined(env_, &result[PARAM1]);
105     CAMERA_NAPI_CHECK_AND_RETURN_LOG((metadataObjList.size() != 0), "callback metadataObjList is null");
106 
107     result[PARAM1] = CreateMetadataObjJSArray(env_, metadataObjList);
108     if (result[PARAM1] == nullptr) {
109         MEDIA_ERR_LOG("invoke CreateMetadataObjJSArray failed");
110         return;
111     }
112 
113     CAMERA_NAPI_CHECK_NULL_PTR_RETURN_VOID(metadataObjectsAvailableCallbackRef_,
114         "metadataObjectsAvailable callback is not registered by JS");
115     napi_get_reference_value(env_, metadataObjectsAvailableCallbackRef_, &callback);
116     napi_call_function(env_, nullptr, callback, ARGS_TWO, result, &retVal);
117 }
118 
SetCallbackRef(const std::string & eventType,const napi_ref & callbackRef)119 void MetadataOutputCallback::SetCallbackRef(const std::string &eventType, const napi_ref &callbackRef)
120 {
121     if (eventType.compare("metadataObjectsAvailable") == 0) {
122         metadataObjectsAvailableCallbackRef_ = callbackRef;
123     } else {
124         MEDIA_ERR_LOG("Incorrect metadata callback event type received from JS");
125     }
126 }
127 
MetadataOutputNapi()128 MetadataOutputNapi::MetadataOutputNapi() : env_(nullptr), wrapper_(nullptr)
129 {
130 }
131 
~MetadataOutputNapi()132 MetadataOutputNapi::~MetadataOutputNapi()
133 {
134     MEDIA_DEBUG_LOG("~MetadataOutputNapi is called");
135     if (wrapper_ != nullptr) {
136         napi_delete_reference(env_, wrapper_);
137     }
138     if (metadataOutput_) {
139         metadataOutput_ = nullptr;
140     }
141     if (metadataCallback_) {
142         metadataCallback_ = nullptr;
143     }
144 }
145 
MetadataOutputNapiDestructor(napi_env env,void * nativeObject,void * finalize_hint)146 void MetadataOutputNapi::MetadataOutputNapiDestructor(napi_env env, void* nativeObject, void* finalize_hint)
147 {
148     MEDIA_DEBUG_LOG("MetadataOutputNapiDestructor is called");
149     MetadataOutputNapi* metadataOutput = reinterpret_cast<MetadataOutputNapi*>(nativeObject);
150     if (metadataOutput != nullptr) {
151         delete metadataOutput;
152     }
153 }
154 
Init(napi_env env,napi_value exports)155 napi_value MetadataOutputNapi::Init(napi_env env, napi_value exports)
156 {
157     MEDIA_DEBUG_LOG("Init is called");
158     napi_status status;
159     napi_value ctorObj;
160     int32_t refCount = 1;
161 
162     napi_property_descriptor metadata_output_props[] = {
163         DECLARE_NAPI_FUNCTION("getSupportedMetadataObjectTypes", GetSupportedMetadataObjectTypes),
164         DECLARE_NAPI_FUNCTION("setCapturingMetadataObjectTypes", SetCapturingMetadataObjectTypes),
165         DECLARE_NAPI_FUNCTION("start", Start),
166         DECLARE_NAPI_FUNCTION("stop", Stop),
167         DECLARE_NAPI_FUNCTION("on", On)
168     };
169 
170     status = napi_define_class(env, CAMERA_METADATA_OUTPUT_NAPI_CLASS_NAME, NAPI_AUTO_LENGTH,
171                                MetadataOutputNapiConstructor, nullptr,
172                                sizeof(metadata_output_props) / sizeof(metadata_output_props[PARAM0]),
173                                metadata_output_props, &ctorObj);
174     if (status == napi_ok) {
175         status = napi_create_reference(env, ctorObj, refCount, &sConstructor_);
176         if (status == napi_ok) {
177             status = napi_set_named_property(env, exports, CAMERA_METADATA_OUTPUT_NAPI_CLASS_NAME, ctorObj);
178             if (status == napi_ok) {
179                 return exports;
180             }
181         }
182     }
183     MEDIA_ERR_LOG("Init call Failed!");
184     return nullptr;
185 }
186 
MetadataOutputNapiConstructor(napi_env env,napi_callback_info info)187 napi_value MetadataOutputNapi::MetadataOutputNapiConstructor(napi_env env, napi_callback_info info)
188 {
189     MEDIA_DEBUG_LOG("MetadataOutputNapiConstructor is called");
190     napi_status status;
191     napi_value result = nullptr;
192     napi_value thisVar = nullptr;
193 
194     napi_get_undefined(env, &result);
195     CAMERA_NAPI_GET_JS_OBJ_WITH_ZERO_ARGS(env, info, status, thisVar);
196 
197     if (status == napi_ok && thisVar != nullptr) {
198         std::unique_ptr<MetadataOutputNapi> obj = std::make_unique<MetadataOutputNapi>();
199         obj->env_ = env;
200         obj->metadataOutput_ = sMetadataOutput_;
201         std::shared_ptr<MetadataOutputCallback> callback =
202             std::make_shared<MetadataOutputCallback>(MetadataOutputCallback(env));
203         ((sptr<MetadataOutput> &)(obj->metadataOutput_))->SetCallback(callback);
204         obj->metadataCallback_ = callback;
205 
206         status = napi_wrap(env, thisVar, reinterpret_cast<void*>(obj.get()),
207                            MetadataOutputNapi::MetadataOutputNapiDestructor, nullptr, nullptr);
208         if (status == napi_ok) {
209             obj.release();
210             return thisVar;
211         } else {
212             MEDIA_ERR_LOG("Failure wrapping js to native napi");
213         }
214     }
215     MEDIA_ERR_LOG("MetadataOutputNapiConstructor call Failed!");
216     return result;
217 }
218 
IsMetadataOutput(napi_env env,napi_value obj)219 bool MetadataOutputNapi::IsMetadataOutput(napi_env env, napi_value obj)
220 {
221     MEDIA_DEBUG_LOG("IsMetadataOutput is called");
222     bool result = false;
223     napi_status status;
224     napi_value constructor = nullptr;
225 
226     status = napi_get_reference_value(env, sConstructor_, &constructor);
227     if (status == napi_ok) {
228         status = napi_instanceof(env, obj, constructor, &result);
229         if (status != napi_ok) {
230             result = false;
231         }
232     }
233     MEDIA_ERR_LOG("IsMetadataOutput call Failed!");
234     return result;
235 }
236 
GetMetadataOutput()237 sptr<MetadataOutput> MetadataOutputNapi::GetMetadataOutput()
238 {
239     return metadataOutput_;
240 }
241 
CreateMetadataOutput(napi_env env)242 napi_value MetadataOutputNapi::CreateMetadataOutput(napi_env env)
243 {
244     MEDIA_DEBUG_LOG("CreateMetadataOutput is called");
245     CAMERA_SYNC_TRACE;
246     napi_status status;
247     napi_value result = nullptr;
248     napi_value constructor;
249 
250     status = napi_get_reference_value(env, sConstructor_, &constructor);
251     if (status == napi_ok) {
252         int retCode = CameraManager::GetInstance()->CreateMetadataOutput(&sMetadataOutput_);
253         if (!CameraNapiUtils::CheckError(env, retCode)) {
254             return nullptr;
255         }
256         if (sMetadataOutput_ == nullptr) {
257             MEDIA_ERR_LOG("failed to create MetadataOutput");
258             return result;
259         }
260         status = napi_new_instance(env, constructor, 0, nullptr, &result);
261         sMetadataOutput_ = nullptr;
262         if (status == napi_ok && result != nullptr) {
263             return result;
264         } else {
265             MEDIA_ERR_LOG("Failed to create metadata output instance");
266         }
267     }
268     MEDIA_ERR_LOG("CreateMetadataOutput call Failed!");
269     napi_get_undefined(env, &result);
270     return result;
271 }
272 
CommonCompleteCallback(napi_env env,napi_status status,void * data)273 static void CommonCompleteCallback(napi_env env, napi_status status, void* data)
274 {
275     MEDIA_DEBUG_LOG("CommonCompleteCallback is called");
276     auto context = static_cast<MetadataOutputAsyncContext*>(data);
277     if (context == nullptr) {
278         MEDIA_ERR_LOG("Async context is null");
279         return;
280     }
281 
282     std::unique_ptr<JSAsyncContextOutput> jsContext = std::make_unique<JSAsyncContextOutput>();
283 
284     if (!context->status) {
285         CameraNapiUtils::CreateNapiErrorObject(env, context->errorCode, context->errorMsg.c_str(), jsContext);
286     } else {
287         jsContext->status = true;
288         napi_get_undefined(env, &jsContext->error);
289         if (context->bRetBool) {
290             napi_get_boolean(env, context->isSupported, &jsContext->data);
291         } else {
292             napi_get_undefined(env, &jsContext->data);
293         }
294     }
295 
296     if (!context->funcName.empty()) {
297         jsContext->funcName = context->funcName;
298     }
299 
300     if (context->work != nullptr) {
301         CameraNapiUtils::InvokeJSAsyncMethod(env, context->deferred, context->callbackRef,
302                                              context->work, *jsContext);
303     }
304     delete context;
305 }
306 
ConvertJSArrayToNative(napi_env env,size_t argc,const napi_value argv[],size_t & i,MetadataOutputAsyncContext & asyncContext)307 static int32_t ConvertJSArrayToNative(napi_env env, size_t argc, const napi_value argv[], size_t &i,
308     MetadataOutputAsyncContext &asyncContext)
309 {
310     MEDIA_DEBUG_LOG("ConvertJSArrayToNative is called");
311     uint32_t len = 0;
312     auto context = &asyncContext;
313 
314     if (napi_get_array_length(env, argv[i], &len) != napi_ok) {
315         return -1;
316     }
317 
318     for (uint32_t j = 0; j < len; j++) {
319         napi_value metadataObjectType = nullptr;
320         napi_valuetype valueType = napi_undefined;
321 
322         napi_get_element(env, argv[j], j, &metadataObjectType);
323         napi_typeof(env, metadataObjectType, &valueType);
324         if (valueType == napi_number) {
325             bool isValid = true;
326             int32_t metadataObjectTypeVal = 0;
327             MetadataObjectType nativeMetadataObjType;
328             napi_get_value_int32(env, metadataObjectType, &metadataObjectTypeVal);
329             CameraNapiUtils::MapMetadataObjSupportedTypesEnumFromJS(
330                 metadataObjectTypeVal, nativeMetadataObjType, isValid);
331             if (!isValid) {
332                 MEDIA_ERR_LOG("Unsupported metadata object type: napi object:%{public}d",
333                     metadataObjectTypeVal);
334                 continue;
335             }
336             context->setSupportedMetadataObjectTypes.push_back(nativeMetadataObjType);
337         }
338         i++;
339     }
340     return static_cast<int32_t>(len);
341 }
342 
ConvertJSArgsToNative(napi_env env,size_t argc,const napi_value argv[],MetadataOutputAsyncContext & asyncContext)343 static napi_value ConvertJSArgsToNative(napi_env env, size_t argc, const napi_value argv[],
344     MetadataOutputAsyncContext &asyncContext)
345 {
346     MEDIA_DEBUG_LOG("ConvertJSArgsToNative is called");
347     const int32_t refCount = 1;
348     napi_value result;
349     auto context = &asyncContext;
350     bool isArray = false;
351     int32_t ArrayLen = 0;
352 
353     NAPI_ASSERT(env, argv != nullptr, "Argument list is empty");
354 
355     for (size_t i = PARAM0; i < argc; i++) {
356         napi_valuetype valueType = napi_undefined;
357         napi_typeof(env, argv[i], &valueType);
358 
359         if ((i == PARAM0) && (napi_is_array(env, argv[i], &isArray) == napi_ok)
360             && (isArray == true)) {
361             ArrayLen = ConvertJSArrayToNative(env, argc, argv, i, asyncContext);
362             if (ArrayLen == -1) {
363                 napi_get_boolean(env, false, &result);
364                 return result;
365             }
366         } else if ((i == static_cast<size_t>(PARAM1 + ArrayLen)) && (valueType == napi_function)) {
367             napi_create_reference(env, argv[i], refCount, &context->callbackRef);
368             break;
369         } else {
370             NAPI_ASSERT(env, false, "type mismatch");
371         }
372     }
373 
374     // Return true napi_value if params are successfully obtained
375     napi_get_boolean(env, true, &result);
376     return result;
377 }
378 
GetSupportedMetadataObjectTypesAsyncCallbackComplete(napi_env env,napi_status status,void * data)379 static void GetSupportedMetadataObjectTypesAsyncCallbackComplete(napi_env env, napi_status status, void* data)
380 {
381     MEDIA_DEBUG_LOG("GetSupportedMetadataObjectTypesAsyncCallbackComplete is called");
382     auto context = static_cast<MetadataOutputAsyncContext*>(data);
383     napi_value metadataObjectTypes = nullptr;
384     CAMERA_NAPI_CHECK_NULL_PTR_RETURN_VOID(context, "Async context is null");
385 
386     std::unique_ptr<JSAsyncContextOutput> jsContext = std::make_unique<JSAsyncContextOutput>();
387     jsContext->status = true;
388     napi_get_undefined(env, &jsContext->error);
389 
390     size_t len = context->SupportedMetadataObjectTypes.size();
391     if (context->SupportedMetadataObjectTypes.empty()
392         || (napi_create_array(env, &metadataObjectTypes) != napi_ok)) {
393         MEDIA_ERR_LOG("No Metadata object Types or create array failed!");
394         CameraNapiUtils::CreateNapiErrorObject(env, context->errorCode,
395             "No Metadata object Types or create array failed!", jsContext);
396     }
397 
398     size_t i;
399     size_t j = 0;
400     for (i = 0; i < len; i++) {
401         int32_t iProp;
402         CameraNapiUtils::MapMetadataObjSupportedTypesEnum(context->SupportedMetadataObjectTypes[i], iProp);
403         napi_value value;
404         if (iProp != -1 && napi_create_int32(env, iProp, &value) == napi_ok) {
405             napi_set_element(env, metadataObjectTypes, j, value);
406             j++;
407         }
408     }
409     jsContext->data = metadataObjectTypes;
410 
411     if (!context->funcName.empty()) {
412         jsContext->funcName = context->funcName;
413     }
414 
415     if (context->work != nullptr) {
416         CameraNapiUtils::InvokeJSAsyncMethod(env, context->deferred, context->callbackRef,
417                                              context->work, *jsContext);
418     }
419     delete context;
420 }
421 
GetSupportedMetadataObjectTypes(napi_env env,napi_callback_info info)422 napi_value MetadataOutputNapi::GetSupportedMetadataObjectTypes(napi_env env, napi_callback_info info)
423 {
424     MEDIA_DEBUG_LOG("GetSupportedMetadataObjectTypes is called");
425     napi_status status;
426     napi_value result = nullptr;
427     size_t argc = ARGS_ONE;
428     napi_value argv[ARGS_ONE] = {0};
429     napi_value thisVar = nullptr;
430     napi_value resource = nullptr;
431     int32_t refCount = 1;
432 
433     CAMERA_NAPI_GET_JS_ARGS(env, info, argc, argv, thisVar);
434     NAPI_ASSERT(env, argc <= ARGS_ONE, "requires 1 parameters maximum");
435 
436     napi_get_undefined(env, &result);
437     std::unique_ptr<MetadataOutputAsyncContext> asyncContext = std::make_unique<MetadataOutputAsyncContext>();
438     status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&asyncContext->objectInfo));
439     if (status == napi_ok && asyncContext->objectInfo != nullptr) {
440         if (argc == ARGS_ONE) {
441             CAMERA_NAPI_GET_JS_ASYNC_CB_REF(env, argv[PARAM0], refCount, asyncContext->callbackRef);
442         }
443         CAMERA_NAPI_CREATE_PROMISE(env, asyncContext->callbackRef, asyncContext->deferred, result);
444         CAMERA_NAPI_CREATE_RESOURCE_NAME(env, resource, "GetSupportedMetadataObjectTypes");
445 
446         status = napi_create_async_work(
447             env, nullptr, resource, [](napi_env env, void* data) {
448                 auto context = static_cast<MetadataOutputAsyncContext*>(data);
449                 context->status = false;
450                 if (context->objectInfo != nullptr && context->objectInfo->metadataOutput_ != nullptr) {
451                     context->funcName = "MetadataOutputNapi::GetSupportedMetadataObjectTypes";
452                     context->SupportedMetadataObjectTypes =
453                         context->objectInfo->metadataOutput_->GetSupportedMetadataObjectTypes();
454                     context->status = true;
455                 }
456             },
457             GetSupportedMetadataObjectTypesAsyncCallbackComplete,
458             static_cast<void*>(asyncContext.get()), &asyncContext->work);
459         if (status != napi_ok) {
460             MEDIA_ERR_LOG("Failed to create napi_create_async_work for PhotoOutputNapi::Release");
461             napi_get_undefined(env, &result);
462         } else {
463             napi_queue_async_work(env, asyncContext->work);
464             asyncContext.release();
465         }
466     } else {
467         MEDIA_ERR_LOG("GetSupportedMetadataObjectTypes call Failed!");
468     }
469     return result;
470 }
471 
SetCapturingMetadataObjectTypes(napi_env env,napi_callback_info info)472 napi_value MetadataOutputNapi::SetCapturingMetadataObjectTypes(napi_env env, napi_callback_info info)
473 {
474     MEDIA_DEBUG_LOG("SetCapturingMetadataObjectTypes is called");
475     napi_status status;
476     napi_value result = nullptr;
477     size_t argc = ARGS_TWO;
478     napi_value argv[ARGS_TWO] = {0};
479     napi_value thisVar = nullptr;
480     napi_value resource = nullptr;
481 
482     CAMERA_NAPI_GET_JS_ARGS(env, info, argc, argv, thisVar);
483     NAPI_ASSERT(env, argc <= ARGS_TWO, "requires 2 parameters maximum");
484 
485     napi_get_undefined(env, &result);
486     std::unique_ptr<MetadataOutputAsyncContext> asyncContext = std::make_unique<MetadataOutputAsyncContext>();
487     status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&asyncContext->objectInfo));
488     if (status == napi_ok && asyncContext->objectInfo != nullptr) {
489         result = ConvertJSArgsToNative(env, argc, argv, *asyncContext);
490         CAMERA_NAPI_CHECK_NULL_PTR_RETURN_UNDEFINED(env, result, result, "Failed to obtain arguments");
491         CAMERA_NAPI_CREATE_PROMISE(env, asyncContext->callbackRef, asyncContext->deferred, result);
492         CAMERA_NAPI_CREATE_RESOURCE_NAME(env, resource, "SetCapturingMetadataObjectTypes");
493 
494         status = napi_create_async_work(
495             env, nullptr, resource, [](napi_env env, void* data) {
496                 auto context = static_cast<MetadataOutputAsyncContext*>(data);
497                 context->status = false;
498                 if (context->objectInfo != nullptr && context->objectInfo->metadataOutput_ != nullptr) {
499                     context->bRetBool = false;
500                     context->status = true;
501                     context->funcName = "MetadataOutputNapi::SetCapturingMetadataObjectTypes";
502                     context->objectInfo->metadataOutput_->SetCapturingMetadataObjectTypes(
503                         context->setSupportedMetadataObjectTypes);
504                 }
505             },
506             CommonCompleteCallback, static_cast<void*>(asyncContext.get()),
507             &asyncContext->work);
508         if (status != napi_ok) {
509             MEDIA_ERR_LOG("Failed to create napi_create_async_work for "
510                 "MetadataOutputNapi::SetCapturingMetadataObjectTypes");
511             napi_get_undefined(env, &result);
512         } else {
513             napi_queue_async_work(env, asyncContext->work);
514             asyncContext.release();
515         }
516     } else {
517         MEDIA_ERR_LOG("SetCapturingMetadataObjectTypes call Failed!");
518     }
519     return result;
520 }
521 
Start(napi_env env,napi_callback_info info)522 napi_value MetadataOutputNapi::Start(napi_env env, napi_callback_info info)
523 {
524     MEDIA_INFO_LOG("Start is called");
525     napi_status status;
526     napi_value result = nullptr;
527     const int32_t refCount = 1;
528     napi_value resource = nullptr;
529     size_t argc = ARGS_ONE;
530     napi_value argv[ARGS_ONE] = {0};
531     napi_value thisVar = nullptr;
532 
533     CAMERA_NAPI_GET_JS_ARGS(env, info, argc, argv, thisVar);
534     NAPI_ASSERT(env, argc <= ARGS_ONE, "requires 1 parameter maximum");
535 
536     napi_get_undefined(env, &result);
537     std::unique_ptr<MetadataOutputAsyncContext> asyncContext = std::make_unique<MetadataOutputAsyncContext>();
538     status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&asyncContext->objectInfo));
539     if (status == napi_ok && asyncContext->objectInfo != nullptr) {
540         if (argc == ARGS_ONE) {
541             CAMERA_NAPI_GET_JS_ASYNC_CB_REF(env, argv[PARAM0], refCount, asyncContext->callbackRef);
542         }
543 
544         CAMERA_NAPI_CREATE_PROMISE(env, asyncContext->callbackRef, asyncContext->deferred, result);
545         CAMERA_NAPI_CREATE_RESOURCE_NAME(env, resource, "Start");
546 
547         status = napi_create_async_work(
548             env, nullptr, resource, [](napi_env env, void* data) {
549                 auto context = static_cast<MetadataOutputAsyncContext*>(data);
550                 context->status = false;
551                 if (context->objectInfo != nullptr && context->objectInfo->metadataOutput_ != nullptr) {
552                     context->bRetBool = false;
553                     context->funcName = "MetadataOutputNapi::Start";
554                     context->errorCode = context->objectInfo->metadataOutput_->Start();
555                     context->status = context->errorCode == 0;
556                 }
557             },
558             CommonCompleteCallback, static_cast<void*>(asyncContext.get()), &asyncContext->work);
559         if (status != napi_ok) {
560             MEDIA_ERR_LOG("Failed to create napi_create_async_work for MetadataOutputNapi::Start");
561             napi_get_undefined(env, &result);
562         } else {
563             napi_queue_async_work(env, asyncContext->work);
564             asyncContext.release();
565         }
566     } else {
567         MEDIA_ERR_LOG("Start call Failed!");
568     }
569     return result;
570 }
571 
Stop(napi_env env,napi_callback_info info)572 napi_value MetadataOutputNapi::Stop(napi_env env, napi_callback_info info)
573 {
574     MEDIA_INFO_LOG("Stop is called");
575     napi_status status;
576     napi_value result = nullptr;
577     const int32_t refCount = 1;
578     napi_value resource = nullptr;
579     size_t argc = ARGS_ONE;
580     napi_value argv[ARGS_ONE] = {0};
581     napi_value thisVar = nullptr;
582 
583     CAMERA_NAPI_GET_JS_ARGS(env, info, argc, argv, thisVar);
584     NAPI_ASSERT(env, argc <= ARGS_ONE, "requires 1 parameter maximum");
585 
586     napi_get_undefined(env, &result);
587     std::unique_ptr<MetadataOutputAsyncContext> asyncContext = std::make_unique<MetadataOutputAsyncContext>();
588     status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&asyncContext->objectInfo));
589     if (status == napi_ok && asyncContext->objectInfo != nullptr) {
590         if (argc == ARGS_ONE) {
591             CAMERA_NAPI_GET_JS_ASYNC_CB_REF(env, argv[PARAM0], refCount, asyncContext->callbackRef);
592         }
593 
594         CAMERA_NAPI_CREATE_PROMISE(env, asyncContext->callbackRef, asyncContext->deferred, result);
595         CAMERA_NAPI_CREATE_RESOURCE_NAME(env, resource, "Stop");
596 
597         status = napi_create_async_work(
598             env, nullptr, resource, [](napi_env env, void* data) {
599                 auto context = static_cast<MetadataOutputAsyncContext*>(data);
600                 context->status = false;
601                 if (context->objectInfo != nullptr && context->objectInfo->metadataOutput_ != nullptr) {
602                     context->bRetBool = false;
603                     context->status = true;
604                     context->funcName = "MetadataOutputNapi::Stop";
605                     context->errorCode = context->objectInfo->metadataOutput_->Stop();
606                     context->status = context->errorCode == 0;
607                 }
608             },
609             CommonCompleteCallback, static_cast<void*>(asyncContext.get()), &asyncContext->work);
610         if (status != napi_ok) {
611             MEDIA_ERR_LOG("Failed to create napi_create_async_work for MetadataOutputNapi::Stop");
612             napi_get_undefined(env, &result);
613         } else {
614             napi_queue_async_work(env, asyncContext->work);
615             asyncContext.release();
616         }
617     } else {
618         MEDIA_ERR_LOG("Stop call Failed!");
619     }
620     return result;
621 }
622 
On(napi_env env,napi_callback_info info)623 napi_value MetadataOutputNapi::On(napi_env env, napi_callback_info info)
624 {
625     MEDIA_INFO_LOG("On is called");
626     napi_value undefinedResult = nullptr;
627     size_t argCount = ARGS_TWO;
628     napi_value argv[ARGS_TWO] = {nullptr};
629     napi_value thisVar = nullptr;
630     size_t res = 0;
631     char buffer[SIZE];
632     const int32_t refCount = 1;
633     MetadataOutputNapi* obj = nullptr;
634     napi_status status;
635 
636     napi_get_undefined(env, &undefinedResult);
637 
638     CAMERA_NAPI_GET_JS_ARGS(env, info, argCount, argv, thisVar);
639     NAPI_ASSERT(env, argCount == ARGS_TWO, "requires 2 parameters");
640 
641     if (thisVar == nullptr || argv[PARAM0] == nullptr || argv[PARAM1] == nullptr) {
642         MEDIA_ERR_LOG("Failed to retrieve details about the callback");
643         return undefinedResult;
644     }
645 
646     status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&obj));
647     if (status == napi_ok && obj != nullptr) {
648         napi_valuetype valueType = napi_undefined;
649         if (napi_typeof(env, argv[PARAM0], &valueType) != napi_ok || valueType != napi_string
650             || napi_typeof(env, argv[PARAM1], &valueType) != napi_ok || valueType != napi_function) {
651             return undefinedResult;
652         }
653 
654         napi_get_value_string_utf8(env, argv[PARAM0], buffer, SIZE, &res);
655         std::string eventType = std::string(buffer);
656 
657         napi_ref callbackRef;
658         napi_create_reference(env, argv[PARAM1], refCount, &callbackRef);
659 
660         if (!eventType.empty()) {
661             obj->metadataCallback_->SetCallbackRef(eventType, callbackRef);
662         } else {
663             MEDIA_ERR_LOG("Failed to Register Callback: event type is empty!");
664         }
665     } else {
666         MEDIA_ERR_LOG("On call Failed!");
667     }
668     return undefinedResult;
669 }
670 } // namespace CameraStandard
671 } // namespace OHOS