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