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