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