• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "output/preview_output_napi.h"
17 #include <unistd.h>
18 #include <uv.h>
19 
20 namespace OHOS {
21 namespace CameraStandard {
22 using namespace std;
23 using OHOS::HiviewDFX::HiLog;
24 using OHOS::HiviewDFX::HiLogLabel;
25 namespace {
26     constexpr HiLogLabel LABEL = {LOG_CORE, LOG_DOMAIN, "PreviewOutputNapi"};
27 }
28 thread_local napi_ref PreviewOutputNapi::sConstructor_ = nullptr;
29 thread_local sptr<PreviewOutput> PreviewOutputNapi::sPreviewOutput_ = nullptr;
30 thread_local uint32_t PreviewOutputNapi::previewOutputTaskId = CAMERA_PREVIEW_OUTPUT_TASKID;
31 
PreviewOutputCallback(napi_env env)32 PreviewOutputCallback::PreviewOutputCallback(napi_env env) : env_(env) {}
33 
UpdateJSCallbackAsync(std::string propName,const int32_t value) const34 void PreviewOutputCallback::UpdateJSCallbackAsync(std::string propName, const int32_t value) const
35 {
36     MEDIA_DEBUG_LOG("UpdateJSCallbackAsync is called");
37     uv_loop_s* loop = nullptr;
38     napi_get_uv_event_loop(env_, &loop);
39     if (!loop) {
40         MEDIA_ERR_LOG("failed to get event loop");
41         return;
42     }
43     uv_work_t* work = new(std::nothrow) uv_work_t;
44     if (!work) {
45         MEDIA_ERR_LOG("failed to allocate work");
46         return;
47     }
48     std::unique_ptr<PreviewOutputCallbackInfo> callbackInfo =
49         std::make_unique<PreviewOutputCallbackInfo>(propName, value, this);
50     work->data = callbackInfo.get();
51     int ret = uv_queue_work(loop, work, [] (uv_work_t* work) {}, [] (uv_work_t* work, int status) {
52         PreviewOutputCallbackInfo* callbackInfo = reinterpret_cast<PreviewOutputCallbackInfo *>(work->data);
53         if (callbackInfo) {
54             callbackInfo->listener_->UpdateJSCallback(callbackInfo->eventName_, callbackInfo->value_);
55             delete callbackInfo;
56         }
57         delete work;
58     });
59     if (ret) {
60         MEDIA_ERR_LOG("failed to execute work");
61         delete work;
62     } else {
63         callbackInfo.release();
64     }
65 }
66 
OnFrameStarted() const67 void PreviewOutputCallback::OnFrameStarted() const
68 {
69     CAMERA_SYNC_TRACE;
70     MEDIA_DEBUG_LOG("OnFrameStarted is called");
71     UpdateJSCallbackAsync("OnFrameStarted", -1);
72 }
73 
OnFrameEnded(const int32_t frameCount) const74 void PreviewOutputCallback::OnFrameEnded(const int32_t frameCount) const
75 {
76     CAMERA_SYNC_TRACE;
77     MEDIA_DEBUG_LOG("OnFrameEnded is called, frameCount: %{public}d", frameCount);
78     UpdateJSCallbackAsync("OnFrameEnded", frameCount);
79 }
80 
OnError(const int32_t errorCode) const81 void PreviewOutputCallback::OnError(const int32_t errorCode) const
82 {
83     MEDIA_DEBUG_LOG("OnError is called, errorCode: %{public}d", errorCode);
84     UpdateJSCallbackAsync("OnError", errorCode);
85 }
86 
SetCallbackRef(const std::string & eventType,const napi_ref & callbackRef)87 void PreviewOutputCallback::SetCallbackRef(const std::string &eventType, const napi_ref &callbackRef)
88 {
89     MEDIA_DEBUG_LOG("SetCallbackRef is called");
90     if (eventType.compare("frameStart") == 0) {
91         frameStartCallbackRef_ = callbackRef;
92     } else if (eventType.compare("frameEnd") == 0) {
93         frameEndCallbackRef_ = callbackRef;
94     } else if (eventType.compare("error") == 0) {
95         errorCallbackRef_ = callbackRef;
96     } else {
97         MEDIA_ERR_LOG("Incorrect preview callback event type received from JS");
98     }
99 }
100 
UpdateJSCallback(std::string propName,const int32_t value) const101 void PreviewOutputCallback::UpdateJSCallback(std::string propName, const int32_t value) const
102 {
103     MEDIA_DEBUG_LOG("UpdateJSCallback is called");
104     napi_value result[ARGS_TWO];
105     napi_value callback = nullptr;
106     napi_value retVal;
107     napi_value propValue;
108     napi_get_undefined(env_, &result[PARAM0]);
109     if (propName.compare("OnFrameStarted") == 0) {
110         CAMERA_NAPI_CHECK_NULL_PTR_RETURN_VOID(frameStartCallbackRef_,
111             "OnFrameStart callback is not registered by JS");
112         napi_get_undefined(env_, &result[PARAM1]);
113         napi_get_reference_value(env_, frameStartCallbackRef_, &callback);
114     } else if (propName.compare("OnFrameEnded") == 0) {
115         CAMERA_NAPI_CHECK_NULL_PTR_RETURN_VOID(frameEndCallbackRef_,
116             "OnFrameEnd callback is not registered by JS");
117         napi_get_undefined(env_, &result[PARAM1]);
118         napi_get_reference_value(env_, frameEndCallbackRef_, &callback);
119     } else {
120         CAMERA_NAPI_CHECK_NULL_PTR_RETURN_VOID(errorCallbackRef_,
121             "OnError callback is not registered by JS");
122         napi_value errJsResult[ARGS_ONE];
123         int32_t jsErrorCodeUnknown = -1;
124         napi_create_object(env_, &errJsResult[PARAM0]);
125         napi_create_int32(env_, jsErrorCodeUnknown, &propValue);
126         napi_set_named_property(env_, errJsResult[PARAM0], "code", propValue);
127         napi_get_reference_value(env_, errorCallbackRef_, &callback); // should errorcode be valued as -1
128         if (errorCallbackRef_ != nullptr) {
129             napi_delete_reference(env_, errorCallbackRef_);
130         }
131         napi_call_function(env_, nullptr, callback, ARGS_ONE, errJsResult, &retVal);
132         return;
133     }
134 
135     napi_call_function(env_, nullptr, callback, ARGS_TWO, result, &retVal);
136 }
137 
PreviewOutputNapi()138 PreviewOutputNapi::PreviewOutputNapi() : env_(nullptr), wrapper_(nullptr)
139 {
140 }
141 
~PreviewOutputNapi()142 PreviewOutputNapi::~PreviewOutputNapi()
143 {
144     MEDIA_DEBUG_LOG("~PreviewOutputNapi is called");
145     if (wrapper_ != nullptr) {
146         napi_delete_reference(env_, wrapper_);
147     }
148     if (previewOutput_) {
149         previewOutput_ = nullptr;
150     }
151     if (previewCallback_) {
152         previewCallback_ = nullptr;
153     }
154 }
155 
PreviewOutputNapiDestructor(napi_env env,void * nativeObject,void * finalize_hint)156 void PreviewOutputNapi::PreviewOutputNapiDestructor(napi_env env, void* nativeObject, void* finalize_hint)
157 {
158     MEDIA_DEBUG_LOG("PreviewOutputNapiDestructor is called");
159     PreviewOutputNapi* cameraObj = reinterpret_cast<PreviewOutputNapi*>(nativeObject);
160     if (cameraObj != nullptr) {
161         delete cameraObj;
162     }
163 }
164 
Init(napi_env env,napi_value exports)165 napi_value PreviewOutputNapi::Init(napi_env env, napi_value exports)
166 {
167     MEDIA_DEBUG_LOG("Init is called");
168     napi_status status;
169     napi_value ctorObj;
170     int32_t refCount = 1;
171 
172     napi_property_descriptor preview_output_props[] = {
173         DECLARE_NAPI_FUNCTION("addDeferredSurface", AddDeferredSurface),
174         DECLARE_NAPI_FUNCTION("start", Start),
175         DECLARE_NAPI_FUNCTION("stop", Stop),
176         DECLARE_NAPI_FUNCTION("release", Release),
177         DECLARE_NAPI_FUNCTION("on", On)
178     };
179 
180     status = napi_define_class(env, CAMERA_PREVIEW_OUTPUT_NAPI_CLASS_NAME, NAPI_AUTO_LENGTH,
181                                PreviewOutputNapiConstructor, nullptr,
182                                sizeof(preview_output_props) / sizeof(preview_output_props[PARAM0]),
183                                preview_output_props, &ctorObj);
184     if (status == napi_ok) {
185         status = napi_create_reference(env, ctorObj, refCount, &sConstructor_);
186         if (status == napi_ok) {
187             status = napi_set_named_property(env, exports, CAMERA_PREVIEW_OUTPUT_NAPI_CLASS_NAME, ctorObj);
188             if (status == napi_ok) {
189                 return exports;
190             }
191         }
192     }
193     MEDIA_ERR_LOG("Init call Failed!");
194     return nullptr;
195 }
196 // Constructor callback
PreviewOutputNapiConstructor(napi_env env,napi_callback_info info)197 napi_value PreviewOutputNapi::PreviewOutputNapiConstructor(napi_env env, napi_callback_info info)
198 {
199     MEDIA_DEBUG_LOG("PreviewOutputNapiConstructor is called");
200     napi_status status;
201     napi_value result = nullptr;
202     napi_value thisVar = nullptr;
203 
204     napi_get_undefined(env, &result);
205     CAMERA_NAPI_GET_JS_OBJ_WITH_ZERO_ARGS(env, info, status, thisVar);
206 
207     if (status == napi_ok && thisVar != nullptr) {
208         std::unique_ptr<PreviewOutputNapi> obj = std::make_unique<PreviewOutputNapi>();
209         if (obj != nullptr) {
210             obj->env_ = env;
211             obj->previewOutput_ = sPreviewOutput_;
212 
213             std::shared_ptr<PreviewOutputCallback> callback =
214                 std::make_shared<PreviewOutputCallback>(PreviewOutputCallback(env));
215             ((sptr<PreviewOutput> &)(obj->previewOutput_))->SetCallback(callback);
216             obj->previewCallback_ = callback;
217 
218             status = napi_wrap(env, thisVar, reinterpret_cast<void*>(obj.get()),
219                                PreviewOutputNapi::PreviewOutputNapiDestructor, nullptr, nullptr);
220             if (status == napi_ok) {
221                 obj.release();
222                 return thisVar;
223             } else {
224                 MEDIA_ERR_LOG("Failure wrapping js to native napi");
225             }
226         }
227     }
228     MEDIA_ERR_LOG("PreviewOutputNapiConstructor call Failed!");
229     return result;
230 }
231 
CommonCompleteCallback(napi_env env,napi_status status,void * data)232 static void CommonCompleteCallback(napi_env env, napi_status status, void* data)
233 {
234     MEDIA_DEBUG_LOG("CommonCompleteCallback is called");
235     auto context = static_cast<PreviewOutputAsyncContext*>(data);
236     if (context == nullptr) {
237         MEDIA_ERR_LOG("Async context is null");
238         return;
239     }
240 
241     std::unique_ptr<JSAsyncContextOutput> jsContext = std::make_unique<JSAsyncContextOutput>();
242 
243     if (!context->status) {
244         CameraNapiUtils::CreateNapiErrorObject(env, context->errorCode, context->errorMsg.c_str(), jsContext);
245     } else {
246         jsContext->status = true;
247         napi_get_undefined(env, &jsContext->error);
248         if (context->bRetBool) {
249             napi_get_boolean(env, context->status, &jsContext->data);
250         } else {
251             napi_get_undefined(env, &jsContext->data);
252         }
253     }
254 
255     if (!context->funcName.empty() && context->taskId > 0) {
256         // Finish async trace
257         CAMERA_FINISH_ASYNC_TRACE(context->funcName, context->taskId);
258         jsContext->funcName = context->funcName;
259     }
260 
261     if (context->work != nullptr) {
262         CameraNapiUtils::InvokeJSAsyncMethod(env, context->deferred, context->callbackRef,
263                                              context->work, *jsContext);
264     }
265     delete context;
266 }
267 
CreateDeferredPreviewOutput(napi_env env,Profile & profile)268 napi_value PreviewOutputNapi::CreateDeferredPreviewOutput(napi_env env, Profile &profile)
269 {
270     CAMERA_SYNC_TRACE;
271     napi_status status;
272     napi_value result = nullptr;
273     napi_value constructor;
274 
275     status = napi_get_reference_value(env, sConstructor_, &constructor);
276     if (status == napi_ok) {
277         sPreviewOutput_ = CameraManager::GetInstance()->CreateDeferredPreviewOutput(profile);
278         if (sPreviewOutput_ == nullptr) {
279             MEDIA_ERR_LOG("failed to create previewOutput");
280             return result;
281         }
282         status = napi_new_instance(env, constructor, 0, nullptr, &result);
283         sPreviewOutput_ = nullptr;
284 
285         if (status == napi_ok && result != nullptr) {
286             return result;
287         } else {
288             MEDIA_ERR_LOG("Failed to create preview output instance");
289         }
290     }
291 
292     napi_get_undefined(env, &result);
293     return result;
294 }
295 
CreatePreviewOutput(napi_env env,Profile & profile,std::string surfaceId)296 napi_value PreviewOutputNapi::CreatePreviewOutput(napi_env env, Profile &profile, std::string surfaceId)
297 {
298     MEDIA_INFO_LOG("CreatePreviewOutput is called");
299     CAMERA_SYNC_TRACE;
300     napi_status status;
301     napi_value result = nullptr;
302     napi_value constructor;
303 
304     status = napi_get_reference_value(env, sConstructor_, &constructor);
305     if (status == napi_ok) {
306         uint64_t iSurfaceId;
307         std::istringstream iss(surfaceId);
308         iss >> iSurfaceId;
309         sptr<Surface> surface = SurfaceUtils::GetInstance()->GetSurface(iSurfaceId);
310         if (!surface) {
311             surface = Media::ImageReceiver::getSurfaceById(surfaceId);
312         }
313         if (surface == nullptr) {
314             MEDIA_ERR_LOG("failed to get surface");
315             return result;
316         }
317 
318         surface->SetUserData(CameraManager::surfaceFormat, std::to_string(profile.GetCameraFormat()));
319         int retCode = CameraManager::GetInstance()->CreatePreviewOutput(profile, surface, &sPreviewOutput_);
320         if (!CameraNapiUtils::CheckError(env, retCode)) {
321             return nullptr;
322         }
323         if (sPreviewOutput_ == nullptr) {
324             MEDIA_ERR_LOG("failed to create previewOutput");
325             return result;
326         }
327         status = napi_new_instance(env, constructor, 0, nullptr, &result);
328         sPreviewOutput_ = nullptr;
329 
330         if (status == napi_ok && result != nullptr) {
331             return result;
332         } else {
333             MEDIA_ERR_LOG("Failed to create preview output instance");
334         }
335     }
336     MEDIA_ERR_LOG("CreatePreviewOutput call Failed!");
337     napi_get_undefined(env, &result);
338     return result;
339 }
340 
GetPreviewOutput()341 sptr<PreviewOutput> PreviewOutputNapi::GetPreviewOutput()
342 {
343     return previewOutput_;
344 }
345 
IsPreviewOutput(napi_env env,napi_value obj)346 bool PreviewOutputNapi::IsPreviewOutput(napi_env env, napi_value obj)
347 {
348     MEDIA_DEBUG_LOG("IsPreviewOutput is called");
349     bool result = false;
350     napi_status status;
351     napi_value constructor = nullptr;
352 
353     status = napi_get_reference_value(env, sConstructor_, &constructor);
354     if (status == napi_ok) {
355         status = napi_instanceof(env, obj, constructor, &result);
356         if (status != napi_ok) {
357             result = false;
358         }
359     }
360     return result;
361 }
362 
Release(napi_env env,napi_callback_info info)363 napi_value PreviewOutputNapi::Release(napi_env env, napi_callback_info info)
364 {
365     MEDIA_DEBUG_LOG("Release is called");
366     napi_status status;
367     napi_value result = nullptr;
368     const int32_t refCount = 1;
369     napi_value resource = nullptr;
370     size_t argc = ARGS_ONE;
371     napi_value argv[ARGS_ONE] = {0};
372     napi_value thisVar = nullptr;
373 
374     CAMERA_NAPI_GET_JS_ARGS(env, info, argc, argv, thisVar);
375     NAPI_ASSERT(env, argc <= ARGS_ONE, "requires 1 parameter maximum");
376 
377     napi_get_undefined(env, &result);
378     std::unique_ptr<PreviewOutputAsyncContext> asyncContext = std::make_unique<PreviewOutputAsyncContext>();
379     status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&asyncContext->objectInfo));
380     if (status == napi_ok && asyncContext->objectInfo != nullptr) {
381         if (argc == ARGS_ONE) {
382             CAMERA_NAPI_GET_JS_ASYNC_CB_REF(env, argv[PARAM0], refCount, asyncContext->callbackRef);
383         }
384 
385         CAMERA_NAPI_CREATE_PROMISE(env, asyncContext->callbackRef, asyncContext->deferred, result);
386         CAMERA_NAPI_CREATE_RESOURCE_NAME(env, resource, "Release");
387 
388         status = napi_create_async_work(
389             env, nullptr, resource, [](napi_env env, void* data) {
390                 auto context = static_cast<PreviewOutputAsyncContext*>(data);
391                 context->status = false;
392                 // Start async trace
393                 context->funcName = "PreviewOutputNapi::Release";
394                 context->taskId = CameraNapiUtils::IncreamentAndGet(previewOutputTaskId);
395                 CAMERA_START_ASYNC_TRACE(context->funcName, context->taskId);
396                 if (context->objectInfo != nullptr && context->objectInfo->previewOutput_ != nullptr) {
397                     context->bRetBool = false;
398                     context->status = true;
399                     ((sptr<PreviewOutput> &)(context->objectInfo->previewOutput_))->Release();
400                 }
401             },
402             CommonCompleteCallback, static_cast<void*>(asyncContext.get()), &asyncContext->work);
403         if (status != napi_ok) {
404             MEDIA_ERR_LOG("Failed to create napi_create_async_work for PreviewOutputNapi::Release");
405             napi_get_undefined(env, &result);
406         } else {
407             napi_queue_async_work(env, asyncContext->work);
408             asyncContext.release();
409         }
410     } else {
411         MEDIA_ERR_LOG("Release call Failed!");
412     }
413     return result;
414 }
415 
ConvertJSArgsToNative(napi_env env,size_t argc,const napi_value argv[],PreviewOutputAsyncContext & asyncContext)416 static napi_value ConvertJSArgsToNative(napi_env env, size_t argc, const napi_value argv[],
417     PreviewOutputAsyncContext &asyncContext)
418 {
419     char buffer[PATH_MAX];
420     const int32_t refCount = 1;
421     napi_value result;
422     size_t length = 0;
423     auto context = &asyncContext;
424 
425     NAPI_ASSERT(env, argv != nullptr, "Argument list is empty");
426 
427     for (size_t i = PARAM0; i < argc; i++) {
428         napi_valuetype valueType = napi_undefined;
429         napi_typeof(env, argv[i], &valueType);
430         if (i == PARAM0 && valueType == napi_string) {
431             if (napi_get_value_string_utf8(env, argv[i], buffer, PATH_MAX, &length) == napi_ok) {
432                 MEDIA_DEBUG_LOG("surfaceId buffer: %{public}s", buffer);
433                 context->surfaceId = std::string(buffer);
434                 MEDIA_DEBUG_LOG("context->surfaceId after convert : %{public}s", context->surfaceId.c_str());
435             } else {
436                 MEDIA_ERR_LOG("Could not able to read surfaceId argument!");
437             }
438         } else if (i == PARAM1 && valueType == napi_function) {
439             napi_create_reference(env, argv[i], refCount, &context->callbackRef);
440             break;
441         } else {
442             NAPI_ASSERT(env, false, "type mismatch");
443         }
444     }
445 
446     // Return true napi_value if params are successfully obtained
447     napi_get_boolean(env, true, &result);
448     return result;
449 }
450 
CreateAsyncTask(napi_env env,napi_value resource,std::unique_ptr<PreviewOutputAsyncContext> & asyncContext)451 napi_status PreviewOutputNapi::CreateAsyncTask(napi_env env, napi_value resource,
452     std::unique_ptr<PreviewOutputAsyncContext> &asyncContext)
453 {
454     napi_status status = napi_create_async_work(env, nullptr, resource, [](napi_env env, void* data) {
455         auto context = static_cast<PreviewOutputAsyncContext*>(data);
456         context->status = false;
457         // Start async trace
458         context->funcName = "PreviewOutputNapi::AddDeferredSurface";
459         context->taskId = CameraNapiUtils::IncreamentAndGet(previewOutputTaskId);
460         CAMERA_START_ASYNC_TRACE(context->funcName, context->taskId);
461         if (context->objectInfo != nullptr && context->objectInfo->previewOutput_ != nullptr) {
462             context->bRetBool = false;
463             context->status = true;
464             uint64_t iSurfaceId;
465             std::istringstream iss(context->surfaceId);
466             iss >> iSurfaceId;
467             sptr<Surface> surface = SurfaceUtils::GetInstance()->GetSurface(iSurfaceId);
468             if (!surface) {
469                 surface = Media::ImageReceiver::getSurfaceById(context->surfaceId);
470             }
471             if (surface == nullptr) {
472                 MEDIA_ERR_LOG("failed to get surface");
473                 return;
474             }
475             CameraFormat format = ((sptr<PreviewOutput> &)(context->objectInfo->previewOutput_))->format;
476             surface->SetUserData(CameraManager::surfaceFormat, std::to_string(format));
477             ((sptr<PreviewOutput> &)(context->objectInfo->previewOutput_))->AddDeferredSurface(surface);
478         }
479     },
480     CommonCompleteCallback, static_cast<void*>(asyncContext.get()), &asyncContext->work);
481     return status;
482 }
483 
AddDeferredSurface(napi_env env,napi_callback_info info)484 napi_value PreviewOutputNapi::AddDeferredSurface(napi_env env, napi_callback_info info)
485 {
486     MEDIA_DEBUG_LOG("AddDeferredSurface is called");
487     if (!CameraNapiUtils::CheckSystemApp(env)) {
488         MEDIA_ERR_LOG("SystemApi AddDeferredSurface is called!");
489         return nullptr;
490     }
491     napi_status status;
492     napi_value result = nullptr;
493     const int32_t refCount = 1;
494     napi_value resource = nullptr;
495     size_t argc = ARGS_TWO;
496     napi_value argv[ARGS_TWO] = {0};
497     napi_value thisVar = nullptr;
498     CAMERA_NAPI_GET_JS_ARGS(env, info, argc, argv, thisVar);
499     if (!CameraNapiUtils::CheckInvalidArgument(env, argc, ARGS_TWO, argv, ADD_DEFERRED_SURFACE)) {
500         return result;
501     }
502     napi_get_undefined(env, &result);
503     std::unique_ptr<PreviewOutputAsyncContext> asyncContext = std::make_unique<PreviewOutputAsyncContext>();
504     status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&asyncContext->objectInfo));
505     result = ConvertJSArgsToNative(env, argc, argv, *asyncContext);
506     CAMERA_NAPI_CHECK_NULL_PTR_RETURN_UNDEFINED(env, result, result, "Failed to obtain arguments");
507     if (status == napi_ok && asyncContext->objectInfo != nullptr) {
508         if (argc == ARGS_TWO) {
509             CAMERA_NAPI_GET_JS_ASYNC_CB_REF(env, argv[PARAM1], refCount, asyncContext->callbackRef);
510         }
511         CAMERA_NAPI_CREATE_PROMISE(env, asyncContext->callbackRef, asyncContext->deferred, result);
512         CAMERA_NAPI_CREATE_RESOURCE_NAME(env, resource, "AddDeferredSurface");
513         status = CreateAsyncTask(env, resource, asyncContext);
514         if (status != napi_ok) {
515             MEDIA_ERR_LOG("Failed to create napi_create_async_work!");
516             napi_get_undefined(env, &result);
517         } else {
518             napi_queue_async_work(env, asyncContext->work);
519             asyncContext.release();
520         }
521     } else {
522         MEDIA_ERR_LOG("AddDeferredSurface call Failed!");
523     }
524     return result;
525 }
526 
Start(napi_env env,napi_callback_info info)527 napi_value PreviewOutputNapi::Start(napi_env env, napi_callback_info info)
528 {
529     MEDIA_INFO_LOG("Start is called");
530     napi_status status;
531     napi_value result = nullptr;
532     const int32_t refCount = 1;
533     napi_value resource = nullptr;
534     size_t argc = ARGS_ONE;
535     napi_value argv[ARGS_ONE] = {0};
536     napi_value thisVar = nullptr;
537 
538     CAMERA_NAPI_GET_JS_ARGS(env, info, argc, argv, thisVar);
539     NAPI_ASSERT(env, argc <= ARGS_ONE, "requires 1 parameter maximum");
540 
541     napi_get_undefined(env, &result);
542     std::unique_ptr<PreviewOutputAsyncContext> asyncContext = std::make_unique<PreviewOutputAsyncContext>();
543     status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&asyncContext->objectInfo));
544     if (status == napi_ok && asyncContext->objectInfo != nullptr) {
545         if (argc == ARGS_ONE) {
546             CAMERA_NAPI_GET_JS_ASYNC_CB_REF(env, argv[PARAM0], refCount, asyncContext->callbackRef);
547         }
548 
549         CAMERA_NAPI_CREATE_PROMISE(env, asyncContext->callbackRef, asyncContext->deferred, result);
550         CAMERA_NAPI_CREATE_RESOURCE_NAME(env, resource, "Start");
551 
552         status = napi_create_async_work(
553             env, nullptr, resource, [](napi_env env, void* data) {
554                 auto context = static_cast<PreviewOutputAsyncContext*>(data);
555                 context->status = false;
556                 // Start async trace
557                 context->funcName = "PreviewOutputNapi::Start";
558                 context->taskId = CameraNapiUtils::IncreamentAndGet(previewOutputTaskId);
559                 CAMERA_START_ASYNC_TRACE(context->funcName, context->taskId);
560                 if (context->objectInfo != nullptr && context->objectInfo->previewOutput_ != nullptr) {
561                     context->bRetBool = false;
562                     context->errorCode = context->objectInfo->previewOutput_->Start();
563                     context->status = context->errorCode == 0;
564                 }
565             },
566             CommonCompleteCallback, static_cast<void*>(asyncContext.get()), &asyncContext->work);
567         if (status != napi_ok) {
568             MEDIA_ERR_LOG("Failed to create napi_create_async_work for PreviewOutputNapi::Release");
569             napi_get_undefined(env, &result);
570         } else {
571             napi_queue_async_work(env, asyncContext->work);
572             asyncContext.release();
573         }
574     } else {
575         MEDIA_ERR_LOG("Start call Failed!");
576     }
577     return result;
578 }
579 
Stop(napi_env env,napi_callback_info info)580 napi_value PreviewOutputNapi::Stop(napi_env env, napi_callback_info info)
581 {
582     MEDIA_INFO_LOG("Stop is called");
583     napi_status status;
584     napi_value result = nullptr;
585     const int32_t refCount = 1;
586     napi_value resource = nullptr;
587     size_t argc = ARGS_ONE;
588     napi_value argv[ARGS_ONE] = {0};
589     napi_value thisVar = nullptr;
590 
591     CAMERA_NAPI_GET_JS_ARGS(env, info, argc, argv, thisVar);
592     NAPI_ASSERT(env, argc <= ARGS_ONE, "requires 1 parameter maximum");
593 
594     napi_get_undefined(env, &result);
595     std::unique_ptr<PreviewOutputAsyncContext> asyncContext = std::make_unique<PreviewOutputAsyncContext>();
596     status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&asyncContext->objectInfo));
597     if (status == napi_ok && asyncContext->objectInfo != nullptr) {
598         if (argc == ARGS_ONE) {
599             CAMERA_NAPI_GET_JS_ASYNC_CB_REF(env, argv[PARAM0], refCount, asyncContext->callbackRef);
600         }
601 
602         CAMERA_NAPI_CREATE_PROMISE(env, asyncContext->callbackRef, asyncContext->deferred, result);
603         CAMERA_NAPI_CREATE_RESOURCE_NAME(env, resource, "Stop");
604 
605         status = napi_create_async_work(
606             env, nullptr, resource, [](napi_env env, void* data) {
607                 auto context = static_cast<PreviewOutputAsyncContext*>(data);
608                 context->status = false;
609                 // Start async trace
610                 context->funcName = "PreviewOutputNapi::Stop";
611                 context->taskId = CameraNapiUtils::IncreamentAndGet(previewOutputTaskId);
612                 CAMERA_START_ASYNC_TRACE(context->funcName, context->taskId);
613                 if (context->objectInfo != nullptr && context->objectInfo->previewOutput_ != nullptr) {
614                     context->bRetBool = false;
615                     context->errorCode = context->objectInfo->previewOutput_->Stop();
616                     context->status = context->errorCode == 0;
617                 }
618             },
619             CommonCompleteCallback, static_cast<void*>(asyncContext.get()), &asyncContext->work);
620         if (status != napi_ok) {
621             MEDIA_ERR_LOG("Failed to create napi_create_async_work for PreviewOutputNapi::Release");
622             napi_get_undefined(env, &result);
623         } else {
624             napi_queue_async_work(env, asyncContext->work);
625             asyncContext.release();
626         }
627     } else {
628         MEDIA_ERR_LOG("Stop call Failed!");
629     }
630     return result;
631 }
632 
On(napi_env env,napi_callback_info info)633 napi_value PreviewOutputNapi::On(napi_env env, napi_callback_info info)
634 {
635     MEDIA_INFO_LOG("On is called");
636     napi_value undefinedResult = nullptr;
637     size_t argCount = ARGS_TWO;
638     napi_value argv[ARGS_TWO] = {nullptr};
639     napi_value thisVar = nullptr;
640     size_t res = 0;
641     char buffer[SIZE];
642     std::string eventType;
643     const int32_t refCount = 1;
644     PreviewOutputNapi* obj = nullptr;
645     napi_status status;
646 
647     napi_get_undefined(env, &undefinedResult);
648 
649     CAMERA_NAPI_GET_JS_ARGS(env, info, argCount, argv, thisVar);
650     NAPI_ASSERT(env, argCount == ARGS_TWO, "requires 2 parameters");
651 
652     if (thisVar == nullptr || argv[PARAM0] == nullptr || argv[PARAM1] == nullptr) {
653         MEDIA_ERR_LOG("Failed to retrieve details about the callback");
654         return undefinedResult;
655     }
656 
657     status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&obj));
658     if (status == napi_ok && obj != nullptr) {
659         napi_valuetype valueType = napi_undefined;
660         if (napi_typeof(env, argv[PARAM0], &valueType) != napi_ok || valueType != napi_string
661             || napi_typeof(env, argv[PARAM1], &valueType) != napi_ok || valueType != napi_function) {
662             return undefinedResult;
663         }
664 
665         napi_get_value_string_utf8(env, argv[PARAM0], buffer, SIZE, &res);
666         eventType = std::string(buffer);
667 
668         napi_ref callbackRef;
669         napi_create_reference(env, argv[PARAM1], refCount, &callbackRef);
670 
671         if (!eventType.empty()) {
672             obj->previewCallback_->SetCallbackRef(eventType, callbackRef);
673         } else {
674             MEDIA_ERR_LOG("Failed to Register Callback: event type is empty!");
675         }
676     } else {
677         MEDIA_ERR_LOG("On call Failed!");
678     }
679     return undefinedResult;
680 }
681 } // namespace CameraStandard
682 } // namespace OHOS
683