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