1 /*
2 * Copyright (C) 2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include <climits>
17 #include "avrecorder_callback.h"
18 #include "media_dfx.h"
19 #include "media_log.h"
20 #include "media_errors.h"
21 #include "scope_guard.h"
22 #include "common_napi.h"
23 #include "surface_utils.h"
24 #include "string_ex.h"
25 #include "avcodec_info.h"
26 #include "av_common.h"
27 #ifdef SUPPORT_JSSTACK
28 #include "xpower_event_js.h"
29 #endif
30 #include "avrecorder_napi.h"
31
32 namespace {
33 constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, LOG_DOMAIN, "AVRecorderNapi"};
34 }
35
36 namespace OHOS {
37 namespace Media {
38 thread_local napi_ref AVRecorderNapi::constructor_ = nullptr;
39 const std::string CLASS_NAME = "AVRecorder";
40 std::map<std::string, AVRecorderNapi::AvRecorderTaskqFunc> AVRecorderNapi::taskQFuncs_ = {
41 {AVRecordergOpt::GETINPUTSURFACE, &AVRecorderNapi::GetInputSurface},
42 {AVRecordergOpt::START, &AVRecorderNapi::Start},
43 {AVRecordergOpt::PAUSE, &AVRecorderNapi::Pause},
44 {AVRecordergOpt::RESUME, &AVRecorderNapi::Resume},
45 {AVRecordergOpt::STOP, &AVRecorderNapi::Stop},
46 {AVRecordergOpt::RESET, &AVRecorderNapi::Reset},
47 {AVRecordergOpt::RELEASE, &AVRecorderNapi::Release},
48 };
49
AVRecorderNapi()50 AVRecorderNapi::AVRecorderNapi()
51 {
52 MEDIA_LOGI("0x%{public}06" PRIXPTR "Instances create", FAKE_POINTER(this));
53 }
54
~AVRecorderNapi()55 AVRecorderNapi::~AVRecorderNapi()
56 {
57 MEDIA_LOGI("0x%{public}06" PRIXPTR "Instances destroy", FAKE_POINTER(this));
58 }
59
Init(napi_env env,napi_value exports)60 napi_value AVRecorderNapi::Init(napi_env env, napi_value exports)
61 {
62 napi_property_descriptor staticProperty[] = {
63 DECLARE_NAPI_STATIC_FUNCTION("createAVRecorder", JsCreateAVRecorder),
64 };
65
66 napi_property_descriptor properties[] = {
67 DECLARE_NAPI_FUNCTION("prepare", JsPrepare),
68 DECLARE_NAPI_FUNCTION("getInputSurface", JsGetInputSurface),
69 DECLARE_NAPI_FUNCTION("start", JsStart),
70 DECLARE_NAPI_FUNCTION("pause", JsPause),
71 DECLARE_NAPI_FUNCTION("resume", JsResume),
72 DECLARE_NAPI_FUNCTION("stop", JsStop),
73 DECLARE_NAPI_FUNCTION("reset", JsReset),
74 DECLARE_NAPI_FUNCTION("release", JsRelease),
75 DECLARE_NAPI_FUNCTION("on", JsSetEventCallback),
76 DECLARE_NAPI_FUNCTION("off", JsCancelEventCallback),
77 DECLARE_NAPI_FUNCTION("getAVRecorderProfile", JsGetAVRecorderProfile),
78 DECLARE_NAPI_FUNCTION("setAVRecorderConfig", JsSetAVRecorderConfig),
79
80 DECLARE_NAPI_GETTER("state", JsGetState),
81 };
82
83 napi_value constructor = nullptr;
84 napi_status status = napi_define_class(env, CLASS_NAME.c_str(), NAPI_AUTO_LENGTH, Constructor, nullptr,
85 sizeof(properties) / sizeof(properties[0]), properties, &constructor);
86 CHECK_AND_RETURN_RET_LOG(status == napi_ok, nullptr, "Failed to define AVRecorder class");
87
88 status = napi_create_reference(env, constructor, 1, &constructor_);
89 CHECK_AND_RETURN_RET_LOG(status == napi_ok, nullptr, "Failed to create reference of constructor");
90
91 status = napi_set_named_property(env, exports, CLASS_NAME.c_str(), constructor);
92 CHECK_AND_RETURN_RET_LOG(status == napi_ok, nullptr, "Failed to set constructor");
93
94 status = napi_define_properties(env, exports, sizeof(staticProperty) / sizeof(staticProperty[0]), staticProperty);
95 CHECK_AND_RETURN_RET_LOG(status == napi_ok, nullptr, "Failed to define static function");
96
97 MEDIA_LOGI("Init success");
98 return exports;
99 }
100
Constructor(napi_env env,napi_callback_info info)101 napi_value AVRecorderNapi::Constructor(napi_env env, napi_callback_info info)
102 {
103 MediaTrace trace("AVRecorder::Constructor");
104 napi_value result = nullptr;
105 napi_get_undefined(env, &result);
106
107 size_t argCount = 0;
108 napi_value jsThis = nullptr;
109 napi_status status = napi_get_cb_info(env, info, &argCount, nullptr, &jsThis, nullptr);
110 CHECK_AND_RETURN_RET_LOG(status == napi_ok, result, "failed to napi_get_cb_info");
111
112 AVRecorderNapi *jsRecorder = new(std::nothrow) AVRecorderNapi();
113 CHECK_AND_RETURN_RET_LOG(jsRecorder != nullptr, result, "failed to new AVRecorderNapi");
114
115 jsRecorder->env_ = env;
116 jsRecorder->recorder_ = RecorderFactory::CreateRecorder();
117 CHECK_AND_RETURN_RET_LOG(jsRecorder->recorder_ != nullptr, result, "failed to CreateRecorder");
118
119 jsRecorder->taskQue_ = std::make_unique<TaskQueue>("AVRecorderNapi");
120 (void)jsRecorder->taskQue_->Start();
121
122 jsRecorder->recorderCb_ = std::make_shared<AVRecorderCallback>(env);
123 CHECK_AND_RETURN_RET_LOG(jsRecorder->recorderCb_ != nullptr, result, "failed to CreateRecorderCb");
124 (void)jsRecorder->recorder_->SetRecorderCallback(jsRecorder->recorderCb_);
125
126 status = napi_wrap(env, jsThis, reinterpret_cast<void *>(jsRecorder),
127 AVRecorderNapi::Destructor, nullptr, nullptr);
128 if (status != napi_ok) {
129 delete jsRecorder;
130 MEDIA_LOGE("Failed to wrap native instance");
131 return result;
132 }
133
134 MEDIA_LOGI("Constructor success");
135 return jsThis;
136 }
137
Destructor(napi_env env,void * nativeObject,void * finalize)138 void AVRecorderNapi::Destructor(napi_env env, void *nativeObject, void *finalize)
139 {
140 MediaTrace trace("AVRecorder::Destructor");
141 (void)finalize;
142 if (nativeObject != nullptr) {
143 AVRecorderNapi *napi = reinterpret_cast<AVRecorderNapi *>(nativeObject);
144 if (napi->taskQue_ != nullptr) {
145 (void)napi->taskQue_->Stop();
146 }
147
148 napi->RemoveSurface();
149 napi->recorderCb_ = nullptr;
150
151 if (napi->recorder_) {
152 napi->recorder_->Release();
153 napi->recorder_ = nullptr;
154 }
155
156 delete napi;
157 }
158 MEDIA_LOGI("Destructor success");
159 }
160
JsCreateAVRecorder(napi_env env,napi_callback_info info)161 napi_value AVRecorderNapi::JsCreateAVRecorder(napi_env env, napi_callback_info info)
162 {
163 MediaTrace trace("AVRecorder::JsCreateAVRecorder");
164 napi_value result = nullptr;
165 napi_get_undefined(env, &result);
166
167 // get args
168 napi_value jsThis = nullptr;
169 napi_value args[1] = { nullptr };
170 size_t argCount = 1;
171 napi_status status = napi_get_cb_info(env, info, &argCount, args, &jsThis, nullptr);
172 CHECK_AND_RETURN_RET_LOG(status == napi_ok, result, "failed to napi_get_cb_info");
173
174 std::unique_ptr<AVRecorderAsyncContext> asyncCtx = std::make_unique<AVRecorderAsyncContext>(env);
175 CHECK_AND_RETURN_RET_LOG(asyncCtx != nullptr, result, "failed to get AsyncContext");
176
177 asyncCtx->callbackRef = CommonNapi::CreateReference(env, args[0]);
178 asyncCtx->deferred = CommonNapi::CreatePromise(env, asyncCtx->callbackRef, result);
179 asyncCtx->JsResult = std::make_unique<MediaJsResultInstance>(constructor_);
180 asyncCtx->ctorFlag = true;
181
182 napi_value resource = nullptr;
183 napi_create_string_utf8(env, "JsCreateAVRecorder", NAPI_AUTO_LENGTH, &resource);
184 NAPI_CALL(env, napi_create_async_work(env, nullptr, resource, [](napi_env env, void* data) {},
185 MediaAsyncContext::CompleteCallback, static_cast<void *>(asyncCtx.get()), &asyncCtx->work));
186 NAPI_CALL(env, napi_queue_async_work(env, asyncCtx->work));
187 asyncCtx.release();
188
189 MEDIA_LOGI("JsCreateAVRecorder success");
190 return result;
191 }
192
GetRetInfo(int32_t errCode,const std::string & operate,const std::string & param,const std::string & add="")193 RetInfo GetRetInfo(int32_t errCode, const std::string &operate, const std::string ¶m, const std::string &add = "")
194 {
195 MEDIA_LOGE("failed to %{public}s, param %{public}s, errCode = %{public}d", operate.c_str(), param.c_str(), errCode);
196 MediaServiceExtErrCodeAPI9 err = MSErrorToExtErrorAPI9(static_cast<MediaServiceErrCode>(errCode));
197 if (errCode == MSERR_UNSUPPORT_VID_PARAMS) {
198 return RetInfo(err, "The video parameter is not supported. Please check the type and range.");
199 }
200
201 if (errCode == MSERR_UNSUPPORT_AUD_PARAMS) {
202 return RetInfo(err, "The audio parameter is not supported. Please check the type and range.");
203 }
204
205 std::string message;
206 if (err == MSERR_EXT_API9_INVALID_PARAMETER) {
207 message = MSExtErrorAPI9ToString(err, param, "") + add;
208 } else {
209 message = MSExtErrorAPI9ToString(err, operate, "") + add;
210 }
211
212 MEDIA_LOGE("errCode: %{public}d, errMsg: %{public}s", err, message.c_str());
213 return RetInfo(err, message);
214 }
215
JsPrepare(napi_env env,napi_callback_info info)216 napi_value AVRecorderNapi::JsPrepare(napi_env env, napi_callback_info info)
217 {
218 MediaTrace trace("AVRecorder::JsPrepare");
219 const std::string &opt = AVRecordergOpt::PREPARE;
220 MEDIA_LOGI("Js %{public}s Start", opt.c_str());
221
222 const int32_t maxParam = 2; // config + callbackRef
223 size_t argCount = maxParam;
224 napi_value args[maxParam] = { nullptr };
225
226 napi_value result = nullptr;
227 napi_get_undefined(env, &result);
228
229 auto asyncCtx = std::make_unique<AVRecorderAsyncContext>(env);
230 CHECK_AND_RETURN_RET_LOG(asyncCtx != nullptr, result, "failed to get AsyncContext");
231 asyncCtx->napi = AVRecorderNapi::GetJsInstanceAndArgs(env, info, argCount, args);
232 CHECK_AND_RETURN_RET_LOG(asyncCtx->napi != nullptr, result, "failed to GetJsInstanceAndArgs");
233 CHECK_AND_RETURN_RET_LOG(asyncCtx->napi->taskQue_ != nullptr, result, "taskQue is nullptr!");
234
235 asyncCtx->callbackRef = CommonNapi::CreateReference(env, args[1]);
236 asyncCtx->deferred = CommonNapi::CreatePromise(env, asyncCtx->callbackRef, result);
237
238 if (asyncCtx->napi->CheckStateMachine(opt) == MSERR_OK) {
239 if (asyncCtx->napi->GetConfig(asyncCtx, env, args[0]) == MSERR_OK) {
240 asyncCtx->task_ = AVRecorderNapi::GetPrepareTask(asyncCtx);
241 (void)asyncCtx->napi->taskQue_->EnqueueTask(asyncCtx->task_);
242 }
243 } else {
244 asyncCtx->AVRecorderSignError(MSERR_INVALID_OPERATION, opt, "");
245 }
246
247 napi_value resource = nullptr;
248 napi_create_string_utf8(env, opt.c_str(), NAPI_AUTO_LENGTH, &resource);
249 NAPI_CALL(env, napi_create_async_work(env, nullptr, resource, [](napi_env env, void* data) {
250 AVRecorderAsyncContext* asyncCtx = reinterpret_cast<AVRecorderAsyncContext *>(data);
251 CHECK_AND_RETURN_LOG(asyncCtx != nullptr, "asyncCtx is nullptr!");
252
253 if (asyncCtx->task_) {
254 auto result = asyncCtx->task_->GetResult();
255 if (result.Value().first != MSERR_EXT_API9_OK) {
256 asyncCtx->SignError(result.Value().first, result.Value().second);
257 }
258 }
259 MEDIA_LOGI("The js thread of prepare finishes execution and returns");
260 }, MediaAsyncContext::CompleteCallback, static_cast<void *>(asyncCtx.get()), &asyncCtx->work));
261 NAPI_CALL(env, napi_queue_async_work(env, asyncCtx->work));
262 asyncCtx.release();
263
264 MEDIA_LOGI("Js %{public}s End", opt.c_str());
265 return result;
266 }
267
GetPrepareTask(std::unique_ptr<AVRecorderAsyncContext> & asyncCtx)268 std::shared_ptr<TaskHandler<RetInfo>> AVRecorderNapi::GetPrepareTask(std::unique_ptr<AVRecorderAsyncContext> &asyncCtx)
269 {
270 return std::make_shared<TaskHandler<RetInfo>>([napi = asyncCtx->napi, config = asyncCtx->config_]() {
271 const std::string &option = AVRecordergOpt::PREPARE;
272 MEDIA_LOGI("%{public}s Start", option.c_str());
273 CHECK_AND_RETURN_RET(napi != nullptr && napi->recorder_ != nullptr && config != nullptr,
274 GetRetInfo(MSERR_INVALID_OPERATION, option, ""));
275
276 CHECK_AND_RETURN_RET(napi->CheckStateMachine(option) == MSERR_OK,
277 GetRetInfo(MSERR_INVALID_OPERATION, option, ""));
278
279 RetInfo retinfo = napi->Configure(config);
280 CHECK_AND_RETURN_RET(retinfo.first == MSERR_OK, ((void)napi->recorder_->Reset(), retinfo));
281
282 int32_t ret = napi->recorder_->Prepare();
283 CHECK_AND_RETURN_RET(ret == MSERR_OK, ((void)napi->recorder_->Reset(), GetRetInfo(ret, "Prepare", "")));
284
285 napi->RemoveSurface();
286 napi->StateCallback(AVRecorderState::STATE_PREPARED);
287 napi->getVideoInputSurface_ = false;
288 napi->withVideo_ = config->withVideo;
289 MEDIA_LOGI("%{public}s End", option.c_str());
290 return RetInfo(MSERR_EXT_API9_OK, "");
291 });
292 }
293
JsGetInputSurface(napi_env env,napi_callback_info info)294 napi_value AVRecorderNapi::JsGetInputSurface(napi_env env, napi_callback_info info)
295 {
296 MediaTrace trace("AVRecorder::JsGetInputSurface");
297 return ExecuteByPromise(env, info, AVRecordergOpt::GETINPUTSURFACE);
298 }
299
JsStart(napi_env env,napi_callback_info info)300 napi_value AVRecorderNapi::JsStart(napi_env env, napi_callback_info info)
301 {
302 MediaTrace trace("AVRecorder::JsStart");
303 #ifdef SUPPORT_JSSTACK
304 HiviewDFX::ReportXPowerJsStackSysEvent(env, "STREAM_CHANGE", "SRC=Media");
305 #endif
306 return ExecuteByPromise(env, info, AVRecordergOpt::START);
307 }
308
JsPause(napi_env env,napi_callback_info info)309 napi_value AVRecorderNapi::JsPause(napi_env env, napi_callback_info info)
310 {
311 MediaTrace trace("AVRecorder::JsPause");
312 return ExecuteByPromise(env, info, AVRecordergOpt::PAUSE);
313 }
314
JsResume(napi_env env,napi_callback_info info)315 napi_value AVRecorderNapi::JsResume(napi_env env, napi_callback_info info)
316 {
317 MediaTrace trace("AVRecorder::JsResume");
318 #ifdef SUPPORT_JSSTACK
319 HiviewDFX::ReportXPowerJsStackSysEvent(env, "STREAM_CHANGE", "SRC=Media");
320 #endif
321 return ExecuteByPromise(env, info, AVRecordergOpt::RESUME);
322 }
323
JsStop(napi_env env,napi_callback_info info)324 napi_value AVRecorderNapi::JsStop(napi_env env, napi_callback_info info)
325 {
326 MediaTrace trace("AVRecorder::JsStop");
327 return ExecuteByPromise(env, info, AVRecordergOpt::STOP);
328 }
329
JsReset(napi_env env,napi_callback_info info)330 napi_value AVRecorderNapi::JsReset(napi_env env, napi_callback_info info)
331 {
332 MediaTrace trace("AVRecorder::JsReset");
333 return ExecuteByPromise(env, info, AVRecordergOpt::RESET);
334 }
335
JsRelease(napi_env env,napi_callback_info info)336 napi_value AVRecorderNapi::JsRelease(napi_env env, napi_callback_info info)
337 {
338 MediaTrace trace("AVRecorder::JsRelease");
339 return ExecuteByPromise(env, info, AVRecordergOpt::RELEASE);
340 }
341
JsGetAVRecorderProfile(napi_env env,napi_callback_info info)342 napi_value AVRecorderNapi::JsGetAVRecorderProfile(napi_env env, napi_callback_info info)
343 {
344 MediaTrace trace("AVRecorder::JsGetAVRecorderProfile");
345 MEDIA_LOGI("AVRecorder::JsGetAVRecorderProfile");
346 const std::string &opt = AVRecordergOpt::GET_AV_RECORDER_PROFILE;
347 MEDIA_LOGI("Js %{public}s Start", opt.c_str());
348
349 const int32_t maxParam = 3; // config + callbackRef
350 const int32_t callbackParam = 2; // callback
351 size_t argCount = maxParam;
352 napi_value args[maxParam] = { nullptr };
353 napi_value result = nullptr;
354 napi_get_undefined(env, &result);
355
356 auto asyncCtx = std::make_unique<AVRecorderAsyncContext>(env);
357 CHECK_AND_RETURN_RET_LOG(asyncCtx != nullptr, result, "failed to get AsyncContext");
358 asyncCtx->napi = AVRecorderNapi::GetJsInstanceAndArgs(env, info, argCount, args);
359 CHECK_AND_RETURN_RET_LOG(asyncCtx->napi != nullptr, result, "failed to GetJsInstanceAndArgs");
360 CHECK_AND_RETURN_RET_LOG(asyncCtx->napi->taskQue_ != nullptr, result, "taskQue is nullptr!");
361
362 asyncCtx->callbackRef = CommonNapi::CreateReference(env, args[callbackParam]);
363 asyncCtx->deferred = CommonNapi::CreatePromise(env, asyncCtx->callbackRef, result);
364
365 if (asyncCtx->napi->GetSourceIdAndQuality(asyncCtx, env, args[0], args[1], opt) == MSERR_OK) {
366 asyncCtx->task_ = AVRecorderNapi::GetAVRecorderProfileTask(asyncCtx);
367 (void)asyncCtx->napi->taskQue_->EnqueueTask(asyncCtx->task_);
368 }
369
370 napi_value resource = nullptr;
371 napi_create_string_utf8(env, opt.c_str(), NAPI_AUTO_LENGTH, &resource);
372 NAPI_CALL(env, napi_create_async_work(env, nullptr, resource, [](napi_env env, void* data) {
373 AVRecorderAsyncContext* asyncCtx = reinterpret_cast<AVRecorderAsyncContext *>(data);
374 CHECK_AND_RETURN_LOG(asyncCtx != nullptr, "asyncCtx is nullptr!");
375 if (asyncCtx->task_) {
376 auto result = asyncCtx->task_->GetResult();
377 if (result.Value().first != MSERR_EXT_API9_OK) {
378 asyncCtx->SignError(result.Value().first, result.Value().second);
379 } else {
380 asyncCtx->JsResult = std::make_unique<MediaJsAVRecorderProfile>(asyncCtx->profile_);
381 }
382 }
383 MEDIA_LOGI("The js thread of prepare finishes execution and returns");
384 }, MediaAsyncContext::CompleteCallback, static_cast<void *>(asyncCtx.get()), &asyncCtx->work));
385 NAPI_CALL(env, napi_queue_async_work(env, asyncCtx->work));
386 asyncCtx.release();
387
388 MEDIA_LOGI("Js %{public}s End", opt.c_str());
389 return result;
390 }
391
GetAVRecorderProfileTask(const std::unique_ptr<AVRecorderAsyncContext> & asyncCtx)392 std::shared_ptr<TaskHandler<RetInfo>> AVRecorderNapi::GetAVRecorderProfileTask(
393 const std::unique_ptr<AVRecorderAsyncContext> &asyncCtx)
394 {
395 return std::make_shared<TaskHandler<RetInfo>>([napi = asyncCtx->napi, &profile = asyncCtx->profile_]() {
396 const std::string &option = AVRecordergOpt::GET_AV_RECORDER_PROFILE;
397 MEDIA_LOGI("%{public}s Start", option.c_str());
398 profile = std::make_shared<AVRecorderProfile>();
399
400 CHECK_AND_RETURN_RET(napi != nullptr && profile != nullptr,
401 GetRetInfo(MSERR_INVALID_OPERATION, option, ""));
402
403 CHECK_AND_RETURN_RET(napi->CheckStateMachine(option) == MSERR_OK,
404 GetRetInfo(MSERR_INVALID_OPERATION, option, ""));
405
406 CHECK_AND_RETURN_RET_LOG(napi->sourceId_ >= 0 && ((napi->qualityLevel_ >= RECORDER_QUALITY_LOW &&
407 napi->qualityLevel_ <= RECORDER_QUALITY_2160P) ||
408 (napi->qualityLevel_ >= RECORDER_QUALITY_TIME_LAPSE_LOW &&
409 napi->qualityLevel_ <= RECORDER_QUALITY_TIME_LAPSE_2160P) ||
410 (napi->qualityLevel_ >= RECORDER_QUALITY_HIGH_SPEED_LOW &&
411 napi->qualityLevel_ <= RECORDER_QUALITY_HIGH_SPEED_1080P)),
412 GetRetInfo(MSERR_INVALID_VAL, "GetAVRecorderProfileTask", ""), "sourceId or qualityLevel is null");
413
414 int32_t ret = AVRecorderNapi::GetAVRecorderProfile(profile, napi->sourceId_, napi->qualityLevel_);
415 CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, GetRetInfo(MSERR_INVALID_VAL, "GetAVRecorderProfileTask", ""),
416 "get AVRecorderProfile failed");
417
418 MEDIA_LOGI("%{public}s End", option.c_str());
419 return RetInfo(MSERR_EXT_API9_OK, "");
420 });
421 }
422
SetAVRecorderConfigTask(std::unique_ptr<AVRecorderAsyncContext> & asyncCtx)423 std::shared_ptr<TaskHandler<RetInfo>> AVRecorderNapi::SetAVRecorderConfigTask(
424 std::unique_ptr<AVRecorderAsyncContext> &asyncCtx)
425 {
426 return std::make_shared<TaskHandler<RetInfo>>([napi = asyncCtx->napi, config = asyncCtx->config_]() {
427 const std::string &option = AVRecordergOpt::SET_AV_RECORDER_CONFIG;
428 MEDIA_LOGI("%{public}s Start", option.c_str());
429 CHECK_AND_RETURN_RET(napi != nullptr && napi->recorder_ != nullptr && config != nullptr,
430 GetRetInfo(MSERR_INVALID_OPERATION, option, ""));
431
432 CHECK_AND_RETURN_RET(napi->CheckStateMachine(option) == MSERR_OK,
433 GetRetInfo(MSERR_INVALID_OPERATION, option, ""));
434
435 RetInfo retinfo = napi->Configure(config);
436 CHECK_AND_RETURN_RET(retinfo.first == MSERR_OK, ((void)napi->recorder_->Reset(), retinfo));
437
438 napi->withVideo_ = config->withVideo;
439 MEDIA_LOGI("%{public}s End", option.c_str());
440 return RetInfo(MSERR_EXT_API9_OK, "");
441 });
442 }
443
JsSetAVRecorderConfig(napi_env env,napi_callback_info info)444 napi_value AVRecorderNapi::JsSetAVRecorderConfig(napi_env env, napi_callback_info info)
445 {
446 MediaTrace trace("AVRecorder::JsSetAVRecorderConfig");
447 const std::string &opt = AVRecordergOpt::SET_AV_RECORDER_CONFIG;
448 MEDIA_LOGI("Js %{public}s Start", opt.c_str());
449
450 const int32_t maxParam = 2; // config + callbackRef
451 size_t argCount = maxParam;
452 napi_value args[maxParam] = { nullptr };
453 napi_value result = nullptr;
454 napi_get_undefined(env, &result);
455
456 auto asyncCtx = std::make_unique<AVRecorderAsyncContext>(env);
457 CHECK_AND_RETURN_RET_LOG(asyncCtx != nullptr, result, "failed to get AsyncContext");
458 asyncCtx->napi = AVRecorderNapi::GetJsInstanceAndArgs(env, info, argCount, args);
459 CHECK_AND_RETURN_RET_LOG(asyncCtx->napi != nullptr, result, "failed to GetJsInstanceAndArgs");
460 CHECK_AND_RETURN_RET_LOG(asyncCtx->napi->taskQue_ != nullptr, result, "taskQue is nullptr!");
461
462 asyncCtx->callbackRef = CommonNapi::CreateReference(env, args[1]);
463 asyncCtx->deferred = CommonNapi::CreatePromise(env, asyncCtx->callbackRef, result);
464
465 if (asyncCtx->napi->CheckStateMachine(opt) == MSERR_OK) {
466 if (asyncCtx->napi->GetConfig(asyncCtx, env, args[0]) == MSERR_OK) {
467 asyncCtx->task_ = AVRecorderNapi::SetAVRecorderConfigTask(asyncCtx);
468 (void)asyncCtx->napi->taskQue_->EnqueueTask(asyncCtx->task_);
469 }
470 } else {
471 asyncCtx->AVRecorderSignError(MSERR_INVALID_OPERATION, opt, "");
472 }
473
474 napi_value resource = nullptr;
475 napi_create_string_utf8(env, opt.c_str(), NAPI_AUTO_LENGTH, &resource);
476 NAPI_CALL(env, napi_create_async_work(env, nullptr, resource, [](napi_env env, void* data) {
477 AVRecorderAsyncContext* asyncCtx = reinterpret_cast<AVRecorderAsyncContext *>(data);
478 CHECK_AND_RETURN_LOG(asyncCtx != nullptr, "asyncCtx is nullptr!");
479 if (asyncCtx->task_) {
480 auto result = asyncCtx->task_->GetResult();
481 if (result.Value().first != MSERR_EXT_API9_OK) {
482 asyncCtx->SignError(result.Value().first, result.Value().second);
483 }
484 }
485 MEDIA_LOGI("The js thread of prepare finishes execution and returns");
486 }, MediaAsyncContext::CompleteCallback, static_cast<void *>(asyncCtx.get()), &asyncCtx->work));
487 NAPI_CALL(env, napi_queue_async_work(env, asyncCtx->work));
488 asyncCtx.release();
489
490 MEDIA_LOGI("Js %{public}s End", opt.c_str());
491 return result;
492 }
493
JsSetEventCallback(napi_env env,napi_callback_info info)494 napi_value AVRecorderNapi::JsSetEventCallback(napi_env env, napi_callback_info info)
495 {
496 MediaTrace trace("AVRecorder::JsSetEventCallback");
497 MEDIA_LOGI("JsSetEventCallback Start");
498 napi_value result = nullptr;
499 napi_get_undefined(env, &result);
500
501 size_t argCount = 2;
502 napi_value args[2] = { nullptr, nullptr };
503 AVRecorderNapi *recorderNapi = AVRecorderNapi::GetJsInstanceAndArgs(env, info, argCount, args);
504 CHECK_AND_RETURN_RET_LOG(recorderNapi != nullptr, result, "Failed to retrieve instance");
505
506 napi_valuetype valueType0 = napi_undefined;
507 napi_valuetype valueType1 = napi_undefined;
508 if (napi_typeof(env, args[0], &valueType0) != napi_ok || valueType0 != napi_string ||
509 napi_typeof(env, args[1], &valueType1) != napi_ok || valueType1 != napi_function) {
510 recorderNapi->ErrorCallback(MSERR_INVALID_VAL, "SetEventCallback");
511 return result;
512 }
513
514 std::string callbackName = CommonNapi::GetStringArgument(env, args[0]);
515 if (callbackName != AVRecorderEvent::EVENT_ERROR && callbackName != AVRecorderEvent::EVENT_STATE_CHANGE) {
516 recorderNapi->ErrorCallback(MSERR_INVALID_VAL, "SetEventCallback");
517 return result;
518 }
519
520 napi_ref ref = nullptr;
521 napi_status status = napi_create_reference(env, args[1], 1, &ref);
522 CHECK_AND_RETURN_RET_LOG(status == napi_ok && ref != nullptr, result, "failed to create reference!");
523
524 std::shared_ptr<AutoRef> autoRef = std::make_shared<AutoRef>(env, ref);
525 recorderNapi->SetCallbackReference(callbackName, autoRef);
526
527 MEDIA_LOGI("JsSetEventCallback End");
528 return result;
529 }
530
JsCancelEventCallback(napi_env env,napi_callback_info info)531 napi_value AVRecorderNapi::JsCancelEventCallback(napi_env env, napi_callback_info info)
532 {
533 MediaTrace trace("AVRecorder::JsCancelEventCallback");
534 MEDIA_LOGI("JsCancelEventCallback Start");
535 napi_value result = nullptr;
536 napi_get_undefined(env, &result);
537
538 size_t argCount = 1;
539 napi_value args[1] = { nullptr };
540 AVRecorderNapi *recorderNapi = AVRecorderNapi::GetJsInstanceAndArgs(env, info, argCount, args);
541 CHECK_AND_RETURN_RET_LOG(recorderNapi != nullptr, result, "Failed to retrieve instance");
542
543 napi_valuetype valueType0 = napi_undefined;
544 if (napi_typeof(env, args[0], &valueType0) != napi_ok || valueType0 != napi_string) {
545 recorderNapi->ErrorCallback(MSERR_INVALID_VAL, "CancelEventCallback");
546 return result;
547 }
548
549 std::string callbackName = CommonNapi::GetStringArgument(env, args[0]);
550 if (callbackName != AVRecorderEvent::EVENT_ERROR && callbackName != AVRecorderEvent::EVENT_STATE_CHANGE) {
551 recorderNapi->ErrorCallback(MSERR_INVALID_VAL, "CancelEventCallback");
552 return result;
553 }
554
555 recorderNapi->CancelCallbackReference(callbackName);
556
557 MEDIA_LOGI("JsCancelEventCallback End");
558 return result;
559 }
560
JsGetState(napi_env env,napi_callback_info info)561 napi_value AVRecorderNapi::JsGetState(napi_env env, napi_callback_info info)
562 {
563 MediaTrace trace("AVRecorder::JsGetState");
564 napi_value result = nullptr;
565 napi_get_undefined(env, &result);
566
567 size_t argCount = 0;
568 AVRecorderNapi *recorderNapi = AVRecorderNapi::GetJsInstanceAndArgs(env, info, argCount, nullptr);
569 CHECK_AND_RETURN_RET_LOG(recorderNapi != nullptr, result, "failed to GetJsInstance");
570
571 auto napiCb = std::static_pointer_cast<AVRecorderCallback>(recorderNapi->recorderCb_);
572 CHECK_AND_RETURN_RET_LOG(napiCb != nullptr, result, "napiCb is nullptr!");
573 std::string curState = napiCb->GetState();
574 MEDIA_LOGI("GetState success, State: %{public}s", curState.c_str());
575
576 napi_value jsResult = nullptr;
577 napi_status status = napi_create_string_utf8(env, curState.c_str(), NAPI_AUTO_LENGTH, &jsResult);
578 CHECK_AND_RETURN_RET_LOG(status == napi_ok, result, "napi_create_string_utf8 error");
579 return jsResult;
580 }
581
GetJsInstanceAndArgs(napi_env env,napi_callback_info info,size_t & argCount,napi_value * args)582 AVRecorderNapi* AVRecorderNapi::GetJsInstanceAndArgs(napi_env env, napi_callback_info info,
583 size_t &argCount, napi_value *args)
584 {
585 napi_value jsThis = nullptr;
586 napi_status status = napi_get_cb_info(env, info, &argCount, args, &jsThis, nullptr);
587 CHECK_AND_RETURN_RET_LOG(status == napi_ok && jsThis != nullptr, nullptr, "failed to napi_get_cb_info");
588 MEDIA_LOGI("argCount:%{public}zu", argCount);
589
590 AVRecorderNapi *recorderNapi = nullptr;
591 status = napi_unwrap(env, jsThis, reinterpret_cast<void **>(&recorderNapi));
592 CHECK_AND_RETURN_RET_LOG(status == napi_ok && recorderNapi != nullptr, nullptr, "failed to retrieve instance");
593
594 return recorderNapi;
595 }
596
GetPromiseTask(AVRecorderNapi * avnapi,const std::string & opt)597 std::shared_ptr<TaskHandler<RetInfo>> AVRecorderNapi::GetPromiseTask(AVRecorderNapi *avnapi, const std::string &opt)
598 {
599 return std::make_shared<TaskHandler<RetInfo>>([napi = avnapi, option = opt]() {
600 MEDIA_LOGI("%{public}s Start", option.c_str());
601 CHECK_AND_RETURN_RET(napi != nullptr && napi->recorder_ != nullptr,
602 GetRetInfo(MSERR_INVALID_OPERATION, option, ""));
603
604 CHECK_AND_RETURN_RET(napi->CheckStateMachine(option) == MSERR_OK,
605 GetRetInfo(MSERR_INVALID_OPERATION, option, ""));
606
607 CHECK_AND_RETURN_RET(napi->CheckRepeatOperation(option) == MSERR_OK,
608 RetInfo(MSERR_EXT_API9_OK, ""));
609
610 RetInfo ret(MSERR_EXT_API9_OPERATE_NOT_PERMIT, "");
611 auto itFunc = taskQFuncs_.find(option);
612 CHECK_AND_RETURN_RET_LOG(itFunc != taskQFuncs_.end(), ret, "%{public}s not found in map!", option.c_str());
613 auto memberFunc = itFunc->second;
614 CHECK_AND_RETURN_RET_LOG(memberFunc != nullptr, ret, "memberFunc is nullptr!");
615 ret = (napi->*memberFunc)();
616
617 MEDIA_LOGI("%{public}s End", option.c_str());
618 return ret;
619 });
620 }
621
ExecuteByPromise(napi_env env,napi_callback_info info,const std::string & opt)622 napi_value AVRecorderNapi::ExecuteByPromise(napi_env env, napi_callback_info info, const std::string &opt)
623 {
624 MEDIA_LOGI("Js %{public}s Start", opt.c_str());
625 napi_value result = nullptr;
626 napi_get_undefined(env, &result);
627 size_t argCount = 1; // Only callbackRef parameter
628 napi_value args[1] = { nullptr }; // Only callbackRef parameter
629
630 auto asyncCtx = std::make_unique<AVRecorderAsyncContext>(env);
631 CHECK_AND_RETURN_RET_LOG(asyncCtx != nullptr, result, "failed to get AsyncContext");
632 asyncCtx->napi = AVRecorderNapi::GetJsInstanceAndArgs(env, info, argCount, args);
633 CHECK_AND_RETURN_RET_LOG(asyncCtx->napi != nullptr, result, "failed to GetJsInstanceAndArgs");
634 CHECK_AND_RETURN_RET_LOG(asyncCtx->napi->taskQue_ != nullptr, result, "taskQue is nullptr!");
635
636 asyncCtx->callbackRef = CommonNapi::CreateReference(env, args[0]);
637 asyncCtx->deferred = CommonNapi::CreatePromise(env, asyncCtx->callbackRef, result);
638
639 if (asyncCtx->napi->CheckStateMachine(opt) == MSERR_OK) {
640 asyncCtx->task_ = AVRecorderNapi::GetPromiseTask(asyncCtx->napi, opt);
641 (void)asyncCtx->napi->taskQue_->EnqueueTask(asyncCtx->task_);
642 asyncCtx->opt_ = opt;
643 } else {
644 asyncCtx->AVRecorderSignError(MSERR_INVALID_OPERATION, opt, "");
645 }
646
647 napi_value resource = nullptr;
648 napi_create_string_utf8(env, opt.c_str(), NAPI_AUTO_LENGTH, &resource);
649 NAPI_CALL(env, napi_create_async_work(env, nullptr, resource, [](napi_env env, void* data) {
650 AVRecorderAsyncContext* asyncCtx = reinterpret_cast<AVRecorderAsyncContext *>(data);
651 CHECK_AND_RETURN_LOG(asyncCtx != nullptr, "asyncCtx is nullptr!");
652
653 if (asyncCtx->task_) {
654 auto result = asyncCtx->task_->GetResult();
655 if (result.Value().first != MSERR_EXT_API9_OK) {
656 asyncCtx->SignError(result.Value().first, result.Value().second);
657 }
658
659 if ((result.Value().first == MSERR_EXT_API9_OK) && (asyncCtx->opt_ == AVRecordergOpt::GETINPUTSURFACE)) {
660 asyncCtx->JsResult = std::make_unique<MediaJsResultString>(result.Value().second);
661 }
662 }
663 MEDIA_LOGI("The js thread of %{public}s finishes execution and returns", asyncCtx->opt_.c_str());
664 }, MediaAsyncContext::CompleteCallback, static_cast<void *>(asyncCtx.get()), &asyncCtx->work));
665 NAPI_CALL(env, napi_queue_async_work(env, asyncCtx->work));
666 asyncCtx.release();
667
668 MEDIA_LOGI("Js %{public}s End", opt.c_str());
669 return result;
670 }
671
GetInputSurface()672 RetInfo AVRecorderNapi::GetInputSurface()
673 {
674 CHECK_AND_RETURN_RET_LOG(withVideo_, GetRetInfo(MSERR_INVALID_OPERATION, "GetInputSurface", "",
675 "The VideoSourceType is not configured. Please do not call getInputSurface"), "No video recording");
676
677 if (surface_ == nullptr) {
678 surface_ = recorder_->GetSurface(videoSourceID_);
679 CHECK_AND_RETURN_RET_LOG(surface_ != nullptr,
680 GetRetInfo(MSERR_INVALID_OPERATION, "GetInputSurface", ""), "failed to GetSurface");
681
682 SurfaceError error = SurfaceUtils::GetInstance()->Add(surface_->GetUniqueId(), surface_);
683 CHECK_AND_RETURN_RET_LOG(error == SURFACE_ERROR_OK,
684 GetRetInfo(MSERR_INVALID_OPERATION, "GetInputSurface", ""), "failed to AddSurface");
685 }
686
687 auto surfaceId = std::to_string(surface_->GetUniqueId());
688 getVideoInputSurface_ = true;
689 return RetInfo(MSERR_EXT_API9_OK, surfaceId);
690 }
691
Start()692 RetInfo AVRecorderNapi::Start()
693 {
694 if (withVideo_ && !getVideoInputSurface_) {
695 return GetRetInfo(MSERR_INVALID_OPERATION, "Start", "",
696 " Please get the video input surface through GetInputSurface first!");
697 }
698
699 int32_t ret = recorder_->Start();
700 CHECK_AND_RETURN_RET(ret == MSERR_OK, GetRetInfo(ret, "Start", ""));
701 StateCallback(AVRecorderState::STATE_STARTED);
702 return RetInfo(MSERR_EXT_API9_OK, "");
703 }
704
Pause()705 RetInfo AVRecorderNapi::Pause()
706 {
707 int32_t ret = recorder_->Pause();
708 CHECK_AND_RETURN_RET(ret == MSERR_OK, GetRetInfo(ret, "Pause", ""));
709 StateCallback(AVRecorderState::STATE_PAUSED);
710 return RetInfo(MSERR_EXT_API9_OK, "");
711 }
712
Resume()713 RetInfo AVRecorderNapi::Resume()
714 {
715 int32_t ret = recorder_->Resume();
716 CHECK_AND_RETURN_RET(ret == MSERR_OK, GetRetInfo(ret, "Resume", ""));
717 StateCallback(AVRecorderState::STATE_STARTED);
718 return RetInfo(MSERR_EXT_API9_OK, "");
719 }
720
Stop()721 RetInfo AVRecorderNapi::Stop()
722 {
723 int32_t ret = recorder_->Stop(false);
724 CHECK_AND_RETURN_RET(ret == MSERR_OK, GetRetInfo(ret, "Stop", ""));
725 StateCallback(AVRecorderState::STATE_STOPPED);
726 hasConfiged_ = false;
727 return RetInfo(MSERR_EXT_API9_OK, "");
728 }
729
Reset()730 RetInfo AVRecorderNapi::Reset()
731 {
732 RemoveSurface();
733 int32_t ret = recorder_->Reset();
734 CHECK_AND_RETURN_RET(ret == MSERR_OK, GetRetInfo(ret, "Reset", ""));
735
736 StateCallback(AVRecorderState::STATE_IDLE);
737 hasConfiged_ = false;
738 return RetInfo(MSERR_EXT_API9_OK, "");
739 }
740
Release()741 RetInfo AVRecorderNapi::Release()
742 {
743 RemoveSurface();
744 int32_t ret = recorder_->Release();
745 CHECK_AND_RETURN_RET(ret == MSERR_OK, GetRetInfo(ret, "Release", ""));
746
747 StateCallback(AVRecorderState::STATE_RELEASED);
748 CancelCallback();
749 hasConfiged_ = false;
750 return RetInfo(MSERR_EXT_API9_OK, "");
751 }
752
CheckStateMachine(const std::string & opt)753 int32_t AVRecorderNapi::CheckStateMachine(const std::string &opt)
754 {
755 auto napiCb = std::static_pointer_cast<AVRecorderCallback>(recorderCb_);
756 CHECK_AND_RETURN_RET_LOG(napiCb != nullptr, MSERR_INVALID_OPERATION, "napiCb is nullptr!");
757
758 std::string curState = napiCb->GetState();
759 std::vector<std::string> allowedOpt = stateCtrlList.at(curState);
760 if (find(allowedOpt.begin(), allowedOpt.end(), opt) == allowedOpt.end()) {
761 MEDIA_LOGE("The %{public}s operation is not allowed in the %{public}s state!", opt.c_str(), curState.c_str());
762 return MSERR_INVALID_OPERATION;
763 }
764
765 return MSERR_OK;
766 }
767
CheckRepeatOperation(const std::string & opt)768 int32_t AVRecorderNapi::CheckRepeatOperation(const std::string &opt)
769 {
770 const std::map<std::string, std::vector<std::string>> stateCtrl = {
771 {AVRecorderState::STATE_IDLE, {
772 AVRecordergOpt::RESET,
773 AVRecordergOpt::GET_AV_RECORDER_PROFILE,
774 AVRecordergOpt::SET_AV_RECORDER_CONFIG,
775 }},
776 {AVRecorderState::STATE_PREPARED, {}},
777 {AVRecorderState::STATE_STARTED, {
778 AVRecordergOpt::START,
779 AVRecordergOpt::RESUME
780 }},
781 {AVRecorderState::STATE_PAUSED, {
782 AVRecordergOpt::PAUSE
783 }},
784 {AVRecorderState::STATE_STOPPED, {
785 AVRecordergOpt::STOP
786 }},
787 {AVRecorderState::STATE_RELEASED, {
788 AVRecordergOpt::RELEASE
789 }},
790 {AVRecorderState::STATE_ERROR, {}},
791 };
792
793 auto napiCb = std::static_pointer_cast<AVRecorderCallback>(recorderCb_);
794 CHECK_AND_RETURN_RET_LOG(napiCb != nullptr, MSERR_INVALID_OPERATION, "napiCb is nullptr!");
795
796 std::string curState = napiCb->GetState();
797 std::vector<std::string> repeatOpt = stateCtrl.at(curState);
798 if (find(repeatOpt.begin(), repeatOpt.end(), opt) != repeatOpt.end()) {
799 MEDIA_LOGI("Current state is %{public}s. Please do not call %{public}s again!", curState.c_str(), opt.c_str());
800 return MSERR_INVALID_OPERATION;
801 }
802
803 return MSERR_OK;
804 }
805
GetAudioCodecFormat(const std::string & mime,AudioCodecFormat & codecFormat)806 int32_t AVRecorderNapi::GetAudioCodecFormat(const std::string &mime, AudioCodecFormat &codecFormat)
807 {
808 MEDIA_LOGI("mime %{public}s", mime.c_str());
809 const std::map<std::string_view, AudioCodecFormat> mimeStrToCodecFormat = {
810 { CodecMimeType::AUDIO_AAC, AudioCodecFormat::AAC_LC },
811 { "", AudioCodecFormat::AUDIO_DEFAULT },
812 };
813
814 auto iter = mimeStrToCodecFormat.find(mime);
815 if (iter != mimeStrToCodecFormat.end()) {
816 codecFormat = iter->second;
817 return MSERR_OK;
818 }
819 return MSERR_INVALID_VAL;
820 }
821
GetVideoCodecFormat(const std::string & mime,VideoCodecFormat & codecFormat)822 int32_t AVRecorderNapi::GetVideoCodecFormat(const std::string &mime, VideoCodecFormat &codecFormat)
823 {
824 MEDIA_LOGI("mime %{public}s", mime.c_str());
825 const std::map<std::string_view, VideoCodecFormat> mimeStrToCodecFormat = {
826 { CodecMimeType::VIDEO_AVC, VideoCodecFormat::H264 },
827 { CodecMimeType::VIDEO_MPEG4, VideoCodecFormat::MPEG4 },
828 { "", VideoCodecFormat::VIDEO_DEFAULT },
829 };
830
831 auto iter = mimeStrToCodecFormat.find(mime);
832 if (iter != mimeStrToCodecFormat.end()) {
833 codecFormat = iter->second;
834 return MSERR_OK;
835 }
836 return MSERR_INVALID_VAL;
837 }
838
GetOutputFormat(const std::string & extension,OutputFormatType & type)839 int32_t AVRecorderNapi::GetOutputFormat(const std::string &extension, OutputFormatType &type)
840 {
841 MEDIA_LOGI("mime %{public}s", extension.c_str());
842 const std::map<std::string, OutputFormatType> extensionToOutputFormat = {
843 { "mp4", OutputFormatType::FORMAT_MPEG_4 },
844 { "m4a", OutputFormatType::FORMAT_M4A },
845 { "", OutputFormatType::FORMAT_DEFAULT },
846 };
847
848 auto iter = extensionToOutputFormat.find(extension);
849 if (iter != extensionToOutputFormat.end()) {
850 type = iter->second;
851 return MSERR_OK;
852 }
853 return MSERR_INVALID_VAL;
854 }
855
GetSourceType(std::unique_ptr<AVRecorderAsyncContext> & asyncCtx,napi_env env,napi_value args)856 int32_t AVRecorderNapi::GetSourceType(std::unique_ptr<AVRecorderAsyncContext> &asyncCtx, napi_env env, napi_value args)
857 {
858 std::shared_ptr<AVRecorderConfig> config = asyncCtx->config_;
859 int32_t audioSource = AUDIO_SOURCE_INVALID;
860 int32_t videoSource = VIDEO_SOURCE_BUTT;
861
862 bool getValue = false;
863 int32_t ret = AVRecorderNapi::GetPropertyInt32(env, args, "audioSourceType", audioSource, getValue);
864 CHECK_AND_RETURN_RET(ret == MSERR_OK,
865 (asyncCtx->AVRecorderSignError(ret, "getaudioSourceType", "audioSourceType"), ret));
866 if (getValue) {
867 config->audioSourceType = static_cast<AudioSourceType>(audioSource);
868 config->withAudio = true;
869 MEDIA_LOGI("audioSource Type %{public}d!", audioSource);
870 }
871
872 ret = AVRecorderNapi::GetPropertyInt32(env, args, "videoSourceType", videoSource, getValue);
873 CHECK_AND_RETURN_RET(ret == MSERR_OK,
874 (asyncCtx->AVRecorderSignError(ret, "getvideoSourceType", "videoSourceType"), ret));
875 if (getValue) {
876 config->videoSourceType = static_cast<VideoSourceType>(videoSource);
877 config->withVideo = true;
878 MEDIA_LOGI("videoSource Type %{public}d!", videoSource);
879 }
880
881 CHECK_AND_RETURN_RET(config->withAudio || config->withVideo,
882 (asyncCtx->AVRecorderSignError(MSERR_INVALID_VAL, "getsourcetype", "SourceType"), MSERR_INVALID_VAL));
883
884 return MSERR_OK;
885 }
886
GetProfile(std::unique_ptr<AVRecorderAsyncContext> & asyncCtx,napi_env env,napi_value args)887 int32_t AVRecorderNapi::GetProfile(std::unique_ptr<AVRecorderAsyncContext> &asyncCtx, napi_env env, napi_value args)
888 {
889 napi_value item = nullptr;
890 napi_get_named_property(env, args, "profile", &item);
891 CHECK_AND_RETURN_RET_LOG(item != nullptr, MSERR_INVALID_VAL, "get profile error");
892
893 AVRecorderProfile &profile = asyncCtx->config_->profile;
894
895 int32_t ret = MSERR_OK;
896 if (asyncCtx->config_->withAudio) {
897 std::string audioCodec = CommonNapi::GetPropertyString(env, item, "audioCodec");
898 ret = AVRecorderNapi::GetAudioCodecFormat(audioCodec, profile.audioCodecFormat);
899 CHECK_AND_RETURN_RET(ret == MSERR_OK,
900 (asyncCtx->AVRecorderSignError(ret, "GetAudioCodecFormat", "audioCodecFormat"), ret));
901
902 ret = MSERR_INVALID_VAL;
903 CHECK_AND_RETURN_RET(CommonNapi::GetPropertyInt32(env, item, "audioBitrate", profile.audioBitrate),
904 (asyncCtx->AVRecorderSignError(ret, "GetaudioBitrate", "audioBitrate"), ret));
905 CHECK_AND_RETURN_RET(CommonNapi::GetPropertyInt32(env, item, "audioChannels", profile.audioChannels),
906 (asyncCtx->AVRecorderSignError(ret, "GetaudioChannels", "audioChannels"), ret));
907 CHECK_AND_RETURN_RET(CommonNapi::GetPropertyInt32(env, item, "audioSampleRate", profile.auidoSampleRate),
908 (asyncCtx->AVRecorderSignError(ret, "GetauidoSampleRate", "auidoSampleRate"), ret));
909
910 MEDIA_LOGI("audioBitrate %{public}d, audioChannels %{public}d, audioCodecFormat %{public}d,"
911 " audioSampleRate %{public}d!", profile.audioBitrate, profile.audioChannels,
912 profile.audioCodecFormat, profile.auidoSampleRate);
913 }
914
915 if (asyncCtx->config_->withVideo) {
916 std::string videoCodec = CommonNapi::GetPropertyString(env, item, "videoCodec");
917 ret = AVRecorderNapi::GetVideoCodecFormat(videoCodec, profile.videoCodecFormat);
918 CHECK_AND_RETURN_RET(ret == MSERR_OK,
919 (asyncCtx->AVRecorderSignError(ret, "GetVideoCodecFormat", "videoCodecFormat"), ret));
920
921 ret = MSERR_INVALID_VAL;
922 CHECK_AND_RETURN_RET(CommonNapi::GetPropertyInt32(env, item, "videoBitrate", profile.videoBitrate),
923 (asyncCtx->AVRecorderSignError(ret, "GetvideoBitrate", "videoBitrate"), ret));
924 CHECK_AND_RETURN_RET(CommonNapi::GetPropertyInt32(env, item, "videoFrameWidth", profile.videoFrameWidth),
925 (asyncCtx->AVRecorderSignError(ret, "GetvideoFrameWidth", "videoFrameWidth"), ret));
926 CHECK_AND_RETURN_RET(CommonNapi::GetPropertyInt32(env, item, "videoFrameHeight", profile.videoFrameHeight),
927 (asyncCtx->AVRecorderSignError(ret, "GetvideoFrameHeight", "videoFrameHeight"), ret));
928 CHECK_AND_RETURN_RET(CommonNapi::GetPropertyInt32(env, item, "videoFrameRate", profile.videoFrameRate),
929 (asyncCtx->AVRecorderSignError(ret, "GetvideoFrameRate", "videoFrameRate"), ret));
930
931 MEDIA_LOGI("videoBitrate %{public}d, videoCodecFormat %{public}d, videoFrameWidth %{public}d,"
932 " videoFrameHeight %{public}d, videoFrameRate %{public}d",
933 profile.videoBitrate, profile.videoCodecFormat, profile.videoFrameWidth,
934 profile.videoFrameHeight, profile.videoFrameRate);
935 }
936
937 std::string outputFile = CommonNapi::GetPropertyString(env, item, "fileFormat");
938 ret = AVRecorderNapi::GetOutputFormat(outputFile, profile.fileFormat);
939 CHECK_AND_RETURN_RET(ret == MSERR_OK,
940 (asyncCtx->AVRecorderSignError(ret, "GetOutputFormat", "fileFormat"), ret));
941 MEDIA_LOGI("fileFormat %{public}d", profile.fileFormat);
942
943 return MSERR_OK;
944 }
945
GetConfig(std::unique_ptr<AVRecorderAsyncContext> & asyncCtx,napi_env env,napi_value args)946 int32_t AVRecorderNapi::GetConfig(std::unique_ptr<AVRecorderAsyncContext> &asyncCtx, napi_env env, napi_value args)
947 {
948 napi_valuetype valueType = napi_undefined;
949 if (args == nullptr || napi_typeof(env, args, &valueType) != napi_ok || valueType != napi_object) {
950 asyncCtx->AVRecorderSignError(MSERR_INVALID_VAL, "GetConfig", "AVRecorderConfig");
951 return MSERR_INVALID_VAL;
952 }
953
954 asyncCtx->config_ = std::make_shared<AVRecorderConfig>();
955 CHECK_AND_RETURN_RET(asyncCtx->config_,
956 (asyncCtx->AVRecorderSignError(MSERR_NO_MEMORY, "AVRecorderConfig", "AVRecorderConfig"), MSERR_NO_MEMORY));
957
958 std::shared_ptr<AVRecorderConfig> config = asyncCtx->config_;
959
960 int32_t ret = GetSourceType(asyncCtx, env, args);
961 CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, ret, "failed to GetSourceType");
962
963 ret = GetProfile(asyncCtx, env, args);
964 CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, ret, "failed to GetProfile");
965
966 config->url = CommonNapi::GetPropertyString(env, args, "url");
967 MEDIA_LOGI("url %{public}s!", config->url.c_str());
968 CHECK_AND_RETURN_RET(config->url != "",
969 (asyncCtx->AVRecorderSignError(MSERR_INVALID_VAL, "geturl", "url"), MSERR_INVALID_VAL));
970
971 bool getValue = false;
972 ret = AVRecorderNapi::GetPropertyInt32(env, args, "rotation", config->rotation, getValue);
973 CHECK_AND_RETURN_RET(ret == MSERR_OK,
974 (asyncCtx->AVRecorderSignError(ret, "getrotation", "rotation"), ret));
975 MEDIA_LOGI("rotation %{public}d!", config->rotation);
976 CHECK_AND_RETURN_RET((config->rotation == VIDEO_ROTATION_0 || config->rotation == VIDEO_ROTATION_90 ||
977 config->rotation == VIDEO_ROTATION_180 || config->rotation == VIDEO_ROTATION_270),
978 (asyncCtx->AVRecorderSignError(MSERR_INVALID_VAL, "getrotation", "rotation"), MSERR_INVALID_VAL));
979
980 napi_value geoLocation = nullptr;
981 napi_get_named_property(env, args, "location", &geoLocation);
982 double tempLatitude = 0;
983 double tempLongitude = 0;
984 (void)CommonNapi::GetPropertyDouble(env, geoLocation, "latitude", tempLatitude);
985 (void)CommonNapi::GetPropertyDouble(env, geoLocation, "longitude", tempLongitude);
986 config->location.latitude = static_cast<float>(tempLatitude);
987 config->location.longitude = static_cast<float>(tempLongitude);
988
989 return MSERR_OK;
990 }
991
SetProfile(std::shared_ptr<AVRecorderConfig> config)992 RetInfo AVRecorderNapi::SetProfile(std::shared_ptr<AVRecorderConfig> config)
993 {
994 int32_t ret;
995 AVRecorderProfile &profile = config->profile;
996
997 ret = recorder_->SetOutputFormat(profile.fileFormat);
998 CHECK_AND_RETURN_RET(ret == MSERR_OK, GetRetInfo(ret, "SetOutputFormat", "fileFormat"));
999
1000 if (config->withAudio) {
1001 ret = recorder_->SetAudioEncoder(audioSourceID_, profile.audioCodecFormat);
1002 CHECK_AND_RETURN_RET(ret == MSERR_OK, GetRetInfo(ret, "SetAudioEncoder", "audioCodecFormat"));
1003
1004 ret = recorder_->SetAudioSampleRate(audioSourceID_, profile.auidoSampleRate);
1005 CHECK_AND_RETURN_RET(ret == MSERR_OK, GetRetInfo(ret, "SetAudioSampleRate", "auidoSampleRate"));
1006
1007 ret = recorder_->SetAudioChannels(audioSourceID_, profile.audioChannels);
1008 CHECK_AND_RETURN_RET(ret == MSERR_OK, GetRetInfo(ret, "SetAudioChannels", "audioChannels"));
1009
1010 ret = recorder_->SetAudioEncodingBitRate(audioSourceID_, profile.audioBitrate);
1011 CHECK_AND_RETURN_RET(ret == MSERR_OK, GetRetInfo(ret, "SetAudioEncodingBitRate", "audioBitrate"));
1012 }
1013
1014 if (config->withVideo) {
1015 ret = recorder_->SetVideoEncoder(videoSourceID_, profile.videoCodecFormat);
1016 CHECK_AND_RETURN_RET(ret == MSERR_OK, GetRetInfo(ret, "SetVideoEncoder", "videoCodecFormat"));
1017
1018 ret = recorder_->SetVideoSize(videoSourceID_, profile.videoFrameWidth, profile.videoFrameHeight);
1019 CHECK_AND_RETURN_RET(ret == MSERR_OK, GetRetInfo(ret, "SetVideoSize", "VideoSize"));
1020
1021 ret = recorder_->SetVideoFrameRate(videoSourceID_, profile.videoFrameRate);
1022 CHECK_AND_RETURN_RET(ret == MSERR_OK, GetRetInfo(ret, "SetVideoFrameRate", "videoFrameRate"));
1023
1024 ret = recorder_->SetVideoEncodingBitRate(videoSourceID_, profile.videoBitrate);
1025 CHECK_AND_RETURN_RET(ret == MSERR_OK, GetRetInfo(ret, "SetVideoEncodingBitRate", "videoBitrate"));
1026 }
1027
1028 return RetInfo(MSERR_EXT_API9_OK, "");
1029 }
1030
Configure(std::shared_ptr<AVRecorderConfig> config)1031 RetInfo AVRecorderNapi::Configure(std::shared_ptr<AVRecorderConfig> config)
1032 {
1033 CHECK_AND_RETURN_RET(recorder_ != nullptr, GetRetInfo(MSERR_INVALID_OPERATION, "Configure", ""));
1034 CHECK_AND_RETURN_RET(config != nullptr, GetRetInfo(MSERR_INVALID_VAL, "Configure", "config"));
1035
1036 if (hasConfiged_) {
1037 MEDIA_LOGE("AVRecorderConfig has been configured and will not be configured again");
1038 return RetInfo(MSERR_EXT_API9_OK, "");
1039 }
1040
1041 int32_t ret;
1042 if (config->withAudio) {
1043 ret = recorder_->SetAudioSource(config->audioSourceType, audioSourceID_);
1044 CHECK_AND_RETURN_RET(ret == MSERR_OK, GetRetInfo(ret, "SetAudioSource", "audioSourceType"));
1045 }
1046
1047 if (config->withVideo) {
1048 ret = recorder_->SetVideoSource(config->videoSourceType, videoSourceID_);
1049 CHECK_AND_RETURN_RET(ret == MSERR_OK, GetRetInfo(ret, "SetVideoSource", "videoSourceType"));
1050 }
1051
1052 RetInfo retInfo = SetProfile(config);
1053 CHECK_AND_RETURN_RET_LOG(retInfo.first == MSERR_OK, retInfo, "Fail to set videoBitrate");
1054
1055 recorder_->SetLocation(config->location.latitude, config->location.longitude);
1056
1057 if (config->withVideo) {
1058 recorder_->SetOrientationHint(config->rotation);
1059 }
1060
1061 ret = MSERR_INVALID_VAL;
1062 const std::string fdHead = "fd://";
1063 CHECK_AND_RETURN_RET(config->url.find(fdHead) != std::string::npos, GetRetInfo(ret, "Getfd", "uri"));
1064 int32_t fd = -1;
1065 std::string inputFd = config->url.substr(fdHead.size());
1066 CHECK_AND_RETURN_RET(StrToInt(inputFd, fd) == true && fd >= 0, GetRetInfo(ret, "Getfd", "uri"));
1067
1068 ret = recorder_->SetOutputFile(fd);
1069 CHECK_AND_RETURN_RET(ret == MSERR_OK, GetRetInfo(ret, "SetOutputFile", "uri"));
1070 hasConfiged_ = true;
1071
1072 return RetInfo(MSERR_EXT_API9_OK, "");
1073 }
1074
GetSourceIdAndQuality(std::unique_ptr<AVRecorderAsyncContext> & asyncCtx,napi_env env,napi_value sourceIdArgs,napi_value qualityArgs,const std::string & opt)1075 int32_t AVRecorderNapi::GetSourceIdAndQuality(std::unique_ptr<AVRecorderAsyncContext> &asyncCtx,
1076 napi_env env, napi_value sourceIdArgs, napi_value qualityArgs, const std::string &opt)
1077 {
1078 if (asyncCtx->napi->CheckStateMachine(opt) == MSERR_OK) {
1079 napi_status ret = napi_get_value_int32(env, sourceIdArgs, &asyncCtx->napi->sourceId_);
1080 if (ret != napi_ok) {
1081 asyncCtx->AVRecorderSignError(MSERR_INVALID_VAL, "failed to get sourceId", "");
1082 return MSERR_INVALID_VAL;
1083 }
1084 ret = napi_get_value_int32(env, qualityArgs, &asyncCtx->napi->qualityLevel_);
1085 if (ret != napi_ok) {
1086 asyncCtx->AVRecorderSignError(MSERR_INVALID_VAL, "failed to get qualityLevel", "");
1087 return MSERR_INVALID_VAL;
1088 }
1089 } else {
1090 asyncCtx->AVRecorderSignError(MSERR_INVALID_OPERATION, opt, "");
1091 return MSERR_INVALID_OPERATION;
1092 }
1093 return MSERR_OK;
1094 }
1095
GetAVRecorderProfile(std::shared_ptr<AVRecorderProfile> & profile,const int32_t sourceId,const int32_t qualityLevel)1096 int32_t AVRecorderNapi::GetAVRecorderProfile(std::shared_ptr<AVRecorderProfile> &profile,
1097 const int32_t sourceId, const int32_t qualityLevel)
1098 {
1099 MediaTrace trace("AVRecorder::GetAVRecorderProfile");
1100 std::shared_ptr<VideoRecorderProfile> videoRecorderProfile =
1101 OHOS::Media::RecorderProfilesFactory::CreateRecorderProfiles().GetVideoRecorderProfile(sourceId, qualityLevel);
1102 CHECK_AND_RETURN_RET_LOG(videoRecorderProfile != nullptr, MSERR_INVALID_VAL, "failed to get videoRecorderProfile");
1103
1104 int32_t ret = MSERR_OK;
1105 ret = AVRecorderNapi::GetOutputFormat(videoRecorderProfile->containerFormatType, profile ->fileFormat);
1106 CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, MSERR_INVALID_VAL, "get outputFormat error");
1107
1108 ret = AVRecorderNapi::GetAudioCodecFormat(videoRecorderProfile->audioCodec, profile ->audioCodecFormat);
1109 CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, MSERR_INVALID_VAL, "get audioCodec error");
1110
1111 ret = AVRecorderNapi::GetVideoCodecFormat(videoRecorderProfile->videoCodec, profile ->videoCodecFormat);
1112 CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, MSERR_INVALID_VAL, "get videoCodec error");
1113
1114 profile->audioBitrate = videoRecorderProfile->audioBitrate;
1115 profile->audioChannels = videoRecorderProfile->audioChannels;
1116 profile->auidoSampleRate = videoRecorderProfile->audioSampleRate;
1117 profile->videoBitrate = videoRecorderProfile->videoBitrate;
1118 profile->videoFrameWidth = videoRecorderProfile->videoFrameWidth;
1119 profile->videoFrameHeight = videoRecorderProfile->videoFrameHeight;
1120 profile->videoFrameRate = videoRecorderProfile->videoFrameRate;
1121
1122 return MSERR_OK;
1123 }
1124
ErrorCallback(int32_t errCode,const std::string & operate,const std::string & add)1125 void AVRecorderNapi::ErrorCallback(int32_t errCode, const std::string &operate, const std::string &add)
1126 {
1127 MEDIA_LOGE("failed to %{public}s, errCode = %{public}d", operate.c_str(), errCode);
1128 CHECK_AND_RETURN_LOG(recorderCb_ != nullptr, "recorderCb_ is nullptr!");
1129 auto napiCb = std::static_pointer_cast<AVRecorderCallback>(recorderCb_);
1130
1131 MediaServiceExtErrCodeAPI9 err = MSErrorToExtErrorAPI9(static_cast<MediaServiceErrCode>(errCode));
1132 std::string msg = MSExtErrorAPI9ToString(err, operate, "") + add;
1133 napiCb->SendErrorCallback(errCode, msg);
1134 }
1135
StateCallback(const std::string & state)1136 void AVRecorderNapi::StateCallback(const std::string &state)
1137 {
1138 MEDIA_LOGI("Change state to %{public}s", state.c_str());
1139 CHECK_AND_RETURN_LOG(recorderCb_ != nullptr, "recorderCb_ is nullptr!");
1140 auto napiCb = std::static_pointer_cast<AVRecorderCallback>(recorderCb_);
1141 napiCb->SendStateCallback(state, StateChangeReason::USER);
1142 }
1143
SetCallbackReference(const std::string & callbackName,std::shared_ptr<AutoRef> ref)1144 void AVRecorderNapi::SetCallbackReference(const std::string &callbackName, std::shared_ptr<AutoRef> ref)
1145 {
1146 eventCbMap_[callbackName] = ref;
1147 CHECK_AND_RETURN_LOG(recorderCb_ != nullptr, "recorderCb_ is nullptr!");
1148 auto napiCb = std::static_pointer_cast<AVRecorderCallback>(recorderCb_);
1149 napiCb->SaveCallbackReference(callbackName, ref);
1150 }
1151
CancelCallbackReference(const std::string & callbackName)1152 void AVRecorderNapi::CancelCallbackReference(const std::string &callbackName)
1153 {
1154 CHECK_AND_RETURN_LOG(recorderCb_ != nullptr, "recorderCb_ is nullptr!");
1155 auto napiCb = std::static_pointer_cast<AVRecorderCallback>(recorderCb_);
1156 napiCb->CancelCallbackReference(callbackName);
1157 eventCbMap_[callbackName] = nullptr;
1158 }
1159
CancelCallback()1160 void AVRecorderNapi::CancelCallback()
1161 {
1162 CHECK_AND_RETURN_LOG(recorderCb_ != nullptr, "recorderCb_ is nullptr!");
1163 auto napiCb = std::static_pointer_cast<AVRecorderCallback>(recorderCb_);
1164 napiCb->ClearCallbackReference();
1165 }
1166
RemoveSurface()1167 void AVRecorderNapi::RemoveSurface()
1168 {
1169 if (surface_ != nullptr) {
1170 auto id = surface_->GetUniqueId();
1171 auto surface = SurfaceUtils::GetInstance()->GetSurface(id);
1172 if (surface) {
1173 (void)SurfaceUtils::GetInstance()->Remove(id);
1174 }
1175 surface_ = nullptr;
1176 }
1177 }
1178
GetPropertyInt32(napi_env env,napi_value configObj,const std::string & type,int32_t & result,bool & getValue)1179 int32_t AVRecorderNapi::GetPropertyInt32(napi_env env, napi_value configObj, const std::string &type, int32_t &result,
1180 bool &getValue)
1181 {
1182 napi_value item = nullptr;
1183 bool exist = false;
1184 getValue = false;
1185 napi_status status = napi_has_named_property(env, configObj, type.c_str(), &exist);
1186 if (status != napi_ok || !exist) {
1187 MEDIA_LOGI("can not find %{public}s property", type.c_str());
1188 return MSERR_OK;
1189 }
1190
1191 if (napi_get_named_property(env, configObj, type.c_str(), &item) != napi_ok) {
1192 MEDIA_LOGI("get %{public}s property fail", type.c_str());
1193 return MSERR_UNKNOWN;
1194 }
1195
1196 if (napi_get_value_int32(env, item, &result) != napi_ok) {
1197 std::string string = CommonNapi::GetStringArgument(env, item);
1198 if (string == "") {
1199 // This attribute has not been assigned
1200 return MSERR_OK;
1201 } else {
1202 MEDIA_LOGE("get %{public}s property value fail", type.c_str());
1203 return MSERR_INVALID_VAL;
1204 }
1205 }
1206
1207 MEDIA_LOGI("get %{public}s : %{public}d!", type.c_str(), result);
1208 getValue = true;
1209 return MSERR_OK;
1210 }
1211
GetJsResult(napi_env env,napi_value & result)1212 napi_status MediaJsAVRecorderProfile::GetJsResult(napi_env env, napi_value &result)
1213 {
1214 napi_status ret = napi_ok;
1215 bool setRet = true;
1216 int32_t setState = MSERR_OK;
1217 CHECK_AND_RETURN_RET(value_ != nullptr, napi_generic_failure);
1218 CHECK_AND_RETURN_RET((ret = napi_create_object(env, &result)) == napi_ok, ret);
1219
1220 setRet = CommonNapi::SetPropertyInt32(env, result, "audioBitrate", value_->audioBitrate);
1221 CHECK_AND_RETURN_RET(setRet == true, napi_generic_failure);
1222 setRet = CommonNapi::SetPropertyInt32(env, result, "audioChannels", value_->audioChannels);
1223 CHECK_AND_RETURN_RET(setRet == true, napi_generic_failure);
1224
1225 std::string audioCodec;
1226 setState = SetAudioCodecFormat(value_->audioCodecFormat, audioCodec);
1227 CHECK_AND_RETURN_RET(setState == MSERR_OK, napi_generic_failure);
1228 setRet = CommonNapi::SetPropertyString(env, result, "audioCodec", audioCodec);
1229 CHECK_AND_RETURN_RET(setRet == true, napi_generic_failure);
1230
1231 setRet = CommonNapi::SetPropertyInt32(env, result, "audioSampleRate", value_->auidoSampleRate);
1232 CHECK_AND_RETURN_RET(setRet == true, napi_generic_failure);
1233
1234 std::string fileFormat;
1235 setState = SetFileFormat(value_->fileFormat, fileFormat);
1236 CHECK_AND_RETURN_RET(setState == MSERR_OK, napi_generic_failure);
1237 setRet = CommonNapi::SetPropertyString(env, result, "fileFormat", fileFormat);
1238 CHECK_AND_RETURN_RET(setRet == true, napi_generic_failure);
1239
1240 setRet = CommonNapi::SetPropertyInt32(env, result, "videoBitrate", value_->videoBitrate);
1241 CHECK_AND_RETURN_RET(setRet == true, napi_generic_failure);
1242
1243 std::string videoCodec;
1244 setState = SetVideoCodecFormat(value_->videoCodecFormat, videoCodec);
1245 CHECK_AND_RETURN_RET(setState == MSERR_OK, napi_generic_failure);
1246 setRet = CommonNapi::SetPropertyString(env, result, "videoCodec", videoCodec);
1247 CHECK_AND_RETURN_RET(setRet == true, napi_generic_failure);
1248
1249 CHECK_AND_RETURN_RET(setRet == true, napi_generic_failure);
1250 setRet = CommonNapi::SetPropertyInt32(env, result, "videoFrameWidth", value_->videoFrameWidth);
1251 CHECK_AND_RETURN_RET(setRet == true, napi_generic_failure);
1252 setRet = CommonNapi::SetPropertyInt32(env, result, "videoFrameHeight", value_->videoFrameHeight);
1253 CHECK_AND_RETURN_RET(setRet == true, napi_generic_failure);
1254 setRet = CommonNapi::SetPropertyInt32(env, result, "videoFrameRate", value_->videoFrameRate);
1255 CHECK_AND_RETURN_RET(setRet == true, napi_generic_failure);
1256
1257 return ret;
1258 }
1259
SetAudioCodecFormat(AudioCodecFormat & codecFormat,std::string & mime)1260 int32_t MediaJsAVRecorderProfile::SetAudioCodecFormat(AudioCodecFormat &codecFormat, std::string &mime)
1261 {
1262 MEDIA_LOGI("audioCodecFormat %{public}d", codecFormat);
1263 const std::map<AudioCodecFormat, std::string_view> codecFormatToMimeStr = {
1264 { AudioCodecFormat::AAC_LC, CodecMimeType::AUDIO_AAC },
1265 { AudioCodecFormat::AUDIO_DEFAULT, "" },
1266 };
1267
1268 auto iter = codecFormatToMimeStr.find(codecFormat);
1269 if (iter != codecFormatToMimeStr.end()) {
1270 mime = iter->second;
1271 return MSERR_OK;
1272 }
1273 return MSERR_INVALID_VAL;
1274 }
1275
SetVideoCodecFormat(VideoCodecFormat & codecFormat,std::string & mime)1276 int32_t MediaJsAVRecorderProfile::SetVideoCodecFormat(VideoCodecFormat &codecFormat, std::string &mime)
1277 {
1278 MEDIA_LOGI("VideoCodecFormat %{public}d", codecFormat);
1279 const std::map<VideoCodecFormat, std::string_view> codecFormatTomimeStr = {
1280 { VideoCodecFormat::H264, CodecMimeType::VIDEO_AVC },
1281 { VideoCodecFormat::MPEG4, CodecMimeType::VIDEO_MPEG4 },
1282 { VideoCodecFormat::VIDEO_DEFAULT, ""},
1283 };
1284
1285 auto iter = codecFormatTomimeStr.find(codecFormat);
1286 if (iter != codecFormatTomimeStr.end()) {
1287 mime = iter->second;
1288 return MSERR_OK;
1289 }
1290 return MSERR_INVALID_VAL;
1291 }
1292
SetFileFormat(OutputFormatType & type,std::string & extension)1293 int32_t MediaJsAVRecorderProfile::SetFileFormat(OutputFormatType &type, std::string &extension)
1294 {
1295 MEDIA_LOGI("OutputFormatType %{public}d", type);
1296 const std::map<OutputFormatType, std::string> outputFormatToextension = {
1297 { OutputFormatType::FORMAT_MPEG_4, "mp4" },
1298 { OutputFormatType::FORMAT_M4A, "m4a" },
1299 { OutputFormatType::FORMAT_DEFAULT, "" },
1300 };
1301
1302 auto iter = outputFormatToextension.find(type);
1303 if (iter != outputFormatToextension.end()) {
1304 extension = iter->second;
1305 return MSERR_OK;
1306 }
1307 return MSERR_INVALID_VAL;
1308 }
1309
AVRecorderSignError(int32_t errCode,const std::string & operate,const std::string & param,const std::string & add)1310 void AVRecorderAsyncContext::AVRecorderSignError(int32_t errCode, const std::string &operate,
1311 const std::string ¶m, const std::string &add)
1312 {
1313 RetInfo retInfo = GetRetInfo(errCode, operate, param, add);
1314 SignError(retInfo.first, retInfo.second);
1315 }
1316 } // namespace Media
1317 } // namespace OHOS