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, effect_suggestion_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 CHECK_ERROR_RETURN_RET(status == napi_ok, exports);
65 }
66 }
67 MEDIA_ERR_LOG("Init call Failed!");
68 return nullptr;
69 }
70
CreateCameraSession(napi_env env)71 napi_value VideoSessionForSysNapi::CreateCameraSession(napi_env env)
72 {
73 MEDIA_DEBUG_LOG("CreateCameraSession is called");
74 CAMERA_SYNC_TRACE;
75 napi_status status;
76 napi_value result = nullptr;
77 napi_value constructor;
78 status = napi_get_reference_value(env, sConstructor_, &constructor);
79 if (status == napi_ok) {
80 sCameraSession_ = CameraManager::GetInstance()->CreateCaptureSession(SceneMode::VIDEO);
81 if (sCameraSession_ == nullptr) {
82 MEDIA_ERR_LOG("Failed to create Video session instance");
83 napi_get_undefined(env, &result);
84 return result;
85 }
86 status = napi_new_instance(env, constructor, 0, nullptr, &result);
87 sCameraSession_ = nullptr;
88 if (status == napi_ok && result != nullptr) {
89 MEDIA_DEBUG_LOG("success to create Video session napi instance");
90 return result;
91 } else {
92 MEDIA_ERR_LOG("Failed to create Video session napi instance");
93 }
94 }
95 MEDIA_ERR_LOG("Failed to create Video session napi instance last");
96 napi_get_undefined(env, &result);
97 return result;
98 }
99
VideoSessionForSysNapiConstructor(napi_env env,napi_callback_info info)100 napi_value VideoSessionForSysNapi::VideoSessionForSysNapiConstructor(napi_env env, napi_callback_info info)
101 {
102 MEDIA_DEBUG_LOG("VideoSessionForSysNapiConstructor is called");
103 napi_status status;
104 napi_value result = nullptr;
105 napi_value thisVar = nullptr;
106
107 napi_get_undefined(env, &result);
108 CAMERA_NAPI_GET_JS_OBJ_WITH_ZERO_ARGS(env, info, status, thisVar);
109
110 if (status == napi_ok && thisVar != nullptr) {
111 std::unique_ptr<VideoSessionForSysNapi> obj = std::make_unique<VideoSessionForSysNapi>();
112 obj->env_ = env;
113 CHECK_ERROR_RETURN_RET_LOG(sCameraSession_ == nullptr, result, "sCameraSession_ is null");
114 obj->videoSession_ = static_cast<VideoSession*>(sCameraSession_.GetRefPtr());
115 obj->cameraSession_ = obj->videoSession_;
116 CHECK_ERROR_RETURN_RET_LOG(obj->videoSession_ == nullptr, result, "videoSession_ is null");
117 status = napi_wrap(env, thisVar, reinterpret_cast<void*>(obj.get()),
118 VideoSessionForSysNapi::VideoSessionForSysNapiDestructor, nullptr, nullptr);
119 if (status == napi_ok) {
120 obj.release();
121 return thisVar;
122 } else {
123 MEDIA_ERR_LOG("VideoSessionForSysNapi Failure wrapping js to native napi");
124 }
125 }
126 MEDIA_ERR_LOG("VideoSessionForSysNapi call Failed!");
127 return result;
128 }
129
RegisterFocusTrackingInfoCallbackListener(const std::string & eventName,napi_env env,napi_value callback,const std::vector<napi_value> & args,bool isOnce)130 void VideoSessionForSysNapi::RegisterFocusTrackingInfoCallbackListener(const std::string& eventName,
131 napi_env env, napi_value callback, const std::vector<napi_value>& args, bool isOnce)
132 {
133 MEDIA_DEBUG_LOG("%{public}s is called", __FUNCTION__);
134 CHECK_ERROR_RETURN_LOG(videoSession_ == nullptr, "%{public}s videoSession is nullptr!", __FUNCTION__);
135 if (focusTrackingInfoCallback_ == nullptr) {
136 focusTrackingInfoCallback_ = std::make_shared<FocusTrackingCallbackListener>(env);
137 videoSession_->SetFocusTrackingInfoCallback(focusTrackingInfoCallback_);
138 }
139 focusTrackingInfoCallback_->SaveCallbackReference(eventName, callback, isOnce);
140 }
141
UnregisterFocusTrackingInfoCallbackListener(const std::string & eventName,napi_env env,napi_value callback,const std::vector<napi_value> & args)142 void VideoSessionForSysNapi::UnregisterFocusTrackingInfoCallbackListener(const std::string& eventName,
143 napi_env env, napi_value callback, const std::vector<napi_value>& args)
144 {
145 MEDIA_DEBUG_LOG("%{public}s is called", __FUNCTION__);
146 CHECK_ERROR_RETURN_LOG(focusTrackingInfoCallback_ == nullptr,
147 "%{public}s focusTrackingInfoCallback_ is nullptr", __FUNCTION__);
148 focusTrackingInfoCallback_->RemoveCallbackRef(eventName, callback);
149 }
150
OnFocusTrackingInfoAvailable(FocusTrackingInfo & focusTrackingInfo) const151 void FocusTrackingCallbackListener::OnFocusTrackingInfoAvailable(FocusTrackingInfo &focusTrackingInfo) const
152 {
153 MEDIA_DEBUG_LOG("%{public}s is called", __FUNCTION__);
154 OnFocusTrackingInfoCallbackAsync(focusTrackingInfo);
155 }
156
OnFocusTrackingInfoCallbackAsync(FocusTrackingInfo & focusTrackingInfo) const157 void FocusTrackingCallbackListener::OnFocusTrackingInfoCallbackAsync(FocusTrackingInfo &focusTrackingInfo) const
158 {
159 MEDIA_DEBUG_LOG("%{public}s is called", __FUNCTION__);
160 std::unique_ptr<FocusTrackingCallbackInfo> callback =
161 std::make_unique<FocusTrackingCallbackInfo>(focusTrackingInfo, shared_from_this());
162 FocusTrackingCallbackInfo *event = callback.get();
163 auto task = [event] () {
164 FocusTrackingCallbackInfo* callback = reinterpret_cast<FocusTrackingCallbackInfo *>(event);
165 if (callback) {
166 auto listener = callback->listener_.lock();
167 if (listener != nullptr) {
168 listener->OnFocusTrackingInfoCallback(callback->focusTrackingInfo_);
169 }
170 delete callback;
171 }
172 };
173 if (napi_ok != napi_send_event(env_, task, napi_eprio_immediate)) {
174 MEDIA_ERR_LOG("%{public}s: failed to execute work", __FUNCTION__);
175 } else {
176 callback.release();
177 }
178 }
179
OnFocusTrackingInfoCallback(FocusTrackingInfo & focusTrackingInfo) const180 void FocusTrackingCallbackListener::OnFocusTrackingInfoCallback(FocusTrackingInfo &focusTrackingInfo) const
181 {
182 MEDIA_DEBUG_LOG("%{public}s is called", __FUNCTION__);
183
184 napi_value result[ARGS_ONE] = { nullptr };
185 napi_value retVal = nullptr;
186
187 result[PARAM0] = CameraNapiFocusTrackingInfo(focusTrackingInfo).GenerateNapiValue(env_);
188
189 ExecuteCallbackNapiPara callbackNapiPara { .recv = nullptr, .argc = ARGS_ONE, .argv = result, .result = &retVal };
190 ExecuteCallback("focusTrackingInfoAvailable", callbackNapiPara);
191 }
192
RegisterLightStatusCallbackListener(const std::string & eventName,napi_env env,napi_value callback,const std::vector<napi_value> & args,bool isOnce)193 void VideoSessionForSysNapi::RegisterLightStatusCallbackListener(
194 const std::string& eventName, napi_env env, napi_value callback, const std::vector<napi_value>& args, bool isOnce)
195 {
196 MEDIA_INFO_LOG("VideoSessionForSysNapi::RegisterLightStatusCallbackListener called");
197 if (lightStatusCallback_ == nullptr) {
198 lightStatusCallback_ = std::make_shared<LightStatusCallbackListener>(env);
199 videoSession_->SetLightStatusCallback(lightStatusCallback_);
200 videoSession_->SetLightStatus(0);
201 }
202 lightStatusCallback_->SaveCallbackReference(eventName, callback, isOnce);
203 }
204
UnregisterLightStatusCallbackListener(const std::string & eventName,napi_env env,napi_value callback,const std::vector<napi_value> & args)205 void VideoSessionForSysNapi::UnregisterLightStatusCallbackListener(
206 const std::string& eventName, napi_env env, napi_value callback, const std::vector<napi_value>& args)
207 {
208 MEDIA_INFO_LOG("VideoSessionForSysNapi::UnregisterLightStatusCallbackListener is called");
209 if (lightStatusCallback_ == nullptr) {
210 MEDIA_DEBUG_LOG("abilityCallback is null");
211 } else {
212 lightStatusCallback_->RemoveCallbackRef(eventName, callback);
213 }
214 }
215
OnLightStatusChangedCallbackAsync(LightStatus & status) const216 void LightStatusCallbackListener::OnLightStatusChangedCallbackAsync(LightStatus &status) const
217 {
218 MEDIA_INFO_LOG("OnLightStatusChangedCallbackAsync is called");
219 std::unique_ptr<LightStatusChangedCallback> callback =
220 std::make_unique<LightStatusChangedCallback>(status, shared_from_this());
221 LightStatusChangedCallback *event = callback.get();
222 auto task = [event] () {
223 LightStatusChangedCallback* callback = reinterpret_cast<LightStatusChangedCallback *>(event);
224 if (callback) {
225 MEDIA_DEBUG_LOG("the light status is %{public}d", callback->status_.status);
226 auto listener = callback->listener_.lock();
227 if (listener != nullptr) {
228 listener->OnLightStatusChangedCallback(callback->status_);
229 }
230 delete callback;
231 }
232 };
233 if (napi_ok != napi_send_event(env_, task, napi_eprio_immediate)) {
234 MEDIA_ERR_LOG("failed to execute work");
235 } else {
236 callback.release();
237 }
238 }
239
OnLightStatusChangedCallback(LightStatus & status) const240 void LightStatusCallbackListener::OnLightStatusChangedCallback(LightStatus &status) const
241 {
242 MEDIA_DEBUG_LOG("OnLightStatusChangedCallback is called, light status is %{public}d", status.status);
243 ExecuteCallbackScopeSafe("lightStatusChange", [&]() {
244 napi_value errCode = CameraNapiUtils::GetUndefinedValue(env_);
245 napi_value result;
246 napi_create_uint32(env_, status.status, &result);
247 return ExecuteCallbackData(env_, errCode, result);
248 });
249 }
250
OnLightStatusChanged(LightStatus & status)251 void LightStatusCallbackListener::OnLightStatusChanged(LightStatus &status)
252 {
253 MEDIA_DEBUG_LOG("OnLightStatusChanged is called, lightStatus: %{public}d", status.status);
254 OnLightStatusChangedCallbackAsync(status);
255 }
256 } // namespace CameraStandard
257 } // namespace OHOS
258