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