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