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