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