1 /*
2 * Copyright (c) 2021-2023 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/photo_napi.h"
17
18 #include "camera_log.h"
19 #include "hilog/log.h"
20 #include "image_napi.h"
21 #include "napi/native_common.h"
22
23 namespace OHOS {
24 namespace CameraStandard {
25 thread_local napi_ref PhotoNapi::sConstructor_ = nullptr;
26 thread_local napi_value PhotoNapi::sMainImage_ = nullptr;
27 thread_local napi_value PhotoNapi::sRawImage_ = nullptr;
28 thread_local uint32_t PhotoNapi::photoTaskId = PHOTO_TASKID;
29
PhotoNapi()30 PhotoNapi::PhotoNapi() : env_(nullptr), mainImage_(nullptr), rawImage_(nullptr) {}
31
~PhotoNapi()32 PhotoNapi::~PhotoNapi()
33 {
34 MEDIA_DEBUG_LOG("~PhotoNapi is called");
35 }
36
37 // Constructor callback
PhotoNapiConstructor(napi_env env,napi_callback_info info)38 napi_value PhotoNapi::PhotoNapiConstructor(napi_env env, napi_callback_info info)
39 {
40 MEDIA_DEBUG_LOG("PhotoNapiConstructor is called");
41 napi_status status;
42 napi_value result = nullptr;
43 napi_value thisVar = nullptr;
44
45 napi_get_undefined(env, &result);
46 CAMERA_NAPI_GET_JS_OBJ_WITH_ZERO_ARGS(env, info, status, thisVar);
47
48 if (status == napi_ok && thisVar != nullptr) {
49 std::unique_ptr<PhotoNapi> obj = std::make_unique<PhotoNapi>();
50 obj->env_ = env;
51 obj->mainImage_ = sMainImage_;
52 obj->rawImage_ = sRawImage_;
53 status = napi_wrap(env, thisVar, reinterpret_cast<void*>(obj.get()),
54 PhotoNapi::PhotoNapiDestructor, nullptr, nullptr);
55 if (status == napi_ok) {
56 obj.release();
57 return thisVar;
58 } else {
59 MEDIA_ERR_LOG("Failure wrapping js to native napi");
60 }
61 }
62 MEDIA_ERR_LOG("PhotoNapiConstructor call Failed!");
63 return result;
64 }
65
PhotoNapiDestructor(napi_env env,void * nativeObject,void * finalize_hint)66 void PhotoNapi::PhotoNapiDestructor(napi_env env, void* nativeObject, void* finalize_hint)
67 {
68 MEDIA_DEBUG_LOG("PhotoNapiDestructor is called");
69 PhotoNapi* photo = reinterpret_cast<PhotoNapi*>(nativeObject);
70 if (photo != nullptr) {
71 delete photo;
72 }
73 }
74
Init(napi_env env,napi_value exports)75 napi_value PhotoNapi::Init(napi_env env, napi_value exports)
76 {
77 MEDIA_DEBUG_LOG("Init is called");
78 napi_status status;
79 napi_value ctorObj;
80 int32_t refCount = 1;
81
82 napi_property_descriptor photo_properties[] = {
83 // Photo
84 DECLARE_NAPI_GETTER("main", GetMain),
85 DECLARE_NAPI_GETTER("rawImage", GetRaw),
86 DECLARE_NAPI_FUNCTION("release", Release),
87 };
88
89 status = napi_define_class(env, PHOTO_NAPI_CLASS_NAME, NAPI_AUTO_LENGTH,
90 PhotoNapiConstructor, nullptr,
91 sizeof(photo_properties) / sizeof(photo_properties[PARAM0]),
92 photo_properties, &ctorObj);
93 if (status == napi_ok) {
94 if (napi_create_reference(env, ctorObj, refCount, &sConstructor_) == napi_ok) {
95 status = napi_set_named_property(env, exports, PHOTO_NAPI_CLASS_NAME, ctorObj);
96 CHECK_ERROR_RETURN_RET(status == napi_ok, exports);
97 }
98 }
99 MEDIA_ERR_LOG("Init call Failed!");
100 return nullptr;
101 }
102
CreatePhoto(napi_env env,napi_value mainImage)103 napi_value PhotoNapi::CreatePhoto(napi_env env, napi_value mainImage)
104 {
105 MEDIA_DEBUG_LOG("CreatePhoto is called");
106 CAMERA_SYNC_TRACE;
107 napi_status status;
108 napi_value result = nullptr;
109 napi_value constructor;
110 napi_get_undefined(env, &result);
111
112 status = napi_get_reference_value(env, sConstructor_, &constructor);
113 if (status == napi_ok) {
114 sMainImage_ = mainImage;
115 status = napi_new_instance(env, constructor, 0, nullptr, &result);
116 sMainImage_ = nullptr;
117 if (status == napi_ok && result != nullptr) {
118 return result;
119 } else {
120 MEDIA_ERR_LOG("Failed to create photo obj instance");
121 }
122 }
123 napi_get_undefined(env, &result);
124 MEDIA_ERR_LOG("CreatePhoto call Failed");
125 return result;
126 }
127
GetMain(napi_env env,napi_callback_info info)128 napi_value PhotoNapi::GetMain(napi_env env, napi_callback_info info)
129 {
130 MEDIA_INFO_LOG("GetMain is called");
131 napi_status status;
132 napi_value result = nullptr;
133 size_t argc = ARGS_ZERO;
134 napi_value argv[ARGS_ZERO];
135 napi_value thisVar = nullptr;
136
137 CAMERA_NAPI_GET_JS_ARGS(env, info, argc, argv, thisVar);
138
139 napi_get_undefined(env, &result);
140 PhotoNapi* photoNapi = nullptr;
141 status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&photoNapi));
142 if (status == napi_ok && photoNapi != nullptr) {
143 result = photoNapi->mainImage_;
144 MEDIA_ERR_LOG("PhotoNapi::GetMain Success");
145 return result;
146 }
147 napi_get_undefined(env, &result);
148 MEDIA_ERR_LOG("PhotoNapi::GetMain call Failed");
149 return result;
150 }
151
CreateRawPhoto(napi_env env,napi_value rawImage)152 napi_value PhotoNapi::CreateRawPhoto(napi_env env, napi_value rawImage)
153 {
154 MEDIA_DEBUG_LOG("CreateRawPhoto is called");
155 CAMERA_SYNC_TRACE;
156 napi_status status;
157 napi_value result = nullptr;
158 napi_value constructor;
159 napi_get_undefined(env, &result);
160
161 status = napi_get_reference_value(env, sConstructor_, &constructor);
162 if (status == napi_ok) {
163 sRawImage_ = rawImage;
164 status = napi_new_instance(env, constructor, 0, nullptr, &result);
165 sRawImage_ = nullptr;
166 if (status == napi_ok && result != nullptr) {
167 return result;
168 } else {
169 MEDIA_ERR_LOG("Failed to create photo obj instance");
170 }
171 }
172 napi_get_undefined(env, &result);
173 MEDIA_ERR_LOG("CreateRawPhoto call Failed");
174 return result;
175 }
176
GetRaw(napi_env env,napi_callback_info info)177 napi_value PhotoNapi::GetRaw(napi_env env, napi_callback_info info)
178 {
179 MEDIA_INFO_LOG("GetRaw is called");
180 napi_status status;
181 napi_value result = nullptr;
182 size_t argc = ARGS_ZERO;
183 napi_value argv[ARGS_ZERO];
184 napi_value thisVar = nullptr;
185
186 CAMERA_NAPI_GET_JS_ARGS(env, info, argc, argv, thisVar);
187
188 napi_get_undefined(env, &result);
189 PhotoNapi* photoNapi = nullptr;
190 status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&photoNapi));
191 if (status == napi_ok && photoNapi != nullptr) {
192 result = photoNapi->rawImage_;
193 MEDIA_DEBUG_LOG("PhotoNapi::GetRaw Success");
194 return result;
195 }
196 napi_get_undefined(env, &result);
197 MEDIA_ERR_LOG("PhotoNapi::GetRaw call Failed");
198 return result;
199 }
200
Release(napi_env env,napi_callback_info info)201 napi_value PhotoNapi::Release(napi_env env, napi_callback_info info)
202 {
203 MEDIA_INFO_LOG("Release is called");
204 napi_status status;
205 napi_value result = nullptr;
206 napi_value resource = nullptr;
207 size_t argc = ARGS_ZERO;
208 napi_value argv[ARGS_ZERO];
209 napi_value thisVar = nullptr;
210
211 CAMERA_NAPI_GET_JS_ARGS(env, info, argc, argv, thisVar);
212
213 napi_get_undefined(env, &result);
214 std::unique_ptr<PhotoAsyncContext> asyncContext = std::make_unique<PhotoAsyncContext>();
215 status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&asyncContext->objectInfo));
216 if (status == napi_ok && asyncContext->objectInfo != nullptr) {
217 CAMERA_NAPI_CREATE_PROMISE(env, asyncContext->callbackRef, asyncContext->deferred, result);
218 CAMERA_NAPI_CREATE_RESOURCE_NAME(env, resource, "Release");
219
220 status = napi_create_async_work(
221 env, nullptr, resource,
222 [](napi_env env, void* data) {
223 auto context = static_cast<PhotoAsyncContext*>(data);
224 context->status = false;
225 // Start async trace
226 context->funcName = "PhotoNapi::Release";
227 context->taskId = CameraNapiUtils::IncrementAndGet(photoTaskId);
228 CAMERA_START_ASYNC_TRACE(context->funcName, context->taskId);
229 if (context->objectInfo != nullptr) {
230 context->status = true;
231 context->objectInfo->mainImage_ = nullptr;
232 context->objectInfo->rawImage_ = nullptr;
233 }
234 },
235 [](napi_env env, napi_status status, void* data) {
236 auto context = static_cast<PhotoAsyncContext*>(data);
237 CAMERA_FINISH_ASYNC_TRACE(context->funcName, context->taskId);
238 napi_value result = nullptr;
239 napi_get_undefined(env, &result);
240 napi_resolve_deferred(env, context->deferred, result);
241 napi_delete_async_work(env, context->work);
242 delete context->objectInfo;
243 delete context;
244 }, static_cast<void*>(asyncContext.get()), &asyncContext->work);
245 if (status != napi_ok) {
246 MEDIA_ERR_LOG("Failed to create napi_create_async_work for PhotoNapi::Release");
247 napi_get_undefined(env, &result);
248 } else {
249 napi_queue_async_work_with_qos(env, asyncContext->work, napi_qos_user_initiated);
250 asyncContext.release();
251 }
252 } else {
253 MEDIA_ERR_LOG("Release call Failed!");
254 }
255 return result;
256 }
257 } // namespace CameraStandard
258 } // namespace OHOS