1 /*
2 * Copyright (c) 2024-2024 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 "camera_napi_security_utils.h"
17 #include "camera_napi_param_parser.h"
18 #include "uv.h"
19 #include "mode/slow_motion_session_napi.h"
20
21 namespace OHOS {
22 namespace CameraStandard {
23 using namespace std;
24
25 thread_local napi_ref SlowMotionSessionNapi::sConstructor_ = nullptr;
26
OnSlowMotionStateCbAsync(const SlowMotionState state) const27 void SlowMotionStateListener::OnSlowMotionStateCbAsync(const SlowMotionState state) const
28 {
29 MEDIA_DEBUG_LOG("OnSlowMotionStateCbAsync is called");
30 uv_loop_s* loop = nullptr;
31 napi_get_uv_event_loop(env_, &loop);
32 if (!loop) {
33 MEDIA_ERR_LOG("failed to get event loop");
34 return;
35 }
36 uv_work_t* work = new(std::nothrow) uv_work_t;
37 if (!work) {
38 MEDIA_ERR_LOG("failed to allocate work");
39 return;
40 }
41 std::unique_ptr<SlowMotionStateListenerInfo> callbackInfo =
42 std::make_unique<SlowMotionStateListenerInfo>(state, this);
43 work->data = callbackInfo.get();
44 int ret = uv_queue_work_with_qos(loop, work, [] (uv_work_t* work) {}, [] (uv_work_t* work, int status) {
45 SlowMotionStateListenerInfo* callbackInfo = reinterpret_cast<SlowMotionStateListenerInfo *>(work->data);
46 if (callbackInfo) {
47 callbackInfo->listener_->OnSlowMotionStateCb(callbackInfo->state_);
48 delete callbackInfo;
49 }
50 delete work;
51 }, uv_qos_user_initiated);
52 if (ret) {
53 MEDIA_ERR_LOG("failed to execute work");
54 delete work;
55 } else {
56 callbackInfo.release();
57 }
58 }
59
OnSlowMotionStateCb(const SlowMotionState state) const60 void SlowMotionStateListener::OnSlowMotionStateCb(const SlowMotionState state) const
61 {
62 MEDIA_DEBUG_LOG("OnSlowMotionStateCb is called, state: %{public}d", state);
63 napi_value result[ARGS_TWO] = {nullptr, nullptr};
64 napi_value retVal;
65 napi_get_undefined(env_, &result[PARAM0]);
66 napi_create_int32(env_, state, &result[PARAM1]);
67 ExecuteCallbackNapiPara callbackNapiPara { .recv = nullptr, .argc = ARGS_TWO, .argv = result, .result = &retVal };
68 ExecuteCallback("slowMotionStatus", callbackNapiPara);
69 }
70
OnSlowMotionState(SlowMotionState state)71 void SlowMotionStateListener::OnSlowMotionState(SlowMotionState state)
72 {
73 OnSlowMotionStateCbAsync(state);
74 }
75
SlowMotionSessionNapi()76 SlowMotionSessionNapi::SlowMotionSessionNapi() : env_(nullptr)
77 {
78 }
79
~SlowMotionSessionNapi()80 SlowMotionSessionNapi::~SlowMotionSessionNapi()
81 {
82 MEDIA_DEBUG_LOG("~SlowMotionSessionNapi is called");
83 }
84
SlowMotionSessionNapiDestructor(napi_env env,void * nativeObject,void * finalize_hint)85 void SlowMotionSessionNapi::SlowMotionSessionNapiDestructor(napi_env env, void* nativeObject, void* finalize_hint)
86 {
87 MEDIA_DEBUG_LOG("SlowMotionSessionNapiDestructor is called");
88 SlowMotionSessionNapi* cameraObj = reinterpret_cast<SlowMotionSessionNapi*>(nativeObject);
89 if (cameraObj != nullptr) {
90 delete cameraObj;
91 }
92 }
93
Init(napi_env env,napi_value exports)94 napi_value SlowMotionSessionNapi::Init(napi_env env, napi_value exports)
95 {
96 MEDIA_DEBUG_LOG("Init is called");
97 napi_status status;
98 napi_value ctorObj;
99 std::vector<napi_property_descriptor> slow_motion_props = {
100 DECLARE_NAPI_FUNCTION("isSlowMotionDetectionSupported", IsSlowMotionDetectionSupported),
101 DECLARE_NAPI_FUNCTION("setSlowMotionDetectionArea", SetSlowMotionDetectionArea)
102 };
103 std::vector<std::vector<napi_property_descriptor>> descriptors = {camera_process_props, flash_props,
104 auto_exposure_props, focus_props, zoom_props, filter_props, slow_motion_props};
105 std::vector<napi_property_descriptor> slow_motion_session_props =
106 CameraNapiUtils::GetPropertyDescriptor(descriptors);
107 status = napi_define_class(env, SLOW_MOTION_SESSION_NAPI_CLASS_NAME, NAPI_AUTO_LENGTH,
108 SlowMotionSessionNapiConstructor, nullptr,
109 slow_motion_session_props.size(),
110 slow_motion_session_props.data(), &ctorObj);
111 if (status == napi_ok) {
112 int32_t refCount = 1;
113 status = napi_create_reference(env, ctorObj, refCount, &sConstructor_);
114 if (status == napi_ok) {
115 status = napi_set_named_property(env, exports, SLOW_MOTION_SESSION_NAPI_CLASS_NAME, ctorObj);
116 if (status == napi_ok) {
117 return exports;
118 }
119 } else {
120 MEDIA_ERR_LOG("napi_create_reference Failed!");
121 }
122 }
123 MEDIA_ERR_LOG("Init call Failed!");
124 return nullptr;
125 }
126
CreateCameraSession(napi_env env)127 napi_value SlowMotionSessionNapi::CreateCameraSession(napi_env env)
128 {
129 MEDIA_DEBUG_LOG("CreateCameraSession is called");
130 CAMERA_SYNC_TRACE;
131 napi_status status;
132 napi_value result = nullptr;
133 napi_value constructor;
134 status = napi_get_reference_value(env, sConstructor_, &constructor);
135 if (status == napi_ok) {
136 sCameraSession_ = CameraManager::GetInstance()->CreateCaptureSession(SceneMode::SLOW_MOTION);
137 if (sCameraSession_ == nullptr) {
138 MEDIA_ERR_LOG("Failed to create SlowMotion session instance");
139 napi_get_undefined(env, &result);
140 return result;
141 }
142 status = napi_new_instance(env, constructor, 0, nullptr, &result);
143 sCameraSession_ = nullptr;
144 if (status == napi_ok && result != nullptr) {
145 MEDIA_DEBUG_LOG("success to create slow motion session napi instance");
146 return result;
147 } else {
148 MEDIA_ERR_LOG("Failed to create slow motion session napi instance");
149 }
150 }
151 MEDIA_ERR_LOG("Failed to create slow motion session napi instance last");
152 napi_get_undefined(env, &result);
153 return result;
154 }
155
SlowMotionSessionNapiConstructor(napi_env env,napi_callback_info info)156 napi_value SlowMotionSessionNapi::SlowMotionSessionNapiConstructor(napi_env env, napi_callback_info info)
157 {
158 MEDIA_DEBUG_LOG("SlowMotionSessionNapiConstructor is called");
159 napi_status status;
160 napi_value result = nullptr;
161 napi_value thisVar = nullptr;
162
163 napi_get_undefined(env, &result);
164 CAMERA_NAPI_GET_JS_OBJ_WITH_ZERO_ARGS(env, info, status, thisVar);
165
166 if (status == napi_ok && thisVar != nullptr) {
167 std::unique_ptr<SlowMotionSessionNapi> obj = std::make_unique<SlowMotionSessionNapi>();
168 obj->env_ = env;
169 if (sCameraSession_ == nullptr) {
170 MEDIA_ERR_LOG("sCameraSession is null");
171 return result;
172 }
173 obj->slowMotionSession_ = static_cast<SlowMotionSession*>(sCameraSession_.GetRefPtr());
174 obj->cameraSession_ = obj->slowMotionSession_;
175 if (obj->slowMotionSession_ == nullptr) {
176 MEDIA_ERR_LOG("slowMotionSession is null");
177 return result;
178 }
179 status = napi_wrap(env, thisVar, reinterpret_cast<void*>(obj.get()),
180 SlowMotionSessionNapi::SlowMotionSessionNapiDestructor, nullptr, nullptr);
181 if (status == napi_ok) {
182 obj.release();
183 return thisVar;
184 } else {
185 MEDIA_ERR_LOG("SlowMotionSessionNapi Failure wrapping js to native napi");
186 }
187 }
188 MEDIA_ERR_LOG("SlowMotionSessionNapi call Failed!");
189 return result;
190 }
191
IsSlowMotionDetectionSupported(napi_env env,napi_callback_info info)192 napi_value SlowMotionSessionNapi::IsSlowMotionDetectionSupported(napi_env env, napi_callback_info info)
193 {
194 MEDIA_INFO_LOG("IsSlowMotionDetectionSupported is called");
195 napi_value result = CameraNapiUtils::GetUndefinedValue(env);
196 if (!CameraNapiSecurity::CheckSystemApp(env)) {
197 MEDIA_ERR_LOG("SystemApi IsSlowMotionDetectionSupported is called!");
198 return result;
199 }
200 SlowMotionSessionNapi* slowMotionSessionNapi = nullptr;
201 CameraNapiParamParser jsParamParser(env, info, slowMotionSessionNapi);
202 if (!jsParamParser.AssertStatus(INVALID_ARGUMENT, "parse parameter occur error")) {
203 MEDIA_ERR_LOG("IsSlowMotionDetectionSupported parse parameter occur error");
204 return result;
205 }
206 if (slowMotionSessionNapi != nullptr && slowMotionSessionNapi->slowMotionSession_ != nullptr) {
207 bool isSupported = slowMotionSessionNapi->slowMotionSession_->IsSlowMotionDetectionSupported();
208 napi_get_boolean(env, isSupported, &result);
209 } else {
210 MEDIA_ERR_LOG("IsSlowMotionDetectionSupported call Failed!");
211 }
212 return result;
213 }
214
GetDoubleProperty(napi_env env,napi_value param,const std::string & propertyName,double & propertyValue)215 napi_value SlowMotionSessionNapi::GetDoubleProperty(napi_env env, napi_value param, const std::string& propertyName,
216 double& propertyValue)
217 {
218 napi_status status;
219 napi_value property;
220 status = napi_get_named_property(env, param, propertyName.c_str(), &property);
221 if (status != napi_ok) {
222 return nullptr;
223 }
224 status = napi_get_value_double(env, property, &propertyValue);
225 if (status != napi_ok) {
226 return nullptr;
227 }
228 return property;
229 }
230
SetSlowMotionDetectionArea(napi_env env,napi_callback_info info)231 napi_value SlowMotionSessionNapi::SetSlowMotionDetectionArea(napi_env env, napi_callback_info info)
232 {
233 MEDIA_INFO_LOG("SetSlowMotionDetectionArea is called");
234 napi_value result = CameraNapiUtils::GetUndefinedValue(env);
235 if (!CameraNapiSecurity::CheckSystemApp(env)) {
236 MEDIA_ERR_LOG("SystemApi SetSlowMotionDetectionArea is called!");
237 return result;
238 }
239 SlowMotionSessionNapi* slowMotionSessionNapi = nullptr;
240 napi_status status;
241 size_t argc = ARGS_ONE;
242 napi_value argv[ARGS_ONE] = {0};
243 napi_value thisVar = nullptr;
244 double topLeftX;
245 double topLeftY;
246 double width;
247 double height;
248
249 CAMERA_NAPI_GET_JS_ARGS(env, info, argc, argv, thisVar);
250
251 if ((GetDoubleProperty(env, argv[PARAM0], "topLeftX", topLeftX) == nullptr) ||
252 (GetDoubleProperty(env, argv[PARAM0], "topLeftY", topLeftY) == nullptr) ||
253 (GetDoubleProperty(env, argv[PARAM0], "width", width) == nullptr) ||
254 (GetDoubleProperty(env, argv[PARAM0], "height", height) == nullptr)) {
255 return result;
256 }
257
258 Rect rect = (Rect) {topLeftX, topLeftY, width, height};
259 napi_get_undefined(env, &result);
260 status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&slowMotionSessionNapi));
261 if (status == napi_ok && slowMotionSessionNapi != nullptr && slowMotionSessionNapi->slowMotionSession_ != nullptr) {
262 slowMotionSessionNapi->slowMotionSession_->SetSlowMotionDetectionArea(rect);
263 } else {
264 MEDIA_ERR_LOG("SetSlowMotionDetectionArea call Failed!");
265 }
266 return result;
267 }
268
RegisterSlowMotionStateCb(const std::string & eventName,napi_env env,napi_value callback,const std::vector<napi_value> & args,bool isOnce)269 void SlowMotionSessionNapi::RegisterSlowMotionStateCb(
270 const std::string& eventName, napi_env env, napi_value callback, const std::vector<napi_value>& args, bool isOnce)
271 {
272 MEDIA_INFO_LOG("RegisterSlowMotionStateCb is called");
273 if (slowMotionStateListener_ == nullptr) {
274 shared_ptr<SlowMotionStateListener> slowMotionStateListenerTemp =
275 static_pointer_cast<SlowMotionStateListener>(slowMotionSession_->GetApplicationCallback());
276 if (slowMotionStateListenerTemp == nullptr) {
277 slowMotionStateListenerTemp = make_shared<SlowMotionStateListener>(env);
278 slowMotionSession_->SetCallback(slowMotionStateListenerTemp);
279 }
280 slowMotionStateListener_ = slowMotionStateListenerTemp;
281 }
282 slowMotionStateListener_->SaveCallbackReference(eventName, callback, isOnce);
283 MEDIA_INFO_LOG("RegisterSlowMotionStateCb success");
284 }
285
UnregisterSlowMotionStateCb(const std::string & eventName,napi_env env,napi_value callback,const std::vector<napi_value> & args)286 void SlowMotionSessionNapi::UnregisterSlowMotionStateCb(
287 const std::string& eventName, napi_env env, napi_value callback, const std::vector<napi_value>& args)
288 {
289 MEDIA_INFO_LOG("UnregisterSlowMotionStateCb is called");
290 if (slowMotionStateListener_ == nullptr) {
291 MEDIA_ERR_LOG("slowMotionStateListener_ is null");
292 } else {
293 slowMotionStateListener_->RemoveCallbackRef(eventName, callback);
294 }
295 }
296 } // namespace CameraStandard
297 } // namespace OHOS