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