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