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