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