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