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