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