• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2022 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 "avplayer_callback.h"
17 #include <uv.h>
18 #include "avplayer_napi.h"
19 #include "media_errors.h"
20 #include "media_log.h"
21 #include "scope_guard.h"
22 
23 namespace {
24 constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, LOG_DOMAIN, "AVPlayerCallback"};
25 }
26 
27 namespace OHOS {
28 namespace Media {
29 class NapiCallback {
30 public:
31     struct Base {
32         std::weak_ptr<AutoRef> callback;
33         std::string callbackName = "unknown";
34         Base() = default;
35         virtual ~Base() = default;
UvWorkOHOS::Media::NapiCallback::Base36         virtual void UvWork()
37         {
38             std::shared_ptr<AutoRef> ref = callback.lock();
39             CHECK_AND_RETURN_LOG(ref != nullptr,
40                 "%{public}s AutoRef is nullptr", callbackName.c_str());
41 
42             napi_value jsCallback = nullptr;
43             napi_status status = napi_get_reference_value(ref->env_, ref->cb_, &jsCallback);
44             CHECK_AND_RETURN_LOG(status == napi_ok && jsCallback != nullptr,
45                 "%{public}s failed to napi_get_reference_value", callbackName.c_str());
46 
47             // Call back function
48             napi_value result = nullptr;
49             status = napi_call_function(ref->env_, nullptr, jsCallback, 0, nullptr, &result);
50             CHECK_AND_RETURN_LOG(status == napi_ok,
51                 "%{public}s failed to napi_call_function", callbackName.c_str());
52         }
53     };
54 
55     struct Error : public Base {
56         std::string errorMsg = "unknown";
57         MediaServiceExtErrCodeAPI9 errorCode = MSERR_EXT_API9_UNSUPPORT_FORMAT;
UvWorkOHOS::Media::NapiCallback::Error58         void UvWork() override
59         {
60             std::shared_ptr<AutoRef> ref = callback.lock();
61             CHECK_AND_RETURN_LOG(ref != nullptr,
62                 "%{public}s AutoRef is nullptr", callbackName.c_str());
63 
64             napi_value jsCallback = nullptr;
65             napi_status status = napi_get_reference_value(ref->env_, ref->cb_, &jsCallback);
66             CHECK_AND_RETURN_LOG(status == napi_ok && jsCallback != nullptr,
67                 "%{public}s failed to napi_get_reference_value", callbackName.c_str());
68 
69             napi_value args[1] = {nullptr};
70             (void)CommonNapi::CreateError(ref->env_, errorCode, errorMsg, args[0]);
71 
72             // Call back function
73             napi_value result = nullptr;
74             status = napi_call_function(ref->env_, nullptr, jsCallback, 1, args, &result);
75             CHECK_AND_RETURN_LOG(status == napi_ok,
76                 "%{public}s failed to napi_call_function", callbackName.c_str());
77         }
78     };
79 
80     struct Int : public Base {
81         int32_t value = 0;
UvWorkOHOS::Media::NapiCallback::Int82         void UvWork() override
83         {
84             std::shared_ptr<AutoRef> ref = callback.lock();
85             CHECK_AND_RETURN_LOG(ref != nullptr,
86                 "%{public}s AutoRef is nullptr", callbackName.c_str());
87 
88             napi_value jsCallback = nullptr;
89             napi_status status = napi_get_reference_value(ref->env_, ref->cb_, &jsCallback);
90             CHECK_AND_RETURN_LOG(status == napi_ok && jsCallback != nullptr,
91                 "%{public}s failed to napi_get_reference_value", callbackName.c_str());
92 
93             napi_value args[1] = {nullptr}; // callback: (int)
94             (void)napi_create_int32(ref->env_, value, &args[0]);
95 
96             napi_value result = nullptr;
97             status = napi_call_function(ref->env_, nullptr, jsCallback, 1, args, &result);
98             CHECK_AND_RETURN_LOG(status == napi_ok,
99                 "%{public}s failed to napi_call_function", callbackName.c_str());
100         }
101     };
102 
103     struct IntVec : public Base {
104         std::vector<int32_t> valueVec;
UvWorkOHOS::Media::NapiCallback::IntVec105         void UvWork() override
106         {
107             std::shared_ptr<AutoRef> ref = callback.lock();
108             CHECK_AND_RETURN_LOG(ref != nullptr,
109                 "%{public}s AutoRef is nullptr", callbackName.c_str());
110 
111             napi_value jsCallback = nullptr;
112             napi_status status = napi_get_reference_value(ref->env_, ref->cb_, &jsCallback);
113             CHECK_AND_RETURN_LOG(status == napi_ok && jsCallback != nullptr,
114                 "%{public}s failed to napi_get_reference_value", callbackName.c_str());
115 
116             napi_value args[2] = {nullptr}; // callback: (int, int)
117             (void)napi_create_int32(ref->env_, valueVec[0], &args[0]);
118             (void)napi_create_int32(ref->env_, valueVec[1], &args[1]);
119 
120             const int32_t argCount = static_cast<int32_t>(valueVec.size());
121             napi_value result = nullptr;
122             status = napi_call_function(ref->env_, nullptr, jsCallback, argCount, args, &result);
123             CHECK_AND_RETURN_LOG(status == napi_ok,
124                 "%{public}s failed to napi_call_function", callbackName.c_str());
125         }
126     };
127 
128     struct IntArray : public Base {
129         std::vector<int32_t> valueVec;
UvWorkOHOS::Media::NapiCallback::IntArray130         void UvWork() override
131         {
132             std::shared_ptr<AutoRef> ref = callback.lock();
133             CHECK_AND_RETURN_LOG(ref != nullptr,
134                 "%{public}s AutoRef is nullptr", callbackName.c_str());
135 
136             napi_value jsCallback = nullptr;
137             napi_status status = napi_get_reference_value(ref->env_, ref->cb_, &jsCallback);
138             CHECK_AND_RETURN_LOG(status == napi_ok && jsCallback != nullptr,
139                 "%{public}s failed to napi_get_reference_value", callbackName.c_str());
140 
141             napi_value array = nullptr;
142             (void)napi_create_array_with_length(ref->env_, valueVec.size(), &array);
143 
144             for (uint32_t i = 0; i < valueVec.size(); i++) {
145                 napi_value number = nullptr;
146                 (void)napi_create_int32(ref->env_, valueVec.at(i), &number);
147                 (void)napi_set_element(ref->env_, array, i, number);
148             }
149 
150             napi_value result = nullptr;
151             napi_value args[1] = {array};
152             status = napi_call_function(ref->env_, nullptr, jsCallback, 1, args, &result);
153             CHECK_AND_RETURN_LOG(status == napi_ok,
154                 "%{public}s failed to napi_call_function", callbackName.c_str());
155         }
156     };
157 
158     struct Double : public Base {
159         double value = 0.0;
UvWorkOHOS::Media::NapiCallback::Double160         void UvWork() override
161         {
162             std::shared_ptr<AutoRef> ref = callback.lock();
163             CHECK_AND_RETURN_LOG(ref != nullptr,
164                 "%{public}s AutoRef is nullptr", callbackName.c_str());
165 
166             napi_value jsCallback = nullptr;
167             napi_status status = napi_get_reference_value(ref->env_, ref->cb_, &jsCallback);
168             CHECK_AND_RETURN_LOG(status == napi_ok && jsCallback != nullptr,
169                 "%{public}s failed to napi_get_reference_value", callbackName.c_str());
170 
171             napi_value args[1] = {nullptr};
172             (void)napi_create_double(ref->env_, value, &args[0]);
173 
174             napi_value result = nullptr;
175             status = napi_call_function(ref->env_, nullptr, jsCallback, 1, args, &result);
176             CHECK_AND_RETURN_LOG(status == napi_ok,
177                 "%{public}s failed to napi_call_function", callbackName.c_str());
178         }
179     };
180 
181     struct PropertyInt : public Base {
182         std::map<std::string, int32_t> valueMap;
UvWorkOHOS::Media::NapiCallback::PropertyInt183         void UvWork() override
184         {
185             std::shared_ptr<AutoRef> ref = callback.lock();
186             CHECK_AND_RETURN_LOG(ref != nullptr,
187                 "%{public}s AutoRef is nullptr", callbackName.c_str());
188 
189             napi_value jsCallback = nullptr;
190             napi_status status = napi_get_reference_value(ref->env_, ref->cb_, &jsCallback);
191             CHECK_AND_RETURN_LOG(status == napi_ok && jsCallback != nullptr,
192                 "%{public}s failed to napi_get_reference_value", callbackName.c_str());
193 
194             napi_value args[1] = {nullptr};
195             napi_create_object(ref->env_, &args[0]);
196             for (auto &it : valueMap) {
197                 CommonNapi::SetPropertyInt32(ref->env_, args[0], it.first, it.second);
198             }
199 
200             napi_value result = nullptr;
201             status = napi_call_function(ref->env_, nullptr, jsCallback, 1, args, &result);
202             CHECK_AND_RETURN_LOG(status == napi_ok,
203                 "%{public}s fail to napi_call_function", callbackName.c_str());
204         }
205     };
206 
207     struct StateChange : public Base {
208         std::string state = "";
209         int32_t reason = 0;
UvWorkOHOS::Media::NapiCallback::StateChange210         void UvWork() override
211         {
212             std::shared_ptr<AutoRef> ref = callback.lock();
213             CHECK_AND_RETURN_LOG(ref != nullptr,
214                 "%{public}s AutoRef is nullptr", callbackName.c_str());
215 
216             napi_value jsCallback = nullptr;
217             napi_status status = napi_get_reference_value(ref->env_, ref->cb_, &jsCallback);
218             CHECK_AND_RETURN_LOG(status == napi_ok && jsCallback != nullptr,
219                 "%{public}s failed to napi_get_reference_value", callbackName.c_str());
220 
221             const int32_t argCount = 2;
222             // callback: (state: AVPlayerState, reason: StateChangeReason)
223             napi_value args[argCount] = {nullptr};
224             (void)napi_create_string_utf8(ref->env_, state.c_str(), NAPI_AUTO_LENGTH, &args[0]);
225             (void)napi_create_int32(ref->env_, reason, &args[1]);
226 
227             napi_value result = nullptr;
228             status = napi_call_function(ref->env_, nullptr, jsCallback, argCount, args, &result);
229             CHECK_AND_RETURN_LOG(status == napi_ok,
230                 "%{public}s fail to napi_call_function", callbackName.c_str());
231         }
232     };
233 
CompleteCallback(napi_env env,NapiCallback::Base * jsCb)234     static void CompleteCallback(napi_env env, NapiCallback::Base *jsCb)
235     {
236         ON_SCOPE_EXIT(0) { delete jsCb; };
237 
238         uv_loop_s *loop = nullptr;
239         napi_get_uv_event_loop(env, &loop);
240         CHECK_AND_RETURN_LOG(loop != nullptr, "Fail to napi_get_uv_event_loop");
241 
242         uv_work_t *work = new(std::nothrow) uv_work_t;
243         CHECK_AND_RETURN_LOG(work != nullptr, "Fail to new uv_work_t");
244 
245         work->data = reinterpret_cast<void *>(jsCb);
246         // async callback, jsWork and jsWork->data should be heap object.
247         int ret = uv_queue_work(loop, work, [] (uv_work_t *work) {}, [] (uv_work_t *work, int status) {
248             CHECK_AND_RETURN_LOG(work != nullptr, "Work thread is nullptr");
249             (void)status;
250             NapiCallback::Base *cb = reinterpret_cast<NapiCallback::Base *>(work->data);
251             if (cb != nullptr) {
252                 MEDIA_LOGI("JsCallBack %{public}s, uv_queue_work start", cb->callbackName.c_str());
253                 cb->UvWork();
254                 delete cb;
255             }
256             delete work;
257         });
258         if (ret != 0) {
259             MEDIA_LOGE("Failed to execute libuv work queue");
260             delete jsCb;
261             delete work;
262         }
263         CANCEL_SCOPE_EXIT_GUARD(0);
264     }
265 };
266 
AVPlayerCallback(napi_env env,AVPlayerNotify * listener)267 AVPlayerCallback::AVPlayerCallback(napi_env env, AVPlayerNotify *listener)
268     : env_(env), listener_(listener)
269 {
270     MEDIA_LOGI("0x%{public}06" PRIXPTR " Instances create", FAKE_POINTER(this));
271 }
272 
~AVPlayerCallback()273 AVPlayerCallback::~AVPlayerCallback()
274 {
275     MEDIA_LOGI("0x%{public}06" PRIXPTR " Instances destroy", FAKE_POINTER(this));
276 }
277 
OnError(int32_t errorCode,const std::string & errorMsg)278 void AVPlayerCallback::OnError(int32_t errorCode, const std::string &errorMsg)
279 {
280     MediaServiceExtErrCodeAPI9 errorCodeApi9 = MSErrorToExtErrorAPI9(static_cast<MediaServiceErrCode>(errorCode));
281     if (errorCodeApi9 == MSERR_EXT_API9_NO_PERMISSION ||
282         errorCodeApi9 == MSERR_EXT_API9_NO_MEMORY ||
283         errorCodeApi9 == MSERR_EXT_API9_TIMEOUT ||
284         errorCodeApi9 == MSERR_EXT_API9_SERVICE_DIED ||
285         errorCodeApi9 == MSERR_EXT_API9_UNSUPPORT_FORMAT) {
286         Format infoBody;
287         AVPlayerCallback::OnInfo(INFO_TYPE_STATE_CHANGE, PLAYER_STATE_ERROR, infoBody);
288     }
289     AVPlayerCallback::OnErrorCb(errorCodeApi9, errorMsg);
290 }
291 
OnErrorCb(MediaServiceExtErrCodeAPI9 errorCode,const std::string & errorMsg)292 void AVPlayerCallback::OnErrorCb(MediaServiceExtErrCodeAPI9 errorCode, const std::string &errorMsg)
293 {
294     std::string message = MSExtAVErrorToString(errorCode) + errorMsg;
295     MEDIA_LOGE("OnErrorCb:errorCode %{public}d, errorMsg %{public}s", errorCode, message.c_str());
296     std::lock_guard<std::mutex> lock(mutex_);
297     if (refMap_.find(AVPlayerEvent::EVENT_ERROR) == refMap_.end()) {
298         MEDIA_LOGW("can not find error callback!");
299         return;
300     }
301 
302     NapiCallback::Error *cb = new(std::nothrow) NapiCallback::Error();
303     CHECK_AND_RETURN_LOG(cb != nullptr, "failed to new Error");
304 
305     cb->callback = refMap_.at(AVPlayerEvent::EVENT_ERROR);
306     cb->callbackName = AVPlayerEvent::EVENT_ERROR;
307     cb->errorCode = errorCode;
308     cb->errorMsg = message;
309     NapiCallback::CompleteCallback(env_, cb);
310 }
311 
OnInfo(PlayerOnInfoType type,int32_t extra,const Format & infoBody)312 void AVPlayerCallback::OnInfo(PlayerOnInfoType type, int32_t extra, const Format &infoBody)
313 {
314     std::lock_guard<std::mutex> lock(mutex_);
315     MEDIA_LOGI("OnInfo is called, PlayerOnInfoType: %{public}d", type);
316 
317     switch (type) {
318         case INFO_TYPE_STATE_CHANGE:
319             AVPlayerCallback::OnStateChangeCb(static_cast<PlayerStates>(extra), infoBody);
320             break;
321         case INFO_TYPE_VOLUME_CHANGE:
322             AVPlayerCallback::OnVolumeChangeCb(infoBody);
323             break;
324         case INFO_TYPE_SEEKDONE:
325             AVPlayerCallback::OnSeekDoneCb(extra);
326             break;
327         case INFO_TYPE_SPEEDDONE:
328             AVPlayerCallback::OnSpeedDoneCb(extra);
329             break;
330         case INFO_TYPE_BITRATEDONE:
331             AVPlayerCallback::OnBitRateDoneCb(extra);
332             break;
333         case INFO_TYPE_POSITION_UPDATE:
334             AVPlayerCallback::OnPositionUpdateCb(extra);
335             break;
336         case INFO_TYPE_DURATION_UPDATE:
337             AVPlayerCallback::OnDurationUpdateCb(extra);
338             break;
339         case INFO_TYPE_BUFFERING_UPDATE:
340             AVPlayerCallback::OnBufferingUpdateCb(infoBody);
341             break;
342         case INFO_TYPE_MESSAGE:
343             AVPlayerCallback::OnMessageCb(extra, infoBody);
344             break;
345         case INFO_TYPE_RESOLUTION_CHANGE:
346             AVPlayerCallback::OnVideoSizeChangedCb(infoBody);
347             break;
348         case INFO_TYPE_INTERRUPT_EVENT:
349             AVPlayerCallback::OnAudioInterruptCb(infoBody);
350             break;
351         case INFO_TYPE_BITRATE_COLLECT:
352             AVPlayerCallback::OnBitRateCollectedCb(infoBody);
353             break;
354         case INFO_TYPE_EOS:
355             AVPlayerCallback::OnEosCb(extra);
356             break;
357         default:
358             break;
359     }
360 }
361 
OnStateChangeCb(PlayerStates state,const Format & infoBody)362 void AVPlayerCallback::OnStateChangeCb(PlayerStates state, const Format &infoBody)
363 {
364     MEDIA_LOGI("OnStateChanged is called, current state: %{public}d", state);
365 
366     if (listener_ != nullptr) {
367         listener_->NotifyState(state);
368     }
369 
370     if (state_ != state) {
371         state_ = state;
372         static std::map<PlayerStates, std::string> stateMap = {
373             { PLAYER_IDLE, AVPlayerState::STATE_IDLE },
374             { PLAYER_INITIALIZED, AVPlayerState::STATE_INITIALIZED },
375             { PLAYER_PREPARED, AVPlayerState::STATE_PREPARED },
376             { PLAYER_STARTED, AVPlayerState::STATE_PLAYING },
377             { PLAYER_PAUSED, AVPlayerState::STATE_PAUSED },
378             { PLAYER_STOPPED, AVPlayerState::STATE_STOPPED },
379             { PLAYER_PLAYBACK_COMPLETE, AVPlayerState::STATE_COMPLETED },
380             { PLAYER_RELEASED, AVPlayerState::STATE_RELEASED },
381             { PLAYER_STATE_ERROR, AVPlayerState::STATE_ERROR },
382         };
383 
384         if (stateMap.find(state) != stateMap.end()) {
385             if (refMap_.find(AVPlayerEvent::EVENT_STATE_CHANGE) == refMap_.end()) {
386                 MEDIA_LOGW("can not find state change callback!");
387                 return;
388             }
389             NapiCallback::StateChange *cb = new(std::nothrow) NapiCallback::StateChange();
390             CHECK_AND_RETURN_LOG(cb != nullptr, "failed to new StateChange");
391 
392             int32_t reason = StateChangeReason::USER;
393             if (infoBody.ContainKey(PlayerKeys::PLAYER_STATE_CHANGED_REASON)) {
394                 (void)infoBody.GetIntValue(PlayerKeys::PLAYER_STATE_CHANGED_REASON, reason);
395             }
396             cb->callback = refMap_.at(AVPlayerEvent::EVENT_STATE_CHANGE);
397             cb->callbackName = AVPlayerEvent::EVENT_STATE_CHANGE;
398             cb->state = stateMap.at(state);
399             cb->reason = reason;
400             NapiCallback::CompleteCallback(env_, cb);
401         }
402     }
403 }
404 
OnVolumeChangeCb(const Format & infoBody)405 void AVPlayerCallback::OnVolumeChangeCb(const Format &infoBody)
406 {
407     CHECK_AND_RETURN_LOG(isloaded_.load(), "current source is unready");
408     float volumeLevel = 0.0;
409     (void)infoBody.GetFloatValue(PlayerKeys::PLAYER_VOLUME_LEVEL, volumeLevel);
410 
411     MEDIA_LOGI("OnVolumeChangeCb in volume=%{public}f", volumeLevel);
412     if (refMap_.find(AVPlayerEvent::EVENT_VOLUME_CHANGE) == refMap_.end()) {
413         MEDIA_LOGW("can not find vol change callback!");
414         return;
415     }
416 
417     NapiCallback::Double *cb = new(std::nothrow) NapiCallback::Double();
418     CHECK_AND_RETURN_LOG(cb != nullptr, "failed to new Double");
419     cb->callback = refMap_.at(AVPlayerEvent::EVENT_VOLUME_CHANGE);
420     cb->callbackName = AVPlayerEvent::EVENT_VOLUME_CHANGE;
421     cb->value = static_cast<double>(volumeLevel);
422     NapiCallback::CompleteCallback(env_, cb);
423 }
424 
OnSeekDoneCb(int32_t currentPositon) const425 void AVPlayerCallback::OnSeekDoneCb(int32_t currentPositon) const
426 {
427     CHECK_AND_RETURN_LOG(isloaded_.load(), "current source is unready");
428     MEDIA_LOGI("OnSeekDone is called, currentPositon: %{public}d", currentPositon);
429     if (refMap_.find(AVPlayerEvent::EVENT_SEEK_DONE) == refMap_.end()) {
430         MEDIA_LOGW("can not find seekdone callback!");
431         return;
432     }
433 
434     NapiCallback::Int *cb = new(std::nothrow) NapiCallback::Int();
435     CHECK_AND_RETURN_LOG(cb != nullptr, "failed to new Int");
436 
437     cb->callback = refMap_.at(AVPlayerEvent::EVENT_SEEK_DONE);
438     cb->callbackName = AVPlayerEvent::EVENT_SEEK_DONE;
439     cb->value = currentPositon;
440     NapiCallback::CompleteCallback(env_, cb);
441 }
442 
OnSpeedDoneCb(int32_t speedMode) const443 void AVPlayerCallback::OnSpeedDoneCb(int32_t speedMode) const
444 {
445     CHECK_AND_RETURN_LOG(isloaded_.load(), "current source is unready");
446     MEDIA_LOGI("OnSpeedDoneCb is called, speedMode: %{public}d", speedMode);
447     if (refMap_.find(AVPlayerEvent::EVENT_SPEED_DONE) == refMap_.end()) {
448         MEDIA_LOGW("can not find speeddone callback!");
449         return;
450     }
451 
452     NapiCallback::Int *cb = new(std::nothrow) NapiCallback::Int();
453     CHECK_AND_RETURN_LOG(cb != nullptr, "failed to new Int");
454 
455     cb->callback = refMap_.at(AVPlayerEvent::EVENT_SPEED_DONE);
456     cb->callbackName = AVPlayerEvent::EVENT_SPEED_DONE;
457     cb->value = speedMode;
458     NapiCallback::CompleteCallback(env_, cb);
459 }
460 
OnBitRateDoneCb(int32_t bitRate) const461 void AVPlayerCallback::OnBitRateDoneCb(int32_t bitRate) const
462 {
463     CHECK_AND_RETURN_LOG(isloaded_.load(), "current source is unready");
464     MEDIA_LOGI("OnBitRateDoneCb is called, bitRate: %{public}d", bitRate);
465     if (refMap_.find(AVPlayerEvent::EVENT_BITRATE_DONE) == refMap_.end()) {
466         MEDIA_LOGW("can not find bitrate callback!");
467         return;
468     }
469 
470     NapiCallback::Int *cb = new(std::nothrow) NapiCallback::Int();
471     CHECK_AND_RETURN_LOG(cb != nullptr, "failed to new Int");
472 
473     cb->callback = refMap_.at(AVPlayerEvent::EVENT_BITRATE_DONE);
474     cb->callbackName = AVPlayerEvent::EVENT_BITRATE_DONE;
475     cb->value = bitRate;
476     NapiCallback::CompleteCallback(env_, cb);
477 }
478 
OnPositionUpdateCb(int32_t position) const479 void AVPlayerCallback::OnPositionUpdateCb(int32_t position) const
480 {
481     CHECK_AND_RETURN_LOG(isloaded_.load(), "current source is unready");
482     MEDIA_LOGI("OnPositionUpdateCb is called, position: %{public}d", position);
483 
484     if (listener_ != nullptr) {
485         listener_->NotifyPosition(position);
486     }
487 
488     if (refMap_.find(AVPlayerEvent::EVENT_TIME_UPDATE) == refMap_.end()) {
489         MEDIA_LOGW("can not find timeupdate callback!");
490         return;
491     }
492 
493     NapiCallback::Int *cb = new(std::nothrow) NapiCallback::Int();
494     CHECK_AND_RETURN_LOG(cb != nullptr, "failed to new Int");
495 
496     cb->callback = refMap_.at(AVPlayerEvent::EVENT_TIME_UPDATE);
497     cb->callbackName = AVPlayerEvent::EVENT_TIME_UPDATE;
498     cb->value = position;
499     NapiCallback::CompleteCallback(env_, cb);
500 }
501 
OnDurationUpdateCb(int32_t duration) const502 void AVPlayerCallback::OnDurationUpdateCb(int32_t duration) const
503 {
504     CHECK_AND_RETURN_LOG(isloaded_.load(), "current source is unready");
505     MEDIA_LOGI("OnDurationUpdateCb is called, duration: %{public}d", duration);
506 
507     if (listener_ != nullptr) {
508         listener_->NotifyDuration(duration);
509     }
510 
511     if (refMap_.find(AVPlayerEvent::EVENT_DURATION_UPDATE) == refMap_.end()) {
512         MEDIA_LOGW("can not find duration update callback!");
513         return;
514     }
515 
516     NapiCallback::Int *cb = new(std::nothrow) NapiCallback::Int();
517     CHECK_AND_RETURN_LOG(cb != nullptr, "failed to new Int");
518 
519     cb->callback = refMap_.at(AVPlayerEvent::EVENT_DURATION_UPDATE);
520     cb->callbackName = AVPlayerEvent::EVENT_DURATION_UPDATE;
521     cb->value = duration;
522     NapiCallback::CompleteCallback(env_, cb);
523 }
524 
OnBufferingUpdateCb(const Format & infoBody) const525 void AVPlayerCallback::OnBufferingUpdateCb(const Format &infoBody) const
526 {
527     CHECK_AND_RETURN_LOG(isloaded_.load(), "current source is unready");
528     MEDIA_LOGI("OnBufferingUpdateCb is called");
529     if (refMap_.find(AVPlayerEvent::EVENT_BUFFERING_UPDATE) == refMap_.end()) {
530         MEDIA_LOGW("can not find buffering update callback!");
531         return;
532     }
533 
534     int32_t value = 0;
535     int32_t bufferingType = -1;
536     if (infoBody.ContainKey(std::string(PlayerKeys::PLAYER_BUFFERING_START))) {
537         bufferingType = BUFFERING_START;
538         (void)infoBody.GetIntValue(std::string(PlayerKeys::PLAYER_BUFFERING_START), value);
539     } else if (infoBody.ContainKey(std::string(PlayerKeys::PLAYER_BUFFERING_END))) {
540         bufferingType = BUFFERING_END;
541         (void)infoBody.GetIntValue(std::string(PlayerKeys::PLAYER_BUFFERING_END), value);
542     } else if (infoBody.ContainKey(std::string(PlayerKeys::PLAYER_BUFFERING_PERCENT))) {
543         bufferingType = BUFFERING_PERCENT;
544         (void)infoBody.GetIntValue(std::string(PlayerKeys::PLAYER_BUFFERING_PERCENT), value);
545     } else if (infoBody.ContainKey(std::string(PlayerKeys::PLAYER_CACHED_DURATION))) {
546         bufferingType = CACHED_DURATION;
547         (void)infoBody.GetIntValue(std::string(PlayerKeys::PLAYER_CACHED_DURATION), value);
548     } else {
549         return;
550     }
551 
552     MEDIA_LOGI("OnBufferingUpdateCb is called, buffering type: %{public}d value: %{public}d", bufferingType, value);
553     NapiCallback::IntVec *cb = new(std::nothrow) NapiCallback::IntVec();
554     CHECK_AND_RETURN_LOG(cb != nullptr, "failed to new IntVec");
555 
556     cb->callback = refMap_.at(AVPlayerEvent::EVENT_BUFFERING_UPDATE);
557     cb->callbackName = AVPlayerEvent::EVENT_BUFFERING_UPDATE;
558     cb->valueVec.push_back(bufferingType);
559     cb->valueVec.push_back(value);
560     NapiCallback::CompleteCallback(env_, cb);
561 }
562 
OnMessageCb(int32_t extra,const Format & infoBody) const563 void AVPlayerCallback::OnMessageCb(int32_t extra, const Format &infoBody) const
564 {
565     CHECK_AND_RETURN_LOG(isloaded_.load(), "current source is unready");
566     MEDIA_LOGI("OnMessageCb is called, extra: %{public}d", extra);
567     if (extra == PlayerMessageType::PLAYER_INFO_VIDEO_RENDERING_START) {
568         AVPlayerCallback::OnStartRenderFrameCb();
569     }
570 }
571 
OnStartRenderFrameCb() const572 void AVPlayerCallback::OnStartRenderFrameCb() const
573 {
574     MEDIA_LOGI("OnStartRenderFrameCb is called");
575     CHECK_AND_RETURN_LOG(isloaded_.load(), "current source is unready");
576     if (refMap_.find(AVPlayerEvent::EVENT_START_RENDER_FRAME) == refMap_.end()) {
577         MEDIA_LOGW("can not find start render callback!");
578         return;
579     }
580 
581     NapiCallback::Base *cb = new(std::nothrow) NapiCallback::Base();
582     CHECK_AND_RETURN_LOG(cb != nullptr, "failed to new Base");
583 
584     cb->callback = refMap_.at(AVPlayerEvent::EVENT_START_RENDER_FRAME);
585     cb->callbackName = AVPlayerEvent::EVENT_START_RENDER_FRAME;
586     NapiCallback::CompleteCallback(env_, cb);
587 }
588 
OnVideoSizeChangedCb(const Format & infoBody)589 void AVPlayerCallback::OnVideoSizeChangedCb(const Format &infoBody)
590 {
591     CHECK_AND_RETURN_LOG(isloaded_.load(), "current source is unready");
592     int32_t width = 0;
593     int32_t height = 0;
594     (void)infoBody.GetIntValue(PlayerKeys::PLAYER_WIDTH, width);
595     (void)infoBody.GetIntValue(PlayerKeys::PLAYER_HEIGHT, height);
596     MEDIA_LOGI("OnVideoSizeChangedCb is called, width = %{public}d, height = %{public}d", width, height);
597 
598     if (listener_ != nullptr) {
599         listener_->NotifyVideoSize(width, height);
600     }
601 
602     if (refMap_.find(AVPlayerEvent::EVENT_VIDEO_SIZE_CHANGE) == refMap_.end()) {
603         MEDIA_LOGW("can not find video size changed callback!");
604         return;
605     }
606     NapiCallback::IntVec *cb = new(std::nothrow) NapiCallback::IntVec();
607     CHECK_AND_RETURN_LOG(cb != nullptr, "failed to new IntVec");
608 
609     cb->callback = refMap_.at(AVPlayerEvent::EVENT_VIDEO_SIZE_CHANGE);
610     cb->callbackName = AVPlayerEvent::EVENT_VIDEO_SIZE_CHANGE;
611     cb->valueVec.push_back(width);
612     cb->valueVec.push_back(height);
613     NapiCallback::CompleteCallback(env_, cb);
614 }
615 
OnAudioInterruptCb(const Format & infoBody) const616 void AVPlayerCallback::OnAudioInterruptCb(const Format &infoBody) const
617 {
618     CHECK_AND_RETURN_LOG(isloaded_.load(), "current source is unready");
619     if (refMap_.find(AVPlayerEvent::EVENT_AUDIO_INTERRUPT) == refMap_.end()) {
620         MEDIA_LOGW("can not find audio interrupt callback!");
621         return;
622     }
623 
624     NapiCallback::PropertyInt *cb = new(std::nothrow) NapiCallback::PropertyInt();
625     CHECK_AND_RETURN_LOG(cb != nullptr, "failed to new PropertyInt");
626 
627     cb->callback = refMap_.at(AVPlayerEvent::EVENT_AUDIO_INTERRUPT);
628     cb->callbackName = AVPlayerEvent::EVENT_AUDIO_INTERRUPT;
629     int32_t eventType = 0;
630     int32_t forceType = 0;
631     int32_t hintType = 0;
632     (void)infoBody.GetIntValue(PlayerKeys::AUDIO_INTERRUPT_TYPE, eventType);
633     (void)infoBody.GetIntValue(PlayerKeys::AUDIO_INTERRUPT_FORCE, forceType);
634     (void)infoBody.GetIntValue(PlayerKeys::AUDIO_INTERRUPT_HINT, hintType);
635     MEDIA_LOGI("OnAudioInterruptCb is called, eventType = %{public}d, forceType = %{public}d, hintType = %{public}d",
636         eventType, forceType, hintType);
637     // ohos.multimedia.audio.d.ts interface InterruptEvent
638     cb->valueMap["eventType"] = eventType;
639     cb->valueMap["forceType"] = forceType;
640     cb->valueMap["hintType"] = hintType;
641     NapiCallback::CompleteCallback(env_, cb);
642 }
643 
OnBitRateCollectedCb(const Format & infoBody) const644 void AVPlayerCallback::OnBitRateCollectedCb(const Format &infoBody) const
645 {
646     CHECK_AND_RETURN_LOG(isloaded_.load(), "current source is unready");
647     if (refMap_.find(AVPlayerEvent::EVENT_AVAILABLE_BITRATES) == refMap_.end()) {
648         MEDIA_LOGW("can not find bitrate collected callback!");
649         return;
650     }
651 
652     std::vector<int32_t> bitrateVec;
653     if (infoBody.ContainKey(std::string(PlayerKeys::PLAYER_BITRATE))) {
654         uint8_t *addr = nullptr;
655         size_t size  = 0;
656         infoBody.GetBuffer(std::string(PlayerKeys::PLAYER_BITRATE), &addr, size);
657         CHECK_AND_RETURN_LOG(addr != nullptr, "bitrate addr is nullptr");
658 
659         MEDIA_LOGI("bitrate size = %{public}zu", size / sizeof(uint32_t));
660         while (size > 0) {
661             if (size < sizeof(uint32_t)) {
662                 break;
663             }
664 
665             uint32_t bitrate = *(static_cast<uint32_t *>(static_cast<void *>(addr)));
666             MEDIA_LOGI("bitrate = %{public}u", bitrate);
667             addr += sizeof(uint32_t);
668             size -= sizeof(uint32_t);
669             bitrateVec.push_back(static_cast<int32_t>(bitrate));
670         }
671     }
672 
673     NapiCallback::IntArray *cb = new(std::nothrow) NapiCallback::IntArray();
674     CHECK_AND_RETURN_LOG(cb != nullptr, "failed to new IntArray");
675 
676     cb->callback = refMap_.at(AVPlayerEvent::EVENT_AVAILABLE_BITRATES);
677     cb->callbackName = AVPlayerEvent::EVENT_AVAILABLE_BITRATES;
678     cb->valueVec = bitrateVec;
679     NapiCallback::CompleteCallback(env_, cb);
680 }
681 
OnEosCb(int32_t isLooping) const682 void AVPlayerCallback::OnEosCb(int32_t isLooping) const
683 {
684     CHECK_AND_RETURN_LOG(isloaded_.load(), "current source is unready");
685     MEDIA_LOGI("OnEndOfStream is called, isloop: %{public}d", isLooping);
686     if (refMap_.find(AVPlayerEvent::EVENT_END_OF_STREAM) == refMap_.end()) {
687         MEDIA_LOGW("can not find EndOfStream callback!");
688         return;
689     }
690 
691     NapiCallback::Base *cb = new(std::nothrow) NapiCallback::Base();
692     CHECK_AND_RETURN_LOG(cb != nullptr, "failed to new Base");
693 
694     cb->callback = refMap_.at(AVPlayerEvent::EVENT_END_OF_STREAM);
695     cb->callbackName = AVPlayerEvent::EVENT_END_OF_STREAM;
696     NapiCallback::CompleteCallback(env_, cb);
697 }
698 
SaveCallbackReference(const std::string & name,std::weak_ptr<AutoRef> ref)699 void AVPlayerCallback::SaveCallbackReference(const std::string &name, std::weak_ptr<AutoRef> ref)
700 {
701     std::lock_guard<std::mutex> lock(mutex_);
702     refMap_[name] = ref;
703 }
704 
ClearCallbackReference()705 void AVPlayerCallback::ClearCallbackReference()
706 {
707     std::lock_guard<std::mutex> lock(mutex_);
708     refMap_.clear();
709 }
710 
ClearCallbackReference(const std::string & name)711 void AVPlayerCallback::ClearCallbackReference(const std::string &name)
712 {
713     std::lock_guard<std::mutex> lock(mutex_);
714     refMap_.erase(name);
715 }
716 
Start()717 void AVPlayerCallback::Start()
718 {
719     isloaded_ = true;
720 }
721 
Pause()722 void AVPlayerCallback::Pause()
723 {
724     isloaded_ = false;
725 }
726 
Release()727 void AVPlayerCallback::Release()
728 {
729     std::lock_guard<std::mutex> lock(mutex_);
730 
731     Format infoBody;
732     AVPlayerCallback::OnStateChangeCb(PlayerStates::PLAYER_RELEASED, infoBody);
733     listener_ = nullptr;
734 }
735 } // namespace Media
736 } // namespace OHOS