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