• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 &param,
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 &param, 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