1 /*
2 * Copyright (C) 2024 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 "avtranscoder_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 "avtranscoder_napi.h"
31
32 namespace {
33 constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, LOG_DOMAIN_PLAYER, "AVTransCoderNapi"};
34 }
35
36 namespace OHOS {
37 namespace Media {
38 using namespace MediaAVCodec;
39 thread_local napi_ref AVTransCoderNapi::constructor_ = nullptr;
40 const std::string CLASS_NAME = "AVTransCoder";
41 const std::map<std::string, std::vector<std::string>> STATE_CTRL = {
42 {AVTransCoderState::STATE_IDLE, {
43 AVTransCoderOpt::SET_AV_TRANSCODER_CONFIG,
44 }},
45 {AVTransCoderState::STATE_PREPARED, {}},
46 {AVTransCoderState::STATE_STARTED, {
47 AVTransCoderOpt::START,
48 AVTransCoderOpt::RESUME
49 }},
50 {AVTransCoderState::STATE_PAUSED, {
51 AVTransCoderOpt::PAUSE
52 }},
53 {AVTransCoderState::STATE_CANCELLED, {
54 AVTransCoderOpt::CANCEL
55 }},
56 {AVTransCoderState::STATE_RELEASED, {
57 AVTransCoderOpt::RELEASE
58 }},
59 {AVTransCoderState::STATE_COMPLETED, {}},
60 {AVTransCoderState::STATE_ERROR, {}},
61 };
62 std::map<std::string, AVTransCoderNapi::AvTransCoderTaskqFunc> AVTransCoderNapi::taskQFuncs_ = {
63 {AVTransCoderOpt::START, &AVTransCoderNapi::Start},
64 {AVTransCoderOpt::PAUSE, &AVTransCoderNapi::Pause},
65 {AVTransCoderOpt::RESUME, &AVTransCoderNapi::Resume},
66 {AVTransCoderOpt::CANCEL, &AVTransCoderNapi::Cancel},
67 {AVTransCoderOpt::RELEASE, &AVTransCoderNapi::Release},
68 };
69
AVTransCoderNapi()70 AVTransCoderNapi::AVTransCoderNapi()
71 {
72 MEDIA_LOGI("0x%{public}06" PRIXPTR "Instances create", FAKE_POINTER(this));
73 }
74
~AVTransCoderNapi()75 AVTransCoderNapi::~AVTransCoderNapi()
76 {
77 MEDIA_LOGI("0x%{public}06" PRIXPTR "Instances destroy", FAKE_POINTER(this));
78 }
79
Init(napi_env env,napi_value exports)80 napi_value AVTransCoderNapi::Init(napi_env env, napi_value exports)
81 {
82 napi_property_descriptor staticProperty[] = {
83 DECLARE_NAPI_STATIC_FUNCTION("createAVTranscoder", JsCreateAVTransCoder),
84 };
85
86 napi_property_descriptor properties[] = {
87 DECLARE_NAPI_FUNCTION("prepare", JsPrepare),
88 DECLARE_NAPI_FUNCTION("start", JsStart),
89 DECLARE_NAPI_FUNCTION("pause", JsPause),
90 DECLARE_NAPI_FUNCTION("resume", JsResume),
91 DECLARE_NAPI_FUNCTION("cancel", JsCancel),
92 DECLARE_NAPI_FUNCTION("release", JsRelease),
93 DECLARE_NAPI_FUNCTION("on", JsSetEventCallback),
94 DECLARE_NAPI_FUNCTION("off", JsCancelEventCallback),
95
96 DECLARE_NAPI_GETTER_SETTER("fdSrc", JsGetSrcFd, JsSetSrcFd),
97 DECLARE_NAPI_GETTER_SETTER("fdDst", JsGetDstFd, JsSetDstFd),
98 };
99
100 napi_value constructor = nullptr;
101 napi_status status = napi_define_class(env, CLASS_NAME.c_str(), NAPI_AUTO_LENGTH, Constructor, nullptr,
102 sizeof(properties) / sizeof(properties[0]), properties, &constructor);
103 CHECK_AND_RETURN_RET_LOG(status == napi_ok, nullptr, "Failed to define AVTransCoder class");
104
105 status = napi_create_reference(env, constructor, 1, &constructor_);
106 CHECK_AND_RETURN_RET_LOG(status == napi_ok, nullptr, "Failed to create reference of constructor");
107
108 status = napi_set_named_property(env, exports, CLASS_NAME.c_str(), constructor);
109 CHECK_AND_RETURN_RET_LOG(status == napi_ok, nullptr, "Failed to set constructor");
110
111 status = napi_define_properties(env, exports, sizeof(staticProperty) / sizeof(staticProperty[0]), staticProperty);
112 CHECK_AND_RETURN_RET_LOG(status == napi_ok, nullptr, "Failed to define static function");
113
114 MEDIA_LOGD("Init success");
115 return exports;
116 }
117
Constructor(napi_env env,napi_callback_info info)118 napi_value AVTransCoderNapi::Constructor(napi_env env, napi_callback_info info)
119 {
120 MediaTrace trace("AVTransCoder::Constructor");
121 napi_value result = nullptr;
122 napi_get_undefined(env, &result);
123
124 size_t argCount = 0;
125 napi_value jsThis = nullptr;
126 napi_status status = napi_get_cb_info(env, info, &argCount, nullptr, &jsThis, nullptr);
127 CHECK_AND_RETURN_RET_LOG(status == napi_ok, result, "failed to napi_get_cb_info");
128
129 AVTransCoderNapi *jsTransCoder = new(std::nothrow) AVTransCoderNapi();
130 CHECK_AND_RETURN_RET_LOG(jsTransCoder != nullptr, result, "failed to new AVTransCoderNapi");
131
132 jsTransCoder->env_ = env;
133 jsTransCoder->transCoder_ = TransCoderFactory::CreateTransCoder();
134 CHECK_AND_RETURN_RET_LOG(jsTransCoder->transCoder_ != nullptr, result, "failed to CreateTransCoder");
135
136 jsTransCoder->taskQue_ = std::make_unique<TaskQueue>("OS_AVTransCoderNapi");
137 (void)jsTransCoder->taskQue_->Start();
138
139 jsTransCoder->transCoderCb_ = std::make_shared<AVTransCoderCallback>(env);
140 CHECK_AND_RETURN_RET_LOG(jsTransCoder->transCoderCb_ != nullptr, result, "failed to CreateTransCoderCb");
141 (void)jsTransCoder->transCoder_->SetTransCoderCallback(jsTransCoder->transCoderCb_);
142
143 status = napi_wrap(env, jsThis, reinterpret_cast<void *>(jsTransCoder),
144 AVTransCoderNapi::Destructor, nullptr, nullptr);
145 if (status != napi_ok) {
146 delete jsTransCoder;
147 MEDIA_LOGE("Failed to wrap native instance");
148 return result;
149 }
150
151 MEDIA_LOGI("Constructor success");
152 return jsThis;
153 }
154
Destructor(napi_env env,void * nativeObject,void * finalize)155 void AVTransCoderNapi::Destructor(napi_env env, void *nativeObject, void *finalize)
156 {
157 MediaTrace trace("AVTransCoder::Destructor");
158 (void)finalize;
159 if (nativeObject != nullptr) {
160 AVTransCoderNapi *napi = reinterpret_cast<AVTransCoderNapi *>(nativeObject);
161 if (napi->taskQue_ != nullptr) {
162 (void)napi->taskQue_->Stop();
163 }
164
165 napi->transCoderCb_ = nullptr;
166
167 if (napi->transCoder_) {
168 napi->transCoder_->Release();
169 napi->transCoder_ = nullptr;
170 }
171
172 delete napi;
173 }
174 MEDIA_LOGI("Destructor success");
175 }
176
JsCreateAVTransCoder(napi_env env,napi_callback_info info)177 napi_value AVTransCoderNapi::JsCreateAVTransCoder(napi_env env, napi_callback_info info)
178 {
179 MediaTrace trace("AVTransCoder::JsCreateAVTransCoder");
180 napi_value result = nullptr;
181 napi_get_undefined(env, &result);
182
183 MEDIA_LOGI("JsCreateAVTransCoder Start");
184
185 // get args
186 napi_value jsThis = nullptr;
187 napi_value args[1] = { nullptr };
188 size_t argCount = 1;
189 napi_status status = napi_get_cb_info(env, info, &argCount, args, &jsThis, nullptr);
190 CHECK_AND_RETURN_RET_LOG(status == napi_ok, result, "failed to napi_get_cb_info");
191
192 std::unique_ptr<AVTransCoderAsyncContext> asyncCtx = std::make_unique<AVTransCoderAsyncContext>(env);
193 CHECK_AND_RETURN_RET_LOG(asyncCtx != nullptr, result, "failed to get AsyncContext");
194
195 asyncCtx->callbackRef = CommonNapi::CreateReference(env, args[0]);
196 asyncCtx->deferred = CommonNapi::CreatePromise(env, asyncCtx->callbackRef, result);
197 asyncCtx->JsResult = std::make_unique<MediaJsResultInstance>(constructor_);
198 asyncCtx->ctorFlag = true;
199
200 napi_value resource = nullptr;
201 napi_create_string_utf8(env, "JsCreateAVTransCoder", NAPI_AUTO_LENGTH, &resource);
202 NAPI_CALL(env, napi_create_async_work(env, nullptr, resource, [](napi_env env, void* data) {},
203 MediaAsyncContext::CompleteCallback, static_cast<void *>(asyncCtx.get()), &asyncCtx->work));
204 NAPI_CALL(env, napi_queue_async_work_with_qos(env, asyncCtx->work, napi_qos_user_initiated));
205 asyncCtx.release();
206
207 MEDIA_LOGI("JsCreateAVTransCoder success");
208 return result;
209 }
210
GetReturnRet(int32_t errCode,const std::string & operate,const std::string & param,const std::string & add="")211 RetInfo GetReturnRet(int32_t errCode, const std::string &operate, const std::string ¶m, const std::string &add = "")
212 {
213 MEDIA_LOGE("failed to %{public}s, param %{public}s, errCode = %{public}d", operate.c_str(), param.c_str(), errCode);
214 MediaServiceExtErrCodeAPI9 err = MSErrorToExtErrorAPI9(static_cast<MediaServiceErrCode>(errCode));
215
216 std::string message;
217 if (err == MSERR_EXT_API9_INVALID_PARAMETER) {
218 message = MSExtErrorAPI9ToString(err, param, "") + add;
219 } else {
220 message = MSExtErrorAPI9ToString(err, operate, "") + add;
221 }
222
223 MEDIA_LOGE("errCode: %{public}d, errMsg: %{public}s", err, message.c_str());
224 return RetInfo(err, message);
225 }
226
JsPrepare(napi_env env,napi_callback_info info)227 napi_value AVTransCoderNapi::JsPrepare(napi_env env, napi_callback_info info)
228 {
229 MediaTrace trace("AVTransCoder::JsPrepare");
230 const std::string &opt = AVTransCoderOpt::PREPARE;
231 MEDIA_LOGI("Js %{public}s Start", opt.c_str());
232
233 const int32_t maxParam = 2; // config + callbackRef
234 size_t argCount = maxParam;
235 napi_value args[maxParam] = { nullptr };
236
237 napi_value result = nullptr;
238 napi_get_undefined(env, &result);
239
240 auto asyncCtx = std::make_unique<AVTransCoderAsyncContext>(env);
241 CHECK_AND_RETURN_RET_LOG(asyncCtx != nullptr, result, "failed to get AsyncContext");
242 asyncCtx->napi = AVTransCoderNapi::GetJsInstanceAndArgs(env, info, argCount, args);
243 CHECK_AND_RETURN_RET_LOG(asyncCtx->napi != nullptr, result, "failed to GetJsInstanceAndArgs");
244 CHECK_AND_RETURN_RET_LOG(asyncCtx->napi->taskQue_ != nullptr, result, "taskQue is nullptr!");
245
246 asyncCtx->callbackRef = CommonNapi::CreateReference(env, args[1]);
247 asyncCtx->deferred = CommonNapi::CreatePromise(env, asyncCtx->callbackRef, result);
248
249 if (asyncCtx->napi->CheckStateMachine(opt) == MSERR_OK) {
250 if (asyncCtx->napi->GetConfig(asyncCtx, env, args[0]) == MSERR_OK) {
251 asyncCtx->task_ = AVTransCoderNapi::GetPrepareTask(asyncCtx);
252 (void)asyncCtx->napi->taskQue_->EnqueueTask(asyncCtx->task_);
253 }
254 } else {
255 asyncCtx->AVTransCoderSignError(MSERR_INVALID_OPERATION, opt, "");
256 }
257
258 napi_value resource = nullptr;
259 napi_create_string_utf8(env, opt.c_str(), NAPI_AUTO_LENGTH, &resource);
260 NAPI_CALL(env, napi_create_async_work(env, nullptr, resource, [](napi_env env, void* data) {
261 AVTransCoderAsyncContext* asyncCtx = reinterpret_cast<AVTransCoderAsyncContext *>(data);
262 CHECK_AND_RETURN_LOG(asyncCtx != nullptr, "asyncCtx is nullptr!");
263
264 if (asyncCtx->task_) {
265 auto result = asyncCtx->task_->GetResult();
266 if (result.Value().first != MSERR_EXT_API9_OK) {
267 asyncCtx->SignError(result.Value().first, result.Value().second);
268 }
269 }
270 MEDIA_LOGI("The js thread of prepare finishes execution and returns");
271 }, MediaAsyncContext::CompleteCallback, static_cast<void *>(asyncCtx.get()), &asyncCtx->work));
272 NAPI_CALL(env, napi_queue_async_work_with_qos(env, asyncCtx->work, napi_qos_user_initiated));
273 asyncCtx.release();
274
275 MEDIA_LOGI("Js %{public}s End", opt.c_str());
276 return result;
277 }
278
GetPrepareTask(std::unique_ptr<AVTransCoderAsyncContext> & asyncCtx)279 std::shared_ptr<TaskHandler<RetInfo>> AVTransCoderNapi::GetPrepareTask(
280 std::unique_ptr<AVTransCoderAsyncContext> &asyncCtx)
281 {
282 return std::make_shared<TaskHandler<RetInfo>>([napi = asyncCtx->napi, config = asyncCtx->config_]() {
283 const std::string &option = AVTransCoderOpt::PREPARE;
284 MEDIA_LOGI("%{public}s Start", option.c_str());
285 CHECK_AND_RETURN_RET(napi != nullptr && napi->transCoder_ != nullptr && config != nullptr,
286 GetReturnRet(MSERR_INVALID_OPERATION, option, ""));
287
288 CHECK_AND_RETURN_RET(napi->CheckStateMachine(option) == MSERR_OK,
289 GetReturnRet(MSERR_INVALID_OPERATION, option, ""));
290
291 RetInfo retinfo = napi->Configure(config);
292 CHECK_AND_RETURN_RET(retinfo.first == MSERR_OK, ((void)napi->transCoder_->Cancel(), retinfo));
293
294 int32_t ret = napi->transCoder_->Prepare();
295 CHECK_AND_RETURN_RET(ret == MSERR_OK, ((void)napi->transCoder_->Cancel(), GetReturnRet(ret, "Prepare", "")));
296
297 napi->StateCallback(AVTransCoderState::STATE_PREPARED);
298 MEDIA_LOGI("%{public}s End", option.c_str());
299 return RetInfo(MSERR_EXT_API9_OK, "");
300 });
301 }
302
JsStart(napi_env env,napi_callback_info info)303 napi_value AVTransCoderNapi::JsStart(napi_env env, napi_callback_info info)
304 {
305 MediaTrace trace("AVTransCoder::JsStart");
306 #ifdef SUPPORT_JSSTACK
307 HiviewDFX::ReportXPowerJsStackSysEvent(env, "STREAM_CHANGE", "SRC=Media");
308 #endif
309 return ExecuteByPromise(env, info, AVTransCoderOpt::START);
310 }
311
JsPause(napi_env env,napi_callback_info info)312 napi_value AVTransCoderNapi::JsPause(napi_env env, napi_callback_info info)
313 {
314 MediaTrace trace("AVTransCoder::JsPause");
315 return ExecuteByPromise(env, info, AVTransCoderOpt::PAUSE);
316 }
317
JsResume(napi_env env,napi_callback_info info)318 napi_value AVTransCoderNapi::JsResume(napi_env env, napi_callback_info info)
319 {
320 MediaTrace trace("AVTransCoder::JsResume");
321 #ifdef SUPPORT_JSSTACK
322 HiviewDFX::ReportXPowerJsStackSysEvent(env, "STREAM_CHANGE", "SRC=Media");
323 #endif
324 return ExecuteByPromise(env, info, AVTransCoderOpt::RESUME);
325 }
326
JsCancel(napi_env env,napi_callback_info info)327 napi_value AVTransCoderNapi::JsCancel(napi_env env, napi_callback_info info)
328 {
329 MediaTrace trace("AVTransCoder::JsCancle");
330 return ExecuteByPromise(env, info, AVTransCoderOpt::CANCEL);
331 }
332
JsRelease(napi_env env,napi_callback_info info)333 napi_value AVTransCoderNapi::JsRelease(napi_env env, napi_callback_info info)
334 {
335 MediaTrace trace("AVTransCoder::JsRelease");
336 return ExecuteByPromise(env, info, AVTransCoderOpt::RELEASE);
337 }
338
JsSetEventCallback(napi_env env,napi_callback_info info)339 napi_value AVTransCoderNapi::JsSetEventCallback(napi_env env, napi_callback_info info)
340 {
341 MediaTrace trace("AVTransCoder::JsSetEventCallback");
342 MEDIA_LOGI("JsSetEventCallback Start");
343 napi_value result = nullptr;
344 napi_get_undefined(env, &result);
345
346 size_t argCount = 2;
347 napi_value args[2] = { nullptr, nullptr };
348 AVTransCoderNapi *transCoderNapi = AVTransCoderNapi::GetJsInstanceAndArgs(env, info, argCount, args);
349 CHECK_AND_RETURN_RET_LOG(transCoderNapi != nullptr, result, "Failed to retrieve instance");
350
351 napi_valuetype valueType0 = napi_undefined;
352 napi_valuetype valueType1 = napi_undefined;
353 if (napi_typeof(env, args[0], &valueType0) != napi_ok || valueType0 != napi_string ||
354 napi_typeof(env, args[1], &valueType1) != napi_ok || valueType1 != napi_function) {
355 transCoderNapi->ErrorCallback(MSERR_INVALID_VAL, "SetEventCallback");
356 return result;
357 }
358
359 std::string callbackName = CommonNapi::GetStringArgument(env, args[0]);
360
361 napi_ref ref = nullptr;
362 napi_status status = napi_create_reference(env, args[1], 1, &ref);
363 CHECK_AND_RETURN_RET_LOG(status == napi_ok && ref != nullptr, result, "failed to create reference!");
364
365 std::shared_ptr<AutoRef> autoRef = std::make_shared<AutoRef>(env, ref);
366 transCoderNapi->SetCallbackReference(callbackName, autoRef);
367
368 MEDIA_LOGI("JsSetEventCallback End");
369 return result;
370 }
371
JsCancelEventCallback(napi_env env,napi_callback_info info)372 napi_value AVTransCoderNapi::JsCancelEventCallback(napi_env env, napi_callback_info info)
373 {
374 MediaTrace trace("AVTransCoder::JsCancelEventCallback");
375 MEDIA_LOGI("JsCancelEventCallback Start");
376 napi_value result = nullptr;
377 napi_get_undefined(env, &result);
378
379 size_t argCount = 1;
380 napi_value args[1] = { nullptr };
381 AVTransCoderNapi *transCoderNapi = AVTransCoderNapi::GetJsInstanceAndArgs(env, info, argCount, args);
382 CHECK_AND_RETURN_RET_LOG(transCoderNapi != nullptr, result, "Failed to retrieve instance");
383
384 napi_valuetype valueType0 = napi_undefined;
385 if (napi_typeof(env, args[0], &valueType0) != napi_ok || valueType0 != napi_string) {
386 transCoderNapi->ErrorCallback(MSERR_INVALID_VAL, "CancelEventCallback");
387 return result;
388 }
389
390 std::string callbackName = CommonNapi::GetStringArgument(env, args[0]);
391
392 transCoderNapi->CancelCallbackReference(callbackName);
393
394 MEDIA_LOGI("JsCancelEventCallback End");
395 return result;
396 }
397
GetJsInstanceAndArgs(napi_env env,napi_callback_info info,size_t & argCount,napi_value * args)398 AVTransCoderNapi *AVTransCoderNapi::GetJsInstanceAndArgs(
399 napi_env env, napi_callback_info info, size_t &argCount, napi_value *args)
400 {
401 napi_value jsThis = nullptr;
402 napi_status status = napi_get_cb_info(env, info, &argCount, args, &jsThis, nullptr);
403 CHECK_AND_RETURN_RET_LOG(status == napi_ok && jsThis != nullptr, nullptr, "failed to napi_get_cb_info");
404 MEDIA_LOGI("argCount:%{public}zu", argCount);
405
406 AVTransCoderNapi *transCoderNapi = nullptr;
407 status = napi_unwrap(env, jsThis, reinterpret_cast<void **>(&transCoderNapi));
408 CHECK_AND_RETURN_RET_LOG(status == napi_ok && transCoderNapi != nullptr, nullptr, "failed to retrieve instance");
409
410 return transCoderNapi;
411 }
412
GetPromiseTask(AVTransCoderNapi * avnapi,const std::string & opt)413 std::shared_ptr<TaskHandler<RetInfo>> AVTransCoderNapi::GetPromiseTask(AVTransCoderNapi *avnapi, const std::string &opt)
414 {
415 return std::make_shared<TaskHandler<RetInfo>>([napi = avnapi, option = opt]() {
416 MEDIA_LOGI("%{public}s Start", option.c_str());
417 CHECK_AND_RETURN_RET(napi != nullptr && napi->transCoder_ != nullptr,
418 GetReturnRet(MSERR_INVALID_OPERATION, option, ""));
419
420 CHECK_AND_RETURN_RET(napi->CheckStateMachine(option) == MSERR_OK,
421 GetReturnRet(MSERR_INVALID_OPERATION, option, ""));
422
423 CHECK_AND_RETURN_RET(napi->CheckRepeatOperation(option) == MSERR_OK,
424 RetInfo(MSERR_EXT_API9_OK, ""));
425
426 RetInfo ret(MSERR_EXT_API9_OPERATE_NOT_PERMIT, "");
427 auto itFunc = taskQFuncs_.find(option);
428 CHECK_AND_RETURN_RET_LOG(itFunc != taskQFuncs_.end(), ret, "%{public}s not found in map!", option.c_str());
429 auto memberFunc = itFunc->second;
430 CHECK_AND_RETURN_RET_LOG(memberFunc != nullptr, ret, "memberFunc is nullptr!");
431 ret = (napi->*memberFunc)();
432
433 MEDIA_LOGI("%{public}s End", option.c_str());
434 return ret;
435 });
436 }
437
ExecuteByPromise(napi_env env,napi_callback_info info,const std::string & opt)438 napi_value AVTransCoderNapi::ExecuteByPromise(napi_env env, napi_callback_info info, const std::string &opt)
439 {
440 MEDIA_LOGI("Js %{public}s Start", opt.c_str());
441 napi_value result = nullptr;
442 napi_get_undefined(env, &result);
443 size_t argCount = 1; // Only callbackRef parameter
444 napi_value args[1] = { nullptr }; // Only callbackRef parameter
445
446 auto asyncCtx = std::make_unique<AVTransCoderAsyncContext>(env);
447 CHECK_AND_RETURN_RET_LOG(asyncCtx != nullptr, result, "failed to get AsyncContext");
448 asyncCtx->napi = AVTransCoderNapi::GetJsInstanceAndArgs(env, info, argCount, args);
449 CHECK_AND_RETURN_RET_LOG(asyncCtx->napi != nullptr, result, "failed to GetJsInstanceAndArgs");
450 CHECK_AND_RETURN_RET_LOG(asyncCtx->napi->taskQue_ != nullptr, result, "taskQue is nullptr!");
451
452 asyncCtx->callbackRef = CommonNapi::CreateReference(env, args[0]);
453 asyncCtx->deferred = CommonNapi::CreatePromise(env, asyncCtx->callbackRef, result);
454
455 if (asyncCtx->napi->CheckStateMachine(opt) == MSERR_OK) {
456 asyncCtx->task_ = AVTransCoderNapi::GetPromiseTask(asyncCtx->napi, opt);
457 (void)asyncCtx->napi->taskQue_->EnqueueTask(asyncCtx->task_);
458 asyncCtx->opt_ = opt;
459 } else {
460 asyncCtx->AVTransCoderSignError(MSERR_INVALID_OPERATION, opt, "");
461 }
462
463 napi_value resource = nullptr;
464 napi_create_string_utf8(env, opt.c_str(), NAPI_AUTO_LENGTH, &resource);
465 NAPI_CALL(env, napi_create_async_work(env, nullptr, resource, [](napi_env env, void* data) {
466 AVTransCoderAsyncContext* asyncCtx = reinterpret_cast<AVTransCoderAsyncContext *>(data);
467 CHECK_AND_RETURN_LOG(asyncCtx != nullptr, "asyncCtx is nullptr!");
468
469 if (asyncCtx->task_) {
470 auto result = asyncCtx->task_->GetResult();
471 if (result.Value().first != MSERR_EXT_API9_OK) {
472 asyncCtx->SignError(result.Value().first, result.Value().second);
473 }
474 }
475 MEDIA_LOGI("The js thread of %{public}s finishes execution and returns", asyncCtx->opt_.c_str());
476 }, MediaAsyncContext::CompleteCallback, static_cast<void *>(asyncCtx.get()), &asyncCtx->work));
477 NAPI_CALL(env, napi_queue_async_work_with_qos(env, asyncCtx->work, napi_qos_user_initiated));
478 asyncCtx.release();
479
480 MEDIA_LOGI("Js %{public}s End", opt.c_str());
481 return result;
482 }
483
JsGetSrcUrl(napi_env env,napi_callback_info info)484 napi_value AVTransCoderNapi::JsGetSrcUrl(napi_env env, napi_callback_info info)
485 {
486 MediaTrace trace("AVTransCoderNapi::get url");
487 size_t argCount = 1;
488 napi_value args[1] = { nullptr };
489
490 napi_value result = nullptr;
491 napi_get_undefined(env, &result);
492
493 auto asyncCtx = std::make_unique<AVTransCoderAsyncContext>(env);
494 CHECK_AND_RETURN_RET_LOG(asyncCtx != nullptr, result, "failed to get AsyncContext");
495 asyncCtx->napi = AVTransCoderNapi::GetJsInstanceAndArgs(env, info, argCount, args);
496 CHECK_AND_RETURN_RET_LOG(asyncCtx->napi != nullptr, result, "failed to GetJsInstanceAndArgs");
497
498 napi_value value = nullptr;
499 (void)napi_create_string_utf8(env, asyncCtx->napi->srcUrl_.c_str(), NAPI_AUTO_LENGTH, &value);
500
501 MEDIA_LOGD("JsGetUrl Out Current Url: %{public}s", asyncCtx->napi->srcUrl_.c_str());
502 return value;
503 }
504
JsSetSrcFd(napi_env env,napi_callback_info info)505 napi_value AVTransCoderNapi::JsSetSrcFd(napi_env env, napi_callback_info info)
506 {
507 MediaTrace trace("AVTransCoderNapi::set fd");
508 const std::string &opt = AVTransCoderOpt::PREPARE;
509 size_t argCount = 1;
510 napi_value args[1] = { nullptr };
511
512 napi_value result = nullptr;
513 napi_get_undefined(env, &result);
514
515 auto asyncCtx = std::make_unique<AVTransCoderAsyncContext>(env);
516 CHECK_AND_RETURN_RET_LOG(asyncCtx != nullptr, result, "failed to get AsyncContext");
517 asyncCtx->napi = AVTransCoderNapi::GetJsInstanceAndArgs(env, info, argCount, args);
518 CHECK_AND_RETURN_RET_LOG(asyncCtx->napi != nullptr, result, "failed to GetJsInstanceAndArgs");
519
520 // get url from js
521 if (!CommonNapi::GetFdArgument(env, args[0], asyncCtx->napi->srcFd_)) {
522 MEDIA_LOGE("get fileDescriptor argument failed!");
523 return result;
524 }
525
526 auto task = std::make_shared<TaskHandler<void>>([napi = asyncCtx->napi]() {
527 MEDIA_LOGI("JsSetSrcFd Task");
528 napi->SetInputFile(napi->srcFd_.fd, napi->srcFd_.offset, napi->srcFd_.length);
529 });
530 (void)asyncCtx->napi->taskQue_->EnqueueTask(task);
531
532 napi_value resource = nullptr;
533 napi_create_string_utf8(env, opt.c_str(), NAPI_AUTO_LENGTH, &resource);
534 NAPI_CALL(env, napi_create_async_work(env, nullptr, resource, [](napi_env env, void* data) {
535 AVTransCoderAsyncContext* asyncCtx = reinterpret_cast<AVTransCoderAsyncContext *>(data);
536 CHECK_AND_RETURN_LOG(asyncCtx != nullptr, "asyncCtx is nullptr!");
537
538 if (asyncCtx->task_) {
539 auto result = asyncCtx->task_->GetResult();
540 if (result.Value().first != MSERR_EXT_API9_OK) {
541 asyncCtx->SignError(result.Value().first, result.Value().second);
542 }
543 }
544 MEDIA_LOGI("The js thread of %{public}s finishes execution and returns", asyncCtx->opt_.c_str());
545 }, MediaAsyncContext::CompleteCallback, static_cast<void *>(asyncCtx.get()), &asyncCtx->work));
546 NAPI_CALL(env, napi_queue_async_work_with_qos(env, asyncCtx->work, napi_qos_user_initiated));
547 asyncCtx.release();
548
549 MEDIA_LOGI("JsSetSrcFd Out");
550 return result;
551 }
552
JsGetSrcFd(napi_env env,napi_callback_info info)553 napi_value AVTransCoderNapi::JsGetSrcFd(napi_env env, napi_callback_info info)
554 {
555 MediaTrace trace("AVTransCoderNapi::get url");
556 size_t argCount = 1;
557 napi_value args[1] = { nullptr };
558
559 napi_value result = nullptr;
560 napi_get_undefined(env, &result);
561
562 auto asyncCtx = std::make_unique<AVTransCoderAsyncContext>(env);
563 CHECK_AND_RETURN_RET_LOG(asyncCtx != nullptr, result, "failed to get AsyncContext");
564 asyncCtx->napi = AVTransCoderNapi::GetJsInstanceAndArgs(env, info, argCount, args);
565 CHECK_AND_RETURN_RET_LOG(asyncCtx->napi != nullptr, result, "failed to GetJsInstanceAndArgs");
566
567 napi_value value = nullptr;
568 (void)napi_create_string_utf8(env, asyncCtx->napi->srcUrl_.c_str(), NAPI_AUTO_LENGTH, &value);
569
570 MEDIA_LOGD("JsGetUrl Out Current Url: %{public}s", asyncCtx->napi->srcUrl_.c_str());
571 return value;
572 }
573
JsSetDstFd(napi_env env,napi_callback_info info)574 napi_value AVTransCoderNapi::JsSetDstFd(napi_env env, napi_callback_info info)
575 {
576 MediaTrace trace("AVTransCoderNapi::set fd");
577 const std::string &opt = AVTransCoderOpt::PREPARE;
578 size_t argCount = 1;
579 napi_value args[1] = { nullptr };
580
581 napi_value result = nullptr;
582 napi_get_undefined(env, &result);
583
584 auto asyncCtx = std::make_unique<AVTransCoderAsyncContext>(env);
585 CHECK_AND_RETURN_RET_LOG(asyncCtx != nullptr, result, "failed to get AsyncContext");
586 asyncCtx->napi = AVTransCoderNapi::GetJsInstanceAndArgs(env, info, argCount, args);
587 CHECK_AND_RETURN_RET_LOG(asyncCtx->napi != nullptr, result, "failed to GetJsInstanceAndArgs");
588
589 // get url from js
590 napi_get_value_int32(env, args[0], &asyncCtx->napi->dstFd_);
591
592 auto task = std::make_shared<TaskHandler<void>>([napi = asyncCtx->napi]() {
593 MEDIA_LOGI("JsSetSrcFd Task");
594 napi->SetOutputFile(napi->dstFd_);
595 });
596 (void)asyncCtx->napi->taskQue_->EnqueueTask(task);
597
598 napi_value resource = nullptr;
599 napi_create_string_utf8(env, opt.c_str(), NAPI_AUTO_LENGTH, &resource);
600 NAPI_CALL(env, napi_create_async_work(env, nullptr, resource, [](napi_env env, void* data) {
601 AVTransCoderAsyncContext* asyncCtx = reinterpret_cast<AVTransCoderAsyncContext *>(data);
602 CHECK_AND_RETURN_LOG(asyncCtx != nullptr, "asyncCtx is nullptr!");
603
604 if (asyncCtx->task_) {
605 auto result = asyncCtx->task_->GetResult();
606 if (result.Value().first != MSERR_EXT_API9_OK) {
607 asyncCtx->SignError(result.Value().first, result.Value().second);
608 }
609 }
610 MEDIA_LOGI("The js thread of %{public}s finishes execution and returns", asyncCtx->opt_.c_str());
611 }, MediaAsyncContext::CompleteCallback, static_cast<void *>(asyncCtx.get()), &asyncCtx->work));
612 NAPI_CALL(env, napi_queue_async_work_with_qos(env, asyncCtx->work, napi_qos_user_initiated));
613 asyncCtx.release();
614
615 MEDIA_LOGI("JsSetDstFd Out");
616 return result;
617 }
618
JsGetDstFd(napi_env env,napi_callback_info info)619 napi_value AVTransCoderNapi::JsGetDstFd(napi_env env, napi_callback_info info)
620 {
621 MediaTrace trace("AVTransCoderNapi::get url");
622 size_t argCount = 1;
623 napi_value args[1] = { nullptr };
624
625 napi_value result = nullptr;
626 napi_get_undefined(env, &result);
627
628 auto asyncCtx = std::make_unique<AVTransCoderAsyncContext>(env);
629 CHECK_AND_RETURN_RET_LOG(asyncCtx != nullptr, result, "failed to get AsyncContext");
630 asyncCtx->napi = AVTransCoderNapi::GetJsInstanceAndArgs(env, info, argCount, args);
631 CHECK_AND_RETURN_RET_LOG(asyncCtx->napi != nullptr, result, "failed to GetJsInstanceAndArgs");
632
633 napi_value value = nullptr;
634 (void)napi_create_int32(env, asyncCtx->napi->dstFd_, &value);
635
636 MEDIA_LOGD("JsGetUrl Out Current Url: %{public}s", asyncCtx->napi->srcUrl_.c_str());
637 return value;
638 }
639
Start()640 RetInfo AVTransCoderNapi::Start()
641 {
642 int32_t ret = transCoder_->Start();
643 CHECK_AND_RETURN_RET(ret == MSERR_OK, GetReturnRet(ret, "Start", ""));
644 StateCallback(AVTransCoderState::STATE_STARTED);
645 return RetInfo(MSERR_EXT_API9_OK, "");
646 }
647
Pause()648 RetInfo AVTransCoderNapi::Pause()
649 {
650 int32_t ret = transCoder_->Pause();
651 CHECK_AND_RETURN_RET(ret == MSERR_OK, GetReturnRet(ret, "Pause", ""));
652 StateCallback(AVTransCoderState::STATE_PAUSED);
653 return RetInfo(MSERR_EXT_API9_OK, "");
654 }
655
Resume()656 RetInfo AVTransCoderNapi::Resume()
657 {
658 int32_t ret = transCoder_->Resume();
659 CHECK_AND_RETURN_RET(ret == MSERR_OK, GetReturnRet(ret, "Resume", ""));
660 StateCallback(AVTransCoderState::STATE_STARTED);
661 return RetInfo(MSERR_EXT_API9_OK, "");
662 }
663
Cancel()664 RetInfo AVTransCoderNapi::Cancel()
665 {
666 int32_t ret = transCoder_->Cancel();
667 CHECK_AND_RETURN_RET(ret == MSERR_OK, GetReturnRet(ret, "Stop", ""));
668 StateCallback(AVTransCoderState::STATE_CANCELLED);
669 hasConfiged_ = false;
670 return RetInfo(MSERR_EXT_API9_OK, "");
671 }
672
Release()673 RetInfo AVTransCoderNapi::Release()
674 {
675 int32_t ret = transCoder_->Release();
676 CHECK_AND_RETURN_RET(ret == MSERR_OK, GetReturnRet(ret, "Release", ""));
677
678 StateCallback(AVTransCoderState::STATE_RELEASED);
679 CancelCallback();
680 hasConfiged_ = false;
681 return RetInfo(MSERR_EXT_API9_OK, "");
682 }
683
SetInputFile(int32_t fd,int64_t offset,int64_t size)684 RetInfo AVTransCoderNapi::SetInputFile(int32_t fd, int64_t offset, int64_t size)
685 {
686 int32_t ret = transCoder_->SetInputFile(fd, offset, size);
687 CHECK_AND_RETURN_RET(ret == MSERR_OK, GetReturnRet(ret, "SetInputFile", ""));
688 return RetInfo(MSERR_EXT_API9_OK, "");
689 }
690
SetOutputFile(int32_t fd)691 RetInfo AVTransCoderNapi::SetOutputFile(int32_t fd)
692 {
693 int32_t ret = transCoder_->SetOutputFile(fd);
694 CHECK_AND_RETURN_RET(ret == MSERR_OK, GetReturnRet(ret, "SetOutputFile", ""));
695 return RetInfo(MSERR_EXT_API9_OK, "");
696 }
697
CheckStateMachine(const std::string & opt)698 int32_t AVTransCoderNapi::CheckStateMachine(const std::string &opt)
699 {
700 auto napiCb = std::static_pointer_cast<AVTransCoderCallback>(transCoderCb_);
701 CHECK_AND_RETURN_RET_LOG(napiCb != nullptr, MSERR_INVALID_OPERATION, "napiCb is nullptr!");
702
703 std::string curState = napiCb->GetState();
704 CHECK_AND_RETURN_RET_LOG(STATE_LIST.find(curState) != STATE_LIST.end(), MSERR_INVALID_VAL, "state is not in list");
705 std::vector<std::string> allowedOpt = STATE_LIST.at(curState);
706 if (find(allowedOpt.begin(), allowedOpt.end(), opt) == allowedOpt.end()) {
707 MEDIA_LOGE("The %{public}s operation is not allowed in the %{public}s state!", opt.c_str(), curState.c_str());
708 return MSERR_INVALID_OPERATION;
709 }
710
711 return MSERR_OK;
712 }
713
CheckRepeatOperation(const std::string & opt)714 int32_t AVTransCoderNapi::CheckRepeatOperation(const std::string &opt)
715 {
716 auto napiCb = std::static_pointer_cast<AVTransCoderCallback>(transCoderCb_);
717 CHECK_AND_RETURN_RET_LOG(napiCb != nullptr, MSERR_INVALID_OPERATION, "napiCb is nullptr!");
718
719 std::string curState = napiCb->GetState();
720 std::vector<std::string> repeatOpt = STATE_CTRL.at(curState);
721 if (find(repeatOpt.begin(), repeatOpt.end(), opt) != repeatOpt.end()) {
722 MEDIA_LOGI("Current state is %{public}s. Please do not call %{public}s again!",
723 curState.c_str(), opt.c_str());
724 return MSERR_INVALID_OPERATION;
725 }
726
727 return MSERR_OK;
728 }
729
Configure(std::shared_ptr<AVTransCoderConfig> config)730 RetInfo AVTransCoderNapi::Configure(std::shared_ptr<AVTransCoderConfig> config)
731 {
732 CHECK_AND_RETURN_RET(transCoder_ != nullptr, GetReturnRet(MSERR_INVALID_OPERATION, "Configure", ""));
733 CHECK_AND_RETURN_RET(config != nullptr, GetReturnRet(MSERR_INVALID_VAL, "Configure", "config"));
734
735 if (hasConfiged_) {
736 MEDIA_LOGE("AVTransCoderConfig has been configured and will not be configured again");
737 return RetInfo(MSERR_EXT_API9_OK, "");
738 }
739
740 int32_t ret = transCoder_->SetOutputFormat(config->fileFormat);
741 CHECK_AND_RETURN_RET(ret == MSERR_OK, GetReturnRet(ret, "SetOutputFormat", "fileFormat"));
742
743 ret = transCoder_->SetAudioEncoder(config->audioCodecFormat);
744 CHECK_AND_RETURN_RET(ret == MSERR_OK, GetReturnRet(ret, "SetAudioEncoder", "audioCodecFormat"));
745
746 ret = transCoder_->SetAudioEncodingBitRate(config->audioBitrate);
747 CHECK_AND_RETURN_RET(ret == MSERR_OK, GetReturnRet(ret, "SetAudioEncoderBitRate", "audioBitrate"));
748
749 ret = transCoder_->SetVideoEncoder(config->videoCodecFormat);
750 CHECK_AND_RETURN_RET(ret == MSERR_OK, GetReturnRet(ret, "SetVideoEncoder", "videoCodecFormat"));
751
752 ret = transCoder_->SetVideoSize(config->videoFrameWidth, config->videoFrameHeight);
753 CHECK_AND_RETURN_RET(ret == MSERR_OK, GetReturnRet(ret, "SetVideoSize", "videoSize"));
754
755 ret = transCoder_->SetVideoEncodingBitRate(config->videoBitrate);
756 CHECK_AND_RETURN_RET(ret == MSERR_OK, GetReturnRet(ret, "SetVideoEncoderBitRate", "videoBitrate"));
757
758 hasConfiged_ = true;
759 return RetInfo(MSERR_EXT_API9_OK, "");
760 }
761
ErrorCallback(int32_t errCode,const std::string & operate,const std::string & add)762 void AVTransCoderNapi::ErrorCallback(int32_t errCode, const std::string &operate, const std::string &add)
763 {
764 MEDIA_LOGE("failed to %{public}s, errCode = %{public}d", operate.c_str(), errCode);
765 CHECK_AND_RETURN_LOG(transCoderCb_ != nullptr, "transCoderCb_ is nullptr!");
766 auto napiCb = std::static_pointer_cast<AVTransCoderCallback>(transCoderCb_);
767
768 MediaServiceExtErrCodeAPI9 err = MSErrorToExtErrorAPI9(static_cast<MediaServiceErrCode>(errCode));
769 std::string msg = MSExtErrorAPI9ToString(err, operate, "") + add;
770 napiCb->SendErrorCallback(err, msg);
771 }
772
StateCallback(const std::string & state)773 void AVTransCoderNapi::StateCallback(const std::string &state)
774 {
775 MEDIA_LOGI("Change state to %{public}s", state.c_str());
776 CHECK_AND_RETURN_LOG(transCoderCb_ != nullptr, "transCoderCb_ is nullptr!");
777 auto napiCb = std::static_pointer_cast<AVTransCoderCallback>(transCoderCb_);
778 napiCb->SendStateCallback(state, StateChangeReason::USER);
779 }
780
SetCallbackReference(const std::string & callbackName,std::shared_ptr<AutoRef> ref)781 void AVTransCoderNapi::SetCallbackReference(const std::string &callbackName, std::shared_ptr<AutoRef> ref)
782 {
783 eventCbMap_[callbackName] = ref;
784 CHECK_AND_RETURN_LOG(transCoderCb_ != nullptr, "transCoderCb_ is nullptr!");
785 auto napiCb = std::static_pointer_cast<AVTransCoderCallback>(transCoderCb_);
786 napiCb->SaveCallbackReference(callbackName, ref);
787 }
788
CancelCallbackReference(const std::string & callbackName)789 void AVTransCoderNapi::CancelCallbackReference(const std::string &callbackName)
790 {
791 CHECK_AND_RETURN_LOG(transCoderCb_ != nullptr, "transCoderCb_ is nullptr!");
792 auto napiCb = std::static_pointer_cast<AVTransCoderCallback>(transCoderCb_);
793 napiCb->CancelCallbackReference(callbackName);
794 eventCbMap_[callbackName] = nullptr;
795 }
796
CancelCallback()797 void AVTransCoderNapi::CancelCallback()
798 {
799 CHECK_AND_RETURN_LOG(transCoderCb_ != nullptr, "transCoderCb_ is nullptr!");
800 auto napiCb = std::static_pointer_cast<AVTransCoderCallback>(transCoderCb_);
801 napiCb->ClearCallbackReference();
802 }
803
GetAudioCodecFormat(const std::string & mime,AudioCodecFormat & codecFormat)804 int32_t AVTransCoderNapi::GetAudioCodecFormat(const std::string &mime, AudioCodecFormat &codecFormat)
805 {
806 MEDIA_LOGI("mime %{public}s", mime.c_str());
807 const std::map<std::string_view, AudioCodecFormat> mimeStrToCodecFormat = {
808 { CodecMimeType::AUDIO_AAC, AudioCodecFormat::AAC_LC },
809 { "", AudioCodecFormat::AUDIO_DEFAULT },
810 };
811
812 auto iter = mimeStrToCodecFormat.find(mime);
813 if (iter != mimeStrToCodecFormat.end()) {
814 codecFormat = iter->second;
815 return MSERR_OK;
816 }
817 return MSERR_INVALID_VAL;
818 }
819
GetAudioConfig(std::unique_ptr<AVTransCoderAsyncContext> & asyncCtx,napi_env env,napi_value args)820 int32_t AVTransCoderNapi::GetAudioConfig(std::unique_ptr<AVTransCoderAsyncContext> &asyncCtx,
821 napi_env env, napi_value args)
822 {
823 std::shared_ptr<AVTransCoderConfig> config = asyncCtx->config_;
824 std::string audioCodec = CommonNapi::GetPropertyString(env, args, "audioCodec");
825 (void)AVTransCoderNapi::GetAudioCodecFormat(audioCodec, config->audioCodecFormat);
826 (void)CommonNapi::GetPropertyInt32(env, args, "audioBitrate", config->audioBitrate);
827 return MSERR_OK;
828 }
829
GetVideoCodecFormat(const std::string & mime,VideoCodecFormat & codecFormat)830 int32_t AVTransCoderNapi::GetVideoCodecFormat(const std::string &mime, VideoCodecFormat &codecFormat)
831 {
832 MEDIA_LOGI("mime %{public}s", mime.c_str());
833 const std::map<std::string_view, VideoCodecFormat> mimeStrToCodecFormat = {
834 { CodecMimeType::VIDEO_AVC, VideoCodecFormat::H264 },
835 { CodecMimeType::VIDEO_HEVC, VideoCodecFormat::H265 },
836 { "", VideoCodecFormat::VIDEO_DEFAULT },
837 };
838
839 auto iter = mimeStrToCodecFormat.find(mime);
840 if (iter != mimeStrToCodecFormat.end()) {
841 codecFormat = iter->second;
842 return MSERR_OK;
843 }
844 return MSERR_INVALID_VAL;
845 }
846
GetVideoConfig(std::unique_ptr<AVTransCoderAsyncContext> & asyncCtx,napi_env env,napi_value args)847 int32_t AVTransCoderNapi::GetVideoConfig(std::unique_ptr<AVTransCoderAsyncContext> &asyncCtx,
848 napi_env env, napi_value args)
849 {
850 std::shared_ptr<AVTransCoderConfig> config = asyncCtx->config_;
851 std::string videoCodec = CommonNapi::GetPropertyString(env, args, "videoCodec");
852 (void)AVTransCoderNapi::GetVideoCodecFormat(videoCodec, config->videoCodecFormat);
853 (void)CommonNapi::GetPropertyInt32(env, args, "videoBitrate", config->videoBitrate);
854 (void)CommonNapi::GetPropertyInt32(env, args, "videoFrameWidth", config->videoFrameWidth);
855 (void)CommonNapi::GetPropertyInt32(env, args, "videoFrameHeight", config->videoFrameHeight);
856 return MSERR_OK;
857 }
858
GetOutputFormat(const std::string & extension,OutputFormatType & type)859 int32_t AVTransCoderNapi::GetOutputFormat(const std::string &extension, OutputFormatType &type)
860 {
861 MEDIA_LOGI("mime %{public}s", extension.c_str());
862 const std::map<std::string, OutputFormatType> extensionToOutputFormat = {
863 { "mp4", OutputFormatType::FORMAT_MPEG_4 },
864 { "m4a", OutputFormatType::FORMAT_M4A },
865 { "", OutputFormatType::FORMAT_DEFAULT },
866 };
867
868 auto iter = extensionToOutputFormat.find(extension);
869 if (iter != extensionToOutputFormat.end()) {
870 type = iter->second;
871 return MSERR_OK;
872 }
873 return MSERR_INVALID_VAL;
874 }
875
GetConfig(std::unique_ptr<AVTransCoderAsyncContext> & asyncCtx,napi_env env,napi_value args)876 int32_t AVTransCoderNapi::GetConfig(std::unique_ptr<AVTransCoderAsyncContext> &asyncCtx,
877 napi_env env, napi_value args)
878 {
879 napi_valuetype valueType = napi_undefined;
880 if (args == nullptr || napi_typeof(env, args, &valueType) != napi_ok || valueType != napi_object) {
881 asyncCtx->AVTransCoderSignError(MSERR_INVALID_VAL, "GetConfig", "AVTransCoderConfig");
882 return MSERR_INVALID_VAL;
883 }
884
885 asyncCtx->config_ = std::make_shared<AVTransCoderConfig>();
886 CHECK_AND_RETURN_RET(asyncCtx->config_,
887 (asyncCtx->AVTransCoderSignError(MSERR_NO_MEMORY, "AVTransCoderConfig", "AVTransCoderConfig"),
888 MSERR_NO_MEMORY));
889
890 std::shared_ptr<AVTransCoderConfig> config = asyncCtx->config_;
891
892 int32_t ret = GetAudioConfig(asyncCtx, env, args);
893 CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, ret, "failed to GetAudioConfig");
894
895 ret = GetVideoConfig(asyncCtx, env, args);
896 CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, ret, "failed to GetVideoConfig");
897
898 std::string fileFormat = CommonNapi::GetPropertyString(env, args, "fileFormat");
899 ret = AVTransCoderNapi::GetOutputFormat(fileFormat, config->fileFormat);
900 CHECK_AND_RETURN_RET(ret == MSERR_OK, (asyncCtx->AVTransCoderSignError(ret, "GetOutputFormat", "fileFormat"), ret));
901
902 return MSERR_OK;
903 }
904
AVTransCoderSignError(int32_t errCode,const std::string & operate,const std::string & param,const std::string & add)905 void AVTransCoderAsyncContext::AVTransCoderSignError(int32_t errCode, const std::string &operate,
906 const std::string ¶m, const std::string &add)
907 {
908 RetInfo retInfo = GetReturnRet(errCode, operate, param, add);
909 SignError(retInfo.first, retInfo.second);
910 }
911
912
913 } // namespace Media
914 } // namespace OHOS