1 /*
2 * Copyright (c) 2023-2023 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 <uv.h>
17
18 #include "mode/video_session_for_sys_napi.h"
19 #include "ability/camera_ability_napi.h"
20 #include "napi/native_common.h"
21 #include "camera_napi_object_types.h"
22
23 namespace OHOS {
24 namespace CameraStandard {
25 using namespace std;
26
27 thread_local napi_ref VideoSessionForSysNapi::sConstructor_ = nullptr;
28
VideoSessionForSysNapi()29 VideoSessionForSysNapi::VideoSessionForSysNapi() : env_(nullptr)
30 {
31 }
~VideoSessionForSysNapi()32 VideoSessionForSysNapi::~VideoSessionForSysNapi()
33 {
34 MEDIA_DEBUG_LOG("~VideoSessionForSysNapi is called");
35 }
VideoSessionForSysNapiDestructor(napi_env env,void * nativeObject,void * finalize_hint)36 void VideoSessionForSysNapi::VideoSessionForSysNapiDestructor(napi_env env, void* nativeObject, void* finalize_hint)
37 {
38 MEDIA_DEBUG_LOG("VideoSessionForSysNapiDestructor is called");
39 VideoSessionForSysNapi* cameraObj = reinterpret_cast<VideoSessionForSysNapi*>(nativeObject);
40 if (cameraObj != nullptr) {
41 delete cameraObj;
42 }
43 }
Init(napi_env env,napi_value exports)44 napi_value VideoSessionForSysNapi::Init(napi_env env, napi_value exports)
45 {
46 MEDIA_DEBUG_LOG("Init is called");
47 napi_status status;
48 napi_value ctorObj;
49
50 std::vector<std::vector<napi_property_descriptor>> descriptors = { camera_process_props, flash_props,
51 auto_exposure_props, focus_props, zoom_props, filter_props, beauty_props, color_effect_props, macro_props,
52 color_management_props, stabilization_props, preconfig_props, camera_output_capability_props,
53 camera_ability_props, aperture_props, color_reservation_props };
54 std::vector<napi_property_descriptor> video_session_props = CameraNapiUtils::GetPropertyDescriptor(descriptors);
55 status = napi_define_class(env, VIDEO_SESSION_FOR_SYS_NAPI_CLASS_NAME, NAPI_AUTO_LENGTH,
56 VideoSessionForSysNapiConstructor, nullptr,
57 video_session_props.size(),
58 video_session_props.data(), &ctorObj);
59 if (status == napi_ok) {
60 int32_t refCount = 1;
61 status = napi_create_reference(env, ctorObj, refCount, &sConstructor_);
62 if (status == napi_ok) {
63 status = napi_set_named_property(env, exports, VIDEO_SESSION_FOR_SYS_NAPI_CLASS_NAME, ctorObj);
64 if (status == napi_ok) {
65 return exports;
66 }
67 }
68 }
69 MEDIA_ERR_LOG("Init call Failed!");
70 return nullptr;
71 }
72
CreateCameraSession(napi_env env)73 napi_value VideoSessionForSysNapi::CreateCameraSession(napi_env env)
74 {
75 MEDIA_DEBUG_LOG("CreateCameraSession is called");
76 CAMERA_SYNC_TRACE;
77 napi_status status;
78 napi_value result = nullptr;
79 napi_value constructor;
80 status = napi_get_reference_value(env, sConstructor_, &constructor);
81 if (status == napi_ok) {
82 sCameraSession_ = CameraManager::GetInstance()->CreateCaptureSession(SceneMode::VIDEO);
83 if (sCameraSession_ == nullptr) {
84 MEDIA_ERR_LOG("Failed to create Video session instance");
85 napi_get_undefined(env, &result);
86 return result;
87 }
88 status = napi_new_instance(env, constructor, 0, nullptr, &result);
89 sCameraSession_ = nullptr;
90 if (status == napi_ok && result != nullptr) {
91 MEDIA_DEBUG_LOG("success to create Video session napi instance");
92 return result;
93 } else {
94 MEDIA_ERR_LOG("Failed to create Video session napi instance");
95 }
96 }
97 MEDIA_ERR_LOG("Failed to create Video session napi instance last");
98 napi_get_undefined(env, &result);
99 return result;
100 }
101
VideoSessionForSysNapiConstructor(napi_env env,napi_callback_info info)102 napi_value VideoSessionForSysNapi::VideoSessionForSysNapiConstructor(napi_env env, napi_callback_info info)
103 {
104 MEDIA_DEBUG_LOG("VideoSessionForSysNapiConstructor is called");
105 napi_status status;
106 napi_value result = nullptr;
107 napi_value thisVar = nullptr;
108
109 napi_get_undefined(env, &result);
110 CAMERA_NAPI_GET_JS_OBJ_WITH_ZERO_ARGS(env, info, status, thisVar);
111
112 if (status == napi_ok && thisVar != nullptr) {
113 std::unique_ptr<VideoSessionForSysNapi> obj = std::make_unique<VideoSessionForSysNapi>();
114 obj->env_ = env;
115 if (sCameraSession_ == nullptr) {
116 MEDIA_ERR_LOG("sCameraSession_ is null");
117 return result;
118 }
119 obj->videoSession_ = static_cast<VideoSession*>(sCameraSession_.GetRefPtr());
120 obj->cameraSession_ = obj->videoSession_;
121 if (obj->videoSession_ == nullptr) {
122 MEDIA_ERR_LOG("videoSession_ is null");
123 return result;
124 }
125 status = napi_wrap(env, thisVar, reinterpret_cast<void*>(obj.get()),
126 VideoSessionForSysNapi::VideoSessionForSysNapiDestructor, nullptr, nullptr);
127 if (status == napi_ok) {
128 obj.release();
129 return thisVar;
130 } else {
131 MEDIA_ERR_LOG("VideoSessionForSysNapi Failure wrapping js to native napi");
132 }
133 }
134 MEDIA_ERR_LOG("VideoSessionForSysNapi call Failed!");
135 return result;
136 }
137
RegisterFocusTrackingInfoCallbackListener(const std::string & eventName,napi_env env,napi_value callback,const std::vector<napi_value> & args,bool isOnce)138 void VideoSessionForSysNapi::RegisterFocusTrackingInfoCallbackListener(const std::string& eventName,
139 napi_env env, napi_value callback, const std::vector<napi_value>& args, bool isOnce)
140 {
141 MEDIA_DEBUG_LOG("%{public}s is called", __FUNCTION__);
142 CHECK_ERROR_RETURN_LOG(videoSession_ == nullptr, "%{public}s videoSession is nullptr!", __FUNCTION__);
143 if (focusTrackingInfoCallback_ == nullptr) {
144 focusTrackingInfoCallback_ = std::make_shared<FocusTrackingCallbackListener>(env);
145 videoSession_->SetFocusTrackingInfoCallback(focusTrackingInfoCallback_);
146 }
147 focusTrackingInfoCallback_->SaveCallbackReference(eventName, callback, isOnce);
148 }
149
UnregisterFocusTrackingInfoCallbackListener(const std::string & eventName,napi_env env,napi_value callback,const std::vector<napi_value> & args)150 void VideoSessionForSysNapi::UnregisterFocusTrackingInfoCallbackListener(const std::string& eventName,
151 napi_env env, napi_value callback, const std::vector<napi_value>& args)
152 {
153 MEDIA_DEBUG_LOG("%{public}s is called", __FUNCTION__);
154 CHECK_ERROR_RETURN_LOG(focusTrackingInfoCallback_ == nullptr,
155 "%{public}s focusTrackingInfoCallback_ is nullptr", __FUNCTION__);
156 focusTrackingInfoCallback_->RemoveCallbackRef(eventName, callback);
157 }
158
OnFocusTrackingInfoAvailable(FocusTrackingInfo & focusTrackingInfo) const159 void FocusTrackingCallbackListener::OnFocusTrackingInfoAvailable(FocusTrackingInfo &focusTrackingInfo) const
160 {
161 MEDIA_DEBUG_LOG("%{public}s is called", __FUNCTION__);
162 OnFocusTrackingInfoCallbackAsync(focusTrackingInfo);
163 }
164
OnFocusTrackingInfoCallbackAsync(FocusTrackingInfo & focusTrackingInfo) const165 void FocusTrackingCallbackListener::OnFocusTrackingInfoCallbackAsync(FocusTrackingInfo &focusTrackingInfo) const
166 {
167 MEDIA_DEBUG_LOG("%{public}s is called", __FUNCTION__);
168
169 uv_loop_s* loop = nullptr;
170 napi_get_uv_event_loop(env_, &loop);
171 CHECK_ERROR_RETURN_LOG(!loop, "%{public}s: failed to get event loop", __FUNCTION__);
172
173 uv_work_t* work = new(std::nothrow) uv_work_t;
174 CHECK_ERROR_RETURN_LOG(!work, "%{public}s: failed to allocate work", __FUNCTION__);
175
176 std::unique_ptr<FocusTrackingCallbackInfo> callback =
177 std::make_unique<FocusTrackingCallbackInfo>(focusTrackingInfo, shared_from_this());
178 work->data = callback.get();
179 int ret = uv_queue_work_with_qos(
180 loop, work, [] (uv_work_t* work) {},
181 [] (uv_work_t* work, int status) {
182 FocusTrackingCallbackInfo* callback = reinterpret_cast<FocusTrackingCallbackInfo *>(work->data);
183 if (callback) {
184 auto listener = callback->listener_.lock();
185 if (listener != nullptr) {
186 listener->OnFocusTrackingInfoCallback(callback->focusTrackingInfo_);
187 }
188 delete callback;
189 }
190 delete work;
191 }, uv_qos_user_initiated);
192 if (ret) {
193 MEDIA_ERR_LOG("%{public}s: failed to execute work", __FUNCTION__);
194 delete work;
195 } else {
196 callback.release();
197 }
198 }
199
OnFocusTrackingInfoCallback(FocusTrackingInfo & focusTrackingInfo) const200 void FocusTrackingCallbackListener::OnFocusTrackingInfoCallback(FocusTrackingInfo &focusTrackingInfo) const
201 {
202 MEDIA_DEBUG_LOG("%{public}s is called", __FUNCTION__);
203
204 napi_value result[ARGS_ONE] = { nullptr };
205 napi_value retVal = nullptr;
206
207 result[PARAM0] = CameraNapiFocusTrackingInfo(focusTrackingInfo).GenerateNapiValue(env_);
208
209 ExecuteCallbackNapiPara callbackNapiPara { .recv = nullptr, .argc = ARGS_ONE, .argv = result, .result = &retVal };
210 ExecuteCallback("focusTrackingInfoAvailable", callbackNapiPara);
211 }
212 } // namespace CameraStandard
213 } // namespace OHOS
214