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