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