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