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