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