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