1 /*
2  * Copyright (C) 2022 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 <climits>
17 #include "avrecorder_callback.h"
18 #include "media_dfx.h"
19 #include "media_log.h"
20 #include "media_errors.h"
21 #include "scope_guard.h"
22 #include "common_napi.h"
23 #include "surface_utils.h"
24 #include "string_ex.h"
25 #include "avcodec_info.h"
26 #include "av_common.h"
27 #ifdef SUPPORT_JSSTACK
28 #include "xpower_event_js.h"
29 #endif
30 #include "avrecorder_napi.h"
31 
32 namespace {
33     constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, LOG_DOMAIN_RECORDER, "AVRecorderNapi"};
34 }
35 
36 namespace OHOS {
37 namespace Media {
38 using namespace MediaAVCodec;
39 
40 thread_local napi_ref AVRecorderNapi::constructor_ = nullptr;
41 const std::string CLASS_NAME = "AVRecorder";
42 std::map<std::string, AVRecorderNapi::AvRecorderTaskqFunc> AVRecorderNapi::taskQFuncs_ = {
43     {AVRecordergOpt::GETINPUTSURFACE, &AVRecorderNapi::GetInputSurface},
44     {AVRecordergOpt::START, &AVRecorderNapi::Start},
45     {AVRecordergOpt::PAUSE, &AVRecorderNapi::Pause},
46     {AVRecordergOpt::RESUME, &AVRecorderNapi::Resume},
47     {AVRecordergOpt::STOP, &AVRecorderNapi::Stop},
48     {AVRecordergOpt::RESET, &AVRecorderNapi::Reset},
49     {AVRecordergOpt::RELEASE, &AVRecorderNapi::Release},
50 };
51 
AVRecorderNapi()52 AVRecorderNapi::AVRecorderNapi()
53 {
54     MEDIA_LOGI("0x%{public}06" PRIXPTR "Instances create", FAKE_POINTER(this));
55 }
56 
~AVRecorderNapi()57 AVRecorderNapi::~AVRecorderNapi()
58 {
59     MEDIA_LOGI("0x%{public}06" PRIXPTR "Instances destroy", FAKE_POINTER(this));
60 }
61 
Init(napi_env env,napi_value exports)62 napi_value AVRecorderNapi::Init(napi_env env, napi_value exports)
63 {
64     MEDIA_LOGI("JS Init Start");
65     napi_property_descriptor staticProperty[] = {
66         DECLARE_NAPI_STATIC_FUNCTION("createAVRecorder", JsCreateAVRecorder),
67     };
68 
69     napi_property_descriptor properties[] = {
70         DECLARE_NAPI_FUNCTION("prepare", JsPrepare),
71         DECLARE_NAPI_FUNCTION("SetOrientationHint", JsSetOrientationHint),
72         DECLARE_NAPI_FUNCTION("updateRotation", JsSetOrientationHint),
73         DECLARE_NAPI_FUNCTION("getInputSurface", JsGetInputSurface),
74         DECLARE_NAPI_FUNCTION("getInputMetaSurface", JsGetInputMetaSurface),
75         DECLARE_NAPI_FUNCTION("start", JsStart),
76         DECLARE_NAPI_FUNCTION("pause", JsPause),
77         DECLARE_NAPI_FUNCTION("resume", JsResume),
78         DECLARE_NAPI_FUNCTION("stop", JsStop),
79         DECLARE_NAPI_FUNCTION("reset", JsReset),
80         DECLARE_NAPI_FUNCTION("release", JsRelease),
81         DECLARE_NAPI_FUNCTION("on", JsSetEventCallback),
82         DECLARE_NAPI_FUNCTION("off", JsCancelEventCallback),
83         DECLARE_NAPI_FUNCTION("getAVRecorderProfile", JsGetAVRecorderProfile),
84         DECLARE_NAPI_FUNCTION("setAVRecorderConfig", JsSetAVRecorderConfig),
85         DECLARE_NAPI_FUNCTION("getAVRecorderConfig", JsGetAVRecorderConfig),
86         DECLARE_NAPI_FUNCTION("getCurrentAudioCapturerInfo", JsGetCurrentAudioCapturerInfo),
87         DECLARE_NAPI_FUNCTION("getAudioCapturerMaxAmplitude", JsGetAudioCapturerMaxAmplitude),
88         DECLARE_NAPI_FUNCTION("getAvailableEncoder", JsGetAvailableEncoder),
89         DECLARE_NAPI_FUNCTION("setWatermark", JsSetWatermark),
90         DECLARE_NAPI_FUNCTION("isWatermarkSupported", JsIsWatermarkSupported),
91 
92         DECLARE_NAPI_GETTER("state", JsGetState),
93     };
94 
95     napi_value constructor = nullptr;
96     napi_status status = napi_define_class(env, CLASS_NAME.c_str(), NAPI_AUTO_LENGTH, Constructor, nullptr,
97                                            sizeof(properties) / sizeof(properties[0]), properties, &constructor);
98     CHECK_AND_RETURN_RET_LOG(status == napi_ok, nullptr, "Failed to define AVRecorder class");
99 
100     status = napi_create_reference(env, constructor, 1, &constructor_);
101     CHECK_AND_RETURN_RET_LOG(status == napi_ok, nullptr, "Failed to create reference of constructor");
102 
103     status = napi_set_named_property(env, exports, CLASS_NAME.c_str(), constructor);
104     CHECK_AND_RETURN_RET_LOG(status == napi_ok, nullptr, "Failed to set constructor");
105 
106     status = napi_define_properties(env, exports, sizeof(staticProperty) / sizeof(staticProperty[0]), staticProperty);
107     CHECK_AND_RETURN_RET_LOG(status == napi_ok, nullptr, "Failed to define static function");
108 
109     MEDIA_LOGI("Js Init End");
110     return exports;
111 }
112 
Constructor(napi_env env,napi_callback_info info)113 napi_value AVRecorderNapi::Constructor(napi_env env, napi_callback_info info)
114 {
115     MediaTrace trace("AVRecorder::Constructor");
116     MEDIA_LOGI("Js Constructor Start");
117     napi_value result = nullptr;
118     napi_get_undefined(env, &result);
119 
120     size_t argCount = 0;
121     napi_value jsThis = nullptr;
122     napi_status status = napi_get_cb_info(env, info, &argCount, nullptr, &jsThis, nullptr);
123     CHECK_AND_RETURN_RET_LOG(status == napi_ok, result, "failed to napi_get_cb_info");
124 
125     AVRecorderNapi *jsRecorder = new(std::nothrow) AVRecorderNapi();
126     CHECK_AND_RETURN_RET_LOG(jsRecorder != nullptr, result, "failed to new AVRecorderNapi");
127 
128     jsRecorder->env_ = env;
129     jsRecorder->recorder_ = RecorderFactory::CreateRecorder();
130     CHECK_AND_RETURN_RET_LOG(jsRecorder->recorder_ != nullptr, result, "failed to CreateRecorder");
131 
132     jsRecorder->taskQue_ = std::make_unique<TaskQueue>("OS_AVRecordNapi");
133     (void)jsRecorder->taskQue_->Start();
134 
135     jsRecorder->recorderCb_ = std::make_shared<AVRecorderCallback>(env);
136     CHECK_AND_RETURN_RET_LOG(jsRecorder->recorderCb_ != nullptr, result, "failed to CreateRecorderCb");
137     (void)jsRecorder->recorder_->SetRecorderCallback(jsRecorder->recorderCb_);
138 
139     status = napi_wrap(env, jsThis, reinterpret_cast<void *>(jsRecorder),
140                        AVRecorderNapi::Destructor, nullptr, nullptr);
141     if (status != napi_ok) {
142         delete jsRecorder;
143         MEDIA_LOGE("Failed to wrap native instance");
144         return result;
145     }
146 
147     MEDIA_LOGI("Js Constructor End");
148     return jsThis;
149 }
150 
Destructor(napi_env env,void * nativeObject,void * finalize)151 void AVRecorderNapi::Destructor(napi_env env, void *nativeObject, void *finalize)
152 {
153     MediaTrace trace("AVRecorder::Destructor");
154     MEDIA_LOGI("Js Destructor Start");
155     (void)finalize;
156     if (nativeObject != nullptr) {
157         AVRecorderNapi *napi = reinterpret_cast<AVRecorderNapi *>(nativeObject);
158         if (napi->taskQue_ != nullptr) {
159             (void)napi->taskQue_->Stop();
160         }
161 
162         napi->RemoveSurface();
163         napi->recorderCb_ = nullptr;
164 
165         if (napi->recorder_) {
166             napi->recorder_->Release();
167             napi->recorder_ = nullptr;
168         }
169 
170         delete napi;
171     }
172     MEDIA_LOGI("Js Destructor End");
173 }
174 
JsCreateAVRecorder(napi_env env,napi_callback_info info)175 napi_value AVRecorderNapi::JsCreateAVRecorder(napi_env env, napi_callback_info info)
176 {
177     MediaTrace trace("AVRecorder::JsCreateAVRecorder");
178     MEDIA_LOGI("Js CreateAVRecorder Start");
179     napi_value result = nullptr;
180     napi_get_undefined(env, &result);
181 
182     // get args
183     napi_value jsThis = nullptr;
184     napi_value args[1] = { nullptr };
185     size_t argCount = 1;
186     napi_status status = napi_get_cb_info(env, info, &argCount, args, &jsThis, nullptr);
187     CHECK_AND_RETURN_RET_LOG(status == napi_ok, result, "failed to napi_get_cb_info");
188 
189     std::unique_ptr<AVRecorderAsyncContext> asyncCtx = std::make_unique<AVRecorderAsyncContext>(env);
190     CHECK_AND_RETURN_RET_LOG(asyncCtx != nullptr, result, "failed to get AsyncContext");
191 
192     asyncCtx->callbackRef = CommonNapi::CreateReference(env, args[0]);
193     asyncCtx->deferred = CommonNapi::CreatePromise(env, asyncCtx->callbackRef, result);
194     asyncCtx->JsResult = std::make_unique<MediaJsResultInstance>(constructor_);
195     asyncCtx->ctorFlag = true;
196 
197     napi_value resource = nullptr;
198     napi_create_string_utf8(env, "JsCreateAVRecorder", NAPI_AUTO_LENGTH, &resource);
199     NAPI_CALL(env, napi_create_async_work(env, nullptr, resource, [](napi_env env, void* data) {},
200               MediaAsyncContext::CompleteCallback, static_cast<void *>(asyncCtx.get()), &asyncCtx->work));
201     NAPI_CALL(env, napi_queue_async_work_with_qos(env, asyncCtx->work, napi_qos_user_initiated));
202     asyncCtx.release();
203 
204     MEDIA_LOGI("Js CreateAVRecorder End");
205     return result;
206 }
207 
GetRetInfo(int32_t errCode,const std::string & operate,const std::string & param,const std::string & add="")208 RetInfo GetRetInfo(int32_t errCode, const std::string &operate, const std::string &param, const std::string &add = "")
209 {
210     MEDIA_LOGE("failed to %{public}s, param %{public}s, errCode = %{public}d", operate.c_str(), param.c_str(), errCode);
211     MediaServiceExtErrCodeAPI9 err = MSErrorToExtErrorAPI9(static_cast<MediaServiceErrCode>(errCode));
212     if (errCode == MSERR_UNSUPPORT_VID_PARAMS) {
213         return RetInfo(err, "The video parameter is not supported. Please check the type and range.");
214     }
215 
216     if (errCode == MSERR_UNSUPPORT_AUD_PARAMS) {
217         return RetInfo(err, "The audio parameter is not supported. Please check the type and range.");
218     }
219 
220     std::string message;
221     if (err == MSERR_EXT_API9_INVALID_PARAMETER) {
222         message = MSExtErrorAPI9ToString(err, param, "") + add;
223     } else {
224         message = MSExtErrorAPI9ToString(err, operate, "") + add;
225     }
226 
227     MEDIA_LOGE("errCode: %{public}d, errMsg: %{public}s", err, message.c_str());
228     return RetInfo(err, message);
229 }
230 
JsPrepare(napi_env env,napi_callback_info info)231 napi_value AVRecorderNapi::JsPrepare(napi_env env, napi_callback_info info)
232 {
233     MediaTrace trace("AVRecorder::JsPrepare");
234     const std::string &opt = AVRecordergOpt::PREPARE;
235     MEDIA_LOGI("Js %{public}s Start", opt.c_str());
236 
237     const int32_t maxParam = 2; // config + callbackRef
238     size_t argCount = maxParam;
239     napi_value args[maxParam] = { nullptr };
240 
241     napi_value result = nullptr;
242     napi_get_undefined(env, &result);
243 
244     auto asyncCtx = std::make_unique<AVRecorderAsyncContext>(env);
245     CHECK_AND_RETURN_RET_LOG(asyncCtx != nullptr, result, "failed to get AsyncContext");
246     asyncCtx->napi = AVRecorderNapi::GetJsInstanceAndArgs(env, info, argCount, args);
247     CHECK_AND_RETURN_RET_LOG(asyncCtx->napi != nullptr, result, "failed to GetJsInstanceAndArgs");
248     CHECK_AND_RETURN_RET_LOG(asyncCtx->napi->taskQue_ != nullptr, result, "taskQue is nullptr!");
249 
250     asyncCtx->callbackRef = CommonNapi::CreateReference(env, args[1]);
251     asyncCtx->deferred = CommonNapi::CreatePromise(env, asyncCtx->callbackRef, result);
252 
253     if (asyncCtx->napi->CheckStateMachine(opt) == MSERR_OK) {
254         if (asyncCtx->napi->GetConfig(asyncCtx, env, args[0]) == MSERR_OK) {
255             asyncCtx->task_ = AVRecorderNapi::GetPrepareTask(asyncCtx);
256             (void)asyncCtx->napi->taskQue_->EnqueueTask(asyncCtx->task_);
257         }
258     } else {
259         asyncCtx->AVRecorderSignError(MSERR_INVALID_OPERATION, opt, "");
260     }
261 
262     napi_value resource = nullptr;
263     napi_create_string_utf8(env, opt.c_str(), NAPI_AUTO_LENGTH, &resource);
264     NAPI_CALL(env, napi_create_async_work(env, nullptr, resource, [](napi_env env, void* data) {
265         AVRecorderAsyncContext* asyncCtx = reinterpret_cast<AVRecorderAsyncContext *>(data);
266         CHECK_AND_RETURN_LOG(asyncCtx != nullptr, "asyncCtx is nullptr!");
267 
268         if (asyncCtx->task_) {
269             auto result = asyncCtx->task_->GetResult();
270             if (result.Value().first != MSERR_EXT_API9_OK) {
271                 asyncCtx->SignError(result.Value().first, result.Value().second);
272             }
273         }
274         MEDIA_LOGI("The js thread of prepare finishes execution and returns");
275     }, MediaAsyncContext::CompleteCallback, static_cast<void *>(asyncCtx.get()), &asyncCtx->work));
276     NAPI_CALL(env, napi_queue_async_work_with_qos(env, asyncCtx->work, napi_qos_user_initiated));
277     asyncCtx.release();
278 
279     MEDIA_LOGI("Js %{public}s End", opt.c_str());
280     return result;
281 }
282 
JsSetOrientationHint(napi_env env,napi_callback_info info)283 napi_value AVRecorderNapi::JsSetOrientationHint(napi_env env, napi_callback_info info)
284 {
285     MediaTrace trace("AVRecorder::JsSetOrientationHint");
286     const std::string &opt = AVRecordergOpt::SET_ORIENTATION_HINT;
287     MEDIA_LOGI("Js %{public}s Start", opt.c_str());
288 
289     const int32_t maxParam = 2; // config + callbackRef
290     size_t argCount = maxParam;
291     napi_value args[maxParam] = { nullptr };
292 
293     napi_value result = nullptr;
294     napi_get_undefined(env, &result);
295 
296     auto asyncCtx = std::make_unique<AVRecorderAsyncContext>(env);
297     CHECK_AND_RETURN_RET_LOG(asyncCtx != nullptr, result, "failed to get AsyncContext");
298     asyncCtx->napi = AVRecorderNapi::GetJsInstanceAndArgs(env, info, argCount, args);
299     CHECK_AND_RETURN_RET_LOG(asyncCtx->napi != nullptr, result, "failed to GetJsInstanceAndArgs");
300     CHECK_AND_RETURN_RET_LOG(asyncCtx->napi->taskQue_ != nullptr, result, "taskQue is nullptr!");
301 
302     asyncCtx->callbackRef = CommonNapi::CreateReference(env, args[1]);
303     asyncCtx->deferred = CommonNapi::CreatePromise(env, asyncCtx->callbackRef, result);
304 
305     if (asyncCtx->napi->CheckStateMachine(opt) == MSERR_OK) {
306         if (asyncCtx->napi->GetRotation(asyncCtx, env, args[0]) == MSERR_OK) {
307             asyncCtx->task_ = AVRecorderNapi::GetSetOrientationHintTask(asyncCtx);
308             (void)asyncCtx->napi->taskQue_->EnqueueTask(asyncCtx->task_);
309         }
310     } else {
311         asyncCtx->AVRecorderSignError(MSERR_INVALID_OPERATION, opt, "");
312     }
313 
314     napi_value resource = nullptr;
315     napi_create_string_utf8(env, opt.c_str(), NAPI_AUTO_LENGTH, &resource);
316     NAPI_CALL(env, napi_create_async_work(env, nullptr, resource, [](napi_env env, void* data) {
317         AVRecorderAsyncContext* asyncCtx = reinterpret_cast<AVRecorderAsyncContext *>(data);
318         CHECK_AND_RETURN_LOG(asyncCtx != nullptr, "asyncCtx is nullptr!");
319 
320         if (asyncCtx->task_) {
321             auto result = asyncCtx->task_->GetResult();
322             if (result.Value().first != MSERR_EXT_API9_OK) {
323                 asyncCtx->SignError(result.Value().first, result.Value().second);
324             }
325         }
326         MEDIA_LOGI("The js thread of prepare finishes execution and returns");
327     }, MediaAsyncContext::CompleteCallback, static_cast<void *>(asyncCtx.get()), &asyncCtx->work));
328     NAPI_CALL(env, napi_queue_async_work_with_qos(env, asyncCtx->work, napi_qos_user_initiated));
329     asyncCtx.release();
330 
331     MEDIA_LOGI("Js %{public}s End", opt.c_str());
332     return result;
333 }
334 
JsSetWatermark(napi_env env,napi_callback_info info)335 napi_value AVRecorderNapi::JsSetWatermark(napi_env env, napi_callback_info info)
336 {
337     MediaTrace trace("AVRecorder::JsSetWatermark");
338     const std::string &opt = AVRecordergOpt::SET_WATERMARK;
339     MEDIA_LOGI("Js %{public}s Start", opt.c_str());
340 
341     const int32_t maxParam = 2; // pixelMap + WatermarkConfig
342     size_t argCount = maxParam;
343     napi_value args[maxParam] = { nullptr };
344 
345     napi_value result = nullptr;
346     napi_get_undefined(env, &result);
347 
348     auto asyncCtx = std::make_unique<AVRecorderAsyncContext>(env);
349     CHECK_AND_RETURN_RET_LOG(asyncCtx != nullptr, result, "failed to get AsyncContext");
350     asyncCtx->napi = AVRecorderNapi::GetJsInstanceAndArgs(env, info, argCount, args);
351     CHECK_AND_RETURN_RET_LOG(asyncCtx->napi != nullptr, result, "failed to GetJsInstanceAndArgs");
352     CHECK_AND_RETURN_RET_LOG(asyncCtx->napi->taskQue_ != nullptr, result, "taskQue is nullptr!");
353 
354     asyncCtx->deferred = CommonNapi::CreatePromise(env, nullptr, result);
355 
356     if (asyncCtx->napi->CheckStateMachine(opt) == MSERR_OK) {
357         if (asyncCtx->napi->GetWatermarkParameter(asyncCtx, env, args[0], args[1]) == MSERR_OK) {
358             asyncCtx->task_ = AVRecorderNapi::SetWatermarkTask(asyncCtx);
359             (void)asyncCtx->napi->taskQue_->EnqueueTask(asyncCtx->task_);
360         }
361     } else {
362         asyncCtx->AVRecorderSignError(MSERR_INVALID_OPERATION, opt, "");
363     }
364 
365     napi_value resource = nullptr;
366     napi_create_string_utf8(env, opt.c_str(), NAPI_AUTO_LENGTH, &resource);
367     NAPI_CALL(env, napi_create_async_work(env, nullptr, resource, [](napi_env env, void* data) {
368         AVRecorderAsyncContext* asyncCtx = reinterpret_cast<AVRecorderAsyncContext *>(data);
369         CHECK_AND_RETURN_LOG(asyncCtx != nullptr, "asyncCtx is nullptr!");
370 
371         if (asyncCtx->task_) {
372             auto result = asyncCtx->task_->GetResult();
373             if (result.Value().first != MSERR_EXT_API9_OK) {
374                 asyncCtx->SignError(result.Value().first, result.Value().second);
375             }
376         }
377         MEDIA_LOGI("The js thread of setWatermark finishes execution and returns");
378     }, MediaAsyncContext::CompleteCallback, static_cast<void *>(asyncCtx.get()), &asyncCtx->work));
379     NAPI_CALL(env, napi_queue_async_work_with_qos(env, asyncCtx->work, napi_qos_user_initiated));
380     asyncCtx.release();
381 
382     MEDIA_LOGI("Js %{public}s End", opt.c_str());
383     return result;
384 }
385 
GetPrepareTask(std::unique_ptr<AVRecorderAsyncContext> & asyncCtx)386 std::shared_ptr<TaskHandler<RetInfo>> AVRecorderNapi::GetPrepareTask(std::unique_ptr<AVRecorderAsyncContext> &asyncCtx)
387 {
388     return std::make_shared<TaskHandler<RetInfo>>([napi = asyncCtx->napi, config = asyncCtx->config_]() {
389         const std::string &option = AVRecordergOpt::PREPARE;
390         MEDIA_LOGI("%{public}s Start", option.c_str());
391         CHECK_AND_RETURN_RET(napi != nullptr && napi->recorder_ != nullptr && config != nullptr,
392             GetRetInfo(MSERR_INVALID_OPERATION, option, ""));
393 
394         CHECK_AND_RETURN_RET(napi->CheckStateMachine(option) == MSERR_OK,
395             GetRetInfo(MSERR_INVALID_OPERATION, option, ""));
396 
397         RetInfo retinfo = napi->Configure(config);
398         CHECK_AND_RETURN_RET(retinfo.first == MSERR_OK, ((void)napi->recorder_->Reset(), retinfo));
399 
400         int32_t ret = napi->recorder_->Prepare();
401         CHECK_AND_RETURN_RET(ret == MSERR_OK, ((void)napi->recorder_->Reset(), GetRetInfo(ret, "Prepare", "")));
402 
403         napi->RemoveSurface();
404         napi->StateCallback(AVRecorderState::STATE_PREPARED);
405         napi->getVideoInputSurface_ = false;
406         napi->withVideo_ = config->withVideo;
407         MEDIA_LOGI("%{public}s End", option.c_str());
408         return RetInfo(MSERR_EXT_API9_OK, "");
409     });
410 }
411 
GetSetOrientationHintTask(const std::unique_ptr<AVRecorderAsyncContext> & asyncCtx)412 std::shared_ptr<TaskHandler<RetInfo>> AVRecorderNapi::GetSetOrientationHintTask(
413     const std::unique_ptr<AVRecorderAsyncContext> &asyncCtx)
414 {
415     return std::make_shared<TaskHandler<RetInfo>>([napi = asyncCtx->napi, config = asyncCtx->config_]() {
416         const std::string &option = AVRecordergOpt::SET_ORIENTATION_HINT;
417         MEDIA_LOGI("%{public}s Start", option.c_str());
418         CHECK_AND_RETURN_RET(napi != nullptr && napi->recorder_ != nullptr && config != nullptr,
419             GetRetInfo(MSERR_INVALID_OPERATION, option, ""));
420 
421         CHECK_AND_RETURN_RET(napi->CheckStateMachine(option) == MSERR_OK,
422             GetRetInfo(MSERR_INVALID_OPERATION, option, ""));
423 
424         napi->recorder_->SetOrientationHint(config->rotation);
425 
426         MEDIA_LOGI("%{public}s End", option.c_str());
427         return RetInfo(MSERR_EXT_API9_OK, "");
428     });
429 }
430 
JsGetInputSurface(napi_env env,napi_callback_info info)431 napi_value AVRecorderNapi::JsGetInputSurface(napi_env env, napi_callback_info info)
432 {
433     MediaTrace trace("AVRecorder::JsGetInputSurface");
434     MEDIA_LOGI("Js GetInputSurface Enter");
435     return ExecuteByPromise(env, info, AVRecordergOpt::GETINPUTSURFACE);
436 }
437 
JsGetInputMetaSurface(napi_env env,napi_callback_info info)438 napi_value AVRecorderNapi::JsGetInputMetaSurface(napi_env env, napi_callback_info info)
439 {
440     MediaTrace trace("AVRecorder::JsGetInputMetaSurface");
441     const std::string &opt = AVRecordergOpt::GETINPUTMETASURFACE;
442     MEDIA_LOGI("Js %{public}s Start", opt.c_str());
443 
444     napi_value args[1] = { nullptr };
445     size_t argCount = 1;
446 
447     napi_value result = nullptr;
448     napi_get_undefined(env, &result);
449 
450     auto asyncCtx = std::make_unique<AVRecorderAsyncContext>(env);
451     CHECK_AND_RETURN_RET_LOG(asyncCtx != nullptr, result, "failed to get AsyncContext");
452     asyncCtx->napi = AVRecorderNapi::GetJsInstanceAndArgs(env, info, argCount, args);
453     CHECK_AND_RETURN_RET_LOG(asyncCtx->napi != nullptr, result, "failed to GetJsInstanceAndArgs");
454     CHECK_AND_RETURN_RET_LOG(asyncCtx->napi->taskQue_ != nullptr, result, "taskQue is nullptr!");
455 
456     asyncCtx->callbackRef = CommonNapi::CreateReference(env, args[0]);
457     asyncCtx->deferred = CommonNapi::CreatePromise(env, asyncCtx->callbackRef, result);
458 
459     if (asyncCtx->napi->CheckStateMachine(opt) == MSERR_OK) {
460         if (asyncCtx->napi->GetMetaType(asyncCtx, env, args[0]) == MSERR_OK) {
461             asyncCtx->task_ = AVRecorderNapi::GetInputMetaSurface(asyncCtx);
462             (void)asyncCtx->napi->taskQue_->EnqueueTask(asyncCtx->task_);
463         }
464     } else {
465         asyncCtx->AVRecorderSignError(MSERR_INVALID_OPERATION, opt, "");
466     }
467 
468     napi_value resource = nullptr;
469     napi_create_string_utf8(env, opt.c_str(), NAPI_AUTO_LENGTH, &resource);
470     NAPI_CALL(env, napi_create_async_work(env, nullptr, resource, [](napi_env env, void* data) {
471         AVRecorderAsyncContext* asyncCtx = reinterpret_cast<AVRecorderAsyncContext *>(data);
472         CHECK_AND_RETURN_LOG(asyncCtx != nullptr, "asyncCtx is nullptr!");
473 
474         if (asyncCtx->task_) {
475             auto result = asyncCtx->task_->GetResult();
476             if (result.Value().first != MSERR_EXT_API9_OK) {
477                 asyncCtx->SignError(result.Value().first, result.Value().second);
478             } else {
479                 asyncCtx->JsResult = std::make_unique<MediaJsResultString>(result.Value().second);
480             }
481         }
482         MEDIA_LOGI("The js thread of getInputMetaSurface finishes execution and returns");
483     }, MediaAsyncContext::CompleteCallback, static_cast<void *>(asyncCtx.get()), &asyncCtx->work));
484     NAPI_CALL(env, napi_queue_async_work_with_qos(env, asyncCtx->work, napi_qos_user_initiated));
485     asyncCtx.release();
486 
487     MEDIA_LOGI("Js %{public}s End", opt.c_str());
488     return result;
489 }
490 
JsStart(napi_env env,napi_callback_info info)491 napi_value AVRecorderNapi::JsStart(napi_env env, napi_callback_info info)
492 {
493     MediaTrace trace("AVRecorder::JsStart");
494     MEDIA_LOGI("Js Start Enter");
495 #ifdef SUPPORT_JSSTACK
496     HiviewDFX::ReportXPowerJsStackSysEvent(env, "STREAM_CHANGE", "SRC=Media");
497 #endif
498     return ExecuteByPromise(env, info, AVRecordergOpt::START);
499 }
500 
JsPause(napi_env env,napi_callback_info info)501 napi_value AVRecorderNapi::JsPause(napi_env env, napi_callback_info info)
502 {
503     MediaTrace trace("AVRecorder::JsPause");
504     MEDIA_LOGI("Js Pause Enter");
505     return ExecuteByPromise(env, info, AVRecordergOpt::PAUSE);
506 }
507 
JsResume(napi_env env,napi_callback_info info)508 napi_value AVRecorderNapi::JsResume(napi_env env, napi_callback_info info)
509 {
510     MediaTrace trace("AVRecorder::JsResume");
511     MEDIA_LOGI("Js Resume Enter");
512 #ifdef SUPPORT_JSSTACK
513     HiviewDFX::ReportXPowerJsStackSysEvent(env, "STREAM_CHANGE", "SRC=Media");
514 #endif
515     return ExecuteByPromise(env, info, AVRecordergOpt::RESUME);
516 }
517 
JsStop(napi_env env,napi_callback_info info)518 napi_value AVRecorderNapi::JsStop(napi_env env, napi_callback_info info)
519 {
520     MediaTrace trace("AVRecorder::JsStop");
521     MEDIA_LOGI("Js Stop Enter");
522     return ExecuteByPromise(env, info, AVRecordergOpt::STOP);
523 }
524 
JsReset(napi_env env,napi_callback_info info)525 napi_value AVRecorderNapi::JsReset(napi_env env, napi_callback_info info)
526 {
527     MediaTrace trace("AVRecorder::JsReset");
528     MEDIA_LOGI("Js Reset Enter");
529     return ExecuteByPromise(env, info, AVRecordergOpt::RESET);
530 }
531 
JsRelease(napi_env env,napi_callback_info info)532 napi_value AVRecorderNapi::JsRelease(napi_env env, napi_callback_info info)
533 {
534     MediaTrace trace("AVRecorder::JsRelease");
535     MEDIA_LOGI("Js Release Enter");
536     return ExecuteByPromise(env, info, AVRecordergOpt::RELEASE);
537 }
538 
JsGetAVRecorderProfile(napi_env env,napi_callback_info info)539 napi_value AVRecorderNapi::JsGetAVRecorderProfile(napi_env env, napi_callback_info info)
540 {
541     MediaTrace trace("AVRecorder::JsGetAVRecorderProfile");
542     MEDIA_LOGI("AVRecorder::JsGetAVRecorderProfile");
543     const std::string &opt = AVRecordergOpt::GET_AV_RECORDER_PROFILE;
544     MEDIA_LOGI("Js %{public}s Start", opt.c_str());
545 
546     const int32_t maxParam = 3; // config + callbackRef
547     const int32_t callbackParam = 2; // callback
548     size_t argCount = maxParam;
549     napi_value args[maxParam] = { nullptr };
550     napi_value result = nullptr;
551     napi_get_undefined(env, &result);
552 
553     auto asyncCtx = std::make_unique<AVRecorderAsyncContext>(env);
554     CHECK_AND_RETURN_RET_LOG(asyncCtx != nullptr, result, "failed to get AsyncContext");
555     asyncCtx->napi = AVRecorderNapi::GetJsInstanceAndArgs(env, info, argCount, args);
556     CHECK_AND_RETURN_RET_LOG(asyncCtx->napi != nullptr, result, "failed to GetJsInstanceAndArgs");
557     CHECK_AND_RETURN_RET_LOG(asyncCtx->napi->taskQue_ != nullptr, result, "taskQue is nullptr!");
558 
559     asyncCtx->callbackRef = CommonNapi::CreateReference(env, args[callbackParam]);
560     asyncCtx->deferred = CommonNapi::CreatePromise(env, asyncCtx->callbackRef, result);
561 
562     if (asyncCtx->napi->GetSourceIdAndQuality(asyncCtx, env, args[0], args[1], opt) == MSERR_OK) {
563         asyncCtx->task_ = AVRecorderNapi::GetAVRecorderProfileTask(asyncCtx);
564         (void)asyncCtx->napi->taskQue_->EnqueueTask(asyncCtx->task_);
565     }
566 
567     napi_value resource = nullptr;
568     napi_create_string_utf8(env, opt.c_str(), NAPI_AUTO_LENGTH, &resource);
569     NAPI_CALL(env, napi_create_async_work(env, nullptr, resource, [](napi_env env, void* data) {
570         AVRecorderAsyncContext* asyncCtx = reinterpret_cast<AVRecorderAsyncContext *>(data);
571         CHECK_AND_RETURN_LOG(asyncCtx != nullptr, "asyncCtx is nullptr!");
572         if (asyncCtx->task_) {
573             auto result = asyncCtx->task_->GetResult();
574             if (result.Value().first != MSERR_EXT_API9_OK) {
575                 asyncCtx->SignError(result.Value().first, result.Value().second);
576             } else {
577                 asyncCtx->JsResult = std::make_unique<MediaJsAVRecorderProfile>(asyncCtx->profile_);
578             }
579         }
580         MEDIA_LOGI("The js thread of prepare finishes execution and returns");
581     }, MediaAsyncContext::CompleteCallback, static_cast<void *>(asyncCtx.get()), &asyncCtx->work));
582     NAPI_CALL(env, napi_queue_async_work_with_qos(env, asyncCtx->work, napi_qos_user_initiated));
583     asyncCtx.release();
584 
585     MEDIA_LOGI("Js %{public}s End", opt.c_str());
586     return result;
587 }
588 
GetAVRecorderProfileTask(const std::unique_ptr<AVRecorderAsyncContext> & asyncCtx)589 std::shared_ptr<TaskHandler<RetInfo>> AVRecorderNapi::GetAVRecorderProfileTask(
590     const std::unique_ptr<AVRecorderAsyncContext> &asyncCtx)
591 {
592     return std::make_shared<TaskHandler<RetInfo>>([napi = asyncCtx->napi, &profile = asyncCtx->profile_]() {
593         const std::string &option = AVRecordergOpt::GET_AV_RECORDER_PROFILE;
594         MEDIA_LOGI("%{public}s Start", option.c_str());
595         profile = std::make_shared<AVRecorderProfile>();
596 
597         CHECK_AND_RETURN_RET(napi != nullptr && profile != nullptr,
598             GetRetInfo(MSERR_INVALID_OPERATION, option, ""));
599 
600         CHECK_AND_RETURN_RET(napi->CheckStateMachine(option) == MSERR_OK,
601             GetRetInfo(MSERR_INVALID_OPERATION, option, ""));
602 
603         CHECK_AND_RETURN_RET_LOG(napi->sourceId_ >= 0 && ((napi->qualityLevel_ >= RECORDER_QUALITY_LOW &&
604             napi->qualityLevel_ <= RECORDER_QUALITY_2160P) ||
605             (napi->qualityLevel_ >= RECORDER_QUALITY_TIME_LAPSE_LOW &&
606             napi->qualityLevel_ <= RECORDER_QUALITY_TIME_LAPSE_2160P) ||
607             (napi->qualityLevel_ >= RECORDER_QUALITY_HIGH_SPEED_LOW &&
608             napi->qualityLevel_ <= RECORDER_QUALITY_HIGH_SPEED_1080P)),
609             GetRetInfo(MSERR_INVALID_VAL, "GetAVRecorderProfileTask", ""), "sourceId or qualityLevel is null");
610 
611         int32_t ret = AVRecorderNapi::GetAVRecorderProfile(profile, napi->sourceId_, napi->qualityLevel_);
612         CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, GetRetInfo(MSERR_INVALID_VAL, "GetAVRecorderProfileTask", ""),
613             "get AVRecorderProfile failed");
614 
615         MEDIA_LOGI("%{public}s End", option.c_str());
616         return RetInfo(MSERR_EXT_API9_OK, "");
617     });
618 }
619 
SetAVRecorderConfigTask(std::unique_ptr<AVRecorderAsyncContext> & asyncCtx)620 std::shared_ptr<TaskHandler<RetInfo>> AVRecorderNapi::SetAVRecorderConfigTask(
621     std::unique_ptr<AVRecorderAsyncContext> &asyncCtx)
622 {
623     return std::make_shared<TaskHandler<RetInfo>>([napi = asyncCtx->napi, config = asyncCtx->config_]() {
624         const std::string &option = AVRecordergOpt::SET_AV_RECORDER_CONFIG;
625         MEDIA_LOGI("%{public}s Start", option.c_str());
626         CHECK_AND_RETURN_RET(napi != nullptr && napi->recorder_ != nullptr && config != nullptr,
627             GetRetInfo(MSERR_INVALID_OPERATION, option, ""));
628 
629         CHECK_AND_RETURN_RET(napi->CheckStateMachine(option) == MSERR_OK,
630             GetRetInfo(MSERR_INVALID_OPERATION, option, ""));
631 
632         RetInfo retinfo = napi->Configure(config);
633         CHECK_AND_RETURN_RET(retinfo.first == MSERR_OK, ((void)napi->recorder_->Reset(), retinfo));
634 
635         napi->withVideo_ = config->withVideo;
636         MEDIA_LOGI("%{public}s End", option.c_str());
637         return RetInfo(MSERR_EXT_API9_OK, "");
638     });
639 }
640 
JsSetAVRecorderConfig(napi_env env,napi_callback_info info)641 napi_value AVRecorderNapi::JsSetAVRecorderConfig(napi_env env, napi_callback_info info)
642 {
643     MediaTrace trace("AVRecorder::JsSetAVRecorderConfig");
644     const std::string &opt = AVRecordergOpt::SET_AV_RECORDER_CONFIG;
645     MEDIA_LOGI("Js %{public}s Start", opt.c_str());
646 
647     const int32_t maxParam = 2; // config + callbackRef
648     size_t argCount = maxParam;
649     napi_value args[maxParam] = { nullptr };
650     napi_value result = nullptr;
651     napi_get_undefined(env, &result);
652 
653     auto asyncCtx = std::make_unique<AVRecorderAsyncContext>(env);
654     CHECK_AND_RETURN_RET_LOG(asyncCtx != nullptr, result, "failed to get AsyncContext");
655     asyncCtx->napi = AVRecorderNapi::GetJsInstanceAndArgs(env, info, argCount, args);
656     CHECK_AND_RETURN_RET_LOG(asyncCtx->napi != nullptr, result, "failed to GetJsInstanceAndArgs");
657     CHECK_AND_RETURN_RET_LOG(asyncCtx->napi->taskQue_ != nullptr, result, "taskQue is nullptr!");
658 
659     asyncCtx->callbackRef = CommonNapi::CreateReference(env, args[1]);
660     asyncCtx->deferred = CommonNapi::CreatePromise(env, asyncCtx->callbackRef, result);
661 
662     if (asyncCtx->napi->CheckStateMachine(opt) == MSERR_OK) {
663         if (asyncCtx->napi->GetConfig(asyncCtx, env, args[0]) == MSERR_OK) {
664             asyncCtx->task_ = AVRecorderNapi::SetAVRecorderConfigTask(asyncCtx);
665             (void)asyncCtx->napi->taskQue_->EnqueueTask(asyncCtx->task_);
666         }
667     } else {
668         asyncCtx->AVRecorderSignError(MSERR_INVALID_OPERATION, opt, "");
669     }
670 
671     napi_value resource = nullptr;
672     napi_create_string_utf8(env, opt.c_str(), NAPI_AUTO_LENGTH, &resource);
673     NAPI_CALL(env, napi_create_async_work(env, nullptr, resource, [](napi_env env, void* data) {
674         AVRecorderAsyncContext* asyncCtx = reinterpret_cast<AVRecorderAsyncContext *>(data);
675         CHECK_AND_RETURN_LOG(asyncCtx != nullptr, "asyncCtx is nullptr!");
676         if (asyncCtx->task_) {
677             auto result = asyncCtx->task_->GetResult();
678             if (result.Value().first != MSERR_EXT_API9_OK) {
679                 asyncCtx->SignError(result.Value().first, result.Value().second);
680             }
681         }
682         MEDIA_LOGI("The js thread of prepare finishes execution and returns");
683     }, MediaAsyncContext::CompleteCallback, static_cast<void *>(asyncCtx.get()), &asyncCtx->work));
684     NAPI_CALL(env, napi_queue_async_work_with_qos(env, asyncCtx->work, napi_qos_user_initiated));
685     asyncCtx.release();
686 
687     MEDIA_LOGI("Js %{public}s End", opt.c_str());
688     return result;
689 }
690 
JsGetAVRecorderConfig(napi_env env,napi_callback_info info)691 napi_value AVRecorderNapi::JsGetAVRecorderConfig(napi_env env, napi_callback_info info)
692 {
693     MediaTrace trace("AVRecorder::JsGetAVRecorderConfig");
694     const std::string &opt = AVRecordergOpt::GET_AV_RECORDER_CONFIG;
695     MEDIA_LOGI("Js %{public}s Start", opt.c_str());
696 
697     napi_value result = nullptr;
698     napi_get_undefined(env, &result);
699     size_t argCount = 1;
700     napi_value args[1] = { nullptr };
701 
702     auto asyncCtx = std::make_unique<AVRecorderAsyncContext>(env);
703     CHECK_AND_RETURN_RET_LOG(asyncCtx != nullptr, result, "failed to get AsyncContext");
704     asyncCtx->napi = AVRecorderNapi::GetJsInstanceAndArgs(env, info, argCount, args);
705     CHECK_AND_RETURN_RET_LOG(asyncCtx->napi != nullptr, result, "failed to GetJsInstanceAndArgs");
706     CHECK_AND_RETURN_RET_LOG(asyncCtx->napi->taskQue_ != nullptr, result, "taskQue is nullptr!");
707 
708     asyncCtx->callbackRef = CommonNapi::CreateReference(env, args[0]);
709     asyncCtx->deferred = CommonNapi::CreatePromise(env, asyncCtx->callbackRef, result);
710 
711     if (asyncCtx->napi->CheckStateMachine(opt) == MSERR_OK) {
712         asyncCtx->task_ = AVRecorderNapi::GetAVRecorderConfigTask(asyncCtx);
713         (void)asyncCtx->napi->taskQue_->EnqueueTask(asyncCtx->task_);
714         asyncCtx->opt_ = opt;
715     } else {
716         asyncCtx->AVRecorderSignError(MSERR_INVALID_OPERATION, opt, "");
717     }
718 
719     napi_value resource = nullptr;
720     napi_create_string_utf8(env, opt.c_str(), NAPI_AUTO_LENGTH, &resource);
721     NAPI_CALL(env, napi_create_async_work(env, nullptr, resource, [](napi_env env, void* data) {
722         AVRecorderAsyncContext* asyncCtx = reinterpret_cast<AVRecorderAsyncContext *>(data);
723         CHECK_AND_RETURN_LOG(asyncCtx != nullptr, "asyncCtx is nullptr!");
724         if (asyncCtx->task_) {
725             auto result = asyncCtx->task_->GetResult();
726             if (result.Value().first != MSERR_EXT_API9_OK) {
727                 asyncCtx->SignError(result.Value().first, result.Value().second);
728             }
729 
730             if ((result.Value().first == MSERR_EXT_API9_OK) &&
731                 (asyncCtx->opt_ == AVRecordergOpt::GET_AV_RECORDER_CONFIG)) {
732                 asyncCtx->JsResult = std::make_unique<MediaJsAVRecorderConfig>(asyncCtx->config_);
733             }
734         }
735         MEDIA_LOGI("The js thread of prepare finishes execution and returns");
736     }, MediaAsyncContext::CompleteCallback, static_cast<void *>(asyncCtx.get()), &asyncCtx->work));
737     NAPI_CALL(env, napi_queue_async_work_with_qos(env, asyncCtx->work, napi_qos_user_initiated));
738     asyncCtx.release();
739 
740     MEDIA_LOGI("Js %{public}s End", opt.c_str());
741     return result;
742 }
743 
JsGetCurrentAudioCapturerInfo(napi_env env,napi_callback_info info)744 napi_value AVRecorderNapi::JsGetCurrentAudioCapturerInfo(napi_env env, napi_callback_info info)
745 {
746     MediaTrace trace("AVRecorder::JsGetCurrentAudioCapturerInfo");
747     const std::string &opt = AVRecordergOpt::GET_CURRENT_AUDIO_CAPTURER_INFO;
748     MEDIA_LOGI("Js %{public}s Start", opt.c_str());
749 
750     napi_value result = nullptr;
751     napi_get_undefined(env, &result);
752     size_t argCount = 1;
753     napi_value args[1] = { nullptr };
754 
755     auto asyncCtx = std::make_unique<AVRecorderAsyncContext>(env);
756     CHECK_AND_RETURN_RET_LOG(asyncCtx != nullptr, result, "failed to get AsyncContext");
757     asyncCtx->napi = AVRecorderNapi::GetJsInstanceAndArgs(env, info, argCount, args);
758     CHECK_AND_RETURN_RET_LOG(asyncCtx->napi != nullptr, result, "failed to GetJsInstanceAndArgs");
759     CHECK_AND_RETURN_RET_LOG(asyncCtx->napi->taskQue_ != nullptr, result, "taskQue is nullptr!");
760 
761     asyncCtx->callbackRef = CommonNapi::CreateReference(env, args[0]);
762     asyncCtx->deferred = CommonNapi::CreatePromise(env, asyncCtx->callbackRef, result);
763     if (asyncCtx->napi->CheckStateMachine(opt) == MSERR_OK) {
764         asyncCtx->task_ = AVRecorderNapi::GetCurrentCapturerChangeInfoTask(asyncCtx);
765         (void)asyncCtx->napi->taskQue_->EnqueueTask(asyncCtx->task_);
766         asyncCtx->opt_ = opt;
767     } else {
768         asyncCtx->AVRecorderSignError(MSERR_INVALID_OPERATION, opt, "");
769     }
770 
771     napi_value resource = nullptr;
772     napi_create_string_utf8(env, opt.c_str(), NAPI_AUTO_LENGTH, &resource);
773     NAPI_CALL(env, napi_create_async_work(env, nullptr, resource, [](napi_env env, void* data) {
774         AVRecorderAsyncContext* asyncCtx = reinterpret_cast<AVRecorderAsyncContext *>(data);
775         CHECK_AND_RETURN_LOG(asyncCtx != nullptr, "asyncCtx is nullptr!");
776         if (asyncCtx->task_) {
777             auto result = asyncCtx->task_->GetResult();
778             if (result.Value().first != MSERR_EXT_API9_OK) {
779                 asyncCtx->SignError(result.Value().first, result.Value().second);
780             }
781 
782             if ((result.Value().first == MSERR_EXT_API9_OK) &&
783                 (asyncCtx->opt_ == AVRecordergOpt::GET_CURRENT_AUDIO_CAPTURER_INFO)) {
784                 asyncCtx->JsResult = std::make_unique<AudioCaptureChangeInfoJsCallback>(asyncCtx->changeInfo_);
785             }
786         }
787         MEDIA_LOGI("The js thread of prepare finishes execution and returns");
788     }, MediaAsyncContext::CompleteCallback, static_cast<void *>(asyncCtx.get()), &asyncCtx->work));
789     NAPI_CALL(env, napi_queue_async_work_with_qos(env, asyncCtx->work, napi_qos_user_initiated));
790     asyncCtx.release();
791 
792     MEDIA_LOGI("Js %{public}s End", opt.c_str());
793     return result;
794 }
795 
JsGetAudioCapturerMaxAmplitude(napi_env env,napi_callback_info info)796 napi_value AVRecorderNapi::JsGetAudioCapturerMaxAmplitude(napi_env env,  napi_callback_info info)
797 {
798     MediaTrace trace("AVRecorder::JsGetAudioCapturerMaxAmplitude");
799     const std::string &opt = AVRecordergOpt::GET_MAX_AMPLITUDE;
800     MEDIA_LOGD("Js %{public}s Start", opt.c_str());
801     napi_value result = nullptr;
802     napi_get_undefined(env, &result);
803     size_t argCount = 1;
804     napi_value args[1] = { nullptr };
805 
806     auto asyncCtx = std::make_unique<AVRecorderAsyncContext>(env);
807     CHECK_AND_RETURN_RET_LOG(asyncCtx != nullptr, result, "failed to get AsyncContext");
808     asyncCtx->napi = AVRecorderNapi::GetJsInstanceAndArgs(env, info, argCount, args);
809     CHECK_AND_RETURN_RET_LOG(asyncCtx->napi != nullptr, result, "failed to GetJsInstanceAndArgs");
810     CHECK_AND_RETURN_RET_LOG(asyncCtx->napi->taskQue_ != nullptr, result, "taskQue is nullptr!");
811 
812     asyncCtx->callbackRef = CommonNapi::CreateReference(env, args[0]);
813     asyncCtx->deferred = CommonNapi::CreatePromise(env, asyncCtx->callbackRef, result);
814     if (asyncCtx->napi->CheckStateMachine(opt) == MSERR_OK) {
815         asyncCtx->task_ = AVRecorderNapi::GetMaxAmplitudeTask(asyncCtx);
816         (void)asyncCtx->napi->taskQue_->EnqueueTask(asyncCtx->task_);
817         asyncCtx->opt_ = opt;
818     } else {
819         asyncCtx->AVRecorderSignError(MSERR_INVALID_OPERATION, opt, "");
820     }
821 
822     napi_value resource = nullptr;
823     napi_create_string_utf8(env, opt.c_str(), NAPI_AUTO_LENGTH, &resource);
824     NAPI_CALL(env, napi_create_async_work(env, nullptr, resource, [](napi_env env, void* data) {
825         AVRecorderAsyncContext* asyncCtx = reinterpret_cast<AVRecorderAsyncContext *>(data);
826         CHECK_AND_RETURN_LOG(asyncCtx != nullptr, "asyncCtx is nullptr!");
827         if (asyncCtx->task_) {
828             auto result = asyncCtx->task_->GetResult();
829             if (result.Value().first != MSERR_EXT_API9_OK) {
830                 asyncCtx->SignError(result.Value().first, result.Value().second);
831             }
832 
833             if ((result.Value().first == MSERR_EXT_API9_OK) &&
834                 (asyncCtx->opt_ == AVRecordergOpt::GET_MAX_AMPLITUDE)) {
835                 asyncCtx->JsResult = std::make_unique<MediaJsResultInt>(asyncCtx->maxAmplitude_);
836             }
837         }
838         MEDIA_LOGI("The js thread of prepare finishes execution and returns");
839     }, MediaAsyncContext::CompleteCallback, static_cast<void *>(asyncCtx.get()), &asyncCtx->work));
840     NAPI_CALL(env, napi_queue_async_work_with_qos(env, asyncCtx->work, napi_qos_user_initiated));
841     asyncCtx.release();
842 
843     MEDIA_LOGD("Js %{public}s End", opt.c_str());
844     return result;
845 }
846 
JsGetAvailableEncoder(napi_env env,napi_callback_info info)847 napi_value AVRecorderNapi::JsGetAvailableEncoder(napi_env env,  napi_callback_info info)
848 {
849     MediaTrace trace("AVRecorder::JsGetAvailableEncoder");
850     const std::string &opt = AVRecordergOpt::GET_ENCODER_INFO;
851     MEDIA_LOGI("Js %{public}s Start", opt.c_str());
852     napi_value result = nullptr;
853     napi_get_undefined(env, &result);
854     size_t argCount = 1;
855     napi_value args[1] = { nullptr };
856 
857     auto asyncCtx = std::make_unique<AVRecorderAsyncContext>(env);
858     CHECK_AND_RETURN_RET_LOG(asyncCtx != nullptr, result, "failed to get AsyncContext");
859     asyncCtx->napi = AVRecorderNapi::GetJsInstanceAndArgs(env, info, argCount, args);
860     CHECK_AND_RETURN_RET_LOG(asyncCtx->napi != nullptr, result, "failed to GetJsInstanceAndArgs");
861     CHECK_AND_RETURN_RET_LOG(asyncCtx->napi->taskQue_ != nullptr, result, "taskQue is nullptr!");
862 
863     asyncCtx->callbackRef = CommonNapi::CreateReference(env, args[0]);
864     asyncCtx->deferred = CommonNapi::CreatePromise(env, asyncCtx->callbackRef, result);
865     if (asyncCtx->napi->CheckStateMachine(opt) == MSERR_OK) {
866         asyncCtx->task_ = AVRecorderNapi::GetEncoderInfoTask(asyncCtx);
867         (void)asyncCtx->napi->taskQue_->EnqueueTask(asyncCtx->task_);
868         asyncCtx->opt_ = opt;
869     } else {
870         asyncCtx->AVRecorderSignError(MSERR_INVALID_OPERATION, opt, "");
871     }
872 
873     napi_value resource = nullptr;
874     napi_create_string_utf8(env, opt.c_str(), NAPI_AUTO_LENGTH, &resource);
875     NAPI_CALL(env, napi_create_async_work(env, nullptr, resource, [](napi_env env, void* data) {
876         AVRecorderAsyncContext* asyncCtx = reinterpret_cast<AVRecorderAsyncContext *>(data);
877         CHECK_AND_RETURN_LOG(asyncCtx != nullptr, "asyncCtx is nullptr!");
878         if (asyncCtx->task_) {
879             auto result = asyncCtx->task_->GetResult();
880             if (result.Value().first != MSERR_EXT_API9_OK) {
881                 asyncCtx->SignError(result.Value().first, result.Value().second);
882             }
883 
884             if ((result.Value().first == MSERR_EXT_API9_OK) &&
885                 (asyncCtx->opt_ == AVRecordergOpt::GET_ENCODER_INFO)) {
886                 asyncCtx->JsResult = std::make_unique<MediaJsEncoderInfo>(asyncCtx->encoderInfo_);
887             }
888         }
889         MEDIA_LOGI("The js thread of prepare finishes execution and returns");
890     }, MediaAsyncContext::CompleteCallback, static_cast<void *>(asyncCtx.get()), &asyncCtx->work));
891     NAPI_CALL(env, napi_queue_async_work_with_qos(env, asyncCtx->work, napi_qos_user_initiated));
892     asyncCtx.release();
893 
894     MEDIA_LOGI("Js %{public}s End", opt.c_str());
895     return result;
896 }
897 
JsSetEventCallback(napi_env env,napi_callback_info info)898 napi_value AVRecorderNapi::JsSetEventCallback(napi_env env, napi_callback_info info)
899 {
900     MediaTrace trace("AVRecorder::JsSetEventCallback");
901     MEDIA_LOGI("JsSetEventCallback Start");
902     napi_value result = nullptr;
903     napi_get_undefined(env, &result);
904 
905     size_t argCount = 2;
906     constexpr size_t requireArgc = 1;
907     napi_value args[2] = { nullptr, nullptr };
908     AVRecorderNapi *recorderNapi = AVRecorderNapi::GetJsInstanceAndArgs(env, info, argCount, args);
909     CHECK_AND_RETURN_RET_LOG(recorderNapi != nullptr, result, "Failed to retrieve instance");
910 
911     napi_valuetype valueType0 = napi_undefined;
912     napi_valuetype valueType1 = napi_undefined;
913 
914     if (argCount < requireArgc) {
915         recorderNapi->ErrorCallback(MSERR_MANDATORY_PARAMETER_UNSPECIFIED, "SetEventCallback",
916             "Mandatory parameters are left unspecified.");
917         return result;
918     }
919 
920     if (napi_typeof(env, args[0], &valueType0) != napi_ok || valueType0 != napi_string) {
921         recorderNapi->ErrorCallback(MSERR_INCORRECT_PARAMETER_TYPE, "SetEventCallback",
922             "type should be string");
923         return result;
924     }
925 
926     if (napi_typeof(env, args[1], &valueType1) != napi_ok || valueType1 != napi_function) {
927         recorderNapi->ErrorCallback(MSERR_INCORRECT_PARAMETER_TYPE, "SetEventCallback",
928             "callback type should be Callback or function.");
929         return result;
930     }
931 
932     std::string callbackName = CommonNapi::GetStringArgument(env, args[0]);
933     if (callbackName != AVRecorderEvent::EVENT_ERROR && callbackName != AVRecorderEvent::EVENT_STATE_CHANGE
934         && callbackName != AVRecorderEvent::EVENT_AUDIO_CAPTURE_CHANGE
935         && callbackName != AVRecorderEvent::EVENT_PHOTO_ASSET_AVAILABLE) {
936         recorderNapi->ErrorCallback(MSERR_PARAMETER_VERIFICATION_FAILED, "SetEventCallback",
937             "type must be error, stateChange or audioCapturerChange or photoAssetAvailable.");
938         return result;
939     }
940 
941     napi_ref ref = nullptr;
942     napi_status status = napi_create_reference(env, args[1], 1, &ref);
943     CHECK_AND_RETURN_RET_LOG(status == napi_ok && ref != nullptr, result, "failed to create reference!");
944 
945     std::shared_ptr<AutoRef> autoRef = std::make_shared<AutoRef>(env, ref);
946     recorderNapi->SetCallbackReference(callbackName, autoRef);
947 
948     MEDIA_LOGI("JsSetEventCallback End");
949     return result;
950 }
951 
JsCancelEventCallback(napi_env env,napi_callback_info info)952 napi_value AVRecorderNapi::JsCancelEventCallback(napi_env env, napi_callback_info info)
953 {
954     MediaTrace trace("AVRecorder::JsCancelEventCallback");
955     MEDIA_LOGI("JsCancelEventCallback Start");
956     napi_value result = nullptr;
957     napi_get_undefined(env, &result);
958     constexpr size_t requireArgc = 1;
959     size_t argCount = 1;
960 
961     napi_value args[1] = { nullptr };
962     AVRecorderNapi *recorderNapi = AVRecorderNapi::GetJsInstanceAndArgs(env, info, argCount, args);
963     CHECK_AND_RETURN_RET_LOG(recorderNapi != nullptr, result, "Failed to retrieve instance");
964 
965     napi_valuetype valueType0 = napi_undefined;
966 
967     if (argCount < requireArgc) {
968         recorderNapi->ErrorCallback(MSERR_MANDATORY_PARAMETER_UNSPECIFIED, "CancelEventCallback",
969             "Mandatory parameters are left unspecified.");
970         return result;
971     }
972 
973     if (napi_typeof(env, args[0], &valueType0) != napi_ok || valueType0 != napi_string) {
974         recorderNapi->ErrorCallback(MSERR_INCORRECT_PARAMETER_TYPE, "CancelEventCallback",
975             "type should be string.");
976         return result;
977     }
978 
979     std::string callbackName = CommonNapi::GetStringArgument(env, args[0]);
980     if (callbackName != AVRecorderEvent::EVENT_ERROR && callbackName != AVRecorderEvent::EVENT_STATE_CHANGE
981         && callbackName != AVRecorderEvent::EVENT_AUDIO_CAPTURE_CHANGE) {
982         recorderNapi->ErrorCallback(MSERR_PARAMETER_VERIFICATION_FAILED, "CancelEventCallback",
983             "type must be error, stateChange or audioCapturerChange.");
984         return result;
985     }
986 
987     recorderNapi->CancelCallbackReference(callbackName);
988 
989     MEDIA_LOGI("JsCancelEventCallback End");
990     return result;
991 }
992 
JsGetState(napi_env env,napi_callback_info info)993 napi_value AVRecorderNapi::JsGetState(napi_env env, napi_callback_info info)
994 {
995     MediaTrace trace("AVRecorder::JsGetState");
996     napi_value result = nullptr;
997     napi_get_undefined(env, &result);
998 
999     size_t argCount = 0;
1000     AVRecorderNapi *recorderNapi = AVRecorderNapi::GetJsInstanceAndArgs(env, info, argCount, nullptr);
1001     CHECK_AND_RETURN_RET_LOG(recorderNapi != nullptr, result, "failed to GetJsInstance");
1002 
1003     auto napiCb = std::static_pointer_cast<AVRecorderCallback>(recorderNapi->recorderCb_);
1004     CHECK_AND_RETURN_RET_LOG(napiCb != nullptr, result, "napiCb is nullptr!");
1005     std::string curState = napiCb->GetState();
1006     MEDIA_LOGD("GetState success, State: %{public}s", curState.c_str());
1007 
1008     napi_value jsResult = nullptr;
1009     napi_status status = napi_create_string_utf8(env, curState.c_str(), NAPI_AUTO_LENGTH, &jsResult);
1010     CHECK_AND_RETURN_RET_LOG(status == napi_ok, result, "napi_create_string_utf8 error");
1011     return jsResult;
1012 }
1013 
JsIsWatermarkSupported(napi_env env,napi_callback_info info)1014 napi_value AVRecorderNapi::JsIsWatermarkSupported(napi_env env, napi_callback_info info)
1015 {
1016     MediaTrace trace("AVRecorderNapi::JsIsWatermarkSupported");
1017     const std::string &opt = AVRecordergOpt::IS_WATERMARK_SUPPORTED;
1018     MEDIA_LOGI("Js %{public}s Start", opt.c_str());
1019     napi_value result = nullptr;
1020     napi_get_undefined(env, &result);
1021 
1022     size_t argCount = 1;
1023     napi_value args[1] = { nullptr };
1024 
1025     auto asyncCtx = std::make_unique<AVRecorderAsyncContext>(env);
1026     CHECK_AND_RETURN_RET_LOG(asyncCtx != nullptr, result, "failed to get AsyncContext");
1027     asyncCtx->napi = AVRecorderNapi::GetJsInstanceAndArgs(env, info, argCount, args);
1028     CHECK_AND_RETURN_RET_LOG(asyncCtx->napi != nullptr, result, "failed to GetJsInstanceAndArgs");
1029     CHECK_AND_RETURN_RET_LOG(asyncCtx->napi->taskQue_ != nullptr, result, "taskQue is nullptr!");
1030 
1031     asyncCtx->deferred = CommonNapi::CreatePromise(env, nullptr, result);
1032 
1033     if (asyncCtx->napi->CheckStateMachine(opt) == MSERR_OK) {
1034         asyncCtx->task_ = AVRecorderNapi::IsWatermarkSupportedTask(asyncCtx);
1035         (void)asyncCtx->napi->taskQue_->EnqueueTask(asyncCtx->task_);
1036         asyncCtx->opt_ = opt;
1037     } else {
1038         asyncCtx->AVRecorderSignError(MSERR_INVALID_OPERATION, opt, "");
1039     }
1040 
1041     napi_value resource = nullptr;
1042     napi_create_string_utf8(env, opt.c_str(), NAPI_AUTO_LENGTH, &resource);
1043     NAPI_CALL(env, napi_create_async_work(env, nullptr, resource, [](napi_env env, void* data) {
1044         AVRecorderAsyncContext* asyncCtx = reinterpret_cast<AVRecorderAsyncContext *>(data);
1045         CHECK_AND_RETURN_LOG(asyncCtx != nullptr, "asyncCtx is nullptr!");
1046         if (asyncCtx->task_) {
1047             auto result = asyncCtx->task_->GetResult();
1048             if (result.Value().first != MSERR_EXT_API9_OK) {
1049                 asyncCtx->SignError(result.Value().first, result.Value().second);
1050             }
1051 
1052             if ((result.Value().first == MSERR_EXT_API9_OK) &&
1053                 (asyncCtx->opt_ == AVRecordergOpt::IS_WATERMARK_SUPPORTED)) {
1054                 asyncCtx->JsResult = std::make_unique<MediaJsResultBoolean>(asyncCtx->isWatermarkSupported_);
1055             }
1056         }
1057         MEDIA_LOGI("The js thread of prepare finishes execution and returns");
1058     }, MediaAsyncContext::CompleteCallback, static_cast<void *>(asyncCtx.get()), &asyncCtx->work));
1059     NAPI_CALL(env, napi_queue_async_work_with_qos(env, asyncCtx->work, napi_qos_user_initiated));
1060     asyncCtx.release();
1061 
1062     MEDIA_LOGI("Js %{public}s End", opt.c_str());
1063     return result;
1064 }
1065 
GetJsInstanceAndArgs(napi_env env,napi_callback_info info,size_t & argCount,napi_value * args)1066 AVRecorderNapi *AVRecorderNapi::GetJsInstanceAndArgs(
1067     napi_env env, napi_callback_info info, size_t &argCount, napi_value *args)
1068 {
1069     napi_value jsThis = nullptr;
1070     napi_status status = napi_get_cb_info(env, info, &argCount, args, &jsThis, nullptr);
1071     CHECK_AND_RETURN_RET_LOG(status == napi_ok && jsThis != nullptr, nullptr, "failed to napi_get_cb_info");
1072     MEDIA_LOGD("argCount:%{public}zu", argCount);
1073 
1074     AVRecorderNapi *recorderNapi = nullptr;
1075     status = napi_unwrap(env, jsThis, reinterpret_cast<void **>(&recorderNapi));
1076     CHECK_AND_RETURN_RET_LOG(status == napi_ok && recorderNapi != nullptr, nullptr, "failed to retrieve instance");
1077 
1078     return recorderNapi;
1079 }
1080 
GetPromiseTask(AVRecorderNapi * avnapi,const std::string & opt)1081 std::shared_ptr<TaskHandler<RetInfo>> AVRecorderNapi::GetPromiseTask(AVRecorderNapi *avnapi, const std::string &opt)
1082 {
1083     return std::make_shared<TaskHandler<RetInfo>>([napi = avnapi, option = opt]() {
1084         MEDIA_LOGI("%{public}s Start", option.c_str());
1085         CHECK_AND_RETURN_RET(napi != nullptr && napi->recorder_ != nullptr,
1086             GetRetInfo(MSERR_INVALID_OPERATION, option, ""));
1087 
1088         CHECK_AND_RETURN_RET(napi->CheckStateMachine(option) == MSERR_OK,
1089             GetRetInfo(MSERR_INVALID_OPERATION, option, ""));
1090 
1091         CHECK_AND_RETURN_RET(napi->CheckRepeatOperation(option) == MSERR_OK,
1092             RetInfo(MSERR_EXT_API9_OK, ""));
1093 
1094         RetInfo ret(MSERR_EXT_API9_OPERATE_NOT_PERMIT, "");
1095         auto itFunc = taskQFuncs_.find(option);
1096         CHECK_AND_RETURN_RET_LOG(itFunc != taskQFuncs_.end(), ret, "%{public}s not found in map!", option.c_str());
1097         auto memberFunc = itFunc->second;
1098         CHECK_AND_RETURN_RET_LOG(memberFunc != nullptr, ret, "memberFunc is nullptr!");
1099         ret = (napi->*memberFunc)();
1100 
1101         MEDIA_LOGI("%{public}s End", option.c_str());
1102         return ret;
1103     });
1104 }
1105 
ExecuteByPromise(napi_env env,napi_callback_info info,const std::string & opt)1106 napi_value AVRecorderNapi::ExecuteByPromise(napi_env env, napi_callback_info info, const std::string &opt)
1107 {
1108     MEDIA_LOGI("Js %{public}s Start", opt.c_str());
1109     napi_value result = nullptr;
1110     napi_get_undefined(env, &result);
1111     size_t argCount = 1; // Only callbackRef parameter
1112     napi_value args[1] = { nullptr }; // Only callbackRef parameter
1113 
1114     auto asyncCtx = std::make_unique<AVRecorderAsyncContext>(env);
1115     CHECK_AND_RETURN_RET_LOG(asyncCtx != nullptr, result, "failed to get AsyncContext");
1116     asyncCtx->napi = AVRecorderNapi::GetJsInstanceAndArgs(env, info, argCount, args);
1117     CHECK_AND_RETURN_RET_LOG(asyncCtx->napi != nullptr, result, "failed to GetJsInstanceAndArgs");
1118     CHECK_AND_RETURN_RET_LOG(asyncCtx->napi->taskQue_ != nullptr, result, "taskQue is nullptr!");
1119 
1120     asyncCtx->callbackRef = CommonNapi::CreateReference(env, args[0]);
1121     asyncCtx->deferred = CommonNapi::CreatePromise(env, asyncCtx->callbackRef, result);
1122 
1123     if (asyncCtx->napi->CheckStateMachine(opt) == MSERR_OK) {
1124         asyncCtx->task_ = AVRecorderNapi::GetPromiseTask(asyncCtx->napi, opt);
1125         (void)asyncCtx->napi->taskQue_->EnqueueTask(asyncCtx->task_);
1126         asyncCtx->opt_ = opt;
1127     } else {
1128         asyncCtx->AVRecorderSignError(MSERR_INVALID_OPERATION, opt, "");
1129     }
1130 
1131     napi_value resource = nullptr;
1132     napi_create_string_utf8(env, opt.c_str(), NAPI_AUTO_LENGTH, &resource);
1133     NAPI_CALL(env, napi_create_async_work(env, nullptr, resource, [](napi_env env, void* data) {
1134         AVRecorderAsyncContext* asyncCtx = reinterpret_cast<AVRecorderAsyncContext *>(data);
1135         CHECK_AND_RETURN_LOG(asyncCtx != nullptr, "asyncCtx is nullptr!");
1136 
1137         if (asyncCtx->task_) {
1138             auto result = asyncCtx->task_->GetResult();
1139             if (result.Value().first != MSERR_EXT_API9_OK) {
1140                 asyncCtx->SignError(result.Value().first, result.Value().second);
1141             }
1142 
1143             if ((result.Value().first == MSERR_EXT_API9_OK) && (asyncCtx->opt_ == AVRecordergOpt::GETINPUTSURFACE)) {
1144                 asyncCtx->JsResult = std::make_unique<MediaJsResultString>(result.Value().second);
1145             }
1146         }
1147         MEDIA_LOGI("The js thread of %{public}s finishes execution and returns", asyncCtx->opt_.c_str());
1148     }, MediaAsyncContext::CompleteCallback, static_cast<void *>(asyncCtx.get()), &asyncCtx->work));
1149     NAPI_CALL(env, napi_queue_async_work_with_qos(env, asyncCtx->work, napi_qos_user_initiated));
1150     asyncCtx.release();
1151 
1152     MEDIA_LOGI("Js %{public}s End", opt.c_str());
1153     return result;
1154 }
1155 
GetAVRecorderConfigTask(const std::unique_ptr<AVRecorderAsyncContext> & asyncCtx)1156 std::shared_ptr<TaskHandler<RetInfo>> AVRecorderNapi::GetAVRecorderConfigTask(
1157     const std::unique_ptr<AVRecorderAsyncContext> &asyncCtx)
1158 {
1159     return std::make_shared<TaskHandler<RetInfo>>([napi = asyncCtx->napi, &config = asyncCtx->config_]() {
1160         const std::string &option = AVRecordergOpt::GET_AV_RECORDER_CONFIG;
1161         MEDIA_LOGI("%{public}s Start", option.c_str());
1162         config = std::make_shared<AVRecorderConfig>();
1163 
1164         CHECK_AND_RETURN_RET(napi != nullptr && config != nullptr,
1165             GetRetInfo(MSERR_INVALID_OPERATION, option, ""));
1166 
1167         CHECK_AND_RETURN_RET(napi->CheckStateMachine(option) == MSERR_OK,
1168             GetRetInfo(MSERR_INVALID_OPERATION, option, ""));
1169 
1170         CHECK_AND_RETURN_RET(napi->CheckRepeatOperation(option) == MSERR_OK,
1171             RetInfo(MSERR_EXT_API9_OK, ""));
1172 
1173         int32_t ret = napi->GetAVRecorderConfig(config);
1174         CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, GetRetInfo(MSERR_INVALID_VAL, "GetAVRecorderConfigTask", ""),
1175             "get AVRecorderConfigTask failed");
1176 
1177         MEDIA_LOGI("%{public}s End", option.c_str());
1178         return RetInfo(MSERR_EXT_API9_OK, "");
1179     });
1180 }
1181 
GetCurrentCapturerChangeInfoTask(const std::unique_ptr<AVRecorderAsyncContext> & asyncCtx)1182 std::shared_ptr<TaskHandler<RetInfo>> AVRecorderNapi::GetCurrentCapturerChangeInfoTask(
1183     const std::unique_ptr<AVRecorderAsyncContext> &asyncCtx)
1184 {
1185     return std::make_shared<TaskHandler<RetInfo>>([napi = asyncCtx->napi, &changeInfo = asyncCtx->changeInfo_]() {
1186         const std::string &option = AVRecordergOpt::GET_CURRENT_AUDIO_CAPTURER_INFO;
1187         MEDIA_LOGI("%{public}s Start", option.c_str());
1188 
1189         CHECK_AND_RETURN_RET(napi != nullptr,
1190             GetRetInfo(MSERR_INVALID_OPERATION, option, ""));
1191 
1192         CHECK_AND_RETURN_RET(napi->CheckStateMachine(option) == MSERR_OK,
1193             GetRetInfo(MSERR_INVALID_OPERATION, option, ""));
1194 
1195         CHECK_AND_RETURN_RET(napi->CheckRepeatOperation(option) == MSERR_OK,
1196             RetInfo(MSERR_EXT_API9_OK, ""));
1197 
1198         int32_t ret = napi->GetCurrentCapturerChangeInfo(changeInfo);
1199         CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, GetRetInfo(MSERR_INVALID_VAL, "GetCurrentCapturerChangeInfoTask", ""),
1200             "get GetCurrentCapturerChangeInfoTask failed");
1201 
1202         MEDIA_LOGI("%{public}s End", option.c_str());
1203         return RetInfo(MSERR_EXT_API9_OK, "");
1204     });
1205 }
1206 
GetMaxAmplitudeTask(const std::unique_ptr<AVRecorderAsyncContext> & asyncCtx)1207 std::shared_ptr<TaskHandler<RetInfo>> AVRecorderNapi::GetMaxAmplitudeTask(
1208     const std::unique_ptr<AVRecorderAsyncContext> &asyncCtx)
1209 {
1210     return std::make_shared<TaskHandler<RetInfo>>([napi = asyncCtx->napi, &maxAmplitude = asyncCtx->maxAmplitude_]() {
1211         const std::string &option = AVRecordergOpt::GET_MAX_AMPLITUDE;
1212         MEDIA_LOGD("%{public}s Start", option.c_str());
1213 
1214         CHECK_AND_RETURN_RET(napi != nullptr,
1215             GetRetInfo(MSERR_INVALID_OPERATION, option, ""));
1216 
1217         CHECK_AND_RETURN_RET(napi->CheckStateMachine(option) == MSERR_OK,
1218             GetRetInfo(MSERR_INVALID_OPERATION, option, ""));
1219 
1220         CHECK_AND_RETURN_RET(napi->CheckRepeatOperation(option) == MSERR_OK,
1221             RetInfo(MSERR_EXT_API9_OK, ""));
1222 
1223         int32_t ret = napi->GetMaxAmplitude(maxAmplitude);
1224         CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, GetRetInfo(MSERR_INVALID_VAL, "GetMaxAmplitudeTask", ""),
1225             "get GetMaxAmplitudeTask failed");
1226 
1227         MEDIA_LOGD("%{public}s End", option.c_str());
1228         return RetInfo(MSERR_EXT_API9_OK, "");
1229     });
1230 }
1231 
GetEncoderInfoTask(const std::unique_ptr<AVRecorderAsyncContext> & asyncCtx)1232 std::shared_ptr<TaskHandler<RetInfo>> AVRecorderNapi::GetEncoderInfoTask(
1233     const std::unique_ptr<AVRecorderAsyncContext> &asyncCtx)
1234 {
1235     return std::make_shared<TaskHandler<RetInfo>>([napi = asyncCtx->napi, &encoderInfo = asyncCtx->encoderInfo_]() {
1236         const std::string &option = AVRecordergOpt::GET_ENCODER_INFO;
1237         MEDIA_LOGI("%{public}s Start", option.c_str());
1238 
1239         CHECK_AND_RETURN_RET(napi != nullptr,
1240             GetRetInfo(MSERR_INVALID_OPERATION, option, ""));
1241 
1242         CHECK_AND_RETURN_RET(napi->CheckStateMachine(option) == MSERR_OK,
1243             GetRetInfo(MSERR_INVALID_OPERATION, option, ""));
1244 
1245         CHECK_AND_RETURN_RET(napi->CheckRepeatOperation(option) == MSERR_OK,
1246             RetInfo(MSERR_EXT_API9_OK, ""));
1247 
1248         int32_t ret = napi->GetEncoderInfo(encoderInfo);
1249         CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, GetRetInfo(MSERR_INVALID_VAL, "GetEncoderInfoTask", ""),
1250             "get GetEncoderInfoTask failed");
1251 
1252         MEDIA_LOGI("%{public}s End", option.c_str());
1253         return RetInfo(MSERR_EXT_API9_OK, "");
1254     });
1255 }
1256 
IsWatermarkSupportedTask(const std::unique_ptr<AVRecorderAsyncContext> & asyncCtx)1257 std::shared_ptr<TaskHandler<RetInfo>> AVRecorderNapi::IsWatermarkSupportedTask(
1258     const std::unique_ptr<AVRecorderAsyncContext> &asyncCtx)
1259 {
1260     return std::make_shared<TaskHandler<RetInfo>>([napi = asyncCtx->napi,
1261         &isWatermarkSupported = asyncCtx->isWatermarkSupported_]() {
1262         const std::string &option = AVRecordergOpt::IS_WATERMARK_SUPPORTED;
1263         MEDIA_LOGI("%{public}s Start", option.c_str());
1264 
1265         CHECK_AND_RETURN_RET(napi != nullptr,
1266             GetRetInfo(MSERR_INVALID_OPERATION, option, ""));
1267 
1268         CHECK_AND_RETURN_RET(napi->CheckStateMachine(option) == MSERR_OK,
1269             GetRetInfo(MSERR_INVALID_OPERATION, option, ""));
1270 
1271         CHECK_AND_RETURN_RET(napi->CheckRepeatOperation(option) == MSERR_OK,
1272             RetInfo(MSERR_EXT_API9_OK, ""));
1273 
1274         int32_t ret = napi->IsWatermarkSupported(isWatermarkSupported);
1275         CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, GetRetInfo(MSERR_INVALID_VAL, "IsWatermarkSupportedTask", ""),
1276             "IsWatermarkSupportedTask failed");
1277 
1278         MEDIA_LOGI("%{public}s End", option.c_str());
1279         return RetInfo(MSERR_EXT_API9_OK, "");
1280     });
1281 }
1282 
SetWatermarkTask(const std::unique_ptr<AVRecorderAsyncContext> & asyncCtx)1283 std::shared_ptr<TaskHandler<RetInfo>> AVRecorderNapi::SetWatermarkTask(
1284     const std::unique_ptr<AVRecorderAsyncContext> &asyncCtx)
1285 {
1286     return std::make_shared<TaskHandler<RetInfo>>([napi = asyncCtx->napi, &pixelMap = asyncCtx->pixelMap_,
1287         &watermarkConfig = asyncCtx->watermarkConfig_]() {
1288         const std::string &option = AVRecordergOpt::SET_WATERMARK;
1289         MEDIA_LOGI("%{public}s Start", option.c_str());
1290 
1291         CHECK_AND_RETURN_RET(napi != nullptr,
1292             GetRetInfo(MSERR_INVALID_OPERATION, option, ""));
1293 
1294         CHECK_AND_RETURN_RET(napi->CheckStateMachine(option) == MSERR_OK,
1295             GetRetInfo(MSERR_INVALID_OPERATION, option, ""));
1296 
1297         CHECK_AND_RETURN_RET(napi->CheckRepeatOperation(option) == MSERR_OK,
1298             RetInfo(MSERR_EXT_API9_OK, ""));
1299         bool isWatermarkSupported = false;
1300         int32_t ret = napi->IsWatermarkSupported(isWatermarkSupported);
1301         CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, GetRetInfo(MSERR_UNKNOWN, "SetWatermarkTask", ""),
1302             "IsWatermarkSupported fail");
1303         CHECK_AND_RETURN_RET_LOG(isWatermarkSupported, GetRetInfo(MSERR_UNSUPPORT_WATER_MARK, "SetWatermarkTask", ""),
1304             "capability not supported");
1305 
1306         ret = napi->SetWatermark(pixelMap, watermarkConfig);
1307         CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, GetRetInfo(ret, "SetWatermarkTask", ""),
1308             "SetWatermarkTask failed");
1309 
1310         MEDIA_LOGI("%{public}s End", option.c_str());
1311         return RetInfo(MSERR_EXT_API9_OK, "");
1312     });
1313 }
1314 
GetInputSurface()1315 RetInfo AVRecorderNapi::GetInputSurface()
1316 {
1317     CHECK_AND_RETURN_RET_LOG(withVideo_, GetRetInfo(MSERR_INVALID_OPERATION, "GetInputSurface", "",
1318         "The VideoSourceType is not configured. Please do not call getInputSurface"), "No video recording");
1319 
1320     if (surface_ == nullptr) {
1321         surface_ = recorder_->GetSurface(videoSourceID_);
1322         CHECK_AND_RETURN_RET_LOG(surface_ != nullptr,
1323             GetRetInfo(MSERR_INVALID_OPERATION, "GetInputSurface", ""), "failed to GetSurface");
1324 
1325         SurfaceError error = SurfaceUtils::GetInstance()->Add(surface_->GetUniqueId(), surface_);
1326         CHECK_AND_RETURN_RET_LOG(error == SURFACE_ERROR_OK,
1327             GetRetInfo(MSERR_INVALID_OPERATION, "GetInputSurface", ""), "failed to AddSurface");
1328     }
1329 
1330     auto surfaceId = std::to_string(surface_->GetUniqueId());
1331     getVideoInputSurface_ = true;
1332     return RetInfo(MSERR_EXT_API9_OK, surfaceId);
1333 }
1334 
GetInputMetaSurface(const std::unique_ptr<AVRecorderAsyncContext> & asyncCtx)1335 std::shared_ptr<TaskHandler<RetInfo>> AVRecorderNapi::GetInputMetaSurface(
1336     const std::unique_ptr<AVRecorderAsyncContext> &asyncCtx)
1337 {
1338     return std::make_shared<TaskHandler<RetInfo>>(
1339         [napi = asyncCtx->napi, config = asyncCtx->config_, type = asyncCtx->metaType_]() {
1340         const std::string &option = AVRecordergOpt::GETINPUTMETASURFACE;
1341         MEDIA_LOGI("%{public}s Start", option.c_str());
1342         CHECK_AND_RETURN_RET(napi != nullptr && napi->recorder_ != nullptr && config != nullptr,
1343             GetRetInfo(MSERR_INVALID_OPERATION, option, ""));
1344 
1345         CHECK_AND_RETURN_RET(napi->CheckStateMachine(option) == MSERR_OK,
1346             GetRetInfo(MSERR_INVALID_OPERATION, option, ""));
1347         CHECK_AND_RETURN_RET_LOG(napi->metaSourceIDMap_.find(type) != napi->metaSourceIDMap_.end(),
1348             GetRetInfo(MSERR_INVALID_OPERATION, "GetInputMetaSurface", "no meta source type"),
1349             "failed to find meta type");
1350         if (napi->metaSurface_ == nullptr) {
1351             MEDIA_LOGI("The meta source type is %{public}d", static_cast<int32_t>(type));
1352             napi->metaSurface_ = napi->recorder_->GetMetaSurface(napi->metaSourceIDMap_.at(type));
1353             CHECK_AND_RETURN_RET_LOG(napi->metaSurface_ != nullptr,
1354                 GetRetInfo(MSERR_INVALID_OPERATION, "GetInputMetaSurface", ""), "failed to GetInputMetaSurface");
1355 
1356             SurfaceError error =
1357                 SurfaceUtils::GetInstance()->Add(napi->metaSurface_->GetUniqueId(), napi->metaSurface_);
1358             CHECK_AND_RETURN_RET_LOG(error == SURFACE_ERROR_OK,
1359                 GetRetInfo(MSERR_INVALID_OPERATION, "GetInputMetaSurface", "add surface failed"),
1360                 "failed to AddSurface");
1361         }
1362 
1363         auto surfaceId = std::to_string(napi->metaSurface_->GetUniqueId());
1364         MEDIA_LOGI("surfaceId:%{public}s", surfaceId.c_str());
1365         MEDIA_LOGI("%{public}s End", option.c_str());
1366         return RetInfo(MSERR_EXT_API9_OK, surfaceId);
1367     });
1368 }
1369 
Start()1370 RetInfo AVRecorderNapi::Start()
1371 {
1372     if (withVideo_ && !getVideoInputSurface_) {
1373         return GetRetInfo(MSERR_INVALID_OPERATION, "Start", "",
1374             " Please get the video input surface through GetInputSurface first!");
1375     }
1376 
1377     int32_t ret = recorder_->Start();
1378     CHECK_AND_RETURN_RET(ret == MSERR_OK, GetRetInfo(ret, "Start", ""));
1379     StateCallback(AVRecorderState::STATE_STARTED);
1380     return RetInfo(MSERR_EXT_API9_OK, "");
1381 }
1382 
Pause()1383 RetInfo AVRecorderNapi::Pause()
1384 {
1385     int32_t ret = recorder_->Pause();
1386     CHECK_AND_RETURN_RET(ret == MSERR_OK, GetRetInfo(ret, "Pause", ""));
1387     StateCallback(AVRecorderState::STATE_PAUSED);
1388     return RetInfo(MSERR_EXT_API9_OK, "");
1389 }
1390 
Resume()1391 RetInfo AVRecorderNapi::Resume()
1392 {
1393     int32_t ret = recorder_->Resume();
1394     CHECK_AND_RETURN_RET(ret == MSERR_OK, GetRetInfo(ret, "Resume", ""));
1395     StateCallback(AVRecorderState::STATE_STARTED);
1396     return RetInfo(MSERR_EXT_API9_OK, "");
1397 }
1398 
Stop()1399 RetInfo AVRecorderNapi::Stop()
1400 {
1401     int32_t ret = recorder_->Stop(false);
1402     CHECK_AND_RETURN_RET(ret == MSERR_OK, GetRetInfo(ret, "Stop", ""));
1403     StateCallback(AVRecorderState::STATE_STOPPED);
1404     hasConfiged_ = false;
1405     return RetInfo(MSERR_EXT_API9_OK, "");
1406 }
1407 
Reset()1408 RetInfo AVRecorderNapi::Reset()
1409 {
1410     RemoveSurface();
1411     int32_t ret = recorder_->Reset();
1412     CHECK_AND_RETURN_RET(ret == MSERR_OK, GetRetInfo(ret, "Reset", ""));
1413 
1414     StateCallback(AVRecorderState::STATE_IDLE);
1415     hasConfiged_ = false;
1416     return RetInfo(MSERR_EXT_API9_OK, "");
1417 }
1418 
Release()1419 RetInfo AVRecorderNapi::Release()
1420 {
1421     RemoveSurface();
1422     int32_t ret = recorder_->Release();
1423     CHECK_AND_RETURN_RET(ret == MSERR_OK, GetRetInfo(ret, "Release", ""));
1424 
1425     StateCallback(AVRecorderState::STATE_RELEASED);
1426     CancelCallback();
1427     hasConfiged_ = false;
1428     return RetInfo(MSERR_EXT_API9_OK, "");
1429 }
1430 
GetAVRecorderConfig(std::shared_ptr<AVRecorderConfig> & config)1431 int32_t AVRecorderNapi::GetAVRecorderConfig(std::shared_ptr<AVRecorderConfig> &config)
1432 {
1433     ConfigMap configMap;
1434     recorder_->GetAVRecorderConfig(configMap);
1435     Location location;
1436     recorder_->GetLocation(location);
1437 
1438     config->profile.audioBitrate = configMap["audioBitrate"];
1439     config->profile.audioChannels = configMap["audioChannels"];
1440     config->profile.audioCodecFormat = static_cast<AudioCodecFormat>(configMap["audioCodec"]);
1441     config->profile.auidoSampleRate = configMap["audioSampleRate"];
1442     config->profile.fileFormat = static_cast<OutputFormatType>(configMap["fileFormat"]);
1443     config->profile.videoBitrate = configMap["videoBitrate"];
1444     config->profile.videoCodecFormat = static_cast<VideoCodecFormat>(configMap["videoCodec"]);
1445     config->profile.videoFrameHeight = configMap["videoFrameHeight"];
1446     config->profile.videoFrameWidth = configMap["videoFrameWidth"];
1447     config->profile.videoFrameRate = configMap["videoFrameRate"];
1448 
1449     config->audioSourceType = static_cast<AudioSourceType>(configMap["audioSourceType"]);
1450     config->videoSourceType = static_cast<VideoSourceType>(configMap["videoSourceType"]);
1451     const std::string fdHead = "fd://";
1452     config->url = fdHead + std::to_string(configMap["url"]);
1453     config->rotation = configMap["rotation"];
1454     config->withVideo = configMap["withVideo"];
1455     config->withAudio = configMap["withAudio"];
1456     config->withLocation = configMap["withLocation"];
1457     config->location.latitude = location.latitude;
1458     config->location.longitude = location.longitude;
1459     return MSERR_OK;
1460 }
1461 
GetCurrentCapturerChangeInfo(AudioRecorderChangeInfo & changeInfo)1462 int32_t AVRecorderNapi::GetCurrentCapturerChangeInfo(AudioRecorderChangeInfo &changeInfo)
1463 {
1464     int32_t ret = recorder_->GetCurrentCapturerChangeInfo(changeInfo);
1465     return ret;
1466 }
1467 
GetMaxAmplitude(int32_t & maxAmplitude)1468 int32_t AVRecorderNapi::GetMaxAmplitude(int32_t &maxAmplitude)
1469 {
1470     maxAmplitude = recorder_->GetMaxAmplitude();
1471     return MSERR_OK;
1472 }
1473 
GetEncoderInfo(std::vector<EncoderCapabilityData> & encoderInfo)1474 int32_t AVRecorderNapi::GetEncoderInfo(std::vector<EncoderCapabilityData> &encoderInfo)
1475 {
1476     int32_t ret = recorder_->GetAvailableEncoder(encoderInfo);
1477     return ret;
1478 }
1479 
IsWatermarkSupported(bool & isWatermarkSupported)1480 int32_t AVRecorderNapi::IsWatermarkSupported(bool &isWatermarkSupported)
1481 {
1482     return recorder_->IsWatermarkSupported(isWatermarkSupported);
1483 }
1484 
SetWatermark(std::shared_ptr<PixelMap> & pixelMap,std::shared_ptr<WatermarkConfig> & watermarkConfig)1485 int32_t AVRecorderNapi::SetWatermark(std::shared_ptr<PixelMap> &pixelMap,
1486     std::shared_ptr<WatermarkConfig> &watermarkConfig)
1487 {
1488 #ifndef CROSS_PLATFORM
1489     MEDIA_LOGD("pixelMap Width %{public}d, height %{public}d, pixelformat %{public}d, RowStride %{public}d",
1490         pixelMap->GetWidth(), pixelMap->GetHeight(), pixelMap->GetPixelFormat(), pixelMap->GetRowStride());
1491     CHECK_AND_RETURN_RET_LOG(pixelMap->GetPixelFormat() == PixelFormat::RGBA_8888, MSERR_INVALID_VAL,
1492         "Invalid pixel format");
1493     std::shared_ptr<Meta> avBufferConfig = std::make_shared<Meta>();
1494     int32_t ret = ConfigAVBufferMeta(pixelMap, watermarkConfig, avBufferConfig);
1495     CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, MSERR_INVALID_VAL, "ConfigAVBufferMeta is failed");
1496     sptr<SurfaceBuffer> surfaceBuffer = SurfaceBuffer::Create();
1497     BufferRequestConfig bufferConfig = {
1498         .width = pixelMap->GetWidth(),
1499         .height = pixelMap->GetHeight(),
1500         .strideAlignment = 0x8,
1501         .format = GraphicPixelFormat::GRAPHIC_PIXEL_FMT_RGBA_8888,
1502         .usage = BUFFER_USAGE_CPU_READ | BUFFER_USAGE_CPU_WRITE | BUFFER_USAGE_MEM_DMA,
1503         .timeout = 0,
1504     };
1505     surfaceBuffer->Alloc(bufferConfig);
1506 
1507     MEDIA_LOGD("surface size %{public}d, surface stride %{public}d",
1508         surfaceBuffer->GetSize(), surfaceBuffer->GetStride());
1509 
1510     for (int i = 0; i < pixelMap->GetHeight(); i++) {
1511         ret = memcpy_s(static_cast<uint8_t *>(surfaceBuffer->GetVirAddr()) + i * surfaceBuffer->GetStride(),
1512             pixelMap->GetRowStride(), pixelMap->GetPixels() + i * pixelMap->GetRowStride(), pixelMap->GetRowStride());
1513         CHECK_AND_RETURN_RET_LOG(ret == 0, MSERR_INVALID_VAL, "memcpy failed");
1514     }
1515     std::shared_ptr<AVBuffer> waterMarkBuffer = AVBuffer::CreateAVBuffer(surfaceBuffer);
1516     CHECK_AND_RETURN_RET_LOG(waterMarkBuffer != nullptr, MSERR_NO_MEMORY, "surfaceBuffer is nullptr");
1517     waterMarkBuffer->meta_ = avBufferConfig;
1518     return recorder_->SetWatermark(waterMarkBuffer);
1519 #endif
1520     return MSERR_OK;
1521 }
1522 
ConfigAVBufferMeta(std::shared_ptr<PixelMap> & pixelMap,std::shared_ptr<WatermarkConfig> & watermarkConfig,std::shared_ptr<Meta> & meta)1523 int32_t AVRecorderNapi::ConfigAVBufferMeta(std::shared_ptr<PixelMap> &pixelMap,
1524     std::shared_ptr<WatermarkConfig> &watermarkConfig, std::shared_ptr<Meta> &meta)
1525 {
1526     int32_t top = watermarkConfig->top;
1527     int32_t left = watermarkConfig->left;
1528     int32_t watermarkWidth = pixelMap->GetWidth();
1529     int32_t watermarkHeight = pixelMap->GetHeight();
1530     meta->Set<Tag::VIDEO_ENCODER_ENABLE_WATERMARK>(true);
1531     switch (rotation_) {
1532         case VIDEO_ROTATION_0:
1533             meta->Set<Tag::VIDEO_COORDINATE_X>(left);
1534             meta->Set<Tag::VIDEO_COORDINATE_Y>(top);
1535             meta->Set<Tag::VIDEO_COORDINATE_W>(watermarkWidth);
1536             meta->Set<Tag::VIDEO_COORDINATE_H>(watermarkHeight);
1537             break;
1538         case VIDEO_ROTATION_90:
1539             MEDIA_LOGI("rotation %{public}d", VIDEO_ROTATION_90);
1540             CHECK_AND_RETURN_RET_LOG(videoFrameHeight_ - left - watermarkWidth >= 0,
1541                 MSERR_INVALID_VAL, "invalid watermark");
1542             pixelMap->rotate(VIDEO_ROTATION_270);
1543             meta->Set<Tag::VIDEO_COORDINATE_X>(top);
1544             meta->Set<Tag::VIDEO_COORDINATE_Y>(videoFrameHeight_ - left - watermarkWidth);
1545             meta->Set<Tag::VIDEO_COORDINATE_W>(watermarkHeight);
1546             meta->Set<Tag::VIDEO_COORDINATE_H>(watermarkWidth);
1547             break;
1548         case VIDEO_ROTATION_180:
1549             MEDIA_LOGI("rotation %{public}d", VIDEO_ROTATION_180);
1550             CHECK_AND_RETURN_RET_LOG(videoFrameWidth_-left-watermarkWidth >= 0,
1551                 MSERR_INVALID_VAL, "invalid watermark");
1552             CHECK_AND_RETURN_RET_LOG(videoFrameHeight_-top-watermarkHeight >= 0,
1553                 MSERR_INVALID_VAL, "invalid watermark");
1554             pixelMap->rotate(VIDEO_ROTATION_180);
1555             meta->Set<Tag::VIDEO_COORDINATE_X>(videoFrameWidth_-left-watermarkWidth);
1556             meta->Set<Tag::VIDEO_COORDINATE_Y>(videoFrameHeight_-top-watermarkHeight);
1557             meta->Set<Tag::VIDEO_COORDINATE_W>(watermarkWidth);
1558             meta->Set<Tag::VIDEO_COORDINATE_H>(watermarkHeight);
1559             break;
1560         case VIDEO_ROTATION_270:
1561             MEDIA_LOGI("rotation %{public}d", VIDEO_ROTATION_270);
1562             CHECK_AND_RETURN_RET_LOG(videoFrameHeight_ - left - watermarkWidth >= 0,
1563                 MSERR_INVALID_VAL, "invalid watermark");
1564             pixelMap->rotate(VIDEO_ROTATION_90);
1565             meta->Set<Tag::VIDEO_COORDINATE_X>(videoFrameWidth_ - top - watermarkHeight);
1566             meta->Set<Tag::VIDEO_COORDINATE_Y>(left);
1567             meta->Set<Tag::VIDEO_COORDINATE_W>(watermarkHeight);
1568             meta->Set<Tag::VIDEO_COORDINATE_H>(watermarkWidth);
1569             break;
1570         default:
1571             break;
1572     }
1573     return MSERR_OK;
1574 }
1575 
CheckStateMachine(const std::string & opt)1576 int32_t AVRecorderNapi::CheckStateMachine(const std::string &opt)
1577 {
1578     auto napiCb = std::static_pointer_cast<AVRecorderCallback>(recorderCb_);
1579     CHECK_AND_RETURN_RET_LOG(napiCb != nullptr, MSERR_INVALID_OPERATION, "napiCb is nullptr!");
1580 
1581     std::string curState = napiCb->GetState();
1582     std::vector<std::string> allowedOpt = stateCtrlList.at(curState);
1583     if (find(allowedOpt.begin(), allowedOpt.end(), opt) == allowedOpt.end()) {
1584         MEDIA_LOGE("The %{public}s operation is not allowed in the %{public}s state!", opt.c_str(), curState.c_str());
1585         return MSERR_INVALID_OPERATION;
1586     }
1587 
1588     return MSERR_OK;
1589 }
1590 
CheckRepeatOperation(const std::string & opt)1591 int32_t AVRecorderNapi::CheckRepeatOperation(const std::string &opt)
1592 {
1593     const std::map<std::string, std::vector<std::string>> stateCtrl = {
1594         {AVRecorderState::STATE_IDLE, {
1595             AVRecordergOpt::RESET,
1596             AVRecordergOpt::GET_AV_RECORDER_PROFILE,
1597             AVRecordergOpt::SET_AV_RECORDER_CONFIG,
1598             AVRecordergOpt::GET_AV_RECORDER_CONFIG,
1599         }},
1600         {AVRecorderState::STATE_PREPARED, {}},
1601         {AVRecorderState::STATE_STARTED, {
1602             AVRecordergOpt::START,
1603             AVRecordergOpt::RESUME
1604         }},
1605         {AVRecorderState::STATE_PAUSED, {
1606             AVRecordergOpt::PAUSE
1607         }},
1608         {AVRecorderState::STATE_STOPPED, {
1609             AVRecordergOpt::STOP
1610         }},
1611         {AVRecorderState::STATE_RELEASED, {
1612             AVRecordergOpt::RELEASE
1613         }},
1614         {AVRecorderState::STATE_ERROR, {}},
1615     };
1616 
1617     auto napiCb = std::static_pointer_cast<AVRecorderCallback>(recorderCb_);
1618     CHECK_AND_RETURN_RET_LOG(napiCb != nullptr, MSERR_INVALID_OPERATION, "napiCb is nullptr!");
1619 
1620     std::string curState = napiCb->GetState();
1621     std::vector<std::string> repeatOpt = stateCtrl.at(curState);
1622     if (find(repeatOpt.begin(), repeatOpt.end(), opt) != repeatOpt.end()) {
1623         MEDIA_LOGI("Current state is %{public}s. Please do not call %{public}s again!", curState.c_str(), opt.c_str());
1624         return MSERR_INVALID_OPERATION;
1625     }
1626 
1627     return MSERR_OK;
1628 }
1629 
GetAudioCodecFormat(const std::string & mime,AudioCodecFormat & codecFormat)1630 int32_t AVRecorderNapi::GetAudioCodecFormat(const std::string &mime, AudioCodecFormat &codecFormat)
1631 {
1632     MEDIA_LOGI("mime %{public}s", mime.c_str());
1633     const std::map<std::string_view, AudioCodecFormat> mimeStrToCodecFormat = {
1634         { CodecMimeType::AUDIO_AAC, AudioCodecFormat::AAC_LC },
1635         { CodecMimeType::AUDIO_MPEG, AudioCodecFormat::AUDIO_MPEG },
1636         { CodecMimeType::AUDIO_G711MU, AudioCodecFormat::AUDIO_G711MU },
1637         { "", AudioCodecFormat::AUDIO_DEFAULT },
1638     };
1639 
1640     auto iter = mimeStrToCodecFormat.find(mime);
1641     if (iter != mimeStrToCodecFormat.end()) {
1642         codecFormat = iter->second;
1643         return MSERR_OK;
1644     }
1645     return MSERR_INVALID_VAL;
1646 }
1647 
GetVideoCodecFormat(const std::string & mime,VideoCodecFormat & codecFormat)1648 int32_t AVRecorderNapi::GetVideoCodecFormat(const std::string &mime, VideoCodecFormat &codecFormat)
1649 {
1650     MEDIA_LOGI("mime %{public}s", mime.c_str());
1651     const std::map<std::string_view, VideoCodecFormat> mimeStrToCodecFormat = {
1652         { CodecMimeType::VIDEO_AVC, VideoCodecFormat::H264 },
1653         { CodecMimeType::VIDEO_MPEG4, VideoCodecFormat::MPEG4 },
1654         { CodecMimeType::VIDEO_HEVC, VideoCodecFormat::H265 },
1655         { "", VideoCodecFormat::VIDEO_DEFAULT },
1656     };
1657 
1658     auto iter = mimeStrToCodecFormat.find(mime);
1659     if (iter != mimeStrToCodecFormat.end()) {
1660         codecFormat = iter->second;
1661         return MSERR_OK;
1662     }
1663     return MSERR_INVALID_VAL;
1664 }
1665 
GetOutputFormat(const std::string & extension,OutputFormatType & type)1666 int32_t AVRecorderNapi::GetOutputFormat(const std::string &extension, OutputFormatType &type)
1667 {
1668     MEDIA_LOGI("mime %{public}s", extension.c_str());
1669     const std::map<std::string, OutputFormatType> extensionToOutputFormat = {
1670         { "mp4", OutputFormatType::FORMAT_MPEG_4 },
1671         { "m4a", OutputFormatType::FORMAT_M4A },
1672         { "mp3", OutputFormatType::FORMAT_MP3 },
1673         { "wav", OutputFormatType::FORMAT_WAV },
1674         { "", OutputFormatType::FORMAT_DEFAULT },
1675     };
1676 
1677     auto iter = extensionToOutputFormat.find(extension);
1678     if (iter != extensionToOutputFormat.end()) {
1679         type = iter->second;
1680         return MSERR_OK;
1681     }
1682     return MSERR_INVALID_VAL;
1683 }
1684 
GetSourceType(std::unique_ptr<AVRecorderAsyncContext> & asyncCtx,napi_env env,napi_value args)1685 int32_t AVRecorderNapi::GetSourceType(std::unique_ptr<AVRecorderAsyncContext> &asyncCtx, napi_env env, napi_value args)
1686 {
1687     std::shared_ptr<AVRecorderConfig> config = asyncCtx->config_;
1688     int32_t audioSource = AUDIO_SOURCE_INVALID;
1689     int32_t videoSource = VIDEO_SOURCE_BUTT;
1690     std::vector<int32_t> metaSource {};
1691 
1692     bool getValue = false;
1693     int32_t ret = AVRecorderNapi::GetPropertyInt32(env, args, "audioSourceType", audioSource, getValue);
1694     CHECK_AND_RETURN_RET(ret == MSERR_OK,
1695         (asyncCtx->AVRecorderSignError(ret, "getaudioSourceType", "audioSourceType"), ret));
1696     if (getValue) {
1697         config->audioSourceType = static_cast<AudioSourceType>(audioSource);
1698         config->withAudio = true;
1699         MEDIA_LOGI("audioSource Type %{public}d!", audioSource);
1700     }
1701 
1702     ret = AVRecorderNapi::GetPropertyInt32(env, args, "videoSourceType", videoSource, getValue);
1703     CHECK_AND_RETURN_RET(ret == MSERR_OK,
1704         (asyncCtx->AVRecorderSignError(ret, "getvideoSourceType", "videoSourceType"), ret));
1705     if (getValue) {
1706         config->videoSourceType = static_cast<VideoSourceType>(videoSource);
1707         config->withVideo = true;
1708         MEDIA_LOGI("videoSource Type %{public}d!", videoSource);
1709     }
1710 
1711     ret = AVRecorderNapi::GetPropertyInt32Vec(env, args, "metaSourceTypes", metaSource, getValue);
1712     CHECK_AND_RETURN_RET(ret == MSERR_OK,
1713         (asyncCtx->AVRecorderSignError(ret, "getMetaSourceTypes", "metaSourceTypes"), ret));
1714     if (getValue) {
1715         for (auto item : metaSource) {
1716             config->metaSourceTypeVec.push_back(static_cast<MetaSourceType>(item));
1717         }
1718     }
1719 
1720     CHECK_AND_RETURN_RET(config->withAudio || config->withVideo,
1721         (asyncCtx->AVRecorderSignError(MSERR_INVALID_VAL, "getsourcetype", "SourceType"), MSERR_INVALID_VAL));
1722 
1723     return MSERR_OK;
1724 }
1725 
GetAudioProfile(std::unique_ptr<AVRecorderAsyncContext> & asyncCtx,napi_env env,napi_value item,AVRecorderProfile & profile)1726 int32_t AVRecorderNapi::GetAudioProfile(std::unique_ptr<AVRecorderAsyncContext> &asyncCtx, napi_env env,
1727     napi_value item, AVRecorderProfile &profile)
1728 {
1729     int32_t ret = MSERR_OK;
1730     std::string audioCodec = CommonNapi::GetPropertyString(env, item, "audioCodec");
1731     ret = AVRecorderNapi::GetAudioCodecFormat(audioCodec, profile.audioCodecFormat);
1732     CHECK_AND_RETURN_RET(ret == MSERR_OK,
1733         (asyncCtx->AVRecorderSignError(ret, "GetAudioCodecFormat", "audioCodecFormat"), ret));
1734     ret = MSERR_INVALID_VAL;
1735     CHECK_AND_RETURN_RET(CommonNapi::GetPropertyInt32(env, item, "audioBitrate", profile.audioBitrate),
1736         (asyncCtx->AVRecorderSignError(ret, "GetaudioBitrate", "audioBitrate"), ret));
1737     CHECK_AND_RETURN_RET(CommonNapi::GetPropertyInt32(env, item, "audioChannels", profile.audioChannels),
1738         (asyncCtx->AVRecorderSignError(ret, "GetaudioChannels", "audioChannels"), ret));
1739     CHECK_AND_RETURN_RET(CommonNapi::GetPropertyInt32(env, item, "audioSampleRate", profile.auidoSampleRate),
1740         (asyncCtx->AVRecorderSignError(ret, "GetauidoSampleRate", "auidoSampleRate"), ret));
1741     MediaProfileLog(false, profile);
1742     return ret;
1743 }
1744 
GetVideoProfile(std::unique_ptr<AVRecorderAsyncContext> & asyncCtx,napi_env env,napi_value item,AVRecorderProfile & profile)1745 int32_t AVRecorderNapi::GetVideoProfile(std::unique_ptr<AVRecorderAsyncContext> &asyncCtx, napi_env env,
1746     napi_value item, AVRecorderProfile &profile)
1747 {
1748     int32_t ret = MSERR_OK;
1749     std::string videoCodec = CommonNapi::GetPropertyString(env, item, "videoCodec");
1750     ret = AVRecorderNapi::GetVideoCodecFormat(videoCodec, profile.videoCodecFormat);
1751     CHECK_AND_RETURN_RET(ret == MSERR_OK,
1752         (asyncCtx->AVRecorderSignError(ret, "GetVideoCodecFormat", "videoCodecFormat"), ret));
1753     ret = MSERR_INVALID_VAL;
1754     CHECK_AND_RETURN_RET(CommonNapi::GetPropertyInt32(env, item, "videoBitrate", profile.videoBitrate),
1755         (asyncCtx->AVRecorderSignError(ret, "GetvideoBitrate", "videoBitrate"), ret));
1756     CHECK_AND_RETURN_RET(CommonNapi::GetPropertyInt32(env, item, "videoFrameWidth", profile.videoFrameWidth),
1757         (asyncCtx->AVRecorderSignError(ret, "GetvideoFrameWidth", "videoFrameWidth"), ret));
1758     videoFrameWidth_ = profile.videoFrameWidth;
1759     CHECK_AND_RETURN_RET(CommonNapi::GetPropertyInt32(env, item, "videoFrameHeight", profile.videoFrameHeight),
1760         (asyncCtx->AVRecorderSignError(ret, "GetvideoFrameHeight", "videoFrameHeight"), ret));
1761     videoFrameHeight_ = profile.videoFrameHeight;
1762     CHECK_AND_RETURN_RET(CommonNapi::GetPropertyInt32(env, item, "videoFrameRate", profile.videoFrameRate),
1763         (asyncCtx->AVRecorderSignError(ret, "GetvideoFrameRate", "videoFrameRate"), ret));
1764     if (CommonNapi::GetPropertyBool(env, item, "isHdr", profile.isHdr)) {
1765         CHECK_AND_RETURN_RET(!(profile.isHdr && (profile.videoCodecFormat != VideoCodecFormat::H265)),
1766             (asyncCtx->AVRecorderSignError(MSERR_UNSUPPORT_VID_PARAMS, "isHdr needs to match video/hevc", ""),
1767             MSERR_UNSUPPORT_VID_PARAMS));
1768     } else {
1769         profile.isHdr = false;
1770     }
1771     if (!CommonNapi::GetPropertyBool(env, item, "enableTemporalScale", profile.enableTemporalScale)) {
1772         MEDIA_LOGI("avRecorderProfile enableTemporalScale is not set.");
1773         profile.enableTemporalScale = false;
1774     }
1775 
1776     MediaProfileLog(true, profile);
1777     return ret;
1778 }
1779 
GetProfile(std::unique_ptr<AVRecorderAsyncContext> & asyncCtx,napi_env env,napi_value args)1780 int32_t AVRecorderNapi::GetProfile(std::unique_ptr<AVRecorderAsyncContext> &asyncCtx, napi_env env, napi_value args)
1781 {
1782     napi_value item = nullptr;
1783     napi_get_named_property(env, args, "profile", &item);
1784     CHECK_AND_RETURN_RET_LOG(item != nullptr, MSERR_INVALID_VAL, "get profile error");
1785     AVRecorderProfile &profile = asyncCtx->config_->profile;
1786     int32_t ret = MSERR_OK;
1787     if (asyncCtx->config_->withAudio) {
1788         ret = GetAudioProfile(asyncCtx, env, item, profile);
1789     }
1790     if (asyncCtx->config_->withVideo) {
1791         ret = GetVideoProfile(asyncCtx, env, item, profile);
1792     }
1793 
1794     std::string outputFile = CommonNapi::GetPropertyString(env, item, "fileFormat");
1795     ret = AVRecorderNapi::GetOutputFormat(outputFile, profile.fileFormat);
1796     CHECK_AND_RETURN_RET(ret == MSERR_OK, (asyncCtx->AVRecorderSignError(ret, "GetOutputFormat", "fileFormat"), ret));
1797     MEDIA_LOGI("fileFormat %{public}d", profile.fileFormat);
1798     return MSERR_OK;
1799 }
1800 
GetModeAndUrl(std::unique_ptr<AVRecorderAsyncContext> & asyncCtx,napi_env env,napi_value args)1801 int32_t AVRecorderNapi::GetModeAndUrl(std::unique_ptr<AVRecorderAsyncContext> &asyncCtx, napi_env env, napi_value args)
1802 {
1803     if (CommonNapi::CheckhasNamedProperty(env, args, "fileGenerationMode")) {
1804         int32_t mode = 0;
1805         CHECK_AND_RETURN_RET(CommonNapi::GetPropertyInt32(env, args, "fileGenerationMode", mode),
1806             (asyncCtx->AVRecorderSignError(MSERR_INVALID_VAL, "GetFileGenerationMode", "fileGenerationMode",
1807                 "failed to GetFileGenerationMode"), MSERR_INVALID_VAL));
1808         CHECK_AND_RETURN_RET(mode >= FileGenerationMode::APP_CREATE
1809             && mode <= FileGenerationMode::AUTO_CREATE_CAMERA_SCENE,
1810             (asyncCtx->AVRecorderSignError(MSERR_INVALID_VAL, "fileGenerationMode", "fileGenerationMode",
1811                 "invalide fileGenerationMode"), MSERR_INVALID_VAL));
1812         asyncCtx->config_->fileGenerationMode = static_cast<FileGenerationMode>(mode);
1813         MEDIA_LOGI("FileGenerationMode %{public}d!", mode);
1814     }
1815 
1816     asyncCtx->config_->url = CommonNapi::GetPropertyString(env, args, "url");
1817     MEDIA_LOGI("url %{public}s!", asyncCtx->config_->url.c_str());
1818     if (asyncCtx->config_->fileGenerationMode == FileGenerationMode::APP_CREATE) {
1819         CHECK_AND_RETURN_RET(asyncCtx->config_->url != "",
1820             (asyncCtx->AVRecorderSignError(MSERR_PARAMETER_VERIFICATION_FAILED, "geturl", "url",
1821                 "config->url cannot be null"), MSERR_PARAMETER_VERIFICATION_FAILED));
1822     }
1823     return MSERR_OK;
1824 }
1825 
MediaProfileLog(bool isVideo,AVRecorderProfile & profile)1826 void AVRecorderNapi::MediaProfileLog(bool isVideo, AVRecorderProfile &profile)
1827 {
1828     if (isVideo) {
1829         MEDIA_LOGI("videoBitrate %{public}d, videoCodecFormat %{public}d, videoFrameWidth %{public}d,"
1830             " videoFrameHeight %{public}d, videoFrameRate %{public}d, isHdr %{public}d, enableTemporalScale %{public}d",
1831             profile.videoBitrate, profile.videoCodecFormat, profile.videoFrameWidth,
1832             profile.videoFrameHeight, profile.videoFrameRate, profile.isHdr, profile.enableTemporalScale);
1833         return;
1834     }
1835     MEDIA_LOGI("audioBitrate %{public}d, audioChannels %{public}d, audioCodecFormat %{public}d,"
1836         " audioSampleRate %{public}d!", profile.audioBitrate, profile.audioChannels,
1837         profile.audioCodecFormat, profile.auidoSampleRate);
1838 }
1839 
GetConfig(std::unique_ptr<AVRecorderAsyncContext> & asyncCtx,napi_env env,napi_value args)1840 int32_t AVRecorderNapi::GetConfig(std::unique_ptr<AVRecorderAsyncContext> &asyncCtx, napi_env env, napi_value args)
1841 {
1842     CHECK_AND_RETURN_RET(CommonNapi::CheckValueType(env, args, napi_object),
1843         (asyncCtx->AVRecorderSignError(MSERR_INCORRECT_PARAMETER_TYPE, "GetConfig", "AVRecorderConfig",
1844             "config type should be AVRecorderConfig."), MSERR_INCORRECT_PARAMETER_TYPE));
1845 
1846     asyncCtx->config_ = std::make_shared<AVRecorderConfig>();
1847     CHECK_AND_RETURN_RET(asyncCtx->config_,
1848         (asyncCtx->AVRecorderSignError(MSERR_NO_MEMORY, "AVRecorderConfig", "AVRecorderConfig"), MSERR_NO_MEMORY));
1849 
1850     std::shared_ptr<AVRecorderConfig> config = asyncCtx->config_;
1851 
1852     int32_t ret = GetSourceType(asyncCtx, env, args);
1853     CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, ret, "failed to GetSourceType");
1854 
1855     ret = GetProfile(asyncCtx, env, args);
1856     CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, ret, "failed to GetProfile");
1857 
1858     ret = GetModeAndUrl(asyncCtx, env, args);
1859     CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, ret, "failed to GetModeAndUrl");
1860 
1861     bool getValue = false;
1862     ret = AVRecorderNapi::GetPropertyInt32(env, args, "rotation", config->rotation, getValue);
1863     CHECK_AND_RETURN_RET(ret == MSERR_OK,
1864         (asyncCtx->AVRecorderSignError(ret, "getrotation", "rotation"), ret));
1865     MEDIA_LOGI("rotation %{public}d!", config->rotation);
1866     CHECK_AND_RETURN_RET((config->rotation == VIDEO_ROTATION_0 || config->rotation == VIDEO_ROTATION_90 ||
1867         config->rotation == VIDEO_ROTATION_180 || config->rotation == VIDEO_ROTATION_270),
1868         (asyncCtx->AVRecorderSignError(MSERR_PARAMETER_VERIFICATION_FAILED, "getrotation", "rotation",
1869             "rotation angle must be 0, 90, 180 or 270!"), MSERR_PARAMETER_VERIFICATION_FAILED));
1870     rotation_ = config->rotation;
1871     if (CommonNapi::CheckhasNamedProperty(env, args, "location")) {
1872         CHECK_AND_RETURN_RET(GetLocation(asyncCtx, env, args),
1873             (asyncCtx->AVRecorderSignError(MSERR_INVALID_VAL, "GetLocation", "Location"), MSERR_INVALID_VAL));
1874     }
1875 
1876     if (CommonNapi::CheckhasNamedProperty(env, args, "metadata")) {
1877         CHECK_AND_RETURN_RET_LOG(AVRecorderNapi::GetAVMetaData(asyncCtx, env, args) == MSERR_OK,
1878             MSERR_INVALID_VAL, "failed to GetAVMetaData");
1879     }
1880     return MSERR_OK;
1881 }
1882 
GetRotation(std::unique_ptr<AVRecorderAsyncContext> & asyncCtx,napi_env env,napi_value args)1883 int32_t AVRecorderNapi::GetRotation(std::unique_ptr<AVRecorderAsyncContext> &asyncCtx, napi_env env, napi_value args)
1884 {
1885     napi_valuetype valueType = napi_undefined;
1886     if (args == nullptr || napi_typeof(env, args, &valueType) != napi_ok ||
1887         (valueType != napi_object && valueType != napi_number)) {
1888         asyncCtx->AVRecorderSignError(MSERR_INCORRECT_PARAMETER_TYPE, "GetConfig", "AVRecorderConfig",
1889             "rotation type should be number.");
1890         return MSERR_INCORRECT_PARAMETER_TYPE;
1891     }
1892 
1893     asyncCtx->config_ = std::make_shared<AVRecorderConfig>();
1894     CHECK_AND_RETURN_RET(asyncCtx->config_,
1895         (asyncCtx->AVRecorderSignError(MSERR_NO_MEMORY, "AVRecorderConfig", "AVRecorderConfig"), MSERR_NO_MEMORY));
1896 
1897     std::shared_ptr<AVRecorderConfig> config = asyncCtx->config_;
1898 
1899     if (napi_get_value_int32(env, args, &(config->rotation)) == napi_ok) {
1900         CHECK_AND_RETURN_RET((config->rotation == VIDEO_ROTATION_0 || config->rotation == VIDEO_ROTATION_90 ||
1901                                  config->rotation == VIDEO_ROTATION_180 || config->rotation == VIDEO_ROTATION_270),
1902             (asyncCtx->AVRecorderSignError(MSERR_INVALID_VAL, "getrotation", "rotation"), MSERR_INVALID_VAL));
1903         MEDIA_LOGI("GetRecordRotation success %{public}d", config->rotation);
1904         rotation_ = config->rotation;
1905         return MSERR_OK;
1906     }
1907 
1908     bool getValue = false;
1909     int32_t ret = AVRecorderNapi::GetPropertyInt32(env, args, "rotation", config->rotation, getValue);
1910     CHECK_AND_RETURN_RET(ret == MSERR_OK,
1911         (asyncCtx->AVRecorderSignError(ret, "getrotation", "rotation"), ret));
1912     MEDIA_LOGI("rotation %{public}d!", config->rotation);
1913     CHECK_AND_RETURN_RET((config->rotation == VIDEO_ROTATION_0 || config->rotation == VIDEO_ROTATION_90 ||
1914         config->rotation == VIDEO_ROTATION_180 || config->rotation == VIDEO_ROTATION_270),
1915         (asyncCtx->AVRecorderSignError(MSERR_INVALID_VAL, "getrotation", "rotation"), MSERR_INVALID_VAL));
1916     rotation_ = config->rotation;
1917     return MSERR_OK;
1918 }
1919 
GetMetaType(std::unique_ptr<AVRecorderAsyncContext> & asyncCtx,napi_env env,napi_value args)1920 int32_t AVRecorderNapi::GetMetaType(std::unique_ptr<AVRecorderAsyncContext> &asyncCtx, napi_env env, napi_value args)
1921 {
1922     napi_valuetype valueType = napi_undefined;
1923     if (args == nullptr || napi_typeof(env, args, &valueType) != napi_ok ||
1924         (valueType != napi_object && valueType != napi_number)) {
1925         asyncCtx->AVRecorderSignError(MSERR_INCORRECT_PARAMETER_TYPE, "GetConfig", "AVRecorderConfig",
1926             "meta type should be number.");
1927         return MSERR_INCORRECT_PARAMETER_TYPE;
1928     }
1929 
1930     asyncCtx->config_ = std::make_shared<AVRecorderConfig>();
1931     CHECK_AND_RETURN_RET(asyncCtx->config_,
1932         (asyncCtx->AVRecorderSignError(MSERR_NO_MEMORY, "AVRecorderConfig", "AVRecorderConfig"), MSERR_NO_MEMORY));
1933 
1934     int32_t metaSourceType = VIDEO_META_SOURCE_INVALID;
1935     if (napi_get_value_int32(env, args, &metaSourceType) != napi_ok) {
1936         std::string string = CommonNapi::GetStringArgument(env, args);
1937         CHECK_AND_RETURN_RET(string == "",
1938             (asyncCtx->AVRecorderSignError(MSERR_INVALID_VAL, "getMetaType", "metaSourceType"), MSERR_INVALID_VAL));
1939     }
1940     asyncCtx->metaType_ = static_cast<MetaSourceType>(metaSourceType);
1941     MEDIA_LOGI("metaSource Type %{public}d!", metaSourceType);
1942     return MSERR_OK;
1943 }
1944 
GetAVMetaData(std::unique_ptr<AVRecorderAsyncContext> & asyncCtx,napi_env env,napi_value args)1945 int32_t AVRecorderNapi::GetAVMetaData(std::unique_ptr<AVRecorderAsyncContext> &asyncCtx, napi_env env,
1946     napi_value args)
1947 {
1948     napi_value metadata = nullptr;
1949     if (napi_get_named_property(env, args, "metadata", &metadata) != napi_ok) {
1950         return (asyncCtx->AVRecorderSignError(MSERR_INVALID_VAL, "GetAVMetaData", "metadata"), MSERR_INVALID_VAL);
1951     }
1952     napi_valuetype valueType = napi_undefined;
1953     if (napi_typeof(env, metadata, &valueType) != napi_ok || valueType != napi_object) {
1954         if (valueType == napi_undefined) {
1955             return MSERR_OK;
1956         }
1957         return (asyncCtx->AVRecorderSignError(MSERR_INVALID_VAL, "GetAVMetaData", "metadata"), MSERR_INVALID_VAL);
1958     }
1959 
1960     AVMetadata &avMetadata = asyncCtx->config_->metadata;
1961 
1962     if (CommonNapi::CheckhasNamedProperty(env, metadata, "location")) {
1963         CHECK_AND_RETURN_RET(GetLocation(asyncCtx, env, metadata),
1964             (asyncCtx->AVRecorderSignError(MSERR_INVALID_VAL, "GetLocation", "Location"), MSERR_INVALID_VAL));
1965     }
1966     if (CommonNapi::CheckhasNamedProperty(env, metadata, "genre")) {
1967         napi_value item = nullptr;
1968         CHECK_AND_RETURN_RET_LOG(napi_get_named_property(env, metadata, "genre", &item) == napi_ok,
1969             MSERR_INVALID_VAL, "get genre property fail");
1970         avMetadata.genre = CommonNapi::GetStringArgument(env, item, CUSTOM_MAX_LENGTH);
1971         CHECK_AND_RETURN_RET(avMetadata.genre != "",
1972             (asyncCtx->AVRecorderSignError(MSERR_INVALID_VAL, "getgenre", "genre"), MSERR_INVALID_VAL));
1973     }
1974     std::string strRotation = CommonNapi::GetPropertyString(env, metadata, "videoOrientation");
1975     if (strRotation == "0" || strRotation == "90" || strRotation == "180" || strRotation == "270") {
1976         asyncCtx->config_->rotation = std::stoi(strRotation);
1977         rotation_ = asyncCtx->config_->rotation;
1978         MEDIA_LOGI("rotation: %{public}d", asyncCtx->config_->rotation);
1979     } else if (strRotation != "") {
1980         asyncCtx->AVRecorderSignError(MSERR_INVALID_VAL, "not support rotation", "videoOrientation");
1981         return MSERR_INVALID_VAL;
1982     }
1983     // get customInfo
1984     if (CommonNapi::CheckhasNamedProperty(env, metadata, "customInfo")) {
1985         CHECK_AND_RETURN_RET(
1986             CommonNapi::GetPropertyRecord(env, metadata, avMetadata.customInfo, "customInfo") == napi_ok,
1987             (asyncCtx->AVRecorderSignError(MSERR_INVALID_VAL, "GetCustomInfo", "customInfo"), MSERR_INVALID_VAL));
1988     }
1989     return MSERR_OK;
1990 }
1991 
GetWatermarkParameter(std::unique_ptr<AVRecorderAsyncContext> & asyncCtx,napi_env env,napi_value watermark,napi_value watermarkConfig)1992 int32_t AVRecorderNapi::GetWatermarkParameter(std::unique_ptr<AVRecorderAsyncContext> &asyncCtx,
1993     napi_env env, napi_value watermark, napi_value watermarkConfig)
1994 {
1995     int32_t ret = GetWatermark(asyncCtx, env, watermark);
1996     CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, ret, "failed to GetWatermark");
1997     ret = GetWatermarkConfig(asyncCtx, env, watermarkConfig);
1998     CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, ret, "failed to GetWatermarkConfig");
1999     return MSERR_OK;
2000 }
2001 
GetWatermark(std::unique_ptr<AVRecorderAsyncContext> & asyncCtx,napi_env env,napi_value args)2002 int32_t AVRecorderNapi::GetWatermark(std::unique_ptr<AVRecorderAsyncContext> &asyncCtx,
2003     napi_env env, napi_value args)
2004 {
2005     CHECK_AND_RETURN_RET(CommonNapi::CheckValueType(env, args, napi_object),
2006         (asyncCtx->AVRecorderSignError(MSERR_INVALID_VAL, "GetPixelMap", "PixelMap"), MSERR_INVALID_VAL));
2007     asyncCtx->pixelMap_ = Media::PixelMapNapi::GetPixelMap(env, args);
2008     CHECK_AND_RETURN_RET(asyncCtx->pixelMap_ != nullptr,
2009         (asyncCtx->AVRecorderSignError(MSERR_INVALID_VAL, "GetPixelMap", "PixelMap"), MSERR_INVALID_VAL));
2010     return MSERR_OK;
2011 }
2012 
GetWatermarkConfig(std::unique_ptr<AVRecorderAsyncContext> & asyncCtx,napi_env env,napi_value args)2013 int32_t AVRecorderNapi::GetWatermarkConfig(std::unique_ptr<AVRecorderAsyncContext> &asyncCtx,
2014     napi_env env, napi_value args)
2015 {
2016     CHECK_AND_RETURN_RET(CommonNapi::CheckValueType(env, args, napi_object),
2017         (asyncCtx->AVRecorderSignError(MSERR_INVALID_VAL, "GetWatermarkConfig", "WatermarkConfig"), MSERR_INVALID_VAL));
2018     asyncCtx->watermarkConfig_ = std::make_shared<WatermarkConfig>();
2019 
2020     bool ret = CommonNapi::GetPropertyInt32(env, args, "top", asyncCtx->watermarkConfig_->top);
2021     CHECK_AND_RETURN_RET(ret && asyncCtx->watermarkConfig_->top >= 0,
2022         (asyncCtx->AVRecorderSignError(MSERR_PARAMETER_VERIFICATION_FAILED, "GetWatermarkConfig", "top",
2023             "config top cannot be null or less than zero"), MSERR_PARAMETER_VERIFICATION_FAILED));
2024 
2025     ret = CommonNapi::GetPropertyInt32(env, args, "left", asyncCtx->watermarkConfig_->left);
2026     CHECK_AND_RETURN_RET(ret && asyncCtx->watermarkConfig_->left >= 0,
2027         (asyncCtx->AVRecorderSignError(MSERR_PARAMETER_VERIFICATION_FAILED, "GetWatermarkConfig", "left",
2028             "config left cannot be null or less than zero"), MSERR_PARAMETER_VERIFICATION_FAILED));
2029     return MSERR_OK;
2030 }
2031 
GetLocation(std::unique_ptr<AVRecorderAsyncContext> & asyncCtx,napi_env env,napi_value args)2032 bool AVRecorderNapi::GetLocation(std::unique_ptr<AVRecorderAsyncContext> &asyncCtx, napi_env env, napi_value args)
2033 {
2034     napi_value geoLocation = nullptr;
2035     napi_valuetype valueType = napi_undefined;
2036     CHECK_AND_RETURN_RET(napi_get_named_property(env, args, "location", &geoLocation) == napi_ok, false);
2037     napi_status status = napi_typeof(env, geoLocation, &valueType);
2038     CHECK_AND_RETURN_RET_LOG(status == napi_ok, status, "get valueType failed");
2039     CHECK_AND_RETURN_RET_LOG(valueType != napi_undefined, true, "location undefined");
2040     userLocation &location = asyncCtx->config_->metadata.location;
2041 
2042     double tempLatitude = 0;
2043     double tempLongitude = 0;
2044     CHECK_AND_RETURN_RET(CommonNapi::GetPropertyDouble(env, geoLocation, "latitude", tempLatitude), false);
2045     CHECK_AND_RETURN_RET(CommonNapi::GetPropertyDouble(env, geoLocation, "longitude", tempLongitude), false);
2046     location.latitude = static_cast<float>(tempLatitude);
2047     location.longitude = static_cast<float>(tempLongitude);
2048     asyncCtx->config_->withLocation = true;
2049     return true;
2050 }
2051 
SetProfile(std::shared_ptr<AVRecorderConfig> config)2052 RetInfo AVRecorderNapi::SetProfile(std::shared_ptr<AVRecorderConfig> config)
2053 {
2054     int32_t ret;
2055     AVRecorderProfile &profile = config->profile;
2056 
2057     ret = recorder_->SetOutputFormat(profile.fileFormat);
2058     CHECK_AND_RETURN_RET(ret == MSERR_OK, GetRetInfo(ret, "SetOutputFormat", "fileFormat"));
2059 
2060     if (config->withAudio) {
2061         ret = recorder_->SetAudioEncoder(audioSourceID_, profile.audioCodecFormat);
2062         CHECK_AND_RETURN_RET(ret == MSERR_OK, GetRetInfo(ret, "SetAudioEncoder", "audioCodecFormat"));
2063 
2064         ret = recorder_->SetAudioSampleRate(audioSourceID_, profile.auidoSampleRate);
2065         CHECK_AND_RETURN_RET(ret == MSERR_OK, GetRetInfo(ret, "SetAudioSampleRate", "auidoSampleRate"));
2066 
2067         ret = recorder_->SetAudioChannels(audioSourceID_, profile.audioChannels);
2068         CHECK_AND_RETURN_RET(ret == MSERR_OK, GetRetInfo(ret, "SetAudioChannels", "audioChannels"));
2069 
2070         ret = recorder_->SetAudioEncodingBitRate(audioSourceID_, profile.audioBitrate);
2071         CHECK_AND_RETURN_RET(ret == MSERR_OK, GetRetInfo(ret, "SetAudioEncodingBitRate", "audioBitrate"));
2072     }
2073 
2074     if (config->withVideo) {
2075         ret = recorder_->SetVideoEncoder(videoSourceID_, profile.videoCodecFormat);
2076         CHECK_AND_RETURN_RET(ret == MSERR_OK, GetRetInfo(ret, "SetVideoEncoder", "videoCodecFormat"));
2077 
2078         ret = recorder_->SetVideoSize(videoSourceID_, profile.videoFrameWidth, profile.videoFrameHeight);
2079         CHECK_AND_RETURN_RET(ret == MSERR_OK, GetRetInfo(ret, "SetVideoSize", "VideoSize"));
2080 
2081         ret = recorder_->SetVideoFrameRate(videoSourceID_, profile.videoFrameRate);
2082         CHECK_AND_RETURN_RET(ret == MSERR_OK, GetRetInfo(ret, "SetVideoFrameRate", "videoFrameRate"));
2083 
2084         ret = recorder_->SetVideoEncodingBitRate(videoSourceID_, profile.videoBitrate);
2085         CHECK_AND_RETURN_RET(ret == MSERR_OK, GetRetInfo(ret, "SetVideoEncodingBitRate", "videoBitrate"));
2086 
2087         ret = recorder_->SetVideoIsHdr(videoSourceID_, profile.isHdr);
2088         CHECK_AND_RETURN_RET(ret == MSERR_OK, GetRetInfo(ret, "SetVideoIsHdr", "isHdr"));
2089 
2090         ret = recorder_->SetVideoEnableTemporalScale(videoSourceID_, profile.enableTemporalScale);
2091         CHECK_AND_RETURN_RET(ret == MSERR_OK, GetRetInfo(ret, "SetVideoEnableTemporalScale", "enableTemporalScale"));
2092     }
2093 
2094     if (config->metaSourceTypeVec.size() != 0 &&
2095         std::find(config->metaSourceTypeVec.cbegin(), config->metaSourceTypeVec.cend(),
2096         MetaSourceType::VIDEO_META_MAKER_INFO) != config->metaSourceTypeVec.cend()) {
2097         ret = recorder_->SetMetaConfigs(metaSourceID_);
2098         CHECK_AND_RETURN_RET(ret == MSERR_OK, GetRetInfo(ret, "SetMetaConfigs", "metaSourceType"));
2099     }
2100 
2101     return RetInfo(MSERR_EXT_API9_OK, "");
2102 }
2103 
Configure(std::shared_ptr<AVRecorderConfig> config)2104 RetInfo AVRecorderNapi::Configure(std::shared_ptr<AVRecorderConfig> config)
2105 {
2106     CHECK_AND_RETURN_RET(recorder_ != nullptr, GetRetInfo(MSERR_INVALID_OPERATION, "Configure", ""));
2107     CHECK_AND_RETURN_RET(config != nullptr, GetRetInfo(MSERR_MANDATORY_PARAMETER_UNSPECIFIED, "Configure", "config"));
2108 
2109     if (hasConfiged_) {
2110         MEDIA_LOGE("AVRecorderConfig has been configured and will not be configured again");
2111         return RetInfo(MSERR_EXT_API9_OK, "");
2112     }
2113 
2114     int32_t ret;
2115     if (config->withAudio) {
2116         ret = recorder_->SetAudioSource(config->audioSourceType, audioSourceID_);
2117         CHECK_AND_RETURN_RET(ret == MSERR_OK, GetRetInfo(ret, "SetAudioSource", "audioSourceType"));
2118     }
2119 
2120     if (config->withVideo) {
2121         ret = recorder_->SetVideoSource(config->videoSourceType, videoSourceID_);
2122         CHECK_AND_RETURN_RET(ret == MSERR_OK, GetRetInfo(ret, "SetVideoSource", "videoSourceType"));
2123     }
2124 
2125     if (config->metaSourceTypeVec.size() != 0 &&
2126         std::find(config->metaSourceTypeVec.cbegin(), config->metaSourceTypeVec.cend(),
2127         MetaSourceType::VIDEO_META_MAKER_INFO) != config->metaSourceTypeVec.cend()) {
2128         ret = recorder_->SetMetaSource(MetaSourceType::VIDEO_META_MAKER_INFO, metaSourceID_);
2129         CHECK_AND_RETURN_RET(ret == MSERR_OK, GetRetInfo(ret, "SetMetaSource", "metaSourceType"));
2130         metaSourceIDMap_.emplace(std::make_pair(MetaSourceType::VIDEO_META_MAKER_INFO, metaSourceID_));
2131     }
2132 
2133     RetInfo retInfo = SetProfile(config);
2134     CHECK_AND_RETURN_RET_LOG(retInfo.first == MSERR_OK, retInfo, "Fail to set videoBitrate");
2135 
2136     if (config->withLocation) {
2137         recorder_->SetLocation(config->metadata.location.latitude, config->metadata.location.longitude);
2138     }
2139 
2140     if (config->withVideo) {
2141         recorder_->SetOrientationHint(config->rotation);
2142     }
2143 
2144     if (!config->metadata.genre.empty()) {
2145         ret = recorder_->SetGenre(config->metadata.genre);
2146         CHECK_AND_RETURN_RET(ret == MSERR_OK, GetRetInfo(ret, "SetGenre", "Genre"));
2147     }
2148     if (!config->metadata.customInfo.Empty()) {
2149         ret = recorder_->SetUserCustomInfo(config->metadata.customInfo);
2150         CHECK_AND_RETURN_RET(ret == MSERR_OK, GetRetInfo(ret, "SetUserCustomInfo", "customInfo"));
2151     }
2152     return ConfigureUrl(config);
2153 }
2154 
ConfigureUrl(std::shared_ptr<AVRecorderConfig> config)2155 RetInfo AVRecorderNapi::ConfigureUrl(std::shared_ptr<AVRecorderConfig> config)
2156 {
2157     int32_t ret;
2158     if (config->fileGenerationMode == FileGenerationMode::AUTO_CREATE_CAMERA_SCENE) {
2159         ret = recorder_->SetFileGenerationMode(config->fileGenerationMode);
2160         CHECK_AND_RETURN_RET(ret == MSERR_OK, GetRetInfo(ret, "SetFileGenerationMode", "fileGenerationMode"));
2161     } else {
2162         ret = MSERR_PARAMETER_VERIFICATION_FAILED;
2163         const std::string fdHead = "fd://";
2164         CHECK_AND_RETURN_RET(config->url.find(fdHead) != std::string::npos, GetRetInfo(ret, "Getfd", "uri"));
2165         int32_t fd = -1;
2166         std::string inputFd = config->url.substr(fdHead.size());
2167         CHECK_AND_RETURN_RET(StrToInt(inputFd, fd) == true && fd >= 0, GetRetInfo(ret, "Getfd", "uri"));
2168 
2169         ret = recorder_->SetOutputFile(fd);
2170         CHECK_AND_RETURN_RET(ret == MSERR_OK, GetRetInfo(ret, "SetOutputFile", "uri"));
2171     }
2172     hasConfiged_ = true;
2173     return RetInfo(MSERR_EXT_API9_OK, "");
2174 }
2175 
GetSourceIdAndQuality(std::unique_ptr<AVRecorderAsyncContext> & asyncCtx,napi_env env,napi_value sourceIdArgs,napi_value qualityArgs,const std::string & opt)2176 int32_t AVRecorderNapi::GetSourceIdAndQuality(std::unique_ptr<AVRecorderAsyncContext> &asyncCtx,
2177     napi_env env, napi_value sourceIdArgs, napi_value qualityArgs, const std::string &opt)
2178 {
2179     if (asyncCtx->napi->CheckStateMachine(opt) == MSERR_OK) {
2180         napi_status ret = napi_get_value_int32(env, sourceIdArgs, &asyncCtx->napi->sourceId_);
2181         if (ret != napi_ok) {
2182             asyncCtx->AVRecorderSignError(MSERR_INVALID_VAL, "failed to get sourceId", "");
2183             return MSERR_INVALID_VAL;
2184         }
2185         ret = napi_get_value_int32(env, qualityArgs, &asyncCtx->napi->qualityLevel_);
2186         if (ret != napi_ok) {
2187             asyncCtx->AVRecorderSignError(MSERR_INVALID_VAL, "failed to get qualityLevel", "");
2188             return MSERR_INVALID_VAL;
2189         }
2190     } else {
2191         asyncCtx->AVRecorderSignError(MSERR_INVALID_OPERATION, opt, "");
2192         return MSERR_INVALID_OPERATION;
2193     }
2194     return MSERR_OK;
2195 }
2196 
GetAVRecorderProfile(std::shared_ptr<AVRecorderProfile> & profile,const int32_t sourceId,const int32_t qualityLevel)2197 int32_t AVRecorderNapi::GetAVRecorderProfile(std::shared_ptr<AVRecorderProfile> &profile,
2198     const int32_t sourceId, const int32_t qualityLevel)
2199 {
2200     MediaTrace trace("AVRecorder::GetAVRecorderProfile");
2201     std::shared_ptr<VideoRecorderProfile> videoRecorderProfile =
2202         OHOS::Media::RecorderProfilesFactory::CreateRecorderProfiles().GetVideoRecorderProfile(sourceId, qualityLevel);
2203     CHECK_AND_RETURN_RET_LOG(videoRecorderProfile != nullptr, MSERR_INVALID_VAL, "failed to get videoRecorderProfile");
2204 
2205     int32_t ret = MSERR_OK;
2206     ret = AVRecorderNapi::GetOutputFormat(videoRecorderProfile->containerFormatType, profile ->fileFormat);
2207     CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, MSERR_INVALID_VAL, "get outputFormat error");
2208 
2209     ret = AVRecorderNapi::GetAudioCodecFormat(videoRecorderProfile->audioCodec, profile ->audioCodecFormat);
2210     CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, MSERR_INVALID_VAL, "get audioCodec error");
2211 
2212     ret = AVRecorderNapi::GetVideoCodecFormat(videoRecorderProfile->videoCodec, profile ->videoCodecFormat);
2213     CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, MSERR_INVALID_VAL, "get videoCodec error");
2214 
2215     profile->audioBitrate = videoRecorderProfile->audioBitrate;
2216     profile->audioChannels = videoRecorderProfile->audioChannels;
2217     profile->auidoSampleRate = videoRecorderProfile->audioSampleRate;
2218     profile->videoBitrate = videoRecorderProfile->videoBitrate;
2219     profile->videoFrameWidth = videoRecorderProfile->videoFrameWidth;
2220     profile->videoFrameHeight = videoRecorderProfile->videoFrameHeight;
2221     profile->videoFrameRate = videoRecorderProfile->videoFrameRate;
2222 
2223     return MSERR_OK;
2224 }
2225 
ErrorCallback(int32_t errCode,const std::string & operate,const std::string & add)2226 void AVRecorderNapi::ErrorCallback(int32_t errCode, const std::string &operate, const std::string &add)
2227 {
2228     MEDIA_LOGE("failed to %{public}s, errCode = %{public}d", operate.c_str(), errCode);
2229     CHECK_AND_RETURN_LOG(recorderCb_ != nullptr, "recorderCb_ is nullptr!");
2230     auto napiCb = std::static_pointer_cast<AVRecorderCallback>(recorderCb_);
2231 
2232     MediaServiceExtErrCodeAPI9 err = MSErrorToExtErrorAPI9(static_cast<MediaServiceErrCode>(errCode));
2233     std::string msg = MSExtErrorAPI9ToString(err, operate, "") + add;
2234     napiCb->SendErrorCallback(errCode, msg);
2235 }
2236 
StateCallback(const std::string & state)2237 void AVRecorderNapi::StateCallback(const std::string &state)
2238 {
2239     MEDIA_LOGI("Change state to %{public}s", state.c_str());
2240     CHECK_AND_RETURN_LOG(recorderCb_ != nullptr, "recorderCb_ is nullptr!");
2241     auto napiCb = std::static_pointer_cast<AVRecorderCallback>(recorderCb_);
2242     napiCb->SendStateCallback(state, StateChangeReason::USER);
2243 }
2244 
SetCallbackReference(const std::string & callbackName,std::shared_ptr<AutoRef> ref)2245 void AVRecorderNapi::SetCallbackReference(const std::string &callbackName, std::shared_ptr<AutoRef> ref)
2246 {
2247     eventCbMap_[callbackName] = ref;
2248     CHECK_AND_RETURN_LOG(recorderCb_ != nullptr, "recorderCb_ is nullptr!");
2249     auto napiCb = std::static_pointer_cast<AVRecorderCallback>(recorderCb_);
2250     napiCb->SaveCallbackReference(callbackName, ref);
2251 }
2252 
CancelCallbackReference(const std::string & callbackName)2253 void AVRecorderNapi::CancelCallbackReference(const std::string &callbackName)
2254 {
2255     CHECK_AND_RETURN_LOG(recorderCb_ != nullptr, "recorderCb_ is nullptr!");
2256     auto napiCb = std::static_pointer_cast<AVRecorderCallback>(recorderCb_);
2257     napiCb->CancelCallbackReference(callbackName);
2258     eventCbMap_[callbackName] = nullptr;
2259 }
2260 
CancelCallback()2261 void AVRecorderNapi::CancelCallback()
2262 {
2263     CHECK_AND_RETURN_LOG(recorderCb_ != nullptr, "recorderCb_ is nullptr!");
2264     auto napiCb = std::static_pointer_cast<AVRecorderCallback>(recorderCb_);
2265     napiCb->ClearCallbackReference();
2266 }
2267 
RemoveSurface()2268 void AVRecorderNapi::RemoveSurface()
2269 {
2270     if (surface_ != nullptr) {
2271         auto id = surface_->GetUniqueId();
2272         auto surface = SurfaceUtils::GetInstance()->GetSurface(id);
2273         if (surface) {
2274             (void)SurfaceUtils::GetInstance()->Remove(id);
2275         }
2276         surface_ = nullptr;
2277     }
2278 }
2279 
GetPropertyInt32(napi_env env,napi_value configObj,const std::string & type,int32_t & result,bool & getValue)2280 int32_t AVRecorderNapi::GetPropertyInt32(napi_env env, napi_value configObj, const std::string &type, int32_t &result,
2281     bool &getValue)
2282 {
2283     napi_value item = nullptr;
2284     bool exist = false;
2285     getValue = false;
2286     napi_status status = napi_has_named_property(env, configObj, type.c_str(), &exist);
2287     if (status != napi_ok || !exist) {
2288         MEDIA_LOGI("can not find %{public}s property", type.c_str());
2289         return MSERR_OK;
2290     }
2291 
2292     if (napi_get_named_property(env, configObj, type.c_str(), &item) != napi_ok) {
2293         MEDIA_LOGI("get %{public}s property fail", type.c_str());
2294         return MSERR_UNKNOWN;
2295     }
2296 
2297     if (napi_get_value_int32(env, item, &result) != napi_ok) {
2298         std::string string = CommonNapi::GetStringArgument(env, item);
2299         if (string == "") {
2300             // This attribute has not been assigned
2301             return MSERR_OK;
2302         } else {
2303             MEDIA_LOGE("get %{public}s property value fail", type.c_str());
2304             return MSERR_INVALID_VAL;
2305         }
2306     }
2307 
2308     MEDIA_LOGI("get %{public}s : %{public}d!", type.c_str(), result);
2309     getValue = true;
2310     return MSERR_OK;
2311 }
2312 
GetPropertyInt32Vec(napi_env env,napi_value configObj,const std::string & type,std::vector<int32_t> & result,bool & getValue)2313 int32_t AVRecorderNapi::GetPropertyInt32Vec(napi_env env, napi_value configObj, const std::string &type,
2314     std::vector<int32_t> &result, bool &getValue)
2315 {
2316     napi_value item = nullptr;
2317     bool exist = false;
2318     getValue = false;
2319     napi_status status = napi_has_named_property(env, configObj, type.c_str(), &exist);
2320     if (status != napi_ok || !exist) {
2321         MEDIA_LOGI("can not find %{public}s property", type.c_str());
2322         return MSERR_OK;
2323     }
2324 
2325     if (napi_get_named_property(env, configObj, type.c_str(), &item) != napi_ok) {
2326         MEDIA_LOGI("get %{public}s property fail", type.c_str());
2327         return MSERR_UNKNOWN;
2328     }
2329     bool isArray = false;
2330     status = napi_is_array(env, item, &isArray);
2331     if (status != napi_ok || !isArray) {
2332         MEDIA_LOGE("get property fail: not array");
2333     }
2334     uint32_t arrayLen = 0;
2335     napi_get_array_length(env, item, &arrayLen);
2336     for (uint32_t i = 0; i < arrayLen; i++) {
2337         napi_value element = nullptr;
2338         napi_get_element(env, item, i, &element);
2339 
2340         napi_valuetype valueType = napi_undefined;
2341         napi_typeof(env, element, &valueType);
2342         if (valueType != napi_number) {
2343             MEDIA_LOGE("get int32 vector failed, not number!");
2344             return MSERR_UNKNOWN;
2345         }
2346 
2347         int32_t int32Value = 0;
2348         napi_get_value_int32(env, element, &int32Value);
2349         result.push_back(int32Value);
2350     }
2351 
2352     getValue = true;
2353     return MSERR_OK;
2354 }
2355 
GetJsResult(napi_env env,napi_value & result)2356 napi_status MediaJsAVRecorderProfile::GetJsResult(napi_env env, napi_value &result)
2357 {
2358     napi_status ret = napi_ok;
2359     bool setRet = true;
2360     int32_t setState = MSERR_OK;
2361     CHECK_AND_RETURN_RET(value_ != nullptr, napi_generic_failure);
2362     CHECK_AND_RETURN_RET((ret = napi_create_object(env, &result)) == napi_ok, ret);
2363 
2364     setRet = CommonNapi::SetPropertyInt32(env, result, "audioBitrate", value_->audioBitrate);
2365     CHECK_AND_RETURN_RET(setRet == true, napi_generic_failure);
2366     setRet = CommonNapi::SetPropertyInt32(env, result, "audioChannels", value_->audioChannels);
2367     CHECK_AND_RETURN_RET(setRet == true, napi_generic_failure);
2368 
2369     std::string audioCodec;
2370     setState = MediaJsResultExtensionMethod::SetAudioCodecFormat(value_->audioCodecFormat, audioCodec);
2371     CHECK_AND_RETURN_RET(setState == MSERR_OK, napi_generic_failure);
2372     setRet = CommonNapi::SetPropertyString(env, result, "audioCodec", audioCodec);
2373     CHECK_AND_RETURN_RET(setRet == true, napi_generic_failure);
2374 
2375     setRet = CommonNapi::SetPropertyInt32(env, result, "audioSampleRate", value_->auidoSampleRate);
2376     CHECK_AND_RETURN_RET(setRet == true, napi_generic_failure);
2377 
2378     std::string fileFormat;
2379     setState = MediaJsResultExtensionMethod::SetFileFormat(value_->fileFormat, fileFormat);
2380     CHECK_AND_RETURN_RET(setState == MSERR_OK, napi_generic_failure);
2381     setRet = CommonNapi::SetPropertyString(env, result, "fileFormat", fileFormat);
2382     CHECK_AND_RETURN_RET(setRet == true, napi_generic_failure);
2383 
2384     setRet = CommonNapi::SetPropertyInt32(env, result, "videoBitrate", value_->videoBitrate);
2385     CHECK_AND_RETURN_RET(setRet == true, napi_generic_failure);
2386 
2387     std::string videoCodec;
2388     setState = MediaJsResultExtensionMethod::SetVideoCodecFormat(value_->videoCodecFormat, videoCodec);
2389     CHECK_AND_RETURN_RET(setState == MSERR_OK, napi_generic_failure);
2390     setRet = CommonNapi::SetPropertyString(env, result, "videoCodec", videoCodec);
2391     CHECK_AND_RETURN_RET(setRet == true, napi_generic_failure);
2392 
2393     CHECK_AND_RETURN_RET(setRet == true, napi_generic_failure);
2394     setRet = CommonNapi::SetPropertyInt32(env, result, "videoFrameWidth", value_->videoFrameWidth);
2395     CHECK_AND_RETURN_RET(setRet == true, napi_generic_failure);
2396     setRet = CommonNapi::SetPropertyInt32(env, result, "videoFrameHeight", value_->videoFrameHeight);
2397     CHECK_AND_RETURN_RET(setRet == true, napi_generic_failure);
2398     setRet = CommonNapi::SetPropertyInt32(env, result, "videoFrameRate", value_->videoFrameRate);
2399     CHECK_AND_RETURN_RET(setRet == true, napi_generic_failure);
2400 
2401     return ret;
2402 }
2403 
SetAudioCodecFormat(AudioCodecFormat & codecFormat,std::string & mime)2404 int32_t MediaJsResultExtensionMethod::SetAudioCodecFormat(AudioCodecFormat &codecFormat, std::string &mime)
2405 {
2406     MEDIA_LOGI("audioCodecFormat %{public}d", codecFormat);
2407     const std::map<AudioCodecFormat, std::string_view> codecFormatToMimeStr = {
2408         { AudioCodecFormat::AAC_LC, CodecMimeType::AUDIO_AAC },
2409         { AudioCodecFormat::AUDIO_MPEG, CodecMimeType::AUDIO_MPEG },
2410         { AudioCodecFormat::AUDIO_G711MU, CodecMimeType::AUDIO_G711MU },
2411         { AudioCodecFormat::AUDIO_DEFAULT, "" },
2412     };
2413 
2414     auto iter = codecFormatToMimeStr.find(codecFormat);
2415     if (iter != codecFormatToMimeStr.end()) {
2416         mime = iter->second;
2417         return MSERR_OK;
2418     }
2419     return MSERR_INVALID_VAL;
2420 }
2421 
SetVideoCodecFormat(VideoCodecFormat & codecFormat,std::string & mime)2422 int32_t MediaJsResultExtensionMethod::SetVideoCodecFormat(VideoCodecFormat &codecFormat, std::string &mime)
2423 {
2424     MEDIA_LOGI("VideoCodecFormat %{public}d", codecFormat);
2425     const std::map<VideoCodecFormat, std::string_view> codecFormatTomimeStr = {
2426         { VideoCodecFormat::H264, CodecMimeType::VIDEO_AVC },
2427         { VideoCodecFormat::MPEG4, CodecMimeType::VIDEO_MPEG4 },
2428         { VideoCodecFormat::H265, CodecMimeType::VIDEO_HEVC },
2429         { VideoCodecFormat::VIDEO_DEFAULT, ""},
2430     };
2431 
2432     auto iter = codecFormatTomimeStr.find(codecFormat);
2433     if (iter != codecFormatTomimeStr.end()) {
2434         mime = iter->second;
2435         return MSERR_OK;
2436     }
2437     return MSERR_INVALID_VAL;
2438 }
2439 
SetFileFormat(OutputFormatType & type,std::string & extension)2440 int32_t MediaJsResultExtensionMethod::SetFileFormat(OutputFormatType &type, std::string &extension)
2441 {
2442     MEDIA_LOGI("OutputFormatType %{public}d", type);
2443     const std::map<OutputFormatType, std::string> outputFormatToextension = {
2444         { OutputFormatType::FORMAT_MPEG_4, "mp4" },
2445         { OutputFormatType::FORMAT_M4A, "m4a" },
2446         { OutputFormatType::FORMAT_MP3, "mp3" },
2447         { OutputFormatType::FORMAT_WAV, "wav" },
2448         { OutputFormatType::FORMAT_DEFAULT, "" },
2449     };
2450 
2451     auto iter = outputFormatToextension.find(type);
2452     if (iter != outputFormatToextension.end()) {
2453         extension = iter->second;
2454         return MSERR_OK;
2455     }
2456     return MSERR_INVALID_VAL;
2457 }
2458 
AVRecorderSignError(int32_t errCode,const std::string & operate,const std::string & param,const std::string & add)2459 void AVRecorderAsyncContext::AVRecorderSignError(int32_t errCode, const std::string &operate,
2460     const std::string &param, const std::string &add)
2461 {
2462     RetInfo retInfo = GetRetInfo(errCode, operate, param, add);
2463     SignError(retInfo.first, retInfo.second);
2464 }
2465 
GetJsResult(napi_env env,napi_value & result)2466 napi_status MediaJsAVRecorderConfig::GetJsResult(napi_env env, napi_value &result)
2467 {
2468     napi_status ret = napi_ok;
2469     int32_t setState = MSERR_OK;
2470     CHECK_AND_RETURN_RET(value_ != nullptr, napi_generic_failure);
2471     CHECK_AND_RETURN_RET((ret = napi_create_object(env, &result)) == napi_ok, ret);
2472 
2473     napi_value profile;
2474     napi_value location;
2475     CHECK_AND_RETURN_RET((ret = napi_create_object(env, &profile)) == napi_ok, ret);
2476     CHECK_AND_RETURN_RET((ret = napi_create_object(env, &location)) == napi_ok, ret);
2477     CHECK_AND_RETURN_RET((ret = audioToSet(env, profile, result)) == napi_ok, ret);
2478     CHECK_AND_RETURN_RET((ret = videoToSet(env, profile, result)) == napi_ok, ret);
2479     CHECK_AND_RETURN_RET((ret = locationToSet(env, location, result)) == napi_ok, ret);
2480 
2481     if (value_->withAudio || value_->withVideo) {
2482         bool setRet = true;
2483         setRet = CommonNapi::SetPropertyString(env, result, "url", value_->url);
2484         CHECK_AND_RETURN_RET(setRet == true, napi_generic_failure);
2485 
2486         std::string fileFormat;
2487         setState = MediaJsResultExtensionMethod::SetFileFormat(value_->profile.fileFormat, fileFormat);
2488         CHECK_AND_RETURN_RET(setState == MSERR_OK, napi_generic_failure);
2489         setRet = CommonNapi::SetPropertyString(env, profile, "fileFormat", fileFormat);
2490         CHECK_AND_RETURN_RET(setRet == true, napi_generic_failure);
2491     }
2492     napi_set_named_property(env, result, "profile", profile);
2493     return ret;
2494 }
2495 
audioToSet(napi_env env,napi_value & profile,napi_value & result)2496 napi_status MediaJsAVRecorderConfig::audioToSet(napi_env env, napi_value &profile, napi_value &result)
2497 {
2498     bool setRet = true;
2499     int32_t setState = MSERR_OK;
2500     CHECK_AND_RETURN_RET(value_->withAudio == true, napi_ok);
2501     setRet = CommonNapi::SetPropertyInt32(env, result, "audioSourceType", value_->audioSourceType);
2502     CHECK_AND_RETURN_RET(setRet == true, napi_generic_failure);
2503     setRet = CommonNapi::SetPropertyInt32(env, profile, "audioBitrate", value_->profile.audioBitrate);
2504     CHECK_AND_RETURN_RET(setRet == true, napi_generic_failure);
2505     setRet = CommonNapi::SetPropertyInt32(env, profile, "audioChannels", value_->profile.audioChannels);
2506     CHECK_AND_RETURN_RET(setRet == true, napi_generic_failure);
2507     setRet = CommonNapi::SetPropertyInt32(env, profile, "audioSampleRate", value_->profile.auidoSampleRate);
2508     CHECK_AND_RETURN_RET(setRet == true, napi_generic_failure);
2509 
2510     std::string audioCodec;
2511     setState = MediaJsResultExtensionMethod::SetAudioCodecFormat(value_->profile.audioCodecFormat, audioCodec);
2512     CHECK_AND_RETURN_RET(setState == MSERR_OK, napi_generic_failure);
2513     setRet = CommonNapi::SetPropertyString(env, profile, "audioCodec", audioCodec);
2514     CHECK_AND_RETURN_RET(setRet == true, napi_generic_failure);
2515     return napi_ok;
2516 }
2517 
videoToSet(napi_env env,napi_value & profile,napi_value & result)2518 napi_status MediaJsAVRecorderConfig::videoToSet(napi_env env, napi_value &profile, napi_value &result)
2519 {
2520     bool setRet = true;
2521     int32_t setState = MSERR_OK;
2522     CHECK_AND_RETURN_RET(value_->withVideo == true, napi_ok);
2523     setRet = CommonNapi::SetPropertyInt32(env, result, "videoSourceType", value_->videoSourceType);
2524     CHECK_AND_RETURN_RET(setRet == true, napi_generic_failure);
2525     setRet = CommonNapi::SetPropertyInt32(env, result, "rotation", value_->rotation);
2526     CHECK_AND_RETURN_RET(setRet == true, napi_generic_failure);
2527     setRet = CommonNapi::SetPropertyInt32(env, profile, "videoBitrate", value_->profile.videoBitrate);
2528     CHECK_AND_RETURN_RET(setRet == true, napi_generic_failure);
2529     setRet = CommonNapi::SetPropertyInt32(env, profile, "videoFrameWidth", value_->profile.videoFrameWidth);
2530     CHECK_AND_RETURN_RET(setRet == true, napi_generic_failure);
2531     setRet = CommonNapi::SetPropertyInt32(env, profile, "videoFrameHeight", value_->profile.videoFrameHeight);
2532     CHECK_AND_RETURN_RET(setRet == true, napi_generic_failure);
2533     setRet = CommonNapi::SetPropertyInt32(env, profile, "videoFrameRate", value_->profile.videoFrameRate);
2534     CHECK_AND_RETURN_RET(setRet == true, napi_generic_failure);
2535 
2536     std::string videoCodec;
2537     setState = MediaJsResultExtensionMethod::SetVideoCodecFormat(value_->profile.videoCodecFormat, videoCodec);
2538     CHECK_AND_RETURN_RET(setState == MSERR_OK, napi_generic_failure);
2539     setRet = CommonNapi::SetPropertyString(env, profile, "videoCodec", videoCodec);
2540     CHECK_AND_RETURN_RET(setRet == true, napi_generic_failure);
2541     return napi_ok;
2542 }
2543 
locationToSet(napi_env env,napi_value & location,napi_value & result)2544 napi_status MediaJsAVRecorderConfig::locationToSet(napi_env env, napi_value &location, napi_value &result)
2545 {
2546     bool setRet = true;
2547     setRet = CommonNapi::SetPropertyDouble(env, location, "latitude", value_->location.latitude);
2548     CHECK_AND_RETURN_RET(setRet == true, napi_generic_failure);
2549     setRet = CommonNapi::SetPropertyDouble(env, location, "longitude", value_->location.longitude);
2550     CHECK_AND_RETURN_RET(setRet == true, napi_generic_failure);
2551     napi_set_named_property(env, result, "location", location);
2552     return napi_ok;
2553 }
2554 
GetJsResult(napi_env env,napi_value & result)2555 napi_status MediaJsEncoderInfo::GetJsResult(napi_env env, napi_value &result)
2556 {
2557     napi_status ret = napi_ok;
2558 
2559     size_t size = encoderInfo_.size();
2560     napi_create_array_with_length(env, size, &result);
2561 
2562     CHECK_AND_RETURN_RET((ret = napi_create_array(env, &result)) == napi_ok, ret);
2563 
2564     napi_value audioEncoder;
2565     napi_value vidoeEncoder;
2566     napi_value encoderInfoArray;
2567     CHECK_AND_RETURN_RET((ret = napi_create_object(env, &audioEncoder)) == napi_ok, ret);
2568     CHECK_AND_RETURN_RET((ret = napi_create_object(env, &vidoeEncoder)) == napi_ok, ret);
2569     CHECK_AND_RETURN_RET((ret = napi_create_array(env, &encoderInfoArray)) == napi_ok, ret);
2570 
2571     for (uint32_t i = 0; i < encoderInfo_.size(); i++) {
2572         if (encoderInfo_[i].type == "audio") {
2573             ret = GetAudioEncoderInfo(env, encoderInfo_[i], result, i);
2574             CHECK_AND_RETURN_RET(ret == napi_ok, ret);
2575         } else {
2576             ret = GetVideoEncoderInfo(env, encoderInfo_[i], result, i);
2577             CHECK_AND_RETURN_RET(ret == napi_ok, ret);
2578         }
2579     }
2580     return napi_ok;
2581 }
2582 
GetAudioEncoderInfo(napi_env env,EncoderCapabilityData encoderCapData,napi_value & result,uint32_t position)2583 napi_status MediaJsEncoderInfo::GetAudioEncoderInfo(
2584     napi_env env, EncoderCapabilityData encoderCapData, napi_value &result, uint32_t position)
2585 {
2586     bool setRet = true;
2587     napi_value encoderInfo;
2588     napi_status ret;
2589     CHECK_AND_RETURN_RET((ret = napi_create_object(env, &encoderInfo)) == napi_ok, ret);
2590 
2591     setRet = CommonNapi::SetPropertyString(env, encoderInfo, "mimeType", encoderCapData.mimeType);
2592     CHECK_AND_RETURN_RET(setRet == true, napi_generic_failure);
2593 
2594     setRet = CommonNapi::SetPropertyString(env, encoderInfo, "type", encoderCapData.type);
2595     CHECK_AND_RETURN_RET(setRet == true, napi_generic_failure);
2596 
2597     setRet = CommonNapi::AddRangeProperty(env, encoderInfo, "bitRate",
2598         encoderCapData.bitrate.minVal, encoderCapData.bitrate.maxVal);
2599     CHECK_AND_RETURN_RET(setRet == true, napi_generic_failure);
2600 
2601     setRet = CommonNapi::AddRangeProperty(env, encoderInfo, "channels",
2602         encoderCapData.channels.minVal, encoderCapData.channels.maxVal);
2603     CHECK_AND_RETURN_RET(setRet == true, napi_generic_failure);
2604 
2605     setRet = CommonNapi::AddArrayProperty(env, encoderInfo, "sampleRate", encoderCapData.sampleRate);
2606     CHECK_AND_RETURN_RET(setRet == true, napi_generic_failure);
2607 
2608     napi_status status = napi_set_element(env, result, position, encoderInfo);
2609     CHECK_AND_RETURN_RET(status == napi_ok, napi_generic_failure);
2610     return napi_ok;
2611 }
2612 
GetVideoEncoderInfo(napi_env env,EncoderCapabilityData encoderCapData,napi_value & result,uint32_t position)2613 napi_status MediaJsEncoderInfo::GetVideoEncoderInfo(
2614     napi_env env, EncoderCapabilityData encoderCapData, napi_value &result, uint32_t position)
2615 {
2616     bool setRet = true;
2617     napi_value encoderInfo;
2618     napi_status ret;
2619     CHECK_AND_RETURN_RET((ret = napi_create_object(env, &encoderInfo)) == napi_ok, ret);
2620 
2621     setRet = CommonNapi::SetPropertyString(env, encoderInfo, "mimeType", encoderCapData.mimeType);
2622     CHECK_AND_RETURN_RET(setRet == true, napi_generic_failure);
2623 
2624     setRet = CommonNapi::SetPropertyString(env, encoderInfo, "type", encoderCapData.type);
2625     CHECK_AND_RETURN_RET(setRet == true, napi_generic_failure);
2626 
2627     setRet = CommonNapi::AddRangeProperty(env, encoderInfo, "bitRate",
2628         encoderCapData.bitrate.minVal, encoderCapData.bitrate.maxVal);
2629     CHECK_AND_RETURN_RET(setRet == true, napi_generic_failure);
2630 
2631     setRet = CommonNapi::AddRangeProperty(env, encoderInfo, "frameRate",
2632         encoderCapData.frameRate.minVal, encoderCapData.frameRate.maxVal);
2633     CHECK_AND_RETURN_RET(setRet == true, napi_generic_failure);
2634 
2635     setRet = CommonNapi::AddRangeProperty(env, encoderInfo, "width",
2636         encoderCapData.width.minVal, encoderCapData.width.maxVal);
2637     CHECK_AND_RETURN_RET(setRet == true, napi_generic_failure);
2638 
2639     setRet = CommonNapi::AddRangeProperty(env, encoderInfo, "height",
2640         encoderCapData.height.minVal, encoderCapData.height.maxVal);
2641     CHECK_AND_RETURN_RET(setRet == true, napi_generic_failure);
2642 
2643     napi_status status = napi_set_element(env, result, position, encoderInfo);
2644     CHECK_AND_RETURN_RET(status == napi_ok, napi_generic_failure);
2645     return napi_ok;
2646 }
2647 } // namespace Media
2648 } // namespace OHOS