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