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