• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 &param, 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 &param, 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