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/depth_data_output_napi.h"
17 
18 #include <cstdint>
19 #include <memory>
20 #include <string>
21 #include <unistd.h>
22 #include <uv.h>
23 
24 #include "camera_error_code.h"
25 #include "camera_napi_const.h"
26 #include "camera_napi_object_types.h"
27 #include "camera_napi_param_parser.h"
28 #include "camera_napi_security_utils.h"
29 #include "camera_napi_template_utils.h"
30 #include "camera_napi_utils.h"
31 #include "camera_output_capability.h"
32 #include "depth_data_output.h"
33 #include "js_native_api.h"
34 #include "js_native_api_types.h"
35 #include "listener_base.h"
36 #include "napi/native_api.h"
37 #include "napi/native_common.h"
38 #include "native_image.h"
39 #include "output/photo_napi.h"
40 #include "pixel_map_napi.h"
41 #include "refbase.h"
42 #include "surface_utils.h"
43 #include "video_key_info.h"
44 
45 namespace OHOS {
46 namespace CameraStandard {
47 using namespace std;
48 thread_local napi_ref DepthDataOutputNapi::sConstructor_ = nullptr;
49 thread_local sptr<DepthDataOutput> DepthDataOutputNapi::sDepthDataOutput_ = nullptr;
50 thread_local sptr<Surface> DepthDataOutputNapi::sDepthDataSurface_ = nullptr;
51 thread_local std::shared_ptr<DepthProfile> DepthDataOutputNapi::depthProfile_ = nullptr;
52 thread_local uint32_t DepthDataOutputNapi::depthDataOutputTaskId = CAMERA_DEPTH_DATA_OUTPUT_TASKID;
53 static std::mutex g_depthDataMutex;
54 
DepthDataListener(napi_env env,const sptr<Surface> depthDataSurface,sptr<DepthDataOutput> depthDataOutput)55 DepthDataListener::DepthDataListener(napi_env env, const sptr<Surface> depthDataSurface,
56                                      sptr<DepthDataOutput> depthDataOutput)
57     : ListenerBase(env), depthDataSurface_(depthDataSurface), depthDataOutput_(depthDataOutput)
58 {
59     if (bufferProcessor_ == nullptr && depthDataSurface != nullptr) {
60         bufferProcessor_ = std::make_shared<DepthDataBufferProcessor>(depthDataSurface);
61     }
62 }
63 
OnBufferAvailable()64 void DepthDataListener::OnBufferAvailable()
65 {
66     std::lock_guard<std::mutex> lock(g_depthDataMutex);
67     CAMERA_SYNC_TRACE;
68     MEDIA_INFO_LOG("DepthDataListener::OnBufferAvailable is called");
69     if (!depthDataSurface_) {
70         MEDIA_ERR_LOG("DepthDataListener napi depthDataSurface_ is null");
71         return;
72     }
73     UpdateJSCallbackAsync(depthDataSurface_);
74 }
75 
ExecuteDepthData(sptr<SurfaceBuffer> surfaceBuffer) const76 void DepthDataListener::ExecuteDepthData(sptr<SurfaceBuffer> surfaceBuffer) const
77 {
78     MEDIA_INFO_LOG("ExecuteDepthData");
79     napi_value result[ARGS_TWO] = {nullptr, nullptr};
80     napi_value retVal;
81 
82     // create pixelMap
83     int32_t depthDataWidth = static_cast<int32_t>(depthProfile_->GetSize().width);
84     int32_t depthDataHeight = static_cast<int32_t>(depthProfile_->GetSize().height);
85     Media::InitializationOptions opts;
86     opts.srcPixelFormat = Media::PixelFormat::RGBA_F16;
87     opts.pixelFormat = Media::PixelFormat::RGBA_F16;
88     opts.size = { .width = depthDataWidth, .height = depthDataHeight };
89     MEDIA_INFO_LOG("ExecuteDepthData depthDataWidth:%{public}d, depthDataHeight: %{public}d",
90         depthDataWidth, depthDataHeight);
91     const int32_t formatSize = 4;
92     auto pixelMap = Media::PixelMap::Create(static_cast<const uint32_t*>(surfaceBuffer->GetVirAddr()),
93         depthDataWidth * depthDataHeight * formatSize, 0, depthDataWidth, opts, true);
94     if (pixelMap == nullptr) {
95         MEDIA_ERR_LOG("create pixelMap failed, pixelMap is null");
96     }
97     napi_value depthMap;
98     napi_get_undefined(env_, &depthMap);
99     depthMap = Media::PixelMapNapi::CreatePixelMap(env_, std::move(pixelMap));
100 
101     napi_value format;
102     napi_get_undefined(env_, &format);
103     int32_t nativeFormat = 0;
104     nativeFormat = static_cast<int32_t>(depthProfile_->GetCameraFormat());
105     napi_create_int32(env_, nativeFormat, &format);
106 
107     napi_value qualityLevel;
108     napi_get_undefined(env_, &qualityLevel);
109     int32_t nativeQualityLevel = 0;
110     surfaceBuffer->GetExtraData()->ExtraGet(OHOS::Camera::depthDataQualityLevel, nativeQualityLevel);
111     napi_create_int32(env_, nativeQualityLevel, &qualityLevel);
112 
113     napi_value accuracy;
114     napi_get_undefined(env_, &accuracy);
115     int32_t nativeAccuracy = 0;
116     nativeAccuracy = static_cast<int32_t>(depthProfile_->GetDataAccuracy());
117     napi_create_int32(env_, nativeAccuracy, &accuracy);
118 
119     result[1] = DepthDataNapi::CreateDepthData(env_, format, depthMap, qualityLevel, accuracy);
120 
121     ExecuteCallbackNapiPara callbackNapiPara { .recv = nullptr, .argc = ARGS_TWO, .argv = result, .result = &retVal };
122     ExecuteCallback(CONST_DEPTH_DATA_AVAILABLE, callbackNapiPara);
123     depthDataSurface_->ReleaseBuffer(surfaceBuffer, -1);
124 }
125 
UpdateJSCallback(sptr<Surface> depthSurface) const126 void DepthDataListener::UpdateJSCallback(sptr<Surface> depthSurface) const
127 {
128     MEDIA_DEBUG_LOG("DepthDataListener UpdateJSCallback enter");
129     sptr<SurfaceBuffer> surfaceBuffer = nullptr;
130     int32_t fence = -1;
131     int64_t timestamp;
132     OHOS::Rect damage;
133 
134     SurfaceError surfaceRet = depthSurface->AcquireBuffer(surfaceBuffer, fence, timestamp, damage);
135     if (surfaceRet != SURFACE_ERROR_OK) {
136         MEDIA_ERR_LOG("DepthDataListener Failed to acquire surface buffer");
137         return;
138     }
139 
140     ExecuteDepthData(surfaceBuffer);
141 }
142 
UpdateJSCallbackAsync(sptr<Surface> depthSurface) const143 void DepthDataListener::UpdateJSCallbackAsync(sptr<Surface> depthSurface) const
144 {
145     MEDIA_DEBUG_LOG("DepthDataListener UpdateJSCallbackAsync enter");
146     uv_loop_s* loop = nullptr;
147     napi_get_uv_event_loop(env_, &loop);
148     if (!loop) {
149         MEDIA_ERR_LOG("DepthDataListener:UpdateJSCallbackAsync() failed to get event loop");
150         return;
151     }
152     uv_work_t* work = new (std::nothrow) uv_work_t;
153     if (!work) {
154         MEDIA_ERR_LOG("DepthDataListener:UpdateJSCallbackAsync() failed to allocate work");
155         return;
156     }
157     std::unique_ptr<DepthDataListenerInfo> callbackInfo = std::make_unique<DepthDataListenerInfo>(depthSurface, this);
158     work->data = callbackInfo.get();
159     MEDIA_DEBUG_LOG("DepthDataListener UpdateJSCallbackAsync uv_queue_work_with_qos start");
160     int ret = uv_queue_work_with_qos(
161         loop, work, [](uv_work_t* work) {},
162         [](uv_work_t* work, int status) {
163             DepthDataListenerInfo* callbackInfo = reinterpret_cast<DepthDataListenerInfo*>(work->data);
164             if (callbackInfo) {
165                 callbackInfo->listener_->UpdateJSCallback(callbackInfo->depthDataSurface_);
166                 MEDIA_INFO_LOG("DepthDataListener:UpdateJSCallbackAsync() complete");
167                 callbackInfo->depthDataSurface_ = nullptr;
168                 callbackInfo->listener_ = nullptr;
169                 delete callbackInfo;
170             }
171             delete work;
172         },
173         uv_qos_user_initiated);
174     if (ret) {
175         MEDIA_ERR_LOG("DepthDataListenerInfo:UpdateJSCallbackAsync() failed to execute work");
176         delete work;
177     } else {
178         callbackInfo.release();
179     }
180 }
181 
SaveCallback(const std::string eventName,napi_value callback)182 void DepthDataListener::SaveCallback(const std::string eventName, napi_value callback)
183 {
184     MEDIA_INFO_LOG("DepthDataListener::SaveCallback is called eventName:%{public}s", eventName.c_str());
185     SaveCallbackReference(eventName, callback, false);
186 }
187 
RemoveCallback(const std::string eventName,napi_value callback)188 void DepthDataListener::RemoveCallback(const std::string eventName, napi_value callback)
189 {
190     MEDIA_INFO_LOG("DepthDataListener::RemoveCallback is called eventName:%{public}s", eventName.c_str());
191     RemoveCallbackRef(eventName, callback);
192 }
193 
SetDepthProfile(std::shared_ptr<DepthProfile> depthProfile)194 void DepthDataListener::SetDepthProfile(std::shared_ptr<DepthProfile> depthProfile)
195 {
196     depthProfile_ = depthProfile;
197 }
198 
DepthDataOutputCallback(napi_env env)199 DepthDataOutputCallback::DepthDataOutputCallback(napi_env env) : ListenerBase(env) {}
200 
OnDepthDataError(const int32_t errorCode) const201 void DepthDataOutputCallback::OnDepthDataError(const int32_t errorCode) const
202 {
203     CAMERA_SYNC_TRACE;
204     MEDIA_DEBUG_LOG("OnDepthDataError is called, errorCode: %{public}d", errorCode);
205     UpdateJSCallbackAsync(DepthDataOutputEventType::DEPTH_DATA_ERROR, errorCode);
206 }
207 
UpdateJSCallbackAsync(DepthDataOutputEventType eventType,const int32_t value) const208 void DepthDataOutputCallback::UpdateJSCallbackAsync(DepthDataOutputEventType eventType, const int32_t value) const
209 {
210     MEDIA_DEBUG_LOG("UpdateJSCallbackAsync is called");
211     uv_loop_s* loop = nullptr;
212     napi_get_uv_event_loop(env_, &loop);
213     if (!loop) {
214         MEDIA_ERR_LOG("failed to get event loop");
215         return;
216     }
217     uv_work_t* work = new(std::nothrow) uv_work_t;
218     if (!work) {
219         MEDIA_ERR_LOG("failed to allocate work");
220         return;
221     }
222     std::unique_ptr<DepthDataOutputCallbackInfo> callbackInfo =
223         std::make_unique<DepthDataOutputCallbackInfo>(eventType, value, shared_from_this());
224     work->data = callbackInfo.get();
225     int ret = uv_queue_work_with_qos(loop, work, [] (uv_work_t* work) {}, [] (uv_work_t* work, int status) {
226         DepthDataOutputCallbackInfo* callbackInfo = reinterpret_cast<DepthDataOutputCallbackInfo *>(work->data);
227         if (callbackInfo) {
228             auto listener = callbackInfo->listener_.lock();
229             if (listener) {
230                 listener->UpdateJSCallback(callbackInfo->eventType_, callbackInfo->value_);
231             }
232             delete callbackInfo;
233         }
234         delete work;
235     }, uv_qos_user_initiated);
236     if (ret) {
237         MEDIA_ERR_LOG("failed to execute work");
238         delete work;
239     } else {
240         callbackInfo.release();
241     }
242 }
243 
UpdateJSCallback(DepthDataOutputEventType eventType,const int32_t value) const244 void DepthDataOutputCallback::UpdateJSCallback(DepthDataOutputEventType eventType, const int32_t value) const
245 {
246     MEDIA_DEBUG_LOG("UpdateJSCallback is called");
247     napi_value result[ARGS_ONE];
248     napi_value retVal;
249     napi_value propValue;
250     napi_get_undefined(env_, &result[PARAM0]);
251     std::string eventName = DepthDataOutputEventTypeHelper.GetKeyString(eventType);
252     if (eventName.empty()) {
253         MEDIA_WARNING_LOG(
254             "DepthDataOutputCallback::UpdateJSCallback, event type is invalid %d", static_cast<int32_t>(eventType));
255         return;
256     }
257 
258     if (eventType == DepthDataOutputEventType::DEPTH_DATA_ERROR) {
259         napi_create_object(env_, &result[PARAM0]);
260         napi_create_int32(env_, value, &propValue);
261         napi_set_named_property(env_, result[PARAM0], "code", propValue);
262     }
263     ExecuteCallbackNapiPara callbackNapiPara { .recv = nullptr, .argc = ARGS_ONE, .argv = result, .result = &retVal };
264     ExecuteCallback(eventName, callbackNapiPara);
265 }
266 
DepthDataOutputNapi()267 DepthDataOutputNapi::DepthDataOutputNapi() : env_(nullptr) {}
268 
~DepthDataOutputNapi()269 DepthDataOutputNapi::~DepthDataOutputNapi()
270 {
271     MEDIA_DEBUG_LOG("~DepthDataOutputNapi is called");
272 }
273 
DepthDataOutputNapiDestructor(napi_env env,void * nativeObject,void * finalize_hint)274 void DepthDataOutputNapi::DepthDataOutputNapiDestructor(napi_env env, void* nativeObject, void* finalize_hint)
275 {
276     MEDIA_DEBUG_LOG("DepthDataOutputNapiDestructor is called");
277     DepthDataOutputNapi* cameraObj = reinterpret_cast<DepthDataOutputNapi*>(nativeObject);
278     if (cameraObj != nullptr) {
279         delete cameraObj;
280     }
281 }
282 
Init(napi_env env,napi_value exports)283 napi_value DepthDataOutputNapi::Init(napi_env env, napi_value exports)
284 {
285     MEDIA_DEBUG_LOG("Init is called");
286     napi_status status;
287     napi_value ctorObj;
288     int32_t refCount = 1;
289 
290     napi_property_descriptor depth_data_output_props[] = {
291         DECLARE_NAPI_FUNCTION("start", Start),
292         DECLARE_NAPI_FUNCTION("stop", Stop),
293         DECLARE_NAPI_FUNCTION("release", Release),
294         DECLARE_NAPI_FUNCTION("on", On),
295         DECLARE_NAPI_FUNCTION("once", Once),
296         DECLARE_NAPI_FUNCTION("off", Off),
297     };
298 
299     status = napi_define_class(env, CAMERA_DEPTH_DATA_OUTPUT_NAPI_CLASS_NAME, NAPI_AUTO_LENGTH,
300                                DepthDataOutputNapiConstructor, nullptr,
301                                sizeof(depth_data_output_props) / sizeof(depth_data_output_props[PARAM0]),
302                                depth_data_output_props, &ctorObj);
303     if (status == napi_ok) {
304         status = napi_create_reference(env, ctorObj, refCount, &sConstructor_);
305         if (status == napi_ok) {
306             status = napi_set_named_property(env, exports, CAMERA_DEPTH_DATA_OUTPUT_NAPI_CLASS_NAME, ctorObj);
307             if (status == napi_ok) {
308                 return exports;
309             }
310         }
311     }
312     MEDIA_ERR_LOG("Init call Failed!");
313     return nullptr;
314 }
315 
316 // Constructor callback
DepthDataOutputNapiConstructor(napi_env env,napi_callback_info info)317 napi_value DepthDataOutputNapi::DepthDataOutputNapiConstructor(napi_env env, napi_callback_info info)
318 {
319     MEDIA_DEBUG_LOG("DepthDataOutputNapiConstructor is called");
320     napi_status status;
321     napi_value result = nullptr;
322     napi_value thisVar = nullptr;
323 
324     napi_get_undefined(env, &result);
325     CAMERA_NAPI_GET_JS_OBJ_WITH_ZERO_ARGS(env, info, status, thisVar);
326 
327     if (status == napi_ok && thisVar != nullptr) {
328         std::unique_ptr<DepthDataOutputNapi> obj = std::make_unique<DepthDataOutputNapi>();
329         if (obj != nullptr) {
330             obj->env_ = env;
331             obj->depthDataOutput_ = sDepthDataOutput_;
332 
333             status = napi_wrap(env, thisVar, reinterpret_cast<void*>(obj.get()),
334                                DepthDataOutputNapi::DepthDataOutputNapiDestructor, nullptr, nullptr);
335             if (status == napi_ok) {
336                 obj.release();
337                 return thisVar;
338             } else {
339                 MEDIA_ERR_LOG("Failure wrapping js to native napi");
340             }
341         }
342     }
343     MEDIA_ERR_LOG("DepthDataOutputNapiConstructor call Failed!");
344     return result;
345 }
346 
CommonCompleteCallback(napi_env env,napi_status status,void * data)347 static void CommonCompleteCallback(napi_env env, napi_status status, void* data)
348 {
349     MEDIA_DEBUG_LOG("CommonCompleteCallback is called");
350     auto context = static_cast<DepthDataOutputAsyncContext*>(data);
351     if (context == nullptr) {
352         MEDIA_ERR_LOG("Async context is null");
353         return;
354     }
355     std::unique_ptr<JSAsyncContextOutput> jsContext = std::make_unique<JSAsyncContextOutput>();
356     if (!context->status) {
357         CameraNapiUtils::CreateNapiErrorObject(env, context->errorCode, context->errorMsg.c_str(), jsContext);
358     } else {
359         jsContext->status = true;
360         napi_get_undefined(env, &jsContext->error);
361         if (context->bRetBool) {
362             napi_get_boolean(env, context->status, &jsContext->data);
363         } else {
364             napi_get_undefined(env, &jsContext->data);
365         }
366     }
367     if (!context->funcName.empty() && context->taskId > 0) {
368         // Finish async trace
369         CAMERA_FINISH_ASYNC_TRACE(context->funcName, context->taskId);
370         jsContext->funcName = context->funcName;
371     }
372     if (context->work != nullptr) {
373         CameraNapiUtils::InvokeJSAsyncMethod(env, context->deferred, context->callbackRef, context->work, *jsContext);
374     }
375     delete context;
376 }
377 
CreateDepthDataOutput(napi_env env,DepthProfile & depthProfile)378 napi_value DepthDataOutputNapi::CreateDepthDataOutput(napi_env env, DepthProfile& depthProfile)
379 {
380     if (!CameraNapiSecurity::CheckSystemApp(env)) {
381         MEDIA_ERR_LOG("SystemApi CreateDepthDataOutput is called!");
382         return nullptr;
383     }
384     MEDIA_DEBUG_LOG("CreateDepthDataOutput is called");
385     CAMERA_SYNC_TRACE;
386     napi_status status;
387     napi_value result = nullptr;
388     napi_value constructor;
389     napi_get_undefined(env, &result);
390     status = napi_get_reference_value(env, sConstructor_, &constructor);
391     if (status == napi_ok) {
392         sptr<Surface> depthDataSurface;
393         MEDIA_INFO_LOG("create surface as consumer");
394         depthDataSurface = Surface::CreateSurfaceAsConsumer("depthDataOutput");
395         sDepthDataSurface_ = depthDataSurface;
396         if (depthDataSurface == nullptr) {
397             MEDIA_ERR_LOG("failed to get surface");
398             return result;
399         }
400 
401         sptr<IBufferProducer> surfaceProducer = depthDataSurface->GetProducer();
402         MEDIA_INFO_LOG("depthProfile width: %{public}d, height: %{public}d, format = %{public}d, "
403                        "surface width: %{public}d, height: %{public}d", depthProfile.GetSize().width,
404                        depthProfile.GetSize().height, static_cast<int32_t>(depthProfile.GetCameraFormat()),
405                        depthDataSurface->GetDefaultWidth(), depthDataSurface->GetDefaultHeight());
406         int retCode = CameraManager::GetInstance()->CreateDepthDataOutput(depthProfile, surfaceProducer,
407             &sDepthDataOutput_);
408         if (!CameraNapiUtils::CheckError(env, retCode) || sDepthDataOutput_ == nullptr) {
409             MEDIA_ERR_LOG("failed to create CreateDepthDataOutput");
410             return result;
411         }
412         status = napi_new_instance(env, constructor, 0, nullptr, &result);
413         sDepthDataOutput_ = nullptr;
414 
415         if (status == napi_ok && result != nullptr) {
416             depthProfile_ = std::make_shared<DepthProfile>(depthProfile);
417             return result;
418         } else {
419             MEDIA_ERR_LOG("Failed to create depth data output instance");
420         }
421     }
422     MEDIA_ERR_LOG("CreateDepthDataOutput call Failed!");
423     return result;
424 }
425 
GetDepthDataOutput()426 sptr<DepthDataOutput> DepthDataOutputNapi::GetDepthDataOutput()
427 {
428     return depthDataOutput_;
429 }
430 
IsDepthDataOutput(napi_env env,napi_value obj)431 bool DepthDataOutputNapi::IsDepthDataOutput(napi_env env, napi_value obj)
432 {
433     MEDIA_DEBUG_LOG("IsDepthDataOutput is called");
434     bool result = false;
435     napi_status status;
436     napi_value constructor = nullptr;
437 
438     status = napi_get_reference_value(env, sConstructor_, &constructor);
439     if (status == napi_ok) {
440         status = napi_instanceof(env, obj, constructor, &result);
441         if (status != napi_ok) {
442             result = false;
443         }
444     }
445     return result;
446 }
447 
Release(napi_env env,napi_callback_info info)448 napi_value DepthDataOutputNapi::Release(napi_env env, napi_callback_info info)
449 {
450     MEDIA_DEBUG_LOG("Release is called");
451     napi_status status;
452     napi_value result = nullptr;
453     const int32_t refCount = 1;
454     napi_value resource = nullptr;
455     size_t argc = ARGS_ONE;
456     napi_value argv[ARGS_ONE] = {0};
457     napi_value thisVar = nullptr;
458 
459     CAMERA_NAPI_GET_JS_ARGS(env, info, argc, argv, thisVar);
460     NAPI_ASSERT(env, argc <= ARGS_ONE, "requires 1 parameter maximum");
461 
462     napi_get_undefined(env, &result);
463     std::unique_ptr<DepthDataOutputAsyncContext> asyncContext = std::make_unique<DepthDataOutputAsyncContext>();
464     status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&asyncContext->objectInfo));
465     if (status == napi_ok && asyncContext->objectInfo != nullptr) {
466         if (argc == ARGS_ONE) {
467             CAMERA_NAPI_GET_JS_ASYNC_CB_REF(env, argv[PARAM0], refCount, asyncContext->callbackRef);
468         }
469 
470         CAMERA_NAPI_CREATE_PROMISE(env, asyncContext->callbackRef, asyncContext->deferred, result);
471         CAMERA_NAPI_CREATE_RESOURCE_NAME(env, resource, "Release");
472 
473         status = napi_create_async_work(
474             env, nullptr, resource, [](napi_env env, void* data) {
475                 auto context = static_cast<DepthDataOutputAsyncContext*>(data);
476                 context->status = false;
477                 // Start async trace
478                 context->funcName = "DepthDataOutputNapi::Release";
479                 context->taskId = CameraNapiUtils::IncrementAndGet(depthDataOutputTaskId);
480                 CAMERA_START_ASYNC_TRACE(context->funcName, context->taskId);
481                 if (context->objectInfo != nullptr) {
482                     context->bRetBool = false;
483                     context->status = true;
484                     ((sptr<DepthDataOutput>&)(context->objectInfo->depthDataOutput_))->Release();
485                 }
486             },
487             CommonCompleteCallback, static_cast<void*>(asyncContext.get()), &asyncContext->work);
488         if (status != napi_ok) {
489             MEDIA_ERR_LOG("Failed to create napi_create_async_work for DepthDataOutputNapi::Release");
490             napi_get_undefined(env, &result);
491         } else {
492             napi_queue_async_work_with_qos(env, asyncContext->work, napi_qos_user_initiated);
493             asyncContext.release();
494         }
495     } else {
496         MEDIA_ERR_LOG("Release call Failed!");
497     }
498     return result;
499 }
500 
Start(napi_env env,napi_callback_info info)501 napi_value DepthDataOutputNapi::Start(napi_env env, napi_callback_info info)
502 {
503     MEDIA_INFO_LOG("Start is called");
504     napi_status status;
505     napi_value result = nullptr;
506     const int32_t refCount = 1;
507     napi_value resource = nullptr;
508     size_t argc = ARGS_ONE;
509     napi_value argv[ARGS_ONE] = {0};
510     napi_value thisVar = nullptr;
511 
512     CAMERA_NAPI_GET_JS_ARGS(env, info, argc, argv, thisVar);
513     NAPI_ASSERT(env, argc <= ARGS_ONE, "requires 1 parameter maximum");
514 
515     napi_get_undefined(env, &result);
516     std::unique_ptr<DepthDataOutputAsyncContext> asyncContext = std::make_unique<DepthDataOutputAsyncContext>();
517     status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&asyncContext->objectInfo));
518     if (status == napi_ok && asyncContext->objectInfo != nullptr) {
519         if (argc == ARGS_ONE) {
520             CAMERA_NAPI_GET_JS_ASYNC_CB_REF(env, argv[PARAM0], refCount, asyncContext->callbackRef);
521         }
522 
523         CAMERA_NAPI_CREATE_PROMISE(env, asyncContext->callbackRef, asyncContext->deferred, result);
524         CAMERA_NAPI_CREATE_RESOURCE_NAME(env, resource, "Start");
525 
526         status = napi_create_async_work(
527             env, nullptr, resource,
528             [](napi_env env, void* data) {
529                 auto context = static_cast<DepthDataOutputAsyncContext*>(data);
530                 context->status = false;
531                 // Start async trace
532                 context->funcName = "DepthDataOutputNapi::Start";
533                 context->taskId = CameraNapiUtils::IncrementAndGet(depthDataOutputTaskId);
534                 CAMERA_START_ASYNC_TRACE(context->funcName, context->taskId);
535                 if (context->objectInfo != nullptr) {
536                     context->bRetBool = false;
537                     context->errorCode = context->objectInfo->depthDataOutput_->Start();
538                     context->status = context->errorCode == 0;
539                 }
540             },
541             CommonCompleteCallback, static_cast<void*>(asyncContext.get()), &asyncContext->work);
542         if (status != napi_ok) {
543             MEDIA_ERR_LOG("Failed to create napi_create_async_work for DepthDataOutputNapi::Release");
544             napi_get_undefined(env, &result);
545         } else {
546             napi_queue_async_work_with_qos(env, asyncContext->work, napi_qos_user_initiated);
547             asyncContext.release();
548         }
549     } else {
550         MEDIA_ERR_LOG("Start call Failed!");
551     }
552     return result;
553 }
554 
Stop(napi_env env,napi_callback_info info)555 napi_value DepthDataOutputNapi::Stop(napi_env env, napi_callback_info info)
556 {
557     MEDIA_INFO_LOG("Stop is called");
558     napi_status status;
559     napi_value result = nullptr;
560     const int32_t refCount = 1;
561     napi_value resource = nullptr;
562     size_t argc = ARGS_ONE;
563     napi_value argv[ARGS_ONE] = {0};
564     napi_value thisVar = nullptr;
565 
566     CAMERA_NAPI_GET_JS_ARGS(env, info, argc, argv, thisVar);
567     NAPI_ASSERT(env, argc <= ARGS_ONE, "requires 1 parameter maximum");
568 
569     napi_get_undefined(env, &result);
570     std::unique_ptr<DepthDataOutputAsyncContext> asyncContext = std::make_unique<DepthDataOutputAsyncContext>();
571     status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&asyncContext->objectInfo));
572     if (status == napi_ok && asyncContext->objectInfo != nullptr) {
573         if (argc == ARGS_ONE) {
574             CAMERA_NAPI_GET_JS_ASYNC_CB_REF(env, argv[PARAM0], refCount, asyncContext->callbackRef);
575         }
576 
577         CAMERA_NAPI_CREATE_PROMISE(env, asyncContext->callbackRef, asyncContext->deferred, result);
578         CAMERA_NAPI_CREATE_RESOURCE_NAME(env, resource, "Stop");
579 
580         status = napi_create_async_work(
581             env, nullptr, resource,
582             [](napi_env env, void* data) {
583                 auto context = static_cast<DepthDataOutputAsyncContext*>(data);
584                 context->status = false;
585                 // Start async trace
586                 context->funcName = "DepthDataOutputNapi::Stop";
587                 context->taskId = CameraNapiUtils::IncrementAndGet(depthDataOutputTaskId);
588                 CAMERA_START_ASYNC_TRACE(context->funcName, context->taskId);
589                 if (context->objectInfo != nullptr) {
590                     context->bRetBool = false;
591                     context->errorCode = context->objectInfo->depthDataOutput_->Stop();
592                     context->status = context->errorCode == 0;
593                 }
594             },
595             CommonCompleteCallback, static_cast<void*>(asyncContext.get()), &asyncContext->work);
596         if (status != napi_ok) {
597             MEDIA_ERR_LOG("Failed to create napi_create_async_work for DepthDataOutputNapi::Release");
598             napi_get_undefined(env, &result);
599         } else {
600             napi_queue_async_work_with_qos(env, asyncContext->work, napi_qos_user_initiated);
601             asyncContext.release();
602         }
603     } else {
604         MEDIA_ERR_LOG("Stop call Failed!");
605     }
606     return result;
607 }
608 
RegisterDepthDataAvailableCallbackListener(const std::string & eventName,napi_env env,napi_value callback,const std::vector<napi_value> & args,bool isOnce)609 void DepthDataOutputNapi::RegisterDepthDataAvailableCallbackListener(
610     const std::string& eventName, napi_env env, napi_value callback, const std::vector<napi_value>& args, bool isOnce)
611 {
612     if (sDepthDataSurface_ == nullptr) {
613         MEDIA_ERR_LOG("sDepthDataSurface_ is null!");
614         return;
615     }
616     if (depthDataListener_ == nullptr) {
617         MEDIA_INFO_LOG("new depthDataListener_ and register surface consumer listener");
618         sptr<DepthDataListener> depthDataListener = new (std::nothrow) DepthDataListener(env, sDepthDataSurface_,
619             depthDataOutput_);
620         SurfaceError ret = sDepthDataSurface_->RegisterConsumerListener((
621             sptr<IBufferConsumerListener>&)depthDataListener);
622         if (ret != SURFACE_ERROR_OK) {
623             MEDIA_ERR_LOG("register surface consumer listener failed!");
624         }
625         depthDataListener_ = depthDataListener;
626     }
627     depthDataListener_->SetDepthProfile(depthProfile_);
628     depthDataListener_->SaveCallback(CONST_DEPTH_DATA_AVAILABLE, callback);
629 }
630 
UnregisterDepthDataAvailableCallbackListener(const std::string & eventName,napi_env env,napi_value callback,const std::vector<napi_value> & args)631 void DepthDataOutputNapi::UnregisterDepthDataAvailableCallbackListener(
632     const std::string& eventName, napi_env env, napi_value callback, const std::vector<napi_value>& args)
633 {
634     if (depthDataListener_ != nullptr) {
635         depthDataListener_->RemoveCallback(CONST_DEPTH_DATA_AVAILABLE, callback);
636     }
637 }
638 
RegisterErrorCallbackListener(const std::string & eventName,napi_env env,napi_value callback,const std::vector<napi_value> & args,bool isOnce)639 void DepthDataOutputNapi::RegisterErrorCallbackListener(
640     const std::string& eventName, napi_env env, napi_value callback, const std::vector<napi_value>& args, bool isOnce)
641 {
642     if (depthDataCallback_ == nullptr) {
643         depthDataCallback_ = std::make_shared<DepthDataOutputCallback>(env);
644         depthDataOutput_->SetCallback(depthDataCallback_);
645     }
646     depthDataCallback_->SaveCallbackReference(CONST_DEPTH_DATA_ERROR, callback, isOnce);
647 }
648 
UnregisterErrorCallbackListener(const std::string & eventName,napi_env env,napi_value callback,const std::vector<napi_value> & args)649 void DepthDataOutputNapi::UnregisterErrorCallbackListener(
650     const std::string& eventName, napi_env env, napi_value callback, const std::vector<napi_value>& args)
651 {
652     if (depthDataCallback_ == nullptr) {
653         MEDIA_ERR_LOG("depthDataCallback is null");
654         return;
655     }
656     depthDataCallback_->RemoveCallbackRef(CONST_DEPTH_DATA_ERROR, callback);
657 }
658 
GetEmitterFunctions()659 const DepthDataOutputNapi::EmitterFunctions& DepthDataOutputNapi::GetEmitterFunctions()
660 {
661     static const EmitterFunctions funMap = {
662         { CONST_DEPTH_DATA_AVAILABLE, {
663             &DepthDataOutputNapi::RegisterDepthDataAvailableCallbackListener,
664             &DepthDataOutputNapi::UnregisterDepthDataAvailableCallbackListener } },
665         { CONST_DEPTH_DATA_ERROR, {
666             &DepthDataOutputNapi::RegisterErrorCallbackListener,
667             &DepthDataOutputNapi::UnregisterErrorCallbackListener } } };
668     return funMap;
669 }
670 
On(napi_env env,napi_callback_info info)671 napi_value DepthDataOutputNapi::On(napi_env env, napi_callback_info info)
672 {
673     return ListenerTemplate<DepthDataOutputNapi>::On(env, info);
674 }
675 
Once(napi_env env,napi_callback_info info)676 napi_value DepthDataOutputNapi::Once(napi_env env, napi_callback_info info)
677 {
678     return ListenerTemplate<DepthDataOutputNapi>::Once(env, info);
679 }
680 
Off(napi_env env,napi_callback_info info)681 napi_value DepthDataOutputNapi::Off(napi_env env, napi_callback_info info)
682 {
683     return ListenerTemplate<DepthDataOutputNapi>::Off(env, info);
684 }
685 } // namespace CameraStandard
686 } // namespace OHOS
687