• 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/photo_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 namespace {
26     constexpr HiLogLabel LABEL = {LOG_CORE, LOG_DOMAIN, "PhotoOutputNapi"};
27 }
28 
29 thread_local napi_ref PhotoOutputNapi::sConstructor_ = nullptr;
30 thread_local sptr<PhotoOutput> PhotoOutputNapi::sPhotoOutput_ = nullptr;
31 thread_local uint32_t PhotoOutputNapi::photoOutputTaskId = CAMERA_PHOTO_OUTPUT_TASKID;
32 
PhotoOutputCallback(napi_env env)33 PhotoOutputCallback::PhotoOutputCallback(napi_env env) : env_(env) {}
34 
UpdateJSCallbackAsync(std::string propName,const CallbackInfo & info) const35 void PhotoOutputCallback::UpdateJSCallbackAsync(std::string propName, const CallbackInfo &info) const
36 {
37     uv_loop_s* loop = nullptr;
38     napi_get_uv_event_loop(env_, &loop);
39     if (!loop) {
40         MEDIA_ERR_LOG("PhotoOutputCallback:UpdateJSCallbackAsync() failed to get event loop");
41         return;
42     }
43     uv_work_t* work = new(std::nothrow) uv_work_t;
44     if (!work) {
45         MEDIA_ERR_LOG("PhotoOutputCallback:UpdateJSCallbackAsync() failed to allocate work");
46         return;
47     }
48     std::unique_ptr<PhotoOutputCallbackInfo> callbackInfo =
49         std::make_unique<PhotoOutputCallbackInfo>(propName, info, this);
50     work->data = callbackInfo.get();
51     int ret = uv_queue_work(loop, work, [] (uv_work_t* work) {}, [] (uv_work_t* work, int status) {
52         PhotoOutputCallbackInfo* callbackInfo = reinterpret_cast<PhotoOutputCallbackInfo *>(work->data);
53         if (callbackInfo) {
54             callbackInfo->listener_->UpdateJSCallback(callbackInfo->eventName_, callbackInfo->info_);
55             delete callbackInfo;
56         }
57         delete work;
58     });
59     if (ret) {
60         MEDIA_ERR_LOG("PhotoOutputCallback:UpdateJSCallbackAsync() failed to execute work");
61         delete work;
62     } else {
63         callbackInfo.release();
64     }
65 }
66 
OnCaptureStarted(const int32_t captureID) const67 void PhotoOutputCallback::OnCaptureStarted(const int32_t captureID) const
68 {
69     CAMERA_SYNC_TRACE;
70     MEDIA_INFO_LOG("PhotoOutputCallback:OnCaptureStarted() is called!, captureID: %{public}d", captureID);
71     CallbackInfo info;
72     info.captureID = captureID;
73     UpdateJSCallbackAsync("OnCaptureStarted", info);
74 }
75 
OnCaptureEnded(const int32_t captureID,const int32_t frameCount) const76 void PhotoOutputCallback::OnCaptureEnded(const int32_t captureID, const int32_t frameCount) const
77 {
78     CAMERA_SYNC_TRACE;
79     MEDIA_INFO_LOG("PhotoOutputCallback:OnCaptureEnded() is called!, captureID: %{public}d, frameCount: %{public}d",
80                    captureID, frameCount);
81     CallbackInfo info;
82     info.captureID = captureID;
83     info.frameCount = frameCount;
84     UpdateJSCallbackAsync("OnCaptureEnded", info);
85 }
86 
OnFrameShutter(const int32_t captureId,const uint64_t timestamp) const87 void PhotoOutputCallback::OnFrameShutter(const int32_t captureId, const uint64_t timestamp) const
88 {
89     CAMERA_SYNC_TRACE;
90     MEDIA_INFO_LOG("PhotoOutputCallback:OnFrameShutter() called, captureID: %{public}d, timestamp: %{public}" PRIu64,
91         captureId, timestamp);
92     CallbackInfo info;
93     info.captureID = captureId;
94     info.timestamp = timestamp;
95     UpdateJSCallbackAsync("OnFrameShutter", info);
96 }
97 
OnCaptureError(const int32_t captureId,const int32_t errorCode) const98 void PhotoOutputCallback::OnCaptureError(const int32_t captureId, const int32_t errorCode) const
99 {
100     MEDIA_INFO_LOG("PhotoOutputCallback:OnCaptureError() is called!, captureID: %{public}d, errorCode: %{public}d",
101         captureId, errorCode);
102     CallbackInfo info;
103     info.captureID = captureId;
104     info.errorCode = errorCode;
105     UpdateJSCallbackAsync("OnCaptureError", info);
106 }
107 
SetCallbackRef(const std::string & eventType,const napi_ref & callbackRef)108 void PhotoOutputCallback::SetCallbackRef(const std::string &eventType, const napi_ref &callbackRef)
109 {
110     if (eventType.compare("captureStart") == 0) {
111         captureStartCallbackRef_ = callbackRef;
112     } else if (eventType.compare("captureEnd") == 0) {
113         captureEndCallbackRef_ = callbackRef;
114     } else if (eventType.compare("frameShutter") == 0) {
115         frameShutterCallbackRef_ = callbackRef;
116     } else if (eventType.compare("error") == 0) {
117         errorCallbackRef_ = callbackRef;
118     } else {
119         MEDIA_ERR_LOG("Incorrect photo callback event type received from JS");
120     }
121 }
122 
UpdateJSCallback(std::string propName,const CallbackInfo & info) const123 void PhotoOutputCallback::UpdateJSCallback(std::string propName, const CallbackInfo &info) const
124 {
125     napi_value result[ARGS_ONE];
126     napi_value callback = nullptr;
127     napi_value retVal;
128     napi_value propValue;
129     int32_t jsErrorCodeUnknown = -1;
130 
131     if (propName.compare("OnCaptureStarted") == 0) {
132         CAMERA_NAPI_CHECK_NULL_PTR_RETURN_VOID(captureStartCallbackRef_,
133             "OnCaptureStart callback is not registered by JS");
134         napi_create_int32(env_, info.captureID, &result[PARAM0]);
135         napi_get_reference_value(env_, captureStartCallbackRef_, &callback);
136     } else if (propName.compare("OnCaptureEnded") == 0) {
137         CAMERA_NAPI_CHECK_NULL_PTR_RETURN_VOID(captureEndCallbackRef_,
138             "OnCaptureEnd callback is not registered by JS");
139         napi_create_object(env_, &result[PARAM0]);
140         napi_create_int32(env_, info.captureID, &propValue);
141         napi_set_named_property(env_, result[PARAM0], "captureId", propValue);
142         napi_create_int32(env_, info.frameCount, &propValue);
143         napi_set_named_property(env_, result[PARAM0], "frameCount", propValue);
144         napi_get_reference_value(env_, captureEndCallbackRef_, &callback);
145     } else if (propName.compare("OnFrameShutter") == 0) {
146         CAMERA_NAPI_CHECK_NULL_PTR_RETURN_VOID(frameShutterCallbackRef_,
147             "OnFrameShutter callback is not registered by JS");
148         napi_create_object(env_, &result[PARAM0]);
149         napi_create_int32(env_, info.captureID, &propValue);
150         napi_set_named_property(env_, result[PARAM0], "captureId", propValue);
151         napi_create_int64(env_, info.timestamp, &propValue);
152         napi_set_named_property(env_, result[PARAM0], "timestamp", propValue);
153         napi_get_reference_value(env_, frameShutterCallbackRef_, &callback);
154     } else {
155         CAMERA_NAPI_CHECK_NULL_PTR_RETURN_VOID(errorCallbackRef_,
156             "OnError callback is not registered by JS");
157         napi_create_object(env_, &result[PARAM0]);
158         napi_create_int32(env_, jsErrorCodeUnknown, &propValue);
159         napi_set_named_property(env_, result[PARAM0], "code", propValue);
160         napi_get_reference_value(env_, errorCallbackRef_, &callback);
161         if (errorCallbackRef_ != nullptr) {
162             napi_delete_reference(env_, errorCallbackRef_);
163         }
164     }
165 
166     napi_call_function(env_, nullptr, callback, ARGS_ONE, result, &retVal);
167 }
168 
PhotoOutputNapi()169 PhotoOutputNapi::PhotoOutputNapi() : env_(nullptr), wrapper_(nullptr)
170 {
171 }
172 
~PhotoOutputNapi()173 PhotoOutputNapi::~PhotoOutputNapi()
174 {
175     if (wrapper_ != nullptr) {
176         napi_delete_reference(env_, wrapper_);
177     }
178     if (photoOutput_) {
179         photoOutput_ = nullptr;
180     }
181     if (photoCallback_) {
182         photoCallback_ = nullptr;
183     }
184 }
185 
PhotoOutputNapiDestructor(napi_env env,void * nativeObject,void * finalize_hint)186 void PhotoOutputNapi::PhotoOutputNapiDestructor(napi_env env, void* nativeObject, void* finalize_hint)
187 {
188     MEDIA_DEBUG_LOG("PhotoOutputNapiDestructor enter");
189     PhotoOutputNapi* photoOutput = reinterpret_cast<PhotoOutputNapi*>(nativeObject);
190     if (photoOutput != nullptr) {
191         photoOutput->~PhotoOutputNapi();
192     }
193 }
194 
Init(napi_env env,napi_value exports)195 napi_value PhotoOutputNapi::Init(napi_env env, napi_value exports)
196 {
197     napi_status status;
198     napi_value ctorObj;
199     int32_t refCount = 1;
200 
201     napi_property_descriptor photo_output_props[] = {
202         DECLARE_NAPI_FUNCTION("getDefaultCaptureSetting", GetDefaultCaptureSetting),
203         DECLARE_NAPI_FUNCTION("capture", Capture),
204         DECLARE_NAPI_FUNCTION("release", Release),
205         DECLARE_NAPI_FUNCTION("isMirrorSupported", IsMirrorSupported),
206         DECLARE_NAPI_FUNCTION("setMirror", SetMirror),
207         DECLARE_NAPI_FUNCTION("on", On)
208     };
209 
210     status = napi_define_class(env, CAMERA_PHOTO_OUTPUT_NAPI_CLASS_NAME, NAPI_AUTO_LENGTH,
211                                PhotoOutputNapiConstructor, nullptr,
212                                sizeof(photo_output_props) / sizeof(photo_output_props[PARAM0]),
213                                photo_output_props, &ctorObj);
214     if (status == napi_ok) {
215         status = napi_create_reference(env, ctorObj, refCount, &sConstructor_);
216         if (status == napi_ok) {
217             status = napi_set_named_property(env, exports, CAMERA_PHOTO_OUTPUT_NAPI_CLASS_NAME, ctorObj);
218             if (status == napi_ok) {
219                 return exports;
220             }
221         }
222     }
223 
224     return nullptr;
225 }
226 
227 // Constructor callback
PhotoOutputNapiConstructor(napi_env env,napi_callback_info info)228 napi_value PhotoOutputNapi::PhotoOutputNapiConstructor(napi_env env, napi_callback_info info)
229 {
230     napi_status status;
231     napi_value result = nullptr;
232     napi_value thisVar = nullptr;
233 
234     napi_get_undefined(env, &result);
235     CAMERA_NAPI_GET_JS_OBJ_WITH_ZERO_ARGS(env, info, status, thisVar);
236 
237     if (status == napi_ok && thisVar != nullptr) {
238         std::unique_ptr<PhotoOutputNapi> obj = std::make_unique<PhotoOutputNapi>();
239         obj->env_ = env;
240         obj->photoOutput_ = sPhotoOutput_;
241         std::shared_ptr<PhotoOutputCallback> callback =
242             std::make_shared<PhotoOutputCallback>(PhotoOutputCallback(env));
243         ((sptr<PhotoOutput> &)(obj->photoOutput_))->SetCallback(callback);
244         obj->photoCallback_ = callback;
245 
246         status = napi_wrap(env, thisVar, reinterpret_cast<void*>(obj.get()),
247                            PhotoOutputNapi::PhotoOutputNapiDestructor, nullptr, nullptr);
248         if (status == napi_ok) {
249             obj.release();
250             return thisVar;
251         } else {
252             MEDIA_ERR_LOG("Failure wrapping js to native napi");
253         }
254     }
255 
256     return result;
257 }
258 
GetPhotoOutput()259 sptr<PhotoOutput> PhotoOutputNapi::GetPhotoOutput()
260 {
261     return photoOutput_;
262 }
263 
IsPhotoOutput(napi_env env,napi_value obj)264 bool PhotoOutputNapi::IsPhotoOutput(napi_env env, napi_value obj)
265 {
266     bool result = false;
267     napi_status status;
268     napi_value constructor = nullptr;
269 
270     status = napi_get_reference_value(env, sConstructor_, &constructor);
271     if (status == napi_ok) {
272         status = napi_instanceof(env, obj, constructor, &result);
273         if (status != napi_ok) {
274             result = false;
275         }
276     }
277 
278     return result;
279 }
280 
CreatePhotoOutput(napi_env env,Profile & profile,std::string surfaceId)281 napi_value PhotoOutputNapi::CreatePhotoOutput(napi_env env, Profile &profile, std::string surfaceId)
282 {
283     CAMERA_SYNC_TRACE;
284     napi_status status;
285     napi_value result = nullptr;
286     napi_value constructor;
287     MEDIA_INFO_LOG("CreatePhotoOutput start");
288     MEDIA_INFO_LOG("CreatePhotoOutput profile CameraFormat= %{public}d", profile.GetCameraFormat());
289     napi_get_undefined(env, &result);
290     status = napi_get_reference_value(env, sConstructor_, &constructor);
291     if (status == napi_ok) {
292         MEDIA_INFO_LOG("CreatePhotoOutput surfaceId: %{public}s", surfaceId.c_str());
293         sptr<Surface> sface = Media::ImageReceiver::getSurfaceById(surfaceId);
294         if (sface == nullptr) {
295             MEDIA_ERR_LOG("failed to get surface from ImageReceiver");
296             return result;
297         }
298         MEDIA_INFO_LOG("surface width: %{public}d, height: %{public}d", sface->GetDefaultWidth(),
299                        sface->GetDefaultHeight());
300         sface->SetUserData(CameraManager::surfaceFormat, std::to_string(profile.GetCameraFormat()));
301         int retCode = CameraManager::GetInstance()->CreatePhotoOutput(profile, sface, &sPhotoOutput_);
302         if (!CameraNapiUtils::CheckError(env, retCode)) {
303             return nullptr;
304         }
305         if (sPhotoOutput_ == nullptr) {
306             MEDIA_ERR_LOG("failed to create CreatePhotoOutput");
307             return result;
308         }
309         status = napi_new_instance(env, constructor, 0, nullptr, &result);
310         sPhotoOutput_ = nullptr;
311         if (status == napi_ok && result != nullptr) {
312             MEDIA_ERR_LOG("Success to create photo output instance");
313             return result;
314         } else {
315             MEDIA_ERR_LOG("Failed to create photo output instance");
316         }
317     }
318     MEDIA_INFO_LOG("CreatePhotoOutput get undefined");
319     return result;
320 }
321 
CommonCompleteCallback(napi_env env,napi_status status,void * data)322 static void CommonCompleteCallback(napi_env env, napi_status status, void* data)
323 {
324     auto context = static_cast<PhotoOutputAsyncContext*>(data);
325     if (context == nullptr) {
326         MEDIA_ERR_LOG("Async context is null");
327         return;
328     }
329 
330     std::unique_ptr<JSAsyncContextOutput> jsContext = std::make_unique<JSAsyncContextOutput>();
331 
332     if (!context->status) {
333         CameraNapiUtils::CreateNapiErrorObject(env, context->errorCode, context->errorMsg.c_str(), jsContext);
334     } else {
335         jsContext->status = true;
336         napi_get_undefined(env, &jsContext->error);
337         if (context->bRetBool) {
338             napi_get_boolean(env, context->isSupported, &jsContext->data);
339         } else {
340             napi_get_undefined(env, &jsContext->data);
341         }
342     }
343 
344     if (!context->funcName.empty() && context->taskId > 0) {
345         // Finish async trace
346         CAMERA_FINISH_ASYNC_TRACE(context->funcName, context->taskId);
347         jsContext->funcName = context->funcName;
348     }
349 
350     if (context->work != nullptr) {
351         CameraNapiUtils::InvokeJSAsyncMethod(env, context->deferred, context->callbackRef,
352                                              context->work, *jsContext);
353     }
354     delete context;
355 }
356 
QueryAndGetProperty(napi_env env,napi_value arg,const string & propertyName,napi_value & property)357 int32_t QueryAndGetProperty(napi_env env, napi_value arg, const string &propertyName, napi_value &property)
358 {
359     bool present = false;
360     int32_t retval = 0;
361     if ((napi_has_named_property(env, arg, propertyName.c_str(), &present) != napi_ok)
362         || (!present) || (napi_get_named_property(env, arg, propertyName.c_str(), &property) != napi_ok)) {
363             HiLog::Error(LABEL, "Failed to obtain property: %{public}s", propertyName.c_str());
364             retval = -1;
365     }
366 
367     return retval;
368 }
369 
GetLocationProperties(napi_env env,napi_value locationObj,const PhotoOutputAsyncContext & context)370 int32_t GetLocationProperties(napi_env env, napi_value locationObj, const PhotoOutputAsyncContext &context)
371 {
372     PhotoOutputAsyncContext* asyncContext = const_cast<PhotoOutputAsyncContext *>(&context);
373     napi_value latproperty = nullptr;
374     napi_value lonproperty = nullptr;
375     napi_value altproperty = nullptr;
376     double latitude = -1.0;
377     double longitude = -1.0;
378     double altitude = -1.0;
379 
380     if ((QueryAndGetProperty(env, locationObj, "latitude", latproperty) == 0) &&
381         (QueryAndGetProperty(env, locationObj, "longitude", lonproperty) == 0) &&
382         (QueryAndGetProperty(env, locationObj, "altitude", altproperty) == 0)) {
383         if ((napi_get_value_double(env, latproperty, &latitude) != napi_ok) ||
384             (napi_get_value_double(env, lonproperty, &longitude) != napi_ok) ||
385             (napi_get_value_double(env, altproperty, &altitude) != napi_ok)) {
386             return -1;
387         } else {
388             asyncContext->location = std::make_unique<Location>();
389             asyncContext->location->latitude = latitude;
390             asyncContext->location->longitude = longitude;
391             asyncContext->location->altitude = altitude;
392         }
393     } else {
394         return -1;
395     }
396 
397     return 0;
398 }
399 
GetFetchOptionsParam(napi_env env,napi_value arg,const PhotoOutputAsyncContext & context,bool & err)400 static void GetFetchOptionsParam(napi_env env, napi_value arg, const PhotoOutputAsyncContext &context, bool &err)
401 {
402     PhotoOutputAsyncContext* asyncContext = const_cast<PhotoOutputAsyncContext *>(&context);
403     int32_t intValue;
404     std::string strValue;
405     napi_value property = nullptr;
406     PhotoCaptureSetting::QualityLevel quality;
407     PhotoCaptureSetting::RotationConfig rotation;
408 
409     if (QueryAndGetProperty(env, arg, "quality", property) == 0) {
410         if (napi_get_value_int32(env, property, &intValue) != napi_ok
411             || CameraNapiUtils::MapQualityLevelFromJs(intValue, quality) == -1) {
412             err = true;
413             return;
414         } else {
415             asyncContext->quality = quality;
416         }
417     }
418 
419     if (QueryAndGetProperty(env, arg, "rotation", property) == 0) {
420         if (napi_get_value_int32(env, property, &intValue) != napi_ok
421             || CameraNapiUtils::MapImageRotationFromJs(intValue, rotation) == -1) {
422             err = true;
423             return;
424         } else {
425             asyncContext->rotation = rotation;
426         }
427     }
428 
429     if (QueryAndGetProperty(env, arg, "location", property) == 0) {
430         if (GetLocationProperties(env, property, context) == -1) {
431             err = true;
432             return;
433         }
434     }
435 
436     if (QueryAndGetProperty(env, arg, "mirror", property) == 0) {
437         bool isMirror = false;
438         if (napi_get_value_bool(env, property, &isMirror) != napi_ok) {
439             err = true;
440             return;
441         } else {
442             asyncContext->isMirror = isMirror;
443         }
444     }
445 }
446 
ConvertJSArgsToNative(napi_env env,size_t argc,const napi_value argv[],PhotoOutputAsyncContext & asyncContext)447 static napi_value ConvertJSArgsToNative(napi_env env, size_t argc, const napi_value argv[],
448     PhotoOutputAsyncContext &asyncContext)
449 {
450     const int32_t refCount = 1;
451     napi_value result = nullptr;
452     auto context = &asyncContext;
453     bool err = false;
454 
455     NAPI_ASSERT(env, argv != nullptr, "Argument list is empty");
456 
457     for (size_t i = PARAM0; i < argc; i++) {
458         napi_valuetype valueType = napi_undefined;
459         napi_typeof(env, argv[i], &valueType);
460         if (i == PARAM0 && valueType == napi_object) {
461             GetFetchOptionsParam(env, argv[PARAM0], asyncContext, err);
462             if (err) {
463                 HiLog::Error(LABEL, "fetch options retrieval failed");
464                 NAPI_ASSERT(env, false, "type mismatch");
465             }
466             asyncContext.hasPhotoSettings = true;
467         } else if ((i == PARAM0) && (valueType == napi_function)) {
468             napi_create_reference(env, argv[i], refCount, &context->callbackRef);
469             break;
470         } else if ((i == PARAM1) && (valueType == napi_function)) {
471             napi_create_reference(env, argv[i], refCount, &context->callbackRef);
472             break;
473         } else if ((i == PARAM0) && (valueType == napi_boolean)) {
474             napi_get_value_bool(env, argv[i], &context->isSupported);
475             break;
476         } else {
477             NAPI_ASSERT(env, false, "type mismatch");
478         }
479     }
480 
481     // Return true napi_value if params are successfully obtained
482     napi_get_boolean(env, true, &result);
483     return result;
484 }
485 
Capture(napi_env env,napi_callback_info info)486 napi_value PhotoOutputNapi::Capture(napi_env env, napi_callback_info info)
487 {
488     napi_status status;
489     napi_value result = nullptr;
490     size_t argc = ARGS_TWO;
491     napi_value argv[ARGS_TWO] = {0};
492     napi_value thisVar = nullptr;
493     napi_value resource = nullptr;
494 
495     CAMERA_NAPI_GET_JS_ARGS(env, info, argc, argv, thisVar);
496 
497     napi_get_undefined(env, &result);
498     unique_ptr<PhotoOutputAsyncContext> asyncContext = make_unique<PhotoOutputAsyncContext>();
499     if (!CameraNapiUtils::CheckInvalidArgument(env, argc, ARGS_TWO, argv, PHOTO_OUT_CAPTURE)) {
500         asyncContext->isInvalidArgument = true;
501         asyncContext->status = false;
502         asyncContext->errorCode = INVALID_ARGUMENT;
503     }
504     status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&asyncContext->objectInfo));
505     if (status == napi_ok && asyncContext->objectInfo != nullptr) {
506         if (!asyncContext->isInvalidArgument) {
507             result = ConvertJSArgsToNative(env, argc, argv, *asyncContext);
508         }
509         CAMERA_NAPI_CHECK_NULL_PTR_RETURN_UNDEFINED(env, result, result, "Failed to obtain arguments");
510         CAMERA_NAPI_CREATE_PROMISE(env, asyncContext->callbackRef, asyncContext->deferred, result);
511         CAMERA_NAPI_CREATE_RESOURCE_NAME(env, resource, "Capture");
512         status = napi_create_async_work(
513             env, nullptr, resource, [](napi_env env, void* data) {
514                 PhotoOutputAsyncContext* context = static_cast<PhotoOutputAsyncContext*>(data);
515                 // Start async trace
516                 context->funcName = "PhotoOutputNapi::Capture";
517                 context->taskId = CameraNapiUtils::IncreamentAndGet(photoOutputTaskId);
518                 if (context->isInvalidArgument) {
519                     return;
520                 }
521                 CAMERA_START_ASYNC_TRACE(context->funcName, context->taskId);
522                 if (context->objectInfo == nullptr) {
523                     context->status = false;
524                     return;
525                 }
526 
527                 context->bRetBool = false;
528                 context->status = true;
529                 sptr<PhotoOutput> photoOutput = ((sptr<PhotoOutput> &)(context->objectInfo->photoOutput_));
530                 if ((context->hasPhotoSettings)) {
531                     std::shared_ptr<PhotoCaptureSetting> capSettings = make_shared<PhotoCaptureSetting>();
532 
533                     if (context->quality != -1) {
534                         capSettings->SetQuality(
535                             static_cast<PhotoCaptureSetting::QualityLevel>(context->quality));
536                     }
537 
538                     if (context->rotation != -1) {
539                         capSettings->SetRotation(
540                             static_cast<PhotoCaptureSetting::RotationConfig>(context->rotation));
541                     }
542 
543                     capSettings->SetMirror(context->isMirror);
544 
545                     if (context->location != nullptr) {
546                         capSettings->SetLocation(context->location);
547                     }
548 
549                     context->errorCode = photoOutput->Capture(capSettings);
550                 } else {
551                     context->errorCode = photoOutput->Capture();
552                 }
553                 context->status = context->errorCode == 0;
554             }, CommonCompleteCallback, static_cast<void*>(asyncContext.get()), &asyncContext->work);
555         if (status != napi_ok) {
556             MEDIA_ERR_LOG("Failed to create napi_create_async_work for PhotoOutputNapi::Capture");
557             napi_get_undefined(env, &result);
558         } else {
559             napi_queue_async_work(env, asyncContext->work);
560             asyncContext.release();
561         }
562     }
563 
564     return result;
565 }
566 
Release(napi_env env,napi_callback_info info)567 napi_value PhotoOutputNapi::Release(napi_env env, napi_callback_info info)
568 {
569     napi_status status;
570     napi_value result = nullptr;
571     const int32_t refCount = 1;
572     napi_value resource = nullptr;
573     size_t argc = ARGS_ONE;
574     napi_value argv[ARGS_ONE] = {0};
575     napi_value thisVar = nullptr;
576 
577     CAMERA_NAPI_GET_JS_ARGS(env, info, argc, argv, thisVar);
578     NAPI_ASSERT(env, argc <= ARGS_ONE, "requires 1 parameter maximum");
579 
580     napi_get_undefined(env, &result);
581     std::unique_ptr<PhotoOutputAsyncContext> asyncContext = std::make_unique<PhotoOutputAsyncContext>();
582     status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&asyncContext->objectInfo));
583     if (status == napi_ok && asyncContext->objectInfo != nullptr) {
584         if (argc == ARGS_ONE) {
585             CAMERA_NAPI_GET_JS_ASYNC_CB_REF(env, argv[PARAM0], refCount, asyncContext->callbackRef);
586         }
587 
588         CAMERA_NAPI_CREATE_PROMISE(env, asyncContext->callbackRef, asyncContext->deferred, result);
589         CAMERA_NAPI_CREATE_RESOURCE_NAME(env, resource, "Release");
590 
591         status = napi_create_async_work(
592             env, nullptr, resource, [](napi_env env, void* data) {
593                 auto context = static_cast<PhotoOutputAsyncContext*>(data);
594                 context->status = false;
595                 // Start async trace
596                 context->funcName = "PhotoOutputNapi::Release";
597                 context->taskId = CameraNapiUtils::IncreamentAndGet(photoOutputTaskId);
598                 CAMERA_START_ASYNC_TRACE(context->funcName, context->taskId);
599                 if (context->objectInfo != nullptr) {
600                     context->bRetBool = false;
601                     context->status = true;
602                     ((sptr<PhotoOutput> &)(context->objectInfo->photoOutput_))->Release();
603                 }
604             },
605             CommonCompleteCallback, static_cast<void*>(asyncContext.get()), &asyncContext->work);
606         if (status != napi_ok) {
607             MEDIA_ERR_LOG("Failed to create napi_create_async_work for PhotoOutputNapi::Release");
608             napi_get_undefined(env, &result);
609         } else {
610             napi_queue_async_work(env, asyncContext->work);
611             asyncContext.release();
612         }
613     }
614 
615     return result;
616 }
617 
GetDefaultCaptureSetting(napi_env env,napi_callback_info info)618 napi_value PhotoOutputNapi::GetDefaultCaptureSetting(napi_env env, napi_callback_info info)
619 {
620     napi_status status;
621     napi_value result = nullptr;
622     const int32_t refCount = 1;
623     napi_value resource = nullptr;
624     size_t argc = ARGS_ONE;
625     napi_value argv[ARGS_ONE] = {0};
626     napi_value thisVar = nullptr;
627 
628     CAMERA_NAPI_GET_JS_ARGS(env, info, argc, argv, thisVar);
629     NAPI_ASSERT(env, argc <= ARGS_ONE, "requires 1 parameter maximum");
630 
631     napi_get_undefined(env, &result);
632     std::unique_ptr<PhotoOutputAsyncContext> asyncContext = std::make_unique<PhotoOutputAsyncContext>();
633     status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&asyncContext->objectInfo));
634     if (status == napi_ok && asyncContext->objectInfo != nullptr) {
635         if (argc == ARGS_ONE) {
636             CAMERA_NAPI_GET_JS_ASYNC_CB_REF(env, argv[PARAM0], refCount, asyncContext->callbackRef);
637         }
638 
639         CAMERA_NAPI_CREATE_PROMISE(env, asyncContext->callbackRef, asyncContext->deferred, result);
640         CAMERA_NAPI_CREATE_RESOURCE_NAME(env, resource, "GetDefaultCaptureSetting");
641 
642         status = napi_create_async_work(
643             env, nullptr, resource, [](napi_env env, void* data) {
644                 auto context = static_cast<PhotoOutputAsyncContext*>(data);
645                 context->status = false;
646                 // Start async trace
647                 context->funcName = "PhotoOutputNapi::GetDefaultCaptureSetting";
648                 context->taskId = CameraNapiUtils::IncreamentAndGet(photoOutputTaskId);
649                 CAMERA_START_ASYNC_TRACE(context->funcName, context->taskId);
650                 if (context->objectInfo != nullptr) {
651                     context->bRetBool = false;
652                     context->status = true;
653                 }
654             },
655             CommonCompleteCallback, static_cast<void*>(asyncContext.get()), &asyncContext->work);
656         if (status != napi_ok) {
657             MEDIA_ERR_LOG("Failed to create napi_create_async_work for PhotoOutputNapi::GetDefaultCaptureSetting");
658             napi_get_undefined(env, &result);
659         } else {
660             napi_queue_async_work(env, asyncContext->work);
661             asyncContext.release();
662         }
663     }
664 
665     return result;
666 }
667 
IsMirrorSupported(napi_env env,napi_callback_info info)668 napi_value PhotoOutputNapi::IsMirrorSupported(napi_env env, napi_callback_info info)
669 {
670     napi_status status;
671     napi_value result = nullptr;
672     size_t argc = ARGS_ZERO;
673     napi_value argv[ARGS_ZERO];
674     napi_value thisVar = nullptr;
675 
676     CAMERA_NAPI_GET_JS_ARGS(env, info, argc, argv, thisVar);
677 
678     napi_get_undefined(env, &result);
679     PhotoOutputNapi* photoOutputNapi = nullptr;
680     status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&photoOutputNapi));
681     if (status == napi_ok && photoOutputNapi != nullptr) {
682         bool isSupported = photoOutputNapi->photoOutput_->IsMirrorSupported();
683         napi_get_boolean(env, isSupported, &result);
684     }
685 
686     return result;
687 }
688 
SetMirror(napi_env env,napi_callback_info info)689 napi_value PhotoOutputNapi::SetMirror(napi_env env, napi_callback_info info)
690 {
691     napi_status status;
692     napi_value result = nullptr;
693     const int32_t refCount = 1;
694     napi_value resource = nullptr;
695     size_t argc = ARGS_TWO;
696     napi_value argv[ARGS_TWO] = {0};
697     napi_value thisVar = nullptr;
698 
699     CAMERA_NAPI_GET_JS_ARGS(env, info, argc, argv, thisVar);
700     NAPI_ASSERT(env, argc <= ARGS_TWO, "requires 2 parameters maximum");
701 
702     napi_get_undefined(env, &result);
703     std::unique_ptr<PhotoOutputAsyncContext> asyncContext = std::make_unique<PhotoOutputAsyncContext>();
704     status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&asyncContext->objectInfo));
705     if (status == napi_ok && asyncContext->objectInfo != nullptr) {
706         if (argc == ARGS_TWO) {
707             CAMERA_NAPI_GET_JS_ASYNC_CB_REF(env, argv[PARAM1], refCount, asyncContext->callbackRef);
708         }
709 
710         result = ConvertJSArgsToNative(env, argc, argv, *asyncContext);
711         asyncContext->isMirror = asyncContext->isSupported;
712         CAMERA_NAPI_CREATE_PROMISE(env, asyncContext->callbackRef, asyncContext->deferred, result);
713         CAMERA_NAPI_CREATE_RESOURCE_NAME(env, resource, "SetMirror");
714         status = napi_create_async_work(
715             env, nullptr, resource, [](napi_env env, void* data) {
716                 auto context = static_cast<PhotoOutputAsyncContext*>(data);
717                 context->status = false;
718                 // Start async trace
719                 context->funcName = "PhotoOutputNapi::SetMirror";
720                 context->taskId = CameraNapiUtils::IncreamentAndGet(photoOutputTaskId);
721                 CAMERA_START_ASYNC_TRACE(context->funcName, context->taskId);
722                 if (context->objectInfo != nullptr) {
723                     context->bRetBool = false;
724                     context->status = true;
725                 }
726             },
727             CommonCompleteCallback, static_cast<void*>(asyncContext.get()), &asyncContext->work);
728         if (status != napi_ok) {
729             MEDIA_ERR_LOG("Failed to create napi_create_async_work for SetMirror");
730             napi_get_undefined(env, &result);
731         } else {
732             napi_queue_async_work(env, asyncContext->work);
733             asyncContext.release();
734         }
735     }
736 
737     return result;
738 }
739 
On(napi_env env,napi_callback_info info)740 napi_value PhotoOutputNapi::On(napi_env env, napi_callback_info info)
741 {
742     CAMERA_SYNC_TRACE;
743     napi_value undefinedResult = nullptr;
744     size_t argCount = ARGS_TWO;
745     napi_value argv[ARGS_TWO] = {nullptr};
746     napi_value thisVar = nullptr;
747     size_t res = 0;
748     char buffer[SIZE];
749     const int32_t refCount = 1;
750     PhotoOutputNapi* obj = nullptr;
751     napi_status status;
752 
753     napi_get_undefined(env, &undefinedResult);
754 
755     CAMERA_NAPI_GET_JS_ARGS(env, info, argCount, argv, thisVar);
756     NAPI_ASSERT(env, argCount == ARGS_TWO, "requires 2 parameters");
757 
758     if (thisVar == nullptr || argv[PARAM0] == nullptr || argv[PARAM1] == nullptr) {
759         MEDIA_ERR_LOG("Failed to retrieve details about the callback");
760         return undefinedResult;
761     }
762 
763     status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&obj));
764     if (status == napi_ok && obj != nullptr) {
765         napi_valuetype valueType = napi_undefined;
766         if (napi_typeof(env, argv[PARAM0], &valueType) != napi_ok || valueType != napi_string
767             || napi_typeof(env, argv[PARAM1], &valueType) != napi_ok || valueType != napi_function) {
768             return undefinedResult;
769         }
770 
771         napi_get_value_string_utf8(env, argv[PARAM0], buffer, SIZE, &res);
772         std::string eventType = std::string(buffer);
773 
774         napi_ref callbackRef;
775         napi_create_reference(env, argv[PARAM1], refCount, &callbackRef);
776 
777         if (!eventType.empty()) {
778             obj->photoCallback_->SetCallbackRef(eventType, callbackRef);
779         } else {
780             MEDIA_ERR_LOG("Failed to Register Callback: event type is empty!");
781         }
782     }
783     return undefinedResult;
784 }
785 } // namespace CameraStandard
786 } // namespace OHOS
787