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 &param, 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 &param, 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