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/camera_output_napi.h"
17 #include <uv.h>
18
19 namespace OHOS {
20 namespace CameraStandard {
21 using namespace std;
22
23 thread_local napi_ref CameraOutputCapabilityNapi::sCapabilityConstructor_ = nullptr;
24 thread_local sptr<CameraOutputCapability> CameraOutputCapabilityNapi::sCameraOutputCapability_ = nullptr;
25
CameraOutputCapabilityNapi()26 CameraOutputCapabilityNapi::CameraOutputCapabilityNapi() : env_(nullptr), wrapper_(nullptr)
27 {
28 cameraOutputCapability_ = nullptr;
29 }
30
~CameraOutputCapabilityNapi()31 CameraOutputCapabilityNapi::~CameraOutputCapabilityNapi()
32 {
33 MEDIA_DEBUG_LOG("~CameraOutputCapabilityNapi is called");
34 if (wrapper_ != nullptr) {
35 napi_delete_reference(env_, wrapper_);
36 }
37 if (cameraOutputCapability_) {
38 cameraOutputCapability_ = nullptr;
39 }
40 }
41
CameraOutputCapabilityNapiDestructor(napi_env env,void * nativeObject,void * finalize_hint)42 void CameraOutputCapabilityNapi::CameraOutputCapabilityNapiDestructor(
43 napi_env env, void* nativeObject, void* finalize_hint)
44 {
45 MEDIA_DEBUG_LOG("CameraOutputCapabilityNapiDestructor is called");
46 CameraOutputCapabilityNapi* cameraOutputCapabilityNapi =
47 reinterpret_cast<CameraOutputCapabilityNapi*>(nativeObject);
48 if (cameraOutputCapabilityNapi != nullptr) {
49 delete cameraOutputCapabilityNapi;
50 }
51 }
52
Init(napi_env env,napi_value exports)53 napi_value CameraOutputCapabilityNapi::Init(napi_env env, napi_value exports)
54 {
55 MEDIA_DEBUG_LOG("Init is called");
56 napi_status status;
57 napi_value ctorObj;
58
59 napi_property_descriptor camera_output_capability_props[] = {
60 DECLARE_NAPI_GETTER("previewProfiles", GetPreviewProfiles),
61 DECLARE_NAPI_GETTER("photoProfiles", GetPhotoProfiles),
62 DECLARE_NAPI_GETTER("videoProfiles", GetVideoProfiles),
63 DECLARE_NAPI_GETTER("supportedMetadataObjectTypes", GetSupportedMetadataObjectTypes)
64 };
65
66 status = napi_define_class(env, CAMERA_OUTPUT_CAPABILITY_NAPI_CLASS_NAME, NAPI_AUTO_LENGTH,
67 CameraOutputCapabilityNapiConstructor, nullptr,
68 sizeof(camera_output_capability_props) / sizeof(camera_output_capability_props[PARAM0]),
69 camera_output_capability_props, &ctorObj);
70 if (status == napi_ok) {
71 int32_t refCount = 1;
72 status = napi_create_reference(env, ctorObj, refCount, &sCapabilityConstructor_);
73 if (status == napi_ok) {
74 status = napi_set_named_property(env, exports, CAMERA_OUTPUT_CAPABILITY_NAPI_CLASS_NAME, ctorObj);
75 if (status == napi_ok) {
76 return exports;
77 }
78 }
79 }
80
81 MEDIA_ERR_LOG("Init call Failed!");
82 return nullptr;
83 }
84
WrapSizeJs(napi_env env,Size & size,napi_value & result)85 void WrapSizeJs(napi_env env, Size &size, napi_value &result)
86 {
87 MEDIA_DEBUG_LOG("WrapSizeJs is called");
88 napi_value value = nullptr;
89 napi_create_int32(env, size.width, &value);
90 napi_set_named_property(env, result, "width", value);
91 napi_create_int32(env, size.height, &value);
92 napi_set_named_property(env, result, "height", value);
93 }
94
WrapProfileJs(napi_env env,Profile & profile,napi_value & result)95 void WrapProfileJs(napi_env env, Profile &profile, napi_value &result)
96 {
97 MEDIA_DEBUG_LOG("WrapProfileJs is called");
98 napi_value sizeNapi = nullptr;
99 napi_create_object(env, &result);
100 napi_create_object(env, &sizeNapi);
101 WrapSizeJs(env, profile.size_, sizeNapi);
102 napi_value value = nullptr;
103 napi_create_int32(env, profile.format_, &value);
104 napi_set_named_property(env, result, "format", value);
105 napi_set_named_property(env, result, "size", sizeNapi);
106 }
107
CreateProfileJsArray(napi_env env,napi_status status,std::vector<Profile> profileList)108 static napi_value CreateProfileJsArray(napi_env env, napi_status status, std::vector<Profile> profileList)
109 {
110 MEDIA_DEBUG_LOG("CreateProfileJsArray is called");
111 napi_value profileArray = nullptr;
112
113 napi_get_undefined(env, &profileArray);
114 if (profileList.empty()) {
115 MEDIA_ERR_LOG("profileList is empty");
116 return profileArray;
117 }
118
119 status = napi_create_array(env, &profileArray);
120 if (status == napi_ok) {
121 for (uint32_t i = 0; i < profileList.size(); i++) {
122 napi_value profile = nullptr;
123 WrapProfileJs(env, profileList[i], profile);
124 if (profile == nullptr || napi_set_element(env, profileArray, i, profile) != napi_ok) {
125 MEDIA_ERR_LOG("Failed to create profile napi wrapper object");
126 napi_get_undefined(env, &profileArray);
127 return profileArray;
128 }
129 }
130 } else {
131 MEDIA_ERR_LOG("CreateProfileJsArray call Failed!");
132 }
133 return profileArray;
134 }
135
WrapJsVideoProfile(napi_env env,VideoProfile & profile,napi_value & result)136 void WrapJsVideoProfile(napi_env env, VideoProfile &profile, napi_value &result)
137 {
138 MEDIA_DEBUG_LOG("WrapJsVideoProfile is called");
139 napi_value sizeNapi = nullptr;
140 napi_create_object(env, &result);
141 napi_create_object(env, &sizeNapi);
142 WrapSizeJs(env, profile.size_, sizeNapi);
143 napi_set_named_property(env, result, "size", sizeNapi);
144
145 napi_value value = nullptr;
146 napi_create_int32(env, profile.format_, &value);
147 napi_set_named_property(env, result, "format", value);
148
149 napi_value frameRateRange;
150 napi_create_object(env, &frameRateRange);
151 std::vector<int32_t> ranges = profile.framerates_;
152 napi_create_int32(env, ranges[0], &value);
153 napi_set_named_property(env, frameRateRange, "min", value);
154 napi_create_int32(env, ranges[1], &value);
155 napi_set_named_property(env, frameRateRange, "max", value);
156 napi_set_named_property(env, result, "frameRateRange", frameRateRange);
157 }
158
CreateVideoProfileJsArray(napi_env env,napi_status status,std::vector<VideoProfile> profileList)159 static napi_value CreateVideoProfileJsArray(napi_env env, napi_status status, std::vector<VideoProfile> profileList)
160 {
161 MEDIA_DEBUG_LOG("CreateVideoProfileJsArray is called");
162 napi_value profileArray = nullptr;
163 napi_value profile = nullptr;
164
165 napi_get_undefined(env, &profileArray);
166 if (profileList.empty()) {
167 MEDIA_ERR_LOG("profileList is empty");
168 return profileArray;
169 }
170
171 status = napi_create_array(env, &profileArray);
172 if (status == napi_ok) {
173 for (size_t i = 0; i < profileList.size(); i++) {
174 WrapJsVideoProfile(env, profileList[i], profile);
175 if (profile == nullptr || napi_set_element(env, profileArray, i, profile) != napi_ok) {
176 MEDIA_ERR_LOG("Failed to create profile napi wrapper object");
177 napi_get_undefined(env, &profileArray);
178 return profileArray;
179 }
180 }
181 }
182 MEDIA_INFO_LOG("VideoProfileList is %{public}zu", profileList.size());
183 return profileArray;
184 }
185
CreateMetadataObjectTypeJsArray(napi_env env,napi_status status,std::vector<MetadataObjectType> metadataTypeList)186 static napi_value CreateMetadataObjectTypeJsArray(napi_env env, napi_status status,
187 std::vector<MetadataObjectType> metadataTypeList)
188 {
189 MEDIA_DEBUG_LOG("CreateMetadataObjectTypeJsArray is called");
190 napi_value metadataTypeArray = nullptr;
191 napi_value metadataType = nullptr;
192
193 napi_get_undefined(env, &metadataTypeArray);
194 if (metadataTypeList.empty()) {
195 MEDIA_ERR_LOG("metadataTypeList is empty");
196 return metadataTypeArray;
197 }
198
199 status = napi_create_array(env, &metadataTypeArray);
200 if (status == napi_ok) {
201 for (size_t i = 0; i < metadataTypeList.size(); i++) {
202 napi_create_int32(env, static_cast<int32_t>(metadataTypeList[i]), &metadataType);
203 MEDIA_INFO_LOG("WrapJsVideoProfile success");
204 if (metadataType == nullptr || napi_set_element(env, metadataTypeArray, i, metadataType) != napi_ok) {
205 MEDIA_ERR_LOG("Failed to create metadataType napi wrapper object");
206 napi_get_undefined(env, &metadataTypeArray);
207 return metadataTypeArray;
208 }
209 }
210 }
211 return metadataTypeArray;
212 }
213
214 // Constructor callback
CameraOutputCapabilityNapiConstructor(napi_env env,napi_callback_info info)215 napi_value CameraOutputCapabilityNapi::CameraOutputCapabilityNapiConstructor(napi_env env, napi_callback_info info)
216 {
217 MEDIA_DEBUG_LOG("CameraOutputCapabilityNapiConstructor is called");
218 napi_status status;
219 napi_value result = nullptr;
220 napi_value thisVar = nullptr;
221
222 napi_get_undefined(env, &result);
223 CAMERA_NAPI_GET_JS_OBJ_WITH_ZERO_ARGS(env, info, status, thisVar);
224
225 if (status == napi_ok && thisVar != nullptr) {
226 std::unique_ptr<CameraOutputCapabilityNapi> obj = std::make_unique<CameraOutputCapabilityNapi>();
227 obj->env_ = env;
228 obj->cameraOutputCapability_ = sCameraOutputCapability_;
229 status = napi_wrap(env, thisVar, reinterpret_cast<void*>(obj.get()),
230 CameraOutputCapabilityNapi::CameraOutputCapabilityNapiDestructor,
231 nullptr,
232 nullptr);
233 if (status == napi_ok) {
234 obj.release();
235 MEDIA_DEBUG_LOG("CameraOutputCapabilityNapiConstructor Success wrapping js to native napi");
236 return thisVar;
237 } else {
238 MEDIA_ERR_LOG("Failure wrapping js to native napi");
239 }
240 }
241 MEDIA_ERR_LOG("CameraOutputCapabilityNapiConstructor call Failed");
242 return result;
243 }
244
CreateCameraOutputCapability(napi_env env,sptr<CameraDevice> camera)245 napi_value CameraOutputCapabilityNapi::CreateCameraOutputCapability(napi_env env, sptr<CameraDevice> camera)
246 {
247 MEDIA_INFO_LOG("CreateCameraOutputCapability is called");
248 CAMERA_SYNC_TRACE;
249 napi_status status;
250 napi_value result = nullptr;
251 napi_value constructor;
252 if (camera == nullptr) {
253 MEDIA_ERR_LOG("camera is Null");
254 return result;
255 }
256
257 status = napi_get_reference_value(env, sCapabilityConstructor_, &constructor);
258 if (status == napi_ok) {
259 sCameraOutputCapability_ = CameraManager::GetInstance()->GetSupportedOutputCapability(camera);
260 if (sCameraOutputCapability_ == nullptr) {
261 MEDIA_ERR_LOG("failed to create CreateCameraOutputCapability");
262 return result;
263 }
264 status = napi_new_instance(env, constructor, 0, nullptr, &result);
265 sCameraOutputCapability_ = nullptr;
266 if (status == napi_ok && result != nullptr) {
267 MEDIA_INFO_LOG("success to create CreateCameraOutputCapabilityNapi");
268 return result;
269 } else {
270 MEDIA_ERR_LOG("Failed to create photo output instance");
271 }
272 }
273
274 MEDIA_ERR_LOG("CreateCameraOutputCapability call Failed");
275 napi_get_undefined(env, &result);
276 return result;
277 }
278
CreateCameraOutputCapability(napi_env env,sptr<CameraDevice> camera,CameraMode modename)279 napi_value CameraOutputCapabilityNapi::CreateCameraOutputCapability(napi_env env,
280 sptr<CameraDevice> camera, CameraMode modename)
281 {
282 MEDIA_INFO_LOG("CreateCameraOutputCapability is called");
283 CAMERA_SYNC_TRACE;
284 napi_status status;
285 napi_value result = nullptr;
286 napi_value constructor;
287 if (camera == nullptr) {
288 MEDIA_ERR_LOG("camera is Null");
289 return result;
290 }
291
292 status = napi_get_reference_value(env, sCapabilityConstructor_, &constructor);
293 if (status == napi_ok) {
294 sCameraOutputCapability_ = ModeManager::GetInstance()->GetSupportedOutputCapability(camera, modename);
295 if (sCameraOutputCapability_ == nullptr) {
296 MEDIA_ERR_LOG("failed to create CreateCameraOutputCapability");
297 return result;
298 }
299 status = napi_new_instance(env, constructor, 0, nullptr, &result);
300 sCameraOutputCapability_ = nullptr;
301 if (status == napi_ok && result != nullptr) {
302 MEDIA_INFO_LOG("success to create CreateCameraOutputCapabilityNapi");
303 return result;
304 } else {
305 MEDIA_ERR_LOG("Failed to create photo output instance");
306 }
307 }
308
309 MEDIA_ERR_LOG("CreateCameraOutputCapability call Failed");
310 napi_get_undefined(env, &result);
311 return result;
312 }
313
GetPreviewProfiles(napi_env env,napi_callback_info info)314 napi_value CameraOutputCapabilityNapi::GetPreviewProfiles(napi_env env, napi_callback_info info)
315 {
316 MEDIA_INFO_LOG("GetPreviewProfiles is called");
317 napi_status status;
318 napi_value jsResult = nullptr;
319 napi_value undefinedResult = nullptr;
320 CameraOutputCapabilityNapi* obj = nullptr;
321 napi_value thisVar = nullptr;
322
323 napi_get_undefined(env, &undefinedResult);
324 CAMERA_NAPI_GET_JS_OBJ_WITH_ZERO_ARGS(env, info, status, thisVar);
325
326 if (status != napi_ok || thisVar == nullptr) {
327 MEDIA_ERR_LOG("Invalid arguments!");
328 return undefinedResult;
329 }
330
331 status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
332 if ((status == napi_ok) && (obj != nullptr)) {
333 std::vector<Profile> profileList = obj->cameraOutputCapability_->GetPreviewProfiles();
334 jsResult = CreateProfileJsArray(env, status, profileList);
335 return jsResult;
336 }
337 MEDIA_ERR_LOG("GetPreviewProfiles call Failed");
338 return undefinedResult;
339 }
340
GetPhotoProfiles(napi_env env,napi_callback_info info)341 napi_value CameraOutputCapabilityNapi::GetPhotoProfiles(napi_env env, napi_callback_info info)
342 {
343 MEDIA_INFO_LOG("GetPhotoProfiles is called");
344 napi_status status;
345 napi_value jsResult = nullptr;
346 napi_value undefinedResult = nullptr;
347 CameraOutputCapabilityNapi* obj = nullptr;
348 napi_value thisVar = nullptr;
349
350 napi_get_undefined(env, &undefinedResult);
351 CAMERA_NAPI_GET_JS_OBJ_WITH_ZERO_ARGS(env, info, status, thisVar);
352
353 if (status != napi_ok || thisVar == nullptr) {
354 MEDIA_ERR_LOG("Invalid arguments!");
355 return undefinedResult;
356 }
357
358 status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
359 if ((status == napi_ok) && (obj != nullptr)) {
360 std::vector<Profile> profileList = obj->cameraOutputCapability_->GetPhotoProfiles();
361 jsResult = CreateProfileJsArray(env, status, profileList);
362 return jsResult;
363 }
364 MEDIA_ERR_LOG("GetPhotoProfiles call Failed");
365 return undefinedResult;
366 }
367
368 // todo : should return VideoProfile
GetVideoProfiles(napi_env env,napi_callback_info info)369 napi_value CameraOutputCapabilityNapi::GetVideoProfiles(napi_env env, napi_callback_info info)
370 {
371 MEDIA_INFO_LOG("GetVideoProfiles is called");
372 napi_status status;
373 napi_value jsResult = nullptr;
374 napi_value undefinedResult = nullptr;
375 CameraOutputCapabilityNapi* obj = nullptr;
376 napi_value thisVar = nullptr;
377
378 napi_get_undefined(env, &undefinedResult);
379 CAMERA_NAPI_GET_JS_OBJ_WITH_ZERO_ARGS(env, info, status, thisVar);
380
381 if (status != napi_ok || thisVar == nullptr) {
382 MEDIA_ERR_LOG("Invalid arguments!");
383 return undefinedResult;
384 }
385
386 status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
387 if ((status == napi_ok) && (obj != nullptr)) {
388 std::vector<VideoProfile> profileList = obj->cameraOutputCapability_->GetVideoProfiles();
389 jsResult = CreateVideoProfileJsArray(env, status, profileList);
390 return jsResult;
391 }
392 MEDIA_ERR_LOG("GetVideoProfiles call Failed");
393 return undefinedResult;
394 }
395
GetSupportedMetadataObjectTypes(napi_env env,napi_callback_info info)396 napi_value CameraOutputCapabilityNapi::GetSupportedMetadataObjectTypes(napi_env env, napi_callback_info info)
397 {
398 MEDIA_DEBUG_LOG("GetSupportedMetadataObjectTypes is called");
399 napi_status status;
400 napi_value jsResult = nullptr;
401 napi_value undefinedResult = nullptr;
402 CameraOutputCapabilityNapi* obj = nullptr;
403 napi_value thisVar = nullptr;
404
405 napi_get_undefined(env, &undefinedResult);
406 CAMERA_NAPI_GET_JS_OBJ_WITH_ZERO_ARGS(env, info, status, thisVar);
407
408 if (status != napi_ok || thisVar == nullptr) {
409 MEDIA_ERR_LOG("Invalid arguments!");
410 return undefinedResult;
411 }
412
413 status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
414 if ((status == napi_ok) && (obj != nullptr)) {
415 std::vector<MetadataObjectType> metadataTypeList;
416 metadataTypeList = obj->cameraOutputCapability_->GetSupportedMetadataObjectType();
417 jsResult = CreateMetadataObjectTypeJsArray(env, status, metadataTypeList);
418 return jsResult;
419 }
420 MEDIA_ERR_LOG("GetSupportedMetadataObjectTypes call Failed");
421 return undefinedResult;
422 }
423 } // namespace CameraStandard
424 } // namespace OHOS
425