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