1 /*
2 * Copyright (C) 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 "avscreen_capture_napi.h"
17 #include "avscreen_capture_callback.h"
18 #include "common_napi.h"
19 #include "media_dfx.h"
20 #include "media_log.h"
21 #ifndef CROSS_PLATFORM
22 #include "display_manager.h"
23 #endif
24 namespace {
25 constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, LOG_DOMAIN_SCREENCAPTURE, "AVScreenCaptureNapi"};
26 }
27
28 namespace OHOS {
29 namespace Media {
30 thread_local napi_ref AVScreenCaptureNapi::constructor_ = nullptr;
31 const std::string CLASS_NAME = "AVScreenCapture";
32 std::map<std::string, AVScreenCaptureNapi::AvScreenCaptureTaskqFunc> AVScreenCaptureNapi::taskQFuncs_ = {
33 {AVScreenCapturegOpt::START_RECORDING, &AVScreenCaptureNapi::StartRecording},
34 {AVScreenCapturegOpt::STOP_RECORDING, &AVScreenCaptureNapi::StopRecording},
35 {AVScreenCapturegOpt::RELEASE, &AVScreenCaptureNapi::Release},
36 };
37
AVScreenCaptureNapi()38 AVScreenCaptureNapi::AVScreenCaptureNapi()
39 {
40 MEDIA_LOGI("0x%{public}06" PRIXPTR "Instances create", FAKE_POINTER(this));
41 }
42
~AVScreenCaptureNapi()43 AVScreenCaptureNapi::~AVScreenCaptureNapi()
44 {
45 MEDIA_LOGI("0x%{public}06" PRIXPTR "Instances destroy", FAKE_POINTER(this));
46 }
47
Init(napi_env env,napi_value exports)48 napi_value AVScreenCaptureNapi::Init(napi_env env, napi_value exports)
49 {
50 napi_property_descriptor staticProperty[] = {
51 DECLARE_NAPI_STATIC_FUNCTION("createAVScreenCaptureRecorder", JsCreateAVScreenRecorder),
52 DECLARE_NAPI_STATIC_FUNCTION("reportAVScreenCaptureUserChoice", JsReportAVScreenCaptureUserChoice)
53 };
54
55 napi_property_descriptor properties[] = {
56 DECLARE_NAPI_FUNCTION("init", JsInit),
57 DECLARE_NAPI_FUNCTION("startRecording", JsStartRecording),
58 DECLARE_NAPI_FUNCTION("stopRecording", JsStopRecording),
59 DECLARE_NAPI_FUNCTION("skipPrivacyMode", JsSkipPrivacyMode),
60 DECLARE_NAPI_FUNCTION("setMicEnabled", JsSetMicrophoneEnabled),
61 DECLARE_NAPI_FUNCTION("release", JsRelease),
62 DECLARE_NAPI_FUNCTION("on", JsSetEventCallback),
63 DECLARE_NAPI_FUNCTION("off", JsCancelEventCallback),
64 };
65
66 napi_value constructor = nullptr;
67 napi_status status = napi_define_class(env, CLASS_NAME.c_str(), NAPI_AUTO_LENGTH, Constructor, nullptr,
68 sizeof(properties) / sizeof(properties[0]), properties, &constructor);
69 CHECK_AND_RETURN_RET_LOG(status == napi_ok, nullptr, "Failed to define AVScreenCapture class");
70
71 status = napi_create_reference(env, constructor, 1, &constructor_);
72 CHECK_AND_RETURN_RET_LOG(status == napi_ok, nullptr, "Failed to create reference of constructor");
73
74 status = napi_set_named_property(env, exports, CLASS_NAME.c_str(), constructor);
75 CHECK_AND_RETURN_RET_LOG(status == napi_ok, nullptr, "Failed to set constructor");
76
77 status = napi_define_properties(env, exports, sizeof(staticProperty) / sizeof(staticProperty[0]), staticProperty);
78 CHECK_AND_RETURN_RET_LOG(status == napi_ok, nullptr, "Failed to define static function");
79
80 MEDIA_LOGD("AVScreenCaptureNapi Init success");
81 return exports;
82 }
83
Constructor(napi_env env,napi_callback_info info)84 napi_value AVScreenCaptureNapi::Constructor(napi_env env, napi_callback_info info)
85 {
86 MediaTrace trace("AVScreenCaptureNapi::Constructor");
87 napi_value result = nullptr;
88 napi_get_undefined(env, &result);
89
90 size_t argCount = 0;
91 napi_value jsThis = nullptr;
92 napi_status status = napi_get_cb_info(env, info, &argCount, nullptr, &jsThis, nullptr);
93 CHECK_AND_RETURN_RET_LOG(status == napi_ok, result, "failed to napi_get_cb_info");
94
95 AVScreenCaptureNapi *jsScreenCapture = new(std::nothrow) AVScreenCaptureNapi();
96 CHECK_AND_RETURN_RET_LOG(jsScreenCapture != nullptr, result, "failed to new AVScreenCaptureNapi");
97
98 jsScreenCapture->env_ = env;
99 jsScreenCapture->screenCapture_ = ScreenCaptureFactory::CreateScreenCapture();
100 if (jsScreenCapture->screenCapture_ == nullptr) {
101 delete jsScreenCapture;
102 MEDIA_LOGE("failed to CreateScreenCapture");
103 return result;
104 }
105
106 jsScreenCapture->taskQue_ = std::make_unique<TaskQueue>("OS_AVScreenCaptureNapi");
107 (void)jsScreenCapture->taskQue_->Start();
108
109 jsScreenCapture->screenCaptureCb_ = std::make_shared<AVScreenCaptureCallback>(env);
110 if (jsScreenCapture->screenCaptureCb_ == nullptr) {
111 delete jsScreenCapture;
112 MEDIA_LOGE("failed to CreateScreenCaptureCb");
113 return result;
114 }
115 (void)jsScreenCapture->screenCapture_->SetScreenCaptureCallback(jsScreenCapture->screenCaptureCb_);
116
117 status = napi_wrap(env, jsThis, reinterpret_cast<void *>(jsScreenCapture),
118 AVScreenCaptureNapi::Destructor, nullptr, nullptr);
119 if (status != napi_ok) {
120 delete jsScreenCapture;
121 MEDIA_LOGE("Failed to wrap native instance");
122 return result;
123 }
124
125 MEDIA_LOGI("Constructor success");
126 return jsThis;
127 }
128
Destructor(napi_env env,void * nativeObject,void * finalize)129 void AVScreenCaptureNapi::Destructor(napi_env env, void *nativeObject, void *finalize)
130 {
131 MediaTrace trace("AVScreenCaptureNapi::Destructor");
132 (void)finalize;
133 if (nativeObject != nullptr) {
134 AVScreenCaptureNapi *napi = reinterpret_cast<AVScreenCaptureNapi *>(nativeObject);
135 if (napi->taskQue_ != nullptr) {
136 (void)napi->taskQue_->Stop();
137 }
138
139 napi->screenCaptureCb_ = nullptr;
140
141 if (napi->screenCapture_) {
142 napi->screenCapture_->Release();
143 napi->screenCapture_ = nullptr;
144 }
145
146 delete napi;
147 }
148 MEDIA_LOGI("Destructor success");
149 }
150
JsCreateAVScreenRecorder(napi_env env,napi_callback_info info)151 napi_value AVScreenCaptureNapi::JsCreateAVScreenRecorder(napi_env env, napi_callback_info info)
152 {
153 MediaTrace trace("AVScreenCapture::JsCreateAVScreenRecorder");
154 napi_value result = nullptr;
155 napi_get_undefined(env, &result);
156
157 // get args
158 napi_value jsThis = nullptr;
159 napi_value args[1] = { nullptr };
160 size_t argCount = 1;
161 napi_status status = napi_get_cb_info(env, info, &argCount, args, &jsThis, nullptr);
162 CHECK_AND_RETURN_RET_LOG(status == napi_ok, result, "failed to napi_get_cb_info");
163
164 std::unique_ptr<AVScreenCaptureAsyncContext> asyncCtx = std::make_unique<AVScreenCaptureAsyncContext>(env);
165 CHECK_AND_RETURN_RET_LOG(asyncCtx != nullptr, result, "failed to get AsyncContext");
166
167 asyncCtx->callbackRef = CommonNapi::CreateReference(env, args[0]);
168 asyncCtx->deferred = CommonNapi::CreatePromise(env, asyncCtx->callbackRef, result);
169 asyncCtx->JsResult = std::make_unique<MediaJsResultInstance>(constructor_);
170 asyncCtx->ctorFlag = true;
171 auto ret = MediaAsyncContext::SendCompleteEvent(env, asyncCtx.get(), napi_eprio_immediate);
172 if (ret != napi_status::napi_ok) {
173 MEDIA_LOGE("failed to SendEvent, ret = %{public}d", ret);
174 } else {
175 asyncCtx.release();
176 }
177
178 MEDIA_LOGI("JsCreateAVScreenRecorder success");
179 return result;
180 }
181
GetReturnInfo(int32_t errCode,const std::string & operate,const std::string & param,const std::string & add="")182 RetInfo GetReturnInfo(int32_t errCode, const std::string &operate, const std::string ¶m,
183 const std::string &add = "")
184 {
185 MEDIA_LOGE("failed to %{public}s, param %{public}s, errCode = %{public}d",
186 operate.c_str(), param.c_str(), errCode);
187 MediaServiceExtErrCodeAPI9 err = MSErrorToExtErrorAPI9(static_cast<MediaServiceErrCode>(errCode));
188
189 std::string message;
190 if (err == MSERR_EXT_API9_INVALID_PARAMETER) {
191 message = MSExtErrorAPI9ToString(err, param, "") + add;
192 } else {
193 message = MSExtErrorAPI9ToString(err, operate, "") + add;
194 }
195
196 MEDIA_LOGE("errCode: %{public}d, errMsg: %{public}s", err, message.c_str());
197 return RetInfo(err, message);
198 }
199
JsReportAVScreenCaptureUserChoice(napi_env env,napi_callback_info info)200 napi_value AVScreenCaptureNapi::JsReportAVScreenCaptureUserChoice(napi_env env, napi_callback_info info)
201 {
202 MediaTrace trace("AVScreenCapture::JsReportAVScreenCaptureUserChoice");
203 const std::string &opt = AVScreenCapturegOpt::REPORT_USER_CHOICE;
204 MEDIA_LOGI("Js %{public}s Start", opt.c_str());
205
206 const int32_t maxParam = 2; // config + callbackRef
207 size_t argCount = maxParam;
208 napi_value args[maxParam] = { nullptr };
209
210 napi_value result = nullptr;
211 napi_get_undefined(env, &result);
212
213 auto asyncCtx = std::make_unique<AVScreenCaptureAsyncContext>(env);
214 CHECK_AND_RETURN_RET_LOG(asyncCtx != nullptr, result, "failed to get AsyncContext");
215
216 napi_value jsThis = nullptr;
217 napi_status status = napi_get_cb_info(env, info, &argCount, args, &jsThis, nullptr);
218 CHECK_AND_RETURN_RET_LOG(status == napi_ok && jsThis != nullptr, nullptr, "failed to napi_get_cb_info");
219 MEDIA_LOGI("argCountL %{public}zu", argCount);
220
221 if (argCount < maxParam) {
222 asyncCtx->AVScreenCaptureSignError(MSERR_MANDATORY_PARAMETER_UNSPECIFIED, "ReportUserChoice", "");
223 return result;
224 }
225
226 napi_valuetype valueType = napi_undefined;
227 if (napi_typeof(env, args[0], &valueType) != napi_ok || valueType != napi_number) {
228 asyncCtx->AVScreenCaptureSignError(MSERR_INCORRECT_PARAMETER_TYPE, "ReportUserChoice", "sessionId",
229 "sessionId is not number");
230 return result;
231 }
232 int32_t sessionId;
233 status = napi_get_value_int32(env, args[0], &sessionId);
234 if (status != napi_ok) {
235 asyncCtx->AVScreenCaptureSignError(MSERR_INCORRECT_PARAMETER_TYPE, "ReportUserChoice", "sessionId",
236 "UserChoice get sessionId failed");
237 return result;
238 }
239
240 valueType = napi_undefined;
241 if (napi_typeof(env, args[1], &valueType) != napi_ok || valueType != napi_string) {
242 asyncCtx->AVScreenCaptureSignError(MSERR_INCORRECT_PARAMETER_TYPE, "ReportUserChoice", "choice",
243 "choice is not string");
244 return result;
245 }
246 std::string choice = CommonNapi::GetStringArgument(env, args[1]);
247 MEDIA_LOGI("JsReportAVScreenCaptureUserChoice sessionId: %{public}d, choice: %{public}s",
248 sessionId, choice.c_str());
249
250 asyncCtx->deferred = CommonNapi::CreatePromise(env, asyncCtx->callbackRef, result);
251 asyncCtx->controller_ = ScreenCaptureControllerFactory::CreateScreenCaptureController();
252 asyncCtx->controller_->ReportAVScreenCaptureUserChoice(sessionId, choice);
253
254 napi_value resource = nullptr;
255 napi_create_string_utf8(env, opt.c_str(), NAPI_AUTO_LENGTH, &resource);
256 NAPI_CALL(env, napi_create_async_work(env, nullptr, resource, AsyncJsReportAVScreenCaptureUserChoice,
257 MediaAsyncContext::CompleteCallback, static_cast<void *>(asyncCtx.get()), &asyncCtx->work));
258 NAPI_CALL(env, napi_queue_async_work_with_qos(env, asyncCtx->work, napi_qos_user_initiated));
259 asyncCtx.release();
260
261 MEDIA_LOGI("Js %{public}s End", opt.c_str());
262 return result;
263 }
264
AsyncJsReportAVScreenCaptureUserChoice(napi_env env,void * data)265 void AVScreenCaptureNapi::AsyncJsReportAVScreenCaptureUserChoice(napi_env env, void* data)
266 {
267 AVScreenCaptureAsyncContext* asyncCtx = reinterpret_cast<AVScreenCaptureAsyncContext *>(data);
268 CHECK_AND_RETURN_LOG(asyncCtx != nullptr, "asyncCtx is nullptr!");
269
270 if (asyncCtx->task_) {
271 auto result = asyncCtx->task_->GetResult();
272 if (result.Value().first != MSERR_EXT_API9_OK) {
273 asyncCtx->SignError(result.Value().first, result.Value().second);
274 }
275 }
276 MEDIA_LOGI("The js thread of ReportAVScreenCaptureUserChoice finishes execution and returns");
277 }
278
JsInit(napi_env env,napi_callback_info info)279 napi_value AVScreenCaptureNapi::JsInit(napi_env env, napi_callback_info info)
280 {
281 MediaTrace trace("AVScreenCapture::JsInit");
282 const std::string &opt = AVScreenCapturegOpt::INIT;
283 MEDIA_LOGI("Js %{public}s Start", opt.c_str());
284
285 const int32_t maxParam = 2; // config + callbackRef
286 size_t argCount = maxParam;
287 napi_value args[maxParam] = { nullptr };
288
289 napi_value result = nullptr;
290 napi_get_undefined(env, &result);
291
292 auto asyncCtx = std::make_unique<AVScreenCaptureAsyncContext>(env);
293 CHECK_AND_RETURN_RET_LOG(asyncCtx != nullptr, result, "failed to get AsyncContext");
294 asyncCtx->napi = AVScreenCaptureNapi::GetJsInstanceAndArgs(env, info, argCount, args);
295 CHECK_AND_RETURN_RET_LOG(asyncCtx->napi != nullptr, result, "failed to GetJsInstanceAndArgs");
296 CHECK_AND_RETURN_RET_LOG(asyncCtx->napi->taskQue_ != nullptr, result, "taskQue is nullptr!");
297
298 asyncCtx->callbackRef = CommonNapi::CreateReference(env, args[1]);
299 asyncCtx->deferred = CommonNapi::CreatePromise(env, asyncCtx->callbackRef, result);
300
301 if (asyncCtx->napi->GetConfig(asyncCtx, env, args[0]) == MSERR_OK) {
302 asyncCtx->task_ = AVScreenCaptureNapi::GetInitTask(asyncCtx);
303 (void)asyncCtx->napi->taskQue_->EnqueueTask(asyncCtx->task_);
304 }
305
306 napi_value resource = nullptr;
307 napi_create_string_utf8(env, opt.c_str(), NAPI_AUTO_LENGTH, &resource);
308 NAPI_CALL(env, napi_create_async_work(env, nullptr, resource, [](napi_env env, void* data) {
309 AVScreenCaptureAsyncContext* asyncCtx = reinterpret_cast<AVScreenCaptureAsyncContext *>(data);
310 CHECK_AND_RETURN_LOG(asyncCtx != nullptr, "asyncCtx is nullptr!");
311
312 if (asyncCtx->task_) {
313 auto result = asyncCtx->task_->GetResult();
314 if (result.Value().first != MSERR_EXT_API9_OK) {
315 asyncCtx->SignError(result.Value().first, result.Value().second);
316 }
317 }
318 MEDIA_LOGI("The js thread of init finishes execution and returns");
319 }, MediaAsyncContext::CompleteCallback, static_cast<void *>(asyncCtx.get()), &asyncCtx->work));
320 NAPI_CALL(env, napi_queue_async_work_with_qos(env, asyncCtx->work, napi_qos_user_initiated));
321 asyncCtx.release();
322
323 MEDIA_LOGI("Js %{public}s End", opt.c_str());
324 return result;
325 }
326
JsStartRecording(napi_env env,napi_callback_info info)327 napi_value AVScreenCaptureNapi::JsStartRecording(napi_env env, napi_callback_info info)
328 {
329 MediaTrace trace("AVScreenCapture::JsStartRecording");
330 return ExecuteByPromise(env, info, AVScreenCapturegOpt::START_RECORDING);
331 }
332
JsStopRecording(napi_env env,napi_callback_info info)333 napi_value AVScreenCaptureNapi::JsStopRecording(napi_env env, napi_callback_info info)
334 {
335 MediaTrace trace("AVScreenCapture::JsStopRecording");
336 return ExecuteByPromise(env, info, AVScreenCapturegOpt::STOP_RECORDING);
337 }
338
GetWindowIDsVectorParams(std::vector<uint64_t> & windowIDsVec,napi_env env,napi_value * args)339 napi_status AVScreenCaptureNapi::GetWindowIDsVectorParams(std::vector<uint64_t> &windowIDsVec, napi_env env,
340 napi_value* args)
341 {
342 uint32_t array_length;
343 napi_status status = napi_get_array_length(env, args[0], &array_length);
344 if (status != napi_ok) {
345 return status;
346 }
347 for (uint32_t i = 0; i < array_length; i++) {
348 napi_value temp;
349 status = napi_get_element(env, args[0], i, &temp);
350 int32_t tempValue = -1;
351 if (status == napi_ok) {
352 napi_get_value_int32(env, temp, &tempValue);
353 }
354 if (tempValue >= 0) {
355 windowIDsVec.push_back(static_cast<uint64_t>(tempValue));
356 } else {
357 MEDIA_LOGI("JsSkipPrivacyMode skip %{public}d", tempValue);
358 }
359 }
360 return napi_ok;
361 }
362
JsSkipPrivacyMode(napi_env env,napi_callback_info info)363 napi_value AVScreenCaptureNapi::JsSkipPrivacyMode(napi_env env, napi_callback_info info)
364 {
365 MediaTrace trace("AVScreenCapture::JsSkipPrivacyMode");
366 const std::string &opt = AVScreenCapturegOpt::SKIP_PRIVACY_MODE;
367 MEDIA_LOGI("Js %{public}s Start", opt.c_str());
368 size_t argCount = 1; // arg[0] vector
369 napi_value args[1] = { nullptr };
370 napi_value result = nullptr;
371 napi_get_undefined(env, &result);
372 auto asyncCtx = std::make_unique<AVScreenCaptureAsyncContext>(env);
373 CHECK_AND_RETURN_RET_LOG(asyncCtx != nullptr, result, "failed to get AsyncContext");
374 asyncCtx->napi = AVScreenCaptureNapi::GetJsInstanceAndArgs(env, info, argCount, args);
375 CHECK_AND_RETURN_RET_LOG(asyncCtx->napi != nullptr, result, "failed to GetJsInstanceAndArgs");
376 CHECK_AND_RETURN_RET_LOG(asyncCtx->napi->taskQue_ != nullptr, result, "taskQue is nullptr!");
377 std::vector<uint64_t> windowIDsVec;
378 napi_get_cb_info(env, info, &argCount, args, nullptr, nullptr);
379 napi_status status = GetWindowIDsVectorParams(windowIDsVec, env, args);
380 CHECK_AND_RETURN_RET_LOG(status == napi_ok, (asyncCtx->AVScreenCaptureSignError(MSERR_EXT_API9_INVALID_PARAMETER,
381 "SkipPrivacyMode", "SkipPrivacyMode get value failed"), result), "failed to GetWindowIDsVectorParams");
382 asyncCtx->deferred = CommonNapi::CreatePromise(env, asyncCtx->callbackRef, result);
383 asyncCtx->task_ = AVScreenCaptureNapi::GetSkipPrivacyModeTask(asyncCtx, windowIDsVec);
384 (void)asyncCtx->napi->taskQue_->EnqueueTask(asyncCtx->task_);
385 napi_value resource = nullptr;
386 napi_create_string_utf8(env, opt.c_str(), NAPI_AUTO_LENGTH, &resource);
387 NAPI_CALL(env, napi_create_async_work(env, nullptr, resource, [](napi_env env, void* data) {
388 AVScreenCaptureAsyncContext* asyncCtx = reinterpret_cast<AVScreenCaptureAsyncContext *>(data);
389 CHECK_AND_RETURN_LOG(asyncCtx != nullptr, "asyncCtx is nullptr!");
390 if (asyncCtx->task_) {
391 auto result = asyncCtx->task_->GetResult();
392 if (result.Value().first != MSERR_EXT_API9_OK) {
393 asyncCtx->SignError(result.Value().first, result.Value().second);
394 }
395 }
396 MEDIA_LOGI("The js thread of init finishes execution and returns");
397 }, MediaAsyncContext::CompleteCallback, static_cast<void *>(asyncCtx.get()), &asyncCtx->work));
398 NAPI_CALL(env, napi_queue_async_work_with_qos(env, asyncCtx->work, napi_qos_user_initiated));
399 asyncCtx.release();
400 MEDIA_LOGI("Js %{public}s End", opt.c_str());
401 return result;
402 }
403
JsSetMicrophoneEnabled(napi_env env,napi_callback_info info)404 napi_value AVScreenCaptureNapi::JsSetMicrophoneEnabled(napi_env env, napi_callback_info info)
405 {
406 MediaTrace trace("AVScreenCapture::JsSetMicrophoneEnabled");
407 const std::string &opt = AVScreenCapturegOpt::SET_MIC_ENABLE;
408 MEDIA_LOGI("Js %{public}s Start", opt.c_str());
409
410 const int32_t maxParam = 1; // config + callbackRef
411 size_t argCount = maxParam;
412 napi_value args[maxParam] = { nullptr };
413
414 napi_value result = nullptr;
415 napi_get_undefined(env, &result);
416
417 auto asyncCtx = std::make_unique<AVScreenCaptureAsyncContext>(env);
418 CHECK_AND_RETURN_RET_LOG(asyncCtx != nullptr, result, "failed to get AsyncContext");
419 asyncCtx->napi = AVScreenCaptureNapi::GetJsInstanceAndArgs(env, info, argCount, args);
420 CHECK_AND_RETURN_RET_LOG(asyncCtx->napi != nullptr, result, "failed to GetJsInstanceAndArgs");
421 CHECK_AND_RETURN_RET_LOG(asyncCtx->napi->taskQue_ != nullptr, result, "taskQue is nullptr!");
422
423 napi_valuetype valueType = napi_undefined;
424 if (argCount < 1 || napi_typeof(env, args[0], &valueType) != napi_ok || valueType != napi_boolean) {
425 asyncCtx->AVScreenCaptureSignError(MSERR_EXT_API9_INVALID_PARAMETER, "SetMivcrophoneEnable",
426 "setMicrophone input is not boolean");
427 return result;
428 }
429 bool enable;
430 napi_status status = napi_get_value_bool(env, args[0], &enable);
431 if (status != napi_ok) {
432 asyncCtx->AVScreenCaptureSignError(MSERR_EXT_API9_INVALID_PARAMETER, "SetMivcrophoneEnable",
433 "setMicrophone get value failed");
434 return result;
435 }
436
437 asyncCtx->deferred = CommonNapi::CreatePromise(env, asyncCtx->callbackRef, result);
438 asyncCtx->task_ = AVScreenCaptureNapi::GetSetMicrophoneEnableTask(asyncCtx, enable);
439 (void)asyncCtx->napi->taskQue_->EnqueueTask(asyncCtx->task_);
440
441 napi_value resource = nullptr;
442 napi_create_string_utf8(env, opt.c_str(), NAPI_AUTO_LENGTH, &resource);
443 NAPI_CALL(env, napi_create_async_work(env, nullptr, resource, [](napi_env env, void* data) {
444 AVScreenCaptureAsyncContext* asyncCtx = reinterpret_cast<AVScreenCaptureAsyncContext *>(data);
445 CHECK_AND_RETURN_LOG(asyncCtx != nullptr, "asyncCtx is nullptr!");
446
447 if (asyncCtx->task_) {
448 auto result = asyncCtx->task_->GetResult();
449 if (result.Value().first != MSERR_EXT_API9_OK) {
450 asyncCtx->SignError(result.Value().first, result.Value().second);
451 }
452 }
453 MEDIA_LOGI("The js thread of init finishes execution and returns");
454 }, MediaAsyncContext::CompleteCallback, static_cast<void *>(asyncCtx.get()), &asyncCtx->work));
455 NAPI_CALL(env, napi_queue_async_work_with_qos(env, asyncCtx->work, napi_qos_user_initiated));
456 asyncCtx.release();
457
458 MEDIA_LOGI("Js %{public}s End", opt.c_str());
459 return result;
460 }
461
JsRelease(napi_env env,napi_callback_info info)462 napi_value AVScreenCaptureNapi::JsRelease(napi_env env, napi_callback_info info)
463 {
464 MediaTrace trace("AVScreenCapture::JsRelease");
465 return ExecuteByPromise(env, info, AVScreenCapturegOpt::RELEASE);
466 }
467
JsSetEventCallback(napi_env env,napi_callback_info info)468 napi_value AVScreenCaptureNapi::JsSetEventCallback(napi_env env, napi_callback_info info)
469 {
470 MediaTrace trace("AVScreenCapture::JsSetEventCallback");
471 MEDIA_LOGI("JsSetEventCallback Start");
472 napi_value result = nullptr;
473 napi_get_undefined(env, &result);
474
475 size_t argCount = 2;
476 napi_value args[2] = { nullptr, nullptr };
477 AVScreenCaptureNapi *avScreenCaptureNapi = AVScreenCaptureNapi::GetJsInstanceAndArgs(env, info, argCount, args);
478 CHECK_AND_RETURN_RET_LOG(avScreenCaptureNapi != nullptr, result, "Failed to retrieve instance");
479
480 napi_valuetype valueType0 = napi_undefined;
481 napi_valuetype valueType1 = napi_undefined;
482 if (napi_typeof(env, args[0], &valueType0) != napi_ok || valueType0 != napi_string ||
483 napi_typeof(env, args[1], &valueType1) != napi_ok || valueType1 != napi_function) {
484 avScreenCaptureNapi->ErrorCallback(MSERR_INVALID_VAL, "SetEventCallback");
485 return result;
486 }
487
488 std::string callbackName = CommonNapi::GetStringArgument(env, args[0]);
489 if (callbackName != AVScreenCaptureEvent::EVENT_ERROR &&
490 callbackName != AVScreenCaptureEvent::EVENT_STATE_CHANGE) {
491 avScreenCaptureNapi->ErrorCallback(MSERR_INVALID_VAL, "SetEventCallback");
492 return result;
493 }
494
495 napi_ref ref = nullptr;
496 napi_status status = napi_create_reference(env, args[1], 1, &ref);
497 CHECK_AND_RETURN_RET_LOG(status == napi_ok && ref != nullptr, result, "failed to create reference!");
498
499 std::shared_ptr<AutoRef> autoRef = std::make_shared<AutoRef>(env, ref);
500 avScreenCaptureNapi->SetCallbackReference(callbackName, autoRef);
501
502 MEDIA_LOGI("JsSetEventCallback set callback %{public}s End", callbackName.c_str());
503 return result;
504 }
505
JsCancelEventCallback(napi_env env,napi_callback_info info)506 napi_value AVScreenCaptureNapi::JsCancelEventCallback(napi_env env, napi_callback_info info)
507 {
508 MediaTrace trace("AVScreenCapture::JsCancelEventCallback");
509 MEDIA_LOGI("JsCancelEventCallback Start");
510 napi_value result = nullptr;
511 napi_get_undefined(env, &result);
512
513 size_t argCount = 1;
514 napi_value args[1] = { nullptr };
515 AVScreenCaptureNapi *avScreenCaptureNapi = AVScreenCaptureNapi::GetJsInstanceAndArgs(env, info, argCount, args);
516 CHECK_AND_RETURN_RET_LOG(avScreenCaptureNapi != nullptr, result, "Failed to retrieve instance");
517
518 napi_valuetype valueType0 = napi_undefined;
519 if (napi_typeof(env, args[0], &valueType0) != napi_ok || valueType0 != napi_string) {
520 avScreenCaptureNapi->ErrorCallback(MSERR_INVALID_VAL, "CancelEventCallback");
521 return result;
522 }
523
524 std::string callbackName = CommonNapi::GetStringArgument(env, args[0]);
525 if (callbackName != AVScreenCaptureEvent::EVENT_ERROR &&
526 callbackName != AVScreenCaptureEvent::EVENT_STATE_CHANGE) {
527 avScreenCaptureNapi->ErrorCallback(MSERR_INVALID_VAL, "CancelEventCallback");
528 return result;
529 }
530
531 avScreenCaptureNapi->CancelCallbackReference(callbackName);
532
533 MEDIA_LOGI("JsCancelEventCallback cancel callback %{public}s End", callbackName.c_str());
534 return result;
535 }
536
GetInitTask(const std::unique_ptr<AVScreenCaptureAsyncContext> & asyncCtx)537 std::shared_ptr<TaskHandler<RetInfo>> AVScreenCaptureNapi::GetInitTask(
538 const std::unique_ptr<AVScreenCaptureAsyncContext> &asyncCtx)
539 {
540 return std::make_shared<TaskHandler<RetInfo>>([napi = asyncCtx->napi, config = asyncCtx->config_]() {
541 const std::string &option = AVScreenCapturegOpt::INIT;
542 MEDIA_LOGI("%{public}s Start", option.c_str());
543
544 CHECK_AND_RETURN_RET(napi != nullptr && napi->screenCapture_ != nullptr,
545 GetReturnInfo(MSERR_INVALID_OPERATION, option, ""));
546
547 int32_t ret = napi->screenCapture_->Init(config);
548 CHECK_AND_RETURN_RET(ret == MSERR_OK, ((void)napi->screenCapture_->Release(), GetReturnInfo(ret, "Init", "")));
549
550 MEDIA_LOGI("%{public}s End", option.c_str());
551 return RetInfo(MSERR_EXT_API9_OK, "");
552 });
553 }
554
GetSkipPrivacyModeTask(const std::unique_ptr<AVScreenCaptureAsyncContext> & asyncCtx,const std::vector<uint64_t> windowIDsVec)555 std::shared_ptr<TaskHandler<RetInfo>> AVScreenCaptureNapi::GetSkipPrivacyModeTask(
556 const std::unique_ptr<AVScreenCaptureAsyncContext> &asyncCtx, const std::vector<uint64_t> windowIDsVec)
557 {
558 return std::make_shared<TaskHandler<RetInfo>>([napi = asyncCtx->napi, windowIDsVec]() {
559 const std::string &option = AVScreenCapturegOpt::SKIP_PRIVACY_MODE;
560 MEDIA_LOGI("%{public}s Start", option.c_str());
561 CHECK_AND_RETURN_RET(napi != nullptr && napi->screenCapture_ != nullptr,
562 GetReturnInfo(MSERR_INVALID_OPERATION, option, ""));
563 int32_t ret = napi->screenCapture_->SkipPrivacyMode(const_cast<std::vector<uint64_t> &>(windowIDsVec));
564 CHECK_AND_RETURN_RET(ret == MSERR_OK, GetReturnInfo(MSERR_UNKNOWN, option, ""));
565 MEDIA_LOGI("%{public}s End", option.c_str());
566 return RetInfo(MSERR_EXT_API9_OK, "");
567 });
568 }
569
GetSetMicrophoneEnableTask(const std::unique_ptr<AVScreenCaptureAsyncContext> & asyncCtx,const bool enable)570 std::shared_ptr<TaskHandler<RetInfo>> AVScreenCaptureNapi::GetSetMicrophoneEnableTask(
571 const std::unique_ptr<AVScreenCaptureAsyncContext> &asyncCtx, const bool enable)
572 {
573 return std::make_shared<TaskHandler<RetInfo>>([napi = asyncCtx->napi, enable]() {
574 const std::string &option = AVScreenCapturegOpt::SET_MIC_ENABLE;
575 MEDIA_LOGI("%{public}s Start", option.c_str());
576
577 CHECK_AND_RETURN_RET(napi != nullptr && napi->screenCapture_ != nullptr,
578 GetReturnInfo(MSERR_INVALID_OPERATION, option, ""));
579
580 int32_t ret = napi->screenCapture_->SetMicrophoneEnabled(enable);
581 CHECK_AND_RETURN_RET(ret == MSERR_OK, GetReturnInfo(MSERR_UNKNOWN, option, ""));
582
583 MEDIA_LOGI("%{public}s End", option.c_str());
584 return RetInfo(MSERR_EXT_API9_OK, "");
585 });
586 }
587
GetJsInstanceAndArgs(napi_env env,napi_callback_info info,size_t & argCount,napi_value * args)588 AVScreenCaptureNapi *AVScreenCaptureNapi::GetJsInstanceAndArgs(
589 napi_env env, napi_callback_info info, size_t &argCount, napi_value *args)
590 {
591 napi_value jsThis = nullptr;
592 napi_status status = napi_get_cb_info(env, info, &argCount, args, &jsThis, nullptr);
593 CHECK_AND_RETURN_RET_LOG(status == napi_ok && jsThis != nullptr, nullptr, "failed to napi_get_cb_info");
594 MEDIA_LOGI("argCount:%{public}zu", argCount);
595
596 AVScreenCaptureNapi *screenCaptureNapi = nullptr;
597 status = napi_unwrap(env, jsThis, reinterpret_cast<void **>(&screenCaptureNapi));
598 CHECK_AND_RETURN_RET_LOG(status == napi_ok && screenCaptureNapi != nullptr, nullptr,
599 "failed to retrieve instance");
600
601 return screenCaptureNapi;
602 }
603
StartRecording()604 RetInfo AVScreenCaptureNapi::StartRecording()
605 {
606 int32_t ret = screenCapture_->SetPrivacyAuthorityEnabled();
607 CHECK_AND_RETURN_RET(ret == MSERR_OK, GetReturnInfo(ret, "SetPrivacyAuthorityEnabled", ""));
608 ret = screenCapture_->StartScreenRecording();
609 CHECK_AND_RETURN_RET(ret == MSERR_OK, GetReturnInfo(ret, "StartRecording", ""));
610 return RetInfo(MSERR_EXT_API9_OK, "");
611 }
612
StopRecording()613 RetInfo AVScreenCaptureNapi::StopRecording()
614 {
615 int32_t ret = screenCapture_->StopScreenRecording();
616 CHECK_AND_RETURN_RET(ret == MSERR_OK, GetReturnInfo(ret, "StopRecording", ""));
617 return RetInfo(MSERR_EXT_API9_OK, "");
618 }
619
Release()620 RetInfo AVScreenCaptureNapi::Release()
621 {
622 int32_t ret = screenCapture_->Release();
623 CHECK_AND_RETURN_RET(ret == MSERR_OK, GetReturnInfo(ret, "Release", ""));
624 return RetInfo(MSERR_EXT_API9_OK, "");
625 }
626
GetConfig(std::unique_ptr<AVScreenCaptureAsyncContext> & asyncCtx,napi_env env,napi_value args)627 int32_t AVScreenCaptureNapi::GetConfig(std::unique_ptr<AVScreenCaptureAsyncContext> &asyncCtx,
628 napi_env env, napi_value args)
629 {
630 napi_valuetype valueType = napi_undefined;
631 if (args == nullptr || napi_typeof(env, args, &valueType) != napi_ok || valueType != napi_object) {
632 asyncCtx->AVScreenCaptureSignError(MSERR_INCORRECT_PARAMETER_TYPE, "GetConfig", "AVScreenCaptureRecordConfig",
633 "config type should be AVScreenCaptureRecordConfig.");
634 return MSERR_INCORRECT_PARAMETER_TYPE;
635 }
636
637 asyncCtx->config_.captureMode = CaptureMode::CAPTURE_HOME_SCREEN;
638 asyncCtx->config_.dataType = DataType::CAPTURE_FILE;
639
640 int32_t ret = GetAudioInfo(asyncCtx, env, args);
641 CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, ret, "failed to GetAudioInfo");
642 ret = GetVideoInfo(asyncCtx, env, args);
643 CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, ret, "failed to GetVideoInfo");
644 ret = GetRecorderInfo(asyncCtx, env, args);
645 CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, ret, "failed to GetRecorderInfo");
646 return MSERR_OK;
647 }
648
GetAudioInfo(std::unique_ptr<AVScreenCaptureAsyncContext> & asyncCtx,napi_env env,napi_value args)649 int32_t AVScreenCaptureNapi::GetAudioInfo(std::unique_ptr<AVScreenCaptureAsyncContext> &asyncCtx,
650 napi_env env, napi_value args)
651 {
652 int32_t audioSampleRate = AVSCREENCAPTURE_DEFAULT_AUDIO_SAMPLE_RATE;
653 int32_t audioChannels = AVSCREENCAPTURE_DEFAULT_AUDIO_CHANNELS;
654 int32_t audioBitrate = AVSCREENCAPTURE_DEFAULT_AUDIO_BIT_RATE;
655
656 AudioCaptureInfo &micConfig = asyncCtx->config_.audioInfo.micCapInfo;
657 AudioCaptureInfo &innerConfig = asyncCtx->config_.audioInfo.innerCapInfo;
658 AudioEncInfo &encoderConfig = asyncCtx->config_.audioInfo.audioEncInfo;
659
660 int32_t ret = AVScreenCaptureNapi::GetPropertyInt32(env, args, "audioSampleRate", audioSampleRate);
661 CHECK_AND_RETURN_RET(ret == MSERR_OK,
662 (asyncCtx->AVScreenCaptureSignError(ret, "getAudioSampleRate", "audioSampleRate"), ret));
663 ret = AVScreenCaptureNapi::CheckAudioSampleRate(audioSampleRate);
664 CHECK_AND_RETURN_RET(ret == MSERR_OK,
665 (asyncCtx->AVScreenCaptureSignError(ret, "getAudioSampleRate", "audioSampleRate"), ret));
666 micConfig.audioSampleRate = audioSampleRate;
667 innerConfig.audioSampleRate = audioSampleRate;
668 MEDIA_LOGI("input audioSampleRate %{public}d", micConfig.audioSampleRate);
669
670 ret = AVScreenCaptureNapi::GetPropertyInt32(env, args, "audioChannelCount", audioChannels);
671 CHECK_AND_RETURN_RET(ret == MSERR_OK,
672 (asyncCtx->AVScreenCaptureSignError(ret, "getAudioChannelCount", "audioChannelCount"), ret));
673 ret = AVScreenCaptureNapi::CheckAudioChannelCount(audioChannels);
674 CHECK_AND_RETURN_RET(ret == MSERR_OK,
675 (asyncCtx->AVScreenCaptureSignError(ret, "getAudioChannelCount", "audioChannelCount"), ret));
676 micConfig.audioChannels = audioChannels;
677 innerConfig.audioChannels = audioChannels;
678 MEDIA_LOGI("input audioChannelCount %{public}d", micConfig.audioChannels);
679 micConfig.audioSource = AudioCaptureSourceType::MIC;
680 innerConfig.audioSource = AudioCaptureSourceType::ALL_PLAYBACK;
681
682 ret = AVScreenCaptureNapi::GetPropertyInt32(env, args, "audioBitrate", audioBitrate);
683 CHECK_AND_RETURN_RET(ret == MSERR_OK,
684 (asyncCtx->AVScreenCaptureSignError(ret, "getAudioBitrate", "audioBitrate"), ret));
685 encoderConfig.audioBitrate = audioBitrate;
686 encoderConfig.audioCodecformat = AudioCodecFormat::AAC_LC;
687 MEDIA_LOGI("input audioBitrate %{public}d", encoderConfig.audioBitrate);
688 return MSERR_OK;
689 }
690
GetVideoInfo(std::unique_ptr<AVScreenCaptureAsyncContext> & asyncCtx,napi_env env,napi_value args)691 int32_t AVScreenCaptureNapi::GetVideoInfo(std::unique_ptr<AVScreenCaptureAsyncContext> &asyncCtx,
692 napi_env env, napi_value args)
693 {
694 int32_t videoBitrate = AVSCREENCAPTURE_DEFAULT_VIDEO_BIT_RATE;
695 int32_t preset = AVScreenCaptureRecorderPreset::SCREEN_RECORD_PRESET_H264_AAC_MP4;
696 int32_t frameWidth = AVSCREENCAPTURE_DEFAULT_FRAME_WIDTH;
697 int32_t frameHeight = AVSCREENCAPTURE_DEFAULT_FRAME_HEIGHT;
698 int32_t displayId = AVSCREENCAPTURE_DEFAULT_DISPLAY_ID;
699 int32_t fillMode = AVScreenCaptureFillMode::PRESERVE_ASPECT_RATIO;
700 VideoEncInfo &encoderConfig = asyncCtx->config_.videoInfo.videoEncInfo;
701 VideoCaptureInfo &videoConfig = asyncCtx->config_.videoInfo.videoCapInfo;
702 int32_t ret = AVScreenCaptureNapi::GetPropertyInt32(env, args, "displayId", displayId);
703 CHECK_AND_RETURN_RET(ret == MSERR_OK && displayId >= 0,
704 (asyncCtx->AVScreenCaptureSignError(MSERR_INVALID_VAL, "getDisplayId", "displayId"), MSERR_INVALID_VAL));
705 videoConfig.displayId = static_cast<uint64_t>(displayId);
706 if (videoConfig.displayId > 0) {
707 asyncCtx->config_.captureMode = CaptureMode::CAPTURE_SPECIFIED_SCREEN;
708 }
709 MEDIA_LOGI("input displayId %{public}" PRIu64, videoConfig.displayId);
710 ret = AVScreenCaptureNapi::GetPropertyInt32(env, args, "videoBitrate", videoBitrate);
711 CHECK_AND_RETURN_RET(ret == MSERR_OK,
712 (asyncCtx->AVScreenCaptureSignError(ret, "getVideoBitrate", "videoBitrate"), ret));
713 encoderConfig.videoBitrate = videoBitrate;
714 encoderConfig.videoFrameRate = AVSCREENCAPTURE_DEFAULT_VIDEO_FRAME_RATE;
715 MEDIA_LOGI("input videoBitrate %{public}d", encoderConfig.videoBitrate);
716 ret = AVScreenCaptureNapi::GetPropertyInt32(env, args, "preset", preset);
717 CHECK_AND_RETURN_RET(ret == MSERR_OK, (asyncCtx->AVScreenCaptureSignError(ret, "getPreset", "preset"), ret));
718 ret = AVScreenCaptureNapi::CheckVideoCodecFormat(preset);
719 CHECK_AND_RETURN_RET(ret == MSERR_OK, (asyncCtx->AVScreenCaptureSignError(ret, "getPreset", "preset"), ret));
720 encoderConfig.videoCodec = AVScreenCaptureNapi::GetVideoCodecFormat(preset);
721 MEDIA_LOGI("input videoCodec %{public}d", encoderConfig.videoCodec);
722 ret = AVScreenCaptureNapi::GetPropertyInt32(env, args, "frameWidth", frameWidth);
723 CHECK_AND_RETURN_RET(ret == MSERR_OK,
724 (asyncCtx->AVScreenCaptureSignError(ret, "getFrameWidth", "frameWidth"), ret));
725 ret = AVScreenCaptureNapi::GetPropertyInt32(env, args, "frameHeight", frameHeight);
726 CHECK_AND_RETURN_RET(ret == MSERR_OK,
727 (asyncCtx->AVScreenCaptureSignError(ret, "getFrameHeight", "frameHeight"), ret));
728 MEDIA_LOGI("input frameWidth %{public}d, frameHeight %{public}d", frameWidth, frameHeight);
729 ret = AVScreenCaptureNapi::CheckVideoFrameFormat(frameWidth, frameHeight,
730 videoConfig.videoFrameWidth, videoConfig.videoFrameHeight);
731 CHECK_AND_RETURN_RET(ret == MSERR_OK,
732 (asyncCtx->AVScreenCaptureSignError(ret, "getVideoFrame", "VideoFrame"), ret));
733 MEDIA_LOGI("input formatted frameWidth %{public}d, frameHeight %{public}d",
734 videoConfig.videoFrameWidth, videoConfig.videoFrameHeight);
735 videoConfig.videoSource = VideoSourceType::VIDEO_SOURCE_SURFACE_RGBA;
736 ret = AVScreenCaptureNapi::GetPropertyInt32(env, args, "fillMode", fillMode);
737 CHECK_AND_RETURN_RET(ret == MSERR_OK, (asyncCtx->AVScreenCaptureSignError(
738 ret, "getScreenCaptureFillMode", "screenCaptureFillMode"), ret));
739 videoConfig.screenCaptureFillMode = GetScreenCaptureFillMode(fillMode);
740 MEDIA_LOGI("input screenCaptureFillMode %{public}d", videoConfig.screenCaptureFillMode);
741 return MSERR_OK;
742 }
743
GetRecorderInfo(std::unique_ptr<AVScreenCaptureAsyncContext> & asyncCtx,napi_env env,napi_value args)744 int32_t AVScreenCaptureNapi::GetRecorderInfo(std::unique_ptr<AVScreenCaptureAsyncContext> &asyncCtx,
745 napi_env env, napi_value args)
746 {
747 RecorderInfo &recorderConfig = asyncCtx->config_.recorderInfo;
748 recorderConfig.fileFormat = AVSCREENCAPTURE_DEFAULT_FILE_FORMAT;
749 int32_t fd = -1;
750 (void)CommonNapi::GetPropertyInt32(env, args, "fd", fd);
751 CHECK_AND_RETURN_RET(fd > 0, // 0 to 2 for system std log
752 (asyncCtx->AVScreenCaptureSignError(MSERR_INVALID_VAL, "GetRecorderInfo", "url"), MSERR_INVALID_VAL));
753 recorderConfig.url = "fd://" + std::to_string(fd);
754 CHECK_AND_RETURN_RET(recorderConfig.url != "",
755 (asyncCtx->AVScreenCaptureSignError(MSERR_INVALID_VAL, "GetRecorderInfo", "url"), MSERR_INVALID_VAL));
756 MEDIA_LOGI("input url %{public}s", recorderConfig.url.c_str());
757 return MSERR_OK;
758 }
759
CheckAudioSampleRate(const int32_t & audioSampleRate)760 int32_t AVScreenCaptureNapi::CheckAudioSampleRate(const int32_t &audioSampleRate)
761 {
762 if (audioSampleRate == 48000 || audioSampleRate == 16000) { // 16000 48000 AudioSampleRate options
763 return MSERR_OK;
764 }
765 return MSERR_INVALID_VAL;
766 }
767
CheckAudioChannelCount(const int32_t & audioChannelCount)768 int32_t AVScreenCaptureNapi::CheckAudioChannelCount(const int32_t &audioChannelCount)
769 {
770 if (audioChannelCount == 1 || audioChannelCount == 2) { // 1 2 channelCount number options
771 return MSERR_OK;
772 }
773 return MSERR_INVALID_VAL;
774 }
775
CheckVideoFrameFormat(const int32_t & frameWidth,const int32_t & frameHeight,int32_t & videoFrameWidth,int32_t & videoFrameHeight)776 int32_t AVScreenCaptureNapi::CheckVideoFrameFormat(const int32_t &frameWidth, const int32_t &frameHeight,
777 int32_t &videoFrameWidth, int32_t &videoFrameHeight)
778 {
779 #ifndef CROSS_PLATFORM
780 if (frameWidth == AVSCREENCAPTURE_DEFAULT_FRAME_WIDTH || frameHeight == AVSCREENCAPTURE_DEFAULT_FRAME_HEIGHT ||
781 !(frameWidth == 0 && frameHeight == 0)) { // 0 one of width height is zero, use default display
782 sptr<Rosen::Display> display = Rosen::DisplayManager::GetInstance().GetDefaultDisplaySync();
783 if (display == nullptr) {
784 return MSERR_INVALID_VAL;
785 }
786 MEDIA_LOGI("check video frame get displayInfo width:%{public}d,height:%{public}d,density:%{public}f",
787 display->GetWidth(), display->GetHeight(), display->GetVirtualPixelRatio());
788 if (frameWidth == AVSCREENCAPTURE_DEFAULT_FRAME_WIDTH || frameWidth == 0) { // 0 use default display
789 videoFrameWidth = display->GetWidth();
790 } else {
791 videoFrameWidth = frameWidth;
792 }
793 if (frameHeight == AVSCREENCAPTURE_DEFAULT_FRAME_HEIGHT || frameHeight == 0) { // 0 use default display
794 videoFrameHeight = display->GetHeight();
795 } else {
796 videoFrameHeight = frameHeight;
797 }
798 } else {
799 videoFrameWidth = frameWidth;
800 videoFrameHeight = frameHeight;
801 }
802 #else
803 videoFrameWidth = frameWidth;
804 videoFrameHeight = frameHeight;
805 #endif
806 return MSERR_OK;
807 }
808
CheckVideoCodecFormat(const int32_t & preset)809 int32_t AVScreenCaptureNapi::CheckVideoCodecFormat(const int32_t &preset)
810 {
811 if (static_cast<int32_t>(AVScreenCaptureRecorderPreset::SCREEN_RECORD_PRESET_H264_AAC_MP4) <= preset &&
812 static_cast<int32_t>(AVScreenCaptureRecorderPreset::SCREEN_RECORD_PRESET_H265_AAC_MP4) >= preset) {
813 return MSERR_OK;
814 }
815 return MSERR_INVALID_VAL;
816 }
817
GetVideoCodecFormat(const int32_t & preset)818 VideoCodecFormat AVScreenCaptureNapi::GetVideoCodecFormat(const int32_t &preset)
819 {
820 const std::map<AVScreenCaptureRecorderPreset, VideoCodecFormat> presetToCodecFormat = {
821 { AVScreenCaptureRecorderPreset::SCREEN_RECORD_PRESET_H264_AAC_MP4, VideoCodecFormat::H264 },
822 { AVScreenCaptureRecorderPreset::SCREEN_RECORD_PRESET_H265_AAC_MP4, VideoCodecFormat::H265 }
823 };
824 VideoCodecFormat codecFormat = VideoCodecFormat::H264;
825 auto iter = presetToCodecFormat.find(static_cast<AVScreenCaptureRecorderPreset>(preset));
826 if (iter != presetToCodecFormat.end()) {
827 codecFormat = iter->second;
828 }
829 return codecFormat;
830 }
831
GetScreenCaptureFillMode(const int32_t & fillMode)832 AVScreenCaptureFillMode AVScreenCaptureNapi::GetScreenCaptureFillMode(const int32_t &fillMode)
833 {
834 MEDIA_LOGI("AVScreenCaptureNapi::GetScreenCaptureFillMode in!");
835 const std::map<int32_t, AVScreenCaptureFillMode> intToFillMode = {
836 { 0, AVScreenCaptureFillMode::PRESERVE_ASPECT_RATIO },
837 { 1, AVScreenCaptureFillMode::SCALE_TO_FILL }
838 };
839 AVScreenCaptureFillMode screenCaptureFillMode = AVScreenCaptureFillMode::PRESERVE_ASPECT_RATIO;
840 auto iter = intToFillMode.find(fillMode);
841 if (iter != intToFillMode.end()) {
842 screenCaptureFillMode = iter->second;
843 }
844 MEDIA_LOGI("AVScreenCaptureNapi::GetScreenCaptureFillMode succeed, screenCaptureFillMode: %{public}d",
845 screenCaptureFillMode);
846 return screenCaptureFillMode;
847 }
848
ErrorCallback(int32_t errCode,const std::string & operate,const std::string & add)849 void AVScreenCaptureNapi::ErrorCallback(int32_t errCode, const std::string &operate, const std::string &add)
850 {
851 MEDIA_LOGE("failed to %{public}s, errCode = %{public}d", operate.c_str(), errCode);
852 CHECK_AND_RETURN_LOG(screenCaptureCb_ != nullptr, "screenCaptureCb_ is nullptr!");
853 auto napiCb = std::static_pointer_cast<AVScreenCaptureCallback>(screenCaptureCb_);
854
855 MediaServiceExtErrCodeAPI9 err = MSErrorToExtErrorAPI9(static_cast<MediaServiceErrCode>(errCode));
856 std::string msg = MSExtErrorAPI9ToString(err, operate, "") + add;
857 napiCb->SendErrorCallback(errCode, msg);
858 }
859
StateCallback(const AVScreenCaptureStateCode & stateCode)860 void AVScreenCaptureNapi::StateCallback(const AVScreenCaptureStateCode &stateCode)
861 {
862 MEDIA_LOGI("Change state to %{public}d", stateCode);
863 CHECK_AND_RETURN_LOG(screenCaptureCb_ != nullptr, "screenCaptureCb_ is nullptr!");
864 auto napiCb = std::static_pointer_cast<AVScreenCaptureCallback>(screenCaptureCb_);
865 napiCb->SendStateCallback(stateCode);
866 }
867
SetCallbackReference(const std::string & callbackName,std::shared_ptr<AutoRef> ref)868 void AVScreenCaptureNapi::SetCallbackReference(const std::string &callbackName, std::shared_ptr<AutoRef> ref)
869 {
870 eventCbMap_[callbackName] = ref;
871 CHECK_AND_RETURN_LOG(screenCaptureCb_ != nullptr, "screenCaptureCb_ is nullptr!");
872 auto napiCb = std::static_pointer_cast<AVScreenCaptureCallback>(screenCaptureCb_);
873 napiCb->SaveCallbackReference(callbackName, ref);
874 }
875
CancelCallbackReference(const std::string & callbackName)876 void AVScreenCaptureNapi::CancelCallbackReference(const std::string &callbackName)
877 {
878 CHECK_AND_RETURN_LOG(screenCaptureCb_ != nullptr, "screenCaptureCb_ is nullptr!");
879 auto napiCb = std::static_pointer_cast<AVScreenCaptureCallback>(screenCaptureCb_);
880 napiCb->CancelCallbackReference(callbackName);
881 eventCbMap_[callbackName] = nullptr;
882 }
883
CancelCallback()884 void AVScreenCaptureNapi::CancelCallback()
885 {
886 CHECK_AND_RETURN_LOG(screenCaptureCb_ != nullptr, "screenCaptureCb_ is nullptr!");
887 auto napiCb = std::static_pointer_cast<AVScreenCaptureCallback>(screenCaptureCb_);
888 napiCb->ClearCallbackReference();
889 }
890
GetPromiseTask(AVScreenCaptureNapi * avnapi,const std::string & opt)891 std::shared_ptr<TaskHandler<RetInfo>> AVScreenCaptureNapi::GetPromiseTask(
892 AVScreenCaptureNapi *avnapi, const std::string &opt)
893 {
894 return std::make_shared<TaskHandler<RetInfo>>([napi = avnapi, option = opt]() {
895 MEDIA_LOGI("%{public}s Start", option.c_str());
896 CHECK_AND_RETURN_RET(napi != nullptr && napi->screenCapture_ != nullptr,
897 GetReturnInfo(MSERR_INVALID_OPERATION, option, ""));
898
899 RetInfo ret(MSERR_EXT_API9_OPERATE_NOT_PERMIT, "");
900 auto itFunc = taskQFuncs_.find(option);
901 CHECK_AND_RETURN_RET_LOG(itFunc != taskQFuncs_.end(), ret, "%{public}s not found in map!", option.c_str());
902 auto memberFunc = itFunc->second;
903 CHECK_AND_RETURN_RET_LOG(memberFunc != nullptr, ret, "memberFunc is nullptr!");
904 ret = (napi->*memberFunc)();
905
906 MEDIA_LOGI("%{public}s End", option.c_str());
907 return ret;
908 });
909 }
910
ExecuteByPromise(napi_env env,napi_callback_info info,const std::string & opt)911 napi_value AVScreenCaptureNapi::ExecuteByPromise(napi_env env, napi_callback_info info, const std::string &opt)
912 {
913 MEDIA_LOGI("Js %{public}s Start", opt.c_str());
914 napi_value result = nullptr;
915 napi_get_undefined(env, &result);
916 size_t argCount = 1; // Only callbackRef parameter
917 napi_value args[1] = { nullptr }; // Only callbackRef parameter
918
919 auto asyncCtx = std::make_unique<AVScreenCaptureAsyncContext>(env);
920 CHECK_AND_RETURN_RET_LOG(asyncCtx != nullptr, result, "failed to get AsyncContext");
921 asyncCtx->napi = AVScreenCaptureNapi::GetJsInstanceAndArgs(env, info, argCount, args);
922 CHECK_AND_RETURN_RET_LOG(asyncCtx->napi != nullptr, result, "failed to GetJsInstanceAndArgs");
923 CHECK_AND_RETURN_RET_LOG(asyncCtx->napi->taskQue_ != nullptr, result, "taskQue is nullptr!");
924
925 asyncCtx->callbackRef = CommonNapi::CreateReference(env, args[0]);
926 asyncCtx->deferred = CommonNapi::CreatePromise(env, asyncCtx->callbackRef, result);
927
928 asyncCtx->task_ = AVScreenCaptureNapi::GetPromiseTask(asyncCtx->napi, opt);
929 (void)asyncCtx->napi->taskQue_->EnqueueTask(asyncCtx->task_);
930 asyncCtx->opt_ = opt;
931
932 napi_value resource = nullptr;
933 napi_create_string_utf8(env, opt.c_str(), NAPI_AUTO_LENGTH, &resource);
934 NAPI_CALL(env, napi_create_async_work(env, nullptr, resource, [](napi_env env, void* data) {
935 AVScreenCaptureAsyncContext* asyncCtx = reinterpret_cast<AVScreenCaptureAsyncContext *>(data);
936 CHECK_AND_RETURN_LOG(asyncCtx != nullptr, "asyncCtx is nullptr!");
937
938 if (asyncCtx->task_) {
939 auto result = asyncCtx->task_->GetResult();
940 if (result.Value().first != MSERR_EXT_API9_OK) {
941 asyncCtx->SignError(result.Value().first, result.Value().second);
942 }
943
944 if (result.Value().first == MSERR_EXT_API9_OK) {
945 asyncCtx->JsResult = std::make_unique<MediaJsResultString>(result.Value().second);
946 }
947 }
948 MEDIA_LOGI("The js thread of %{public}s finishes execution and returns", asyncCtx->opt_.c_str());
949 }, MediaAsyncContext::CompleteCallback, static_cast<void *>(asyncCtx.get()), &asyncCtx->work));
950 NAPI_CALL(env, napi_queue_async_work_with_qos(env, asyncCtx->work, napi_qos_user_initiated));
951 asyncCtx.release();
952
953 MEDIA_LOGI("Js %{public}s End", opt.c_str());
954 return result;
955 }
956
GetPropertyInt32(napi_env env,napi_value configObj,const std::string & type,int32_t & result)957 int32_t AVScreenCaptureNapi::GetPropertyInt32(napi_env env, napi_value configObj, const std::string &type,
958 int32_t &result)
959 {
960 napi_value item = nullptr;
961 bool exist = false;
962 napi_status status = napi_has_named_property(env, configObj, type.c_str(), &exist);
963 if (status != napi_ok || !exist) {
964 MEDIA_LOGI("can not find %{public}s property", type.c_str());
965 return MSERR_OK;
966 }
967
968 if (napi_get_named_property(env, configObj, type.c_str(), &item) != napi_ok) {
969 MEDIA_LOGI("get %{public}s property fail", type.c_str());
970 return MSERR_UNKNOWN;
971 }
972
973 if (napi_get_value_int32(env, item, &result) != napi_ok) {
974 std::string string = CommonNapi::GetStringArgument(env, item);
975 if (string == "") {
976 // This attribute has not been assigned
977 return MSERR_OK;
978 } else {
979 MEDIA_LOGE("get %{public}s property value fail", type.c_str());
980 return MSERR_INVALID_VAL;
981 }
982 }
983
984 MEDIA_LOGI("get %{public}s : %{public}d!", type.c_str(), result);
985 return MSERR_OK;
986 }
987
AVScreenCaptureSignError(int32_t errCode,const std::string & operate,const std::string & param,const std::string & add)988 void AVScreenCaptureAsyncContext::AVScreenCaptureSignError(int32_t errCode, const std::string &operate,
989 const std::string ¶m, const std::string &add)
990 {
991 RetInfo retInfo = GetReturnInfo(errCode, operate, param, add);
992 SignError(retInfo.first, retInfo.second);
993 }
994
995 } // namespace Media
996 } // namespace OHOS