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 if (status == napi_ok) {
97 return exports;
98 }
99 }
100 }
101 MEDIA_ERR_LOG("Init call Failed!");
102 return nullptr;
103 }
104
CreatePhoto(napi_env env,napi_value mainImage)105 napi_value PhotoNapi::CreatePhoto(napi_env env, napi_value mainImage)
106 {
107 MEDIA_DEBUG_LOG("CreatePhoto is called");
108 CAMERA_SYNC_TRACE;
109 napi_status status;
110 napi_value result = nullptr;
111 napi_value constructor;
112 napi_get_undefined(env, &result);
113
114 status = napi_get_reference_value(env, sConstructor_, &constructor);
115 if (status == napi_ok) {
116 sMainImage_ = mainImage;
117 status = napi_new_instance(env, constructor, 0, nullptr, &result);
118 sMainImage_ = nullptr;
119 if (status == napi_ok && result != nullptr) {
120 return result;
121 } else {
122 MEDIA_ERR_LOG("Failed to create photo obj instance");
123 }
124 }
125 napi_get_undefined(env, &result);
126 MEDIA_ERR_LOG("CreatePhoto call Failed");
127 return result;
128 }
129
GetMain(napi_env env,napi_callback_info info)130 napi_value PhotoNapi::GetMain(napi_env env, napi_callback_info info)
131 {
132 MEDIA_INFO_LOG("GetMain is called");
133 napi_status status;
134 napi_value result = nullptr;
135 size_t argc = ARGS_ZERO;
136 napi_value argv[ARGS_ZERO];
137 napi_value thisVar = nullptr;
138
139 CAMERA_NAPI_GET_JS_ARGS(env, info, argc, argv, thisVar);
140
141 napi_get_undefined(env, &result);
142 PhotoNapi* photoNapi = nullptr;
143 status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&photoNapi));
144 if (status == napi_ok && photoNapi != nullptr) {
145 result = photoNapi->mainImage_;
146 MEDIA_DEBUG_LOG("PhotoNapi::GetMain Success");
147 return result;
148 }
149 napi_get_undefined(env, &result);
150 MEDIA_ERR_LOG("PhotoNapi::GetMain call Failed");
151 return result;
152 }
153
CreateRawPhoto(napi_env env,napi_value rawImage)154 napi_value PhotoNapi::CreateRawPhoto(napi_env env, napi_value rawImage)
155 {
156 MEDIA_DEBUG_LOG("CreateRawPhoto is called");
157 CAMERA_SYNC_TRACE;
158 napi_status status;
159 napi_value result = nullptr;
160 napi_value constructor;
161 napi_get_undefined(env, &result);
162
163 status = napi_get_reference_value(env, sConstructor_, &constructor);
164 if (status == napi_ok) {
165 sRawImage_ = rawImage;
166 status = napi_new_instance(env, constructor, 0, nullptr, &result);
167 sRawImage_ = nullptr;
168 if (status == napi_ok && result != nullptr) {
169 return result;
170 } else {
171 MEDIA_ERR_LOG("Failed to create photo obj instance");
172 }
173 }
174 napi_get_undefined(env, &result);
175 MEDIA_ERR_LOG("CreateRawPhoto call Failed");
176 return result;
177 }
178
GetRaw(napi_env env,napi_callback_info info)179 napi_value PhotoNapi::GetRaw(napi_env env, napi_callback_info info)
180 {
181 MEDIA_INFO_LOG("GetRaw is called");
182 napi_status status;
183 napi_value result = nullptr;
184 size_t argc = ARGS_ZERO;
185 napi_value argv[ARGS_ZERO];
186 napi_value thisVar = nullptr;
187
188 CAMERA_NAPI_GET_JS_ARGS(env, info, argc, argv, thisVar);
189
190 napi_get_undefined(env, &result);
191 PhotoNapi* photoNapi = nullptr;
192 status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&photoNapi));
193 if (status == napi_ok && photoNapi != nullptr) {
194 result = photoNapi->rawImage_;
195 MEDIA_DEBUG_LOG("PhotoNapi::GetRaw Success");
196 return result;
197 }
198 napi_get_undefined(env, &result);
199 MEDIA_ERR_LOG("PhotoNapi::GetRaw call Failed");
200 return result;
201 }
202
Release(napi_env env,napi_callback_info info)203 napi_value PhotoNapi::Release(napi_env env, napi_callback_info info)
204 {
205 MEDIA_INFO_LOG("Release is called");
206 napi_status status;
207 napi_value result = nullptr;
208 napi_value resource = nullptr;
209 size_t argc = ARGS_ZERO;
210 napi_value argv[ARGS_ZERO];
211 napi_value thisVar = nullptr;
212
213 CAMERA_NAPI_GET_JS_ARGS(env, info, argc, argv, thisVar);
214
215 napi_get_undefined(env, &result);
216 std::unique_ptr<PhotoAsyncContext> asyncContext = std::make_unique<PhotoAsyncContext>();
217 status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&asyncContext->objectInfo));
218 if (status == napi_ok && asyncContext->objectInfo != nullptr) {
219 CAMERA_NAPI_CREATE_PROMISE(env, asyncContext->callbackRef, asyncContext->deferred, result);
220 CAMERA_NAPI_CREATE_RESOURCE_NAME(env, resource, "Release");
221
222 status = napi_create_async_work(
223 env, nullptr, resource,
224 [](napi_env env, void* data) {
225 auto context = static_cast<PhotoAsyncContext*>(data);
226 context->status = false;
227 // Start async trace
228 context->funcName = "PhotoNapi::Release";
229 context->taskId = CameraNapiUtils::IncrementAndGet(photoTaskId);
230 CAMERA_START_ASYNC_TRACE(context->funcName, context->taskId);
231 if (context->objectInfo != nullptr) {
232 context->status = true;
233 context->objectInfo->mainImage_ = nullptr;
234 context->objectInfo->rawImage_ = nullptr;
235 }
236 },
237 [](napi_env env, napi_status status, void* data) {
238 auto context = static_cast<PhotoAsyncContext*>(data);
239 napi_resolve_deferred(env, context->deferred, nullptr);
240 napi_delete_async_work(env, context->work);
241 delete context->objectInfo;
242 delete context;
243 }, static_cast<void*>(asyncContext.get()), &asyncContext->work);
244 if (status != napi_ok) {
245 MEDIA_ERR_LOG("Failed to create napi_create_async_work for PhotoNapi::Release");
246 napi_get_undefined(env, &result);
247 } else {
248 napi_queue_async_work_with_qos(env, asyncContext->work, napi_qos_user_initiated);
249 asyncContext.release();
250 }
251 } else {
252 MEDIA_ERR_LOG("Release call Failed!");
253 }
254 return result;
255 }
256 } // namespace CameraStandard
257 } // namespace OHOS