1 /*
2 * Copyright (C) 2021 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 "video_player_napi.h"
17 #include <climits>
18 #include "video_callback_napi.h"
19 #include "media_log.h"
20 #include "media_errors.h"
21 #include "surface_utils.h"
22 #include "string_ex.h"
23 #include "meta/video_types.h"
24 #ifdef SUPPORT_JSSTACK
25 #include "xpower_event_js.h"
26 #endif
27
28 namespace {
29 constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, LOG_DOMAIN_PLAYER, "VideoPlayerNapi"};
30 }
31
32 namespace OHOS {
33 namespace Media {
34 namespace VideoPlayState {
35 const std::string STATE_IDLE = "idle";
36 const std::string STATE_PREPARED = "prepared";
37 const std::string STATE_PLAYING = "playing";
38 const std::string STATE_PAUSED = "paused";
39 const std::string STATE_STOPPED = "stopped";
40 const std::string STATE_ERROR = "error";
41 };
42 thread_local napi_ref VideoPlayerNapi::constructor_ = nullptr;
43 const std::string CLASS_NAME = "VideoPlayer";
44
GetJSState(PlayerStates currentState)45 static std::string GetJSState(PlayerStates currentState)
46 {
47 std::string result;
48 MEDIA_LOGD("GetJSState()! is called!, %{public}d", currentState);
49 switch (currentState) {
50 case PLAYER_IDLE:
51 case PLAYER_INITIALIZED:
52 result = VideoPlayState::STATE_IDLE;
53 break;
54 case PLAYER_PREPARED:
55 result = VideoPlayState::STATE_PREPARED;
56 break;
57 case PLAYER_STARTED:
58 result = VideoPlayState::STATE_PLAYING;
59 break;
60 case PLAYER_PAUSED:
61 result = VideoPlayState::STATE_PAUSED;
62 break;
63 case PLAYER_STOPPED:
64 case PLAYER_PLAYBACK_COMPLETE:
65 result = VideoPlayState::STATE_STOPPED;
66 break;
67 default:
68 // Considering default state as stopped
69 MEDIA_LOGE("Error state! %{public}d", currentState);
70 result = VideoPlayState::STATE_ERROR;
71 break;
72 }
73 return result;
74 }
75
VideoPlayerNapi()76 VideoPlayerNapi::VideoPlayerNapi()
77 {
78 MEDIA_LOGD("0x%{public}06" PRIXPTR " Instances create", FAKE_POINTER(this));
79 }
80
~VideoPlayerNapi()81 VideoPlayerNapi::~VideoPlayerNapi()
82 {
83 CancelCallback();
84 nativePlayer_ = nullptr;
85 jsCallback_ = nullptr;
86
87 MEDIA_LOGD("0x%{public}06" PRIXPTR " Instances destroy", FAKE_POINTER(this));
88 }
89
Init(napi_env env,napi_value exports)90 napi_value VideoPlayerNapi::Init(napi_env env, napi_value exports)
91 {
92 napi_property_descriptor staticProperty[] = {
93 DECLARE_NAPI_STATIC_FUNCTION("createVideoPlayer", CreateVideoPlayer),
94 };
95
96 napi_property_descriptor properties[] = {
97 DECLARE_NAPI_FUNCTION("setDisplaySurface", SetDisplaySurface),
98 DECLARE_NAPI_FUNCTION("prepare", Prepare),
99 DECLARE_NAPI_FUNCTION("play", Play),
100 DECLARE_NAPI_FUNCTION("pause", Pause),
101 DECLARE_NAPI_FUNCTION("stop", Stop),
102 DECLARE_NAPI_FUNCTION("reset", Reset),
103 DECLARE_NAPI_FUNCTION("release", Release),
104 DECLARE_NAPI_FUNCTION("seek", Seek),
105 DECLARE_NAPI_FUNCTION("on", On),
106 DECLARE_NAPI_FUNCTION("setVolume", SetVolume),
107 DECLARE_NAPI_FUNCTION("getTrackDescription", GetTrackDescription),
108 DECLARE_NAPI_FUNCTION("setSpeed", SetSpeed),
109 DECLARE_NAPI_FUNCTION("selectBitrate", SelectBitrate),
110
111 DECLARE_NAPI_GETTER_SETTER("url", GetUrl, SetUrl),
112 DECLARE_NAPI_GETTER_SETTER("fdSrc", GetFdSrc, SetFdSrc),
113 DECLARE_NAPI_GETTER_SETTER("loop", GetLoop, SetLoop),
114 DECLARE_NAPI_GETTER_SETTER("videoScaleType", GetVideoScaleType, SetVideoScaleType),
115 DECLARE_NAPI_GETTER_SETTER("audioInterruptMode", GetAudioInterruptMode, SetAudioInterruptMode),
116
117 DECLARE_NAPI_GETTER("currentTime", GetCurrentTime),
118 DECLARE_NAPI_GETTER("duration", GetDuration),
119 DECLARE_NAPI_GETTER("state", GetState),
120 DECLARE_NAPI_GETTER("width", GetWidth),
121 DECLARE_NAPI_GETTER("height", GetHeight),
122 };
123
124 napi_value constructor = nullptr;
125 napi_status status = napi_define_class(env, CLASS_NAME.c_str(), NAPI_AUTO_LENGTH, Constructor, nullptr,
126 sizeof(properties) / sizeof(properties[0]), properties, &constructor);
127 CHECK_AND_RETURN_RET_LOG(status == napi_ok, nullptr, "Failed to define AudioPlayer class");
128
129 status = napi_create_reference(env, constructor, 1, &constructor_);
130 CHECK_AND_RETURN_RET_LOG(status == napi_ok, nullptr, "Failed to create reference of constructor");
131
132 status = napi_set_named_property(env, exports, CLASS_NAME.c_str(), constructor);
133 CHECK_AND_RETURN_RET_LOG(status == napi_ok, nullptr, "Failed to set constructor");
134
135 status = napi_define_properties(env, exports, sizeof(staticProperty) / sizeof(staticProperty[0]), staticProperty);
136 CHECK_AND_RETURN_RET_LOG(status == napi_ok, nullptr, "Failed to define static function");
137
138 MEDIA_LOGD("Init success");
139 return exports;
140 }
141
Constructor(napi_env env,napi_callback_info info)142 napi_value VideoPlayerNapi::Constructor(napi_env env, napi_callback_info info)
143 {
144 napi_value result = nullptr;
145 napi_value jsThis = nullptr;
146 size_t argCount = 0;
147 napi_status status = napi_get_cb_info(env, info, &argCount, nullptr, &jsThis, nullptr);
148 if (status != napi_ok) {
149 napi_get_undefined(env, &result);
150 MEDIA_LOGE("Failed to retrieve details about the callback");
151 return result;
152 }
153
154 VideoPlayerNapi *jsPlayer = new(std::nothrow) VideoPlayerNapi();
155 CHECK_AND_RETURN_RET_LOG(jsPlayer != nullptr, nullptr, "failed to new VideoPlayerNapi");
156
157 jsPlayer->env_ = env;
158 jsPlayer->nativePlayer_ = PlayerFactory::CreatePlayer();
159 if (jsPlayer->nativePlayer_ == nullptr) {
160 MEDIA_LOGE("failed to CreatePlayer");
161 }
162
163 if (jsPlayer->jsCallback_ == nullptr && jsPlayer->nativePlayer_ != nullptr) {
164 jsPlayer->jsCallback_ = std::make_shared<VideoCallbackNapi>(env);
165 (void)jsPlayer->nativePlayer_->SetPlayerCallback(jsPlayer->jsCallback_);
166 }
167
168 status = napi_wrap(env, jsThis, reinterpret_cast<void *>(jsPlayer),
169 VideoPlayerNapi::Destructor, nullptr, nullptr);
170 if (status != napi_ok) {
171 napi_get_undefined(env, &result);
172 delete jsPlayer;
173 MEDIA_LOGE("Failed to wrap native instance");
174 return result;
175 }
176
177 MEDIA_LOGD("Constructor success");
178 return jsThis;
179 }
180
Destructor(napi_env env,void * nativeObject,void * finalize)181 void VideoPlayerNapi::Destructor(napi_env env, void *nativeObject, void *finalize)
182 {
183 (void)env;
184 (void)finalize;
185 if (nativeObject != nullptr) {
186 delete reinterpret_cast<VideoPlayerNapi *>(nativeObject);
187 }
188 MEDIA_LOGD("Destructor success");
189 }
190
CreateVideoPlayer(napi_env env,napi_callback_info info)191 napi_value VideoPlayerNapi::CreateVideoPlayer(napi_env env, napi_callback_info info)
192 {
193 napi_value result = nullptr;
194 napi_get_undefined(env, &result);
195 MEDIA_LOGD("CreateVideoPlayer In");
196
197 std::unique_ptr<VideoPlayerAsyncContext> asyncContext = std::make_unique<VideoPlayerAsyncContext>(env);
198
199 // get args
200 napi_value jsThis = nullptr;
201 napi_value args[1] = { nullptr };
202 size_t argCount = 1;
203 napi_status status = napi_get_cb_info(env, info, &argCount, args, &jsThis, nullptr);
204 if (status != napi_ok) {
205 asyncContext->SignError(MSERR_EXT_INVALID_VAL, "failed to napi_get_cb_info");
206 }
207
208 asyncContext->callbackRef = CommonNapi::CreateReference(env, args[0]);
209 asyncContext->deferred = CommonNapi::CreatePromise(env, asyncContext->callbackRef, result);
210 asyncContext->JsResult = std::make_unique<MediaJsResultInstance>(constructor_);
211 napi_value resource = nullptr;
212 napi_create_string_utf8(env, "CreateVideoPlayer", NAPI_AUTO_LENGTH, &resource);
213 NAPI_CALL(env, napi_create_async_work(env, nullptr, resource, [](napi_env env, void* data) {},
214 MediaAsyncContext::CompleteCallback, static_cast<void *>(asyncContext.get()), &asyncContext->work));
215 NAPI_CALL(env, napi_queue_async_work(env, asyncContext->work));
216 asyncContext.release();
217
218 return result;
219 }
220
SetUrl(napi_env env,napi_callback_info info)221 napi_value VideoPlayerNapi::SetUrl(napi_env env, napi_callback_info info)
222 {
223 napi_value undefinedResult = nullptr;
224 napi_get_undefined(env, &undefinedResult);
225 MEDIA_LOGD("SetUrl In");
226 // get args and jsThis
227 napi_value jsThis = nullptr;
228 napi_value args[1] = { nullptr };
229 size_t argCount = 1;
230 napi_status status = napi_get_cb_info(env, info, &argCount, args, &jsThis, nullptr);
231 if (status != napi_ok || jsThis == nullptr) {
232 MEDIA_LOGE("Failed to retrieve details about the callback");
233 return undefinedResult;
234 }
235
236 // get VideoPlayerNapi
237 VideoPlayerNapi *jsPlayer = nullptr;
238 status = napi_unwrap(env, jsThis, reinterpret_cast<void **>(&jsPlayer));
239 CHECK_AND_RETURN_RET_LOG(status == napi_ok && jsPlayer != nullptr, undefinedResult, "Failed to retrieve instance");
240 if (jsPlayer->nativePlayer_ == nullptr) {
241 jsPlayer->ErrorCallback(MSERR_EXT_NO_MEMORY, "player is released(null), please create player again");
242 return undefinedResult;
243 }
244 napi_valuetype valueType = napi_undefined;
245 if (argCount < 1 || napi_typeof(env, args[0], &valueType) != napi_ok || valueType != napi_string) {
246 jsPlayer->ErrorCallback(MSERR_EXT_INVALID_VAL, "napi_typeof failed, please check the input parameters");
247 return undefinedResult;
248 }
249 // get url from js
250 jsPlayer->url_ = CommonNapi::GetStringArgument(env, args[0]);
251
252 const std::string fdHead = "fd://";
253 const std::string httpHead = "http";
254 int32_t ret = MSERR_EXT_INVALID_VAL;
255 MEDIA_LOGD("input url is %{private}s!", jsPlayer->url_.c_str());
256 if (jsPlayer->url_.find(fdHead) != std::string::npos) {
257 std::string inputFd = jsPlayer->url_.substr(fdHead.size());
258 int32_t fd = -1;
259 if (!StrToInt(inputFd, fd) || fd < 0) {
260 jsPlayer->ErrorCallback(MSERR_EXT_INVALID_VAL, "invalid parameters, please check the input parameters");
261 return undefinedResult;
262 }
263
264 ret = jsPlayer->nativePlayer_->SetSource(fd, 0, -1);
265 } else if (jsPlayer->url_.find(httpHead) != std::string::npos) {
266 ret = jsPlayer->nativePlayer_->SetSource(jsPlayer->url_);
267 }
268
269 if (ret != MSERR_OK) {
270 MEDIA_LOGE("input url error!");
271 jsPlayer->ErrorCallback(MSErrorToExtError(static_cast<MediaServiceErrCode>(ret)), "failed to set source");
272 return undefinedResult;
273 }
274
275 MEDIA_LOGD("SetUrl success");
276 return undefinedResult;
277 }
278
GetUrl(napi_env env,napi_callback_info info)279 napi_value VideoPlayerNapi::GetUrl(napi_env env, napi_callback_info info)
280 {
281 napi_value undefinedResult = nullptr;
282 napi_get_undefined(env, &undefinedResult);
283
284 // get jsThis
285 napi_value jsThis = nullptr;
286 size_t argCount = 0;
287 napi_status status = napi_get_cb_info(env, info, &argCount, nullptr, &jsThis, nullptr);
288 if (status != napi_ok || jsThis == nullptr) {
289 MEDIA_LOGE("failed to napi_get_cb_info");
290 return undefinedResult;
291 }
292
293 // get VideoPlayerNapi
294 VideoPlayerNapi *jsPlayer = nullptr;
295 status = napi_unwrap(env, jsThis, reinterpret_cast<void **>(&jsPlayer));
296 CHECK_AND_RETURN_RET_LOG(status == napi_ok && jsPlayer != nullptr, undefinedResult, "Failed to retrieve instance");
297
298 napi_value jsResult = nullptr;
299 status = napi_create_string_utf8(env, jsPlayer->url_.c_str(), NAPI_AUTO_LENGTH, &jsResult);
300 CHECK_AND_RETURN_RET_LOG(status == napi_ok, undefinedResult, "napi_create_string_utf8 error");
301
302 MEDIA_LOGD("GetSrc success");
303 return jsResult;
304 }
305
SetFdSrc(napi_env env,napi_callback_info info)306 napi_value VideoPlayerNapi::SetFdSrc(napi_env env, napi_callback_info info)
307 {
308 napi_value undefinedResult = nullptr;
309 napi_get_undefined(env, &undefinedResult);
310
311 // get args and jsThis
312 napi_value jsThis = nullptr;
313 napi_value args[1] = { nullptr };
314 size_t argCount = 1;
315 napi_status status = napi_get_cb_info(env, info, &argCount, args, &jsThis, nullptr);
316 if (status != napi_ok || jsThis == nullptr) {
317 MEDIA_LOGE("Failed to retrieve details about the callback");
318 return undefinedResult;
319 }
320
321 // get VideoPlayerNapi
322 VideoPlayerNapi *jsPlayer = nullptr;
323 status = napi_unwrap(env, jsThis, reinterpret_cast<void **>(&jsPlayer));
324 CHECK_AND_RETURN_RET_LOG(status == napi_ok && jsPlayer != nullptr, undefinedResult, "Failed to retrieve instance");
325 if (jsPlayer->nativePlayer_ == nullptr) {
326 jsPlayer->ErrorCallback(MSERR_EXT_NO_MEMORY, "player is released(null), please create player again");
327 return undefinedResult;
328 }
329 // get url from js
330 napi_valuetype valueType = napi_undefined;
331 if (argCount < 1 || napi_typeof(env, args[0], &valueType) != napi_ok || valueType != napi_object) {
332 jsPlayer->ErrorCallback(MSERR_EXT_INVALID_VAL, "napi_typeof failed, please check the input parameters");
333 return undefinedResult;
334 }
335
336 if (!CommonNapi::GetFdArgument(env, args[0], jsPlayer->rawFd_)) {
337 MEDIA_LOGE("get rawfd argument failed!");
338 jsPlayer->ErrorCallback(MSERR_EXT_INVALID_VAL, "invalid parameters, please check the input parameters");
339 return undefinedResult;
340 }
341
342 // set url to server
343 int32_t ret = jsPlayer->nativePlayer_->SetSource(jsPlayer->rawFd_.fd, jsPlayer->rawFd_.offset,
344 jsPlayer->rawFd_.length);
345 if (ret != MSERR_OK) {
346 jsPlayer->ErrorCallback(MSErrorToExtError(static_cast<MediaServiceErrCode>(ret)), "failed to SetSource");
347 return undefinedResult;
348 }
349
350 MEDIA_LOGD("SetFdSrc success");
351 return undefinedResult;
352 }
353
GetFdSrc(napi_env env,napi_callback_info info)354 napi_value VideoPlayerNapi::GetFdSrc(napi_env env, napi_callback_info info)
355 {
356 napi_value undefinedResult = nullptr;
357 napi_get_undefined(env, &undefinedResult);
358
359 // get jsThis
360 napi_value jsThis = nullptr;
361 size_t argCount = 0;
362 napi_status status = napi_get_cb_info(env, info, &argCount, nullptr, &jsThis, nullptr);
363 if (status != napi_ok || jsThis == nullptr) {
364 MEDIA_LOGE("failed to napi_get_cb_info");
365 return undefinedResult;
366 }
367
368 // get VideoPlayerNapi
369 VideoPlayerNapi *jsPlayer = nullptr;
370 status = napi_unwrap(env, jsThis, reinterpret_cast<void **>(&jsPlayer));
371 CHECK_AND_RETURN_RET_LOG(status == napi_ok && jsPlayer != nullptr, undefinedResult, "Failed to retrieve instance");
372
373 napi_value jsResult = nullptr;
374 status = napi_create_object(env, &jsResult);
375 CHECK_AND_RETURN_RET_LOG(status == napi_ok, undefinedResult, "create jsResult object error");
376
377 CHECK_AND_RETURN_RET(CommonNapi::AddNumberPropInt32(env, jsResult, "fd", jsPlayer->rawFd_.fd) == true, nullptr);
378 CHECK_AND_RETURN_RET(CommonNapi::AddNumberPropInt64(env, jsResult, "offset", jsPlayer->rawFd_.offset) == true,
379 nullptr);
380 CHECK_AND_RETURN_RET(CommonNapi::AddNumberPropInt64(env, jsResult, "length", jsPlayer->rawFd_.length) == true,
381 nullptr);
382
383 MEDIA_LOGD("GetFdSrc success");
384 return jsResult;
385 }
386
AsyncSetDisplaySurface(napi_env env,void * data)387 void VideoPlayerNapi::AsyncSetDisplaySurface(napi_env env, void *data)
388 {
389 MEDIA_LOGD("AsyncSetDisplaySurface In");
390 auto asyncContext = reinterpret_cast<VideoPlayerAsyncContext *>(data);
391 CHECK_AND_RETURN_LOG(asyncContext != nullptr, "VideoPlayerAsyncContext is nullptr!");
392
393 if (asyncContext->jsPlayer == nullptr) {
394 asyncContext->SignError(MSERR_EXT_NO_MEMORY, "jsPlayer is destroyed(null), please check js_runtime");
395 return;
396 }
397
398 if (asyncContext->jsPlayer->nativePlayer_ == nullptr) {
399 asyncContext->SignError(MSERR_EXT_NO_MEMORY, "nativePlayer is released(null), please create player again");
400 return;
401 }
402
403 uint64_t surfaceId = 0;
404 MEDIA_LOGD("get surface, surfaceStr = %{public}s", asyncContext->surface.c_str());
405 if (asyncContext->surface.empty() || asyncContext->surface[0] < '0' || asyncContext->surface[0] > '9') {
406 asyncContext->SignError(MSERR_EXT_INVALID_VAL, "input surface id is invalid");
407 return;
408 }
409 surfaceId = std::stoull(asyncContext->surface);
410 MEDIA_LOGD("get surface, surfaceId = (%{public}" PRIu64 ")", surfaceId);
411
412 auto surface = SurfaceUtils::GetInstance()->GetSurface(surfaceId);
413 if (surface != nullptr) {
414 int32_t ret = asyncContext->jsPlayer->nativePlayer_->SetVideoSurface(surface);
415 if (ret != MSERR_OK) {
416 asyncContext->SignError(MSERR_EXT_OPERATE_NOT_PERMIT, "failed to SetVideoSurface");
417 }
418 } else {
419 asyncContext->SignError(MSERR_EXT_NO_MEMORY, "failed to get surface from SurfaceUtils");
420 }
421 MEDIA_LOGD("AsyncSetDisplaySurface Out");
422 }
423
SetDisplaySurface(napi_env env,napi_callback_info info)424 napi_value VideoPlayerNapi::SetDisplaySurface(napi_env env, napi_callback_info info)
425 {
426 napi_value result = nullptr;
427 napi_get_undefined(env, &result);
428
429 MEDIA_LOGD("SetDisplaySurface In");
430 std::unique_ptr<VideoPlayerAsyncContext> asyncContext = std::make_unique<VideoPlayerAsyncContext>(env);
431
432 // get args
433 napi_value jsThis = nullptr;
434 napi_value args[2] = { nullptr };
435 size_t argCount = 2;
436 napi_status status = napi_get_cb_info(env, info, &argCount, args, &jsThis, nullptr);
437 if (status != napi_ok || jsThis == nullptr) {
438 asyncContext->SignError(MSERR_EXT_NO_MEMORY, "failed to napi_get_cb_info");
439 }
440
441 // get surface id from js
442 napi_valuetype valueType = napi_undefined;
443 if (argCount > 0 && napi_typeof(env, args[0], &valueType) == napi_ok && valueType == napi_string) {
444 asyncContext->surface = CommonNapi::GetStringArgument(env, args[0]);
445 }
446 asyncContext->callbackRef = CommonNapi::CreateReference(env, args[1]);
447 asyncContext->deferred = CommonNapi::CreatePromise(env, asyncContext->callbackRef, result);
448 // get jsPlayer
449 (void)napi_unwrap(env, jsThis, reinterpret_cast<void **>(&asyncContext->jsPlayer));
450
451 napi_value resource = nullptr;
452 napi_create_string_utf8(env, "SetDisplaySurface", NAPI_AUTO_LENGTH, &resource);
453 NAPI_CALL(env, napi_create_async_work(env, nullptr, resource, VideoPlayerNapi::AsyncSetDisplaySurface,
454 MediaAsyncContext::CompleteCallback, static_cast<void *>(asyncContext.get()), &asyncContext->work));
455 NAPI_CALL(env, napi_queue_async_work(env, asyncContext->work));
456 asyncContext.release();
457
458 return result;
459 }
460
ProcessWork(napi_env env,napi_status status,void * data)461 int32_t VideoPlayerNapi::ProcessWork(napi_env env, napi_status status, void *data)
462 {
463 auto asyncContext = reinterpret_cast<VideoPlayerAsyncContext *>(data);
464
465 int32_t ret = MSERR_OK;
466 auto player = asyncContext->jsPlayer->nativePlayer_;
467 if (asyncContext->asyncWorkType == AsyncWorkType::ASYNC_WORK_PREPARE) {
468 ret = player->PrepareAsync();
469 } else if (asyncContext->asyncWorkType == AsyncWorkType::ASYNC_WORK_PLAY) {
470 ret = player->Play();
471 } else if (asyncContext->asyncWorkType == AsyncWorkType::ASYNC_WORK_PAUSE) {
472 ret = player->Pause();
473 auto cb = std::static_pointer_cast<VideoCallbackNapi>(asyncContext->jsPlayer->jsCallback_);
474 if (cb->GetCurrentState() == PLAYER_PAUSED) {
475 return MSERR_INVALID_OPERATION;
476 }
477 } else if (asyncContext->asyncWorkType == AsyncWorkType::ASYNC_WORK_STOP) {
478 ret = player->Stop();
479 } else if (asyncContext->asyncWorkType == AsyncWorkType::ASYNC_WORK_VOLUME) {
480 float volume = static_cast<float>(asyncContext->volume);
481 ret = player->SetVolume(volume, volume);
482 } else if (asyncContext->asyncWorkType == AsyncWorkType::ASYNC_WORK_SEEK) {
483 PlayerSeekMode seekMode = static_cast<PlayerSeekMode>(asyncContext->seekMode);
484 MEDIA_LOGD("seek position %{public}d, seekmode %{public}d", asyncContext->seekPosition, seekMode);
485 ret = player->Seek(asyncContext->seekPosition, seekMode);
486 } else if (asyncContext->asyncWorkType == AsyncWorkType::ASYNC_WORK_SPEED) {
487 PlaybackRateMode speedMode = static_cast<PlaybackRateMode>(asyncContext->speedMode);
488 ret = player->SetPlaybackSpeed(speedMode);
489 } else if (asyncContext->asyncWorkType == AsyncWorkType::ASYNC_WORK_BITRATE) {
490 uint32_t bitRate = static_cast<uint32_t>(asyncContext->bitRate);
491 ret = player->SelectBitRate(bitRate);
492 } else {
493 MEDIA_LOGW("invalid operate playback!");
494 }
495
496 return ret;
497 }
498
CompleteAsyncWork(napi_env env,napi_status status,void * data)499 void VideoPlayerNapi::CompleteAsyncWork(napi_env env, napi_status status, void *data)
500 {
501 MEDIA_LOGD("CompleteAsyncFunc In");
502 auto asyncContext = reinterpret_cast<VideoPlayerAsyncContext *>(data);
503 CHECK_AND_RETURN_LOG(asyncContext != nullptr, "VideoPlayerAsyncContext is nullptr!");
504
505 if (status != napi_ok) {
506 return MediaAsyncContext::CompleteCallback(env, status, data);
507 }
508
509 if (asyncContext->jsPlayer == nullptr) {
510 asyncContext->SignError(MSERR_EXT_NO_MEMORY, "jsPlayer is destroyed(null), please check js_runtime");
511 return MediaAsyncContext::CompleteCallback(env, status, data);
512 }
513 if (asyncContext->jsPlayer->nativePlayer_ == nullptr || asyncContext->jsPlayer->jsCallback_ == nullptr) {
514 asyncContext->SignError(MSERR_EXT_NO_MEMORY, "nativePlayer is released(null), please create player again");
515 return MediaAsyncContext::CompleteCallback(env, status, data);
516 }
517 if (asyncContext->asyncWorkType < AsyncWorkType::ASYNC_WORK_PREPARE ||
518 asyncContext->asyncWorkType >= AsyncWorkType::ASYNC_WORK_INVALID) {
519 asyncContext->SignError(MSERR_EXT_NO_MEMORY, "invalid asyncWorkType, please check player code");
520 return MediaAsyncContext::CompleteCallback(env, status, data);
521 }
522
523 asyncContext->env_ = env;
524 auto cb = std::static_pointer_cast<VideoCallbackNapi>(asyncContext->jsPlayer->jsCallback_);
525
526 int32_t ret = MSERR_OK;
527 if (asyncContext->asyncWorkType == AsyncWorkType::ASYNC_WORK_RESET) {
528 cb->ClearAsyncWork(false, "the requests was aborted because user called reset");
529 cb->QueueAsyncWork(asyncContext);
530 ret = asyncContext->jsPlayer->nativePlayer_->Reset();
531 } else {
532 cb->QueueAsyncWork(asyncContext);
533 ret = ProcessWork(env, status, data);
534 }
535
536 if (ret != MSERR_OK) {
537 cb->ClearAsyncWork(true, "the request was aborted because videoplayer ProcessWork error");
538 }
539 }
540
Prepare(napi_env env,napi_callback_info info)541 napi_value VideoPlayerNapi::Prepare(napi_env env, napi_callback_info info)
542 {
543 napi_value result = nullptr;
544 napi_get_undefined(env, &result);
545 MEDIA_LOGD("Prepare In");
546
547 std::unique_ptr<VideoPlayerAsyncContext> asyncContext = std::make_unique<VideoPlayerAsyncContext>(env);
548 asyncContext->asyncWorkType = AsyncWorkType::ASYNC_WORK_PREPARE;
549
550 // get args
551 napi_value jsThis = nullptr;
552 napi_value args[1] = { nullptr };
553 size_t argCount = 1;
554 napi_status status = napi_get_cb_info(env, info, &argCount, args, &jsThis, nullptr);
555 if (status != napi_ok || jsThis == nullptr) {
556 asyncContext->SignError(MSERR_EXT_INVALID_VAL, "failed to napi_get_cb_info");
557 }
558
559 asyncContext->callbackRef = CommonNapi::CreateReference(env, args[0]);
560 asyncContext->deferred = CommonNapi::CreatePromise(env, asyncContext->callbackRef, result);
561
562 // get jsPlayer
563 (void)napi_unwrap(env, jsThis, reinterpret_cast<void **>(&asyncContext->jsPlayer));
564 // async work
565 napi_value resource = nullptr;
566 napi_create_string_utf8(env, "Prepare", NAPI_AUTO_LENGTH, &resource);
567 NAPI_CALL(env, napi_create_async_work(env, nullptr, resource, [](napi_env env, void* data) {},
568 CompleteAsyncWork, static_cast<void *>(asyncContext.get()), &asyncContext->work));
569 NAPI_CALL(env, napi_queue_async_work(env, asyncContext->work));
570 asyncContext.release();
571 return result;
572 }
573
Play(napi_env env,napi_callback_info info)574 napi_value VideoPlayerNapi::Play(napi_env env, napi_callback_info info)
575 {
576 napi_value result = nullptr;
577 napi_get_undefined(env, &result);
578 MEDIA_LOGD("Play In");
579
580 std::unique_ptr<VideoPlayerAsyncContext> asyncContext = std::make_unique<VideoPlayerAsyncContext>(env);
581 asyncContext->asyncWorkType = AsyncWorkType::ASYNC_WORK_PLAY;
582 // get args
583 napi_value jsThis = nullptr;
584 napi_value args[1] = { nullptr };
585 size_t argCount = 1;
586 napi_status status = napi_get_cb_info(env, info, &argCount, args, &jsThis, nullptr);
587 if (status != napi_ok || jsThis == nullptr) {
588 asyncContext->SignError(MSERR_EXT_INVALID_VAL, "failed to napi_get_cb_info");
589 }
590
591 asyncContext->callbackRef = CommonNapi::CreateReference(env, args[0]);
592 asyncContext->deferred = CommonNapi::CreatePromise(env, asyncContext->callbackRef, result);
593 // get jsPlayer
594 (void)napi_unwrap(env, jsThis, reinterpret_cast<void **>(&asyncContext->jsPlayer));
595 #ifdef SUPPORT_JSSTACK
596 HiviewDFX::ReportXPowerJsStackSysEvent(env, "STREAM_CHANGE", "SRC=Media");
597 #endif
598 // async work
599 napi_value resource = nullptr;
600 napi_create_string_utf8(env, "Play", NAPI_AUTO_LENGTH, &resource);
601 NAPI_CALL(env, napi_create_async_work(env, nullptr, resource, [](napi_env env, void* data) {},
602 CompleteAsyncWork, static_cast<void *>(asyncContext.get()), &asyncContext->work));
603 NAPI_CALL(env, napi_queue_async_work(env, asyncContext->work));
604 asyncContext.release();
605 return result;
606 }
607
Pause(napi_env env,napi_callback_info info)608 napi_value VideoPlayerNapi::Pause(napi_env env, napi_callback_info info)
609 {
610 napi_value result = nullptr;
611 napi_get_undefined(env, &result);
612
613 MEDIA_LOGD("Pause In");
614 std::unique_ptr<VideoPlayerAsyncContext> asyncContext = std::make_unique<VideoPlayerAsyncContext>(env);
615 asyncContext->asyncWorkType = AsyncWorkType::ASYNC_WORK_PAUSE;
616
617 // get args
618 napi_value jsThis = nullptr;
619 napi_value args[1] = { nullptr };
620 size_t argCount = 1;
621 napi_status status = napi_get_cb_info(env, info, &argCount, args, &jsThis, nullptr);
622 if (status != napi_ok || jsThis == nullptr) {
623 asyncContext->SignError(MSERR_EXT_INVALID_VAL, "failed to napi_get_cb_info");
624 }
625
626 asyncContext->callbackRef = CommonNapi::CreateReference(env, args[0]);
627 asyncContext->deferred = CommonNapi::CreatePromise(env, asyncContext->callbackRef, result);
628
629 // get jsPlayer
630 (void)napi_unwrap(env, jsThis, reinterpret_cast<void **>(&asyncContext->jsPlayer));
631 // async work
632 napi_value resource = nullptr;
633 napi_create_string_utf8(env, "Pause", NAPI_AUTO_LENGTH, &resource);
634 NAPI_CALL(env, napi_create_async_work(env, nullptr, resource, [](napi_env env, void* data) {},
635 CompleteAsyncWork, static_cast<void *>(asyncContext.get()), &asyncContext->work));
636 NAPI_CALL(env, napi_queue_async_work(env, asyncContext->work));
637 asyncContext.release();
638 return result;
639 }
640
Stop(napi_env env,napi_callback_info info)641 napi_value VideoPlayerNapi::Stop(napi_env env, napi_callback_info info)
642 {
643 napi_value result = nullptr;
644 napi_get_undefined(env, &result);
645
646 MEDIA_LOGD("Stop In");
647 std::unique_ptr<VideoPlayerAsyncContext> asyncContext = std::make_unique<VideoPlayerAsyncContext>(env);
648 asyncContext->asyncWorkType = AsyncWorkType::ASYNC_WORK_STOP;
649
650 // get args
651 napi_value jsThis = nullptr;
652 napi_value args[1] = { nullptr };
653 size_t argCount = 1;
654 napi_status status = napi_get_cb_info(env, info, &argCount, args, &jsThis, nullptr);
655 if (status != napi_ok || jsThis == nullptr) {
656 asyncContext->SignError(MSERR_EXT_INVALID_VAL, "failed to napi_get_cb_info");
657 }
658
659 asyncContext->callbackRef = CommonNapi::CreateReference(env, args[0]);
660 asyncContext->deferred = CommonNapi::CreatePromise(env, asyncContext->callbackRef, result);
661 // get jsPlayer
662 (void)napi_unwrap(env, jsThis, reinterpret_cast<void **>(&asyncContext->jsPlayer));
663 // async work
664 napi_value resource = nullptr;
665 napi_create_string_utf8(env, "Stop", NAPI_AUTO_LENGTH, &resource);
666 NAPI_CALL(env, napi_create_async_work(env, nullptr, resource, [](napi_env env, void* data) {},
667 CompleteAsyncWork, static_cast<void *>(asyncContext.get()), &asyncContext->work));
668 NAPI_CALL(env, napi_queue_async_work(env, asyncContext->work));
669 asyncContext.release();
670 return result;
671 }
672
Reset(napi_env env,napi_callback_info info)673 napi_value VideoPlayerNapi::Reset(napi_env env, napi_callback_info info)
674 {
675 napi_value result = nullptr;
676 napi_get_undefined(env, &result);
677
678 MEDIA_LOGD("Reset In");
679 std::unique_ptr<VideoPlayerAsyncContext> asyncContext = std::make_unique<VideoPlayerAsyncContext>(env);
680 asyncContext->asyncWorkType = AsyncWorkType::ASYNC_WORK_RESET;
681
682 // get args
683 napi_value jsThis = nullptr;
684 napi_value args[1] = { nullptr };
685 size_t argCount = 1;
686 napi_status status = napi_get_cb_info(env, info, &argCount, args, &jsThis, nullptr);
687 if (status != napi_ok || jsThis == nullptr) {
688 asyncContext->SignError(MSERR_EXT_INVALID_VAL, "failed to napi_get_cb_info");
689 }
690
691 asyncContext->callbackRef = CommonNapi::CreateReference(env, args[0]);
692 asyncContext->deferred = CommonNapi::CreatePromise(env, asyncContext->callbackRef, result);
693
694 // get jsPlayer
695 (void)napi_unwrap(env, jsThis, reinterpret_cast<void **>(&asyncContext->jsPlayer));
696 // async work
697 napi_value resource = nullptr;
698 napi_create_string_utf8(env, "Reset", NAPI_AUTO_LENGTH, &resource);
699 NAPI_CALL(env, napi_create_async_work(env, nullptr, resource, [](napi_env env, void* data) {},
700 CompleteAsyncWork, static_cast<void *>(asyncContext.get()), &asyncContext->work));
701 NAPI_CALL(env, napi_queue_async_work(env, asyncContext->work));
702 asyncContext.release();
703 return result;
704 }
705
Release(napi_env env,napi_callback_info info)706 napi_value VideoPlayerNapi::Release(napi_env env, napi_callback_info info)
707 {
708 napi_value result = nullptr;
709 napi_get_undefined(env, &result);
710
711 MEDIA_LOGD("Release In");
712 std::unique_ptr<VideoPlayerAsyncContext> asyncContext = std::make_unique<VideoPlayerAsyncContext>(env);
713
714 // get args
715 napi_value jsThis = nullptr;
716 napi_value args[1] = { nullptr };
717 size_t argCount = 1;
718 napi_status status = napi_get_cb_info(env, info, &argCount, args, &jsThis, nullptr);
719 if (status != napi_ok || jsThis == nullptr) {
720 asyncContext->SignError(MSERR_EXT_INVALID_VAL, "failed to napi_get_cb_info");
721 }
722
723 asyncContext->callbackRef = CommonNapi::CreateReference(env, args[0]);
724 asyncContext->deferred = CommonNapi::CreatePromise(env, asyncContext->callbackRef, result);
725
726 // get jsPlayer
727 (void)napi_unwrap(env, jsThis, reinterpret_cast<void **>(&asyncContext->jsPlayer));
728 if (asyncContext->jsPlayer == nullptr) {
729 asyncContext->SignError(MSERR_EXT_NO_MEMORY, "jsPlayer is destroyed(null), please check js_runtime");
730 } else if (asyncContext->jsPlayer->nativePlayer_ == nullptr) {
731 asyncContext->SignError(MSERR_EXT_NO_MEMORY, "nativePlayer is released(null), please create player again");
732 } else {
733 (void)asyncContext->jsPlayer->nativePlayer_->Release();
734 asyncContext->jsPlayer->CancelCallback();
735 asyncContext->jsPlayer->jsCallback_ = nullptr;
736 asyncContext->jsPlayer->nativePlayer_ = nullptr;
737 asyncContext->jsPlayer->url_.clear();
738 }
739
740 // async work
741 napi_value resource = nullptr;
742 napi_create_string_utf8(env, "Release", NAPI_AUTO_LENGTH, &resource);
743 NAPI_CALL(env, napi_create_async_work(env, nullptr, resource, [](napi_env env, void* data) {},
744 MediaAsyncContext::CompleteCallback, static_cast<void *>(asyncContext.get()), &asyncContext->work));
745 NAPI_CALL(env, napi_queue_async_work(env, asyncContext->work));
746 asyncContext.release();
747 return result;
748 }
749
Seek(napi_env env,napi_callback_info info)750 napi_value VideoPlayerNapi::Seek(napi_env env, napi_callback_info info)
751 {
752 napi_value result = nullptr;
753 napi_get_undefined(env, &result);
754
755 MEDIA_LOGI("Seek In");
756 std::unique_ptr<VideoPlayerAsyncContext> asyncContext = std::make_unique<VideoPlayerAsyncContext>(env);
757 asyncContext->asyncWorkType = AsyncWorkType::ASYNC_WORK_SEEK;
758
759 napi_value jsThis = nullptr;
760 napi_value args[3] = { nullptr }; // timeMs: number, mode:SeekMode, callback:AsyncCallback<number>
761 size_t argCount = 3;
762 napi_status status = napi_get_cb_info(env, info, &argCount, args, &jsThis, nullptr);
763 if (status != napi_ok || jsThis == nullptr) {
764 asyncContext->SignError(MSERR_EXT_INVALID_VAL, "failed to napi_get_cb_info");
765 }
766 (void)napi_unwrap(env, jsThis, reinterpret_cast<void **>(&asyncContext->jsPlayer));
767 if (asyncContext->jsPlayer != nullptr && asyncContext->jsPlayer->jsCallback_ != nullptr) {
768 auto cb = std::static_pointer_cast<VideoCallbackNapi>(asyncContext->jsPlayer->jsCallback_);
769 if (GetJSState(cb->GetCurrentState()) == VideoPlayState::STATE_STOPPED) {
770 asyncContext->SignError(MSERR_EXT_OPERATE_NOT_PERMIT, "current state does not support seek");
771 }
772 }
773
774 if (CommonNapi::CheckValueType(env, args[0], napi_number)) {
775 (void)napi_get_value_int32(env, args[0], &asyncContext->seekPosition); // timeMs: number
776 if (asyncContext->seekPosition < 0) {
777 asyncContext->SignError(MSERR_EXT_INVALID_VAL, "seek position < 0");
778 }
779 }
780
781 if (CommonNapi::CheckValueType(env, args[1], napi_number)) {
782 (void)napi_get_value_int32(env, args[1], &asyncContext->seekMode); // mode:SeekMode
783 if (asyncContext->seekMode < SEEK_NEXT_SYNC || asyncContext->seekMode > SEEK_CLOSEST) {
784 asyncContext->SignError(MSERR_EXT_INVALID_VAL, "seek mode invalid");
785 }
786 if (CommonNapi::CheckValueType(env, args[2], napi_function)) { // callback:AsyncCallback<number>
787 asyncContext->callbackRef = CommonNapi::CreateReference(env, args[2]); // callback:AsyncCallback<number>
788 }
789 } else if (CommonNapi::CheckValueType(env, args[1], napi_function)) {
790 asyncContext->callbackRef = CommonNapi::CreateReference(env, args[1]); // callback:AsyncCallback<number>
791 }
792 asyncContext->deferred = CommonNapi::CreatePromise(env, asyncContext->callbackRef, result);
793
794 napi_value resource = nullptr;
795 napi_create_string_utf8(env, "Seek", NAPI_AUTO_LENGTH, &resource);
796 NAPI_CALL(env, napi_create_async_work(env, nullptr, resource, [](napi_env env, void* data) {},
797 CompleteAsyncWork, static_cast<void *>(asyncContext.get()), &asyncContext->work));
798 NAPI_CALL(env, napi_queue_async_work(env, asyncContext->work));
799 asyncContext.release();
800 return result;
801 }
802
SetSpeed(napi_env env,napi_callback_info info)803 napi_value VideoPlayerNapi::SetSpeed(napi_env env, napi_callback_info info)
804 {
805 napi_value result = nullptr;
806 napi_get_undefined(env, &result);
807
808 MEDIA_LOGD("SetSpeed In");
809 std::unique_ptr<VideoPlayerAsyncContext> asyncContext = std::make_unique<VideoPlayerAsyncContext>(env);
810 asyncContext->asyncWorkType = AsyncWorkType::ASYNC_WORK_SPEED;
811
812 // get args
813 napi_value jsThis = nullptr;
814 napi_value args[2] = { nullptr };
815 size_t argCount = 2;
816 napi_status status = napi_get_cb_info(env, info, &argCount, args, &jsThis, nullptr);
817 if (status != napi_ok || jsThis == nullptr) {
818 asyncContext->SignError(MSERR_EXT_INVALID_VAL, "failed to napi_get_cb_info");
819 }
820
821 // get speed mode
822 napi_valuetype valueType = napi_undefined;
823 if (argCount < 1 || napi_typeof(env, args[0], &valueType) != napi_ok || valueType != napi_number) {
824 asyncContext->SignError(MSERR_EXT_INVALID_VAL, "failed get speed mode");
825 }
826 status = napi_get_value_int32(env, args[0], &asyncContext->speedMode);
827 if (status != napi_ok ||
828 asyncContext->speedMode < SPEED_FORWARD_0_75_X ||
829 asyncContext->speedMode > SPEED_FORWARD_2_00_X) {
830 asyncContext->SignError(MSERR_EXT_INVALID_VAL, "speed mode invalid");
831 }
832 asyncContext->callbackRef = CommonNapi::CreateReference(env, args[1]);
833 asyncContext->deferred = CommonNapi::CreatePromise(env, asyncContext->callbackRef, result);
834
835 // get jsPlayer
836 (void)napi_unwrap(env, jsThis, reinterpret_cast<void **>(&asyncContext->jsPlayer));
837 // async work
838 napi_value resource = nullptr;
839 napi_create_string_utf8(env, "SetSpeed", NAPI_AUTO_LENGTH, &resource);
840 NAPI_CALL(env, napi_create_async_work(env, nullptr, resource, [](napi_env env, void* data) {},
841 CompleteAsyncWork, static_cast<void *>(asyncContext.get()), &asyncContext->work));
842 NAPI_CALL(env, napi_queue_async_work(env, asyncContext->work));
843 asyncContext.release();
844 return result;
845 }
846
SelectBitrate(napi_env env,napi_callback_info info)847 napi_value VideoPlayerNapi::SelectBitrate(napi_env env, napi_callback_info info)
848 {
849 napi_value result = nullptr;
850 napi_get_undefined(env, &result);
851
852 MEDIA_LOGD("SelectBitRate In");
853 std::unique_ptr<VideoPlayerAsyncContext> asyncContext = std::make_unique<VideoPlayerAsyncContext>(env);
854 asyncContext->asyncWorkType = AsyncWorkType::ASYNC_WORK_BITRATE;
855
856 // get args
857 napi_value jsThis = nullptr;
858 napi_value args[2] = { nullptr };
859 size_t argCount = 2;
860 napi_status status = napi_get_cb_info(env, info, &argCount, args, &jsThis, nullptr);
861 if (status != napi_ok || jsThis == nullptr) {
862 asyncContext->SignError(MSERR_EXT_INVALID_VAL, "failed to napi_get_cb_info");
863 }
864
865 // get bitrate
866 napi_valuetype valueType = napi_undefined;
867 if (argCount < 1 || napi_typeof(env, args[0], &valueType) != napi_ok || valueType != napi_number) {
868 asyncContext->SignError(MSERR_EXT_INVALID_VAL, "failed get bitrate");
869 }
870 status = napi_get_value_int32(env, args[0], &asyncContext->bitRate);
871 if ((status != napi_ok) || (asyncContext->bitRate < 0)) {
872 asyncContext->SignError(MSERR_EXT_INVALID_VAL, "bitrate invalid");
873 }
874 asyncContext->callbackRef = CommonNapi::CreateReference(env, args[1]);
875 asyncContext->deferred = CommonNapi::CreatePromise(env, asyncContext->callbackRef, result);
876
877 // get jsPlayer
878 (void)napi_unwrap(env, jsThis, reinterpret_cast<void **>(&asyncContext->jsPlayer));
879 // async work
880 napi_value resource = nullptr;
881 napi_create_string_utf8(env, "SelectBitrate", NAPI_AUTO_LENGTH, &resource);
882 NAPI_CALL(env, napi_create_async_work(env, nullptr, resource, [](napi_env env, void* data) {},
883 CompleteAsyncWork, static_cast<void *>(asyncContext.get()), &asyncContext->work));
884 NAPI_CALL(env, napi_queue_async_work(env, asyncContext->work));
885 asyncContext.release();
886 return result;
887 }
888
AsyncGetTrackDescription(napi_env env,void * data)889 void VideoPlayerNapi::AsyncGetTrackDescription(napi_env env, void *data)
890 {
891 auto asyncContext = reinterpret_cast<VideoPlayerAsyncContext *>(data);
892 CHECK_AND_RETURN_LOG(asyncContext != nullptr, "VideoPlayerAsyncContext is nullptr!");
893
894 if (asyncContext->jsPlayer == nullptr) {
895 asyncContext->SignError(MSERR_EXT_NO_MEMORY, "jsPlayer is destroyed(null), please check js_runtime");
896 return;
897 }
898
899 if (asyncContext->jsPlayer->nativePlayer_ == nullptr) {
900 asyncContext->SignError(MSERR_EXT_NO_MEMORY, "nativePlayer is released(null), please create player again");
901 return;
902 }
903
904 auto player = asyncContext->jsPlayer->nativePlayer_;
905 std::vector<Format> &videoInfo = asyncContext->jsPlayer->videoTrackInfoVec_;
906 videoInfo.clear();
907 int32_t ret = player->GetVideoTrackInfo(videoInfo);
908 if (ret != MSERR_OK) {
909 asyncContext->SignError(MSErrorToExtError(static_cast<MediaServiceErrCode>(ret)),
910 "failed to GetVideoTrackInfo");
911 return;
912 }
913
914 ret = player->GetAudioTrackInfo(videoInfo);
915 if (ret != MSERR_OK) {
916 asyncContext->SignError(MSErrorToExtError(static_cast<MediaServiceErrCode>(ret)),
917 "failed to GetAudioTrackInfo");
918 return;
919 }
920
921 if (videoInfo.empty()) {
922 asyncContext->SignError(MSERR_EXT_OPERATE_NOT_PERMIT, "video/audio track info is empty");
923 return;
924 }
925
926 asyncContext->JsResult = std::make_unique<MediaJsResultArray>(videoInfo);
927 MEDIA_LOGD("AsyncGetTrackDescription Out");
928 }
929
GetTrackDescription(napi_env env,napi_callback_info info)930 napi_value VideoPlayerNapi::GetTrackDescription(napi_env env, napi_callback_info info)
931 {
932 napi_value result = nullptr;
933 napi_get_undefined(env, &result);
934
935 MEDIA_LOGD("GetTrackDescription In");
936 std::unique_ptr<VideoPlayerAsyncContext> asyncContext = std::make_unique<VideoPlayerAsyncContext>(env);
937
938 // get args
939 napi_value jsThis = nullptr;
940 napi_value args[1] = { nullptr };
941 size_t argCount = 1;
942 napi_status status = napi_get_cb_info(env, info, &argCount, args, &jsThis, nullptr);
943 if (status != napi_ok || jsThis == nullptr) {
944 asyncContext->SignError(MSERR_EXT_INVALID_VAL, "failed to napi_get_cb_info");
945 }
946
947 asyncContext->callbackRef = CommonNapi::CreateReference(env, args[0]);
948 asyncContext->deferred = CommonNapi::CreatePromise(env, asyncContext->callbackRef, result);
949 // get jsPlayer
950 (void)napi_unwrap(env, jsThis, reinterpret_cast<void **>(&asyncContext->jsPlayer));
951 // async work
952 napi_value resource = nullptr;
953 napi_create_string_utf8(env, "GetTrackDescription", NAPI_AUTO_LENGTH, &resource);
954 NAPI_CALL(env, napi_create_async_work(env, nullptr, resource, VideoPlayerNapi::AsyncGetTrackDescription,
955 MediaAsyncContext::CompleteCallback, static_cast<void *>(asyncContext.get()), &asyncContext->work));
956 NAPI_CALL(env, napi_queue_async_work(env, asyncContext->work));
957 asyncContext.release();
958 return result;
959 }
960
SetVolume(napi_env env,napi_callback_info info)961 napi_value VideoPlayerNapi::SetVolume(napi_env env, napi_callback_info info)
962 {
963 napi_value result = nullptr;
964 napi_get_undefined(env, &result);
965
966 MEDIA_LOGD("SetVolume In");
967 std::unique_ptr<VideoPlayerAsyncContext> asyncContext = std::make_unique<VideoPlayerAsyncContext>(env);
968 asyncContext->asyncWorkType = AsyncWorkType::ASYNC_WORK_VOLUME;
969
970 // get args
971 napi_value jsThis = nullptr;
972 napi_value args[2] = { nullptr };
973 size_t argCount = 2;
974 napi_status status = napi_get_cb_info(env, info, &argCount, args, &jsThis, nullptr);
975 if (status != napi_ok || jsThis == nullptr) {
976 asyncContext->SignError(MSERR_EXT_INVALID_VAL, "failed to napi_get_cb_info");
977 }
978
979 // get volume
980 napi_valuetype valueType = napi_undefined;
981 if (napi_typeof(env, args[0], &valueType) != napi_ok || valueType != napi_number) {
982 asyncContext->SignError(MSERR_EXT_INVALID_VAL, "get volume napi_typeof is't napi_number");
983 } else {
984 status = napi_get_value_double(env, args[0], &asyncContext->volume);
985 if (status != napi_ok || asyncContext->volume < 0.0f || asyncContext->volume > 1.0f) {
986 asyncContext->SignError(MSERR_EXT_INVALID_VAL, "get volume input volume < 0.0f or > 1.0f");
987 }
988 }
989 asyncContext->callbackRef = CommonNapi::CreateReference(env, args[1]);
990 asyncContext->deferred = CommonNapi::CreatePromise(env, asyncContext->callbackRef, result);
991 // get jsPlayer
992 (void)napi_unwrap(env, jsThis, reinterpret_cast<void **>(&asyncContext->jsPlayer));
993 #ifdef SUPPORT_JSSTACK
994 HiviewDFX::ReportXPowerJsStackSysEvent(env, "VOLUME_CHANGE", "SRC=Media");
995 #endif
996 // async work
997 napi_value resource = nullptr;
998 napi_create_string_utf8(env, "SetVolume", NAPI_AUTO_LENGTH, &resource);
999 NAPI_CALL(env, napi_create_async_work(env, nullptr, resource, [](napi_env env, void* data) {},
1000 CompleteAsyncWork, static_cast<void *>(asyncContext.get()), &asyncContext->work));
1001 NAPI_CALL(env, napi_queue_async_work(env, asyncContext->work));
1002 asyncContext.release();
1003 return result;
1004 }
1005
On(napi_env env,napi_callback_info info)1006 napi_value VideoPlayerNapi::On(napi_env env, napi_callback_info info)
1007 {
1008 napi_value undefinedResult = nullptr;
1009 napi_get_undefined(env, &undefinedResult);
1010
1011 static constexpr size_t minArgCount = 2;
1012 size_t argCount = minArgCount;
1013 napi_value args[minArgCount] = { nullptr, nullptr };
1014 napi_value jsThis = nullptr;
1015 napi_status status = napi_get_cb_info(env, info, &argCount, args, &jsThis, nullptr);
1016 if (status != napi_ok || jsThis == nullptr || argCount < minArgCount) {
1017 MEDIA_LOGE("Failed to retrieve details about the callback");
1018 return undefinedResult;
1019 }
1020
1021 VideoPlayerNapi *jsPlayer = nullptr;
1022 status = napi_unwrap(env, jsThis, reinterpret_cast<void **>(&jsPlayer));
1023 CHECK_AND_RETURN_RET_LOG(status == napi_ok && jsPlayer != nullptr, undefinedResult, "Failed to retrieve instance");
1024
1025 napi_valuetype valueType0 = napi_undefined;
1026 napi_valuetype valueType1 = napi_undefined;
1027 if (napi_typeof(env, args[0], &valueType0) != napi_ok || valueType0 != napi_string ||
1028 napi_typeof(env, args[1], &valueType1) != napi_ok || valueType1 != napi_function) {
1029 jsPlayer->ErrorCallback(MSERR_EXT_INVALID_VAL, "napi_typeof failed, please check the input parameters");
1030 return undefinedResult;
1031 }
1032
1033 std::string callbackName = CommonNapi::GetStringArgument(env, args[0]);
1034 MEDIA_LOGD("callbackName: %{public}s", callbackName.c_str());
1035
1036 napi_ref ref = nullptr;
1037 status = napi_create_reference(env, args[1], 1, &ref);
1038 CHECK_AND_RETURN_RET_LOG(status == napi_ok && ref != nullptr, undefinedResult, "failed to create reference!");
1039
1040 std::shared_ptr<AutoRef> autoRef = std::make_shared<AutoRef>(env, ref);
1041 jsPlayer->SetCallbackReference(callbackName, autoRef);
1042 return undefinedResult;
1043 }
1044
SetLoop(napi_env env,napi_callback_info info)1045 napi_value VideoPlayerNapi::SetLoop(napi_env env, napi_callback_info info)
1046 {
1047 napi_value undefinedResult = nullptr;
1048 napi_get_undefined(env, &undefinedResult);
1049
1050 MEDIA_LOGD("SetLoop In");
1051 size_t argCount = 1;
1052 napi_value args[1] = { nullptr };
1053 napi_value jsThis = nullptr;
1054 napi_status status = napi_get_cb_info(env, info, &argCount, args, &jsThis, nullptr);
1055 if (status != napi_ok || jsThis == nullptr || argCount < 1) {
1056 MEDIA_LOGE("Failed to retrieve details about the callback");
1057 return undefinedResult;
1058 }
1059
1060 VideoPlayerNapi *jsPlayer = nullptr;
1061 status = napi_unwrap(env, jsThis, reinterpret_cast<void **>(&jsPlayer));
1062 CHECK_AND_RETURN_RET_LOG(status == napi_ok && jsPlayer != nullptr, undefinedResult, "Failed to retrieve instance");
1063 if (jsPlayer->nativePlayer_ == nullptr) {
1064 jsPlayer->ErrorCallback(MSERR_EXT_NO_MEMORY, "player is released(null), please create player again");
1065 return undefinedResult;
1066 }
1067 napi_valuetype valueType = napi_undefined;
1068 if (napi_typeof(env, args[0], &valueType) != napi_ok || valueType != napi_boolean) {
1069 jsPlayer->ErrorCallback(MSERR_EXT_INVALID_VAL, "napi_typeof failed, please check the input parameters");
1070 return undefinedResult;
1071 }
1072
1073 bool loopFlag = false;
1074 status = napi_get_value_bool(env, args[0], &loopFlag);
1075 CHECK_AND_RETURN_RET_LOG(status == napi_ok, undefinedResult, "napi_get_value_bool error");
1076
1077 int32_t ret = jsPlayer->nativePlayer_->SetLooping(loopFlag);
1078 if (ret != MSERR_OK) {
1079 jsPlayer->ErrorCallback(MSErrorToExtError(static_cast<MediaServiceErrCode>(ret)), "failed to SetLooping");
1080 return undefinedResult;
1081 }
1082 MEDIA_LOGD("SetLoop success");
1083 return undefinedResult;
1084 }
1085
GetLoop(napi_env env,napi_callback_info info)1086 napi_value VideoPlayerNapi::GetLoop(napi_env env, napi_callback_info info)
1087 {
1088 napi_value undefinedResult = nullptr;
1089 napi_get_undefined(env, &undefinedResult);
1090
1091 napi_value jsThis = nullptr;
1092 size_t argCount = 0;
1093 napi_status status = napi_get_cb_info(env, info, &argCount, nullptr, &jsThis, nullptr);
1094 if (status != napi_ok || jsThis == nullptr) {
1095 MEDIA_LOGE("Failed to retrieve details about the callback");
1096 return undefinedResult;
1097 }
1098
1099 VideoPlayerNapi *jsPlayer = nullptr;
1100 status = napi_unwrap(env, jsThis, reinterpret_cast<void **>(&jsPlayer));
1101 CHECK_AND_RETURN_RET_LOG(status == napi_ok && jsPlayer != nullptr, undefinedResult, "Failed to retrieve instance");
1102
1103 if (jsPlayer->nativePlayer_ == nullptr) {
1104 jsPlayer->ErrorCallback(MSERR_EXT_NO_MEMORY, "player is released(null), please create player again");
1105 return undefinedResult;
1106 }
1107 bool loopFlag = jsPlayer->nativePlayer_->IsLooping();
1108
1109 napi_value jsResult = nullptr;
1110 status = napi_get_boolean(env, loopFlag, &jsResult);
1111 CHECK_AND_RETURN_RET_LOG(status == napi_ok, undefinedResult, "napi_get_boolean error");
1112 MEDIA_LOGD("GetSrc success loop Status: %{public}d", loopFlag);
1113 return jsResult;
1114 }
1115
SetVideoScaleType(napi_env env,napi_callback_info info)1116 napi_value VideoPlayerNapi::SetVideoScaleType(napi_env env, napi_callback_info info)
1117 {
1118 napi_value undefinedResult = nullptr;
1119 napi_get_undefined(env, &undefinedResult);
1120
1121 MEDIA_LOGD("SetVideoScaleType In");
1122 size_t argCount = 1;
1123 napi_value args[1] = { nullptr };
1124 napi_value jsThis = nullptr;
1125 napi_status status = napi_get_cb_info(env, info, &argCount, args, &jsThis, nullptr);
1126 if (status != napi_ok || jsThis == nullptr || argCount < 1) {
1127 MEDIA_LOGE("Failed to retrieve details about the callback");
1128 return undefinedResult;
1129 }
1130
1131 VideoPlayerNapi *jsPlayer = nullptr;
1132 status = napi_unwrap(env, jsThis, reinterpret_cast<void **>(&jsPlayer));
1133 CHECK_AND_RETURN_RET_LOG(status == napi_ok && jsPlayer != nullptr, undefinedResult, "Failed to retrieve instance");
1134
1135 if (jsPlayer->nativePlayer_ == nullptr) {
1136 jsPlayer->ErrorCallback(MSERR_EXT_NO_MEMORY, "player is released(null), please create player again");
1137 return undefinedResult;
1138 }
1139
1140 napi_valuetype valueType = napi_undefined;
1141 if (napi_typeof(env, args[0], &valueType) != napi_ok || valueType != napi_number) {
1142 jsPlayer->ErrorCallback(MSERR_EXT_INVALID_VAL, "napi_typeof failed, please check the input parameters");
1143 return undefinedResult;
1144 }
1145
1146 int32_t videoScaleType = 0;
1147 status = napi_get_value_int32(env, args[0], &videoScaleType);
1148 CHECK_AND_RETURN_RET_LOG(status == napi_ok, undefinedResult, "napi_get_value_int32 error");
1149 if (videoScaleType > static_cast<int32_t>(Plugins::VideoScaleType::VIDEO_SCALE_TYPE_FIT_CROP)
1150 || videoScaleType < static_cast<int32_t>(Plugins::VideoScaleType::VIDEO_SCALE_TYPE_FIT)) {
1151 jsPlayer->ErrorCallback(MSERR_EXT_INVALID_VAL, "invalid parameters, please check the input parameters");
1152 return undefinedResult;
1153 }
1154 if (jsPlayer->url_.empty()) {
1155 jsPlayer->ErrorCallback(MSERR_EXT_INVALID_STATE, "invalid state, please input parameters after setSrc");
1156 return undefinedResult;
1157 }
1158 jsPlayer->videoScaleType_ = videoScaleType;
1159 Format format;
1160 (void)format.PutIntValue(PlayerKeys::VIDEO_SCALE_TYPE, videoScaleType);
1161 int32_t ret = jsPlayer->nativePlayer_->SetParameter(format);
1162 if (ret != MSERR_OK) {
1163 jsPlayer->ErrorCallback(MSErrorToExtError(static_cast<MediaServiceErrCode>(ret)), "failed to SetParameter");
1164 return undefinedResult;
1165 }
1166 MEDIA_LOGD("SetVideoScaleType success");
1167 return undefinedResult;
1168 }
1169
GetVideoScaleType(napi_env env,napi_callback_info info)1170 napi_value VideoPlayerNapi::GetVideoScaleType(napi_env env, napi_callback_info info)
1171 {
1172 napi_value undefinedResult = nullptr;
1173 napi_get_undefined(env, &undefinedResult);
1174
1175 napi_value jsThis = nullptr;
1176 size_t argCount = 0;
1177 napi_status status = napi_get_cb_info(env, info, &argCount, nullptr, &jsThis, nullptr);
1178 if (status != napi_ok || jsThis == nullptr) {
1179 MEDIA_LOGE("Failed to retrieve details about the callback");
1180 return undefinedResult;
1181 }
1182
1183 VideoPlayerNapi *jsPlayer = nullptr;
1184 status = napi_unwrap(env, jsThis, reinterpret_cast<void **>(&jsPlayer));
1185 CHECK_AND_RETURN_RET_LOG(status == napi_ok && jsPlayer != nullptr, undefinedResult, "Failed to retrieve instance");
1186
1187 napi_value jsResult = nullptr;
1188 status = napi_create_int32(env, jsPlayer->videoScaleType_, &jsResult);
1189 CHECK_AND_RETURN_RET_LOG(status == napi_ok, undefinedResult, "napi_create_int32 error");
1190 MEDIA_LOGD("GetVideoScaleType success");
1191 return jsResult;
1192 }
1193
GetCurrentTime(napi_env env,napi_callback_info info)1194 napi_value VideoPlayerNapi::GetCurrentTime(napi_env env, napi_callback_info info)
1195 {
1196 napi_value undefinedResult = nullptr;
1197 napi_get_undefined(env, &undefinedResult);
1198
1199 size_t argCount = 0;
1200 napi_value jsThis = nullptr;
1201 napi_status status = napi_get_cb_info(env, info, &argCount, nullptr, &jsThis, nullptr);
1202 if (status != napi_ok || jsThis == nullptr) {
1203 MEDIA_LOGE("Failed to retrieve details about the callback");
1204 return undefinedResult;
1205 }
1206
1207 VideoPlayerNapi *jsPlayer = nullptr;
1208 status = napi_unwrap(env, jsThis, reinterpret_cast<void **>(&jsPlayer));
1209 CHECK_AND_RETURN_RET_LOG(status == napi_ok && jsPlayer != nullptr, undefinedResult, "Failed to retrieve instance");
1210
1211 if (jsPlayer->nativePlayer_ == nullptr) {
1212 jsPlayer->ErrorCallback(MSERR_EXT_NO_MEMORY, "player is released(null), please create player again");
1213 return undefinedResult;
1214 }
1215 int32_t currentTime = -1;
1216 (void)jsPlayer->nativePlayer_->GetCurrentTime(currentTime);
1217
1218 napi_value jsResult = nullptr;
1219 status = napi_create_int32(env, currentTime, &jsResult);
1220 CHECK_AND_RETURN_RET_LOG(status == napi_ok, undefinedResult, "napi_create_int32 error");
1221 MEDIA_LOGD("GetCurrenTime success, Current time: %{public}d", currentTime);
1222 return jsResult;
1223 }
1224
GetDuration(napi_env env,napi_callback_info info)1225 napi_value VideoPlayerNapi::GetDuration(napi_env env, napi_callback_info info)
1226 {
1227 napi_value undefinedResult = nullptr;
1228 napi_get_undefined(env, &undefinedResult);
1229
1230 napi_value jsThis = nullptr;
1231 size_t argCount = 0;
1232 napi_status status = napi_get_cb_info(env, info, &argCount, nullptr, &jsThis, nullptr);
1233 if (status != napi_ok || jsThis == nullptr) {
1234 MEDIA_LOGE("Failed to retrieve details about the callback");
1235 return undefinedResult;
1236 }
1237
1238 VideoPlayerNapi *jsPlayer = nullptr;
1239 status = napi_unwrap(env, jsThis, reinterpret_cast<void **>(&jsPlayer));
1240 CHECK_AND_RETURN_RET_LOG(status == napi_ok && jsPlayer != nullptr, undefinedResult, "Failed to retrieve instance");
1241
1242 if (jsPlayer->nativePlayer_ == nullptr) {
1243 jsPlayer->ErrorCallback(MSERR_EXT_NO_MEMORY, "player is released(null), please create player again");
1244 return undefinedResult;
1245 }
1246 int32_t duration = -1;
1247 (void)jsPlayer->nativePlayer_->GetDuration(duration);
1248
1249 napi_value jsResult = nullptr;
1250 status = napi_create_int32(env, duration, &jsResult);
1251 CHECK_AND_RETURN_RET_LOG(status == napi_ok, undefinedResult, "napi_create_int32 error");
1252
1253 MEDIA_LOGD("GetDuration success, Current time: %{public}d", duration);
1254 return jsResult;
1255 }
1256
GetState(napi_env env,napi_callback_info info)1257 napi_value VideoPlayerNapi::GetState(napi_env env, napi_callback_info info)
1258 {
1259 napi_value jsThis = nullptr;
1260 napi_value undefinedResult = nullptr;
1261 napi_get_undefined(env, &undefinedResult);
1262
1263 size_t argCount = 0;
1264 napi_status status = napi_get_cb_info(env, info, &argCount, nullptr, &jsThis, nullptr);
1265 CHECK_AND_RETURN_RET_LOG(status == napi_ok, undefinedResult, "Failed to retrieve details about the callback");
1266
1267 VideoPlayerNapi *jsPlayer = nullptr;
1268 status = napi_unwrap(env, jsThis, reinterpret_cast<void **>(&jsPlayer));
1269 CHECK_AND_RETURN_RET_LOG(status == napi_ok, undefinedResult, "Failed to retrieve instance");
1270
1271 std::string curState = VideoPlayState::STATE_ERROR;
1272 if (jsPlayer->jsCallback_ != nullptr) {
1273 auto cb = std::static_pointer_cast<VideoCallbackNapi>(jsPlayer->jsCallback_);
1274 curState = GetJSState(cb->GetCurrentState());
1275 MEDIA_LOGD("GetState success, State: %{public}s", curState.c_str());
1276 }
1277
1278 napi_value jsResult = nullptr;
1279 status = napi_create_string_utf8(env, curState.c_str(), NAPI_AUTO_LENGTH, &jsResult);
1280 CHECK_AND_RETURN_RET_LOG(status == napi_ok, undefinedResult, "napi_create_string_utf8 error");
1281 return jsResult;
1282 }
1283
GetWidth(napi_env env,napi_callback_info info)1284 napi_value VideoPlayerNapi::GetWidth(napi_env env, napi_callback_info info)
1285 {
1286 napi_value jsThis = nullptr;
1287 napi_value undefinedResult = nullptr;
1288 napi_get_undefined(env, &undefinedResult);
1289
1290 MEDIA_LOGD("GetWidth In");
1291 size_t argCount = 0;
1292 napi_status status = napi_get_cb_info(env, info, &argCount, nullptr, &jsThis, nullptr);
1293 CHECK_AND_RETURN_RET_LOG(status == napi_ok, undefinedResult, "Failed to retrieve details about the callback");
1294
1295 VideoPlayerNapi *jsPlayer = nullptr;
1296 status = napi_unwrap(env, jsThis, reinterpret_cast<void **>(&jsPlayer));
1297 CHECK_AND_RETURN_RET_LOG(status == napi_ok && jsPlayer != nullptr, undefinedResult, "Failed to retrieve instance");
1298
1299 int32_t width = 0;
1300 if (jsPlayer->jsCallback_ != nullptr) {
1301 auto cb = std::static_pointer_cast<VideoCallbackNapi>(jsPlayer->jsCallback_);
1302 width = cb->GetVideoWidth();
1303 }
1304
1305 napi_value jsResult = nullptr;
1306 status = napi_create_int32(env, width, &jsResult);
1307 CHECK_AND_RETURN_RET_LOG(status == napi_ok, undefinedResult, "napi_create_int32 error");
1308 return jsResult;
1309 }
1310
GetHeight(napi_env env,napi_callback_info info)1311 napi_value VideoPlayerNapi::GetHeight(napi_env env, napi_callback_info info)
1312 {
1313 napi_value jsThis = nullptr;
1314 napi_value undefinedResult = nullptr;
1315 napi_get_undefined(env, &undefinedResult);
1316
1317 MEDIA_LOGD("GetHeight In");
1318 size_t argCount = 0;
1319 napi_status status = napi_get_cb_info(env, info, &argCount, nullptr, &jsThis, nullptr);
1320 CHECK_AND_RETURN_RET_LOG(status == napi_ok, undefinedResult, "Failed to retrieve details about the callback");
1321
1322 VideoPlayerNapi *jsPlayer = nullptr;
1323 status = napi_unwrap(env, jsThis, reinterpret_cast<void **>(&jsPlayer));
1324 CHECK_AND_RETURN_RET_LOG(status == napi_ok && jsPlayer != nullptr, undefinedResult, "Failed to retrieve instance");
1325
1326 int32_t height = 0;
1327 if (jsPlayer->jsCallback_ != nullptr) {
1328 auto cb = std::static_pointer_cast<VideoCallbackNapi>(jsPlayer->jsCallback_);
1329 height = cb->GetVideoHeight();
1330 }
1331
1332 napi_value jsResult = nullptr;
1333 status = napi_create_int32(env, height, &jsResult);
1334 CHECK_AND_RETURN_RET_LOG(status == napi_ok, undefinedResult, "napi_create_int32 error");
1335 return jsResult;
1336 }
1337
ErrorCallback(MediaServiceExtErrCode errCode,std::string errMsg)1338 void VideoPlayerNapi::ErrorCallback(MediaServiceExtErrCode errCode, std::string errMsg)
1339 {
1340 if (jsCallback_ != nullptr) {
1341 auto cb = std::static_pointer_cast<VideoCallbackNapi>(jsCallback_);
1342 cb->SendErrorCallback(errCode, errMsg);
1343 }
1344 }
1345
SetAudioInterruptMode(napi_env env,napi_callback_info info)1346 napi_value VideoPlayerNapi::SetAudioInterruptMode(napi_env env, napi_callback_info info)
1347 {
1348 size_t argCount = 1;
1349 napi_value args[1] = { nullptr };
1350 napi_value jsThis = nullptr;
1351 napi_value undefinedResult = nullptr;
1352 napi_get_undefined(env, &undefinedResult);
1353
1354 MEDIA_LOGD("SetAudioInterruptMode In");
1355 napi_status status = napi_get_cb_info(env, info, &argCount, args, &jsThis, nullptr);
1356 if (status != napi_ok || jsThis == nullptr || argCount < 1) {
1357 MEDIA_LOGE("Failed to retrieve details about the callback");
1358 return undefinedResult;
1359 }
1360
1361 VideoPlayerNapi *jsPlayer = nullptr;
1362 status = napi_unwrap(env, jsThis, reinterpret_cast<void **>(&jsPlayer));
1363 CHECK_AND_RETURN_RET_LOG(status == napi_ok && jsPlayer != nullptr, undefinedResult, "Failed to retrieve instance");
1364
1365 if (jsPlayer->nativePlayer_ == nullptr) {
1366 jsPlayer->ErrorCallback(MSERR_EXT_NO_MEMORY, "player is released(null), please create player again");
1367 return undefinedResult;
1368 }
1369
1370 napi_valuetype valueType = napi_undefined;
1371 if (napi_typeof(env, args[0], &valueType) != napi_ok || valueType != napi_number) {
1372 jsPlayer->ErrorCallback(MSERR_EXT_INVALID_VAL, "napi_typeof failed, please check the input parameters");
1373 return undefinedResult;
1374 }
1375
1376 int32_t interruptMode = 0;
1377 status = napi_get_value_int32(env, args[0], &interruptMode);
1378 CHECK_AND_RETURN_RET_LOG(status == napi_ok, undefinedResult, "napi_get_value_bool error");
1379
1380 if (interruptMode < AudioStandard::InterruptMode::SHARE_MODE ||
1381 interruptMode > AudioStandard::InterruptMode::INDEPENDENT_MODE) {
1382 jsPlayer->ErrorCallback(MSERR_EXT_INVALID_VAL, "invalid parameters, please check the input parameters");
1383 return undefinedResult;
1384 }
1385
1386 jsPlayer->interruptMode_ = AudioStandard::InterruptMode(interruptMode);
1387 Format format;
1388 (void)format.PutIntValue(PlayerKeys::AUDIO_INTERRUPT_MODE, interruptMode);
1389 int32_t ret = jsPlayer->nativePlayer_->SetParameter(format);
1390 if (ret != MSERR_OK) {
1391 jsPlayer->ErrorCallback(MSErrorToExtError(static_cast<MediaServiceErrCode>(ret)), "failed to SetParameter");
1392 return undefinedResult;
1393 }
1394
1395 MEDIA_LOGD("SetAudioInterruptMode success");
1396 return undefinedResult;
1397 }
1398
GetAudioInterruptMode(napi_env env,napi_callback_info info)1399 napi_value VideoPlayerNapi::GetAudioInterruptMode(napi_env env, napi_callback_info info)
1400 {
1401 napi_value jsThis = nullptr;
1402 napi_value jsResult = nullptr;
1403 napi_value undefinedResult = nullptr;
1404 napi_get_undefined(env, &undefinedResult);
1405
1406 size_t argCount = 0;
1407 napi_status status = napi_get_cb_info(env, info, &argCount, nullptr, &jsThis, nullptr);
1408 if (status != napi_ok || jsThis == nullptr) {
1409 MEDIA_LOGE("Failed to retrieve details about the callback");
1410 return undefinedResult;
1411 }
1412
1413 VideoPlayerNapi *player = nullptr;
1414 status = napi_unwrap(env, jsThis, reinterpret_cast<void **>(&player));
1415 CHECK_AND_RETURN_RET_LOG(status == napi_ok && player != nullptr, undefinedResult, "Failed to retrieve instance");
1416
1417 CHECK_AND_RETURN_RET_LOG(player->nativePlayer_ != nullptr, undefinedResult, "No memory");
1418
1419 status = napi_create_object(env, &jsResult);
1420 CHECK_AND_RETURN_RET_LOG(status == napi_ok, undefinedResult, "create jsresult object error");
1421
1422 CHECK_AND_RETURN_RET(CommonNapi::AddNumberPropInt32(env, jsResult, "InterruptMode",
1423 player->interruptMode_) == true, nullptr);
1424 MEDIA_LOGD("GetAudioInterruptMode success");
1425 return jsResult;
1426 }
1427
SetCallbackReference(const std::string & callbackName,std::shared_ptr<AutoRef> ref)1428 void VideoPlayerNapi::SetCallbackReference(const std::string &callbackName, std::shared_ptr<AutoRef> ref)
1429 {
1430 refMap_[callbackName] = ref;
1431 if (jsCallback_ != nullptr) {
1432 std::shared_ptr<PlayerCallbackNapi> napiCb = std::static_pointer_cast<PlayerCallbackNapi>(jsCallback_);
1433 napiCb->SaveCallbackReference(callbackName, ref);
1434 }
1435 }
1436
CancelCallback()1437 void VideoPlayerNapi::CancelCallback()
1438 {
1439 if (jsCallback_ != nullptr) {
1440 std::shared_ptr<VideoCallbackNapi> napiCb = std::static_pointer_cast<VideoCallbackNapi>(jsCallback_);
1441 napiCb->ClearCallbackReference();
1442 napiCb->ClearAsyncWork(false, "the requests was aborted because user called release");
1443 }
1444 }
1445 } // namespace Media
1446 } // namespace OHOS