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/video_output_napi.h"
17 
18 #include <uv.h>
19 
20 #include "camera_napi_const.h"
21 #include "camera_napi_object_types.h"
22 #include "camera_napi_param_parser.h"
23 #include "camera_napi_security_utils.h"
24 #include "camera_napi_template_utils.h"
25 #include "camera_napi_utils.h"
26 #include "camera_napi_worker_queue_keeper.h"
27 #include "camera_output_capability.h"
28 #include "listener_base.h"
29 #include "napi/native_api.h"
30 #include "napi/native_common.h"
31 
32 namespace OHOS {
33 namespace CameraStandard {
34 namespace {
AsyncCompleteCallback(napi_env env,napi_status status,void * data)35 void AsyncCompleteCallback(napi_env env, napi_status status, void* data)
36 {
37     auto context = static_cast<VideoOutputAsyncContext*>(data);
38     CHECK_ERROR_RETURN_LOG(context == nullptr, "VideoOutputNapi AsyncCompleteCallback context is null");
39     MEDIA_INFO_LOG("VideoOutputNapi AsyncCompleteCallback %{public}s, status = %{public}d", context->funcName.c_str(),
40         context->status);
41     std::unique_ptr<JSAsyncContextOutput> jsContext = std::make_unique<JSAsyncContextOutput>();
42     jsContext->status = context->status;
43     if (!context->status) {
44         CameraNapiUtils::CreateNapiErrorObject(env, context->errorCode, context->errorMsg.c_str(), jsContext);
45     } else {
46         napi_get_undefined(env, &jsContext->data);
47     }
48     if (!context->funcName.empty() && context->taskId > 0) {
49         // Finish async trace
50         CAMERA_FINISH_ASYNC_TRACE(context->funcName, context->taskId);
51         jsContext->funcName = context->funcName;
52     }
53     if (context->work != nullptr) {
54         CameraNapiUtils::InvokeJSAsyncMethod(env, context->deferred, context->callbackRef, context->work, *jsContext);
55     }
56     context->FreeHeldNapiValue(env);
57     delete context;
58 }
59 } // namespace
60 
61 thread_local napi_ref VideoOutputNapi::sConstructor_ = nullptr;
62 thread_local sptr<VideoOutput> VideoOutputNapi::sVideoOutput_ = nullptr;
63 thread_local uint32_t VideoOutputNapi::videoOutputTaskId = CAMERA_VIDEO_OUTPUT_TASKID;
64 
VideoCallbackListener(napi_env env)65 VideoCallbackListener::VideoCallbackListener(napi_env env) : ListenerBase(env) {}
66 
UpdateJSCallbackAsync(VideoOutputEventType eventType,const VideoCallbackInfo & info) const67 void VideoCallbackListener::UpdateJSCallbackAsync(VideoOutputEventType eventType, const VideoCallbackInfo& info) const
68 {
69     MEDIA_DEBUG_LOG("UpdateJSCallbackAsync is called");
70     uv_loop_s* loop = nullptr;
71     napi_get_uv_event_loop(env_, &loop);
72     if (!loop) {
73         MEDIA_ERR_LOG("failed to get event loop");
74         return;
75     }
76     uv_work_t* work = new(std::nothrow) uv_work_t;
77     if (!work) {
78         MEDIA_ERR_LOG("failed to allocate work");
79         return;
80     }
81     std::unique_ptr<VideoOutputCallbackInfo> callbackInfo =
82         std::make_unique<VideoOutputCallbackInfo>(eventType, info, shared_from_this());
83     work->data = callbackInfo.get();
84     int ret = uv_queue_work_with_qos(loop, work, [] (uv_work_t* work) {}, [] (uv_work_t* work, int status) {
85         VideoOutputCallbackInfo* callbackInfo = reinterpret_cast<VideoOutputCallbackInfo *>(work->data);
86         if (callbackInfo) {
87             auto listener = callbackInfo->listener_.lock();
88             if (listener) {
89                 listener->UpdateJSCallback(callbackInfo->eventType_, callbackInfo->info_);
90             }
91             delete callbackInfo;
92         }
93         delete work;
94     }, uv_qos_user_initiated);
95     if (ret) {
96         MEDIA_ERR_LOG("failed to execute work");
97         delete work;
98     }  else {
99         callbackInfo.release();
100     }
101 }
102 
OnFrameStarted() const103 void VideoCallbackListener::OnFrameStarted() const
104 {
105     CAMERA_SYNC_TRACE;
106     MEDIA_DEBUG_LOG("OnFrameStarted is called");
107     VideoCallbackInfo info;
108     UpdateJSCallbackAsync(VideoOutputEventType::VIDEO_FRAME_START, info);
109 }
110 
OnFrameEnded(const int32_t frameCount) const111 void VideoCallbackListener::OnFrameEnded(const int32_t frameCount) const
112 {
113     CAMERA_SYNC_TRACE;
114     MEDIA_DEBUG_LOG("OnFrameEnded is called, frameCount: %{public}d", frameCount);
115     VideoCallbackInfo info;
116     info.frameCount = frameCount;
117     UpdateJSCallbackAsync(VideoOutputEventType::VIDEO_FRAME_END, info);
118 }
119 
OnError(const int32_t errorCode) const120 void VideoCallbackListener::OnError(const int32_t errorCode) const
121 {
122     MEDIA_DEBUG_LOG("OnError is called, errorCode: %{public}d", errorCode);
123     VideoCallbackInfo info;
124     info.errorCode = errorCode;
125     UpdateJSCallbackAsync(VideoOutputEventType::VIDEO_FRAME_ERROR, info);
126 }
127 
OnDeferredVideoEnhancementInfo(const CaptureEndedInfoExt captureEndedInfo) const128 void VideoCallbackListener::OnDeferredVideoEnhancementInfo(const CaptureEndedInfoExt captureEndedInfo) const
129 {
130     MEDIA_DEBUG_LOG("OnDeferredVideoEnhancementInfo is called");
131     VideoCallbackInfo info;
132     info.isDeferredVideoEnhancementAvailable = captureEndedInfo.isDeferredVideoEnhancementAvailable;
133     info.videoId = captureEndedInfo.videoId;
134     MEDIA_INFO_LOG("OnDeferredVideoEnhancementInfo isDeferredVideo:%{public}d videoId:%{public}s ",
135         info.isDeferredVideoEnhancementAvailable, info.videoId.c_str());
136     UpdateJSCallbackAsync(VideoOutputEventType::VIDEO_DEFERRED_ENHANCEMENT, info);
137 }
138 
ExecuteOnDeferredVideoCb(const VideoCallbackInfo & info) const139 void VideoCallbackListener::ExecuteOnDeferredVideoCb(const VideoCallbackInfo& info) const
140 {
141     MEDIA_INFO_LOG("ExecuteOnDeferredVideoCb");
142     napi_value result[ARGS_TWO] = {nullptr, nullptr};
143     napi_value retVal;
144 
145     napi_get_undefined(env_, &result[PARAM0]);
146     napi_get_undefined(env_, &result[PARAM1]);
147 
148     napi_value propValue;
149     napi_create_object(env_, &result[PARAM1]);
150     napi_get_boolean(env_, info.isDeferredVideoEnhancementAvailable, &propValue);
151     napi_set_named_property(env_, result[PARAM1], "isDeferredVideoEnhancementAvailable", propValue);
152     napi_create_string_utf8(env_, info.videoId.c_str(), NAPI_AUTO_LENGTH, &propValue);
153     napi_set_named_property(env_, result[PARAM1], "videoId", propValue);
154 
155     ExecuteCallbackNapiPara callbackNapiPara { .recv = nullptr, .argc = ARGS_TWO, .argv = result, .result = &retVal };
156     ExecuteCallback(CONST_VIDEO_DEFERRED_ENHANCEMENT, callbackNapiPara);
157 }
158 
UpdateJSCallback(VideoOutputEventType eventType,const VideoCallbackInfo & info) const159 void VideoCallbackListener::UpdateJSCallback(VideoOutputEventType eventType, const VideoCallbackInfo& info) const
160 {
161     MEDIA_DEBUG_LOG("UpdateJSCallback is called");
162     switch (eventType) {
163         // case VideoOutputEventType::VIDEO_FRAME_START:
164         // case VideoOutputEventType::VIDEO_FRAME_END:
165         // case VideoOutputEventType::VIDEO_FRAME_ERROR:
166         // case VideoOutputEventType::VIDEO_INVALID_TYPE:
167         //     break;
168         case VideoOutputEventType::VIDEO_DEFERRED_ENHANCEMENT:
169             ExecuteOnDeferredVideoCb(info);
170             break;
171         default:
172             MEDIA_ERR_LOG("Incorrect photo callback event type received from JS");
173     }
174 
175     napi_value result[ARGS_ONE];
176     napi_value retVal;
177     napi_value propValue;
178     std::string eventName = VideoOutputEventTypeHelper.GetKeyString(eventType);
179     if (eventName.empty()) {
180         MEDIA_WARNING_LOG(
181             "VideoCallbackListener::UpdateJSCallback, event type is invalid %d", static_cast<int32_t>(eventType));
182         return;
183     }
184     if (eventType == VideoOutputEventType::VIDEO_FRAME_ERROR) {
185         napi_create_object(env_, &result[PARAM0]);
186         napi_create_int32(env_, info.errorCode, &propValue);
187         napi_set_named_property(env_, result[PARAM0], "code", propValue);
188     } else {
189         napi_get_undefined(env_, &result[PARAM0]);
190     }
191     ExecuteCallbackNapiPara callbackNapiPara { .recv = nullptr, .argc = ARGS_ONE, .argv = result, .result = &retVal };
192     ExecuteCallback(eventName, callbackNapiPara);
193 }
194 
VideoOutputNapi()195 VideoOutputNapi::VideoOutputNapi() : env_(nullptr) {}
196 
~VideoOutputNapi()197 VideoOutputNapi::~VideoOutputNapi()
198 {
199     MEDIA_DEBUG_LOG("~VideoOutputNapi is called");
200 }
201 
VideoOutputNapiDestructor(napi_env env,void * nativeObject,void * finalize_hint)202 void VideoOutputNapi::VideoOutputNapiDestructor(napi_env env, void* nativeObject, void* finalize_hint)
203 {
204     MEDIA_DEBUG_LOG("VideoOutputNapiDestructor is called");
205     VideoOutputNapi* videoOutput = reinterpret_cast<VideoOutputNapi*>(nativeObject);
206     if (videoOutput != nullptr) {
207         delete videoOutput;
208     }
209 }
210 
Init(napi_env env,napi_value exports)211 napi_value VideoOutputNapi::Init(napi_env env, napi_value exports)
212 {
213     MEDIA_DEBUG_LOG("Init is called");
214     napi_status status;
215     napi_value ctorObj;
216     int32_t refCount = 1;
217 
218     napi_property_descriptor video_output_props[] = {
219         DECLARE_NAPI_FUNCTION("start", Start),
220         DECLARE_NAPI_FUNCTION("stop", Stop),
221         DECLARE_NAPI_FUNCTION("setFrameRate", SetFrameRate),
222         DECLARE_NAPI_FUNCTION("getActiveFrameRate", GetActiveFrameRate),
223         DECLARE_NAPI_FUNCTION("getSupportedFrameRates", GetSupportedFrameRates),
224         DECLARE_NAPI_FUNCTION("isMirrorSupported", IsMirrorSupported),
225         DECLARE_NAPI_FUNCTION("enableMirror", EnableMirror),
226         DECLARE_NAPI_FUNCTION("release", Release),
227         DECLARE_NAPI_FUNCTION("on", On),
228         DECLARE_NAPI_FUNCTION("once", Once),
229         DECLARE_NAPI_FUNCTION("off", Off),
230         DECLARE_NAPI_FUNCTION("getActiveProfile", GetActiveProfile),
231         DECLARE_NAPI_FUNCTION("getSupportedVideoMetaTypes", GetSupportedVideoMetaTypes),
232         DECLARE_NAPI_FUNCTION("attachMetaSurface", AttachMetaSurface),
233         DECLARE_NAPI_FUNCTION("getVideoRotation", GetVideoRotation),
234         DECLARE_NAPI_FUNCTION("isAutoDeferredVideoEnhancementSupported", IsAutoDeferredVideoEnhancementSupported),
235         DECLARE_NAPI_FUNCTION("isAutoDeferredVideoEnhancementEnabled", IsAutoDeferredVideoEnhancementEnabled),
236         DECLARE_NAPI_FUNCTION("enableAutoDeferredVideoEnhancement", EnableAutoDeferredVideoEnhancement),
237         DECLARE_NAPI_FUNCTION("getSupportedRotations", GetSupportedRotations),
238         DECLARE_NAPI_FUNCTION("isRotationSupported", IsRotationSupported),
239         DECLARE_NAPI_FUNCTION("setRotation", SetRotation),
240     };
241 
242     status = napi_define_class(env, CAMERA_VIDEO_OUTPUT_NAPI_CLASS_NAME, NAPI_AUTO_LENGTH,
243                                VideoOutputNapiConstructor, nullptr,
244                                sizeof(video_output_props) / sizeof(video_output_props[PARAM0]),
245                                video_output_props, &ctorObj);
246     if (status == napi_ok) {
247         status = napi_create_reference(env, ctorObj, refCount, &sConstructor_);
248         if (status == napi_ok) {
249             status = napi_set_named_property(env, exports, CAMERA_VIDEO_OUTPUT_NAPI_CLASS_NAME, ctorObj);
250             if (status == napi_ok) {
251                 return exports;
252             }
253         }
254     }
255     MEDIA_ERR_LOG("Init call Failed!");
256     return nullptr;
257 }
258 
259 // Constructor callback
VideoOutputNapiConstructor(napi_env env,napi_callback_info info)260 napi_value VideoOutputNapi::VideoOutputNapiConstructor(napi_env env, napi_callback_info info)
261 {
262     MEDIA_DEBUG_LOG("VideoOutputNapiConstructor is called");
263     napi_status status;
264     napi_value result = nullptr;
265     napi_value thisVar = nullptr;
266 
267     napi_get_undefined(env, &result);
268     CAMERA_NAPI_GET_JS_OBJ_WITH_ZERO_ARGS(env, info, status, thisVar);
269 
270     if (status == napi_ok && thisVar != nullptr) {
271         std::unique_ptr<VideoOutputNapi> obj = std::make_unique<VideoOutputNapi>();
272         if (obj != nullptr) {
273             obj->env_ = env;
274             obj->videoOutput_ = sVideoOutput_;
275 
276             status = napi_wrap(env, thisVar, reinterpret_cast<void*>(obj.get()),
277                                VideoOutputNapi::VideoOutputNapiDestructor, nullptr, nullptr);
278             if (status == napi_ok) {
279                 obj.release();
280                 return thisVar;
281             } else {
282                 MEDIA_ERR_LOG("Failure wrapping js to native napi");
283             }
284         }
285     }
286     MEDIA_ERR_LOG("VideoOutputNapiConstructor call Failed!");
287     return result;
288 }
289 
GetVideoOutput()290 sptr<VideoOutput> VideoOutputNapi::GetVideoOutput()
291 {
292     return videoOutput_;
293 }
294 
IsVideoOutput(napi_env env,napi_value obj)295 bool VideoOutputNapi::IsVideoOutput(napi_env env, napi_value obj)
296 {
297     MEDIA_DEBUG_LOG("IsVideoOutput is called");
298     bool result = false;
299     napi_status status;
300     napi_value constructor = nullptr;
301 
302     status = napi_get_reference_value(env, sConstructor_, &constructor);
303     if (status == napi_ok) {
304         status = napi_instanceof(env, obj, constructor, &result);
305         if (status != napi_ok) {
306             result = false;
307         }
308     }
309     return result;
310 }
311 
GetActiveProfile(napi_env env,napi_callback_info info)312 napi_value VideoOutputNapi::GetActiveProfile(napi_env env, napi_callback_info info)
313 {
314     MEDIA_DEBUG_LOG("VideoOutputNapi::GetActiveProfile is called");
315     VideoOutputNapi* videoOutputNapi = nullptr;
316     CameraNapiParamParser jsParamParser(env, info, videoOutputNapi);
317     if (!jsParamParser.AssertStatus(INVALID_ARGUMENT, "parse parameter occur error")) {
318         MEDIA_ERR_LOG("VideoOutputNapi::GetActiveProfile parse parameter occur error");
319         return nullptr;
320     }
321     auto profile = videoOutputNapi->videoOutput_->GetVideoProfile();
322     if (profile == nullptr) {
323         return CameraNapiUtils::GetUndefinedValue(env);
324     }
325     return CameraNapiObjVideoProfile(*profile).GenerateNapiValue(env);
326 }
327 
CreateJSArray(napi_env env,napi_status status,std::vector<VideoMetaType> nativeArray)328 static napi_value CreateJSArray(napi_env env, napi_status status, std::vector<VideoMetaType> nativeArray)
329 {
330     MEDIA_DEBUG_LOG("CreateJSArray is called");
331     napi_value jsArray = nullptr;
332     napi_value item = nullptr;
333 
334     if (nativeArray.empty()) {
335         MEDIA_ERR_LOG("nativeArray is empty");
336     }
337 
338     status = napi_create_array(env, &jsArray);
339     if (status == napi_ok) {
340         for (size_t i = 0; i < nativeArray.size(); i++) {
341             napi_create_int32(env, nativeArray[i], &item);
342             if (napi_set_element(env, jsArray, i, item) != napi_ok) {
343                 MEDIA_ERR_LOG("Failed to create profile napi wrapper object");
344                 return nullptr;
345             }
346         }
347     }
348     return jsArray;
349 }
350 
GetSupportedVideoMetaTypes(napi_env env,napi_callback_info info)351 napi_value VideoOutputNapi::GetSupportedVideoMetaTypes(napi_env env, napi_callback_info info)
352 {
353     MEDIA_DEBUG_LOG("GetSupportedVideoMetaTypes is called");
354     napi_status status;
355     napi_value result;
356     size_t argc = ARGS_ZERO;
357     napi_value argv[ARGS_ZERO];
358     napi_value thisVar = nullptr;
359 
360     CAMERA_NAPI_GET_JS_ARGS(env, info, argc, argv, thisVar);
361     NAPI_ASSERT(env, (argc == ARGS_ZERO), "requires no parameter.");
362 
363     napi_get_undefined(env, &result);
364     VideoOutputNapi* videoOutputNapi = nullptr;
365     status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&videoOutputNapi));
366     if (status == napi_ok && videoOutputNapi != nullptr) {
367         std::vector<VideoMetaType> videoMetaType = videoOutputNapi->videoOutput_->GetSupportedVideoMetaTypes();
368         result = CreateJSArray(env, status, videoMetaType);
369     } else {
370         MEDIA_ERR_LOG("GetSupportedVideoMetaTypes call failed!");
371     }
372     return result;
373 }
374 
AttachMetaSurface(napi_env env,napi_callback_info info)375 napi_value VideoOutputNapi::AttachMetaSurface(napi_env env, napi_callback_info info)
376 {
377     CAMERA_SYNC_TRACE;
378     napi_status status;
379     napi_value result;
380     size_t argc = ARGS_TWO;
381     napi_value argv[ARGS_TWO] = {0};
382     napi_value thisVar = nullptr;
383 
384     CAMERA_NAPI_GET_JS_ARGS(env, info, argc, argv, thisVar);
385 
386     napi_get_undefined(env, &result);
387     VideoOutputNapi* videoOutputNapi = nullptr;
388     status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&videoOutputNapi));
389     if (status == napi_ok && videoOutputNapi != nullptr) {
390         char buffer[PATH_MAX];
391         size_t surfaceId;
392         napi_get_value_string_utf8(env, argv[PARAM0], buffer, PATH_MAX, &surfaceId);
393         uint32_t videoMetaType;
394         napi_get_value_uint32(env, argv[PARAM1], &videoMetaType);
395 
396         uint64_t iSurfaceId;
397         std::istringstream iss((std::string(buffer)));
398         iss >> iSurfaceId;
399         sptr<Surface> surface = SurfaceUtils::GetInstance()->GetSurface(iSurfaceId);
400         if (surface == nullptr) {
401             MEDIA_ERR_LOG("failed to get surface from SurfaceUtils");
402         }
403         videoOutputNapi->videoOutput_->AttachMetaSurface(surface, static_cast<VideoMetaType>(videoMetaType));
404     } else {
405         MEDIA_ERR_LOG("VideoOutputNapi::AttachMetaSurface failed!");
406     }
407     return result;
408 }
409 
CreateVideoOutput(napi_env env,VideoProfile & profile,std::string surfaceId)410 napi_value VideoOutputNapi::CreateVideoOutput(napi_env env, VideoProfile &profile, std::string surfaceId)
411 {
412     MEDIA_DEBUG_LOG("CreateVideoOutput is called");
413     CAMERA_SYNC_TRACE;
414     napi_status status;
415     napi_value result = nullptr;
416     napi_value constructor;
417 
418     status = napi_get_reference_value(env, sConstructor_, &constructor);
419     if (status == napi_ok) {
420         uint64_t iSurfaceId;
421         std::istringstream iss(surfaceId);
422         iss >> iSurfaceId;
423         sptr<Surface> surface = SurfaceUtils::GetInstance()->GetSurface(iSurfaceId);
424         if (surface == nullptr) {
425             MEDIA_ERR_LOG("failed to get surface from SurfaceUtils");
426             return result;
427         }
428         surface->SetUserData(CameraManager::surfaceFormat, std::to_string(profile.GetCameraFormat()));
429         int retCode = CameraManager::GetInstance()->CreateVideoOutput(profile, surface, &sVideoOutput_);
430         if (!CameraNapiUtils::CheckError(env, retCode)) {
431             return nullptr;
432         }
433         if (sVideoOutput_ == nullptr) {
434             MEDIA_ERR_LOG("failed to create VideoOutput");
435             return result;
436         }
437         status = napi_new_instance(env, constructor, 0, nullptr, &result);
438         sVideoOutput_ = nullptr;
439         if (status == napi_ok && result != nullptr) {
440             return result;
441         } else {
442             MEDIA_ERR_LOG("Failed to create video output instance");
443         }
444     }
445     napi_get_undefined(env, &result);
446     MEDIA_ERR_LOG("CreateVideoOutput call Failed!");
447     return result;
448 }
449 
CreateVideoOutput(napi_env env,std::string surfaceId)450 napi_value VideoOutputNapi::CreateVideoOutput(napi_env env, std::string surfaceId)
451 {
452     MEDIA_DEBUG_LOG("VideoOutputNapi::CreateVideoOutput is called");
453     CAMERA_SYNC_TRACE;
454     napi_status status;
455     napi_value result = nullptr;
456     napi_value constructor;
457 
458     status = napi_get_reference_value(env, sConstructor_, &constructor);
459     if (status == napi_ok) {
460         uint64_t iSurfaceId;
461         std::istringstream iss(surfaceId);
462         iss >> iSurfaceId;
463         sptr<Surface> surface = SurfaceUtils::GetInstance()->GetSurface(iSurfaceId);
464         if (surface == nullptr) {
465             MEDIA_ERR_LOG("failed to get surface from SurfaceUtils");
466             return result;
467         }
468         int retCode = CameraManager::GetInstance()->CreateVideoOutputWithoutProfile(surface, &sVideoOutput_);
469         if (!CameraNapiUtils::CheckError(env, retCode)) {
470             return nullptr;
471         }
472         if (sVideoOutput_ == nullptr) {
473             MEDIA_ERR_LOG("failed to create VideoOutput");
474             return result;
475         }
476         status = napi_new_instance(env, constructor, 0, nullptr, &result);
477         sVideoOutput_ = nullptr;
478         if (status == napi_ok && result != nullptr) {
479             return result;
480         } else {
481             MEDIA_ERR_LOG("Failed to create video output instance");
482         }
483     }
484     napi_get_undefined(env, &result);
485     MEDIA_ERR_LOG("CreateVideoOutput call Failed!");
486     return result;
487 }
488 
Start(napi_env env,napi_callback_info info)489 napi_value VideoOutputNapi::Start(napi_env env, napi_callback_info info)
490 {
491     MEDIA_INFO_LOG("Start is called");
492     std::unique_ptr<VideoOutputAsyncContext> asyncContext = std::make_unique<VideoOutputAsyncContext>(
493         "VideoOutputNapi::Start", CameraNapiUtils::IncrementAndGet(videoOutputTaskId));
494     auto asyncFunction =
495         std::make_shared<CameraNapiAsyncFunction>(env, "Start", asyncContext->callbackRef, asyncContext->deferred);
496     CameraNapiParamParser jsParamParser(env, info, asyncContext->objectInfo, asyncFunction);
497     if (!jsParamParser.AssertStatus(INVALID_ARGUMENT, "invalid argument")) {
498         MEDIA_ERR_LOG("VideoOutputNapi::Start invalid argument");
499         return nullptr;
500     }
501     asyncContext->HoldNapiValue(env, jsParamParser.GetThisVar());
502     napi_status status = napi_create_async_work(
503         env, nullptr, asyncFunction->GetResourceName(),
504         [](napi_env env, void* data) {
505             MEDIA_INFO_LOG("VideoOutputNapi::Start running on worker");
506             auto context = static_cast<VideoOutputAsyncContext*>(data);
507             CHECK_ERROR_RETURN_LOG(context->objectInfo == nullptr, "VideoOutputNapi::Start async info is nullptr");
508             CAMERA_START_ASYNC_TRACE(context->funcName, context->taskId);
509             CameraNapiWorkerQueueKeeper::GetInstance()->ConsumeWorkerQueueTask(context->queueTask, [&context]() {
510                 context->errorCode = context->objectInfo->videoOutput_->Start();
511                 context->status = true;
512                 MEDIA_INFO_LOG("VideoOutputNapi::Start errorCode:%{public}d", context->errorCode);
513             });
514         },
515         AsyncCompleteCallback, static_cast<void*>(asyncContext.get()), &asyncContext->work);
516     if (status != napi_ok) {
517         MEDIA_ERR_LOG("Failed to create napi_create_async_work for VideoOutputNapi::Start");
518         asyncFunction->Reset();
519     } else {
520         asyncContext->queueTask =
521             CameraNapiWorkerQueueKeeper::GetInstance()->AcquireWorkerQueueTask("VideoOutputNapi::Start");
522         napi_queue_async_work_with_qos(env, asyncContext->work, napi_qos_user_initiated);
523         asyncContext.release();
524     }
525     if (asyncFunction->GetAsyncFunctionType() == ASYNC_FUN_TYPE_PROMISE) {
526         return asyncFunction->GetPromise();
527     }
528     return CameraNapiUtils::GetUndefinedValue(env);
529 }
530 
Stop(napi_env env,napi_callback_info info)531 napi_value VideoOutputNapi::Stop(napi_env env, napi_callback_info info)
532 {
533     MEDIA_INFO_LOG("Stop is called");
534     std::unique_ptr<VideoOutputAsyncContext> asyncContext = std::make_unique<VideoOutputAsyncContext>(
535         "VideoOutputNapi::Stop", CameraNapiUtils::IncrementAndGet(videoOutputTaskId));
536     auto asyncFunction =
537         std::make_shared<CameraNapiAsyncFunction>(env, "Stop", asyncContext->callbackRef, asyncContext->deferred);
538     CameraNapiParamParser jsParamParser(env, info, asyncContext->objectInfo, asyncFunction);
539     if (!jsParamParser.AssertStatus(INVALID_ARGUMENT, "invalid argument")) {
540         MEDIA_ERR_LOG("VideoOutputNapi::Stop invalid argument");
541         return nullptr;
542     }
543     asyncContext->HoldNapiValue(env, jsParamParser.GetThisVar());
544     napi_status status = napi_create_async_work(
545         env, nullptr, asyncFunction->GetResourceName(),
546         [](napi_env env, void* data) {
547             MEDIA_INFO_LOG("VideoOutputNapi::Stop running on worker");
548             auto context = static_cast<VideoOutputAsyncContext*>(data);
549             CHECK_ERROR_RETURN_LOG(context->objectInfo == nullptr, "VideoOutputNapi::Stop async info is nullptr");
550             CAMERA_START_ASYNC_TRACE(context->funcName, context->taskId);
551             CameraNapiWorkerQueueKeeper::GetInstance()->ConsumeWorkerQueueTask(context->queueTask, [&context]() {
552                 context->errorCode = context->objectInfo->videoOutput_->Stop();
553                 context->status = true;
554                 MEDIA_INFO_LOG("VideoOutputNapi::Stop errorCode:%{public}d", context->errorCode);
555             });
556         },
557         AsyncCompleteCallback, static_cast<void*>(asyncContext.get()), &asyncContext->work);
558     if (status != napi_ok) {
559         MEDIA_ERR_LOG("Failed to create napi_create_async_work for VideoOutputNapi::Stop");
560         asyncFunction->Reset();
561     } else {
562         asyncContext->queueTask =
563             CameraNapiWorkerQueueKeeper::GetInstance()->AcquireWorkerQueueTask("VideoOutputNapi::Stop");
564         napi_queue_async_work_with_qos(env, asyncContext->work, napi_qos_user_initiated);
565         asyncContext.release();
566     }
567     if (asyncFunction->GetAsyncFunctionType() == ASYNC_FUN_TYPE_PROMISE) {
568         return asyncFunction->GetPromise();
569     }
570     return CameraNapiUtils::GetUndefinedValue(env);
571 }
572 
SetFrameRate(napi_env env,napi_callback_info info)573 napi_value VideoOutputNapi::SetFrameRate(napi_env env, napi_callback_info info)
574 {
575     MEDIA_DEBUG_LOG("SetFrameRate is called");
576     CAMERA_SYNC_TRACE;
577     napi_status status;
578     napi_value result;
579     size_t argc = ARGS_TWO;
580     napi_value argv[ARGS_TWO] = {0};
581     napi_value thisVar = nullptr;
582 
583     CAMERA_NAPI_GET_JS_ARGS(env, info, argc, argv, thisVar);
584     NAPI_ASSERT(env, (argc == ARGS_TWO), "requires 2 parameters maximum.");
585 
586     napi_get_undefined(env, &result);
587     VideoOutputNapi* videoOutputNapi = nullptr;
588     status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&videoOutputNapi));
589     if (status == napi_ok && videoOutputNapi != nullptr) {
590         int32_t minFrameRate;
591         napi_get_value_int32(env, argv[PARAM0], &minFrameRate);
592         int32_t maxFrameRate;
593         napi_get_value_int32(env, argv[PARAM1], &maxFrameRate);
594         int32_t retCode = videoOutputNapi->videoOutput_->SetFrameRate(minFrameRate, maxFrameRate);
595         if (!CameraNapiUtils::CheckError(env, retCode)) {
596             MEDIA_ERR_LOG("VideoOutputNapi::SetFrameRate! %{public}d", retCode);
597             return result;
598         }
599     } else {
600         MEDIA_ERR_LOG("SetFrameRate call Failed!");
601     }
602     return result;
603 }
604 
GetActiveFrameRate(napi_env env,napi_callback_info info)605 napi_value VideoOutputNapi::GetActiveFrameRate(napi_env env, napi_callback_info info)
606 {
607     MEDIA_DEBUG_LOG("GetFrameRate is called");
608     CAMERA_SYNC_TRACE;
609     napi_status status;
610     napi_value result;
611     size_t argc = ARGS_ZERO;
612     napi_value argv[ARGS_ZERO];
613     napi_value thisVar = nullptr;
614 
615     CAMERA_NAPI_GET_JS_ARGS(env, info, argc, argv, thisVar);
616     NAPI_ASSERT(env, (argc == ARGS_ZERO), "requires no parameter.");
617 
618     napi_get_undefined(env, &result);
619     VideoOutputNapi* videoOutputNapi = nullptr;
620     status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&videoOutputNapi));
621     if (status == napi_ok && videoOutputNapi != nullptr) {
622         std::vector<int32_t> frameRateRange = videoOutputNapi->videoOutput_->GetFrameRateRange();
623         CameraNapiUtils::CreateFrameRateJSArray(env, frameRateRange, result);
624     } else {
625         MEDIA_ERR_LOG("GetFrameRate call failed!");
626     }
627     return result;
628 }
629 
GetSupportedFrameRates(napi_env env,napi_callback_info info)630 napi_value VideoOutputNapi::GetSupportedFrameRates(napi_env env, napi_callback_info info)
631 {
632     MEDIA_DEBUG_LOG("GetSupportedFrameRates is called");
633 
634     CAMERA_SYNC_TRACE;
635     napi_status status;
636     napi_value result;
637     size_t argc = ARGS_ZERO;
638     napi_value argv[ARGS_ZERO];
639     napi_value thisVar = nullptr;
640 
641     CAMERA_NAPI_GET_JS_ARGS(env, info, argc, argv, thisVar);
642     NAPI_ASSERT(env, (argc == ARGS_ZERO), "requires no parameter.");
643     napi_get_undefined(env, &result);
644     VideoOutputNapi* videoOutputNapi = nullptr;
645     status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&videoOutputNapi));
646     if (status == napi_ok && videoOutputNapi != nullptr) {
647         std::vector<std::vector<int32_t>> supportedFrameRatesRange =
648                                           videoOutputNapi->videoOutput_->GetSupportedFrameRates();
649         result = CameraNapiUtils::CreateSupportFrameRatesJSArray(env, supportedFrameRatesRange);
650     } else {
651         MEDIA_ERR_LOG("GetSupportedFrameRates call failed!");
652     }
653     return result;
654 }
655 
GetVideoRotation(napi_env env,napi_callback_info info)656 napi_value VideoOutputNapi::GetVideoRotation(napi_env env, napi_callback_info info)
657 {
658     MEDIA_DEBUG_LOG("GetVideoRotation is called!");
659     CAMERA_SYNC_TRACE;
660     napi_status status;
661     napi_value result = nullptr;
662     size_t argc = ARGS_ONE;
663     napi_value argv[ARGS_ONE] = {0};
664     napi_value thisVar = nullptr;
665     CAMERA_NAPI_GET_JS_ARGS(env, info, argc, argv, thisVar);
666 
667     napi_get_undefined(env, &result);
668     VideoOutputNapi* videoOutputNapi = nullptr;
669     status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&videoOutputNapi));
670     if (status == napi_ok && videoOutputNapi != nullptr) {
671         int32_t imageRotation;
672         napi_status ret = napi_get_value_int32(env, argv[PARAM0], &imageRotation);
673         if (ret != napi_ok) {
674             CameraNapiUtils::ThrowError(env, INVALID_ARGUMENT,
675                 "GetVideoRotation parameter missing or parameter type incorrect.");
676             return result;
677         }
678         int32_t retCode = videoOutputNapi->videoOutput_->GetVideoRotation(imageRotation);
679         if (retCode == SERVICE_FATL_ERROR) {
680             CameraNapiUtils::ThrowError(env, SERVICE_FATL_ERROR,
681                 "GetVideoRotation Camera service fatal error.");
682             return result;
683         }
684         napi_create_int32(env, retCode, &result);
685         MEDIA_INFO_LOG("VideoOutputNapi GetVideoRotation! %{public}d", retCode);
686     } else {
687         MEDIA_ERR_LOG("VideoOutputNapi GetVideoRotation! called failed!");
688     }
689     return result;
690 }
691 
IsMirrorSupported(napi_env env,napi_callback_info info)692 napi_value VideoOutputNapi::IsMirrorSupported(napi_env env, napi_callback_info info)
693 {
694     auto result = CameraNapiUtils::GetUndefinedValue(env);
695     if (!CameraNapiSecurity::CheckSystemApp(env)) {
696         MEDIA_ERR_LOG("SystemApi IsMirrorSupported is called!");
697         return result;
698     }
699     MEDIA_DEBUG_LOG("VideoOutputNapi::IsMirrorSupported is called");
700 
701     VideoOutputNapi* videoOutputNapi = nullptr;
702     CameraNapiParamParser jsParamParser(env, info, videoOutputNapi);
703     if (!jsParamParser.AssertStatus(INVALID_ARGUMENT, "parse parameter occur error")) {
704         MEDIA_ERR_LOG("VideoOutputNapi::IsMirrorSupported parse parameter occur error");
705         return result;
706     }
707     if (videoOutputNapi->videoOutput_ == nullptr) {
708         MEDIA_ERR_LOG("VideoOutputNapi::IsMirrorSupported get native object fail");
709         CameraNapiUtils::ThrowError(env, INVALID_ARGUMENT, "get native object fail");
710         return result;
711     }
712     bool isMirrorSupported = videoOutputNapi->videoOutput_->IsMirrorSupported();
713     if (isMirrorSupported) {
714         napi_get_boolean(env, true, &result);
715         return result;
716     }
717     MEDIA_ERR_LOG("VideoOutputNapi::IsMirrorSupported is not supported");
718     napi_get_boolean(env, false, &result);
719     return result;
720 }
721 
EnableMirror(napi_env env,napi_callback_info info)722 napi_value VideoOutputNapi::EnableMirror(napi_env env, napi_callback_info info)
723 {
724     auto result = CameraNapiUtils::GetUndefinedValue(env);
725     if (!CameraNapiSecurity::CheckSystemApp(env)) {
726         MEDIA_ERR_LOG("SystemApi EnableMirror is called!");
727         return result;
728     }
729     MEDIA_DEBUG_LOG("VideoOutputNapi::EnableMirror is called");
730     VideoOutputNapi* videoOutputNapi = nullptr;
731     bool isEnable;
732     CameraNapiParamParser jsParamParser(env, info, videoOutputNapi, isEnable);
733     if (!jsParamParser.AssertStatus(INVALID_ARGUMENT, "parse parameter occur error")) {
734         MEDIA_ERR_LOG("VideoOutputNapi::IsMirrorSupported parse parameter occur error");
735         return result;
736     }
737     if (videoOutputNapi->videoOutput_ == nullptr) {
738         MEDIA_ERR_LOG("VideoOutputNapi::IsMirrorSupported get native object fail");
739         CameraNapiUtils::ThrowError(env, INVALID_ARGUMENT, "get native object fail");
740         return result;
741     }
742 
743     int32_t retCode = videoOutputNapi->videoOutput_->enableMirror(isEnable);
744     if (!CameraNapiUtils::CheckError(env, retCode)) {
745         MEDIA_ERR_LOG("PhotoOutputNapi::EnableAutoHighQualityPhoto fail %{public}d", retCode);
746     }
747     return result;
748 }
749 
Release(napi_env env,napi_callback_info info)750 napi_value VideoOutputNapi::Release(napi_env env, napi_callback_info info)
751 {
752     MEDIA_INFO_LOG("VideoOutputNapi::Release is called");
753     std::unique_ptr<VideoOutputAsyncContext> asyncContext = std::make_unique<VideoOutputAsyncContext>(
754         "VideoOutputNapi::Release", CameraNapiUtils::IncrementAndGet(videoOutputTaskId));
755     auto asyncFunction =
756         std::make_shared<CameraNapiAsyncFunction>(env, "Release", asyncContext->callbackRef, asyncContext->deferred);
757     CameraNapiParamParser jsParamParser(env, info, asyncContext->objectInfo, asyncFunction);
758     if (!jsParamParser.AssertStatus(INVALID_ARGUMENT, "invalid argument")) {
759         MEDIA_ERR_LOG("VideoOutputNapi::Release invalid argument");
760         return nullptr;
761     }
762     asyncContext->HoldNapiValue(env, jsParamParser.GetThisVar());
763     napi_status status = napi_create_async_work(
764         env, nullptr, asyncFunction->GetResourceName(),
765         [](napi_env env, void* data) {
766             MEDIA_INFO_LOG("VideoOutputNapi::Release running on worker");
767             auto context = static_cast<VideoOutputAsyncContext*>(data);
768             CHECK_ERROR_RETURN_LOG(context->objectInfo == nullptr, "VideoOutputNapi::Release async info is nullptr");
769             CAMERA_START_ASYNC_TRACE(context->funcName, context->taskId);
770             CameraNapiWorkerQueueKeeper::GetInstance()->ConsumeWorkerQueueTask(context->queueTask, [&context]() {
771                 context->errorCode = context->objectInfo->videoOutput_->Release();
772                 context->status = context->errorCode == CameraErrorCode::SUCCESS;
773             });
774         },
775         AsyncCompleteCallback, static_cast<void*>(asyncContext.get()), &asyncContext->work);
776     if (status != napi_ok) {
777         MEDIA_ERR_LOG("Failed to create napi_create_async_work for VideoOutputNapi::Release");
778         asyncFunction->Reset();
779     } else {
780         asyncContext->queueTask =
781             CameraNapiWorkerQueueKeeper::GetInstance()->AcquireWorkerQueueTask("VideoOutputNapi::Release");
782         napi_queue_async_work_with_qos(env, asyncContext->work, napi_qos_user_initiated);
783         asyncContext.release();
784     }
785     if (asyncFunction->GetAsyncFunctionType() == ASYNC_FUN_TYPE_PROMISE) {
786         return asyncFunction->GetPromise();
787     }
788     return CameraNapiUtils::GetUndefinedValue(env);
789 }
790 
RegisterFrameStartCallbackListener(const std::string & eventName,napi_env env,napi_value callback,const std::vector<napi_value> & args,bool isOnce)791 void VideoOutputNapi::RegisterFrameStartCallbackListener(
792     const std::string& eventName, napi_env env, napi_value callback, const std::vector<napi_value>& args, bool isOnce)
793 {
794     if (videoCallback_ == nullptr) {
795         videoCallback_ = make_shared<VideoCallbackListener>(env);
796         videoOutput_->SetCallback(videoCallback_);
797     }
798     videoCallback_->SaveCallbackReference(CONST_VIDEO_FRAME_START, callback, isOnce);
799 }
800 
UnregisterFrameStartCallbackListener(const std::string & eventName,napi_env env,napi_value callback,const std::vector<napi_value> & args)801 void VideoOutputNapi::UnregisterFrameStartCallbackListener(
802     const std::string& eventName, napi_env env, napi_value callback, const std::vector<napi_value>& args)
803 {
804     if (videoCallback_ == nullptr) {
805         MEDIA_ERR_LOG("videoCallback is null");
806         return;
807     }
808     videoCallback_->RemoveCallbackRef(CONST_VIDEO_FRAME_START, callback);
809 }
810 
RegisterFrameEndCallbackListener(const std::string & eventName,napi_env env,napi_value callback,const std::vector<napi_value> & args,bool isOnce)811 void VideoOutputNapi::RegisterFrameEndCallbackListener(
812     const std::string& eventName, napi_env env, napi_value callback, const std::vector<napi_value>& args, bool isOnce)
813 {
814     if (videoCallback_ == nullptr) {
815         videoCallback_ = make_shared<VideoCallbackListener>(env);
816         videoOutput_->SetCallback(videoCallback_);
817     }
818     videoCallback_->SaveCallbackReference(CONST_VIDEO_FRAME_END, callback, isOnce);
819 }
UnregisterFrameEndCallbackListener(const std::string & eventName,napi_env env,napi_value callback,const std::vector<napi_value> & args)820 void VideoOutputNapi::UnregisterFrameEndCallbackListener(
821     const std::string& eventName, napi_env env, napi_value callback, const std::vector<napi_value>& args)
822 {
823     if (videoCallback_ == nullptr) {
824         MEDIA_ERR_LOG("videoCallback is null");
825         return;
826     }
827     videoCallback_->RemoveCallbackRef(CONST_VIDEO_FRAME_END, callback);
828 }
829 
RegisterErrorCallbackListener(const std::string & eventName,napi_env env,napi_value callback,const std::vector<napi_value> & args,bool isOnce)830 void VideoOutputNapi::RegisterErrorCallbackListener(
831     const std::string& eventName, napi_env env, napi_value callback, const std::vector<napi_value>& args, bool isOnce)
832 {
833     if (videoCallback_ == nullptr) {
834         videoCallback_ = make_shared<VideoCallbackListener>(env);
835         videoOutput_->SetCallback(videoCallback_);
836     }
837     videoCallback_->SaveCallbackReference(CONST_VIDEO_FRAME_ERROR, callback, isOnce);
838 }
839 
UnregisterErrorCallbackListener(const std::string & eventName,napi_env env,napi_value callback,const std::vector<napi_value> & args)840 void VideoOutputNapi::UnregisterErrorCallbackListener(
841     const std::string& eventName, napi_env env, napi_value callback, const std::vector<napi_value>& args)
842 {
843     if (videoCallback_ == nullptr) {
844         MEDIA_ERR_LOG("videoCallback is null");
845         return;
846     }
847     videoCallback_->RemoveCallbackRef(CONST_VIDEO_FRAME_ERROR, callback);
848 }
849 
RegisterDeferredVideoCallbackListener(const std::string & eventName,napi_env env,napi_value callback,const std::vector<napi_value> & args,bool isOnce)850 void VideoOutputNapi::RegisterDeferredVideoCallbackListener(
851     const std::string& eventName, napi_env env, napi_value callback, const std::vector<napi_value>& args, bool isOnce)
852 {
853     if (videoCallback_ == nullptr) {
854         videoCallback_ = make_shared<VideoCallbackListener>(env);
855         videoOutput_->SetCallback(videoCallback_);
856     }
857     videoCallback_->SaveCallbackReference(CONST_VIDEO_DEFERRED_ENHANCEMENT, callback, isOnce);
858 }
859 
UnregisterDeferredVideoCallbackListener(const std::string & eventName,napi_env env,napi_value callback,const std::vector<napi_value> & args)860 void VideoOutputNapi::UnregisterDeferredVideoCallbackListener(
861     const std::string& eventName, napi_env env, napi_value callback, const std::vector<napi_value>& args)
862 {
863     if (videoCallback_ == nullptr) {
864         MEDIA_ERR_LOG("videoCallback is null");
865         return;
866     }
867     videoCallback_->RemoveCallbackRef(CONST_VIDEO_DEFERRED_ENHANCEMENT, callback);
868 }
869 
GetEmitterFunctions()870 const VideoOutputNapi::EmitterFunctions& VideoOutputNapi::GetEmitterFunctions()
871 {
872     static const EmitterFunctions funMap = {
873         { CONST_VIDEO_FRAME_START, {
874             &VideoOutputNapi::RegisterFrameStartCallbackListener,
875             &VideoOutputNapi::UnregisterFrameStartCallbackListener } },
876         { CONST_VIDEO_FRAME_END, {
877             &VideoOutputNapi::RegisterFrameEndCallbackListener,
878             &VideoOutputNapi::UnregisterFrameEndCallbackListener } },
879         { CONST_VIDEO_FRAME_ERROR, {
880             &VideoOutputNapi::RegisterErrorCallbackListener,
881             &VideoOutputNapi::UnregisterErrorCallbackListener } },
882         { CONST_VIDEO_DEFERRED_ENHANCEMENT, {
883             &VideoOutputNapi::RegisterDeferredVideoCallbackListener,
884             &VideoOutputNapi::UnregisterDeferredVideoCallbackListener } }};
885     return funMap;
886 }
887 
On(napi_env env,napi_callback_info info)888 napi_value VideoOutputNapi::On(napi_env env, napi_callback_info info)
889 {
890     return ListenerTemplate<VideoOutputNapi>::On(env, info);
891 }
892 
Once(napi_env env,napi_callback_info info)893 napi_value VideoOutputNapi::Once(napi_env env, napi_callback_info info)
894 {
895     return ListenerTemplate<VideoOutputNapi>::Once(env, info);
896 }
897 
Off(napi_env env,napi_callback_info info)898 napi_value VideoOutputNapi::Off(napi_env env, napi_callback_info info)
899 {
900     return ListenerTemplate<VideoOutputNapi>::Off(env, info);
901 }
902 
IsAutoDeferredVideoEnhancementSupported(napi_env env,napi_callback_info info)903 napi_value VideoOutputNapi::IsAutoDeferredVideoEnhancementSupported(napi_env env, napi_callback_info info)
904 {
905     napi_value result = CameraNapiUtils::GetUndefinedValue(env);
906     if (!CameraNapiSecurity::CheckSystemApp(env)) {
907         MEDIA_ERR_LOG("SystemApi IsAutoDeferredVideoEnhancementSupported is called!");
908         return result;
909     }
910     MEDIA_DEBUG_LOG("VideoOutputNapi::IsAutoDeferredVideoEnhancementSupported is called");
911 
912     VideoOutputNapi* videoOutputNapi = nullptr;
913     CameraNapiParamParser jsParamParser(env, info, videoOutputNapi);
914     if (!jsParamParser.AssertStatus(SERVICE_FATL_ERROR, "parse parameter occur error")) {
915         MEDIA_ERR_LOG("VideoOutputNapi::IsAutoDeferredVideoEnhancementSupported parse parameter occur error");
916         return result;
917     }
918     if (videoOutputNapi->videoOutput_ == nullptr) {
919         MEDIA_ERR_LOG("VideoOutputNapi::IsAutoDeferredVideoEnhancementSupported get native object fail");
920         CameraNapiUtils::ThrowError(env, SERVICE_FATL_ERROR, "get native object fail");
921         return result;
922     }
923     int32_t res = videoOutputNapi->videoOutput_->IsAutoDeferredVideoEnhancementSupported();
924     if (res > 1) {
925         CameraNapiUtils::ThrowError(env, SERVICE_FATL_ERROR, "inner fail");
926         return result;
927     }
928     napi_get_boolean(env, res, &result);
929     return result;
930 }
931 
IsAutoDeferredVideoEnhancementEnabled(napi_env env,napi_callback_info info)932 napi_value VideoOutputNapi::IsAutoDeferredVideoEnhancementEnabled(napi_env env, napi_callback_info info)
933 {
934     napi_value result = CameraNapiUtils::GetUndefinedValue(env);
935     if (!CameraNapiSecurity::CheckSystemApp(env)) {
936         MEDIA_ERR_LOG("SystemApi IsAutoDeferredVideoEnhancementEnabled is called!");
937         return result;
938     }
939     MEDIA_DEBUG_LOG("VideoOutputNapi::IsAutoDeferredVideoEnhancementEnabled is called");
940 
941     VideoOutputNapi* videoOutputNapi = nullptr;
942     CameraNapiParamParser jsParamParser(env, info, videoOutputNapi);
943     if (!jsParamParser.AssertStatus(SERVICE_FATL_ERROR, "parse parameter occur error")) {
944         MEDIA_ERR_LOG("VideoOutputNapi::IsAutoDeferredVideoEnhancementEnabled parse parameter occur error");
945         return result;
946     }
947     if (videoOutputNapi->videoOutput_ == nullptr) {
948         MEDIA_ERR_LOG("VideoOutputNapi::IsAutoDeferredVideoEnhancementEnabled get native object fail");
949         CameraNapiUtils::ThrowError(env, SERVICE_FATL_ERROR, "get native object fail");
950         return result;
951     }
952     int32_t res = videoOutputNapi->videoOutput_->IsAutoDeferredVideoEnhancementEnabled();
953     if (res > 1) {
954         CameraNapiUtils::ThrowError(env, SERVICE_FATL_ERROR, "inner fail");
955         return result;
956     }
957     napi_get_boolean(env, res, &result);
958     return result;
959 }
960 
EnableAutoDeferredVideoEnhancement(napi_env env,napi_callback_info info)961 napi_value VideoOutputNapi::EnableAutoDeferredVideoEnhancement(napi_env env, napi_callback_info info)
962 {
963     napi_value result = CameraNapiUtils::GetUndefinedValue(env);
964     if (!CameraNapiSecurity::CheckSystemApp(env)) {
965         MEDIA_ERR_LOG("SystemApi EnableAutoDeferredVideoEnhancement is called!");
966         return result;
967     }
968     napi_status status;
969     size_t argc = ARGS_ONE;
970     napi_value argv[ARGS_ONE] = {0};
971     napi_value thisVar = nullptr;
972     CAMERA_NAPI_GET_JS_ARGS(env, info, argc, argv, thisVar);
973     if (argc != ARGS_ONE) {
974         CameraNapiUtils::ThrowError(env, INVALID_ARGUMENT, "requires one parameter");
975         return result;
976     }
977     int32_t res = 0;
978     napi_get_undefined(env, &result);
979     VideoOutputNapi* videoOutputNapi = nullptr;
980     status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&videoOutputNapi));
981     if (status == napi_ok && videoOutputNapi != nullptr) {
982         bool isEnable;
983         napi_get_value_bool(env, argv[PARAM0], &isEnable);
984         res = videoOutputNapi->videoOutput_->EnableAutoDeferredVideoEnhancement(isEnable);
985     }
986     if (res > 0) {
987         CameraNapiUtils::ThrowError(env, SERVICE_FATL_ERROR, "inner fail");
988     }
989     return result;
990 }
991 
GetSupportedRotations(napi_env env,napi_callback_info info)992 napi_value VideoOutputNapi::GetSupportedRotations(napi_env env, napi_callback_info info)
993 {
994     napi_value result = CameraNapiUtils::GetUndefinedValue(env);
995     if (!CameraNapiSecurity::CheckSystemApp(env)) {
996         MEDIA_ERR_LOG("SystemApi GetSupportedRotations is called!");
997         return result;
998     }
999     MEDIA_DEBUG_LOG("VideoOutputNapi::GetSupportedRotations is called");
1000 
1001     VideoOutputNapi* videoOutputNapi = nullptr;
1002     CameraNapiParamParser jsParamParser(env, info, videoOutputNapi);
1003     if (!jsParamParser.AssertStatus(SERVICE_FATL_ERROR, "parse parameter occur error")) {
1004         MEDIA_ERR_LOG("VideoOutputNapi::GetSupportedRotations parse parameter occur error");
1005         return result;
1006     }
1007     if (videoOutputNapi->videoOutput_ == nullptr) {
1008         MEDIA_ERR_LOG("VideoOutputNapi::GetSupportedRotations get native object fail");
1009         CameraNapiUtils::ThrowError(env, SERVICE_FATL_ERROR, "get native object fail");
1010         return result;
1011     }
1012     std::vector<int32_t> supportedRotations;
1013     int32_t retCode = videoOutputNapi->videoOutput_->GetSupportedRotations(supportedRotations);
1014     if (!CameraNapiUtils::CheckError(env, retCode)) {
1015         return nullptr;
1016     }
1017     napi_status status = napi_create_array(env, &result);
1018     CHECK_ERROR_RETURN_RET_LOG(status != napi_ok, result, "napi_create_array call Failed!");
1019     for (size_t i = 0; i < supportedRotations.size(); i++) {
1020         int32_t value = supportedRotations[i];
1021         napi_value element;
1022         napi_create_int32(env, value, &element);
1023         napi_set_element(env, result, i, element);
1024     }
1025     return result;
1026 }
1027 
IsRotationSupported(napi_env env,napi_callback_info info)1028 napi_value VideoOutputNapi::IsRotationSupported(napi_env env, napi_callback_info info)
1029 {
1030     napi_value result = CameraNapiUtils::GetUndefinedValue(env);
1031     if (!CameraNapiSecurity::CheckSystemApp(env)) {
1032         MEDIA_ERR_LOG("SystemApi IsRotationSupported is called!");
1033         return result;
1034     }
1035     MEDIA_DEBUG_LOG("VideoOutputNapi::IsRotationSupported is called");
1036 
1037     VideoOutputNapi* videoOutputNapi = nullptr;
1038     CameraNapiParamParser jsParamParser(env, info, videoOutputNapi);
1039     if (!jsParamParser.AssertStatus(SERVICE_FATL_ERROR, "parse parameter occur error")) {
1040         MEDIA_ERR_LOG("VideoOutputNapi::IsRotationSupported parse parameter occur error");
1041         return result;
1042     }
1043     if (videoOutputNapi->videoOutput_ == nullptr) {
1044         MEDIA_ERR_LOG("VideoOutputNapi::IsRotationSupported get native object fail");
1045         CameraNapiUtils::ThrowError(env, SERVICE_FATL_ERROR, "get native object fail");
1046         return result;
1047     }
1048     bool isSupported = false;
1049     int32_t retCode = videoOutputNapi->videoOutput_->IsRotationSupported(isSupported);
1050     if (!CameraNapiUtils::CheckError(env, retCode)) {
1051         MEDIA_ERR_LOG("VideoOutputNapi::IsRotationSupported fail %{public}d", retCode);
1052     }
1053     napi_get_boolean(env, isSupported, &result);
1054     return result;
1055 }
1056 
SetRotation(napi_env env,napi_callback_info info)1057 napi_value VideoOutputNapi::SetRotation(napi_env env, napi_callback_info info)
1058 {
1059     napi_value result = CameraNapiUtils::GetUndefinedValue(env);
1060     if (!CameraNapiSecurity::CheckSystemApp(env)) {
1061         MEDIA_ERR_LOG("SystemApi SetRotation is called!");
1062         return result;
1063     }
1064     MEDIA_DEBUG_LOG("VideoOutputNapi::SetRotation is called");
1065     VideoOutputNapi* videoOutputNapi = nullptr;
1066     int32_t rotation;
1067     CameraNapiParamParser jsParamParser(env, info, videoOutputNapi, rotation);
1068     if (!jsParamParser.AssertStatus(INVALID_ARGUMENT, "parse parameter occur error")) {
1069         MEDIA_ERR_LOG("VideoOutputNapi::SetRotation parse parameter occur error");
1070         return result;
1071     }
1072     if (videoOutputNapi->videoOutput_ == nullptr) {
1073         MEDIA_ERR_LOG("VideoOutputNapi::SetRotation get native object fail");
1074         CameraNapiUtils::ThrowError(env, INVALID_ARGUMENT, "get native object fail");
1075         return result;
1076     }
1077     int32_t retCode = videoOutputNapi->videoOutput_->SetRotation(rotation);
1078     if (!CameraNapiUtils::CheckError(env, retCode)) {
1079         MEDIA_ERR_LOG("VideoOutputNapi::SetRotation fail %{public}d", retCode);
1080     }
1081     return result;
1082 }
1083 } // namespace CameraStandard
1084 } // namespace OHOS
1085