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