• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2022 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "avplayer_napi.h"
17 #include "avplayer_callback.h"
18 #include "media_errors.h"
19 #include "common_napi.h"
20 #include "js_common_utils.h"
21 #ifdef SUPPORT_AVPLAYER_DRM
22 #include "key_session_impl.h"
23 #endif
24 #ifdef SUPPORT_VIDEO
25 #include "surface_utils.h"
26 #endif
27 #include "string_ex.h"
28 #include "player_xcollie.h"
29 #include "media_dfx.h"
30 #ifdef SUPPORT_JSSTACK
31 #include "xpower_event_js.h"
32 #endif
33 #include "av_common.h"
34 #include "meta/video_types.h"
35 #include "media_source_napi.h"
36 #include "media_log.h"
37 #ifndef CROSS_PLATFORM
38 #include "ipc_skeleton.h"
39 #include "tokenid_kit.h"
40 #endif
41 
42 using namespace OHOS::AudioStandard;
43 
44 namespace {
45     constexpr OHOS::HiviewDFX::HiLogLabel LABEL = { LOG_CORE, LOG_DOMAIN_PLAYER, "AVPlayerNapi" };
46     constexpr uint32_t MIN_ARG_COUNTS = 1;
47     constexpr uint32_t MAX_ARG_COUNTS = 2;
48     constexpr size_t ARRAY_ARG_COUNTS_TWO = 2;
49     constexpr size_t ARRAY_ARG_COUNTS_THREE = 3;
50     constexpr int32_t PLAY_RANGE_DEFAULT_VALUE = -1;
51     constexpr int32_t SEEK_MODE_CLOSEST = 2;
52     constexpr int32_t INDEX_A = 0;
53     constexpr int32_t INDEX_B = 1;
54     constexpr int32_t INDEX_C = 2;
55     constexpr uint32_t TASK_TIME_LIMIT_MS = 2000; // ms
56     constexpr size_t PARAM_COUNT_SINGLE = 1;
57     constexpr int32_t API_VERSION_17 = 17;
58     static int32_t g_apiVersion = -1;
59     constexpr int32_t ARGS_TWO = 2;
60     constexpr int32_t ARGS_THREE = 3;
61     constexpr int32_t SEEK_CONTINUOUS_TS_ENUM_NUM = 3;
62 }
63 
64 namespace OHOS {
65 namespace Media {
66 thread_local napi_ref AVPlayerNapi::constructor_ = nullptr;
67 const std::string CLASS_NAME = "AVPlayer";
68 
AVPlayerNapi()69 AVPlayerNapi::AVPlayerNapi()
70 {
71     MEDIA_LOGI("0x%{public}06" PRIXPTR " ctor", FAKE_POINTER(this));
72 }
73 
~AVPlayerNapi()74 AVPlayerNapi::~AVPlayerNapi()
75 {
76     MEDIA_LOGI("0x%{public}06" PRIXPTR " dtor", FAKE_POINTER(this));
77 }
78 
Init(napi_env env,napi_value exports)79 napi_value AVPlayerNapi::Init(napi_env env, napi_value exports)
80 {
81     napi_property_descriptor staticProperty[] = {
82         DECLARE_NAPI_STATIC_FUNCTION("createAVPlayer", JsCreateAVPlayer),
83     };
84 
85     napi_property_descriptor properties[] = {
86         DECLARE_NAPI_FUNCTION("prepare", JsPrepare),
87         DECLARE_NAPI_FUNCTION("play", JsPlay),
88         DECLARE_NAPI_FUNCTION("pause", JsPause),
89         DECLARE_NAPI_FUNCTION("stop", JsStop),
90         DECLARE_NAPI_FUNCTION("reset", JsReset),
91         DECLARE_NAPI_FUNCTION("release", JsRelease),
92         DECLARE_NAPI_FUNCTION("seek", JsSeek),
93         DECLARE_NAPI_FUNCTION("setPlaybackRange", JsSetPlaybackRange),
94         DECLARE_NAPI_FUNCTION("setSuperResolution", JsSetSuperResolution),
95         DECLARE_NAPI_FUNCTION("setVideoWindowSize", JsSetVideoWindowSize),
96         DECLARE_NAPI_FUNCTION("on", JsSetOnCallback),
97         DECLARE_NAPI_FUNCTION("off", JsClearOnCallback),
98         DECLARE_NAPI_FUNCTION("setVolume", JsSetVolume),
99         DECLARE_NAPI_FUNCTION("setSpeed", JsSetSpeed),
100         DECLARE_NAPI_FUNCTION("setMediaSource", JsSetMediaSource),
101         DECLARE_NAPI_FUNCTION("setBitrate", JsSelectBitrate),
102         DECLARE_NAPI_FUNCTION("getTrackDescription", JsGetTrackDescription),
103         DECLARE_NAPI_FUNCTION("getSelectedTracks", JsGetSelectedTracks),
104         DECLARE_NAPI_FUNCTION("selectTrack", JsSelectTrack),
105         DECLARE_NAPI_FUNCTION("deselectTrack", JsDeselectTrack),
106         DECLARE_NAPI_FUNCTION("getCurrentTrack", JsGetCurrentTrack),
107         DECLARE_NAPI_FUNCTION("addSubtitleUrl", JsAddSubtitleUrl),
108         DECLARE_NAPI_FUNCTION("addSubtitleFdSrc", JsAddSubtitleAVFileDescriptor),
109         DECLARE_NAPI_FUNCTION("addSubtitleFromUrl", JsAddSubtitleUrl),
110         DECLARE_NAPI_FUNCTION("addSubtitleFromFd", JsAddSubtitleAVFileDescriptor),
111         DECLARE_NAPI_FUNCTION("setDecryptionConfig", JsSetDecryptConfig),
112         DECLARE_NAPI_FUNCTION("getMediaKeySystemInfos", JsGetMediaKeySystemInfos),
113         DECLARE_NAPI_FUNCTION("setPlaybackStrategy", JsSetPlaybackStrategy),
114         DECLARE_NAPI_FUNCTION("setMediaMuted", JsSetMediaMuted),
115         DECLARE_NAPI_FUNCTION("getPlaybackInfo", JsGetPlaybackInfo),
116         DECLARE_NAPI_FUNCTION("isSeekContinuousSupported", JsIsSeekContinuousSupported),
117         DECLARE_NAPI_FUNCTION("getPlaybackPosition", JsGetPlaybackPosition),
118 
119         DECLARE_NAPI_GETTER_SETTER("url", JsGetUrl, JsSetUrl),
120         DECLARE_NAPI_GETTER_SETTER("fdSrc", JsGetAVFileDescriptor, JsSetAVFileDescriptor),
121         DECLARE_NAPI_GETTER_SETTER("dataSrc", JsGetDataSrc, JsSetDataSrc),
122         DECLARE_NAPI_GETTER_SETTER("surfaceId", JsGetSurfaceID, JsSetSurfaceID),
123         DECLARE_NAPI_GETTER_SETTER("loop", JsGetLoop, JsSetLoop),
124         DECLARE_NAPI_GETTER_SETTER("videoScaleType", JsGetVideoScaleType, JsSetVideoScaleType),
125         DECLARE_NAPI_GETTER_SETTER("audioInterruptMode", JsGetAudioInterruptMode, JsSetAudioInterruptMode),
126         DECLARE_NAPI_GETTER_SETTER("audioRendererInfo", JsGetAudioRendererInfo, JsSetAudioRendererInfo),
127         DECLARE_NAPI_GETTER_SETTER("audioEffectMode", JsGetAudioEffectMode, JsSetAudioEffectMode),
128 
129         DECLARE_NAPI_GETTER("state", JsGetState),
130         DECLARE_NAPI_GETTER("currentTime", JsGetCurrentTime),
131         DECLARE_NAPI_GETTER("duration", JsGetDuration),
132         DECLARE_NAPI_GETTER("width", JsGetWidth),
133         DECLARE_NAPI_GETTER("height", JsGetHeight),
134     };
135     napi_value constructor = nullptr;
136     napi_status status = napi_define_class(env, CLASS_NAME.c_str(), NAPI_AUTO_LENGTH, Constructor, nullptr,
137         sizeof(properties) / sizeof(properties[0]), properties, &constructor);
138     CHECK_AND_RETURN_RET_LOG(status == napi_ok, nullptr, "Failed to define AVPlayer class");
139 
140     status = napi_create_reference(env, constructor, 1, &constructor_);
141     CHECK_AND_RETURN_RET_LOG(status == napi_ok, nullptr, "Failed to create reference of constructor");
142 
143     status = napi_set_named_property(env, exports, CLASS_NAME.c_str(), constructor);
144     CHECK_AND_RETURN_RET_LOG(status == napi_ok, nullptr, "Failed to set constructor");
145 
146     status = napi_define_properties(env, exports, sizeof(staticProperty) / sizeof(staticProperty[0]), staticProperty);
147     CHECK_AND_RETURN_RET_LOG(status == napi_ok, nullptr, "Failed to define static function");
148     return exports;
149 }
150 
Constructor(napi_env env,napi_callback_info info)151 napi_value AVPlayerNapi::Constructor(napi_env env, napi_callback_info info)
152 {
153     napi_value result = nullptr;
154     napi_get_undefined(env, &result);
155 
156     size_t argCount = 0;
157     napi_value jsThis = nullptr;
158     napi_status status = napi_get_cb_info(env, info, &argCount, nullptr, &jsThis, nullptr);
159     CHECK_AND_RETURN_RET_LOG(status == napi_ok, result, "failed to napi_get_cb_info");
160 
161     AVPlayerNapi *jsPlayer = new(std::nothrow) AVPlayerNapi();
162     CHECK_AND_RETURN_RET_LOG(jsPlayer != nullptr, result, "failed to new AVPlayerNapi");
163 
164     jsPlayer->env_ = env;
165     jsPlayer->player_ = PlayerFactory::CreatePlayer();
166     if (jsPlayer->player_ == nullptr) {
167         delete jsPlayer;
168         MEDIA_LOGE("failed to CreatePlayer");
169         return result;
170     }
171 
172     jsPlayer->taskQue_ = std::make_unique<TaskQueue>("OS_AVPlayerNapi");
173     (void)jsPlayer->taskQue_->Start();
174 
175     jsPlayer->playerCb_ = std::make_shared<AVPlayerCallback>(env, jsPlayer);
176     (void)jsPlayer->player_->SetPlayerCallback(jsPlayer->playerCb_);
177 
178     status = napi_wrap(env, jsThis, reinterpret_cast<void *>(jsPlayer),
179         AVPlayerNapi::Destructor, nullptr, nullptr);
180     if (status != napi_ok) {
181         delete jsPlayer;
182         MEDIA_LOGE("Failed to wrap native instance");
183         return result;
184     }
185 
186     MEDIA_LOGI("0x%{public}06" PRIXPTR " Constructor success", FAKE_POINTER(jsPlayer));
187     return jsThis;
188 }
189 
Destructor(napi_env env,void * nativeObject,void * finalize)190 void AVPlayerNapi::Destructor(napi_env env, void *nativeObject, void *finalize)
191 {
192     (void)env;
193     (void)finalize;
194     if (nativeObject != nullptr) {
195         AVPlayerNapi *jsPlayer = reinterpret_cast<AVPlayerNapi *>(nativeObject);
196         jsPlayer->ClearCallbackReference();
197         std::thread([jsPlayer]() -> void {
198             auto task = jsPlayer->ReleaseTask();
199             if (task != nullptr) {
200                 MEDIA_LOGI("0x%{public}06" PRIXPTR " Destructor wait >>", FAKE_POINTER(jsPlayer));
201                 task->GetResult(); // sync release
202                 MEDIA_LOGI("0x%{public}06" PRIXPTR " Destructor wait <<", FAKE_POINTER(jsPlayer));
203             }
204             jsPlayer->WaitTaskQueStop();
205             delete jsPlayer;
206         }).detach();
207     }
208     MEDIA_LOGD("Destructor success");
209 }
210 
IsSystemApp()211 bool AVPlayerNapi::IsSystemApp()
212 {
213     static bool isSystemApp = false;
214 #ifndef CROSS_PLATFORM
215     static std::once_flag once;
216     std::call_once(once, [] {
217         uint64_t tokenId = IPCSkeleton::GetSelfTokenID();
218         isSystemApp = Security::AccessToken::TokenIdKit::IsSystemAppByFullTokenID(tokenId);
219     });
220 #endif
221     return isSystemApp;
222 }
223 
JsCreateAVPlayer(napi_env env,napi_callback_info info)224 napi_value AVPlayerNapi::JsCreateAVPlayer(napi_env env, napi_callback_info info)
225 {
226     MediaTrace trace("AVPlayerNapi::createAVPlayer");
227     napi_value result = nullptr;
228     napi_get_undefined(env, &result);
229     MEDIA_LOGD("JsCreateAVPlayer In");
230 
231     std::unique_ptr<MediaAsyncContext> asyncContext = std::make_unique<MediaAsyncContext>(env);
232 
233     // get args
234     napi_value jsThis = nullptr;
235     napi_value args[1] = { nullptr };
236     size_t argCount = 1;
237     napi_status status = napi_get_cb_info(env, info, &argCount, args, &jsThis, nullptr);
238     CHECK_AND_RETURN_RET_LOG(status == napi_ok && jsThis != nullptr, nullptr, "failed to napi_get_cb_info");
239 
240     asyncContext->callbackRef = CommonNapi::CreateReference(env, args[0]);
241     asyncContext->deferred = CommonNapi::CreatePromise(env, asyncContext->callbackRef, result);
242     asyncContext->JsResult = std::make_unique<MediaJsResultInstance>(constructor_);
243     asyncContext->ctorFlag = true;
244 
245     auto ret = MediaAsyncContext::SendCompleteEvent(env, asyncContext.get(), napi_eprio_immediate);
246     if (ret != napi_status::napi_ok) {
247         MEDIA_LOGE("failed to SendEvent, ret = %{public}d", ret);
248     } else {
249         asyncContext.release();
250     }
251     MEDIA_LOGI("0x%{public}06" PRIXPTR " JsCreateAVPlayer Out", FAKE_POINTER(jsThis));
252     return result;
253 }
254 
PrepareTask()255 std::shared_ptr<TaskHandler<TaskRet>> AVPlayerNapi::PrepareTask()
256 {
257     auto task = std::make_shared<TaskHandler<TaskRet>>([this]() {
258         MEDIA_LOGI("0x%{public}06" PRIXPTR " Prepare Task In", FAKE_POINTER(this));
259         std::unique_lock<std::mutex> lock(taskMutex_);
260         auto state = GetCurrentState();
261         if (state == AVPlayerState::STATE_INITIALIZED ||
262             state == AVPlayerState::STATE_STOPPED) {
263             int32_t ret = player_->PrepareAsync();
264             if (ret != MSERR_OK) {
265                 auto errCode = MSErrorToExtErrorAPI9(static_cast<MediaServiceErrCode>(ret));
266                 return TaskRet(errCode, "failed to prepare");
267             }
268             stopWait_ = false;
269             stateChangeCond_.wait(lock, [this]() {
270                 return stopWait_.load() || isInterrupted_.load() || avplayerExit_;
271             });
272 
273             if (GetCurrentState() == AVPlayerState::STATE_ERROR) {
274                 return TaskRet(MSERR_EXT_API9_OPERATE_NOT_PERMIT,
275                     "failed to prepare, avplayer enter error status, please check error callback messages!");
276             }
277         } else if (state == AVPlayerState::STATE_PREPARED) {
278             MEDIA_LOGI("current state is prepared, invalid operation");
279         } else {
280             return TaskRet(MSERR_EXT_API9_OPERATE_NOT_PERMIT,
281                 "current state is not stopped or initialized, unsupport prepare operation");
282         }
283 
284         MEDIA_LOGI("0x%{public}06" PRIXPTR " Prepare Task Out", FAKE_POINTER(this));
285         return TaskRet(MSERR_EXT_API9_OK, "Success");
286     });
287 
288     (void)taskQue_->EnqueueTask(task);
289     return task;
290 }
291 
JsPrepare(napi_env env,napi_callback_info info)292 napi_value AVPlayerNapi::JsPrepare(napi_env env, napi_callback_info info)
293 {
294     MediaTrace trace("AVPlayerNapi::prepare");
295     napi_value result = nullptr;
296     napi_get_undefined(env, &result);
297     MEDIA_LOGI("JsPrepare In");
298 
299     auto promiseCtx = std::make_unique<AVPlayerContext>(env);
300     napi_value args[1] = { nullptr };
301     size_t argCount = 1;
302     AVPlayerNapi *jsPlayer = AVPlayerNapi::GetJsInstanceWithParameter(env, info, argCount, args);
303     CHECK_AND_RETURN_RET_LOG(jsPlayer != nullptr, result, "failed to GetJsInstance");
304 
305     promiseCtx->callbackRef = CommonNapi::CreateReference(env, args[0]);
306     promiseCtx->deferred = CommonNapi::CreatePromise(env, promiseCtx->callbackRef, result);
307     auto state = jsPlayer->GetCurrentState();
308     if (state != AVPlayerState::STATE_INITIALIZED &&
309         state != AVPlayerState::STATE_STOPPED &&
310         state != AVPlayerState::STATE_PREPARED) {
311         promiseCtx->SignError(MSERR_EXT_API9_OPERATE_NOT_PERMIT,
312             "current state is not stopped or initialized, unsupport prepare operation");
313     } else {
314         MEDIA_LOGI("0x%{public}06" PRIXPTR " JsPrepare EnqueueTask In", FAKE_POINTER(jsPlayer));
315         promiseCtx->asyncTask = jsPlayer->PrepareTask();
316         MEDIA_LOGI("0x%{public}06" PRIXPTR " JsPrepare EnqueueTask out", FAKE_POINTER(jsPlayer));
317     }
318 
319     napi_value resource = nullptr;
320     napi_create_string_utf8(env, "JsPrepare", NAPI_AUTO_LENGTH, &resource);
321     NAPI_CALL(env, napi_create_async_work(env, nullptr, resource,
322         [](napi_env env, void *data) {
323             MEDIA_LOGI("Wait Prepare Task Start");
324             auto promiseCtx = reinterpret_cast<AVPlayerContext *>(data);
325             CHECK_AND_RETURN_LOG(promiseCtx != nullptr, "promiseCtx is nullptr!");
326             promiseCtx->CheckTaskResult(true, TASK_TIME_LIMIT_MS);
327             MEDIA_LOGI("Wait Prepare Task End");
328         },
329         MediaAsyncContext::CompleteCallback, static_cast<void *>(promiseCtx.get()), &promiseCtx->work));
330     napi_queue_async_work_with_qos(env, promiseCtx->work, napi_qos_user_initiated);
331     promiseCtx.release();
332     MEDIA_LOGI("0x%{public}06" PRIXPTR " JsPrepare Out", FAKE_POINTER(jsPlayer));
333     return result;
334 }
335 
PlayTask()336 std::shared_ptr<TaskHandler<TaskRet>> AVPlayerNapi::PlayTask()
337 {
338     auto task = std::make_shared<TaskHandler<TaskRet>>([this]() {
339         MEDIA_LOGI("0x%{public}06" PRIXPTR " Play Task In", FAKE_POINTER(this));
340         std::unique_lock<std::mutex> lock(taskMutex_);
341         auto state = GetCurrentState();
342         if (state == AVPlayerState::STATE_PREPARED ||
343             state == AVPlayerState::STATE_PAUSED ||
344             state == AVPlayerState::STATE_COMPLETED) {
345             int32_t ret = player_->Play();
346             if (ret != MSERR_OK) {
347                 auto errCode = MSErrorToExtErrorAPI9(static_cast<MediaServiceErrCode>(ret));
348                 return TaskRet(errCode, "failed to Play");
349             }
350             stopWait_ = false;
351             stateChangeCond_.wait(lock, [this]() {
352                 return stopWait_.load() || isInterrupted_.load() || avplayerExit_;
353             });
354 
355             if (GetCurrentState() == AVPlayerState::STATE_ERROR) {
356                 return TaskRet(MSERR_EXT_API9_OPERATE_NOT_PERMIT,
357                     "failed to play, avplayer enter error status, please check error callback messages!");
358             }
359         } else if (state == AVPlayerState::STATE_PLAYING) {
360             if (IsSystemApp()) {
361                 player_->Seek(-1, SEEK_CONTINOUS);
362             }
363             MEDIA_LOGI("current state is playing, invalid operation");
364         } else {
365             return TaskRet(MSERR_EXT_API9_OPERATE_NOT_PERMIT,
366                 "current state is not prepared/paused/completed, unsupport play operation");
367         }
368 
369         MEDIA_LOGI("0x%{public}06" PRIXPTR " Play Task Out", FAKE_POINTER(this));
370         return TaskRet(MSERR_EXT_API9_OK, "Success");
371     });
372     (void)taskQue_->EnqueueTask(task);
373     return task;
374 }
375 
JsPlay(napi_env env,napi_callback_info info)376 napi_value AVPlayerNapi::JsPlay(napi_env env, napi_callback_info info)
377 {
378     MediaTrace trace("AVPlayerNapi::play");
379     napi_value result = nullptr;
380     napi_get_undefined(env, &result);
381     MEDIA_LOGI("JsPlay In");
382 
383     auto promiseCtx = std::make_unique<AVPlayerContext>(env);
384     napi_value args[1] = { nullptr };
385     size_t argCount = 1;
386     AVPlayerNapi *jsPlayer = AVPlayerNapi::GetJsInstanceWithParameter(env, info, argCount, args);
387     CHECK_AND_RETURN_RET_LOG(jsPlayer != nullptr, result, "failed to GetJsInstance");
388 
389     promiseCtx->callbackRef = CommonNapi::CreateReference(env, args[0]);
390     promiseCtx->deferred = CommonNapi::CreatePromise(env, promiseCtx->callbackRef, result);
391     auto state = jsPlayer->GetCurrentState();
392     if (state != AVPlayerState::STATE_PREPARED &&
393         state != AVPlayerState::STATE_PAUSED &&
394         state != AVPlayerState::STATE_COMPLETED &&
395         state != AVPlayerState::STATE_PLAYING) {
396         promiseCtx->SignError(MSERR_EXT_API9_OPERATE_NOT_PERMIT,
397             "current state is not prepared/paused/completed, unsupport play operation");
398     } else if (state == AVPlayerState::STATE_COMPLETED && jsPlayer->IsLiveSource()) {
399         promiseCtx->SignError(MSERR_EXT_API9_UNSUPPORT_CAPABILITY,
400             "In live mode, replay not be allowed.");
401     } else {
402         MEDIA_LOGI("0x%{public}06" PRIXPTR " JsPlay EnqueueTask In", FAKE_POINTER(jsPlayer));
403         promiseCtx->asyncTask = jsPlayer->PlayTask();
404         MEDIA_LOGI("0x%{public}06" PRIXPTR " JsPlay EnqueueTask Out", FAKE_POINTER(jsPlayer));
405     }
406 #ifdef SUPPORT_JSSTACK
407     HiviewDFX::ReportXPowerJsStackSysEvent(env, "STREAM_CHANGE", "SRC=Media");
408 #endif
409     napi_value resource = nullptr;
410     napi_create_string_utf8(env, "JsPlay", NAPI_AUTO_LENGTH, &resource);
411     NAPI_CALL(env, napi_create_async_work(env, nullptr, resource,
412         [](napi_env env, void *data) {
413             MEDIA_LOGI("Wait JsPlay Task Start");
414             auto promiseCtx = reinterpret_cast<AVPlayerContext *>(data);
415             CHECK_AND_RETURN_LOG(promiseCtx != nullptr, "promiseCtx is nullptr!");
416             promiseCtx->CheckTaskResult(true, TASK_TIME_LIMIT_MS);
417             MEDIA_LOGI("Wait JsPlay Task End");
418         },
419         MediaAsyncContext::CompleteCallback, static_cast<void *>(promiseCtx.get()), &promiseCtx->work));
420     napi_queue_async_work_with_qos(env, promiseCtx->work, napi_qos_user_initiated);
421     promiseCtx.release();
422     MEDIA_LOGI("0x%{public}06" PRIXPTR " JsPlay Out", FAKE_POINTER(jsPlayer));
423     return result;
424 }
425 
PauseTask()426 std::shared_ptr<TaskHandler<TaskRet>> AVPlayerNapi::PauseTask()
427 {
428     auto task = std::make_shared<TaskHandler<TaskRet>>([this]() {
429         MEDIA_LOGI("0x%{public}06" PRIXPTR " Pause Task In", FAKE_POINTER(this));
430         std::unique_lock<std::mutex> lock(taskMutex_);
431         auto state = GetCurrentState();
432         if (state == AVPlayerState::STATE_PLAYING) {
433             int32_t ret = player_->Pause();
434             if (ret != MSERR_OK) {
435                 auto errCode = MSErrorToExtErrorAPI9(static_cast<MediaServiceErrCode>(ret));
436                 return TaskRet(errCode, "failed to Pause");
437             }
438             stopWait_ = false;
439             stateChangeCond_.wait(lock, [this]() { return stopWait_.load() || avplayerExit_; });
440         } else if (state == AVPlayerState::STATE_PAUSED) {
441             MEDIA_LOGI("current state is paused, invalid operation");
442         } else {
443             return TaskRet(MSERR_EXT_API9_OPERATE_NOT_PERMIT,
444                 "current state is not playing, unsupport pause operation");
445         }
446 
447         MEDIA_LOGI("0x%{public}06" PRIXPTR " Pause Task Out", FAKE_POINTER(this));
448         return TaskRet(MSERR_EXT_API9_OK, "Success");
449     });
450     (void)taskQue_->EnqueueTask(task);
451     return task;
452 }
453 
JsPause(napi_env env,napi_callback_info info)454 napi_value AVPlayerNapi::JsPause(napi_env env, napi_callback_info info)
455 {
456     MediaTrace trace("AVPlayerNapi::pause");
457     napi_value result = nullptr;
458     napi_get_undefined(env, &result);
459     MEDIA_LOGI("JsPause In");
460 
461     auto promiseCtx = std::make_unique<AVPlayerContext>(env);
462     napi_value args[1] = { nullptr };
463     size_t argCount = 1;
464     AVPlayerNapi *jsPlayer = AVPlayerNapi::GetJsInstanceWithParameter(env, info, argCount, args);
465     CHECK_AND_RETURN_RET_LOG(jsPlayer != nullptr, result, "failed to GetJsInstance");
466 
467     promiseCtx->callbackRef = CommonNapi::CreateReference(env, args[0]);
468     promiseCtx->deferred = CommonNapi::CreatePromise(env, promiseCtx->callbackRef, result);
469     auto state = jsPlayer->GetCurrentState();
470     if (state != AVPlayerState::STATE_PLAYING &&
471         state != AVPlayerState::STATE_PAUSED) {
472         promiseCtx->SignError(MSERR_EXT_API9_OPERATE_NOT_PERMIT,
473             "current state is not playing, unsupport pause operation");
474     } else {
475         MEDIA_LOGI("0x%{public}06" PRIXPTR " JsPause EnqueueTask In", FAKE_POINTER(jsPlayer));
476         promiseCtx->asyncTask = jsPlayer->PauseTask();
477         MEDIA_LOGI("0x%{public}06" PRIXPTR " JsPause EnqueueTask Out", FAKE_POINTER(jsPlayer));
478     }
479 
480     napi_value resource = nullptr;
481     napi_create_string_utf8(env, "JsPause", NAPI_AUTO_LENGTH, &resource);
482     NAPI_CALL(env, napi_create_async_work(env, nullptr, resource,
483         [](napi_env env, void *data) {
484             MEDIA_LOGI("Wait JsPause Task Start");
485             auto promiseCtx = reinterpret_cast<AVPlayerContext *>(data);
486             CHECK_AND_RETURN_LOG(promiseCtx != nullptr, "promiseCtx is nullptr!");
487             promiseCtx->CheckTaskResult();
488             MEDIA_LOGI("Wait JsPause Task End");
489         },
490         MediaAsyncContext::CompleteCallback, static_cast<void *>(promiseCtx.get()), &promiseCtx->work));
491     napi_queue_async_work_with_qos(env, promiseCtx->work, napi_qos_user_initiated);
492     promiseCtx.release();
493     MEDIA_LOGI("0x%{public}06" PRIXPTR " JsPause Out", FAKE_POINTER(jsPlayer));
494     return result;
495 }
496 
StopTask()497 std::shared_ptr<TaskHandler<TaskRet>> AVPlayerNapi::StopTask()
498 {
499     auto task = std::make_shared<TaskHandler<TaskRet>>([this]() {
500         MEDIA_LOGI("0x%{public}06" PRIXPTR " Stop Task In", FAKE_POINTER(this));
501         std::unique_lock<std::mutex> lock(taskMutex_);
502         if (IsControllable()) {
503             int32_t ret = player_->Stop();
504             if (ret != MSERR_OK) {
505                 auto errCode = MSErrorToExtErrorAPI9(static_cast<MediaServiceErrCode>(ret));
506                 return TaskRet(errCode, "failed to Stop");
507             }
508             stopWait_ = false;
509             stateChangeCond_.wait(lock, [this]() { return stopWait_.load() || avplayerExit_; });
510         } else if (GetCurrentState() == AVPlayerState::STATE_STOPPED) {
511             MEDIA_LOGI("current state is stopped, invalid operation");
512         }  else {
513             return TaskRet(MSERR_EXT_API9_OPERATE_NOT_PERMIT,
514                 "current state is not prepared/playing/paused/completed, unsupport stop operation");
515         }
516 
517         MEDIA_LOGI("0x%{public}06" PRIXPTR " Stop Task Out", FAKE_POINTER(this));
518         return TaskRet(MSERR_EXT_API9_OK, "Success");
519     });
520     (void)taskQue_->EnqueueTask(task);
521     return task;
522 }
523 
JsStop(napi_env env,napi_callback_info info)524 napi_value AVPlayerNapi::JsStop(napi_env env, napi_callback_info info)
525 {
526     MediaTrace trace("AVPlayerNapi::stop");
527     napi_value result = nullptr;
528     napi_get_undefined(env, &result);
529     MEDIA_LOGI("JsStop In");
530 
531     auto promiseCtx = std::make_unique<AVPlayerContext>(env);
532     napi_value args[1] = { nullptr };
533     size_t argCount = 1;
534     AVPlayerNapi *jsPlayer = AVPlayerNapi::GetJsInstanceWithParameter(env, info, argCount, args);
535     CHECK_AND_RETURN_RET_LOG(jsPlayer != nullptr, result, "failed to GetJsInstance");
536 
537     promiseCtx->callbackRef = CommonNapi::CreateReference(env, args[0]);
538     promiseCtx->deferred = CommonNapi::CreatePromise(env, promiseCtx->callbackRef, result);
539     auto state = jsPlayer->GetCurrentState();
540     if (state == AVPlayerState::STATE_IDLE ||
541         state == AVPlayerState::STATE_INITIALIZED ||
542         state == AVPlayerState::STATE_RELEASED ||
543         state == AVPlayerState::STATE_ERROR) {
544         promiseCtx->SignError(MSERR_EXT_API9_OPERATE_NOT_PERMIT,
545             "current state is not prepared/playing/paused/completed, unsupport stop operation");
546     } else {
547         MEDIA_LOGI("0x%{public}06" PRIXPTR " JsStop EnqueueTask In", FAKE_POINTER(jsPlayer));
548         promiseCtx->asyncTask = jsPlayer->StopTask();
549         MEDIA_LOGI("0x%{public}06" PRIXPTR " JsStop EnqueueTask Out", FAKE_POINTER(jsPlayer));
550     }
551 
552     napi_value resource = nullptr;
553     napi_create_string_utf8(env, "JsStop", NAPI_AUTO_LENGTH, &resource);
554     NAPI_CALL(env, napi_create_async_work(env, nullptr, resource,
555         [](napi_env env, void *data) {
556             MEDIA_LOGI("Wait JsStop Task Start");
557             auto promiseCtx = reinterpret_cast<AVPlayerContext *>(data);
558             CHECK_AND_RETURN_LOG(promiseCtx != nullptr, "promiseCtx is nullptr!");
559             promiseCtx->CheckTaskResult();
560             MEDIA_LOGI("Wait JsStop Task End");
561         },
562         MediaAsyncContext::CompleteCallback, static_cast<void *>(promiseCtx.get()), &promiseCtx->work));
563     napi_queue_async_work_with_qos(env, promiseCtx->work, napi_qos_user_initiated);
564     promiseCtx.release();
565     MEDIA_LOGI("0x%{public}06" PRIXPTR " JsStop Out", FAKE_POINTER(jsPlayer));
566     return result;
567 }
568 
ResetTask()569 std::shared_ptr<TaskHandler<TaskRet>> AVPlayerNapi::ResetTask()
570 {
571     auto task = std::make_shared<TaskHandler<TaskRet>>([this]() {
572         MEDIA_LOGI("0x%{public}06" PRIXPTR " Reset Task In", FAKE_POINTER(this));
573         PauseListenCurrentResource(); // Pause event listening for the current resource
574         ResetUserParameters();
575         {
576             isInterrupted_.store(false);
577             std::unique_lock<std::mutex> lock(taskMutex_);
578             if (GetCurrentState() == AVPlayerState::STATE_RELEASED) {
579                 return TaskRet(MSERR_EXT_API9_OPERATE_NOT_PERMIT,
580                     "current state is not playing, unsupport pause operation");
581             } else if (GetCurrentState() == AVPlayerState::STATE_IDLE) {
582                 MEDIA_LOGI("current state is idle, invalid operation");
583             } else {
584                 int32_t ret = player_->Reset();
585                 if (ret != MSERR_OK) {
586                     auto errCode = MSErrorToExtErrorAPI9(static_cast<MediaServiceErrCode>(ret));
587                     return TaskRet(errCode, "failed to Reset");
588                 }
589                 stopWait_ = false;
590                 stateChangeCond_.wait(lock, [this]() { return stopWait_.load() || avplayerExit_; });
591             }
592         }
593         MEDIA_LOGI("0x%{public}06" PRIXPTR " Reset Task Out", FAKE_POINTER(this));
594         return TaskRet(MSERR_EXT_API9_OK, "Success");
595     });
596     (void)taskQue_->EnqueueTask(task, true); // CancelNotExecutedTask
597     isInterrupted_.store(true);
598     stateChangeCond_.notify_all();
599     return task;
600 }
601 
JsReset(napi_env env,napi_callback_info info)602 napi_value AVPlayerNapi::JsReset(napi_env env, napi_callback_info info)
603 {
604     MediaTrace trace("AVPlayerNapi::reset");
605     napi_value result = nullptr;
606     napi_get_undefined(env, &result);
607     MEDIA_LOGI("JsReset In");
608 
609     auto promiseCtx = std::make_unique<AVPlayerContext>(env);
610     napi_value args[1] = { nullptr };
611     size_t argCount = 1;
612     AVPlayerNapi *jsPlayer = AVPlayerNapi::GetJsInstanceWithParameter(env, info, argCount, args);
613     CHECK_AND_RETURN_RET_LOG(jsPlayer != nullptr, result, "failed to GetJsInstance");
614     promiseCtx->callbackRef = CommonNapi::CreateReference(env, args[0]);
615     promiseCtx->deferred = CommonNapi::CreatePromise(env, promiseCtx->callbackRef, result);
616     if (jsPlayer->GetCurrentState() == AVPlayerState::STATE_RELEASED) {
617         promiseCtx->SignError(MSERR_EXT_API9_OPERATE_NOT_PERMIT,
618             "current state is released, unsupport reset operation");
619     } else {
620         MEDIA_LOGI("0x%{public}06" PRIXPTR " JsReset EnqueueTask In", FAKE_POINTER(jsPlayer));
621         promiseCtx->asyncTask = jsPlayer->ResetTask();
622         MEDIA_LOGI("0x%{public}06" PRIXPTR " JsReset EnqueueTask Out", FAKE_POINTER(jsPlayer));
623         if (jsPlayer->dataSrcCb_ != nullptr) {
624             jsPlayer->dataSrcCb_->ClearCallbackReference();
625             jsPlayer->dataSrcCb_ = nullptr;
626         }
627         jsPlayer->isLiveStream_ = false;
628     }
629 
630     napi_value resource = nullptr;
631     napi_create_string_utf8(env, "JsReset", NAPI_AUTO_LENGTH, &resource);
632     NAPI_CALL(env, napi_create_async_work(env, nullptr, resource,
633         [](napi_env env, void *data) {
634             auto promiseCtx = reinterpret_cast<AVPlayerContext *>(data);
635             CHECK_AND_RETURN_LOG(promiseCtx != nullptr, "promiseCtx is nullptr!");
636             if (promiseCtx->asyncTask != nullptr) {
637                 MEDIA_LOGI("Wait Reset Task Start");
638                 promiseCtx->CheckTaskResult();
639                 MEDIA_LOGI("Wait Reset Task Stop");
640             }
641         },
642         MediaAsyncContext::CompleteCallback, static_cast<void *>(promiseCtx.get()), &promiseCtx->work));
643     napi_queue_async_work_with_qos(env, promiseCtx->work, napi_qos_user_initiated);
644     promiseCtx.release();
645     MEDIA_LOGI("0x%{public}06" PRIXPTR " JsReset Out", FAKE_POINTER(jsPlayer));
646     return result;
647 }
648 
WaitTaskQueStop()649 void AVPlayerNapi::WaitTaskQueStop()
650 {
651     MEDIA_LOGI("0x%{public}06" PRIXPTR " WaitTaskQueStop In", FAKE_POINTER(this));
652     std::unique_lock<std::mutex> lock(mutex_);
653     stopTaskQueCond_.wait(lock, [this]() { return taskQueStoped_; });
654     MEDIA_LOGI("0x%{public}06" PRIXPTR " WaitTaskQueStop Out", FAKE_POINTER(this));
655 }
656 
StopTaskQue()657 void AVPlayerNapi::StopTaskQue()
658 {
659     MEDIA_LOGI("0x%{public}06" PRIXPTR " StopTaskQue In", FAKE_POINTER(this));
660     {
661         std::unique_lock<std::mutex> lock(taskMutex_);
662         avplayerExit_ = true;
663     }
664     stateChangeCond_.notify_all();
665     taskQue_->Stop();
666     std::unique_lock<std::mutex> lock(mutex_);
667     taskQueStoped_ = true;
668     stopTaskQueCond_.notify_all();
669     MEDIA_LOGI("0x%{public}06" PRIXPTR " StopTaskQue Out", FAKE_POINTER(this));
670 }
671 
ReleaseTask()672 std::shared_ptr<TaskHandler<TaskRet>> AVPlayerNapi::ReleaseTask()
673 {
674     std::shared_ptr<TaskHandler<TaskRet>> task = nullptr;
675     if (!isReleased_.load()) {
676         task = std::make_shared<TaskHandler<TaskRet>>([this]() {
677             MEDIA_LOGI("0x%{public}06" PRIXPTR " Release Task In", FAKE_POINTER(this));
678             PauseListenCurrentResource(); // Pause event listening for the current resource
679             ResetUserParameters();
680 
681             {
682                 std::lock_guard<std::mutex> lock(syncMutex_);
683                 if (player_ != nullptr) {
684                     (void)player_->ReleaseSync();
685                     player_ = nullptr;
686                 }
687             }
688 
689             if (playerCb_ != nullptr) {
690                 playerCb_->Release();
691             }
692             MEDIA_LOGI("0x%{public}06" PRIXPTR " Release Task Out", FAKE_POINTER(this));
693             std::thread([this] () -> void { this->StopTaskQue(); }).detach();
694             return TaskRet(MSERR_EXT_API9_OK, "Success");
695         });
696 
697         isReleased_.store(true);
698         (void)taskQue_->EnqueueTask(task, true); // CancelNotExecutedTask
699         if (taskQue_->IsTaskExecuting()) {
700             MEDIA_LOGW("0x%{public}06" PRIXPTR " Cancel Executing Task, ReleaseTask Report Error", FAKE_POINTER(this));
701             NotifyState(PlayerStates::PLAYER_STATE_ERROR);
702         }
703     }
704     return task;
705 }
706 
JsRelease(napi_env env,napi_callback_info info)707 napi_value AVPlayerNapi::JsRelease(napi_env env, napi_callback_info info)
708 {
709     MediaTrace trace("AVPlayerNapi::release");
710     napi_value result = nullptr;
711     napi_get_undefined(env, &result);
712     MEDIA_LOGI("JsRelease In");
713 
714     auto promiseCtx = std::make_unique<AVPlayerContext>(env);
715     napi_value args[1] = { nullptr };
716     size_t argCount = 1;
717     AVPlayerNapi *jsPlayer = AVPlayerNapi::GetJsInstanceWithParameter(env, info, argCount, args);
718     CHECK_AND_RETURN_RET_LOG(jsPlayer != nullptr, result, "failed to GetJsInstance");
719     promiseCtx->callbackRef = CommonNapi::CreateReference(env, args[0]);
720     promiseCtx->deferred = CommonNapi::CreatePromise(env, promiseCtx->callbackRef, result);
721     MEDIA_LOGI("0x%{public}06" PRIXPTR " JsRelease EnqueueTask In", FAKE_POINTER(jsPlayer));
722     promiseCtx->asyncTask = jsPlayer->ReleaseTask();
723     MEDIA_LOGI("0x%{public}06" PRIXPTR " JsRelease EnqueueTask Out", FAKE_POINTER(jsPlayer));
724     if (jsPlayer->dataSrcCb_ != nullptr) {
725         jsPlayer->dataSrcCb_->ClearCallbackReference();
726         jsPlayer->dataSrcCb_ = nullptr;
727     }
728 
729     napi_value resource = nullptr;
730     napi_create_string_utf8(env, "JsRelease", NAPI_AUTO_LENGTH, &resource);
731     NAPI_CALL(env, napi_create_async_work(env, nullptr, resource,
732         [](napi_env env, void *data) {
733             auto promiseCtx = reinterpret_cast<AVPlayerContext *>(data);
734             CHECK_AND_RETURN_LOG(promiseCtx != nullptr, "promiseCtx is nullptr!");
735             if (promiseCtx->asyncTask != nullptr) {
736                 MEDIA_LOGI("Wait Release Task Start");
737                 promiseCtx->CheckTaskResult();
738                 MEDIA_LOGI("Wait Release Task Stop");
739             }
740         },
741         MediaAsyncContext::CompleteCallback, static_cast<void *>(promiseCtx.get()), &promiseCtx->work));
742     napi_queue_async_work_with_qos(env, promiseCtx->work, napi_qos_user_initiated);
743     promiseCtx.release();
744     MEDIA_LOGI("0x%{public}06" PRIXPTR " JsRelease Out", FAKE_POINTER(jsPlayer));
745     return result;
746 }
747 
JsSeek(napi_env env,napi_callback_info info)748 napi_value AVPlayerNapi::JsSeek(napi_env env, napi_callback_info info)
749 {
750     MediaTrace trace("AVPlayerNapi::seek");
751     MEDIA_LOGI("JsSeek in");
752     napi_value result = nullptr;
753     napi_get_undefined(env, &result);
754     napi_value args[ARRAY_ARG_COUNTS_TWO] = { nullptr }; // args[0]:timeMs, args[1]:SeekMode
755     size_t argCount = 2; // args[0]:timeMs, args[1]:SeekMode
756     AVPlayerNapi *jsPlayer = AVPlayerNapi::GetJsInstanceWithParameter(env, info, argCount, args);
757     CHECK_AND_RETURN_RET_LOG(jsPlayer != nullptr, result, "failed to GetJsInstanceWithParameter");
758     if (jsPlayer->IsLiveSource()) {
759         jsPlayer->OnErrorCb(MSERR_EXT_API9_UNSUPPORT_CAPABILITY, "The stream is live stream, not support seek");
760         return result;
761     }
762     napi_valuetype valueType = napi_undefined;
763     if (argCount < 1 || napi_typeof(env, args[0], &valueType) != napi_ok || valueType != napi_number) {
764         jsPlayer->OnErrorCb(MSERR_EXT_API9_INVALID_PARAMETER, "seek time is not number");
765         return result;
766     }
767     int32_t time = -1;
768     napi_status status = napi_get_value_int32(env, args[0], &time);
769     if (status != napi_ok || (time < 0 && argCount == 1)) {
770         jsPlayer->OnErrorCb(MSERR_EXT_API9_INVALID_PARAMETER, "invalid parameters, please check seek time");
771         return result;
772     }
773     int32_t mode = SEEK_PREVIOUS_SYNC;
774     if (argCount > 1) {
775         if (napi_typeof(env, args[1], &valueType) != napi_ok || valueType != napi_number) {
776             jsPlayer->OnErrorCb(MSERR_EXT_API9_INVALID_PARAMETER, "seek mode is not number");
777             return result;
778         }
779         status = napi_get_value_int32(env, args[1], &mode);
780         if (status != napi_ok || mode < SEEK_NEXT_SYNC || mode > SEEK_CONTINUOUS_TS_ENUM_NUM) {
781             jsPlayer->OnErrorCb(MSERR_EXT_API9_INVALID_PARAMETER, "invalid parameters, please check seek mode");
782             return result;
783         }
784         bool isNegativeTime = time < 0;
785         bool isExitSeekContinuous = time == -1 && mode == SEEK_CONTINUOUS_TS_ENUM_NUM;
786         if (isNegativeTime && !isExitSeekContinuous) {
787             jsPlayer->OnErrorCb(MSERR_EXT_API9_INVALID_PARAMETER, "invalid parameters, please check seek time");
788             return result;
789         }
790     }
791     if (!jsPlayer->IsControllable()) {
792         jsPlayer->OnErrorCb(MSERR_EXT_API9_OPERATE_NOT_PERMIT,
793             "current state is not prepared/playing/paused/completed, unsupport seek operation");
794         return result;
795     }
796     SeekEnqueueTask(jsPlayer, time, mode);
797     return result;
798 }
799 
TransferSeekMode(int32_t mode)800 PlayerSeekMode AVPlayerNapi::TransferSeekMode(int32_t mode)
801 {
802     MEDIA_LOGI("Seek Task TransferSeekMode, mode: %{public}d", mode);
803     PlayerSeekMode seekMode = PlayerSeekMode::SEEK_PREVIOUS_SYNC;
804     switch (mode) {
805         case 0: // Seek to the next sync frame of the given timestamp.
806             seekMode = PlayerSeekMode::SEEK_NEXT_SYNC;
807             break;
808         case 1: // Seek to the previous sync frame of the given timestamp.
809             seekMode = PlayerSeekMode::SEEK_PREVIOUS_SYNC;
810             break;
811         case 2: // Seek to the closest frame of the given timestamp. 2 refers SeekMode in @ohos.multimedia.media.d.ts
812             seekMode = PlayerSeekMode::SEEK_CLOSEST;
813             break;
814         case 3: // Seek continous of the given timestamp. 3 refers SeekMode in @ohos.multimedia.media.d.ts
815             seekMode = PlayerSeekMode::SEEK_CONTINOUS;
816             break;
817         default:
818             seekMode = PlayerSeekMode::SEEK_PREVIOUS_SYNC;
819             break;
820     }
821     return seekMode;
822 }
823 
JsSetPlaybackRange(napi_env env,napi_callback_info info)824 napi_value AVPlayerNapi::JsSetPlaybackRange(napi_env env, napi_callback_info info)
825 {
826     MediaTrace trace("AVPlayerNapi::setPlaybackRange");
827     napi_value result = nullptr;
828     napi_get_undefined(env, &result);
829     MEDIA_LOGI("JsSetPlaybackRange In");
830 
831     auto promiseCtx = std::make_unique<AVPlayerContext>(env);
832     napi_value args[ARRAY_ARG_COUNTS_THREE] = { nullptr };
833     size_t argCount = ARRAY_ARG_COUNTS_THREE; // args[0]:startTimeMs, args[1]:endTimeMs, args[2]:SeekMode
834     AVPlayerNapi *jsPlayer = AVPlayerNapi::GetJsInstanceWithParameter(env, info, argCount, args);
835     CHECK_AND_RETURN_RET_LOG(jsPlayer != nullptr, result, "failed to GetJsInstance");
836 
837     promiseCtx->deferred = CommonNapi::CreatePromise(env, nullptr, result);
838     napi_valuetype valueType = napi_undefined;
839     int32_t startTimeMs = PLAY_RANGE_DEFAULT_VALUE;
840     int32_t endTimeMs = PLAY_RANGE_DEFAULT_VALUE;
841     int32_t mode = SEEK_PREVIOUS_SYNC;
842     if (!jsPlayer->CanSetPlayRange()) {
843         promiseCtx->SignError(MSERR_EXT_API9_OPERATE_NOT_PERMIT,
844             "current state is not initialized/prepared/paused/stopped/completed, unsupport setPlaybackRange operation");
845     } else if (argCount < ARRAY_ARG_COUNTS_TWO || napi_typeof(env, args[INDEX_A], &valueType) != napi_ok ||
846         valueType != napi_number || napi_typeof(env, args[INDEX_B], &valueType) != napi_ok || valueType != napi_number
847         || napi_get_value_int32(env, args[INDEX_A], &startTimeMs) != napi_ok ||
848         napi_get_value_int32(env, args[INDEX_B], &endTimeMs) != napi_ok ||
849         startTimeMs < PLAY_RANGE_DEFAULT_VALUE || endTimeMs < PLAY_RANGE_DEFAULT_VALUE) {
850         promiseCtx->SignError(MSERR_EXT_API9_INVALID_PARAMETER, "invalid parameters, please check start or end time");
851     } else if (argCount > ARRAY_ARG_COUNTS_TWO && (napi_typeof(env, args[INDEX_C], &valueType) != napi_ok ||
852         valueType != napi_number || napi_get_value_int32(env, args[INDEX_C], &mode) != napi_ok ||
853         mode < SEEK_PREVIOUS_SYNC || mode > SEEK_MODE_CLOSEST)) {
854         promiseCtx->SignError(MSERR_EXT_API9_INVALID_PARAMETER, "invalid parameters, please check seek mode");
855     } else {
856         promiseCtx->asyncTask = jsPlayer->EqueueSetPlayRangeTask(startTimeMs, endTimeMs, mode);
857         MEDIA_LOGI("0x%{public}06" PRIXPTR " JsSetPlaybackRange EnqueueTask Out", FAKE_POINTER(jsPlayer));
858     }
859 
860     napi_value resource = nullptr;
861     napi_create_string_utf8(env, "JsSetPlaybackRange", NAPI_AUTO_LENGTH, &resource);
862     NAPI_CALL(env, napi_create_async_work(env, nullptr, resource,
863         [](napi_env env, void *data) {
864             MEDIA_LOGI("Wait JsSetPlaybackRange Task Start");
865             auto promiseCtx = reinterpret_cast<AVPlayerContext *>(data);
866             CHECK_AND_RETURN_LOG(promiseCtx != nullptr, "promiseCtx is nullptr!");
867             promiseCtx->CheckTaskResult();
868             MEDIA_LOGI("Wait JsSetPlaybackRange Task End");
869         },
870         MediaAsyncContext::CompleteCallback, static_cast<void *>(promiseCtx.get()), &promiseCtx->work));
871     napi_queue_async_work_with_qos(env, promiseCtx->work, napi_qos_user_initiated);
872     promiseCtx.release();
873     MEDIA_LOGI("0x%{public}06" PRIXPTR " JsSetPlaybackRange Out", FAKE_POINTER(jsPlayer));
874     return result;
875 }
876 
EqueueSetPlayRangeTask(int32_t start,int32_t end,int32_t mode)877 std::shared_ptr<TaskHandler<TaskRet>> AVPlayerNapi::EqueueSetPlayRangeTask(int32_t start, int32_t end, int32_t mode)
878 {
879     auto task = std::make_shared<TaskHandler<TaskRet>>([this, start, end, mode]() {
880         std::unique_lock<std::mutex> lock(taskMutex_);
881         MEDIA_LOGI("0x%{public}06" PRIXPTR " JsSetPlaybackRange Task In", FAKE_POINTER(this));
882         if (player_ != nullptr) {
883             auto ret = player_->SetPlayRangeWithMode(start, end, TransferSeekMode(mode));
884             if (ret != MSERR_OK) {
885                 auto errCode = MSErrorToExtErrorAPI9(static_cast<MediaServiceErrCode>(ret));
886                 return TaskRet(errCode, "failed to setPlaybackRange");
887             }
888         }
889         MEDIA_LOGI("0x%{public}06" PRIXPTR " JsSetPlaybackRange Task Out", FAKE_POINTER(this));
890         return TaskRet(MSERR_EXT_API9_OK, "Success");
891     });
892     (void)taskQue_->EnqueueTask(task);
893     return task;
894 }
895 
TransferSwitchMode(int32_t mode)896 PlayerSwitchMode AVPlayerNapi::TransferSwitchMode(int32_t mode)
897 {
898     MEDIA_LOGI("Seek Task TransferSeekMode, mode: %{public}d", mode);
899     PlayerSwitchMode switchMode = PlayerSwitchMode::SWITCH_CLOSEST;
900     switch (mode) {
901         case 0:
902             switchMode = PlayerSwitchMode::SWITCH_SMOOTH;
903             break;
904         case 1:
905             switchMode = PlayerSwitchMode::SWITCH_SEGMENT;
906             break;
907         default:
908             break;
909     }
910     return switchMode;
911 }
912 
JsSetSpeed(napi_env env,napi_callback_info info)913 napi_value AVPlayerNapi::JsSetSpeed(napi_env env, napi_callback_info info)
914 {
915     MediaTrace trace("AVPlayerNapi::setSpeed");
916     napi_value result = nullptr;
917     napi_get_undefined(env, &result);
918     MEDIA_LOGI("JsSetSpeed In");
919 
920     napi_value args[1] = { nullptr };
921     size_t argCount = 1; // setSpeed(speed: number)
922     AVPlayerNapi *jsPlayer = AVPlayerNapi::GetJsInstanceWithParameter(env, info, argCount, args);
923     CHECK_AND_RETURN_RET_LOG(jsPlayer != nullptr, result, "failed to GetJsInstanceWithParameter");
924 
925     if (jsPlayer->IsLiveSource()) {
926         jsPlayer->OnErrorCb(MSERR_EXT_API9_UNSUPPORT_CAPABILITY, "The stream is live stream, not support speed");
927         return result;
928     }
929 
930     napi_valuetype valueType = napi_undefined;
931     if (argCount < 1 || napi_typeof(env, args[0], &valueType) != napi_ok || valueType != napi_number) {
932         jsPlayer->OnErrorCb(MSERR_EXT_API9_INVALID_PARAMETER, "speed mode is not number");
933         return result;
934     }
935 
936     int32_t mode = SPEED_FORWARD_1_00_X;
937     napi_status status = napi_get_value_int32(env, args[0], &mode);
938     if (status != napi_ok || mode < SPEED_FORWARD_0_75_X || mode > SPEED_FORWARD_0_125_X) {
939         jsPlayer->OnErrorCb(MSERR_EXT_API9_INVALID_PARAMETER,
940             "invalid parameters, please check the speed mode");
941         return result;
942     }
943 
944     if (!jsPlayer->IsControllable()) {
945         jsPlayer->OnErrorCb(MSERR_EXT_API9_OPERATE_NOT_PERMIT,
946             "current state is not prepared/playing/paused/completed, unsupport speed operation");
947         return result;
948     }
949 
950     auto task = std::make_shared<TaskHandler<void>>([jsPlayer, mode]() {
951         MEDIA_LOGI("0x%{public}06" PRIXPTR " Speed Task In", FAKE_POINTER(jsPlayer));
952         if (jsPlayer->player_ != nullptr) {
953             (void)jsPlayer->player_->SetPlaybackSpeed(static_cast<PlaybackRateMode>(mode));
954         }
955         MEDIA_LOGI("0x%{public}06" PRIXPTR " Speed Task Out", FAKE_POINTER(jsPlayer));
956     });
957     MEDIA_LOGI("0x%{public}06" PRIXPTR " JsSetSpeed EnqueueTask In", FAKE_POINTER(jsPlayer));
958     (void)jsPlayer->taskQue_->EnqueueTask(task);
959     MEDIA_LOGI("0x%{public}06" PRIXPTR " JsSetSpeed Out", FAKE_POINTER(jsPlayer));
960     return result;
961 }
962 
JsSetVolume(napi_env env,napi_callback_info info)963 napi_value AVPlayerNapi::JsSetVolume(napi_env env, napi_callback_info info)
964 {
965     MediaTrace trace("AVPlayerNapi::setVolume");
966     napi_value result = nullptr;
967     napi_get_undefined(env, &result);
968     MEDIA_LOGI("JsSetVolume In");
969 
970     napi_value args[1] = { nullptr };
971     size_t argCount = 1; // setVolume(vol: number)
972     AVPlayerNapi *jsPlayer = AVPlayerNapi::GetJsInstanceWithParameter(env, info, argCount, args);
973     CHECK_AND_RETURN_RET_LOG(jsPlayer != nullptr, result, "failed to GetJsInstanceWithParameter");
974 
975     if (jsPlayer->playerCb_->isSetVolume_) {
976         MEDIA_LOGI("SetVolume is processing, skip this task until onVolumeChangedCb");
977     }
978     jsPlayer->playerCb_->isSetVolume_ = true;
979 
980     napi_valuetype valueType = napi_undefined;
981     if (argCount < 1 || napi_typeof(env, args[0], &valueType) != napi_ok || valueType != napi_number) {
982         jsPlayer->OnErrorCb(MSERR_EXT_API9_INVALID_PARAMETER, "setVolume level is not number");
983         return result;
984     }
985 
986     double volumeLevel = 1.0f;
987     napi_status status = napi_get_value_double(env, args[0], &volumeLevel);
988     if (status != napi_ok || volumeLevel < 0.0f || volumeLevel > 1.0f) {
989         jsPlayer->OnErrorCb(MSERR_EXT_API9_INVALID_PARAMETER, "invalid parameters, check volume level");
990         return result;
991     }
992 
993     if (!jsPlayer->IsControllable()) {
994         jsPlayer->OnErrorCb(MSERR_EXT_API9_OPERATE_NOT_PERMIT,
995             "current state is not prepared/playing/paused/completed, unsupport volume operation");
996         return result;
997     }
998 #ifdef SUPPORT_JSSTACK
999     HiviewDFX::ReportXPowerJsStackSysEvent(env, "VOLUME_CHANGE", "SRC=Media");
1000 #endif
1001     auto task = std::make_shared<TaskHandler<void>>([jsPlayer, volumeLevel]() {
1002         MEDIA_LOGD("SetVolume Task");
1003         if (jsPlayer->player_ != nullptr) {
1004             (void)jsPlayer->player_->SetVolume(volumeLevel, volumeLevel);
1005         }
1006     });
1007     (void)jsPlayer->taskQue_->EnqueueTask(task);
1008     MEDIA_LOGI("JsSetVolume Out");
1009     return result;
1010 }
1011 
JsSelectBitrate(napi_env env,napi_callback_info info)1012 napi_value AVPlayerNapi::JsSelectBitrate(napi_env env, napi_callback_info info)
1013 {
1014     MediaTrace trace("AVPlayerNapi::setBitrate");
1015     napi_value result = nullptr;
1016     napi_get_undefined(env, &result);
1017     MEDIA_LOGI("JsSelectBitrate In");
1018 
1019     napi_value args[1] = { nullptr };
1020     size_t argCount = 1; // selectBitrate(bitRate: number)
1021     AVPlayerNapi *jsPlayer = AVPlayerNapi::GetJsInstanceWithParameter(env, info, argCount, args);
1022     CHECK_AND_RETURN_RET_LOG(jsPlayer != nullptr, result, "failed to GetJsInstanceWithParameter");
1023 
1024     napi_valuetype valueType = napi_undefined;
1025     if (argCount < 1 || napi_typeof(env, args[0], &valueType) != napi_ok || valueType != napi_number) {
1026         jsPlayer->OnErrorCb(MSERR_EXT_API9_INVALID_PARAMETER, "selectBitrate is not number");
1027         return result;
1028     }
1029 
1030     int32_t bitrate = 0;
1031     napi_status status = napi_get_value_int32(env, args[0], &bitrate);
1032     if (status != napi_ok || bitrate < 0) {
1033         jsPlayer->OnErrorCb(MSERR_EXT_API9_INVALID_PARAMETER, "invalid parameters, please check the input bitrate");
1034         return result;
1035     }
1036 
1037     if (!jsPlayer->IsControllable()) {
1038         jsPlayer->OnErrorCb(MSERR_EXT_API9_OPERATE_NOT_PERMIT,
1039             "current state is not prepared/playing/paused/completed, unsupport select bitrate operation");
1040         return result;
1041     }
1042 
1043     auto task = std::make_shared<TaskHandler<void>>([jsPlayer, bitrate]() {
1044         MEDIA_LOGI("0x%{public}06" PRIXPTR " JsSelectBitrate Task In", FAKE_POINTER(jsPlayer));
1045         if (jsPlayer->player_ != nullptr) {
1046             (void)jsPlayer->player_->SelectBitRate(static_cast<uint32_t>(bitrate));
1047         }
1048         MEDIA_LOGI("0x%{public}06" PRIXPTR " JsSelectBitrate Task Out", FAKE_POINTER(jsPlayer));
1049     });
1050     MEDIA_LOGI("0x%{public}06" PRIXPTR " JsSelectBitrate EnqueueTask In", FAKE_POINTER(jsPlayer));
1051     (void)jsPlayer->taskQue_->EnqueueTask(task);
1052     MEDIA_LOGI("0x%{public}06" PRIXPTR " JsSelectBitrate Out", FAKE_POINTER(jsPlayer));
1053     return result;
1054 }
1055 
AddSubSource(std::string url)1056 void AVPlayerNapi::AddSubSource(std::string url)
1057 {
1058     MEDIA_LOGI("input url is %{private}s!", url.c_str());
1059     bool isFd = (url.find("fd://") != std::string::npos) ? true : false;
1060     bool isNetwork = (url.find("http") != std::string::npos) ? true : false;
1061     if (isNetwork) {
1062         auto task = std::make_shared<TaskHandler<void>>([this, url]() {
1063             MEDIA_LOGI("AddSubtitleNetworkSource Task");
1064             if (player_ != nullptr) {
1065                 if (player_->AddSubSource(url) != MSERR_OK) {
1066                     OnErrorCb(MSERR_EXT_API9_INVALID_PARAMETER, "failed to AddSubtitleNetworkSource");
1067                 }
1068             }
1069         });
1070         (void)taskQue_->EnqueueTask(task);
1071     } else if (isFd) {
1072         const std::string fdHead = "fd://";
1073         std::string inputFd = url.substr(fdHead.size());
1074         int32_t fd = -1;
1075         if (!StrToInt(inputFd, fd) || fd < 0) {
1076             OnErrorCb(MSERR_EXT_API9_INVALID_PARAMETER,
1077                 "invalid parameters, The input parameter is not a fd://+numeric string");
1078             return;
1079         }
1080 
1081         auto task = std::make_shared<TaskHandler<void>>([this, fd]() {
1082             MEDIA_LOGI("AddSubtitleFdSource Task");
1083             if (player_ != nullptr) {
1084                 if (player_->AddSubSource(fd, 0, -1) != MSERR_OK) {
1085                     OnErrorCb(MSERR_EXT_API9_OPERATE_NOT_PERMIT, "failed to AddSubtitleFdSource");
1086                 }
1087             }
1088         });
1089         (void)taskQue_->EnqueueTask(task);
1090     } else {
1091         OnErrorCb(MSERR_EXT_API9_INVALID_PARAMETER,
1092             "invalid parameters, The input parameter is not fd:// or network address");
1093     }
1094 }
1095 
JsAddSubtitleUrl(napi_env env,napi_callback_info info)1096 napi_value AVPlayerNapi::JsAddSubtitleUrl(napi_env env, napi_callback_info info)
1097 {
1098     MediaTrace trace("AVPlayerNapi::addSubtitleUrl");
1099     napi_value result = nullptr;
1100     napi_get_undefined(env, &result);
1101     MEDIA_LOGI("JsAddSubtitleUrl In");
1102 
1103     napi_value args[1] = { nullptr };
1104     size_t argCount = 1; // addSubtitleUrl(url: string)
1105     AVPlayerNapi *jsPlayer = AVPlayerNapi::GetJsInstanceWithParameter(env, info, argCount, args);
1106     CHECK_AND_RETURN_RET_LOG(jsPlayer != nullptr, result, "failed to GetJsInstanceWithParameter");
1107 
1108     napi_valuetype valueType = napi_undefined;
1109     if (argCount < 1 || napi_typeof(env, args[0], &valueType) != napi_ok || valueType != napi_string) {
1110         jsPlayer->OnErrorCb(MSERR_EXT_API9_INVALID_PARAMETER, "url is not string");
1111         return result;
1112     }
1113 
1114     // get subUrl from js
1115     std::string subUrl = CommonNapi::GetStringArgument(env, args[0]);
1116     jsPlayer->AddSubSource(subUrl);
1117 
1118     MEDIA_LOGI("JsAddSubtitleUrl Out");
1119     return result;
1120 }
1121 
JsAddSubtitleAVFileDescriptor(napi_env env,napi_callback_info info)1122 napi_value AVPlayerNapi::JsAddSubtitleAVFileDescriptor(napi_env env, napi_callback_info info)
1123 {
1124     napi_value result = nullptr;
1125     napi_get_undefined(env, &result);
1126     napi_value args[3] = { nullptr };
1127     size_t argCount = 3; // url: string
1128     AVPlayerNapi *jsPlayer = AVPlayerNapi::GetJsInstanceWithParameter(env, info, argCount, args);
1129     CHECK_AND_RETURN_RET_LOG(jsPlayer != nullptr, result, "failed to GetJsInstanceWithParameter");
1130     int32_t subtitleFd = -1;
1131     napi_status status = napi_get_value_int32(env, args[0], &subtitleFd);
1132     if (status != napi_ok) {
1133         MEDIA_LOGE("JsAddSubtitleAVFileDescriptor status != napi_ok");
1134         jsPlayer->OnErrorCb(MSERR_EXT_API9_INVALID_PARAMETER,
1135             "invalid parameters, please check JsAddSubtitleAVFileDescriptor");
1136         return result;
1137     }
1138     int64_t offset = -1;
1139     napi_status status_offset = napi_get_value_int64(env, args[1], &offset);
1140     if (status_offset != napi_ok) {
1141         MEDIA_LOGE("JsAddSubtitleAVFileDescriptor status_offset != napi_ok");
1142         jsPlayer->OnErrorCb(MSERR_EXT_API9_INVALID_PARAMETER,
1143             "invalid parameters, please check JsAddSubtitleAVFileDescriptor");
1144         return result;
1145     }
1146     int64_t length = -1;
1147     napi_status status_length = napi_get_value_int64(env, args[2], &length);
1148     if (status_length != napi_ok) {
1149         MEDIA_LOGE("JsAddSubtitleAVFileDescriptor status_length != napi_ok");
1150         jsPlayer->OnErrorCb(MSERR_EXT_API9_INVALID_PARAMETER,
1151             "invalid parameters, please check JsAddSubtitleAVFileDescriptor");
1152         return result;
1153     }
1154     auto task = std::make_shared<TaskHandler<void>>([jsPlayer, subtitleFd, offset, length]() {
1155         if (jsPlayer->player_ != nullptr) {
1156             if (jsPlayer->player_->AddSubSource(subtitleFd, offset, length) != MSERR_OK) {
1157                 jsPlayer->OnErrorCb(MSERR_EXT_API9_INVALID_PARAMETER, "failed to AddSubtitleAVFileDescriptor");
1158             }
1159         }
1160     });
1161     (void)jsPlayer->taskQue_->EnqueueTask(task);
1162     MEDIA_LOGI("JsAddSubtitleAVFileDescriptor Out");
1163     return result;
1164 }
1165 
SetSource(std::string url)1166 void AVPlayerNapi::SetSource(std::string url)
1167 {
1168     bool isFd = (url.find("fd://") != std::string::npos) ? true : false;
1169     bool isNetwork = (url.find("http") != std::string::npos) ? true : false;
1170     if (isNetwork) {
1171         EnqueueNetworkTask(url);
1172     } else if (isFd) {
1173         std::string inputFd = url.substr(sizeof("fd://") - 1);
1174         int32_t fd = -1;
1175         if (!StrToInt(inputFd, fd) || fd < 0) {
1176             OnErrorCb(MSERR_EXT_API9_INVALID_PARAMETER,
1177                       "invalid parameters, The input parameter is not a fd://+numeric string");
1178             return;
1179         }
1180         EnqueueFdTask(fd);
1181     } else {
1182         OnErrorCb(MSERR_EXT_API9_INVALID_PARAMETER,
1183             "invalid parameters, The input parameter is not fd:// or network address");
1184     }
1185 }
1186 
EnqueueNetworkTask(const std::string url)1187 void AVPlayerNapi::EnqueueNetworkTask(const std::string url)
1188 {
1189     auto task = std::make_shared<TaskHandler<void>>([this, url]() {
1190         std::unique_lock<std::mutex> lock(taskMutex_);
1191         auto state = GetCurrentState();
1192         if (state != AVPlayerState::STATE_IDLE) {
1193             OnErrorCb(MSERR_EXT_API9_OPERATE_NOT_PERMIT, "current state is not idle, unsupport set url");
1194             return;
1195         }
1196         if (player_ != nullptr) {
1197             if (player_->SetSource(url) != MSERR_OK) {
1198                 QueueOnErrorCb(MSERR_EXT_API9_INVALID_PARAMETER, "failed to SetSourceNetWork");
1199                 return;
1200             }
1201             stopWait_ = false;
1202             stateChangeCond_.wait(lock, [this]() { return stopWait_.load() || avplayerExit_; });
1203             MEDIA_LOGI("0x%{public}06" PRIXPTR " Set source network out", FAKE_POINTER(this));
1204         }
1205     });
1206     (void)taskQue_->EnqueueTask(task);
1207 }
1208 
EnqueueFdTask(const int32_t fd)1209 void AVPlayerNapi::EnqueueFdTask(const int32_t fd)
1210 {
1211     auto task = std::make_shared<TaskHandler<void>>([this, fd]() {
1212         std::unique_lock<std::mutex> lock(taskMutex_);
1213         auto state = GetCurrentState();
1214         if (state != AVPlayerState::STATE_IDLE) {
1215             OnErrorCb(MSERR_EXT_API9_OPERATE_NOT_PERMIT, "current state is not idle, unsupport set source fd");
1216             return;
1217         }
1218         if (player_ != nullptr) {
1219             if (player_->SetSource(fd, 0, -1) != MSERR_OK) {
1220                 QueueOnErrorCb(MSERR_EXT_API9_OPERATE_NOT_PERMIT, "failed to SetSourceFd");
1221                 return;
1222             }
1223             stopWait_ = false;
1224             stateChangeCond_.wait(lock, [this]() { return stopWait_.load() || avplayerExit_; });
1225             MEDIA_LOGI("Set source fd out");
1226         }
1227     });
1228     (void)taskQue_->EnqueueTask(task);
1229 }
1230 
QueueOnErrorCb(MediaServiceExtErrCodeAPI9 errorCode,const std::string & errorMsg)1231 void AVPlayerNapi::QueueOnErrorCb(MediaServiceExtErrCodeAPI9 errorCode, const std::string &errorMsg)
1232 {
1233     CHECK_AND_RETURN(!isReleased_.load());
1234     auto task = std::make_shared<TaskHandler<void>>([this, errorCode, errorMsg] {
1235         OnErrorCb(errorCode, errorMsg);
1236     });
1237     (void)taskQue_->EnqueueTask(task);
1238 }
1239 
JsSetUrl(napi_env env,napi_callback_info info)1240 napi_value AVPlayerNapi::JsSetUrl(napi_env env, napi_callback_info info)
1241 {
1242     MediaTrace trace("AVPlayerNapi::set url");
1243     napi_value result = nullptr;
1244     napi_get_undefined(env, &result);
1245     MEDIA_LOGD("JsSetUrl In");
1246 
1247     napi_value args[1] = { nullptr };
1248     size_t argCount = 1; // url: string
1249     AVPlayerNapi *jsPlayer = AVPlayerNapi::GetJsInstanceWithParameter(env, info, argCount, args);
1250     CHECK_AND_RETURN_RET_LOG(jsPlayer != nullptr, result, "failed to GetJsInstanceWithParameter");
1251 
1252     if (jsPlayer->GetCurrentState() != AVPlayerState::STATE_IDLE) {
1253         jsPlayer->OnErrorCb(MSERR_EXT_API9_OPERATE_NOT_PERMIT, "current state is not idle, unsupport set url");
1254         return result;
1255     }
1256 
1257     jsPlayer->StartListenCurrentResource(); // Listen to the events of the current resource
1258     napi_valuetype valueType = napi_undefined;
1259     if (argCount < 1 || napi_typeof(env, args[0], &valueType) != napi_ok || valueType != napi_string) {
1260         jsPlayer->OnErrorCb(MSERR_EXT_API9_INVALID_PARAMETER, "url is not string");
1261         return result;
1262     }
1263 
1264     // get url from js
1265     jsPlayer->url_ = CommonNapi::GetStringArgument(env, args[0]);
1266     MEDIA_LOGD("JsSetUrl url: %{private}s", jsPlayer->url_.c_str());
1267     jsPlayer->SetSource(jsPlayer->url_);
1268 
1269     MEDIA_LOGI("0x%{public}06" PRIXPTR " JsSetUrl Out", FAKE_POINTER(jsPlayer));
1270     return result;
1271 }
1272 
1273 #ifdef SUPPORT_AVPLAYER_DRM
JsSetDecryptConfig(napi_env env,napi_callback_info info)1274 napi_value AVPlayerNapi::JsSetDecryptConfig(napi_env env, napi_callback_info info)
1275 {
1276     MediaTrace trace("AVPlayerNapi::JsSetDecryptConfig");
1277     napi_value result = nullptr;
1278     napi_get_undefined(env, &result);
1279     MEDIA_LOGI("JsSetDecryptConfig In");
1280     napi_value args[ARRAY_ARG_COUNTS_TWO] = { nullptr }; // args[0]:MediaKeySession, args[1]:svp
1281     size_t argCount = 2; // args[0]:int64, args[1]:bool
1282     AVPlayerNapi *jsPlayer = AVPlayerNapi::GetJsInstanceWithParameter(env, info, argCount, args);
1283     CHECK_AND_RETURN_RET_LOG(jsPlayer != nullptr, result, "failed to GetJsInstanceWithParameter");
1284     bool svp = 0;
1285     napi_status status = napi_get_value_bool(env, args[1], &svp);
1286     if (status != napi_ok) {
1287         jsPlayer->OnErrorCb(MSERR_EXT_API9_INVALID_PARAMETER, "secureVideoPath type should be boolean.");
1288         return result;
1289     }
1290     napi_value sessionObj;
1291     status = napi_coerce_to_object(env, args[0], &sessionObj);
1292     CHECK_AND_RETURN_RET_LOG(status == napi_ok, result, "JsSetDecryptConfig get sessionObj failure!");
1293 
1294     napi_valuetype valueType;
1295     if (argCount < 1 || napi_typeof(env, sessionObj, &valueType) != napi_ok || valueType != napi_object) {
1296         jsPlayer->OnErrorCb(MSERR_EXT_API9_INVALID_PARAMETER, "mediaKeySession should be drm.MediaKeySession.");
1297         return result;
1298     }
1299     napi_value nativePointer = nullptr;
1300     std::string type = "MediaKeySessionNative";
1301     bool exist = false;
1302     status = napi_has_named_property(env, sessionObj, type.c_str(), &exist);
1303 
1304     CHECK_AND_RETURN_RET_LOG(status == napi_ok && exist, result, "can not find %{public}s property", type.c_str());
1305     CHECK_AND_RETURN_RET_LOG(napi_get_named_property(env, sessionObj, type.c_str(), &nativePointer) == napi_ok,
1306         result, "get %{public}s property fail", type.c_str());
1307 
1308     int64_t nativePointerInt;
1309     CHECK_AND_RETURN_RET_LOG(napi_get_value_int64(env, nativePointer, &nativePointerInt) == napi_ok, result,
1310         "get %{public}s property value fail", type.c_str());
1311     DrmStandard::MediaKeySessionImpl* keySessionImpl =
1312         reinterpret_cast<DrmStandard::MediaKeySessionImpl*>(nativePointerInt);
1313     if (keySessionImpl != nullptr) {
1314         sptr<DrmStandard::IMediaKeySessionService> keySessionServiceProxy =
1315             keySessionImpl->GetMediaKeySessionServiceProxy();
1316         MEDIA_LOGD("And it's count is: %{public}d", keySessionServiceProxy->GetSptrRefCount());
1317         {
1318             std::lock_guard<std::mutex> lock(jsPlayer->syncMutex_);
1319             CHECK_AND_RETURN_RET_LOG((jsPlayer->player_ != nullptr), result, "JsSetDecryptConfig player_ nullptr");
1320             (void)jsPlayer->player_->SetDecryptConfig(keySessionServiceProxy, svp);
1321         }
1322     } else {
1323         MEDIA_LOGE("SetDecryptConfig keySessionImpl is nullptr!");
1324     }
1325     return result;
1326 }
1327 #else
JsSetDecryptConfig(napi_env env,napi_callback_info info)1328 napi_value AVPlayerNapi::JsSetDecryptConfig(napi_env env, napi_callback_info info)
1329 {
1330     MEDIA_LOGI("JsSetDecryptConfig is not surpport.");
1331     (void)env;
1332     (void)info;
1333     return nullptr;
1334 }
1335 #endif
1336 
JsGetMediaKeySystemInfos(napi_env env,napi_callback_info info)1337 napi_value AVPlayerNapi::JsGetMediaKeySystemInfos(napi_env env, napi_callback_info info)
1338 {
1339     MediaTrace trace("AVPlayerNapi::JsGetMediaKeySystemInfos");
1340     napi_value result = nullptr;
1341     napi_get_undefined(env, &result);
1342     MEDIA_LOGI("JsGetMediaKeySystemInfos In");
1343 
1344     AVPlayerNapi *jsPlayer = AVPlayerNapi::GetJsInstance(env, info);
1345     CHECK_AND_RETURN_RET_LOG(jsPlayer != nullptr, result, "failed to GetJsInstance");
1346     CHECK_AND_RETURN_RET_LOG(!jsPlayer->localDrmInfos_.empty(), result, "localDrmInfo is empty");
1347 
1348     uint32_t index = 0;
1349     napi_value napiMap;
1350     napi_status status = napi_create_array_with_length(env, jsPlayer->localDrmInfos_.size(), &napiMap);
1351     CHECK_AND_RETURN_RET_LOG(status == napi_ok, result, "create napi array failed");
1352 
1353     for (auto item : jsPlayer->localDrmInfos_) {
1354         napi_value jsObject;
1355         napi_value jsUuid;
1356         napi_value jsPssh;
1357         napi_create_object(env, &jsObject);
1358         napi_create_string_utf8(env, item.first.c_str(), NAPI_AUTO_LENGTH, &jsUuid);
1359         napi_set_named_property(env, jsObject, "uuid", jsUuid);
1360 
1361         status = napi_create_array_with_length(env, item.second.size(), &jsPssh);
1362         CHECK_AND_RETURN_RET_LOG(status == napi_ok, result, "create napi array failed");
1363         for (uint32_t i = 0; i < item.second.size(); i++) {
1364             napi_value number = nullptr;
1365             (void)napi_create_uint32(env, item.second[i], &number);
1366             (void)napi_set_element(env, jsPssh, i, number);
1367         }
1368         napi_set_named_property(env, jsObject, "pssh", jsPssh);
1369         napi_set_element(env, napiMap, index, jsObject);
1370         index++;
1371     }
1372 
1373     return napiMap;
1374 }
1375 
JsGetPlaybackInfo(napi_env env,napi_callback_info info)1376 napi_value AVPlayerNapi::JsGetPlaybackInfo(napi_env env, napi_callback_info info)
1377 {
1378     MediaTrace trace("AVPlayerNapi::JsGetPlaybackInfo");
1379     napi_value result = nullptr;
1380     napi_get_undefined(env, &result);
1381     MEDIA_LOGI("GetPlaybackInfo In");
1382 
1383     auto promiseCtx = std::make_unique<AVPlayerContext>(env);
1384     promiseCtx->napi = AVPlayerNapi::GetJsInstance(env, info);
1385     CHECK_AND_RETURN_RET_LOG(promiseCtx->napi != nullptr, result, "failed to GetJsInstance");
1386     promiseCtx->deferred = CommonNapi::CreatePromise(env, nullptr, result);
1387     // async work
1388     napi_value resource = nullptr;
1389     napi_create_string_utf8(env, "JsGetPlaybackInfo", NAPI_AUTO_LENGTH, &resource);
1390     NAPI_CALL(env, napi_create_async_work(env, nullptr, resource,
1391         [](napi_env env, void *data) {
1392             MEDIA_LOGI("GetPlaybackInfo Task");
1393             auto promiseCtx = reinterpret_cast<AVPlayerContext *>(data);
1394             CHECK_AND_RETURN_LOG(promiseCtx != nullptr, "promiseCtx is nullptr!");
1395 
1396             auto jsPlayer = promiseCtx->napi;
1397             if (jsPlayer == nullptr) {
1398                 return promiseCtx->SignError(MSERR_EXT_API9_OPERATE_NOT_PERMIT, "avplayer is deconstructed");
1399             }
1400 
1401             Format &playbackInfo = jsPlayer->playbackInfo_;
1402             if (jsPlayer->IsControllable() && jsPlayer->player_ != nullptr) {
1403                 (void)jsPlayer->player_->GetPlaybackInfo(playbackInfo);
1404             } else {
1405                 return promiseCtx->SignError(MSERR_EXT_API9_OPERATE_NOT_PERMIT,
1406                     "current state unsupport get playback info");
1407             }
1408             promiseCtx->JsResult = std::make_unique<AVCodecJsResultFormat>(playbackInfo);
1409         },
1410         MediaAsyncContext::CompleteCallback, static_cast<void *>(promiseCtx.get()), &promiseCtx->work));
1411     napi_queue_async_work_with_qos(env, promiseCtx->work, napi_qos_user_initiated);
1412     promiseCtx.release();
1413     MEDIA_LOGI("GetPlaybackInfo Out");
1414     return result;
1415 }
1416 
GetAVPlayStrategyFromStrategyTmp(AVPlayStrategy & strategy,const AVPlayStrategyTmp & strategyTmp)1417 void AVPlayerNapi::GetAVPlayStrategyFromStrategyTmp(AVPlayStrategy &strategy, const AVPlayStrategyTmp &strategyTmp)
1418 {
1419     strategy.preferredWidth = strategyTmp.preferredWidth;
1420     strategy.preferredHeight = strategyTmp.preferredHeight;
1421     strategy.preferredBufferDuration = strategyTmp.preferredBufferDuration;
1422     strategy.preferredHdr = strategyTmp.preferredHdr;
1423     strategy.showFirstFrameOnPrepare = strategyTmp.showFirstFrameOnPrepare;
1424     strategy.enableSuperResolution = strategyTmp.enableSuperResolution;
1425     strategy.mutedMediaType = static_cast<MediaType>(strategyTmp.mutedMediaType);
1426     strategy.preferredAudioLanguage = strategyTmp.preferredAudioLanguage;
1427     strategy.preferredSubtitleLanguage = strategyTmp.preferredSubtitleLanguage;
1428     strategy.preferredBufferDurationForPlaying = strategyTmp.isSetBufferDurationForPlaying ?
1429         strategyTmp.preferredBufferDurationForPlaying : -1;
1430     strategy.thresholdForAutoQuickPlay = strategyTmp.isSetThresholdForAutoQuickPlay ?
1431         strategyTmp.thresholdForAutoQuickPlay : -1;
1432 }
1433 
IsPalyingDurationValid(const AVPlayStrategyTmp & strategyTmp)1434 bool AVPlayerNapi::IsPalyingDurationValid(const AVPlayStrategyTmp &strategyTmp)
1435 {
1436     if ((strategyTmp.preferredBufferDuration > 0 && strategyTmp.preferredBufferDurationForPlaying > 0 &&
1437                    strategyTmp.preferredBufferDurationForPlaying > strategyTmp.preferredBufferDuration) ||
1438                    strategyTmp.preferredBufferDurationForPlaying < 0) {
1439         return false;
1440     }
1441     return true;
1442 }
1443 
IsLivingMaxDelayTimeValid(const AVPlayStrategyTmp & strategyTmp)1444 bool AVPlayerNapi::IsLivingMaxDelayTimeValid(const AVPlayStrategyTmp &strategyTmp)
1445 {
1446     if (!strategyTmp.isSetThresholdForAutoQuickPlay) {
1447         return true;
1448     }
1449     if (strategyTmp.thresholdForAutoQuickPlay < AVPlayStrategyConstant::DEFAULT_LIVING_CACHED_DURATION ||
1450         strategyTmp.thresholdForAutoQuickPlay < strategyTmp.preferredBufferDurationForPlaying) {
1451             return false;
1452         }
1453     return true;
1454 }
1455 
JsSetPlaybackStrategy(napi_env env,napi_callback_info info)1456 napi_value AVPlayerNapi::JsSetPlaybackStrategy(napi_env env, napi_callback_info info)
1457 {
1458     MediaTrace trace("AVPlayerNapi::JsSetPlaybackStrategy");
1459     napi_value result = nullptr;
1460     napi_get_undefined(env, &result);
1461     MEDIA_LOGI("JsSetPlaybackStrategy");
1462 
1463     size_t paramCountSingle = PARAM_COUNT_SINGLE;
1464     napi_value args[PARAM_COUNT_SINGLE] = { nullptr };
1465     AVPlayerNapi *jsPlayer = AVPlayerNapi::GetJsInstanceWithParameter(env, info, paramCountSingle, args);
1466     CHECK_AND_RETURN_RET_LOG(jsPlayer != nullptr, result, "failed to GetJsInstance");
1467 
1468     auto promiseCtx = std::make_unique<AVPlayerContext>(env);
1469     promiseCtx->deferred = CommonNapi::CreatePromise(env, nullptr, result);
1470     std::string currentState = jsPlayer->GetCurrentState();
1471     napi_valuetype valueType = napi_undefined;
1472     if (currentState != AVPlayerState::STATE_INITIALIZED && currentState != AVPlayerState::STATE_STOPPED) {
1473         promiseCtx->SignError(MSERR_EXT_API9_OPERATE_NOT_PERMIT,
1474             "current state is not initialized / stopped, unsupport set playback strategy");
1475     } else if (napi_typeof(env, args[0], &valueType) != napi_ok || valueType != napi_object) {
1476         promiseCtx->SignError(MSERR_EXT_API9_INVALID_PARAMETER, "invalid parameters, please check input parameter");
1477     } else {
1478         AVPlayStrategyTmp strategyTmp;
1479         (void)CommonNapi::GetPlayStrategy(env, args[0], strategyTmp);
1480         if ((jsPlayer->GetJsApiVersion() < API_VERSION_17) &&
1481             (strategyTmp.mutedMediaType != MediaType::MEDIA_TYPE_AUD)) {
1482             promiseCtx->SignError(MSERR_EXT_API9_INVALID_PARAMETER, "only support mute media type audio now");
1483         } else if (!jsPlayer->IsPalyingDurationValid(strategyTmp)) {
1484             promiseCtx->SignError(MSERR_EXT_API9_INVALID_PARAMETER,
1485                                   "playing duration is above buffer duration or below zero");
1486         } else if (!jsPlayer->IsLivingMaxDelayTimeValid(strategyTmp)) {
1487             promiseCtx->SignError(MSERR_EXT_API9_INVALID_PARAMETER,
1488                                   "thresholdForAutoQuickPlay is invalid");
1489         } else {
1490             AVPlayStrategy strategy;
1491             jsPlayer->GetAVPlayStrategyFromStrategyTmp(strategy, strategyTmp);
1492             promiseCtx->asyncTask = jsPlayer->SetPlaybackStrategyTask(strategy);
1493         }
1494     }
1495     napi_value resource = nullptr;
1496     napi_create_string_utf8(env, "JsSetPlaybackStrategy", NAPI_AUTO_LENGTH, &resource);
1497     NAPI_CALL(env, napi_create_async_work(env, nullptr, resource,
1498         [](napi_env env, void *data) {
1499             auto promiseCtx = reinterpret_cast<AVPlayerContext *>(data);
1500             CHECK_AND_RETURN_LOG(promiseCtx != nullptr, "promiseCtx is nullptr!");
1501             promiseCtx->CheckTaskResult();
1502         },
1503         MediaAsyncContext::CompleteCallback, static_cast<void *>(promiseCtx.get()), &promiseCtx->work));
1504     napi_queue_async_work_with_qos(env, promiseCtx->work, napi_qos_user_initiated);
1505     promiseCtx.release();
1506     return result;
1507 }
1508 
JsSetMediaMuted(napi_env env,napi_callback_info info)1509 napi_value AVPlayerNapi::JsSetMediaMuted(napi_env env, napi_callback_info info)
1510 {
1511     MediaTrace trace("AVPlayerNapi::JsSetPlaybackStrategy");
1512     napi_value result = nullptr;
1513     napi_get_undefined(env, &result);
1514     MEDIA_LOGI("JsSetMediaMuted");
1515     auto promiseCtx = std::make_unique<AVPlayerContext>(env);
1516 
1517     const int32_t maxParam = 3; // config + callbackRef
1518     size_t argCount = maxParam;
1519     napi_value args[maxParam] = { nullptr };
1520     AVPlayerNapi *jsPlayer = AVPlayerNapi::GetJsInstanceWithParameter(env, info, argCount, args);
1521     CHECK_AND_RETURN_RET_LOG(jsPlayer != nullptr, result, "failed to GetJsInstance");
1522 
1523     if (!jsPlayer->IsControllable()) {
1524         jsPlayer->OnErrorCb(MSERR_EXT_API9_OPERATE_NOT_PERMIT,
1525             "current state is not prepared/playing/paused/completed, unsupport set media muted operation");
1526         return result;
1527     }
1528 
1529     int32_t mediaType = MediaType::MEDIA_TYPE_AUD;
1530     napi_get_value_int32(env, args[0], &mediaType);
1531     bool isMuted = false;
1532     napi_get_value_bool(env, args[1], &isMuted);
1533 
1534     promiseCtx->callbackRef = CommonNapi::CreateReference(env, args[maxParam - 1]);
1535     promiseCtx->deferred = CommonNapi::CreatePromise(env, promiseCtx->callbackRef, result);
1536 
1537     auto curState = jsPlayer->GetCurrentState();
1538     bool canSetMute = curState == AVPlayerState::STATE_PREPARED || curState == AVPlayerState::STATE_PLAYING ||
1539                       curState == AVPlayerState::STATE_PAUSED || curState == AVPlayerState::STATE_COMPLETED;
1540     if (!canSetMute) {
1541         promiseCtx->SignError(MSERR_EXT_API9_OPERATE_NOT_PERMIT,
1542             "current state is not initialized / stopped, unsupport set playback strategy operation");
1543     } else {
1544         promiseCtx->asyncTask = jsPlayer->SetMediaMutedTask(static_cast<MediaType>(mediaType), isMuted);
1545     }
1546     napi_value resource = nullptr;
1547     napi_create_string_utf8(env, "JsSetMediaMuted", NAPI_AUTO_LENGTH, &resource);
1548     NAPI_CALL(env, napi_create_async_work(env, nullptr, resource,
1549         [](napi_env env, void *data) {
1550             auto promiseCtx = reinterpret_cast<AVPlayerContext *>(data);
1551             CHECK_AND_RETURN_LOG(promiseCtx != nullptr, "promiseCtx is nullptr!");
1552             promiseCtx->CheckTaskResult();
1553         },
1554         MediaAsyncContext::CompleteCallback, static_cast<void *>(promiseCtx.get()), &promiseCtx->work));
1555     napi_queue_async_work_with_qos(env, promiseCtx->work, napi_qos_user_initiated);
1556     promiseCtx.release();
1557     return result;
1558 }
1559 
SetMediaMutedTask(MediaType type,bool isMuted)1560 std::shared_ptr<TaskHandler<TaskRet>> AVPlayerNapi::SetMediaMutedTask(MediaType type, bool isMuted)
1561 {
1562     auto task = std::make_shared<TaskHandler<TaskRet>>([this, type, isMuted]() {
1563         std::unique_lock<std::mutex> lock(taskMutex_);
1564         auto state = GetCurrentState();
1565         if (state == AVPlayerState::STATE_INITIALIZED || IsControllable()) {
1566             int32_t ret = player_->SetMediaMuted(type, isMuted);
1567             if (ret != MSERR_OK) {
1568                 auto errCode = MSErrorToExtErrorAPI9(static_cast<MediaServiceErrCode>(ret));
1569                 return TaskRet(errCode, "failed to set muted");
1570             }
1571         } else {
1572             return TaskRet(MSERR_EXT_API9_OPERATE_NOT_PERMIT,
1573                 "current state is not stopped or initialized, unsupport prepare operation");
1574         }
1575         return TaskRet(MSERR_EXT_API9_OK, "Success");
1576     });
1577     (void)taskQue_->EnqueueTask(task);
1578     return task;
1579 }
1580 
SetPlaybackStrategyTask(AVPlayStrategy playStrategy)1581 std::shared_ptr<TaskHandler<TaskRet>> AVPlayerNapi::SetPlaybackStrategyTask(AVPlayStrategy playStrategy)
1582 {
1583     auto task = std::make_shared<TaskHandler<TaskRet>>([this, playStrategy]() {
1584         std::unique_lock<std::mutex> lock(taskMutex_);
1585         auto state = GetCurrentState();
1586         if (state == AVPlayerState::STATE_INITIALIZED || state == AVPlayerState::STATE_STOPPED) {
1587             int32_t ret = player_->SetPlaybackStrategy(playStrategy);
1588             if (ret != MSERR_OK) {
1589                 auto errCode = MSErrorToExtErrorAPI9(static_cast<MediaServiceErrCode>(ret));
1590                 return TaskRet(errCode, "failed to set playback strategy");
1591             }
1592         } else {
1593             return TaskRet(MSERR_EXT_API9_OPERATE_NOT_PERMIT,
1594                 "current state is not initialized or stopped, unsupport set playback strategy operation");
1595         }
1596         return TaskRet(MSERR_EXT_API9_OK, "Success");
1597     });
1598     (void)taskQue_->EnqueueTask(task);
1599     return task;
1600 }
1601 
JsSetSuperResolution(napi_env env,napi_callback_info info)1602 napi_value AVPlayerNapi::JsSetSuperResolution(napi_env env, napi_callback_info info)
1603 {
1604     MediaTrace trace("AVPlayerNapi::setSuperResolution");
1605     napi_value result = nullptr;
1606     napi_get_undefined(env, &result);
1607     MEDIA_LOGI("JsSetSuperResolution In");
1608 
1609     napi_value args[PARAM_COUNT_SINGLE] = { nullptr };
1610     size_t argCount = PARAM_COUNT_SINGLE; // setSuperResolution(enabled: boolean)
1611     AVPlayerNapi *jsPlayer = AVPlayerNapi::GetJsInstanceWithParameter(env, info, argCount, args);
1612     CHECK_AND_RETURN_RET_LOG(jsPlayer != nullptr, result, "failed to GetJsInstanceWithParameter");
1613 
1614     auto promiseCtx = std::make_unique<AVPlayerContext>(env);
1615     promiseCtx->deferred = CommonNapi::CreatePromise(env, nullptr, result);
1616     napi_valuetype valueType = napi_undefined;
1617 
1618     if (!jsPlayer->CanSetSuperResolution()) {
1619         promiseCtx->SignError(MSERR_EXT_API9_OPERATE_NOT_PERMIT,
1620             "current state is not initialized/prepared/playing/paused/completed/stopped, "
1621             "unsupport set super resolution operation");
1622     } else if (argCount < PARAM_COUNT_SINGLE
1623         || napi_typeof(env, args[0], &valueType) != napi_ok || valueType != napi_boolean) {
1624         promiseCtx->SignError(MSERR_EXT_API9_INVALID_PARAMETER, "invalid parameters, please check the input");
1625     } else {
1626         bool enabled = false;
1627         napi_status status = napi_get_value_bool(env, args[0], &enabled);
1628         if (status != napi_ok) {
1629             promiseCtx->SignError(MSERR_EXT_API9_INVALID_PARAMETER,
1630                 "invalid parameters, please check the input");
1631         } else {
1632             promiseCtx->asyncTask = jsPlayer->SetSuperResolutionTask(enabled);
1633         }
1634     }
1635 
1636     napi_value resource = nullptr;
1637     napi_create_string_utf8(env, "JsSetSuperResolution", NAPI_AUTO_LENGTH, &resource);
1638     NAPI_CALL(env, napi_create_async_work(env, nullptr, resource,
1639         [](napi_env env, void *data) {
1640             auto promiseCtx = reinterpret_cast<AVPlayerContext *>(data);
1641             CHECK_AND_RETURN_LOG(promiseCtx != nullptr, "promiseCtx is nullptr!");
1642             promiseCtx->CheckTaskResult();
1643         },
1644         MediaAsyncContext::CompleteCallback, static_cast<void *>(promiseCtx.get()), &promiseCtx->work));
1645     napi_queue_async_work_with_qos(env, promiseCtx->work, napi_qos_user_initiated);
1646     promiseCtx.release();
1647     return result;
1648 }
1649 
SetSuperResolutionTask(bool enable)1650 std::shared_ptr<TaskHandler<TaskRet>> AVPlayerNapi::SetSuperResolutionTask(bool enable)
1651 {
1652     auto task = std::make_shared<TaskHandler<TaskRet>>([this, enable]() {
1653         std::unique_lock<std::mutex> lock(taskMutex_);
1654         if (CanSetSuperResolution()) {
1655             int32_t ret = player_->SetSuperResolution(enable);
1656             if (ret != MSERR_OK) {
1657                 auto errCode = MSErrorToExtErrorAPI9(static_cast<MediaServiceErrCode>(ret));
1658                 return TaskRet(errCode, "failed to set super resolution");
1659             }
1660         } else {
1661             return TaskRet(MSERR_EXT_API9_OPERATE_NOT_PERMIT,
1662                 "current state is not initialized/prepared/playing/paused/completed/stopped, "
1663                 "unsupport set super resolution operation");
1664         }
1665         return TaskRet(MSERR_EXT_API9_OK, "Success");
1666     });
1667     (void)taskQue_->EnqueueTask(task);
1668     return task;
1669 }
1670 
JsSetVideoWindowSize(napi_env env,napi_callback_info info)1671 napi_value AVPlayerNapi::JsSetVideoWindowSize(napi_env env, napi_callback_info info)
1672 {
1673     MediaTrace trace("AVPlayerNapi::setVideoWindowSize");
1674     napi_value result = nullptr;
1675     napi_get_undefined(env, &result);
1676     MEDIA_LOGI("JsSetVideoWindowSize In");
1677 
1678     napi_value args[ARRAY_ARG_COUNTS_TWO] = { nullptr };
1679     size_t argCount = ARRAY_ARG_COUNTS_TWO; // setVideoWindowSize(width: number, height: number)
1680     AVPlayerNapi *jsPlayer = AVPlayerNapi::GetJsInstanceWithParameter(env, info, argCount, args);
1681     CHECK_AND_RETURN_RET_LOG(jsPlayer != nullptr, result, "failed to GetJsInstanceWithParameter");
1682 
1683     auto promiseCtx = std::make_unique<AVPlayerContext>(env);
1684     promiseCtx->deferred = CommonNapi::CreatePromise(env, nullptr, result);
1685     napi_valuetype valueType = napi_undefined;
1686 
1687     if (!jsPlayer->CanSetSuperResolution()) {
1688         promiseCtx->SignError(MSERR_EXT_API9_OPERATE_NOT_PERMIT,
1689             "current state is not initialized/prepared/playing/paused/completed/stopped, "
1690             "unsupport set video window size");
1691     } else if (argCount < ARRAY_ARG_COUNTS_TWO ||
1692                 napi_typeof(env, args[0], &valueType) != napi_ok || valueType != napi_number ||
1693                 napi_typeof(env, args[1], &valueType) != napi_ok || valueType != napi_number) {
1694         promiseCtx->SignError(MSERR_EXT_API9_INVALID_PARAMETER, "invalid parameters, please check the input");
1695     } else {
1696         int32_t width = 0;
1697         int32_t height = 0;
1698         napi_status status1 = napi_get_value_int32(env, args[0], &width);
1699         napi_status status2 = napi_get_value_int32(env, args[1], &height);
1700         if (status1 != napi_ok || status2 != napi_ok) {
1701             promiseCtx->SignError(MSERR_EXT_API9_INVALID_PARAMETER,
1702                 "invalid parameters, please check the input");
1703         } else {
1704             promiseCtx->asyncTask = jsPlayer->SetVideoWindowSizeTask(width, height);
1705         }
1706     }
1707 
1708     napi_value resource = nullptr;
1709     napi_create_string_utf8(env, "JsSetVideoWindowSize", NAPI_AUTO_LENGTH, &resource);
1710     NAPI_CALL(env, napi_create_async_work(env, nullptr, resource,
1711         [](napi_env env, void *data) {
1712             auto promiseCtx = reinterpret_cast<AVPlayerContext *>(data);
1713             CHECK_AND_RETURN_LOG(promiseCtx != nullptr, "promiseCtx is nullptr!");
1714             promiseCtx->CheckTaskResult();
1715         },
1716         MediaAsyncContext::CompleteCallback, static_cast<void *>(promiseCtx.get()), &promiseCtx->work));
1717     napi_queue_async_work_with_qos(env, promiseCtx->work, napi_qos_user_initiated);
1718     promiseCtx.release();
1719     return result;
1720 }
1721 
SetVideoWindowSizeTask(int32_t width,int32_t height)1722 std::shared_ptr<TaskHandler<TaskRet>> AVPlayerNapi::SetVideoWindowSizeTask(int32_t width, int32_t height)
1723 {
1724     auto task = std::make_shared<TaskHandler<TaskRet>>([this, width, height]() {
1725         std::unique_lock<std::mutex> lock(taskMutex_);
1726         auto state = GetCurrentState();
1727         if (CanSetSuperResolution()) {
1728             int32_t ret = player_->SetVideoWindowSize(width, height);
1729             if (ret != MSERR_OK) {
1730                 auto errCode = MSErrorToExtErrorAPI9(static_cast<MediaServiceErrCode>(ret));
1731                 return TaskRet(errCode, "failed to set super resolution");
1732             }
1733         } else {
1734             return TaskRet(MSERR_EXT_API9_OPERATE_NOT_PERMIT,
1735                 "current state is not initialized/prepared/playing/paused/completed/stopped, "
1736                 "unsupport set super resolution operation");
1737         }
1738         return TaskRet(MSERR_EXT_API9_OK, "Success");
1739     });
1740     (void)taskQue_->EnqueueTask(task);
1741     return task;
1742 }
1743 
JsGetUrl(napi_env env,napi_callback_info info)1744 napi_value AVPlayerNapi::JsGetUrl(napi_env env, napi_callback_info info)
1745 {
1746     MediaTrace trace("AVPlayerNapi::get url");
1747     napi_value result = nullptr;
1748     napi_get_undefined(env, &result);
1749     MEDIA_LOGD("JsGetUrl In");
1750 
1751     AVPlayerNapi *jsPlayer = AVPlayerNapi::GetJsInstance(env, info);
1752     CHECK_AND_RETURN_RET_LOG(jsPlayer != nullptr, result, "failed to GetJsInstance");
1753 
1754     napi_value value = nullptr;
1755     (void)napi_create_string_utf8(env, jsPlayer->url_.c_str(), NAPI_AUTO_LENGTH, &value);
1756 
1757     MEDIA_LOGD("JsGetUrl Out Current Url: %{private}s", jsPlayer->url_.c_str());
1758     return value;
1759 }
1760 
JsSetAVFileDescriptor(napi_env env,napi_callback_info info)1761 napi_value AVPlayerNapi::JsSetAVFileDescriptor(napi_env env, napi_callback_info info)
1762 {
1763     MediaTrace trace("AVPlayerNapi::set fd");
1764     napi_value result = nullptr;
1765     napi_get_undefined(env, &result);
1766     MEDIA_LOGI("JsSetAVFileDescriptor In");
1767 
1768     napi_value args[1] = { nullptr };
1769     size_t argCount = 1; // url: string
1770     AVPlayerNapi *jsPlayer = AVPlayerNapi::GetJsInstanceWithParameter(env, info, argCount, args);
1771     CHECK_AND_RETURN_RET_LOG(jsPlayer != nullptr, result, "failed to GetJsInstanceWithParameter");
1772 
1773     if (jsPlayer->GetCurrentState() != AVPlayerState::STATE_IDLE) {
1774         jsPlayer->OnErrorCb(MSERR_EXT_API9_OPERATE_NOT_PERMIT, "current state is not idle, unsupport set fd");
1775         return result;
1776     }
1777 
1778     jsPlayer->StartListenCurrentResource(); // Listen to the events of the current resource
1779     napi_valuetype valueType = napi_undefined;
1780     if (argCount < 1 || napi_typeof(env, args[0], &valueType) != napi_ok || valueType != napi_object) {
1781         jsPlayer->OnErrorCb(MSERR_EXT_API9_INVALID_PARAMETER, "SetAVFileDescriptor is not napi_object");
1782         return result;
1783     }
1784 
1785     if (!CommonNapi::GetFdArgument(env, args[0], jsPlayer->fileDescriptor_)) {
1786         MEDIA_LOGE("get fileDescriptor argument failed!");
1787         jsPlayer->OnErrorCb(MSERR_EXT_API9_INVALID_PARAMETER,
1788             "invalid parameters, please check the input parameters(fileDescriptor)");
1789         return result;
1790     }
1791 
1792     auto task = std::make_shared<TaskHandler<void>>([jsPlayer]() {
1793         MEDIA_LOGI("SetAVFileDescriptor Task");
1794         if (jsPlayer->player_ != nullptr) {
1795             auto playerFd = jsPlayer->fileDescriptor_;
1796             MEDIA_LOGI("JsSetAVFileDescriptor fd: %{public}d, offset: %{public}"
1797                 PRId64 ", size: %{public}" PRId64, playerFd.fd, playerFd.offset, playerFd.length);
1798             if (jsPlayer->player_->SetSource(playerFd.fd, playerFd.offset, playerFd.length) != MSERR_OK) {
1799                 jsPlayer->OnErrorCb(MSERR_EXT_API9_INVALID_PARAMETER, "player SetSource FileDescriptor failed");
1800             }
1801         }
1802     });
1803     (void)jsPlayer->taskQue_->EnqueueTask(task);
1804 
1805     MEDIA_LOGI("JsSetAVFileDescriptor Out");
1806     return result;
1807 }
1808 
JsGetAVFileDescriptor(napi_env env,napi_callback_info info)1809 napi_value AVPlayerNapi::JsGetAVFileDescriptor(napi_env env, napi_callback_info info)
1810 {
1811     MediaTrace trace("AVPlayerNapi::get fd");
1812     napi_value result = nullptr;
1813     napi_get_undefined(env, &result);
1814     MEDIA_LOGI("JsGetAVFileDescriptor In");
1815 
1816     AVPlayerNapi *jsPlayer = AVPlayerNapi::GetJsInstance(env, info);
1817     CHECK_AND_RETURN_RET_LOG(jsPlayer != nullptr, result, "failed to GetJsInstance");
1818 
1819     napi_value value = nullptr;
1820     (void)napi_create_object(env, &value);
1821     (void)CommonNapi::AddNumberPropInt32(env, value, "fd", jsPlayer->fileDescriptor_.fd);
1822     (void)CommonNapi::AddNumberPropInt64(env, value, "offset", jsPlayer->fileDescriptor_.offset);
1823     (void)CommonNapi::AddNumberPropInt64(env, value, "length", jsPlayer->fileDescriptor_.length);
1824 
1825     MEDIA_LOGI("JsGetAVFileDescriptor Out");
1826     return value;
1827 }
1828 
JsSetMediaSource(napi_env env,napi_callback_info info)1829 napi_value AVPlayerNapi::JsSetMediaSource(napi_env env, napi_callback_info info)
1830 {
1831     MediaTrace trace("AVPlayerNapi::JsSetMediaSource");
1832     napi_value result = nullptr;
1833     napi_get_undefined(env, &result);
1834     napi_value args[ARRAY_ARG_COUNTS_TWO] = { nullptr };
1835     size_t argCount = 2;
1836     AVPlayerNapi *jsPlayer = AVPlayerNapi::GetJsInstanceWithParameter(env, info, argCount, args);
1837     CHECK_AND_RETURN_RET_LOG(jsPlayer != nullptr, result, "failed to GetJsInstanceWithParameter");
1838 
1839     if (jsPlayer->GetCurrentState() != AVPlayerState::STATE_IDLE) {
1840         jsPlayer->OnErrorCb(MSERR_EXT_API9_OPERATE_NOT_PERMIT, "current state is not idle, unsupport set mediaSource");
1841         return result;
1842     }
1843     jsPlayer->StartListenCurrentResource(); // Listen to the events of the current resource
1844     napi_valuetype valueType = napi_undefined;
1845     if (argCount < MIN_ARG_COUNTS || napi_typeof(env, args[0], &valueType) != napi_ok || valueType != napi_object) {
1846         jsPlayer->OnErrorCb(MSERR_EXT_API9_INVALID_PARAMETER, "src type should be MediaSource.");
1847         return result;
1848     }
1849     if (napi_typeof(env, args[1], &valueType) != napi_ok || valueType != napi_object) {
1850         jsPlayer->OnErrorCb(MSERR_EXT_API9_INVALID_PARAMETER, "strategy type should be PlaybackStrategy.");
1851         return result;
1852     } else if (argCount > MAX_ARG_COUNTS || napi_typeof(env, args[1], &valueType) != napi_ok) {
1853         jsPlayer->OnErrorCb(MSERR_EXT_API9_INVALID_PARAMETER, "invalid parameters, please check");
1854         return result;
1855     }
1856     std::shared_ptr<AVMediaSourceTmp> srcTmp = MediaSourceNapi::GetMediaSource(env, args[0]);
1857     CHECK_AND_RETURN_RET_LOG(srcTmp != nullptr, result, "get GetMediaSource argument failed!");
1858 
1859     std::shared_ptr<AVMediaSource> mediaSource = GetAVMediaSource(env, args[0], srcTmp);
1860     CHECK_AND_RETURN_RET_LOG(mediaSource != nullptr, result, "create mediaSource failed!");
1861     jsPlayer->AddMediaStreamToAVMediaSource(srcTmp, mediaSource);
1862 
1863     struct AVPlayStrategyTmp strategyTmp;
1864     struct AVPlayStrategy strategy;
1865     if (!CommonNapi::GetPlayStrategy(env, args[1], strategyTmp)) {
1866         jsPlayer->OnErrorCb(MSERR_EXT_API9_INVALID_PARAMETER, "strategy type should be PlaybackStrategy.");
1867         return result;
1868     } else if (!jsPlayer->IsPalyingDurationValid(strategyTmp)) {
1869         jsPlayer->OnErrorCb(MSERR_EXT_API9_INVALID_PARAMETER, "playing duration is invalid");
1870         return result;
1871     } else if (!jsPlayer->IsLivingMaxDelayTimeValid(strategyTmp)) {
1872         jsPlayer->OnErrorCb(MSERR_EXT_API9_INVALID_PARAMETER, "thresholdForAutoQuickPlay is invalid");
1873         return result;
1874     }
1875     jsPlayer->GetAVPlayStrategyFromStrategyTmp(strategy, strategyTmp);
1876     if (jsPlayer->GetJsApiVersion() < API_VERSION_17) {
1877         strategy.mutedMediaType = MediaType::MEDIA_TYPE_MAX_COUNT;
1878     }
1879     jsPlayer->EnqueueMediaSourceTask(jsPlayer, mediaSource, strategy);
1880     return result;
1881 }
1882 
GetAVMediaSource(napi_env env,napi_value value,std::shared_ptr<AVMediaSourceTmp> & srcTmp)1883 std::shared_ptr<AVMediaSource> AVPlayerNapi::GetAVMediaSource(napi_env env, napi_value value,
1884     std::shared_ptr<AVMediaSourceTmp> &srcTmp)
1885 {
1886     std::shared_ptr<AVMediaSource> mediaSource = std::make_shared<AVMediaSource>(srcTmp->url, srcTmp->header);
1887     CHECK_AND_RETURN_RET_LOG(mediaSource != nullptr, nullptr, "create mediaSource failed!");
1888     mediaSource->SetMimeType(srcTmp->GetMimeType());
1889     mediaSource->mediaSourceLoaderCb_ = MediaSourceNapi::GetSourceLoader(env, value);
1890     if (mediaSource->mediaSourceLoaderCb_ == nullptr) {
1891         MEDIA_LOGI("mediaSourceLoaderCb_ nullptr");
1892     }
1893     return mediaSource;
1894 }
1895 
EnqueueMediaSourceTask(AVPlayerNapi * jsPlayer,const std::shared_ptr<AVMediaSource> & mediaSource,const struct AVPlayStrategy & strategy)1896 void AVPlayerNapi::EnqueueMediaSourceTask(AVPlayerNapi *jsPlayer, const std::shared_ptr<AVMediaSource> &mediaSource,
1897                                           const struct AVPlayStrategy &strategy)
1898 {
1899     auto task = std::make_shared<TaskHandler<void>>([jsPlayer, mediaSource, strategy]() {
1900         if (jsPlayer->player_ != nullptr) {
1901             (void)jsPlayer->player_->SetMediaSource(mediaSource, strategy);
1902         }
1903     });
1904     (void)jsPlayer->taskQue_->EnqueueTask(task);
1905 }
1906 
JsSetDataSrc(napi_env env,napi_callback_info info)1907 napi_value AVPlayerNapi::JsSetDataSrc(napi_env env, napi_callback_info info)
1908 {
1909     MediaTrace trace("AVPlayerNapi::set dataSrc");
1910     napi_value result = nullptr;
1911     napi_get_undefined(env, &result);
1912     MEDIA_LOGI("JsSetDataSrc In");
1913 
1914     napi_value args[1] = { nullptr };
1915     size_t argCount = 1;
1916     AVPlayerNapi *jsPlayer = AVPlayerNapi::GetJsInstanceWithParameter(env, info, argCount, args);
1917     CHECK_AND_RETURN_RET_LOG(jsPlayer != nullptr, result, "failed to GetJsInstanceWithParameter");
1918 
1919     if (jsPlayer->GetCurrentState() != AVPlayerState::STATE_IDLE) {
1920         jsPlayer->OnErrorCb(MSERR_EXT_API9_OPERATE_NOT_PERMIT, "current state is not idle, unsupport set dataSrc");
1921         return result;
1922     }
1923     jsPlayer->StartListenCurrentResource(); // Listen to the events of the current resource
1924 
1925     napi_valuetype valueType = napi_undefined;
1926     if (argCount < 1 || napi_typeof(env, args[0], &valueType) != napi_ok || valueType != napi_object) {
1927         jsPlayer->OnErrorCb(MSERR_EXT_API9_INVALID_PARAMETER, "args[0] is not napi_object");
1928         return result;
1929     }
1930     (void)CommonNapi::GetPropertyInt64(env, args[0], "fileSize", jsPlayer->dataSrcDescriptor_.fileSize);
1931     if (jsPlayer->dataSrcDescriptor_.fileSize < -1 || jsPlayer->dataSrcDescriptor_.fileSize == 0) {
1932         jsPlayer->OnErrorCb(MSERR_EXT_API9_INVALID_PARAMETER, "invalid parameters, please check parameter fileSize");
1933         return result;
1934     }
1935     MEDIA_LOGD("Recvive filesize is %{public}" PRId64 "", jsPlayer->dataSrcDescriptor_.fileSize);
1936     jsPlayer->dataSrcCb_ = std::make_shared<MediaDataSourceCallback>(env, jsPlayer->dataSrcDescriptor_.fileSize);
1937 
1938     napi_value callback = nullptr;
1939     napi_ref ref = nullptr;
1940     napi_get_named_property(env, args[0], "callback", &callback);
1941     jsPlayer->dataSrcDescriptor_.callback = callback;
1942     napi_status status = napi_create_reference(env, callback, 1, &ref);
1943     CHECK_AND_RETURN_RET_LOG(status == napi_ok && ref != nullptr, result, "failed to create reference!");
1944     std::shared_ptr<AutoRef> autoRef = std::make_shared<AutoRef>(env, ref);
1945     jsPlayer->dataSrcCb_->SaveCallbackReference(READAT_CALLBACK_NAME, autoRef);
1946 
1947     if (jsPlayer->player_ != nullptr) {
1948         if (jsPlayer->player_->SetSource(jsPlayer->dataSrcCb_) != MSERR_OK) {
1949             jsPlayer->OnErrorCb(MSERR_EXT_API9_INVALID_PARAMETER, "player SetSource DataSrc failed");
1950         } else {
1951             jsPlayer->state_ = PlayerStates::PLAYER_INITIALIZED;
1952         }
1953         if (jsPlayer->dataSrcDescriptor_.fileSize == -1) {
1954             jsPlayer->isLiveStream_ = true;
1955         }
1956     }
1957 
1958     MEDIA_LOGI("JsSetDataSrc Out");
1959     return result;
1960 }
1961 
JsGetDataSrc(napi_env env,napi_callback_info info)1962 napi_value AVPlayerNapi::JsGetDataSrc(napi_env env, napi_callback_info info)
1963 {
1964     MediaTrace trace("AVPlayerNapi::get dataSrc");
1965     napi_value result = nullptr;
1966     napi_get_undefined(env, &result);
1967     MEDIA_LOGI("JsGetDataSrc In");
1968 
1969     AVPlayerNapi *jsPlayer = AVPlayerNapi::GetJsInstance(env, info);
1970     CHECK_AND_RETURN_RET_LOG(jsPlayer != nullptr, result, "failed to GetJsInstance");
1971     CHECK_AND_RETURN_RET_LOG(jsPlayer->dataSrcCb_ != nullptr, result, "failed to check dataSrcCb_");
1972 
1973     napi_value value = nullptr;
1974     int64_t fileSize;
1975     napi_value callback = nullptr;
1976     (void)napi_create_object(env, &value);
1977     (void)jsPlayer->dataSrcCb_->GetSize(fileSize);
1978     (void)CommonNapi::AddNumberPropInt64(env, value, "fileSize", fileSize);
1979     int32_t ret = jsPlayer->dataSrcCb_->GetCallback(READAT_CALLBACK_NAME, &callback);
1980     CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, result, "failed to GetCallback");
1981     (void)MediaDataSourceCallback::AddNapiValueProp(env, value, "callback", callback);
1982 
1983     MEDIA_LOGI("JsGetDataSrc Out");
1984     return value;
1985 }
1986 
1987 #ifdef SUPPORT_VIDEO
SetSurface(const std::string & surfaceStr)1988 void AVPlayerNapi::SetSurface(const std::string &surfaceStr)
1989 {
1990     MEDIA_LOGI("get surface, surfaceStr = %{public}s", surfaceStr.c_str());
1991     uint64_t surfaceId = 0;
1992     if (surfaceStr.empty() || surfaceStr[0] < '0' || surfaceStr[0] > '9') {
1993         OnErrorCb(MSERR_EXT_API9_INVALID_PARAMETER,
1994             "Please obtain the surface from XComponentController.getXComponentSurfaceId");
1995         return;
1996     }
1997     if (!StrToULL(surfaceStr, surfaceId)) {
1998         OnErrorCb(MSERR_EXT_API9_INVALID_PARAMETER,
1999             "invalid parameters, failed to obtain surfaceId");
2000         return;
2001     }
2002     MEDIA_LOGI("get surface, surfaceId = (%{public}" PRIu64 ")", surfaceId);
2003 
2004     auto surface = SurfaceUtils::GetInstance()->GetSurface(surfaceId);
2005     if (surface == nullptr) {
2006         OnErrorCb(MSERR_EXT_API9_INVALID_PARAMETER, "SurfaceUtils cannot convert ID to Surface");
2007         return;
2008     }
2009 
2010     auto task = std::make_shared<TaskHandler<void>>([this, surface]() {
2011         MEDIA_LOGI("0x%{public}06" PRIXPTR " SetSurface Task", FAKE_POINTER(this));
2012         if (player_ != nullptr) {
2013             (void)player_->SetVideoSurface(surface);
2014         }
2015     });
2016     (void)taskQue_->EnqueueTask(task);
2017 }
2018 #else
SetSurface(const std::string & surfaceStr)2019 void AVPlayerNapi::SetSurface(const std::string &surfaceStr)
2020 {
2021     (void)surfaceStr;
2022     OnErrorCb(MSERR_EXT_API9_UNSUPPORT_CAPABILITY, "The music player does not need to support (Surface)");
2023 }
2024 #endif
2025 
JsSetSurfaceID(napi_env env,napi_callback_info info)2026 napi_value AVPlayerNapi::JsSetSurfaceID(napi_env env, napi_callback_info info)
2027 {
2028     MediaTrace trace("AVPlayerNapi::set surface");
2029     napi_value result = nullptr;
2030     napi_get_undefined(env, &result);
2031     MEDIA_LOGD("JsSetSurfaceID In");
2032 
2033     napi_value args[1] = { nullptr };
2034     size_t argCount = 1; // surfaceId?: string
2035     AVPlayerNapi *jsPlayer = AVPlayerNapi::GetJsInstanceWithParameter(env, info, argCount, args);
2036     CHECK_AND_RETURN_RET_LOG(jsPlayer != nullptr, result, "failed to GetJsInstanceWithParameter");
2037 
2038     napi_valuetype valueType = napi_undefined;
2039     if (argCount < 1 || napi_typeof(env, args[0], &valueType) != napi_ok || valueType != napi_string) {
2040         jsPlayer->OnErrorCb(MSERR_EXT_API9_INVALID_PARAMETER, "the attribute(SurfaceID) input is not string");
2041         return result;
2042     }
2043 
2044     std::string curState = jsPlayer->GetCurrentState();
2045     bool setSurfaceFirst = curState == AVPlayerState::STATE_INITIALIZED;
2046     bool switchSurface = curState == AVPlayerState::STATE_PREPARED ||
2047         curState == AVPlayerState::STATE_PLAYING ||
2048         curState == AVPlayerState::STATE_PAUSED ||
2049         curState == AVPlayerState::STATE_STOPPED ||
2050         curState == AVPlayerState::STATE_COMPLETED;
2051 
2052     if (setSurfaceFirst) {
2053         MEDIA_LOGI("JsSetSurfaceID set surface first in %{public}s state", curState.c_str());
2054     } else if (switchSurface) {
2055         MEDIA_LOGI("JsSetSurfaceID switch surface in %{public}s state", curState.c_str());
2056         std::string oldSurface = jsPlayer->surface_;
2057         if (oldSurface.empty()) {
2058             jsPlayer->OnErrorCb(MSERR_EXT_API9_OPERATE_NOT_PERMIT,
2059                 "switch surface with no old surface");
2060             return result;
2061         }
2062     } else {
2063         jsPlayer->OnErrorCb(MSERR_EXT_API9_OPERATE_NOT_PERMIT,
2064             "the attribute(SurfaceID) can only be set in the initialized state");
2065         return result;
2066     }
2067 
2068     // get url from js
2069     jsPlayer->surface_ = CommonNapi::GetStringArgument(env, args[0]);
2070     jsPlayer->SetSurface(jsPlayer->surface_);
2071     MEDIA_LOGI("0x%{public}06" PRIXPTR " JsSetSurfaceID Out", FAKE_POINTER(jsPlayer));
2072     return result;
2073 }
2074 
JsGetSurfaceID(napi_env env,napi_callback_info info)2075 napi_value AVPlayerNapi::JsGetSurfaceID(napi_env env, napi_callback_info info)
2076 {
2077     MediaTrace trace("AVPlayerNapi::get surface");
2078     napi_value result = nullptr;
2079     napi_get_undefined(env, &result);
2080     MEDIA_LOGD("JsGetSurfaceID In");
2081 
2082     AVPlayerNapi *jsPlayer = AVPlayerNapi::GetJsInstance(env, info);
2083     CHECK_AND_RETURN_RET_LOG(jsPlayer != nullptr, result, "failed to GetJsInstance");
2084 
2085     napi_value value = nullptr;
2086     (void)napi_create_string_utf8(env, jsPlayer->surface_.c_str(), NAPI_AUTO_LENGTH, &value);
2087 
2088     MEDIA_LOGI("JsGetSurfaceID Out Current SurfaceID: %{public}s", jsPlayer->surface_.c_str());
2089     return value;
2090 }
2091 
JsSetLoop(napi_env env,napi_callback_info info)2092 napi_value AVPlayerNapi::JsSetLoop(napi_env env, napi_callback_info info)
2093 {
2094     MediaTrace trace("AVPlayerNapi::set loop");
2095     napi_value result = nullptr;
2096     napi_get_undefined(env, &result);
2097     MEDIA_LOGI("JsSetLoop In");
2098 
2099     napi_value args[1] = { nullptr };
2100     size_t argCount = 1; // loop: boolenan
2101     AVPlayerNapi *jsPlayer = AVPlayerNapi::GetJsInstanceWithParameter(env, info, argCount, args);
2102     CHECK_AND_RETURN_RET_LOG(jsPlayer != nullptr, result, "failed to GetJsInstanceWithParameter");
2103 
2104     if (jsPlayer->IsLiveSource()) {
2105         jsPlayer->OnErrorCb(MSERR_EXT_API9_UNSUPPORT_CAPABILITY, "The stream is live stream, not support loop");
2106         return result;
2107     }
2108 
2109     if (!jsPlayer->IsControllable()) {
2110         jsPlayer->OnErrorCb(MSERR_EXT_API9_OPERATE_NOT_PERMIT,
2111             "current state is not prepared/playing/paused/completed, unsupport loop operation");
2112         return result;
2113     }
2114 
2115     napi_valuetype valueType = napi_undefined;
2116     if (argCount < 1 || napi_typeof(env, args[0], &valueType) != napi_ok || valueType != napi_boolean) {
2117         jsPlayer->OnErrorCb(MSERR_EXT_API9_INVALID_PARAMETER, "SetLoop is not napi_boolean");
2118         return result;
2119     }
2120 
2121     napi_status status = napi_get_value_bool(env, args[0], &jsPlayer->loop_);
2122     if (status != napi_ok) {
2123         jsPlayer->OnErrorCb(MSERR_EXT_API9_INVALID_PARAMETER,
2124             "invalid parameters, please check the input loop");
2125         return result;
2126     }
2127 
2128     auto task = std::make_shared<TaskHandler<void>>([jsPlayer]() {
2129         MEDIA_LOGD("SetLooping Task");
2130         if (jsPlayer->player_ != nullptr) {
2131             (void)jsPlayer->player_->SetLooping(jsPlayer->loop_);
2132         }
2133     });
2134     (void)jsPlayer->taskQue_->EnqueueTask(task);
2135     MEDIA_LOGI("0x%{public}06" PRIXPTR " JsSetLoop Out", FAKE_POINTER(jsPlayer));
2136     return result;
2137 }
2138 
JsGetLoop(napi_env env,napi_callback_info info)2139 napi_value AVPlayerNapi::JsGetLoop(napi_env env, napi_callback_info info)
2140 {
2141     MediaTrace trace("AVPlayerNapi::get loop");
2142     napi_value result = nullptr;
2143     napi_get_undefined(env, &result);
2144     MEDIA_LOGI("JsGetLoop In");
2145 
2146     AVPlayerNapi *jsPlayer = AVPlayerNapi::GetJsInstance(env, info);
2147     CHECK_AND_RETURN_RET_LOG(jsPlayer != nullptr, result, "failed to GetJsInstance");
2148 
2149     napi_value value = nullptr;
2150     (void)napi_get_boolean(env, jsPlayer->loop_, &value);
2151     MEDIA_LOGI("JsGetLoop Out Current Loop: %{public}d", jsPlayer->loop_);
2152     return value;
2153 }
2154 
JsSetVideoScaleType(napi_env env,napi_callback_info info)2155 napi_value AVPlayerNapi::JsSetVideoScaleType(napi_env env, napi_callback_info info)
2156 {
2157     MediaTrace trace("AVPlayerNapi::set videoScaleType");
2158     napi_value result = nullptr;
2159     napi_get_undefined(env, &result);
2160     MEDIA_LOGI("JsSetVideoScaleType In");
2161 
2162     napi_value args[1] = { nullptr };
2163     size_t argCount = 1;
2164     AVPlayerNapi *jsPlayer = AVPlayerNapi::GetJsInstanceWithParameter(env, info, argCount, args);
2165     CHECK_AND_RETURN_RET_LOG(jsPlayer != nullptr, result, "failed to GetJsInstanceWithParameter");
2166 
2167     if (!jsPlayer->IsControllable()) {
2168         jsPlayer->OnErrorCb(MSERR_EXT_API9_OPERATE_NOT_PERMIT,
2169             "current state is not prepared/playing/paused/completed, unsupport video scale operation");
2170         return result;
2171     }
2172 
2173     napi_valuetype valueType = napi_undefined;
2174     if (argCount < 1 || napi_typeof(env, args[0], &valueType) != napi_ok || valueType != napi_number) {
2175         jsPlayer->OnErrorCb(MSERR_EXT_API9_INVALID_PARAMETER, "SetVideoScaleType is not napi_number");
2176         return result;
2177     }
2178 
2179     int32_t videoScaleType = 0;
2180     napi_status status = napi_get_value_int32(env, args[0], &videoScaleType);
2181     if (status != napi_ok || videoScaleType < static_cast<int32_t>(Plugins::VideoScaleType::VIDEO_SCALE_TYPE_FIT)
2182         || videoScaleType > static_cast<int32_t>(Plugins::VideoScaleType::VIDEO_SCALE_TYPE_FIT_CROP)) {
2183         jsPlayer->OnErrorCb(MSERR_EXT_API9_INVALID_PARAMETER, "invalid parameters, please check the input scale type");
2184         return result;
2185     }
2186     jsPlayer->videoScaleType_ = videoScaleType;
2187 
2188     auto task = std::make_shared<TaskHandler<void>>([jsPlayer, videoScaleType]() {
2189         MEDIA_LOGI("SetVideoScaleType Task");
2190         if (jsPlayer->player_ != nullptr) {
2191             Format format;
2192             (void)format.PutIntValue(PlayerKeys::VIDEO_SCALE_TYPE, videoScaleType);
2193             (void)jsPlayer->player_->SetParameter(format);
2194         }
2195     });
2196     (void)jsPlayer->taskQue_->EnqueueTask(task);
2197     MEDIA_LOGI("JsSetVideoScaleType Out");
2198     return result;
2199 }
2200 
JsGetVideoScaleType(napi_env env,napi_callback_info info)2201 napi_value AVPlayerNapi::JsGetVideoScaleType(napi_env env, napi_callback_info info)
2202 {
2203     MediaTrace trace("AVPlayerNapi::get videoScaleType");
2204     napi_value result = nullptr;
2205     napi_get_undefined(env, &result);
2206     MEDIA_LOGI("JsGetVideoScaleType In");
2207 
2208     AVPlayerNapi *jsPlayer = AVPlayerNapi::GetJsInstance(env, info);
2209     CHECK_AND_RETURN_RET_LOG(jsPlayer != nullptr, result, "failed to GetJsInstance");
2210 
2211     napi_value value = nullptr;
2212     (void)napi_create_int32(env, static_cast<int32_t>(jsPlayer->videoScaleType_), &value);
2213     MEDIA_LOGI("JsGetVideoScaleType Out Current VideoScale: %{public}d", jsPlayer->videoScaleType_);
2214     return value;
2215 }
2216 
JsSetAudioInterruptMode(napi_env env,napi_callback_info info)2217 napi_value AVPlayerNapi::JsSetAudioInterruptMode(napi_env env, napi_callback_info info)
2218 {
2219     MediaTrace trace("AVPlayerNapi::set audioInterruptMode");
2220     napi_value result = nullptr;
2221     napi_get_undefined(env, &result);
2222     MEDIA_LOGI("JsSetAudioInterruptMode In");
2223 
2224     napi_value args[1] = { nullptr };
2225     size_t argCount = 1;
2226     AVPlayerNapi *jsPlayer = AVPlayerNapi::GetJsInstanceWithParameter(env, info, argCount, args);
2227     CHECK_AND_RETURN_RET_LOG(jsPlayer != nullptr, result, "failed to GetJsInstanceWithParameter");
2228 
2229     if (!jsPlayer->IsControllable()) {
2230         jsPlayer->OnErrorCb(MSERR_EXT_API9_OPERATE_NOT_PERMIT,
2231             "current state is not prepared/playing/paused/completed, unsupport audio interrupt operation");
2232         return result;
2233     }
2234 
2235     napi_valuetype valueType = napi_undefined;
2236     if (argCount < 1 || napi_typeof(env, args[0], &valueType) != napi_ok || valueType != napi_number) {
2237         jsPlayer->OnErrorCb(MSERR_EXT_API9_INVALID_PARAMETER, "SetAudioInterruptMode is not napi_number");
2238         return result;
2239     }
2240 
2241     int32_t interruptMode = 0;
2242     napi_status status = napi_get_value_int32(env, args[0], &interruptMode);
2243     if (status != napi_ok ||
2244         interruptMode < AudioStandard::InterruptMode::SHARE_MODE ||
2245         interruptMode > AudioStandard::InterruptMode::INDEPENDENT_MODE) {
2246         jsPlayer->OnErrorCb(MSERR_EXT_API9_INVALID_PARAMETER,
2247             "invalid parameters, please check the input interrupt Mode");
2248         return result;
2249     }
2250     jsPlayer->interruptMode_ = static_cast<AudioStandard::InterruptMode>(interruptMode);
2251 
2252     auto task = std::make_shared<TaskHandler<void>>([jsPlayer]() {
2253         MEDIA_LOGI("SetAudioInterruptMode Task");
2254         if (jsPlayer->player_ != nullptr) {
2255             Format format;
2256             (void)format.PutIntValue(PlayerKeys::AUDIO_INTERRUPT_MODE, jsPlayer->interruptMode_);
2257             (void)jsPlayer->player_->SetParameter(format);
2258         }
2259     });
2260     (void)jsPlayer->taskQue_->EnqueueTask(task);
2261     MEDIA_LOGI("JsSetAudioInterruptMode Out");
2262     return result;
2263 }
2264 
JsGetAudioInterruptMode(napi_env env,napi_callback_info info)2265 napi_value AVPlayerNapi::JsGetAudioInterruptMode(napi_env env, napi_callback_info info)
2266 {
2267     MediaTrace trace("AVPlayerNapi::get audioInterruptMode");
2268     napi_value result = nullptr;
2269     napi_get_undefined(env, &result);
2270     MEDIA_LOGI("JsGetAudioInterruptMode In");
2271 
2272     AVPlayerNapi *jsPlayer = AVPlayerNapi::GetJsInstance(env, info);
2273     CHECK_AND_RETURN_RET_LOG(jsPlayer != nullptr, result, "failed to GetJsInstance");
2274 
2275     napi_value value = nullptr;
2276     (void)napi_create_int32(env, static_cast<int32_t>(jsPlayer->interruptMode_), &value);
2277     MEDIA_LOGI("JsGetAudioInterruptMode Out");
2278     return value;
2279 }
2280 
JsSetAudioEffectMode(napi_env env,napi_callback_info info)2281 napi_value AVPlayerNapi::JsSetAudioEffectMode(napi_env env, napi_callback_info info)
2282 {
2283     MediaTrace trace("AVPlayerNapi::JsSetAudioEffectMode");
2284     MEDIA_LOGI("JsSetAudioEffectMode In");
2285     napi_value result = nullptr;
2286     napi_get_undefined(env, &result);
2287 
2288     size_t argCount = 1; // 1param audioEffectMode
2289     napi_value args[1] = { nullptr };
2290     AVPlayerNapi *jsPlayer = AVPlayerNapi::GetJsInstanceWithParameter(env, info, argCount, args);
2291     CHECK_AND_RETURN_RET_LOG(jsPlayer != nullptr, result, "failed to GetJsInstanceWithParameter");
2292 
2293     if (!jsPlayer->IsControllable()) {
2294         jsPlayer->OnErrorCb(MSERR_EXT_API9_OPERATE_NOT_PERMIT,
2295             "current state is not prepared/playing/paused/completed, unsupport audio effect mode operation");
2296         return result;
2297     }
2298 
2299     napi_valuetype valueType = napi_undefined;
2300     if (argCount < 1 || napi_typeof(env, args[0], &valueType) != napi_ok || valueType != napi_number) {
2301         jsPlayer->OnErrorCb(MSERR_EXT_API9_INVALID_PARAMETER, "audioEffectMode is not number");
2302         return result;
2303     }
2304 
2305     int32_t effectMode = OHOS::AudioStandard::AudioEffectMode::EFFECT_DEFAULT;
2306     napi_status status = napi_get_value_int32(env, args[0], &effectMode);
2307     if (status != napi_ok || effectMode > OHOS::AudioStandard::AudioEffectMode::EFFECT_DEFAULT ||
2308         effectMode < OHOS::AudioStandard::AudioEffectMode::EFFECT_NONE) {
2309         jsPlayer->OnErrorCb(MSERR_EXT_API9_INVALID_PARAMETER,
2310             "invalid audioEffectMode, please check the input audio effect Mode");
2311         return result;
2312     }
2313 
2314     if (jsPlayer->audioEffectMode_ == effectMode) {
2315         MEDIA_LOGI("Same effectMode parameter");
2316         return result;
2317     }
2318 
2319     jsPlayer->audioEffectMode_ = effectMode;
2320 
2321     auto task = std::make_shared<TaskHandler<void>>([jsPlayer, effectMode]() {
2322         MEDIA_LOGI("JsSetAudioEffectMode Task in");
2323         if (jsPlayer->player_ != nullptr) {
2324             Format format;
2325             (void)format.PutIntValue(PlayerKeys::AUDIO_EFFECT_MODE, effectMode);
2326             (void)jsPlayer->player_->SetParameter(format);
2327         }
2328         MEDIA_LOGI("JsSetAudioEffectMode Task out");
2329     });
2330     (void)jsPlayer->taskQue_->EnqueueTask(task);
2331     MEDIA_LOGI("JsSetAudioEffectMode Out");
2332     return result;
2333 }
2334 
JsGetAudioEffectMode(napi_env env,napi_callback_info info)2335 napi_value AVPlayerNapi::JsGetAudioEffectMode(napi_env env, napi_callback_info info)
2336 {
2337     MediaTrace trace("AVPlayerNapi::JsGetAudioEffectMode");
2338     MEDIA_LOGI("JsGetAudioEffectMode In");
2339     napi_value result = nullptr;
2340     napi_get_undefined(env, &result);
2341 
2342     AVPlayerNapi *jsPlayer = AVPlayerNapi::GetJsInstance(env, info);
2343     CHECK_AND_RETURN_RET_LOG(jsPlayer != nullptr, result, "failed to GetJsInstance");
2344 
2345     napi_value value = nullptr;
2346     (void)napi_create_int32(env, static_cast<int32_t>(jsPlayer->audioEffectMode_), &value);
2347     MEDIA_LOGI("JsGetAudioEffectMode Out");
2348     return value;
2349 }
2350 
JsHandleParameter(napi_env env,napi_value args,AVPlayerNapi * jsPlayer)2351 bool AVPlayerNapi::JsHandleParameter(napi_env env, napi_value args, AVPlayerNapi *jsPlayer)
2352 {
2353     int32_t content = CONTENT_TYPE_UNKNOWN;
2354     int32_t usage = -1;
2355     int32_t rendererFlags = -1;
2356     int32_t volumeMode = -1;
2357     (void)CommonNapi::GetPropertyInt32(env, args, "content", content);
2358     (void)CommonNapi::GetPropertyInt32(env, args, "usage", usage);
2359     (void)CommonNapi::GetPropertyInt32(env, args, "rendererFlags", rendererFlags);
2360     (void)CommonNapi::GetPropertyInt32(env, args, "volumeMode", volumeMode);
2361     MEDIA_LOGI("content = %{public}d, usage = %{public}d, rendererFlags = %{public}d, volumeMode = %{public}d",
2362         content, usage, rendererFlags, volumeMode);
2363     std::vector<int32_t> contents = {
2364         CONTENT_TYPE_UNKNOWN, CONTENT_TYPE_SPEECH,
2365         CONTENT_TYPE_MUSIC, CONTENT_TYPE_MOVIE,
2366         CONTENT_TYPE_SONIFICATION, CONTENT_TYPE_RINGTONE
2367     };
2368     std::vector<int32_t> usages = {
2369         STREAM_USAGE_UNKNOWN, STREAM_USAGE_MEDIA,
2370         STREAM_USAGE_MUSIC, STREAM_USAGE_VOICE_COMMUNICATION,
2371         STREAM_USAGE_VOICE_ASSISTANT, STREAM_USAGE_ALARM,
2372         STREAM_USAGE_VOICE_MESSAGE, STREAM_USAGE_NOTIFICATION_RINGTONE,
2373         STREAM_USAGE_RINGTONE, STREAM_USAGE_NOTIFICATION,
2374         STREAM_USAGE_ACCESSIBILITY, STREAM_USAGE_SYSTEM,
2375         STREAM_USAGE_MOVIE, STREAM_USAGE_GAME,
2376         STREAM_USAGE_AUDIOBOOK, STREAM_USAGE_NAVIGATION,
2377         STREAM_USAGE_DTMF, STREAM_USAGE_ENFORCED_TONE,
2378         STREAM_USAGE_ULTRASONIC, STREAM_USAGE_VIDEO_COMMUNICATION
2379     };
2380     std::vector<int32_t> systemUsages = { STREAM_USAGE_VOICE_CALL_ASSISTANT };
2381     usages.insert(usages.end(), systemUsages.begin(), systemUsages.end());
2382     if (std::find(systemUsages.begin(), systemUsages.end(), usage) != systemUsages.end() && !IsSystemApp()) {
2383         MEDIA_LOGI("The caller is not a system app, usage = %{public}d", usage);
2384         return false;
2385     }
2386     if (std::find(contents.begin(), contents.end(), content) == contents.end() ||
2387         std::find(usages.begin(), usages.end(), usage) == usages.end()) {
2388         return false;
2389     }
2390 
2391     if (jsPlayer->audioRendererInfo_.contentType != content ||
2392         jsPlayer->audioRendererInfo_.streamUsage != usage) {
2393         jsPlayer->audioEffectMode_ = OHOS::AudioStandard::AudioEffectMode::EFFECT_DEFAULT;
2394     }
2395 
2396     jsPlayer->audioRendererInfo_ = AudioStandard::AudioRendererInfo {
2397         static_cast<AudioStandard::ContentType>(content),
2398         static_cast<AudioStandard::StreamUsage>(usage),
2399         rendererFlags,
2400         static_cast<AudioStandard::AudioVolumeMode>(volumeMode)
2401     };
2402     return true;
2403 }
2404 
SeekEnqueueTask(AVPlayerNapi * jsPlayer,int32_t time,int32_t mode)2405 void AVPlayerNapi::SeekEnqueueTask(AVPlayerNapi *jsPlayer, int32_t time, int32_t mode)
2406 {
2407     auto task = std::make_shared<TaskHandler<void>>([jsPlayer, time, mode]() {
2408         MEDIA_LOGI("0x%{public}06" PRIXPTR " JsSeek Task In", FAKE_POINTER(jsPlayer));
2409         if (jsPlayer->player_ != nullptr) {
2410             (void)jsPlayer->player_->Seek(time, jsPlayer->TransferSeekMode(mode));
2411         }
2412         MEDIA_LOGI("0x%{public}06" PRIXPTR " JsSeek Task Out", FAKE_POINTER(jsPlayer));
2413     });
2414     MEDIA_LOGI("0x%{public}06" PRIXPTR " JsSeek EnqueueTask In", FAKE_POINTER(jsPlayer));
2415     (void)jsPlayer->taskQue_->EnqueueTask(task);
2416     MEDIA_LOGI("0x%{public}06" PRIXPTR " JsSeek Out", FAKE_POINTER(jsPlayer));
2417 }
2418 
JsSetAudioRendererInfo(napi_env env,napi_callback_info info)2419 napi_value AVPlayerNapi::JsSetAudioRendererInfo(napi_env env, napi_callback_info info)
2420 {
2421     MediaTrace trace("AVPlayerNapi::set audioRendererInfo");
2422     napi_value result = nullptr;
2423     napi_get_undefined(env, &result);
2424     MEDIA_LOGI("JsSetAudioRendererInfo In");
2425 
2426     napi_value args[1] = { nullptr };
2427     size_t argCount = 1;
2428     AVPlayerNapi *jsPlayer = AVPlayerNapi::GetJsInstanceWithParameter(env, info, argCount, args);
2429     CHECK_AND_RETURN_RET_LOG(jsPlayer != nullptr, result, "failed to GetJsInstanceWithParameter");
2430     napi_valuetype valueType = napi_undefined;
2431     if (argCount < 1 || napi_typeof(env, args[0], &valueType) != napi_ok || valueType != napi_object) {
2432         jsPlayer->OnErrorCb(MSERR_EXT_API9_INVALID_PARAMETER, "invalid parameters, please check the input");
2433         return result;
2434     }
2435     if (jsPlayer->GetCurrentState() != AVPlayerState::STATE_INITIALIZED) {
2436         jsPlayer->OnErrorCb(MSERR_EXT_API9_OPERATE_NOT_PERMIT,
2437             "current state is not initialized, unsupport to set audio renderer info");
2438         return result;
2439     }
2440     if (!AVPlayerNapi::JsHandleParameter(env, args[0], jsPlayer)) {
2441         jsPlayer->OnErrorCb(MSERR_EXT_API9_INVALID_PARAMETER,
2442             "invalid parameters, please check the input audio renderer info");
2443         return result;
2444     }
2445     auto task = std::make_shared<TaskHandler<void>>([jsPlayer]() {
2446         MEDIA_LOGI("SetAudioRendererInfo Task");
2447         if (jsPlayer->player_ != nullptr) {
2448             Format format;
2449             (void)format.PutIntValue(PlayerKeys::CONTENT_TYPE, jsPlayer->audioRendererInfo_.contentType);
2450             (void)format.PutIntValue(PlayerKeys::STREAM_USAGE, jsPlayer->audioRendererInfo_.streamUsage);
2451             (void)format.PutIntValue(PlayerKeys::RENDERER_FLAG, jsPlayer->audioRendererInfo_.rendererFlags);
2452             (void)format.PutIntValue(PlayerKeys::VOLUME_MODE, jsPlayer->audioRendererInfo_.volumeMode);
2453             (void)jsPlayer->player_->SetParameter(format);
2454         }
2455     });
2456     (void)jsPlayer->taskQue_->EnqueueTask(task);
2457     MEDIA_LOGI("JsSetAudioRendererInfo Out");
2458     return result;
2459 }
2460 
JsGetAudioRendererInfo(napi_env env,napi_callback_info info)2461 napi_value AVPlayerNapi::JsGetAudioRendererInfo(napi_env env, napi_callback_info info)
2462 {
2463     MediaTrace trace("AVPlayerNapi::get audioRendererInfo");
2464     napi_value result = nullptr;
2465     napi_get_undefined(env, &result);
2466     MEDIA_LOGI("JsGetAudioRendererInfo In");
2467 
2468     AVPlayerNapi *jsPlayer = AVPlayerNapi::GetJsInstance(env, info);
2469     CHECK_AND_RETURN_RET_LOG(jsPlayer != nullptr, result, "failed to GetJsInstance");
2470 
2471     int32_t content = static_cast<int32_t>(jsPlayer->audioRendererInfo_.contentType);
2472     int32_t usage = static_cast<int32_t>(jsPlayer->audioRendererInfo_.streamUsage);
2473     int32_t rendererFlags = jsPlayer->audioRendererInfo_.rendererFlags;
2474     int32_t volumeMode = static_cast<int32_t>(jsPlayer->audioRendererInfo_.volumeMode);
2475     (void)napi_create_object(env, &result);
2476     CommonNapi::SetPropertyInt32(env, result, "content", content);
2477     CommonNapi::SetPropertyInt32(env, result, "usage", usage);
2478     CommonNapi::SetPropertyInt32(env, result, "rendererFlags", rendererFlags);
2479     CommonNapi::SetPropertyInt32(env, result, "volumeMode", volumeMode);
2480     MEDIA_LOGI("JsGetAudioRendererInfo Out");
2481     return result;
2482 }
2483 
JsGetCurrentTime(napi_env env,napi_callback_info info)2484 napi_value AVPlayerNapi::JsGetCurrentTime(napi_env env, napi_callback_info info)
2485 {
2486     MediaTrace trace("AVPlayerNapi::get currentTime");
2487     napi_value result = nullptr;
2488     napi_get_undefined(env, &result);
2489     MEDIA_LOGD("JsGetCurrentTime In");
2490 
2491     AVPlayerNapi *jsPlayer = AVPlayerNapi::GetJsInstance(env, info);
2492     CHECK_AND_RETURN_RET_LOG(jsPlayer != nullptr, result, "failed to GetJsInstance");
2493 
2494     int32_t currentTime = -1;
2495     if (jsPlayer->IsControllable()) {
2496         currentTime = jsPlayer->position_;
2497     }
2498 
2499     if (jsPlayer->IsLiveSource() && jsPlayer->dataSrcCb_ == nullptr) {
2500         currentTime = -1;
2501     }
2502     napi_value value = nullptr;
2503     (void)napi_create_int32(env, currentTime, &value);
2504     std::string curState = jsPlayer->GetCurrentState();
2505     if (currentTime != -1) {
2506         MEDIA_LOGI("0x%{public}06" PRIXPTR " JsGetCurrenTime Out, state %{public}s, time: %{public}d",
2507             FAKE_POINTER(jsPlayer), curState.c_str(), currentTime);
2508     }
2509     return value;
2510 }
2511 
JsGetPlaybackPosition(napi_env env,napi_callback_info info)2512 napi_value AVPlayerNapi::JsGetPlaybackPosition(napi_env env, napi_callback_info info)
2513 {
2514     MediaTrace trace("AVPlayerNapi::get playbackPosition");
2515     napi_value result = nullptr;
2516     napi_get_undefined(env, &result);
2517     MEDIA_LOGD("JsGetPlaybackPosition In");
2518 
2519     AVPlayerNapi *jsPlayer = AVPlayerNapi::GetJsInstance(env, info);
2520     CHECK_AND_RETURN_RET_LOG(jsPlayer != nullptr, result, "failed to GetJsInstance");
2521     CHECK_AND_RETURN_RET_LOG(jsPlayer->player_ != nullptr, result, "failed to check player_");
2522 
2523     std::string curState = jsPlayer->GetCurrentState();
2524     if (curState == AVPlayerState::STATE_PLAYING &&
2525         curState == AVPlayerState::STATE_PAUSED &&
2526         curState == AVPlayerState::STATE_PREPARED &&
2527         curState == AVPlayerState::STATE_COMPLETED) {
2528         return CommonNapi::ThrowError(env, MSERR_EXT_API9_OPERATE_NOT_PERMIT,
2529             "current state is not prepared/playing/paused/completed, not support get playback position");
2530     }
2531 
2532     int32_t playbackPosition = 0;
2533     (void)jsPlayer->player_->GetPlaybackPosition(playbackPosition);
2534     if (playbackPosition != 0) {
2535         MEDIA_LOGD("0x%{public}06" PRIXPTR " JsGetPlaybackPosition Out, state %{public}s, time: %{public}d",
2536             FAKE_POINTER(jsPlayer), curState.c_str(), playbackPosition);
2537     }
2538 
2539     napi_value value = nullptr;
2540     napi_status status = napi_create_int32(env, playbackPosition, &value);
2541     if (status != napi_ok) {
2542         MEDIA_LOGE("JsGetPlaybackPosition status != napi_ok");
2543     }
2544     return value;
2545 }
2546 
JsGetDuration(napi_env env,napi_callback_info info)2547 napi_value AVPlayerNapi::JsGetDuration(napi_env env, napi_callback_info info)
2548 {
2549     MediaTrace trace("AVPlayerNapi::get duration");
2550     napi_value result = nullptr;
2551     napi_get_undefined(env, &result);
2552     MEDIA_LOGD("JsGetDuration In");
2553 
2554     AVPlayerNapi *jsPlayer = AVPlayerNapi::GetJsInstance(env, info);
2555     CHECK_AND_RETURN_RET_LOG(jsPlayer != nullptr, result, "failed to GetJsInstance");
2556 
2557     int32_t duration = -1;
2558     if (jsPlayer->IsControllable() && !jsPlayer->IsLiveSource()) {
2559         duration = jsPlayer->duration_;
2560     }
2561 
2562     napi_value value = nullptr;
2563     (void)napi_create_int32(env, duration, &value);
2564     std::string curState = jsPlayer->GetCurrentState();
2565     MEDIA_LOGD("JsGetDuration Out, state %{public}s, duration %{public}d", curState.c_str(), duration);
2566     return value;
2567 }
2568 
IsControllable()2569 bool AVPlayerNapi::IsControllable()
2570 {
2571     auto state = GetCurrentState();
2572     if (state == AVPlayerState::STATE_PREPARED || state == AVPlayerState::STATE_PLAYING ||
2573         state == AVPlayerState::STATE_PAUSED || state == AVPlayerState::STATE_COMPLETED) {
2574         return true;
2575     } else {
2576         return false;
2577     }
2578 }
2579 
CanSetPlayRange()2580 bool AVPlayerNapi::CanSetPlayRange()
2581 {
2582     auto state = GetCurrentState();
2583     if (state == AVPlayerState::STATE_INITIALIZED || state == AVPlayerState::STATE_PREPARED ||
2584         state == AVPlayerState::STATE_PAUSED || state == AVPlayerState::STATE_STOPPED ||
2585         state == AVPlayerState::STATE_COMPLETED) {
2586         return true;
2587     }
2588     return false;
2589 }
2590 
CanSetSuperResolution()2591 bool AVPlayerNapi::CanSetSuperResolution()
2592 {
2593     auto state = GetCurrentState();
2594     if (state == AVPlayerState::STATE_INITIALIZED || state == AVPlayerState::STATE_PREPARED ||
2595         state == AVPlayerState::STATE_PLAYING || state == AVPlayerState::STATE_PAUSED ||
2596         state == AVPlayerState::STATE_STOPPED || state == AVPlayerState::STATE_COMPLETED) {
2597         return true;
2598     }
2599     return false;
2600 }
2601 
GetCurrentState()2602 std::string AVPlayerNapi::GetCurrentState()
2603 {
2604     if (isReleased_.load()) {
2605         return AVPlayerState::STATE_RELEASED;
2606     }
2607 
2608     std::string curState = AVPlayerState::STATE_ERROR;
2609     static const std::map<PlayerStates, std::string> stateMap = {
2610         {PLAYER_IDLE, AVPlayerState::STATE_IDLE},
2611         {PLAYER_INITIALIZED, AVPlayerState::STATE_INITIALIZED},
2612         {PLAYER_PREPARED, AVPlayerState::STATE_PREPARED},
2613         {PLAYER_STARTED, AVPlayerState::STATE_PLAYING},
2614         {PLAYER_PAUSED, AVPlayerState::STATE_PAUSED},
2615         {PLAYER_STOPPED, AVPlayerState::STATE_STOPPED},
2616         {PLAYER_PLAYBACK_COMPLETE, AVPlayerState::STATE_COMPLETED},
2617         {PLAYER_STATE_ERROR, AVPlayerState::STATE_ERROR},
2618     };
2619 
2620     if (stateMap.find(state_) != stateMap.end()) {
2621         curState = stateMap.at(state_);
2622     }
2623     return curState;
2624 }
2625 
JsGetState(napi_env env,napi_callback_info info)2626 napi_value AVPlayerNapi::JsGetState(napi_env env, napi_callback_info info)
2627 {
2628     MediaTrace trace("AVPlayerNapi::get state");
2629     napi_value result = nullptr;
2630     napi_get_undefined(env, &result);
2631     MEDIA_LOGD("JsGetState In");
2632 
2633     AVPlayerNapi *jsPlayer = AVPlayerNapi::GetJsInstance(env, info);
2634     CHECK_AND_RETURN_RET_LOG(jsPlayer != nullptr, result, "failed to GetJsInstance");
2635 
2636     std::string curState = jsPlayer->GetCurrentState();
2637     MEDIA_LOGI("0x%{public}06" PRIXPTR " JsGetState curState: %{public}s ",
2638         FAKE_POINTER(jsPlayer), curState.c_str());
2639     napi_value value = nullptr;
2640     (void)napi_create_string_utf8(env, curState.c_str(), NAPI_AUTO_LENGTH, &value);
2641     MEDIA_LOGD("JsGetState Out");
2642     return value;
2643 }
2644 
JsGetWidth(napi_env env,napi_callback_info info)2645 napi_value AVPlayerNapi::JsGetWidth(napi_env env, napi_callback_info info)
2646 {
2647     MediaTrace trace("AVPlayerNapi::get width");
2648     napi_value result = nullptr;
2649     napi_get_undefined(env, &result);
2650     MEDIA_LOGI("JsGetWidth");
2651 
2652     AVPlayerNapi *jsPlayer = AVPlayerNapi::GetJsInstance(env, info);
2653     CHECK_AND_RETURN_RET_LOG(jsPlayer != nullptr, result, "failed to GetJsInstance");
2654 
2655     int32_t width = 0;
2656     if (jsPlayer->IsControllable()) {
2657         width = jsPlayer->width_;
2658     }
2659 
2660     napi_value value = nullptr;
2661     (void)napi_create_int32(env, width, &value);
2662     return value;
2663 }
2664 
JsGetHeight(napi_env env,napi_callback_info info)2665 napi_value AVPlayerNapi::JsGetHeight(napi_env env, napi_callback_info info)
2666 {
2667     MediaTrace trace("AVPlayerNapi::get height");
2668     napi_value result = nullptr;
2669     napi_get_undefined(env, &result);
2670     MEDIA_LOGI("JsGetHeight");
2671 
2672     AVPlayerNapi *jsPlayer = AVPlayerNapi::GetJsInstance(env, info);
2673     CHECK_AND_RETURN_RET_LOG(jsPlayer != nullptr, result, "failed to GetJsInstance");
2674 
2675     int32_t height = 0;
2676     if (jsPlayer->IsControllable()) {
2677         height = jsPlayer->height_;
2678     }
2679 
2680     napi_value value = nullptr;
2681     (void)napi_create_int32(env, height, &value);
2682     return value;
2683 }
2684 
JsGetTrackDescription(napi_env env,napi_callback_info info)2685 napi_value AVPlayerNapi::JsGetTrackDescription(napi_env env, napi_callback_info info)
2686 {
2687     MediaTrace trace("AVPlayerNapi::get trackDescription");
2688     napi_value result = nullptr;
2689     napi_get_undefined(env, &result);
2690     MEDIA_LOGI("GetTrackDescription In");
2691 
2692     auto promiseCtx = std::make_unique<AVPlayerContext>(env);
2693     napi_value args[1] = { nullptr };
2694     size_t argCount = 1;
2695     promiseCtx->napi = AVPlayerNapi::GetJsInstanceWithParameter(env, info, argCount, args);
2696     promiseCtx->callbackRef = CommonNapi::CreateReference(env, args[0]);
2697     promiseCtx->deferred = CommonNapi::CreatePromise(env, promiseCtx->callbackRef, result);
2698 
2699     auto jsPlayer = promiseCtx->napi;
2700     CHECK_AND_RETURN_RET_LOG(jsPlayer != nullptr, result, "failed to GetJsInstance");
2701     MEDIA_LOGD("0x%{public}06" PRIXPTR " JsGetTrackDescription EnqueueTask In", FAKE_POINTER(jsPlayer));
2702     promiseCtx->asyncTask = jsPlayer->GetTrackDescriptionTask(promiseCtx);
2703     MEDIA_LOGD("0x%{public}06" PRIXPTR " JsGetTrackDescription EnqueueTask Out", FAKE_POINTER(jsPlayer));
2704 
2705     // async work
2706     napi_value resource = nullptr;
2707     napi_create_string_utf8(env, "JsGetTrackDescription", NAPI_AUTO_LENGTH, &resource);
2708     NAPI_CALL(env, napi_create_async_work(env, nullptr, resource,
2709         [](napi_env env, void *data) {
2710             MEDIA_LOGI("Wait JsGetTrackDescription Task Start");
2711             auto promiseCtx = reinterpret_cast<AVPlayerContext *>(data);
2712             CHECK_AND_RETURN_LOG(promiseCtx != nullptr, "promiseCtx is nullptr!");
2713             if (promiseCtx->asyncTask) {
2714                 auto result = promiseCtx->asyncTask->GetResult();
2715                 if (!result.HasResult()) {
2716                     return promiseCtx->SignError(MSERR_EXT_API9_OPERATE_NOT_PERMIT,
2717                                                  "task has been cleared");
2718                 }
2719                 if (result.Value().first != MSERR_EXT_API9_OK) {
2720                     return promiseCtx->SignError(result.Value().first, result.Value().second);
2721                 }
2722                 promiseCtx->JsResult = std::make_unique<MediaJsResultArray>(promiseCtx->trackInfoVec_);
2723             }
2724             MEDIA_LOGI("Wait JsGetTrackDescription Task End");
2725         },
2726         MediaAsyncContext::CompleteCallback, static_cast<void *>(promiseCtx.get()), &promiseCtx->work));
2727     napi_queue_async_work_with_qos(env, promiseCtx->work, napi_qos_user_initiated);
2728     promiseCtx.release();
2729     MEDIA_LOGI("GetTrackDescription Out");
2730     return result;
2731 }
2732 
GetTrackDescriptionTask(const std::unique_ptr<AVPlayerContext> & promiseCtx)2733 std::shared_ptr<TaskHandler<TaskRet>> AVPlayerNapi::GetTrackDescriptionTask(const std::unique_ptr<AVPlayerContext>
2734                                                                             &promiseCtx)
2735 {
2736     auto task = std::make_shared<TaskHandler<TaskRet>>([this, &trackInfo = promiseCtx->trackInfoVec_]() {
2737         MEDIA_LOGI("0x%{public}06" PRIXPTR " GetTrackDescription Task In", FAKE_POINTER(this));
2738         std::unique_lock<std::mutex> lock(taskMutex_);
2739         trackInfo.clear();
2740         if (IsControllable()) {
2741             (void)player_->GetVideoTrackInfo(trackInfo);
2742             (void)player_->GetAudioTrackInfo(trackInfo);
2743             (void)player_->GetSubtitleTrackInfo(trackInfo);
2744         } else {
2745             return TaskRet(MSERR_EXT_API9_OPERATE_NOT_PERMIT,
2746                            "current state unsupport get track description");
2747         }
2748         MEDIA_LOGI("0x%{public}06" PRIXPTR " GetTrackDescription Task Out", FAKE_POINTER(this));
2749         return TaskRet(MSERR_EXT_API9_OK, "Success");
2750     });
2751     (void)taskQue_->EnqueueTask(task);
2752     return task;
2753 }
2754 
JsGetSelectedTracks(napi_env env,napi_callback_info info)2755 napi_value AVPlayerNapi::JsGetSelectedTracks(napi_env env, napi_callback_info info)
2756 {
2757     MediaTrace trace("AVPlayerNapi::get selected tracks");
2758     napi_value result = nullptr;
2759     napi_get_undefined(env, &result);
2760     MEDIA_LOGI("JsGetSelectedTracks In");
2761 
2762     auto promiseCtx = std::make_unique<AVPlayerContext>(env);
2763     napi_value args[1] = { nullptr };
2764     size_t argCount = 1;
2765     promiseCtx->napi = AVPlayerNapi::GetJsInstanceWithParameter(env, info, argCount, args);
2766     promiseCtx->callbackRef = CommonNapi::CreateReference(env, args[0]);
2767     promiseCtx->deferred = CommonNapi::CreatePromise(env, promiseCtx->callbackRef, result);
2768     // async work
2769     napi_value resource = nullptr;
2770     napi_create_string_utf8(env, "JsGetSelectedTracks", NAPI_AUTO_LENGTH, &resource);
2771     NAPI_CALL(env, napi_create_async_work(env, nullptr, resource, [](napi_env env, void *data) {
2772             MEDIA_LOGI("JsGetSelectedTracks Task");
2773             auto promiseCtx = reinterpret_cast<AVPlayerContext *>(data);
2774             CHECK_AND_RETURN_LOG(promiseCtx != nullptr, "promiseCtx is nullptr!");
2775 
2776             auto jsPlayer = promiseCtx->napi;
2777             if (jsPlayer == nullptr) {
2778                 return promiseCtx->SignError(MSERR_EXT_API9_OPERATE_NOT_PERMIT, "avplayer is deconstructed");
2779             }
2780 
2781             std::vector<int32_t> trackIndex;
2782             if (jsPlayer->IsControllable()) {
2783                 int32_t videoIndex = -1;
2784                 (void)jsPlayer->player_->GetCurrentTrack(MediaType::MEDIA_TYPE_VID, videoIndex);
2785                 if (videoIndex != -1) {
2786                     trackIndex.push_back(videoIndex);
2787                 }
2788 
2789                 int32_t audioIndex = -1;
2790                 (void)jsPlayer->player_->GetCurrentTrack(MediaType::MEDIA_TYPE_AUD, audioIndex);
2791                 if (audioIndex != -1) {
2792                     trackIndex.push_back(audioIndex);
2793                 }
2794 
2795                 int32_t subtitleIndex = -1;
2796                 (void)jsPlayer->player_->GetCurrentTrack(MediaType::MEDIA_TYPE_SUBTITLE, subtitleIndex);
2797                 if (subtitleIndex != -1) {
2798                     trackIndex.push_back(subtitleIndex);
2799                 }
2800             } else {
2801                 return promiseCtx->SignError(MSERR_EXT_API9_OPERATE_NOT_PERMIT,
2802                     "current state unsupport get current selections");
2803             }
2804             promiseCtx->JsResult = std::make_unique<MediaJsResultIntArray>(trackIndex);
2805         },
2806         MediaAsyncContext::CompleteCallback, static_cast<void *>(promiseCtx.get()), &promiseCtx->work));
2807     napi_queue_async_work_with_qos(env, promiseCtx->work, napi_qos_user_initiated);
2808     promiseCtx.release();
2809     MEDIA_LOGI("JsGetSelectedTracks Out");
2810     return result;
2811 }
2812 
HandleSelectTrack(std::unique_ptr<AVPlayerContext> & promiseCtx,napi_env env,napi_value args[],size_t argCount)2813 void AVPlayerNapi::HandleSelectTrack(std::unique_ptr<AVPlayerContext> &promiseCtx, napi_env env,
2814     napi_value args[], size_t argCount)
2815 {
2816     napi_valuetype valueType = napi_undefined;
2817     if (argCount < 1 || napi_typeof(env, args[0], &valueType) != napi_ok || valueType != napi_number) {
2818         promiseCtx->SignError(MSERR_EXT_API9_INVALID_PARAMETER, "track index is not number");
2819         return;
2820     }
2821 
2822     auto jsPlayer = promiseCtx->napi;
2823     napi_status status = napi_get_value_int32(env, args[0], &jsPlayer->index_);
2824     if (status != napi_ok || jsPlayer->index_ < 0) {
2825         promiseCtx->SignError(MSERR_EXT_API9_INVALID_PARAMETER, "invalid parameters, please check the track index");
2826         return;
2827     }
2828 
2829     if (argCount > 1) {
2830         if (napi_typeof(env, args[1], &valueType) != napi_ok || valueType != napi_number) {
2831             promiseCtx->SignError(MSERR_EXT_API9_INVALID_PARAMETER, "switch mode is not number");
2832             return;
2833         }
2834         status = napi_get_value_int32(env, args[1], &jsPlayer->mode_);
2835         if (status != napi_ok || jsPlayer->mode_ < SWITCH_SMOOTH || jsPlayer->mode_ > SWITCH_CLOSEST) {
2836             promiseCtx->SignError(MSERR_EXT_API9_INVALID_PARAMETER, "invalid parameters, please switch seek mode");
2837             return;
2838         }
2839     }
2840 
2841     if (!jsPlayer->IsControllable()) {
2842         promiseCtx->SignError(MSERR_EXT_API9_OPERATE_NOT_PERMIT,
2843             "current state is not prepared/playing/paused/completed, unsupport selectTrack operation");
2844         return;
2845     }
2846 }
2847 
JsSelectTrack(napi_env env,napi_callback_info info)2848 napi_value AVPlayerNapi::JsSelectTrack(napi_env env, napi_callback_info info)
2849 {
2850     MediaTrace trace("AVPlayerNapi::selectTrack");
2851     MEDIA_LOGI("JsSelectTrack In");
2852     napi_value result = nullptr;
2853     napi_get_undefined(env, &result);
2854 
2855     auto promiseCtx = std::make_unique<AVPlayerContext>(env);
2856     size_t argCount = 3; // 2 prarm, args[0]:index args[1]:SwitchMode callbackRef
2857     napi_value args[ARRAY_ARG_COUNTS_THREE] = { nullptr };
2858     promiseCtx->napi = AVPlayerNapi::GetJsInstanceWithParameter(env, info, argCount, args);
2859     promiseCtx->callbackRef = CommonNapi::CreateReference(env, args[argCount -1]);
2860     promiseCtx->deferred = CommonNapi::CreatePromise(env, promiseCtx->callbackRef, result);
2861     CHECK_AND_RETURN_RET_LOG(promiseCtx->napi != nullptr, result, "failed to GetJsInstanceWithParameter");
2862 
2863     promiseCtx->napi->HandleSelectTrack(promiseCtx, env, args, argCount);
2864 
2865     // async work
2866     napi_value resource = nullptr;
2867     napi_create_string_utf8(env, "JsSelectTrack ", NAPI_AUTO_LENGTH, &resource);
2868     NAPI_CALL(env, napi_create_async_work(env, nullptr, resource, [](napi_env env, void *data) {
2869         MEDIA_LOGI("JsSelectTrack Task");
2870         auto promiseCtx = reinterpret_cast<AVPlayerContext *>(data);
2871         CHECK_AND_RETURN_LOG(promiseCtx != nullptr, "promiseCtx is nullptr!");
2872 
2873         CHECK_AND_RETURN(!promiseCtx->errFlag);
2874 
2875         auto jsPlayer = promiseCtx->napi;
2876         if (jsPlayer == nullptr) {
2877             return promiseCtx->SignError(MSERR_EXT_API9_OPERATE_NOT_PERMIT, "avplayer is deconstructed");
2878         }
2879 
2880         auto task = std::make_shared<TaskHandler<void>>([jsPlayer, index = jsPlayer->index_, mode = jsPlayer->mode_]() {
2881             MEDIA_LOGI("0x%{public}06" PRIXPTR " JsSelectTrack Task In", FAKE_POINTER(jsPlayer));
2882             if (jsPlayer->player_ != nullptr) {
2883                 (void)jsPlayer->player_->SelectTrack(index, jsPlayer->TransferSwitchMode(mode));
2884             }
2885             MEDIA_LOGI("0x%{public}06" PRIXPTR " JsSelectTrack Task Out", FAKE_POINTER(jsPlayer));
2886         });
2887         MEDIA_LOGI("0x%{public}06" PRIXPTR " JsSelectTrack EnqueueTask In", FAKE_POINTER(jsPlayer));
2888         (void)jsPlayer->taskQue_->EnqueueTask(task);
2889         MEDIA_LOGI("0x%{public}06" PRIXPTR " JsSelectTrack Out", FAKE_POINTER(jsPlayer));
2890     },
2891     MediaAsyncContext::CompleteCallback, static_cast<void *>(promiseCtx.get()), &promiseCtx->work));
2892     napi_queue_async_work_with_qos(env, promiseCtx->work, napi_qos_user_initiated);
2893     promiseCtx.release();
2894     MEDIA_LOGI("JsSelectTrack Out");
2895     return result;
2896 }
2897 
JsDeselectTrack(napi_env env,napi_callback_info info)2898 napi_value AVPlayerNapi::JsDeselectTrack(napi_env env, napi_callback_info info)
2899 {
2900     MediaTrace trace("AVPlayerNapi::deselectTrack");
2901     MEDIA_LOGI("deselectTrack In");
2902     napi_value result = nullptr;
2903     napi_get_undefined(env, &result);
2904 
2905     size_t argCount = 1;     // 1 prarm, args[0]:index
2906     napi_value args[1] = { nullptr };
2907     AVPlayerNapi *jsPlayer = AVPlayerNapi::GetJsInstanceWithParameter(env, info, argCount, args);
2908     CHECK_AND_RETURN_RET_LOG(jsPlayer != nullptr, result, "failed to GetJsInstanceWithParameter");
2909 
2910     napi_valuetype valueType = napi_undefined;
2911     if (argCount < 1 || napi_typeof(env, args[0], &valueType) != napi_ok || valueType != napi_number) {
2912         jsPlayer->OnErrorCb(MSERR_EXT_API9_INVALID_PARAMETER, "track index is not number");
2913         return result;
2914     }
2915 
2916     int32_t index = -1;
2917     napi_status status = napi_get_value_int32(env, args[0], &index);
2918     if (status != napi_ok || index < 0) {
2919         jsPlayer->OnErrorCb(MSERR_EXT_API9_INVALID_PARAMETER, "invalid parameters, please check the track index");
2920         return result;
2921     }
2922 
2923     if (!jsPlayer->IsControllable()) {
2924         jsPlayer->OnErrorCb(MSERR_EXT_API9_OPERATE_NOT_PERMIT,
2925             "current state is not prepared/playing/paused/completed, unsupport deselecttrack operation");
2926         return result;
2927     }
2928 
2929     auto task = std::make_shared<TaskHandler<void>>([jsPlayer, index]() {
2930         MEDIA_LOGI("deselectTrack Task");
2931         if (jsPlayer->player_ != nullptr) {
2932             (void)jsPlayer->player_->DeselectTrack(index);
2933         }
2934         MEDIA_LOGI("deselectTrack Task end");
2935     });
2936     (void)jsPlayer->taskQue_->EnqueueTask(task);
2937     return result;
2938 }
2939 
JsGetCurrentTrack(napi_env env,napi_callback_info info)2940 napi_value AVPlayerNapi::JsGetCurrentTrack(napi_env env, napi_callback_info info)
2941 {
2942     MediaTrace trace("AVPlayerNapi::JsGetCurrentTrack");
2943     MEDIA_LOGI("GetCurrentTrack In");
2944     napi_value result = nullptr;
2945     napi_get_undefined(env, &result);
2946 
2947     size_t argCount = 2; // 2 param: trackType + callback
2948     napi_value args[ARRAY_ARG_COUNTS_TWO] = { nullptr };
2949     auto promiseCtx = std::make_unique<AVPlayerContext>(env);
2950     promiseCtx->napi = AVPlayerNapi::GetJsInstanceWithParameter(env, info, argCount, args);
2951     CHECK_AND_RETURN_RET_LOG(promiseCtx->napi != nullptr, result, "failed to GetJsInstanceWithParameter");
2952     promiseCtx->callbackRef = CommonNapi::CreateReference(env, args[1]);
2953     promiseCtx->deferred = CommonNapi::CreatePromise(env, promiseCtx->callbackRef, result);
2954 
2955     promiseCtx->napi->GetCurrentTrackTask(promiseCtx, env, args[0]);
2956 
2957     // async work
2958     napi_value resource = nullptr;
2959     napi_create_string_utf8(env, "JsGetCurrentTrack", NAPI_AUTO_LENGTH, &resource);
2960     NAPI_CALL(env, napi_create_async_work(env, nullptr, resource,
2961         [](napi_env env, void *data) {
2962             MEDIA_LOGI("GetCurrentTrack Task");
2963             auto promiseCtx = reinterpret_cast<AVPlayerContext *>(data);
2964             CHECK_AND_RETURN_LOG(promiseCtx != nullptr, "promiseCtx is nullptr!");
2965             CHECK_AND_RETURN_LOG(promiseCtx->asyncTask != nullptr, "asyncTask is nullptr!");
2966             auto result = promiseCtx->asyncTask->GetResult();
2967             if (result.HasResult() && result.Value().first != MSERR_EXT_API9_OK) {
2968                 promiseCtx->SignError(result.Value().first, result.Value().second);
2969             } else {
2970                 promiseCtx->JsResult = std::make_unique<MediaJsResultInt>(stoi(result.Value().second));
2971             }
2972             MEDIA_LOGI("GetCurrentTrack Task end");
2973         },
2974         MediaAsyncContext::CompleteCallback, static_cast<void *>(promiseCtx.get()), &promiseCtx->work));
2975     napi_queue_async_work_with_qos(env, promiseCtx->work, napi_qos_user_initiated);
2976     promiseCtx.release();
2977     return result;
2978 }
2979 
GetCurrentTrackTask(std::unique_ptr<AVPlayerContext> & promiseCtx,napi_env env,napi_value args)2980 void AVPlayerNapi::GetCurrentTrackTask(std::unique_ptr<AVPlayerContext> &promiseCtx, napi_env env, napi_value args)
2981 {
2982     if (!promiseCtx->napi->IsControllable()) {
2983         promiseCtx->napi->OnErrorCb(MSERR_EXT_API9_OPERATE_NOT_PERMIT,
2984             "current state is not prepared/playing/paused/completed, unsupport getCurrentTrack operation");
2985         return;
2986     }
2987 
2988     napi_valuetype valueType = napi_undefined;
2989     if (args == nullptr || napi_typeof(env, args, &valueType) != napi_ok || valueType != napi_number) {
2990         promiseCtx->SignError(MSERR_EXT_API9_INVALID_PARAMETER, "track index is not number");
2991         return;
2992     }
2993 
2994     int32_t trackType = MediaType::MEDIA_TYPE_AUD;
2995     napi_status status = napi_get_value_int32(env, args, &trackType);
2996     if (status != napi_ok || trackType < MediaType::MEDIA_TYPE_AUD || trackType > MediaType::MEDIA_TYPE_VID) {
2997         promiseCtx->SignError(MSERR_EXT_API9_INVALID_PARAMETER, "invalid track Type");
2998         return;
2999     }
3000 
3001     auto task = std::make_shared<TaskHandler<TaskRet>>([this, trackType]() {
3002         MEDIA_LOGI("GetCurrentTrack Task In");
3003         std::unique_lock<std::mutex> lock(taskMutex_);
3004         CHECK_AND_RETURN_RET(IsControllable(), TaskRet(MSERR_EXT_API9_OPERATE_NOT_PERMIT,
3005             "current state is not prepared/playing/paused/completed, unsupport getCurrentTrack operation"));
3006 
3007         int32_t index = 0;
3008         int32_t ret = player_->GetCurrentTrack(trackType, index);
3009         if (ret != MSERR_OK) {
3010             auto errCode = MSErrorToExtErrorAPI9(static_cast<MediaServiceErrCode>(ret));
3011             return TaskRet(errCode, "failed to GetCurrentTrack");
3012         }
3013         MEDIA_LOGI("GetCurrentTrack Task Out");
3014         return TaskRet(MSERR_EXT_API9_OK, std::to_string(index));
3015     });
3016     (void)taskQue_->EnqueueTask(task);
3017     promiseCtx->asyncTask = task;
3018     return;
3019 }
3020 
DeviceChangeCallbackOn(AVPlayerNapi * jsPlayer,std::string callbackName)3021 void AVPlayerNapi::DeviceChangeCallbackOn(AVPlayerNapi *jsPlayer, std::string callbackName)
3022 {
3023     if (jsPlayer == nullptr) {
3024         deviceChangeCallbackflag_ = false;
3025         return;
3026     }
3027     if (callbackName == "audioOutputDeviceChangeWithInfo") {
3028         deviceChangeCallbackflag_ = true;
3029     }
3030     if (jsPlayer->player_ != nullptr && deviceChangeCallbackflag_) {
3031         (void)jsPlayer->player_->SetDeviceChangeCbStatus(deviceChangeCallbackflag_);
3032     }
3033 }
3034 
DeviceChangeCallbackOff(AVPlayerNapi * jsPlayer,std::string callbackName)3035 void AVPlayerNapi::DeviceChangeCallbackOff(AVPlayerNapi *jsPlayer, std::string callbackName)
3036 {
3037     if (jsPlayer != nullptr && deviceChangeCallbackflag_ && callbackName == "audioOutputDeviceChangeWithInfo") {
3038         deviceChangeCallbackflag_ = false;
3039         if (jsPlayer->player_ != nullptr) {
3040             (void)jsPlayer->player_->SetDeviceChangeCbStatus(deviceChangeCallbackflag_);
3041         }
3042     }
3043 }
3044 
MaxAmplitudeCallbackOn(AVPlayerNapi * jsPlayer,std::string callbackName)3045 void AVPlayerNapi::MaxAmplitudeCallbackOn(AVPlayerNapi *jsPlayer, std::string callbackName)
3046 {
3047     if (jsPlayer == nullptr) {
3048         calMaxAmplitude_ = false;
3049         return;
3050     }
3051     if (callbackName == "amplitudeUpdate") {
3052         calMaxAmplitude_ = true;
3053     }
3054     if (jsPlayer->player_ != nullptr && calMaxAmplitude_) {
3055         (void)jsPlayer->player_->SetMaxAmplitudeCbStatus(calMaxAmplitude_);
3056     }
3057 }
3058 
SeiMessageCallbackOn(AVPlayerNapi * jsPlayer,std::string callbackName,const std::vector<int32_t> & payloadTypes)3059 void AVPlayerNapi::SeiMessageCallbackOn(AVPlayerNapi *jsPlayer, std::string callbackName,
3060     const std::vector<int32_t> &payloadTypes)
3061 {
3062     if (callbackName == "seiMessageReceived") {
3063         seiMessageCallbackflag_ = true;
3064     }
3065 
3066     if (jsPlayer->player_ != nullptr && seiMessageCallbackflag_) {
3067         MEDIA_LOGI("seiMessageCallbackflag_ = %{public}d", seiMessageCallbackflag_);
3068         (void)jsPlayer->player_->SetSeiMessageCbStatus(seiMessageCallbackflag_, payloadTypes);
3069     }
3070 }
3071 
JsSetOnCallback(napi_env env,napi_callback_info info)3072 napi_value AVPlayerNapi::JsSetOnCallback(napi_env env, napi_callback_info info)
3073 {
3074     MediaTrace trace("AVPlayerNapi::on");
3075     napi_value result = nullptr;
3076     napi_get_undefined(env, &result);
3077     MEDIA_LOGD("JsSetOnCallback In");
3078 
3079     napi_value args[ARRAY_ARG_COUNTS_THREE] = { nullptr }; // args[0]:type, args[1]: payloadTypes  args[2]:callback
3080     size_t argCount = ARRAY_ARG_COUNTS_THREE;
3081     AVPlayerNapi *jsPlayer = AVPlayerNapi::GetJsInstanceWithParameter(env, info, argCount, args);
3082     CHECK_AND_RETURN_RET_LOG(jsPlayer != nullptr, result, "failed to GetJsInstanceWithParameter");
3083     if (argCount < ARRAY_ARG_COUNTS_TWO || argCount > ARRAY_ARG_COUNTS_THREE) {
3084         jsPlayer->OnErrorCb(MSERR_EXT_API9_INVALID_PARAMETER, "Mandatory parameters are left unspecified.");
3085         return result;
3086     }
3087 
3088     if (jsPlayer->GetCurrentState() == AVPlayerState::STATE_RELEASED) {
3089         jsPlayer->OnErrorCb(MSERR_EXT_API9_OPERATE_NOT_PERMIT, "current state is released, unsupport to on event");
3090         return result;
3091     }
3092 
3093     CHECK_AND_RETURN_RET_NOLOG(
3094         VerifyExpectedType({ env, args[0], napi_string }, jsPlayer, "type should be string."), result);
3095     std::string callbackName = CommonNapi::GetStringArgument(env, args[0]);
3096 
3097     napi_ref ref = nullptr;
3098     if (argCount == ARGS_THREE) {
3099         CHECK_AND_RETURN_RET_NOLOG(
3100             VerifyExpectedType({ env, args[1], napi_object }, jsPlayer, "payloadTypes should be an Array."), result);
3101         CHECK_AND_RETURN_RET_NOLOG(
3102             VerifyExpectedType({ env, args[ARGS_TWO], napi_function }, jsPlayer, "param should be function."), result);
3103         std::vector<int32_t> payloadTypes = {};
3104         (void)CommonNapi::GetIntArrayArgument(env, args[1], payloadTypes);
3105         jsPlayer->SeiMessageCallbackOn(jsPlayer, callbackName, payloadTypes);
3106         napi_status status = napi_create_reference(env, args[ARGS_TWO], 1, &ref);
3107         CHECK_AND_RETURN_RET_LOG(status == napi_ok && ref != nullptr, result, "failed to create reference!");
3108     } else if (argCount == ARGS_TWO) {
3109         CHECK_AND_RETURN_RET_NOLOG(
3110             VerifyExpectedType({env, args[1], napi_function}, jsPlayer, "param should be function."), result);
3111         jsPlayer->MaxAmplitudeCallbackOn(jsPlayer, callbackName);
3112         napi_status status = napi_create_reference(env, args[1], 1, &ref);
3113         CHECK_AND_RETURN_RET_LOG(status == napi_ok && ref != nullptr, result, "failed to create reference!");
3114     }
3115     std::shared_ptr<AutoRef> autoRef = std::make_shared<AutoRef>(env, ref);
3116         jsPlayer->SaveCallbackReference(callbackName, autoRef);
3117     MEDIA_LOGI("0x%{public}06" PRIXPTR " JsSetOnCallback callbackName: %{public}s success",
3118         FAKE_POINTER(jsPlayer), callbackName.c_str());
3119     return result;
3120 }
3121 
VerifyExpectedType(const NapiTypeCheckUnit & unit,AVPlayerNapi * jsPlayer,const std::string & msg)3122 bool AVPlayerNapi::VerifyExpectedType(const NapiTypeCheckUnit &unit, AVPlayerNapi *jsPlayer, const std::string &msg)
3123 {
3124     napi_valuetype tmpType;
3125     CHECK_AND_RETURN_RET_NOLOG(
3126         napi_typeof(unit.env, unit.param, &tmpType) != napi_ok || tmpType != unit.expectedType, true);
3127     jsPlayer->OnErrorCb(MSERR_EXT_API9_INVALID_PARAMETER, msg);
3128     return false;
3129 }
3130 
MaxAmplitudeCallbackOff(AVPlayerNapi * jsPlayer,std::string callbackName)3131 void AVPlayerNapi::MaxAmplitudeCallbackOff(AVPlayerNapi *jsPlayer, std::string callbackName)
3132 {
3133     if (jsPlayer != nullptr && calMaxAmplitude_ && callbackName == "amplitudeUpdate") {
3134         calMaxAmplitude_ = false;
3135         if (jsPlayer->player_ != nullptr) {
3136             (void)jsPlayer->player_->SetMaxAmplitudeCbStatus(calMaxAmplitude_);
3137         }
3138     }
3139 }
3140 
SeiMessageCallbackOff(AVPlayerNapi * jsPlayer,std::string & callbackName,const std::vector<int32_t> & payloadTypes)3141 void AVPlayerNapi::SeiMessageCallbackOff(AVPlayerNapi *jsPlayer, std::string &callbackName,
3142     const std::vector<int32_t> &payloadTypes)
3143 {
3144     if (jsPlayer == nullptr || !seiMessageCallbackflag_ || callbackName != "seiMessageReceived") {
3145         return;
3146     }
3147     seiMessageCallbackflag_ = false;
3148     if (jsPlayer->player_ == nullptr) {
3149         return;
3150     }
3151     (void)jsPlayer->player_->SetSeiMessageCbStatus(seiMessageCallbackflag_, payloadTypes);
3152 }
3153 
JsClearOnCallback(napi_env env,napi_callback_info info)3154 napi_value AVPlayerNapi::JsClearOnCallback(napi_env env, napi_callback_info info)
3155 {
3156     MediaTrace trace("AVPlayerNapi::off");
3157     napi_value result = nullptr;
3158     napi_get_undefined(env, &result);
3159     MEDIA_LOGD("JsClearOnCallback In");
3160 
3161     napi_value args[ARRAY_ARG_COUNTS_THREE] = { nullptr }; // args[0]:type, args[1]: payloadTypes  args[2]:callback
3162     size_t argCount = 3;
3163     AVPlayerNapi *jsPlayer = AVPlayerNapi::GetJsInstanceWithParameter(env, info, argCount, args);
3164     CHECK_AND_RETURN_RET_LOG(jsPlayer != nullptr, result, "failed to GetJsInstanceWithParameter");
3165 
3166     if (jsPlayer->GetCurrentState() == AVPlayerState::STATE_RELEASED) {
3167         return result;
3168     }
3169 
3170     napi_valuetype valueType0 = napi_undefined;
3171     if (argCount < 1) {
3172         jsPlayer->OnErrorCb(MSERR_EXT_API9_INVALID_PARAMETER, "Mandatory parameters are left unspecified.");
3173         return result;
3174     }
3175 
3176     if (napi_typeof(env, args[0], &valueType0) != napi_ok || valueType0 != napi_string) {
3177         jsPlayer->OnErrorCb(MSERR_EXT_API9_INVALID_PARAMETER, "type should be string.");
3178         return result;
3179     }
3180 
3181     std::string callbackName = CommonNapi::GetStringArgument(env, args[0]);
3182     MEDIA_LOGI("0x%{public}06" PRIXPTR " set callbackName: %{public}s", FAKE_POINTER(jsPlayer), callbackName.c_str());
3183     if (callbackName != "seiMessageReceived") {
3184         jsPlayer->MaxAmplitudeCallbackOff(jsPlayer, callbackName);
3185         jsPlayer->ClearCallbackReference(callbackName);
3186         MEDIA_LOGI("0x%{public}06" PRIXPTR " JsClearOnCallback success", FAKE_POINTER(jsPlayer));
3187         return result;
3188     }
3189 
3190     napi_valuetype valueType1 = napi_undefined;
3191     if (napi_typeof(env, args[1], &valueType1) != napi_ok || valueType1 != napi_object) {
3192         jsPlayer->SeiMessageCallbackOff(jsPlayer, callbackName, {});
3193         jsPlayer->ClearCallbackReference(callbackName);
3194         MEDIA_LOGI("0x%{public}06" PRIXPTR " JsClearOnCallback success", FAKE_POINTER(jsPlayer));
3195         return result;
3196     }
3197     std::vector<int32_t> payloadTypes = {};
3198     if (CommonNapi::GetIntArrayArgument(env, args[1], payloadTypes)) {
3199         jsPlayer->SeiMessageCallbackOff(jsPlayer, callbackName, payloadTypes);
3200     } else {
3201         MEDIA_LOGD("The array is empty, no processing is performed.");
3202     }
3203 
3204     return result;
3205 }
3206 
SaveCallbackReference(const std::string & callbackName,std::shared_ptr<AutoRef> ref)3207 void AVPlayerNapi::SaveCallbackReference(const std::string &callbackName, std::shared_ptr<AutoRef> ref)
3208 {
3209     std::lock_guard<std::mutex> lock(mutex_);
3210     refMap_[callbackName] = ref;
3211     if (playerCb_ != nullptr) {
3212         playerCb_->SaveCallbackReference(callbackName, ref);
3213     }
3214 }
3215 
ClearCallbackReference()3216 void AVPlayerNapi::ClearCallbackReference()
3217 {
3218     std::lock_guard<std::mutex> lock(mutex_);
3219     if (playerCb_ != nullptr) {
3220         playerCb_->ClearCallbackReference();
3221     }
3222     refMap_.clear();
3223 }
3224 
ClearCallbackReference(const std::string & callbackName)3225 void AVPlayerNapi::ClearCallbackReference(const std::string &callbackName)
3226 {
3227     std::lock_guard<std::mutex> lock(mutex_);
3228     if (playerCb_ != nullptr) {
3229         playerCb_->ClearCallbackReference(callbackName);
3230     }
3231     refMap_.erase(callbackName);
3232 }
3233 
NotifyDuration(int32_t duration)3234 void AVPlayerNapi::NotifyDuration(int32_t duration)
3235 {
3236     duration_ = duration;
3237 }
3238 
NotifyPosition(int32_t position)3239 void AVPlayerNapi::NotifyPosition(int32_t position)
3240 {
3241     position_ = position;
3242 }
3243 
NotifyState(PlayerStates state)3244 void AVPlayerNapi::NotifyState(PlayerStates state)
3245 {
3246     std::lock_guard<std::mutex> lock(taskMutex_);
3247     if (state_ != state) {
3248         state_ = state;
3249         MEDIA_LOGI("0x%{public}06" PRIXPTR " notify %{public}s", FAKE_POINTER(this), GetCurrentState().c_str());
3250         stopWait_ = true;
3251         stateChangeCond_.notify_all();
3252     }
3253 }
3254 
NotifyVideoSize(int32_t width,int32_t height)3255 void AVPlayerNapi::NotifyVideoSize(int32_t width, int32_t height)
3256 {
3257     width_ = width;
3258     height_ = height;
3259 }
3260 
NotifyIsLiveStream()3261 void AVPlayerNapi::NotifyIsLiveStream()
3262 {
3263     isLiveStream_ = true;
3264 }
3265 
NotifyDrmInfoUpdated(const std::multimap<std::string,std::vector<uint8_t>> & infos)3266 void AVPlayerNapi::NotifyDrmInfoUpdated(const std::multimap<std::string, std::vector<uint8_t>> &infos)
3267 {
3268     MEDIA_LOGD("NotifyDrmInfoUpdated");
3269     std::unique_lock<std::shared_mutex> lock(drmMutex_);
3270     for (auto &newItem : infos) {
3271         auto pos = localDrmInfos_.equal_range(newItem.first);
3272         if (pos.first == pos.second && pos.first == localDrmInfos_.end()) {
3273             localDrmInfos_.insert(newItem);
3274             continue;
3275         }
3276         bool isSame = false;
3277         for (; pos.first != pos.second; ++pos.first) {
3278             if (newItem.second == pos.first->second) {
3279                 isSame = true;
3280                 break;
3281             }
3282         }
3283         if (!isSame) {
3284             localDrmInfos_.insert(newItem);
3285         }
3286     }
3287 }
3288 
ResetUserParameters()3289 void AVPlayerNapi::ResetUserParameters()
3290 {
3291     url_.clear();
3292     fileDescriptor_.fd = 0;
3293     fileDescriptor_.offset = 0;
3294     fileDescriptor_.length = -1;
3295     width_ = 0;
3296     height_ = 0;
3297     position_ = -1;
3298     duration_ = -1;
3299     loop_ = false;
3300 }
3301 
StartListenCurrentResource()3302 void AVPlayerNapi::StartListenCurrentResource()
3303 {
3304     std::lock_guard<std::mutex> lock(mutex_);
3305     if (playerCb_ != nullptr) {
3306         playerCb_->Start();
3307     }
3308 }
3309 
PauseListenCurrentResource()3310 void AVPlayerNapi::PauseListenCurrentResource()
3311 {
3312     std::lock_guard<std::mutex> lock(mutex_);
3313     if (playerCb_ != nullptr) {
3314         playerCb_->Pause();
3315     }
3316 }
3317 
3318 /**
3319  * DO NOT hold taskMutex_ before call this function
3320  * AVPlayerCallback::OnErrorCb() hold AVPlayerCallback::mutex_ and wait taskMutex_, may cause dead lock
3321 */
OnErrorCb(MediaServiceExtErrCodeAPI9 errorCode,const std::string & errorMsg)3322 void AVPlayerNapi::OnErrorCb(MediaServiceExtErrCodeAPI9 errorCode, const std::string &errorMsg)
3323 {
3324     std::lock_guard<std::mutex> lock(mutex_);
3325     if (playerCb_ != nullptr) {
3326         playerCb_->OnErrorCb(errorCode, errorMsg);
3327     }
3328 }
3329 
GetJsInstance(napi_env env,napi_callback_info info)3330 AVPlayerNapi* AVPlayerNapi::GetJsInstance(napi_env env, napi_callback_info info)
3331 {
3332     size_t argCount = 0;
3333     napi_value jsThis = nullptr;
3334     napi_status status = napi_get_cb_info(env, info, &argCount, nullptr, &jsThis, nullptr);
3335     CHECK_AND_RETURN_RET_LOG(status == napi_ok && jsThis != nullptr, nullptr, "failed to napi_get_cb_info");
3336 
3337     AVPlayerNapi *jsPlayer = nullptr;
3338     status = napi_unwrap(env, jsThis, reinterpret_cast<void **>(&jsPlayer));
3339     CHECK_AND_RETURN_RET_LOG(status == napi_ok && jsPlayer != nullptr, nullptr, "failed to napi_unwrap");
3340 
3341     return jsPlayer;
3342 }
3343 
GetJsInstanceWithParameter(napi_env env,napi_callback_info info,size_t & argc,napi_value * argv)3344 AVPlayerNapi* AVPlayerNapi::GetJsInstanceWithParameter(napi_env env, napi_callback_info info,
3345     size_t &argc, napi_value *argv)
3346 {
3347     napi_value jsThis = nullptr;
3348     napi_status status = napi_get_cb_info(env, info, &argc, argv, &jsThis, nullptr);
3349     CHECK_AND_RETURN_RET_LOG(status == napi_ok && jsThis != nullptr, nullptr, "failed to napi_get_cb_info");
3350 
3351     AVPlayerNapi *jsPlayer = nullptr;
3352     status = napi_unwrap(env, jsThis, reinterpret_cast<void **>(&jsPlayer));
3353     CHECK_AND_RETURN_RET_LOG(status == napi_ok && jsPlayer != nullptr, nullptr, "failed to napi_unwrap");
3354 
3355     return jsPlayer;
3356 }
3357 
IsLiveSource() const3358 bool AVPlayerNapi::IsLiveSource() const
3359 {
3360     return isLiveStream_;
3361 }
3362 
GetJsApiVersion()3363 int32_t AVPlayerNapi::GetJsApiVersion()
3364 {
3365     if (player_ != nullptr && getApiVersionFlag_) {
3366         getApiVersionFlag_ = false;
3367         player_->GetApiVersion(g_apiVersion);
3368         MEDIA_LOGI("apiVersion is: %{public}d", g_apiVersion);
3369     }
3370     return g_apiVersion;
3371 }
3372 
AddMediaStreamToAVMediaSource(const std::shared_ptr<AVMediaSourceTmp> & srcTmp,std::shared_ptr<AVMediaSource> & mediaSource)3373 void AVPlayerNapi::AddMediaStreamToAVMediaSource(
3374     const std::shared_ptr<AVMediaSourceTmp> &srcTmp, std::shared_ptr<AVMediaSource> &mediaSource)
3375 {
3376     for (const auto &mediaStreamTmp : srcTmp->getAVPlayMediaStreamTmpList()) {
3377         AVPlayMediaStream mediaStream;
3378         mediaStream.url = mediaStreamTmp.url;
3379         mediaStream.width = mediaStreamTmp.width;
3380         mediaStream.height = mediaStreamTmp.height;
3381         mediaStream.bitrate = mediaStreamTmp.bitrate;
3382         mediaSource->AddMediaStream(mediaStream);
3383     }
3384 }
3385 
JsIsSeekContinuousSupported(napi_env env,napi_callback_info info)3386 napi_value AVPlayerNapi::JsIsSeekContinuousSupported(napi_env env, napi_callback_info info)
3387 {
3388     MediaTrace trace("AVPlayerNapi::isSeekContinuousSupported");
3389     MEDIA_LOGI("JsIsSeekContinuousSupported In");
3390     napi_value result = nullptr;
3391     bool isSeekContinuousSupported = false;
3392     napi_status status = napi_get_boolean(env, isSeekContinuousSupported, &result);
3393     CHECK_AND_RETURN_RET_LOG(status == napi_ok, result, "napi_get_boolean failed");
3394     size_t argCount = 0;
3395     AVPlayerNapi *jsPlayer = AVPlayerNapi::GetJsInstanceWithParameter(env, info, argCount, nullptr);
3396     CHECK_AND_RETURN_RET_LOG(jsPlayer != nullptr, result, "failed to GetJsInstance");
3397     if (jsPlayer->player_ != nullptr) {
3398         isSeekContinuousSupported = jsPlayer->player_->IsSeekContinuousSupported();
3399         status = napi_get_boolean(env, isSeekContinuousSupported, &result);
3400         CHECK_AND_RETURN_RET_LOG(status == napi_ok, result, "napi_get_boolean failed");
3401     }
3402     return result;
3403 }
3404 } // namespace Media
3405 } // namespace OHOS