1 /*
2  * Copyright (C) 2024 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_napi.h"
17 
18 #include "camera_log.h"
19 #include "camera_napi_utils.h"
20 #include "camera_util.h"
21 #include "napi/native_common.h"
22 
23 namespace OHOS {
24 namespace CameraStandard {
25 thread_local napi_ref DepthDataNapi::sConstructor_ = nullptr;
26 thread_local napi_value DepthDataNapi::sFormat_ = nullptr;
27 thread_local napi_value DepthDataNapi::sDepthMap_ = nullptr;
28 thread_local napi_value DepthDataNapi::sQualityLevel_ = nullptr;
29 thread_local napi_value DepthDataNapi::sAccuracy_ = nullptr;
30 thread_local uint32_t DepthDataNapi::depthDataTaskId = DEPTH_DATA_TASKID;
31 
DepthDataNapi()32 DepthDataNapi::DepthDataNapi() : env_(nullptr), format_(nullptr), depthMap_(nullptr),
33     qualityLevel_(nullptr), accuracy_(nullptr)
34 {}
35 
~DepthDataNapi()36 DepthDataNapi::~DepthDataNapi()
37 {
38     MEDIA_DEBUG_LOG("~PhotoNapi is called");
39 }
40 
41 // Constructor callback
DepthDataNapiConstructor(napi_env env,napi_callback_info info)42 napi_value DepthDataNapi::DepthDataNapiConstructor(napi_env env, napi_callback_info info)
43 {
44     MEDIA_DEBUG_LOG("DepthDataNapiConstructor is called");
45     napi_status status;
46     napi_value result = nullptr;
47     napi_value thisVar = nullptr;
48 
49     napi_get_undefined(env, &result);
50     CAMERA_NAPI_GET_JS_OBJ_WITH_ZERO_ARGS(env, info, status, thisVar);
51 
52     if (status == napi_ok && thisVar != nullptr) {
53         std::unique_ptr<DepthDataNapi> obj = std::make_unique<DepthDataNapi>();
54         obj->env_ = env;
55         obj->format_ = sFormat_;
56         obj->depthMap_ = sDepthMap_;
57         obj->qualityLevel_ = sQualityLevel_;
58         obj->accuracy_ = sAccuracy_;
59         status = napi_wrap(env, thisVar, reinterpret_cast<void*>(obj.get()),
60                            DepthDataNapi::DepthDataNapiDestructor, nullptr, nullptr);
61         if (status == napi_ok) {
62             obj.release();
63             return thisVar;
64         } else {
65             MEDIA_ERR_LOG("Failure wrapping js to native napi");
66         }
67     }
68     MEDIA_ERR_LOG("DepthDataNapiConstructor call Failed!");
69     return result;
70 }
71 
DepthDataNapiDestructor(napi_env env,void * nativeObject,void * finalize)72 void DepthDataNapi::DepthDataNapiDestructor(napi_env env, void *nativeObject, void *finalize)
73 {
74     MEDIA_DEBUG_LOG("DepthDataNapiDestructor is called");
75     DepthDataNapi* depthData = reinterpret_cast<DepthDataNapi*>(nativeObject);
76     if (depthData != nullptr) {
77         delete depthData;
78     }
79 }
80 
Init(napi_env env,napi_value exports)81 napi_value DepthDataNapi::Init(napi_env env, napi_value exports)
82 {
83     MEDIA_DEBUG_LOG("Init is called");
84     napi_status status;
85     napi_value ctorObj;
86     int32_t refCount = PARAM1;
87 
88     napi_property_descriptor depth_data_properties[] = {
89         DECLARE_NAPI_GETTER("format", GetFormat),
90         DECLARE_NAPI_GETTER("depthMap", GetDepthMap),
91         DECLARE_NAPI_GETTER("qualityLevel", GetQualityLevel),
92         DECLARE_NAPI_GETTER("dataAccurary", GetAccuracy),
93         DECLARE_NAPI_FUNCTION("release", Release),
94     };
95 
96     status = napi_define_class(env, DEPTH_DATA_NAPI_CLASS_NAME, NAPI_AUTO_LENGTH,
97                                DepthDataNapiConstructor, nullptr,
98                                sizeof(depth_data_properties) / sizeof(depth_data_properties[PARAM0]),
99                                depth_data_properties, &ctorObj);
100     if (status == napi_ok) {
101         if (napi_create_reference(env, ctorObj, refCount, &sConstructor_) == napi_ok) {
102             status = napi_set_named_property(env, exports, DEPTH_DATA_NAPI_CLASS_NAME, ctorObj);
103             if (status == napi_ok) {
104                 return exports;
105             }
106         }
107     }
108     MEDIA_ERR_LOG("Init call failed!");
109     return nullptr;
110 }
111 
CreateDepthData(napi_env env,napi_value format,napi_value depthMap,napi_value qualityLevel,napi_value accuracy)112 napi_value DepthDataNapi::CreateDepthData(napi_env env, napi_value format, napi_value depthMap,
113     napi_value qualityLevel, napi_value accuracy)
114 {
115     MEDIA_DEBUG_LOG("CreateDepthData is called");
116     CAMERA_SYNC_TRACE;
117     napi_status status;
118     napi_value result = nullptr;
119     napi_value constructor;
120     napi_get_undefined(env, &result);
121 
122     status = napi_get_reference_value(env, sConstructor_, &constructor);
123     if (status == napi_ok) {
124         sFormat_ = format;
125         sDepthMap_ = depthMap;
126         sQualityLevel_ = qualityLevel;
127         sAccuracy_ = accuracy;
128         status = napi_new_instance(env, constructor, 0, nullptr, &result);
129         sFormat_ = nullptr;
130         sDepthMap_ = nullptr;
131         sQualityLevel_ = nullptr;
132         sAccuracy_ = nullptr;
133         if (status == napi_ok && result != nullptr) {
134             return result;
135         } else {
136             MEDIA_ERR_LOG("Failed to create depthData obj instance");
137         }
138     }
139     napi_get_undefined(env, &result);
140     MEDIA_ERR_LOG("CreateDepthData call Failed");
141     return result;
142 }
143 
GetFormat(napi_env env,napi_callback_info info)144 napi_value DepthDataNapi::GetFormat(napi_env env, napi_callback_info info)
145 {
146     MEDIA_DEBUG_LOG("GetFormat is called");
147     napi_status status;
148     napi_value result = nullptr;
149     size_t argc = ARGS_ZERO;
150     napi_value argv[ARGS_ZERO];
151     napi_value thisVar = nullptr;
152 
153     CAMERA_NAPI_GET_JS_ARGS(env, info, argc, argv, thisVar);
154 
155     napi_get_undefined(env, &result);
156     DepthDataNapi* depthDataNapi = nullptr;
157     status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&depthDataNapi));
158     if (status == napi_ok && depthDataNapi != nullptr) {
159         result = depthDataNapi->format_;
160         return result;
161     }
162     napi_get_undefined(env, &result);
163     MEDIA_ERR_LOG("DepthDataNapi::GetFormat call Failed");
164     return result;
165 }
166 
GetDepthMap(napi_env env,napi_callback_info info)167 napi_value DepthDataNapi::GetDepthMap(napi_env env, napi_callback_info info)
168 {
169     MEDIA_DEBUG_LOG("GetDepthMap is called");
170     napi_status status;
171     napi_value result = nullptr;
172     size_t argc = ARGS_ZERO;
173     napi_value argv[ARGS_ZERO];
174     napi_value thisVar = nullptr;
175 
176     CAMERA_NAPI_GET_JS_ARGS(env, info, argc, argv, thisVar);
177 
178     napi_get_undefined(env, &result);
179     DepthDataNapi* depthDataNapi = nullptr;
180     status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&depthDataNapi));
181     if (status == napi_ok && depthDataNapi != nullptr) {
182         result = depthDataNapi->depthMap_;
183         return result;
184     }
185     napi_get_undefined(env, &result);
186     MEDIA_ERR_LOG("DepthDataNapi::GetDepthMap call Failed");
187     return result;
188 }
189 
GetQualityLevel(napi_env env,napi_callback_info info)190 napi_value DepthDataNapi::GetQualityLevel(napi_env env, napi_callback_info info)
191 {
192     MEDIA_INFO_LOG("GetQualityLevel is called");
193     napi_status status;
194     napi_value result = nullptr;
195     size_t argc = ARGS_ZERO;
196     napi_value argv[ARGS_ZERO];
197     napi_value thisVar = nullptr;
198 
199     CAMERA_NAPI_GET_JS_ARGS(env, info, argc, argv, thisVar);
200 
201     napi_get_undefined(env, &result);
202     DepthDataNapi* depthDataNapi = nullptr;
203     status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&depthDataNapi));
204     if (status == napi_ok && depthDataNapi != nullptr) {
205         result = depthDataNapi->qualityLevel_;
206         return result;
207     }
208     napi_get_undefined(env, &result);
209     MEDIA_ERR_LOG("DepthDataNapi::GetQualityLevel call Failed");
210     return result;
211 }
212 
GetAccuracy(napi_env env,napi_callback_info info)213 napi_value DepthDataNapi::GetAccuracy(napi_env env, napi_callback_info info)
214 {
215     MEDIA_INFO_LOG("GetAccuracy is called");
216     napi_status status;
217     napi_value result = nullptr;
218     size_t argc = ARGS_ZERO;
219     napi_value argv[ARGS_ZERO];
220     napi_value thisVar = nullptr;
221 
222     CAMERA_NAPI_GET_JS_ARGS(env, info, argc, argv, thisVar);
223 
224     napi_get_undefined(env, &result);
225     DepthDataNapi* depthDataNapi = nullptr;
226     status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&depthDataNapi));
227     if (status == napi_ok && depthDataNapi != nullptr) {
228         result = depthDataNapi->accuracy_;
229         return result;
230     }
231     napi_get_undefined(env, &result);
232     MEDIA_ERR_LOG("DepthDataNapi::GetAccuracy call Failed");
233     return result;
234 }
235 
Release(napi_env env,napi_callback_info info)236 napi_value DepthDataNapi::Release(napi_env env, napi_callback_info info)
237 {
238     MEDIA_INFO_LOG("Release is called");
239     napi_status status;
240     napi_value result = nullptr;
241     napi_value resource = nullptr;
242     size_t argc = ARGS_ZERO;
243     napi_value argv[ARGS_ZERO];
244     napi_value thisVar = nullptr;
245 
246     CAMERA_NAPI_GET_JS_ARGS(env, info, argc, argv, thisVar);
247 
248     napi_get_undefined(env, &result);
249     std::unique_ptr<DepthDataAsyncContext> asyncContext = std::make_unique<DepthDataAsyncContext>();
250     status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&asyncContext->objectInfo));
251     if (status == napi_ok && asyncContext->objectInfo != nullptr) {
252         CAMERA_NAPI_CREATE_PROMISE(env, asyncContext->callbackRef, asyncContext->deferred, result);
253         CAMERA_NAPI_CREATE_RESOURCE_NAME(env, resource, "Release");
254 
255         status = napi_create_async_work(
256             env, nullptr, resource,
257             [](napi_env env, void* data) {
258                 auto context = static_cast<DepthDataAsyncContext*>(data);
259                 context->status = false;
260                 // Start async trace
261                 context->funcName = "DepthDataNapi::Release";
262                 context->taskId = CameraNapiUtils::IncrementAndGet(depthDataTaskId);
263                 CAMERA_START_ASYNC_TRACE(context->funcName, context->taskId);
264                 if (context->objectInfo != nullptr) {
265                     context->status = true;
266                     context->objectInfo->format_ = nullptr;
267                     context->objectInfo->depthMap_ = nullptr;
268                     context->objectInfo->qualityLevel_ = nullptr;
269                     context->objectInfo->accuracy_ = nullptr;
270                 }
271             },
272             [](napi_env env, napi_status status, void* data) {
273                 auto context = static_cast<DepthDataAsyncContext*>(data);
274                 napi_resolve_deferred(env, context->deferred, nullptr);
275                 napi_delete_async_work(env, context->work);
276                 delete context->objectInfo;
277                 delete context;
278             }, static_cast<void*>(asyncContext.get()), &asyncContext->work);
279         if (status != napi_ok) {
280             MEDIA_ERR_LOG("Failed to create napi_create_async_work for DepthDataNapi::Release");
281             napi_get_undefined(env, &result);
282         } else {
283             napi_queue_async_work_with_qos(env, asyncContext->work, napi_qos_user_initiated);
284             asyncContext.release();
285         }
286     } else {
287         MEDIA_ERR_LOG("Release call Failed!");
288     }
289     return result;
290 }
291 
292 }  // namespace CameraStandard
293 }  // namespace OHOS
294