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