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