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 &param,
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 &param, 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