• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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