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