• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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