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 "avcontainer_common.h"
27 #include "avrecorder_napi.h"
28
29 namespace {
30 constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, LOG_DOMAIN, "AVRecorderNapi"};
31 }
32
33 namespace OHOS {
34 namespace Media {
35 thread_local napi_ref AVRecorderNapi::constructor_ = nullptr;
36 const std::string CLASS_NAME = "AVRecorder";
37 std::map<std::string, AVRecorderNapi::AvRecorderTaskqFunc> AVRecorderNapi::taskQFuncs_ = {
38 {AVRecordergOpt::GETINPUTSURFACE, &AVRecorderNapi::GetInputSurface},
39 {AVRecordergOpt::START, &AVRecorderNapi::Start},
40 {AVRecordergOpt::PAUSE, &AVRecorderNapi::Pause},
41 {AVRecordergOpt::RESUME, &AVRecorderNapi::Resume},
42 {AVRecordergOpt::STOP, &AVRecorderNapi::Stop},
43 {AVRecordergOpt::RESET, &AVRecorderNapi::Reset},
44 {AVRecordergOpt::RELEASE, &AVRecorderNapi::Release},
45 };
46
AVRecorderNapi()47 AVRecorderNapi::AVRecorderNapi()
48 {
49 MEDIA_LOGI("0x%{public}06" PRIXPTR "Instances create", FAKE_POINTER(this));
50 }
51
~AVRecorderNapi()52 AVRecorderNapi::~AVRecorderNapi()
53 {
54 MEDIA_LOGI("0x%{public}06" PRIXPTR "Instances destroy", FAKE_POINTER(this));
55 }
56
Init(napi_env env,napi_value exports)57 napi_value AVRecorderNapi::Init(napi_env env, napi_value exports)
58 {
59 napi_property_descriptor staticProperty[] = {
60 DECLARE_NAPI_STATIC_FUNCTION("createAVRecorder", JsCreateAVRecorder),
61 };
62
63 napi_property_descriptor properties[] = {
64 DECLARE_NAPI_FUNCTION("prepare", JsPrepare),
65 DECLARE_NAPI_FUNCTION("getInputSurface", JsGetInputSurface),
66 DECLARE_NAPI_FUNCTION("start", JsStart),
67 DECLARE_NAPI_FUNCTION("pause", JsPause),
68 DECLARE_NAPI_FUNCTION("resume", JsResume),
69 DECLARE_NAPI_FUNCTION("stop", JsStop),
70 DECLARE_NAPI_FUNCTION("reset", JsReset),
71 DECLARE_NAPI_FUNCTION("release", JsRelease),
72 DECLARE_NAPI_FUNCTION("on", JsSetEventCallback),
73 DECLARE_NAPI_FUNCTION("off", JsCancelEventCallback),
74
75 DECLARE_NAPI_GETTER("state", JsGetState),
76 };
77
78 napi_value constructor = nullptr;
79 napi_status status = napi_define_class(env, CLASS_NAME.c_str(), NAPI_AUTO_LENGTH, Constructor, nullptr,
80 sizeof(properties) / sizeof(properties[0]), properties, &constructor);
81 CHECK_AND_RETURN_RET_LOG(status == napi_ok, nullptr, "Failed to define AVRecorder class");
82
83 status = napi_create_reference(env, constructor, 1, &constructor_);
84 CHECK_AND_RETURN_RET_LOG(status == napi_ok, nullptr, "Failed to create reference of constructor");
85
86 status = napi_set_named_property(env, exports, CLASS_NAME.c_str(), constructor);
87 CHECK_AND_RETURN_RET_LOG(status == napi_ok, nullptr, "Failed to set constructor");
88
89 status = napi_define_properties(env, exports, sizeof(staticProperty) / sizeof(staticProperty[0]), staticProperty);
90 CHECK_AND_RETURN_RET_LOG(status == napi_ok, nullptr, "Failed to define static function");
91
92 MEDIA_LOGI("Init success");
93 return exports;
94 }
95
Constructor(napi_env env,napi_callback_info info)96 napi_value AVRecorderNapi::Constructor(napi_env env, napi_callback_info info)
97 {
98 MediaTrace trace("AVRecorder::Constructor");
99 napi_value result = nullptr;
100 napi_get_undefined(env, &result);
101
102 size_t argCount = 0;
103 napi_value jsThis = nullptr;
104 napi_status status = napi_get_cb_info(env, info, &argCount, nullptr, &jsThis, nullptr);
105 CHECK_AND_RETURN_RET_LOG(status == napi_ok, result, "failed to napi_get_cb_info");
106
107 AVRecorderNapi *jsRecorder = new(std::nothrow) AVRecorderNapi();
108 CHECK_AND_RETURN_RET_LOG(jsRecorder != nullptr, result, "failed to new AVRecorderNapi");
109
110 jsRecorder->env_ = env;
111 jsRecorder->recorder_ = RecorderFactory::CreateRecorder();
112 CHECK_AND_RETURN_RET_LOG(jsRecorder->recorder_ != nullptr, result, "failed to CreateRecorder");
113
114 jsRecorder->taskQue_ = std::make_unique<TaskQueue>("AVRecorderNapi");
115 (void)jsRecorder->taskQue_->Start();
116
117 jsRecorder->recorderCb_ = std::make_shared<AVRecorderCallback>(env);
118 CHECK_AND_RETURN_RET_LOG(jsRecorder->recorderCb_ != nullptr, result, "failed to CreateRecorderCb");
119 (void)jsRecorder->recorder_->SetRecorderCallback(jsRecorder->recorderCb_);
120
121 status = napi_wrap(env, jsThis, reinterpret_cast<void *>(jsRecorder),
122 AVRecorderNapi::Destructor, nullptr, nullptr);
123 if (status != napi_ok) {
124 delete jsRecorder;
125 MEDIA_LOGE("Failed to wrap native instance");
126 return result;
127 }
128
129 MEDIA_LOGI("Constructor success");
130 return jsThis;
131 }
132
Destructor(napi_env env,void * nativeObject,void * finalize)133 void AVRecorderNapi::Destructor(napi_env env, void *nativeObject, void *finalize)
134 {
135 MediaTrace trace("AVRecorder::Destructor");
136 (void)finalize;
137 if (nativeObject != nullptr) {
138 AVRecorderNapi *napi = reinterpret_cast<AVRecorderNapi *>(nativeObject);
139 if (napi->taskQue_ != nullptr) {
140 (void)napi->taskQue_->Stop();
141 }
142
143 napi->RemoveSurface();
144 napi->recorderCb_ = nullptr;
145
146 if (napi->recorder_) {
147 napi->recorder_->Release();
148 napi->recorder_ = nullptr;
149 }
150
151 delete napi;
152 }
153 MEDIA_LOGI("Destructor success");
154 }
155
JsCreateAVRecorder(napi_env env,napi_callback_info info)156 napi_value AVRecorderNapi::JsCreateAVRecorder(napi_env env, napi_callback_info info)
157 {
158 MediaTrace trace("AVRecorder::JsCreateAVRecorder");
159 napi_value result = nullptr;
160 napi_get_undefined(env, &result);
161
162 // get args
163 napi_value jsThis = nullptr;
164 napi_value args[1] = { nullptr };
165 size_t argCount = 1;
166 napi_status status = napi_get_cb_info(env, info, &argCount, args, &jsThis, nullptr);
167 CHECK_AND_RETURN_RET_LOG(status == napi_ok, result, "failed to napi_get_cb_info");
168
169 std::unique_ptr<AVRecorderAsyncContext> asyncCtx = std::make_unique<AVRecorderAsyncContext>(env);
170 CHECK_AND_RETURN_RET_LOG(asyncCtx != nullptr, result, "failed to get AsyncContext");
171
172 asyncCtx->callbackRef = CommonNapi::CreateReference(env, args[0]);
173 asyncCtx->deferred = CommonNapi::CreatePromise(env, asyncCtx->callbackRef, result);
174 asyncCtx->JsResult = std::make_unique<MediaJsResultInstance>(constructor_);
175 asyncCtx->ctorFlag = true;
176
177 napi_value resource = nullptr;
178 napi_create_string_utf8(env, "JsCreateAVRecorder", NAPI_AUTO_LENGTH, &resource);
179 NAPI_CALL(env, napi_create_async_work(env, nullptr, resource, [](napi_env env, void* data) {},
180 MediaAsyncContext::CompleteCallback, static_cast<void *>(asyncCtx.get()), &asyncCtx->work));
181 NAPI_CALL(env, napi_queue_async_work(env, asyncCtx->work));
182 asyncCtx.release();
183
184 MEDIA_LOGI("JsCreateAVRecorder success");
185 return result;
186 }
187
GetRetInfo(int32_t errCode,const std::string & operate,const std::string & param,const std::string & add="")188 RetInfo GetRetInfo(int32_t errCode, const std::string &operate, const std::string ¶m, const std::string &add = "")
189 {
190 MEDIA_LOGE("failed to %{public}s, param %{public}s, errCode = %{public}d", operate.c_str(), param.c_str(), errCode);
191 MediaServiceExtErrCodeAPI9 err = MSErrorToExtErrorAPI9(static_cast<MediaServiceErrCode>(errCode));
192 if (errCode == MSERR_UNSUPPORT_VID_PARAMS) {
193 return RetInfo(err, "The video parameter is not supported. Please check the type and range.");
194 }
195
196 if (errCode == MSERR_UNSUPPORT_AUD_PARAMS) {
197 return RetInfo(err, "The audio parameter is not supported. Please check the type and range.");
198 }
199
200 std::string message;
201 if (err == MSERR_EXT_API9_INVALID_PARAMETER) {
202 message = MSExtErrorAPI9ToString(err, param, "") + add;
203 } else {
204 message = MSExtErrorAPI9ToString(err, operate, "") + add;
205 }
206
207 MEDIA_LOGE("errCode: %{public}d, errMsg: %{public}s", err, message.c_str());
208 return RetInfo(err, message);
209 }
210
JsPrepare(napi_env env,napi_callback_info info)211 napi_value AVRecorderNapi::JsPrepare(napi_env env, napi_callback_info info)
212 {
213 MediaTrace trace("AVRecorder::JsPrepare");
214 const std::string &opt = AVRecordergOpt::PREPARE;
215 MEDIA_LOGI("Js %{public}s Start", opt.c_str());
216
217 const int32_t maxParam = 2; // config + callbackRef
218 size_t argCount = maxParam;
219 napi_value args[maxParam] = { nullptr };
220
221 napi_value result = nullptr;
222 napi_get_undefined(env, &result);
223
224 auto asyncCtx = std::make_unique<AVRecorderAsyncContext>(env);
225 CHECK_AND_RETURN_RET_LOG(asyncCtx != nullptr, result, "failed to get AsyncContext");
226 asyncCtx->napi = AVRecorderNapi::GetJsInstanceAndArgs(env, info, argCount, args);
227 CHECK_AND_RETURN_RET_LOG(asyncCtx->napi != nullptr, result, "failed to GetJsInstanceAndArgs");
228 CHECK_AND_RETURN_RET_LOG(asyncCtx->napi->taskQue_ != nullptr, result, "taskQue is nullptr!");
229
230 asyncCtx->callbackRef = CommonNapi::CreateReference(env, args[1]);
231 asyncCtx->deferred = CommonNapi::CreatePromise(env, asyncCtx->callbackRef, result);
232
233 if (asyncCtx->napi->CheckStateMachine(opt) == MSERR_OK) {
234 if (asyncCtx->napi->GetConfig(asyncCtx, env, args[0]) == MSERR_OK) {
235 asyncCtx->task_ = AVRecorderNapi::GetPrepareTask(asyncCtx);
236 (void)asyncCtx->napi->taskQue_->EnqueueTask(asyncCtx->task_);
237 }
238 } else {
239 asyncCtx->AVRecorderSignError(MSERR_INVALID_OPERATION, opt, "");
240 }
241
242 napi_value resource = nullptr;
243 napi_create_string_utf8(env, opt.c_str(), NAPI_AUTO_LENGTH, &resource);
244 NAPI_CALL(env, napi_create_async_work(env, nullptr, resource, [](napi_env env, void* data) {
245 AVRecorderAsyncContext* asyncCtx = reinterpret_cast<AVRecorderAsyncContext *>(data);
246 CHECK_AND_RETURN_LOG(asyncCtx != nullptr, "asyncCtx is nullptr!");
247
248 if (asyncCtx->task_) {
249 auto result = asyncCtx->task_->GetResult();
250 if (result.Value().first != MSERR_EXT_API9_OK) {
251 asyncCtx->SignError(result.Value().first, result.Value().second);
252 }
253 }
254 MEDIA_LOGI("The js thread of prepare finishes execution and returns");
255 }, MediaAsyncContext::CompleteCallback, static_cast<void *>(asyncCtx.get()), &asyncCtx->work));
256 NAPI_CALL(env, napi_queue_async_work(env, asyncCtx->work));
257 asyncCtx.release();
258
259 MEDIA_LOGI("Js %{public}s End", opt.c_str());
260 return result;
261 }
262
GetPrepareTask(std::unique_ptr<AVRecorderAsyncContext> & asyncCtx)263 std::shared_ptr<TaskHandler<RetInfo>> AVRecorderNapi::GetPrepareTask(std::unique_ptr<AVRecorderAsyncContext> &asyncCtx)
264 {
265 return std::make_shared<TaskHandler<RetInfo>>([napi = asyncCtx->napi, config = asyncCtx->config_]() {
266 const std::string &option = AVRecordergOpt::PREPARE;
267 MEDIA_LOGI("%{public}s Start", option.c_str());
268 CHECK_AND_RETURN_RET(napi != nullptr && napi->recorder_ != nullptr && config != nullptr,
269 GetRetInfo(MSERR_INVALID_OPERATION, option, ""));
270
271 CHECK_AND_RETURN_RET(napi->CheckStateMachine(option) == MSERR_OK,
272 GetRetInfo(MSERR_INVALID_OPERATION, option, ""));
273
274 RetInfo retinfo = napi->Configure(config);
275 CHECK_AND_RETURN_RET(retinfo.first == MSERR_OK, ((void)napi->recorder_->Reset(), retinfo));
276
277 int32_t ret = napi->recorder_->Prepare();
278 CHECK_AND_RETURN_RET(ret == MSERR_OK, ((void)napi->recorder_->Reset(), GetRetInfo(ret, "Prepare", "")));
279
280 napi->RemoveSurface();
281 napi->StateCallback(AVRecorderState::STATE_PREPARED);
282 napi->getVideoInputSurface_ = false;
283 napi->withVideo_ = config->withVideo;
284 MEDIA_LOGI("%{public}s End", option.c_str());
285 return RetInfo(MSERR_EXT_API9_OK, "");
286 });
287 }
288
JsGetInputSurface(napi_env env,napi_callback_info info)289 napi_value AVRecorderNapi::JsGetInputSurface(napi_env env, napi_callback_info info)
290 {
291 MediaTrace trace("AVRecorder::JsGetInputSurface");
292 return ExecuteByPromise(env, info, AVRecordergOpt::GETINPUTSURFACE);
293 }
294
JsStart(napi_env env,napi_callback_info info)295 napi_value AVRecorderNapi::JsStart(napi_env env, napi_callback_info info)
296 {
297 MediaTrace trace("AVRecorder::JsStart");
298 return ExecuteByPromise(env, info, AVRecordergOpt::START);
299 }
300
JsPause(napi_env env,napi_callback_info info)301 napi_value AVRecorderNapi::JsPause(napi_env env, napi_callback_info info)
302 {
303 MediaTrace trace("AVRecorder::JsPause");
304 return ExecuteByPromise(env, info, AVRecordergOpt::PAUSE);
305 }
306
JsResume(napi_env env,napi_callback_info info)307 napi_value AVRecorderNapi::JsResume(napi_env env, napi_callback_info info)
308 {
309 MediaTrace trace("AVRecorder::JsResume");
310 return ExecuteByPromise(env, info, AVRecordergOpt::RESUME);
311 }
312
JsStop(napi_env env,napi_callback_info info)313 napi_value AVRecorderNapi::JsStop(napi_env env, napi_callback_info info)
314 {
315 MediaTrace trace("AVRecorder::JsStop");
316 return ExecuteByPromise(env, info, AVRecordergOpt::STOP);
317 }
318
JsReset(napi_env env,napi_callback_info info)319 napi_value AVRecorderNapi::JsReset(napi_env env, napi_callback_info info)
320 {
321 MediaTrace trace("AVRecorder::JsReset");
322 return ExecuteByPromise(env, info, AVRecordergOpt::RESET);
323 }
324
JsRelease(napi_env env,napi_callback_info info)325 napi_value AVRecorderNapi::JsRelease(napi_env env, napi_callback_info info)
326 {
327 MediaTrace trace("AVRecorder::JsRelease");
328 return ExecuteByPromise(env, info, AVRecordergOpt::RELEASE);
329 }
330
JsSetEventCallback(napi_env env,napi_callback_info info)331 napi_value AVRecorderNapi::JsSetEventCallback(napi_env env, napi_callback_info info)
332 {
333 MediaTrace trace("AVRecorder::JsSetEventCallback");
334 MEDIA_LOGI("JsSetEventCallback Start");
335 napi_value result = nullptr;
336 napi_get_undefined(env, &result);
337
338 size_t argCount = 2;
339 napi_value args[2] = { nullptr, nullptr };
340 AVRecorderNapi *recorderNapi = AVRecorderNapi::GetJsInstanceAndArgs(env, info, argCount, args);
341 CHECK_AND_RETURN_RET_LOG(recorderNapi != nullptr, result, "Failed to retrieve instance");
342
343 napi_valuetype valueType0 = napi_undefined;
344 napi_valuetype valueType1 = napi_undefined;
345 if (napi_typeof(env, args[0], &valueType0) != napi_ok || valueType0 != napi_string ||
346 napi_typeof(env, args[1], &valueType1) != napi_ok || valueType1 != napi_function) {
347 recorderNapi->ErrorCallback(MSERR_INVALID_VAL, "SetEventCallback");
348 return result;
349 }
350
351 std::string callbackName = CommonNapi::GetStringArgument(env, args[0]);
352 if (callbackName != AVRecorderEvent::EVENT_ERROR && callbackName != AVRecorderEvent::EVENT_STATE_CHANGE) {
353 recorderNapi->ErrorCallback(MSERR_INVALID_VAL, "SetEventCallback");
354 return result;
355 }
356
357 napi_ref ref = nullptr;
358 napi_status status = napi_create_reference(env, args[1], 1, &ref);
359 CHECK_AND_RETURN_RET_LOG(status == napi_ok && ref != nullptr, result, "failed to create reference!");
360
361 std::shared_ptr<AutoRef> autoRef = std::make_shared<AutoRef>(env, ref);
362 recorderNapi->SetCallbackReference(callbackName, autoRef);
363
364 MEDIA_LOGI("JsSetEventCallback End");
365 return result;
366 }
367
JsCancelEventCallback(napi_env env,napi_callback_info info)368 napi_value AVRecorderNapi::JsCancelEventCallback(napi_env env, napi_callback_info info)
369 {
370 MediaTrace trace("AVRecorder::JsCancelEventCallback");
371 MEDIA_LOGI("JsCancelEventCallback Start");
372 napi_value result = nullptr;
373 napi_get_undefined(env, &result);
374
375 size_t argCount = 1;
376 napi_value args[1] = { nullptr };
377 AVRecorderNapi *recorderNapi = AVRecorderNapi::GetJsInstanceAndArgs(env, info, argCount, args);
378 CHECK_AND_RETURN_RET_LOG(recorderNapi != nullptr, result, "Failed to retrieve instance");
379
380 napi_valuetype valueType0 = napi_undefined;
381 if (napi_typeof(env, args[0], &valueType0) != napi_ok || valueType0 != napi_string) {
382 recorderNapi->ErrorCallback(MSERR_INVALID_VAL, "CancelEventCallback");
383 return result;
384 }
385
386 std::string callbackName = CommonNapi::GetStringArgument(env, args[0]);
387 if (callbackName != AVRecorderEvent::EVENT_ERROR && callbackName != AVRecorderEvent::EVENT_STATE_CHANGE) {
388 recorderNapi->ErrorCallback(MSERR_INVALID_VAL, "CancelEventCallback");
389 return result;
390 }
391
392 recorderNapi->CancelCallbackReference(callbackName);
393
394 MEDIA_LOGI("JsCancelEventCallback End");
395 return result;
396 }
397
JsGetState(napi_env env,napi_callback_info info)398 napi_value AVRecorderNapi::JsGetState(napi_env env, napi_callback_info info)
399 {
400 MediaTrace trace("AVRecorder::JsGetState");
401 napi_value result = nullptr;
402 napi_get_undefined(env, &result);
403
404 size_t argCount = 0;
405 AVRecorderNapi *recorderNapi = AVRecorderNapi::GetJsInstanceAndArgs(env, info, argCount, nullptr);
406 CHECK_AND_RETURN_RET_LOG(recorderNapi != nullptr, result, "failed to GetJsInstance");
407
408 auto napiCb = std::static_pointer_cast<AVRecorderCallback>(recorderNapi->recorderCb_);
409 CHECK_AND_RETURN_RET_LOG(napiCb != nullptr, result, "napiCb is nullptr!");
410 std::string curState = napiCb->GetState();
411 MEDIA_LOGI("GetState success, State: %{public}s", curState.c_str());
412
413 napi_value jsResult = nullptr;
414 napi_status status = napi_create_string_utf8(env, curState.c_str(), NAPI_AUTO_LENGTH, &jsResult);
415 CHECK_AND_RETURN_RET_LOG(status == napi_ok, result, "napi_create_string_utf8 error");
416 return jsResult;
417 }
418
GetJsInstanceAndArgs(napi_env env,napi_callback_info info,size_t & argCount,napi_value * args)419 AVRecorderNapi* AVRecorderNapi::GetJsInstanceAndArgs(napi_env env, napi_callback_info info,
420 size_t &argCount, napi_value *args)
421 {
422 napi_value jsThis = nullptr;
423 napi_status status = napi_get_cb_info(env, info, &argCount, args, &jsThis, nullptr);
424 CHECK_AND_RETURN_RET_LOG(status == napi_ok && jsThis != nullptr, nullptr, "failed to napi_get_cb_info");
425 MEDIA_LOGI("argCount:%{public}zu", argCount);
426
427 AVRecorderNapi *recorderNapi = nullptr;
428 status = napi_unwrap(env, jsThis, reinterpret_cast<void **>(&recorderNapi));
429 CHECK_AND_RETURN_RET_LOG(status == napi_ok && recorderNapi != nullptr, nullptr, "failed to retrieve instance");
430
431 return recorderNapi;
432 }
433
GetPromiseTask(AVRecorderNapi * avnapi,const std::string & opt)434 std::shared_ptr<TaskHandler<RetInfo>> AVRecorderNapi::GetPromiseTask(AVRecorderNapi *avnapi, const std::string &opt)
435 {
436 return std::make_shared<TaskHandler<RetInfo>>([napi = avnapi, option = opt]() {
437 MEDIA_LOGI("%{public}s Start", option.c_str());
438 CHECK_AND_RETURN_RET(napi != nullptr && napi->recorder_ != nullptr,
439 GetRetInfo(MSERR_INVALID_OPERATION, option, ""));
440
441 CHECK_AND_RETURN_RET(napi->CheckStateMachine(option) == MSERR_OK,
442 GetRetInfo(MSERR_INVALID_OPERATION, option, ""));
443
444 CHECK_AND_RETURN_RET(napi->CheckRepeatOperation(option) == MSERR_OK,
445 RetInfo(MSERR_EXT_API9_OK, ""));
446
447 RetInfo ret(MSERR_EXT_API9_OPERATE_NOT_PERMIT, "");
448 auto itFunc = taskQFuncs_.find(option);
449 CHECK_AND_RETURN_RET_LOG(itFunc != taskQFuncs_.end(), ret, "%{public}s not found in map!", option.c_str());
450 auto memberFunc = itFunc->second;
451 CHECK_AND_RETURN_RET_LOG(memberFunc != nullptr, ret, "memberFunc is nullptr!");
452 ret = (napi->*memberFunc)();
453
454 MEDIA_LOGI("%{public}s End", option.c_str());
455 return ret;
456 });
457 }
458
ExecuteByPromise(napi_env env,napi_callback_info info,const std::string & opt)459 napi_value AVRecorderNapi::ExecuteByPromise(napi_env env, napi_callback_info info, const std::string &opt)
460 {
461 MEDIA_LOGI("Js %{public}s Start", opt.c_str());
462 napi_value result = nullptr;
463 napi_get_undefined(env, &result);
464 size_t argCount = 1; // Only callbackRef parameter
465 napi_value args[1] = { nullptr }; // Only callbackRef parameter
466
467 auto asyncCtx = std::make_unique<AVRecorderAsyncContext>(env);
468 CHECK_AND_RETURN_RET_LOG(asyncCtx != nullptr, result, "failed to get AsyncContext");
469 asyncCtx->napi = AVRecorderNapi::GetJsInstanceAndArgs(env, info, argCount, args);
470 CHECK_AND_RETURN_RET_LOG(asyncCtx->napi != nullptr, result, "failed to GetJsInstanceAndArgs");
471 CHECK_AND_RETURN_RET_LOG(asyncCtx->napi->taskQue_ != nullptr, result, "taskQue is nullptr!");
472
473 asyncCtx->callbackRef = CommonNapi::CreateReference(env, args[0]);
474 asyncCtx->deferred = CommonNapi::CreatePromise(env, asyncCtx->callbackRef, result);
475
476 if (asyncCtx->napi->CheckStateMachine(opt) == MSERR_OK) {
477 asyncCtx->task_ = AVRecorderNapi::GetPromiseTask(asyncCtx->napi, opt);
478 (void)asyncCtx->napi->taskQue_->EnqueueTask(asyncCtx->task_);
479 asyncCtx->opt_ = opt;
480 } else {
481 asyncCtx->AVRecorderSignError(MSERR_INVALID_OPERATION, opt, "");
482 }
483
484 napi_value resource = nullptr;
485 napi_create_string_utf8(env, opt.c_str(), NAPI_AUTO_LENGTH, &resource);
486 NAPI_CALL(env, napi_create_async_work(env, nullptr, resource, [](napi_env env, void* data) {
487 AVRecorderAsyncContext* asyncCtx = reinterpret_cast<AVRecorderAsyncContext *>(data);
488 CHECK_AND_RETURN_LOG(asyncCtx != nullptr, "asyncCtx is nullptr!");
489
490 if (asyncCtx->task_) {
491 auto result = asyncCtx->task_->GetResult();
492 if (result.Value().first != MSERR_EXT_API9_OK) {
493 asyncCtx->SignError(result.Value().first, result.Value().second);
494 }
495
496 if ((result.Value().first == MSERR_EXT_API9_OK) && (asyncCtx->opt_ == AVRecordergOpt::GETINPUTSURFACE)) {
497 asyncCtx->JsResult = std::make_unique<MediaJsResultString>(result.Value().second);
498 }
499 }
500 MEDIA_LOGI("The js thread of %{public}s finishes execution and returns", asyncCtx->opt_.c_str());
501 }, MediaAsyncContext::CompleteCallback, static_cast<void *>(asyncCtx.get()), &asyncCtx->work));
502 NAPI_CALL(env, napi_queue_async_work(env, asyncCtx->work));
503 asyncCtx.release();
504
505 MEDIA_LOGI("Js %{public}s End", opt.c_str());
506 return result;
507 }
508
GetInputSurface()509 RetInfo AVRecorderNapi::GetInputSurface()
510 {
511 CHECK_AND_RETURN_RET_LOG(withVideo_, GetRetInfo(MSERR_INVALID_OPERATION, "GetInputSurface", "",
512 "The VideoSourceType is not configured. Please do not call getInputSurface"), "No video recording");
513
514 if (surface_ == nullptr) {
515 surface_ = recorder_->GetSurface(videoSourceID_);
516 CHECK_AND_RETURN_RET_LOG(surface_ != nullptr,
517 GetRetInfo(MSERR_INVALID_OPERATION, "GetInputSurface", ""), "failed to GetSurface");
518
519 SurfaceError error = SurfaceUtils::GetInstance()->Add(surface_->GetUniqueId(), surface_);
520 CHECK_AND_RETURN_RET_LOG(error == SURFACE_ERROR_OK,
521 GetRetInfo(MSERR_INVALID_OPERATION, "GetInputSurface", ""), "failed to AddSurface");
522 }
523
524 auto surfaceId = std::to_string(surface_->GetUniqueId());
525 getVideoInputSurface_ = true;
526 return RetInfo(MSERR_EXT_API9_OK, surfaceId);
527 }
528
Start()529 RetInfo AVRecorderNapi::Start()
530 {
531 if (withVideo_ && !getVideoInputSurface_) {
532 return GetRetInfo(MSERR_INVALID_OPERATION, "Start", "",
533 " Please get the video input surface through GetInputSurface first!");
534 }
535
536 int32_t ret = recorder_->Start();
537 CHECK_AND_RETURN_RET(ret == MSERR_OK, GetRetInfo(ret, "Start", ""));
538 StateCallback(AVRecorderState::STATE_STARTED);
539 return RetInfo(MSERR_EXT_API9_OK, "");
540 }
541
Pause()542 RetInfo AVRecorderNapi::Pause()
543 {
544 int32_t ret = recorder_->Pause();
545 CHECK_AND_RETURN_RET(ret == MSERR_OK, GetRetInfo(ret, "Pause", ""));
546 StateCallback(AVRecorderState::STATE_PAUSED);
547 return RetInfo(MSERR_EXT_API9_OK, "");
548 }
549
Resume()550 RetInfo AVRecorderNapi::Resume()
551 {
552 int32_t ret = recorder_->Resume();
553 CHECK_AND_RETURN_RET(ret == MSERR_OK, GetRetInfo(ret, "Resume", ""));
554 StateCallback(AVRecorderState::STATE_STARTED);
555 return RetInfo(MSERR_EXT_API9_OK, "");
556 }
557
Stop()558 RetInfo AVRecorderNapi::Stop()
559 {
560 int32_t ret = recorder_->Stop(false);
561 CHECK_AND_RETURN_RET(ret == MSERR_OK, GetRetInfo(ret, "Stop", ""));
562 StateCallback(AVRecorderState::STATE_STOPPED);
563 return RetInfo(MSERR_EXT_API9_OK, "");
564 }
565
Reset()566 RetInfo AVRecorderNapi::Reset()
567 {
568 RemoveSurface();
569 int32_t ret = recorder_->Reset();
570 CHECK_AND_RETURN_RET(ret == MSERR_OK, GetRetInfo(ret, "Reset", ""));
571
572 StateCallback(AVRecorderState::STATE_IDLE);
573 return RetInfo(MSERR_EXT_API9_OK, "");
574 }
575
Release()576 RetInfo AVRecorderNapi::Release()
577 {
578 RemoveSurface();
579 int32_t ret = recorder_->Release();
580 CHECK_AND_RETURN_RET(ret == MSERR_OK, GetRetInfo(ret, "Release", ""));
581
582 StateCallback(AVRecorderState::STATE_RELEASED);
583 CancelCallback();
584 return RetInfo(MSERR_EXT_API9_OK, "");
585 }
586
CheckStateMachine(const std::string & opt)587 int32_t AVRecorderNapi::CheckStateMachine(const std::string &opt)
588 {
589 const std::map<std::string, std::vector<std::string>> stateCtrl = {
590 {AVRecorderState::STATE_IDLE, {
591 AVRecordergOpt::PREPARE,
592 AVRecordergOpt::RESET,
593 AVRecordergOpt::RELEASE
594 }},
595 {AVRecorderState::STATE_PREPARED, {
596 AVRecordergOpt::GETINPUTSURFACE,
597 AVRecordergOpt::START,
598 AVRecordergOpt::RESET,
599 AVRecordergOpt::RELEASE
600 }},
601 {AVRecorderState::STATE_STARTED, {
602 AVRecordergOpt::START,
603 AVRecordergOpt::RESUME,
604 AVRecordergOpt::PAUSE,
605 AVRecordergOpt::STOP,
606 AVRecordergOpt::RESET,
607 AVRecordergOpt::RELEASE
608 }},
609 {AVRecorderState::STATE_PAUSED, {
610 AVRecordergOpt::PAUSE,
611 AVRecordergOpt::RESUME,
612 AVRecordergOpt::STOP,
613 AVRecordergOpt::RESET,
614 AVRecordergOpt::RELEASE
615 }},
616 {AVRecorderState::STATE_STOPPED, {
617 AVRecordergOpt::STOP,
618 AVRecordergOpt::PREPARE,
619 AVRecordergOpt::RESET,
620 AVRecordergOpt::RELEASE
621 }},
622 {AVRecorderState::STATE_RELEASED, {
623 AVRecordergOpt::RELEASE
624 }},
625 {AVRecorderState::STATE_ERROR, {
626 AVRecordergOpt::RESET,
627 AVRecordergOpt::RELEASE
628 }},
629 };
630
631 auto napiCb = std::static_pointer_cast<AVRecorderCallback>(recorderCb_);
632 CHECK_AND_RETURN_RET_LOG(napiCb != nullptr, MSERR_INVALID_OPERATION, "napiCb is nullptr!");
633
634 std::string curState = napiCb->GetState();
635 std::vector<std::string> allowedOpt = stateCtrl.at(curState);
636 if (find(allowedOpt.begin(), allowedOpt.end(), opt) == allowedOpt.end()) {
637 MEDIA_LOGE("The %{public}s operation is not allowed in the %{public}s state!", opt.c_str(), curState.c_str());
638 return MSERR_INVALID_OPERATION;
639 }
640
641 return MSERR_OK;
642 }
643
CheckRepeatOperation(const std::string & opt)644 int32_t AVRecorderNapi::CheckRepeatOperation(const std::string &opt)
645 {
646 const std::map<std::string, std::vector<std::string>> stateCtrl = {
647 {AVRecorderState::STATE_IDLE, {
648 AVRecordergOpt::RESET
649 }},
650 {AVRecorderState::STATE_PREPARED, {}},
651 {AVRecorderState::STATE_STARTED, {
652 AVRecordergOpt::START,
653 AVRecordergOpt::RESUME
654 }},
655 {AVRecorderState::STATE_PAUSED, {
656 AVRecordergOpt::PAUSE
657 }},
658 {AVRecorderState::STATE_STOPPED, {
659 AVRecordergOpt::STOP
660 }},
661 {AVRecorderState::STATE_RELEASED, {
662 AVRecordergOpt::RELEASE
663 }},
664 {AVRecorderState::STATE_ERROR, {}},
665 };
666
667 auto napiCb = std::static_pointer_cast<AVRecorderCallback>(recorderCb_);
668 CHECK_AND_RETURN_RET_LOG(napiCb != nullptr, MSERR_INVALID_OPERATION, "napiCb is nullptr!");
669
670 std::string curState = napiCb->GetState();
671 std::vector<std::string> repeatOpt = stateCtrl.at(curState);
672 if (find(repeatOpt.begin(), repeatOpt.end(), opt) != repeatOpt.end()) {
673 MEDIA_LOGI("Current state is %{public}s. Please do not call %{public}s again!", curState.c_str(), opt.c_str());
674 return MSERR_INVALID_OPERATION;
675 }
676
677 return MSERR_OK;
678 }
679
GetAudioCodecFormat(const std::string & mime,AudioCodecFormat & codecFormat)680 int32_t AVRecorderNapi::GetAudioCodecFormat(const std::string &mime, AudioCodecFormat &codecFormat)
681 {
682 MEDIA_LOGI("mime %{public}s", mime.c_str());
683 const std::map<std::string_view, AudioCodecFormat> mimeStrToCodecFormat = {
684 { CodecMimeType::AUDIO_AAC, AudioCodecFormat::AAC_LC },
685 };
686
687 auto iter = mimeStrToCodecFormat.find(mime);
688 if (iter != mimeStrToCodecFormat.end()) {
689 codecFormat = iter->second;
690 return MSERR_OK;
691 }
692 return MSERR_INVALID_VAL;
693 }
694
GetVideoCodecFormat(const std::string & mime,VideoCodecFormat & codecFormat)695 int32_t AVRecorderNapi::GetVideoCodecFormat(const std::string &mime, VideoCodecFormat &codecFormat)
696 {
697 MEDIA_LOGI("mime %{public}s", mime.c_str());
698 const std::map<std::string_view, VideoCodecFormat> mimeStrToCodecFormat = {
699 { CodecMimeType::VIDEO_AVC, VideoCodecFormat::H264 },
700 { CodecMimeType::VIDEO_MPEG4, VideoCodecFormat::MPEG4 },
701 };
702
703 auto iter = mimeStrToCodecFormat.find(mime);
704 if (iter != mimeStrToCodecFormat.end()) {
705 codecFormat = iter->second;
706 return MSERR_OK;
707 }
708 return MSERR_INVALID_VAL;
709 }
710
GetOutputFormat(const std::string & extension,OutputFormatType & type)711 int32_t AVRecorderNapi::GetOutputFormat(const std::string &extension, OutputFormatType &type)
712 {
713 MEDIA_LOGI("mime %{public}s", extension.c_str());
714 const std::map<std::string, OutputFormatType> extensionToOutputFormat = {
715 { "mp4", OutputFormatType::FORMAT_MPEG_4 },
716 { "m4a", OutputFormatType::FORMAT_M4A },
717 };
718
719 auto iter = extensionToOutputFormat.find(extension);
720 if (iter != extensionToOutputFormat.end()) {
721 type = iter->second;
722 return MSERR_OK;
723 }
724 return MSERR_INVALID_VAL;
725 }
726
GetSourceType(std::unique_ptr<AVRecorderAsyncContext> & asyncCtx,napi_env env,napi_value args)727 int32_t AVRecorderNapi::GetSourceType(std::unique_ptr<AVRecorderAsyncContext> &asyncCtx, napi_env env, napi_value args)
728 {
729 std::shared_ptr<AVRecorderConfig> config = asyncCtx->config_;
730 int32_t audioSource = AUDIO_SOURCE_INVALID;
731 int32_t videoSource = VIDEO_SOURCE_BUTT;
732
733 bool getValue = false;
734 int32_t ret = AVRecorderNapi::GetPropertyInt32(env, args, "audioSourceType", audioSource, getValue);
735 CHECK_AND_RETURN_RET(ret == MSERR_OK,
736 (asyncCtx->AVRecorderSignError(ret, "getaudioSourceType", "audioSourceType"), ret));
737 if (getValue) {
738 config->audioSourceType = static_cast<AudioSourceType>(audioSource);
739 config->withAudio = true;
740 MEDIA_LOGI("audioSource Type %{public}d!", audioSource);
741 }
742
743 ret = AVRecorderNapi::GetPropertyInt32(env, args, "videoSourceType", videoSource, getValue);
744 CHECK_AND_RETURN_RET(ret == MSERR_OK,
745 (asyncCtx->AVRecorderSignError(ret, "getvideoSourceType", "videoSourceType"), ret));
746 if (getValue) {
747 config->videoSourceType = static_cast<VideoSourceType>(videoSource);
748 config->withVideo = true;
749 MEDIA_LOGI("videoSource Type %{public}d!", videoSource);
750 }
751
752 CHECK_AND_RETURN_RET(config->withAudio || config->withVideo,
753 (asyncCtx->AVRecorderSignError(MSERR_INVALID_VAL, "getsourcetype", "SourceType"), MSERR_INVALID_VAL));
754
755 return MSERR_OK;
756 }
757
GetProfile(std::unique_ptr<AVRecorderAsyncContext> & asyncCtx,napi_env env,napi_value args)758 int32_t AVRecorderNapi::GetProfile(std::unique_ptr<AVRecorderAsyncContext> &asyncCtx, napi_env env, napi_value args)
759 {
760 napi_value item = nullptr;
761 napi_get_named_property(env, args, "profile", &item);
762 CHECK_AND_RETURN_RET_LOG(item != nullptr, MSERR_INVALID_VAL, "get profile error");
763
764 AVRecorderProfile &profile = asyncCtx->config_->profile;
765
766 int32_t ret = MSERR_OK;
767 if (asyncCtx->config_->withAudio) {
768 std::string audioCodec = CommonNapi::GetPropertyString(env, item, "audioCodec");
769 ret = AVRecorderNapi::GetAudioCodecFormat(audioCodec, profile.audioCodecFormat);
770 CHECK_AND_RETURN_RET(ret == MSERR_OK,
771 (asyncCtx->AVRecorderSignError(ret, "GetAudioCodecFormat", "audioCodecFormat"), ret));
772
773 ret = MSERR_INVALID_VAL;
774 CHECK_AND_RETURN_RET(CommonNapi::GetPropertyInt32(env, item, "audioBitrate", profile.audioBitrate),
775 (asyncCtx->AVRecorderSignError(ret, "GetaudioBitrate", "audioBitrate"), ret));
776 CHECK_AND_RETURN_RET(CommonNapi::GetPropertyInt32(env, item, "audioChannels", profile.audioChannels),
777 (asyncCtx->AVRecorderSignError(ret, "GetaudioChannels", "audioChannels"), ret));
778 CHECK_AND_RETURN_RET(CommonNapi::GetPropertyInt32(env, item, "audioSampleRate", profile.auidoSampleRate),
779 (asyncCtx->AVRecorderSignError(ret, "GetauidoSampleRate", "auidoSampleRate"), ret));
780
781 MEDIA_LOGI("audioBitrate %{public}d, audioChannels %{public}d, audioCodecFormat %{public}d,"
782 " audioSampleRate %{public}d!", profile.audioBitrate, profile.audioChannels,
783 profile.audioCodecFormat, profile.auidoSampleRate);
784 }
785
786 if (asyncCtx->config_->withVideo) {
787 std::string videoCodec = CommonNapi::GetPropertyString(env, item, "videoCodec");
788 ret = AVRecorderNapi::GetVideoCodecFormat(videoCodec, profile.videoCodecFormat);
789 CHECK_AND_RETURN_RET(ret == MSERR_OK,
790 (asyncCtx->AVRecorderSignError(ret, "GetVideoCodecFormat", "videoCodecFormat"), ret));
791
792 ret = MSERR_INVALID_VAL;
793 CHECK_AND_RETURN_RET(CommonNapi::GetPropertyInt32(env, item, "videoBitrate", profile.videoBitrate),
794 (asyncCtx->AVRecorderSignError(ret, "GetvideoBitrate", "videoBitrate"), ret));
795 CHECK_AND_RETURN_RET(CommonNapi::GetPropertyInt32(env, item, "videoFrameWidth", profile.videoFrameWidth),
796 (asyncCtx->AVRecorderSignError(ret, "GetvideoFrameWidth", "videoFrameWidth"), ret));
797 CHECK_AND_RETURN_RET(CommonNapi::GetPropertyInt32(env, item, "videoFrameHeight", profile.videoFrameHeight),
798 (asyncCtx->AVRecorderSignError(ret, "GetvideoFrameHeight", "videoFrameHeight"), ret));
799 CHECK_AND_RETURN_RET(CommonNapi::GetPropertyInt32(env, item, "videoFrameRate", profile.videoFrameRate),
800 (asyncCtx->AVRecorderSignError(ret, "GetvideoFrameRate", "videoFrameRate"), ret));
801
802 MEDIA_LOGI("videoBitrate %{public}d, videoCodecFormat %{public}d, videoFrameWidth %{public}d,"
803 " videoFrameHeight %{public}d, videoFrameRate %{public}d",
804 profile.videoBitrate, profile.videoCodecFormat, profile.videoFrameWidth,
805 profile.videoFrameHeight, profile.videoFrameRate);
806 }
807
808 std::string outputFile = CommonNapi::GetPropertyString(env, item, "fileFormat");
809 ret = AVRecorderNapi::GetOutputFormat(outputFile, profile.fileFormat);
810 CHECK_AND_RETURN_RET(ret == MSERR_OK,
811 (asyncCtx->AVRecorderSignError(ret, "GetOutputFormat", "fileFormat"), ret));
812 MEDIA_LOGI("fileFormat %{public}d", profile.fileFormat);
813
814 return MSERR_OK;
815 }
816
GetConfig(std::unique_ptr<AVRecorderAsyncContext> & asyncCtx,napi_env env,napi_value args)817 int32_t AVRecorderNapi::GetConfig(std::unique_ptr<AVRecorderAsyncContext> &asyncCtx, napi_env env, napi_value args)
818 {
819 napi_valuetype valueType = napi_undefined;
820 if (args == nullptr || napi_typeof(env, args, &valueType) != napi_ok || valueType != napi_object) {
821 asyncCtx->AVRecorderSignError(MSERR_INVALID_VAL, "GetConfig", "AVRecorderConfig");
822 return MSERR_INVALID_VAL;
823 }
824
825 asyncCtx->config_ = std::make_shared<AVRecorderConfig>();
826 CHECK_AND_RETURN_RET(asyncCtx->config_,
827 (asyncCtx->AVRecorderSignError(MSERR_NO_MEMORY, "AVRecorderConfig", "AVRecorderConfig"), MSERR_NO_MEMORY));
828
829 std::shared_ptr<AVRecorderConfig> config = asyncCtx->config_;
830
831 int32_t ret = GetSourceType(asyncCtx, env, args);
832 CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, ret, "failed to GetSourceType");
833
834 ret = GetProfile(asyncCtx, env, args);
835 CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, ret, "failed to GetProfile");
836
837 config->url = CommonNapi::GetPropertyString(env, args, "url");
838 MEDIA_LOGI("url %{public}s!", config->url.c_str());
839 CHECK_AND_RETURN_RET(config->url != "",
840 (asyncCtx->AVRecorderSignError(MSERR_INVALID_VAL, "geturl", "url"), MSERR_INVALID_VAL));
841
842 bool getValue = false;
843 ret = AVRecorderNapi::GetPropertyInt32(env, args, "rotation", config->rotation, getValue);
844 CHECK_AND_RETURN_RET(ret == MSERR_OK,
845 (asyncCtx->AVRecorderSignError(ret, "getrotation", "rotation"), ret));
846 MEDIA_LOGI("rotation %{public}d!", config->rotation);
847 CHECK_AND_RETURN_RET((config->rotation == VIDEO_ROTATION_0 || config->rotation == VIDEO_ROTATION_90 ||
848 config->rotation == VIDEO_ROTATION_180 || config->rotation == VIDEO_ROTATION_270),
849 (asyncCtx->AVRecorderSignError(MSERR_INVALID_VAL, "getrotation", "rotation"), MSERR_INVALID_VAL));
850
851 napi_value geoLocation = nullptr;
852 napi_get_named_property(env, args, "location", &geoLocation);
853 double tempLatitude = 0;
854 double tempLongitude = 0;
855 (void)CommonNapi::GetPropertyDouble(env, geoLocation, "latitude", tempLatitude);
856 (void)CommonNapi::GetPropertyDouble(env, geoLocation, "longitude", tempLongitude);
857 config->location.latitude = static_cast<float>(tempLatitude);
858 config->location.longitude = static_cast<float>(tempLongitude);
859
860 return MSERR_OK;
861 }
862
SetProfile(std::shared_ptr<AVRecorderConfig> config)863 RetInfo AVRecorderNapi::SetProfile(std::shared_ptr<AVRecorderConfig> config)
864 {
865 int32_t ret;
866 AVRecorderProfile &profile = config->profile;
867
868 ret = recorder_->SetOutputFormat(profile.fileFormat);
869 CHECK_AND_RETURN_RET(ret == MSERR_OK, GetRetInfo(ret, "SetOutputFormat", "fileFormat"));
870
871 if (config->withAudio) {
872 ret = recorder_->SetAudioEncoder(audioSourceID_, profile.audioCodecFormat);
873 CHECK_AND_RETURN_RET(ret == MSERR_OK, GetRetInfo(ret, "SetAudioEncoder", "audioCodecFormat"));
874
875 ret = recorder_->SetAudioSampleRate(audioSourceID_, profile.auidoSampleRate);
876 CHECK_AND_RETURN_RET(ret == MSERR_OK, GetRetInfo(ret, "SetAudioSampleRate", "auidoSampleRate"));
877
878 ret = recorder_->SetAudioChannels(audioSourceID_, profile.audioChannels);
879 CHECK_AND_RETURN_RET(ret == MSERR_OK, GetRetInfo(ret, "SetAudioChannels", "audioChannels"));
880
881 ret = recorder_->SetAudioEncodingBitRate(audioSourceID_, profile.audioBitrate);
882 CHECK_AND_RETURN_RET(ret == MSERR_OK, GetRetInfo(ret, "SetAudioEncodingBitRate", "audioBitrate"));
883 }
884
885 if (config->withVideo) {
886 ret = recorder_->SetVideoEncoder(videoSourceID_, profile.videoCodecFormat);
887 CHECK_AND_RETURN_RET(ret == MSERR_OK, GetRetInfo(ret, "SetVideoEncoder", "videoCodecFormat"));
888
889 ret = recorder_->SetVideoSize(videoSourceID_, profile.videoFrameWidth, profile.videoFrameHeight);
890 CHECK_AND_RETURN_RET(ret == MSERR_OK, GetRetInfo(ret, "SetVideoSize", "VideoSize"));
891
892 ret = recorder_->SetVideoFrameRate(videoSourceID_, profile.videoFrameRate);
893 CHECK_AND_RETURN_RET(ret == MSERR_OK, GetRetInfo(ret, "SetVideoFrameRate", "videoFrameRate"));
894
895 ret = recorder_->SetVideoEncodingBitRate(videoSourceID_, profile.videoBitrate);
896 CHECK_AND_RETURN_RET(ret == MSERR_OK, GetRetInfo(ret, "SetVideoEncodingBitRate", "videoBitrate"));
897 }
898
899 return RetInfo(MSERR_EXT_API9_OK, "");
900 }
901
Configure(std::shared_ptr<AVRecorderConfig> config)902 RetInfo AVRecorderNapi::Configure(std::shared_ptr<AVRecorderConfig> config)
903 {
904 CHECK_AND_RETURN_RET(recorder_ != nullptr, GetRetInfo(MSERR_INVALID_OPERATION, "Configure", ""));
905 CHECK_AND_RETURN_RET(config != nullptr, GetRetInfo(MSERR_INVALID_VAL, "Configure", "config"));
906
907 int32_t ret;
908
909 if (config->withAudio) {
910 ret = recorder_->SetAudioSource(config->audioSourceType, audioSourceID_);
911 CHECK_AND_RETURN_RET(ret == MSERR_OK, GetRetInfo(ret, "SetAudioSource", "audioSourceType"));
912 }
913
914 if (config->withVideo) {
915 ret = recorder_->SetVideoSource(config->videoSourceType, videoSourceID_);
916 CHECK_AND_RETURN_RET(ret == MSERR_OK, GetRetInfo(ret, "SetVideoSource", "videoSourceType"));
917 }
918
919 RetInfo retInfo = SetProfile(config);
920 CHECK_AND_RETURN_RET_LOG(retInfo.first == MSERR_OK, retInfo, "Fail to set videoBitrate");
921
922 recorder_->SetLocation(config->location.latitude, config->location.longitude);
923
924 if (config->withVideo) {
925 recorder_->SetOrientationHint(config->rotation);
926 }
927
928 ret = MSERR_INVALID_VAL;
929 const std::string fdHead = "fd://";
930 CHECK_AND_RETURN_RET(config->url.find(fdHead) != std::string::npos, GetRetInfo(ret, "Getfd", "uri"));
931 int32_t fd = -1;
932 std::string inputFd = config->url.substr(fdHead.size());
933 CHECK_AND_RETURN_RET(StrToInt(inputFd, fd) == true && fd >= 0, GetRetInfo(ret, "Getfd", "uri"));
934
935 ret = recorder_->SetOutputFile(fd);
936 CHECK_AND_RETURN_RET(ret == MSERR_OK, GetRetInfo(ret, "SetOutputFile", "uri"));
937
938 return RetInfo(MSERR_EXT_API9_OK, "");
939 }
940
ErrorCallback(int32_t errCode,const std::string & operate,const std::string & add)941 void AVRecorderNapi::ErrorCallback(int32_t errCode, const std::string &operate, const std::string &add)
942 {
943 MEDIA_LOGE("failed to %{public}s, errCode = %{public}d", operate.c_str(), errCode);
944 CHECK_AND_RETURN_LOG(recorderCb_ != nullptr, "recorderCb_ is nullptr!");
945 auto napiCb = std::static_pointer_cast<AVRecorderCallback>(recorderCb_);
946
947 MediaServiceExtErrCodeAPI9 err = MSErrorToExtErrorAPI9(static_cast<MediaServiceErrCode>(errCode));
948 std::string msg = MSExtErrorAPI9ToString(err, operate, "") + add;
949 napiCb->SendErrorCallback(errCode, msg);
950 }
951
StateCallback(const std::string & state)952 void AVRecorderNapi::StateCallback(const std::string &state)
953 {
954 MEDIA_LOGI("Change state to %{public}s", state.c_str());
955 CHECK_AND_RETURN_LOG(recorderCb_ != nullptr, "recorderCb_ is nullptr!");
956 auto napiCb = std::static_pointer_cast<AVRecorderCallback>(recorderCb_);
957 napiCb->SendStateCallback(state, StateChangeReason::USER);
958 }
959
SetCallbackReference(const std::string & callbackName,std::shared_ptr<AutoRef> ref)960 void AVRecorderNapi::SetCallbackReference(const std::string &callbackName, std::shared_ptr<AutoRef> ref)
961 {
962 eventCbMap_[callbackName] = ref;
963 CHECK_AND_RETURN_LOG(recorderCb_ != nullptr, "recorderCb_ is nullptr!");
964 auto napiCb = std::static_pointer_cast<AVRecorderCallback>(recorderCb_);
965 napiCb->SaveCallbackReference(callbackName, ref);
966 }
967
CancelCallbackReference(const std::string & callbackName)968 void AVRecorderNapi::CancelCallbackReference(const std::string &callbackName)
969 {
970 CHECK_AND_RETURN_LOG(recorderCb_ != nullptr, "recorderCb_ is nullptr!");
971 auto napiCb = std::static_pointer_cast<AVRecorderCallback>(recorderCb_);
972 napiCb->CancelCallbackReference(callbackName);
973 eventCbMap_[callbackName] = nullptr;
974 }
975
CancelCallback()976 void AVRecorderNapi::CancelCallback()
977 {
978 CHECK_AND_RETURN_LOG(recorderCb_ != nullptr, "recorderCb_ is nullptr!");
979 auto napiCb = std::static_pointer_cast<AVRecorderCallback>(recorderCb_);
980 napiCb->ClearCallbackReference();
981 }
982
RemoveSurface()983 void AVRecorderNapi::RemoveSurface()
984 {
985 if (surface_ != nullptr) {
986 auto id = surface_->GetUniqueId();
987 auto surface = SurfaceUtils::GetInstance()->GetSurface(id);
988 if (surface) {
989 (void)SurfaceUtils::GetInstance()->Remove(id);
990 }
991 surface_ = nullptr;
992 }
993 }
994
GetPropertyInt32(napi_env env,napi_value configObj,const std::string & type,int32_t & result,bool & getValue)995 int32_t AVRecorderNapi::GetPropertyInt32(napi_env env, napi_value configObj, const std::string &type, int32_t &result,
996 bool &getValue)
997 {
998 napi_value item = nullptr;
999 bool exist = false;
1000 getValue = false;
1001 napi_status status = napi_has_named_property(env, configObj, type.c_str(), &exist);
1002 if (status != napi_ok || !exist) {
1003 MEDIA_LOGI("can not find %{public}s property", type.c_str());
1004 return MSERR_OK;
1005 }
1006
1007 if (napi_get_named_property(env, configObj, type.c_str(), &item) != napi_ok) {
1008 MEDIA_LOGI("get %{public}s property fail", type.c_str());
1009 return MSERR_UNKNOWN;
1010 }
1011
1012 if (napi_get_value_int32(env, item, &result) != napi_ok) {
1013 std::string string = CommonNapi::GetStringArgument(env, item);
1014 if (string == "") {
1015 // This attribute has not been assigned
1016 return MSERR_OK;
1017 } else {
1018 MEDIA_LOGE("get %{public}s property value fail", type.c_str());
1019 return MSERR_INVALID_VAL;
1020 }
1021 }
1022
1023 MEDIA_LOGI("get %{public}s : %{public}d!", type.c_str(), result);
1024 getValue = true;
1025 return MSERR_OK;
1026 }
1027
AVRecorderSignError(int32_t errCode,const std::string & operate,const std::string & param,const std::string & add)1028 void AVRecorderAsyncContext::AVRecorderSignError(int32_t errCode, const std::string &operate,
1029 const std::string ¶m, const std::string &add)
1030 {
1031 RetInfo retInfo = GetRetInfo(errCode, operate, param, add);
1032 SignError(retInfo.first, retInfo.second);
1033 }
1034 } // namespace Media
1035 } // namespace OHOS