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 "core/components/video/resource/player.h"
17
18 #include <iomanip>
19 #include <sstream>
20
21 #include "base/log/log.h"
22
23 namespace OHOS::Ace {
24
25 const char PLAYER_PARAM_WIDTH[] = "width";
26 const char PLAYER_PARAM_HEIGHT[] = "height";
27 const char PLAYER_PARAM_DURATION[] = "duration";
28 const char PLAYER_PARAM_CURRENTPOS[] = "currentpos";
29 const char PLAYER_PARAM_ISPLAYING[] = "isplaying";
30 const char PLAYER_PARAM_SRC[] = "src";
31 const char PLAYER_PARAM_ISAUTOPLAY[] = "autoplay";
32 const char PLAYER_PARAM_ISMUTE[] = "mute";
33 const char PLAYER_PARAM_TEXTURE[] = "texture";
34 const char PLAYER_PARAM_NEEDFRESHFORCE[] = "needRefreshForce";
35 const char PLAYER_PARAM_LOOP[] = "loop";
36 const char PLAYER_PARAM_SEEKMODE[] = "seekMode";
37 const char PLAYER_PARAM_ISTEXTURE[] = "isTexture";
38
39 const char PLAYER_METHOD_INIT[] = "init";
40 const char PLAYER_METHOD_GETPOSITION[] = "getposition";
41 const char PLAYER_METHOD_START[] = "start";
42 const char PLAYER_METHOD_PAUSE[] = "pause";
43 const char PLAYER_METHOD_SEEKTO[] = "seekto";
44 const char PLAYER_METHOD_STOP[] = "stop";
45 const char PLAYER_METHOD_SETVOLUME[] = "setvolume";
46 const char PLAYER_METHOD_FULLSCREEN[] = "fullscreen";
47 const char PLAYER_METHOD_ENABLE_LOOPING[] = "enablelooping";
48 const char PLAYER_METHOD_SETSPEED[] = "setspeed";
49 const char PLAYER_METHOD_SETDIRECTION[] = "setdirection";
50 const char PLAYER_METHOD_SETLANDSCAPE[] = "setlandscape";
51 const char PLAYER_METHOD_SETSURFACE[] = "setsurface";
52 const char PLAYER_METHOD_UPDATERESOURCE[] = "updateresource";
53
54 const char PLAYER_EVENT_PREPARED[] = "prepared";
55 const char PLAYER_EVENT_COMPLETION[] = "completion";
56 const char PLAYER_EVENT_SEEKCOMPLETE[] = "seekcomplete";
57 const char PLAYER_EVENT_ONPLAYSTATUS[] = "onplaystatus";
58 const char PLAYER_EVENT_ONGETCURRENTTIME[] = "ongetcurrenttime";
59
60 const char PLAYER_ERROR_CODE_CREATEFAIL[] = "error_video_000001";
61 const char PLAYER_ERROR_MSG_CREATEFAIL[] = "Create player failed.";
62 const char PLAYER_ERROR_CODE_FILEINVALID[] = "error_video_000002";
63 const char PLAYER_ERROR_MSG_FILEINVALID[] = "File invalid.";
64 const int32_t DURATION_THOUSAND = 1000;
65
Create(const std::function<void (int64_t)> & onCreate)66 void Player::Create(const std::function<void(int64_t)>& onCreate)
67 {
68 scheduler_ = SchedulerBuilder::Build(
69 [weak = WeakClaim(this)](uint64_t timestamp) {
70 auto player = weak.Upgrade();
71 if (player) {
72 player->OnTick(timestamp);
73 }
74 },
75 context_);
76 auto context = context_.Upgrade();
77 if (!context) {
78 LOGE("fail to get context to create player");
79 return;
80 }
81
82 auto platformTaskExecutor = SingleTaskExecutor::Make(context->GetTaskExecutor(), TaskExecutor::TaskType::PLATFORM);
83
84 platformTaskExecutor.PostTask([weak = WeakClaim(this), onCreate] {
85 auto player = weak.Upgrade();
86 if (player) {
87 player->CreatePlayer(onCreate);
88 }
89 }, "ArkUIVideoCreatePlayer");
90 }
91
CreatePlayer(const std::function<void (int64_t)> & onCreate)92 void Player::CreatePlayer(const std::function<void(int64_t)>& onCreate)
93 {
94 auto context = context_.Upgrade();
95 if (!context) {
96 return;
97 }
98 auto resRegister = context->GetPlatformResRegister();
99 if (resRegister == nullptr) {
100 return;
101 }
102 std::stringstream paramStream;
103 paramStream << PLAYER_PARAM_TEXTURE << PARAM_EQUALS << textureId_;
104 std::string param = paramStream.str();
105 id_ = resRegister->CreateResource(type_, param);
106 if (id_ == INVALID_ID) {
107 if (onError_) {
108 onError_(PLAYER_ERROR_CODE_CREATEFAIL, PLAYER_ERROR_MSG_CREATEFAIL);
109 }
110 return;
111 }
112 hash_ = MakeResourceHash();
113 resRegister->RegisterEvent(
114 MakeEventHash(PLAYER_EVENT_PREPARED), [weak = WeakClaim(this)](const std::string& param) {
115 auto player = weak.Upgrade();
116 if (player) {
117 player->OnPrepared(param);
118 }
119 });
120 resRegister->RegisterEvent(
121 MakeEventHash(PLAYER_EVENT_COMPLETION), [weak = WeakClaim(this)](const std::string& param) {
122 auto player = weak.Upgrade();
123 if (player) {
124 player->OnCompletion(param);
125 }
126 });
127 resRegister->RegisterEvent(
128 MakeEventHash(PLAYER_EVENT_SEEKCOMPLETE), [weak = WeakClaim(this)](const std::string& param) {
129 auto player = weak.Upgrade();
130 if (player) {
131 player->OnSeekComplete(param);
132 }
133 });
134 resRegister->RegisterEvent(
135 MakeEventHash(PLAYER_EVENT_ONPLAYSTATUS), [weak = WeakClaim(this)](const std::string& param) {
136 auto player = weak.Upgrade();
137 if (player) {
138 player->OnPlayStatus(param);
139 }
140 });
141 resRegister->RegisterEvent(
142 MakeEventHash(PLAYER_EVENT_ONGETCURRENTTIME), [weak = WeakClaim(this)](const std::string& param) {
143 auto player = weak.Upgrade();
144 if (player) {
145 player->OnTimeGetted(param);
146 }
147 });
148 if (onCreate) {
149 onCreate(id_);
150 }
151 InitPlay();
152 }
153
InitPlay()154 void Player::InitPlay()
155 {
156 std::stringstream paramStream;
157 paramStream << PLAYER_PARAM_SRC << PARAM_EQUALS << src_ << PARAM_AND << PLAYER_PARAM_ISMUTE << PARAM_EQUALS
158 << (isMute_ ? 1 : 0) << PARAM_AND << PLAYER_PARAM_ISAUTOPLAY << PARAM_EQUALS << (isAutoPlay_ ? 1 : 0);
159
160 std::string param = paramStream.str();
161 CallResRegisterMethod(MakeMethodHash(PLAYER_METHOD_INIT), param, [weak = WeakClaim(this)](std::string& result) {
162 auto player = weak.Upgrade();
163 if (player) {
164 if (!player->IsResultSuccess(result)) {
165 player->OnError(PLAYER_ERROR_CODE_FILEINVALID, PLAYER_ERROR_MSG_FILEINVALID);
166 }
167 }
168 });
169
170 isInit_ = true;
171 }
172
SetSource(const std::string & src)173 void Player::SetSource(const std::string& src)
174 {
175 src_ = src;
176 if (isInit_) {
177 std::stringstream paramStream;
178 paramStream << PLAYER_PARAM_SRC << PARAM_EQUALS << src_;
179 std::string param = paramStream.str();
180 CallResRegisterMethod(MakeMethodHash(PLAYER_METHOD_UPDATERESOURCE), param,
181 [weak = WeakClaim(this)](std::string& result) {
182 auto player = weak.Upgrade();
183 if (player) {
184 if (!player->IsResultSuccess(result)) {
185 player->OnError(PLAYER_ERROR_CODE_FILEINVALID, PLAYER_ERROR_MSG_FILEINVALID);
186 }
187 }
188 });
189 }
190 }
191
SetSurfaceId(int64_t id,bool isTexture)192 void Player::SetSurfaceId(int64_t id, bool isTexture)
193 {
194 textureId_ = id;
195 std::stringstream paramStream;
196 paramStream << PARAM_VALUE << PARAM_EQUALS << textureId_ << PARAM_AND
197 << PLAYER_PARAM_ISTEXTURE << PARAM_EQUALS << (isTexture ? "1" : "0");
198 std::string param = paramStream.str();
199 CallResRegisterMethod(MakeMethodHash(PLAYER_METHOD_SETSURFACE), param);
200 }
201
OnPrepared(const std::string & param)202 void Player::OnPrepared(const std::string& param)
203 {
204 currentPos_ = 0;
205 width_ = static_cast<uint32_t>(GetIntParam(param, PLAYER_PARAM_WIDTH));
206 height_ = static_cast<uint32_t>(GetIntParam(param, PLAYER_PARAM_HEIGHT));
207 duration_ = static_cast<uint32_t>(GetIntParam(param, PLAYER_PARAM_DURATION) / DURATION_THOUSAND);
208 isPlaying_ = GetIntParam(param, PLAYER_PARAM_ISPLAYING) == 1;
209 isNeedFreshForce_ = GetIntParam(param, PLAYER_PARAM_NEEDFRESHFORCE) == 1;
210 isPrepared_ = true;
211 if (width_ == 0 || height_ == 0 || duration_ == 0) {
212 if (onError_) {
213 onError_(PLAYER_ERROR_CODE_FILEINVALID, PLAYER_ERROR_MSG_FILEINVALID);
214 }
215 return;
216 }
217 getCurrentPosMethod_ = MakeMethodHash(PLAYER_METHOD_GETPOSITION);
218 playMethod_ = MakeMethodHash(PLAYER_METHOD_START);
219 pauseMethod_ = MakeMethodHash(PLAYER_METHOD_PAUSE);
220 seekMethod_ = MakeMethodHash(PLAYER_METHOD_SEEKTO);
221 stopMethod_ = MakeMethodHash(PLAYER_METHOD_STOP);
222 setVolumeMethod_ = MakeMethodHash(PLAYER_METHOD_SETVOLUME);
223 fullscreenMethod_ = MakeMethodHash(PLAYER_METHOD_FULLSCREEN);
224 enableloopingMethod_ = MakeMethodHash(PLAYER_METHOD_ENABLE_LOOPING);
225 setSpeedMethod_ = MakeMethodHash(PLAYER_METHOD_SETSPEED);
226 setDirectionMethod_ = MakeMethodHash(PLAYER_METHOD_SETDIRECTION);
227 setLandsacpeMethod_ = MakeMethodHash(PLAYER_METHOD_SETLANDSCAPE);
228
229 if (isPlaying_) {
230 SetTickActive(true);
231 }
232
233 for (const auto& listener : onPreparedListener_) {
234 listener(width_, height_, isPlaying_, duration_, currentPos_, true);
235 }
236 }
237
OnCompletion(const std::string & param)238 void Player::OnCompletion(const std::string& param)
239 {
240 isPlaying_ = false;
241 currentPos_ = duration_;
242 SetTickActive(isPlaying_);
243 for (const auto& listener : onCompletionListener_) {
244 listener();
245 }
246 }
247
OnSeekComplete(const std::string & param)248 void Player::OnSeekComplete(const std::string& param)
249 {
250 currentPos_ = static_cast<uint32_t>(GetIntParam(param, PLAYER_PARAM_CURRENTPOS));
251 if (!onCurrentPosListener_.empty()) {
252 onCurrentPosListener_.back()(currentPos_);
253 }
254 }
255
OnPlayStatus(const std::string & param)256 void Player::OnPlayStatus(const std::string& param)
257 {
258 isPlaying_ = GetIntParam(param, PLAYER_PARAM_ISPLAYING) == 1;
259 SetTickActive(isPlaying_);
260 for (const auto& listener : onPlayStatusListener_) {
261 listener(isPlaying_);
262 }
263 }
264
SetTickActive(bool isActive)265 void Player::SetTickActive(bool isActive)
266 {
267 auto context = context_.Upgrade();
268 if (!context) {
269 LOGE("fail to get context to set tick active");
270 return;
271 }
272
273 auto uiTaskExecutor = SingleTaskExecutor::Make(context->GetTaskExecutor(), TaskExecutor::TaskType::UI);
274 uiTaskExecutor.PostSyncTask(
275 [this, isActive] {
276 if (scheduler_) {
277 if (isActive) {
278 scheduler_->Start();
279 } else {
280 scheduler_->Stop();
281 }
282 }
283 },
284 "ArkUIVideoSetTickActive");
285 }
286
OnTick(uint64_t timeStamp)287 void Player::OnTick(uint64_t timeStamp)
288 {
289 timeStamp_ += timeStamp;
290 if (isNeedFreshForce_) {
291 if (!onRefreshRenderListener_.empty()) {
292 onRefreshRenderListener_.back()();
293 }
294 }
295 if (timeStamp_ > FREAUENCY_GET_CURRENT_TIME) {
296 GetCurrentTime();
297 timeStamp_ -= FREAUENCY_GET_CURRENT_TIME;
298 }
299 }
300
GetCurrentTime()301 void Player::GetCurrentTime()
302 {
303 CallResRegisterMethod(getCurrentPosMethod_, PARAM_NONE);
304 }
305
OnTimeGetted(const std::string & result)306 void Player::OnTimeGetted(const std::string& result)
307 {
308 currentPos_ = static_cast<uint32_t>(GetIntParam(result, PLAYER_PARAM_CURRENTPOS));
309 if (!onCurrentPosListener_.empty()) {
310 onCurrentPosListener_.back()(currentPos_);
311 }
312 }
313
Start()314 void Player::Start()
315 {
316 CallResRegisterMethod(playMethod_, PARAM_NONE, [weak = WeakClaim(this)](std::string& result) {
317 auto player = weak.Upgrade();
318 if (player) {
319 player->OnStarted();
320 }
321 });
322 }
323
OnStarted()324 void Player::OnStarted()
325 {
326 isPlaying_ = true;
327 SetTickActive(isPlaying_);
328
329 for (const auto& listener : onPlayStatusListener_) {
330 listener(isPlaying_);
331 }
332 }
333
Pause()334 void Player::Pause()
335 {
336 CallResRegisterMethod(pauseMethod_, PARAM_NONE, [weak = WeakClaim(this)](std::string& result) {
337 auto player = weak.Upgrade();
338 if (player) {
339 player->OnPaused();
340 }
341 });
342 }
343
OnPaused()344 void Player::OnPaused()
345 {
346 isPlaying_ = false;
347 SetTickActive(isPlaying_);
348
349 for (const auto& listener : onPlayStatusListener_) {
350 listener(isPlaying_);
351 }
352 }
353
Stop()354 void Player::Stop()
355 {
356 if (scheduler_) {
357 scheduler_->Stop();
358 }
359
360 CallResRegisterMethod(stopMethod_, PARAM_NONE, [weak = WeakClaim(this)](std::string& result) {
361 LOGI("callback play OnStop.");
362 auto player = weak.Upgrade();
363 if (player) {
364 player->OnStop();
365 }
366 });
367 }
368
OnStop()369 void Player::OnStop()
370 {
371 isPlaying_ = false;
372 currentPos_ = 0;
373 SetTickActive(isPlaying_);
374
375 for (const auto& listener : onPlayStatusListener_) {
376 listener(isPlaying_);
377 }
378 }
379
UnregisterEvent()380 void Player::UnregisterEvent()
381 {
382 auto context = context_.Upgrade();
383 if (!context) {
384 LOGE("fail to get context");
385 return;
386 }
387 auto resRegister = context->GetPlatformResRegister();
388 if (resRegister == nullptr) {
389 return;
390 }
391 resRegister->UnregisterEvent(MakeEventHash(PLAYER_EVENT_PREPARED));
392 resRegister->UnregisterEvent(MakeEventHash(PLAYER_EVENT_COMPLETION));
393 resRegister->UnregisterEvent(MakeEventHash(PLAYER_EVENT_SEEKCOMPLETE));
394 resRegister->UnregisterEvent(MakeEventHash(PLAYER_EVENT_ONPLAYSTATUS));
395 }
396
EnterFullScreen()397 void Player::EnterFullScreen()
398 {
399 CallResRegisterMethod(fullscreenMethod_, PARAM_NONE);
400 }
401
SeekTo(uint32_t pos)402 void Player::SeekTo(uint32_t pos)
403 {
404 std::stringstream paramStream;
405 paramStream << PARAM_VALUE << PARAM_EQUALS << pos;
406
407 std::string param = paramStream.str();
408 CallResRegisterMethod(seekMethod_, param);
409 }
410
SeekTo(uint32_t pos,uint32_t mode)411 void Player::SeekTo(uint32_t pos, uint32_t mode)
412 {
413 std::stringstream paramStream;
414 paramStream << PARAM_VALUE << PARAM_EQUALS << pos << PARAM_AND <<
415 PLAYER_PARAM_SEEKMODE << PARAM_EQUALS << mode;
416
417 std::string param = paramStream.str();
418 CallResRegisterMethod(seekMethod_, param);
419 }
420
SetVolume(float volume)421 void Player::SetVolume(float volume)
422 {
423 std::stringstream paramStream;
424 paramStream << PARAM_VALUE << PARAM_EQUALS << volume;
425
426 std::string param = paramStream.str();
427 CallResRegisterMethod(setVolumeMethod_, param);
428 }
429
AddPreparedListener(PreparedListener && listener)430 void Player::AddPreparedListener(PreparedListener&& listener)
431 {
432 auto context = context_.Upgrade();
433 if (!context) {
434 LOGE("fail to get context");
435 return;
436 }
437
438 auto platformTaskExecutor = SingleTaskExecutor::Make(context->GetTaskExecutor(), TaskExecutor::TaskType::PLATFORM);
439 platformTaskExecutor.PostTask(
440 [weak = WeakClaim(this), listener = std::move(listener)]() mutable {
441 auto player = weak.Upgrade();
442 if (player) {
443 player->OnAddPreparedListener(std::move(listener));
444 }
445 },
446 "ArkUIVideoAddPreparedListener");
447 }
448
OnAddPreparedListener(PreparedListener && listener)449 void Player::OnAddPreparedListener(PreparedListener&& listener)
450 {
451 onPreparedListener_.push_back(std::move(listener));
452 if (isPrepared_) {
453 onPreparedListener_.back()(width_, height_, isPlaying_, duration_, currentPos_, false);
454 }
455 }
456
AddPlayStatusListener(PlayStatusListener && listener)457 void Player::AddPlayStatusListener(PlayStatusListener&& listener)
458 {
459 auto context = context_.Upgrade();
460 if (!context) {
461 LOGE("fail to get context");
462 return;
463 }
464
465 auto platformTaskExecutor = SingleTaskExecutor::Make(context->GetTaskExecutor(), TaskExecutor::TaskType::PLATFORM);
466 platformTaskExecutor.PostTask(
467 [weak = WeakClaim(this), listener = std::move(listener)]() mutable {
468 auto player = weak.Upgrade();
469 if (player) {
470 player->OnAddPlayStatusListener(std::move(listener));
471 }
472 },
473 "ArkUIVideoAddPlayStatusListener");
474 }
475
OnAddPlayStatusListener(PlayStatusListener && listener)476 void Player::OnAddPlayStatusListener(PlayStatusListener&& listener)
477 {
478 onPlayStatusListener_.push_back(std::move(listener));
479 }
480
AddCurrentPosListener(CurrentPosListener && listener)481 void Player::AddCurrentPosListener(CurrentPosListener&& listener)
482 {
483 auto context = context_.Upgrade();
484 if (!context) {
485 LOGE("fail to get context");
486 return;
487 }
488
489 auto platformTaskExecutor = SingleTaskExecutor::Make(context->GetTaskExecutor(), TaskExecutor::TaskType::PLATFORM);
490 platformTaskExecutor.PostTask(
491 [weak = WeakClaim(this), listener = std::move(listener)]() mutable {
492 auto player = weak.Upgrade();
493 if (player) {
494 player->OnAddCurrentPosListener(std::move(listener));
495 }
496 },
497 "ArkUIVideoAddCurrentPosListener");
498 }
499
OnAddCurrentPosListener(CurrentPosListener && listener)500 void Player::OnAddCurrentPosListener(CurrentPosListener&& listener)
501 {
502 onCurrentPosListener_.push_back(std::move(listener));
503 }
504
AddCompletionListener(CompletionListener && listener)505 void Player::AddCompletionListener(CompletionListener&& listener)
506 {
507 auto context = context_.Upgrade();
508 if (!context) {
509 LOGE("fail to get context");
510 return;
511 }
512
513 auto platformTaskExecutor = SingleTaskExecutor::Make(context->GetTaskExecutor(), TaskExecutor::TaskType::PLATFORM);
514 platformTaskExecutor.PostTask(
515 [weak = WeakClaim(this), listener = std::move(listener)]() mutable {
516 auto player = weak.Upgrade();
517 if (player) {
518 player->OnAddCompletionListener(std::move(listener));
519 }
520 },
521 "ArkUIVideoAddCompletionListener");
522 }
523
OnAddCompletionListener(CompletionListener && listener)524 void Player::OnAddCompletionListener(CompletionListener&& listener)
525 {
526 onCompletionListener_.push_back(std::move(listener));
527 }
528
PopListener()529 void Player::PopListener()
530 {
531 onRefreshRenderListener_.pop_back();
532 auto context = context_.Upgrade();
533 if (!context) {
534 LOGE("fail to get context");
535 return;
536 }
537
538 auto platformTaskExecutor = SingleTaskExecutor::Make(context->GetTaskExecutor(), TaskExecutor::TaskType::PLATFORM);
539 platformTaskExecutor.PostTask(
540 [weak = WeakClaim(this)] {
541 auto player = weak.Upgrade();
542 if (player) {
543 player->OnPopListener();
544 }
545 },
546 "ArkUIVideoPopListener");
547 }
548
AddRefreshRenderListener(RefreshRenderListener && listener)549 void Player::AddRefreshRenderListener(RefreshRenderListener&& listener)
550 {
551 onRefreshRenderListener_.push_back(std::move(listener));
552 }
553
EnableLooping(bool loop)554 void Player::EnableLooping(bool loop)
555 {
556 std::stringstream paramStream;
557 paramStream << PLAYER_PARAM_LOOP << PARAM_EQUALS << (loop ? "1" : "0");
558
559 std::string param = paramStream.str();
560 CallResRegisterMethod(enableloopingMethod_, param);
561 }
562
SetSpeed(float speed)563 void Player::SetSpeed(float speed)
564 {
565 std::stringstream paramStream;
566 paramStream << PARAM_VALUE << PARAM_EQUALS << speed;
567
568 std::string param = paramStream.str();
569 CallResRegisterMethod(setSpeedMethod_, param);
570 }
571
SetDirection(std::string & direction)572 void Player::SetDirection(std::string& direction)
573 {
574 std::stringstream paramStream;
575 paramStream << PARAM_VALUE << PARAM_EQUALS << direction;
576
577 std::string param = paramStream.str();
578 CallResRegisterMethod(setDirectionMethod_, param);
579 }
580
SetLandscape()581 void Player::SetLandscape()
582 {
583 CallResRegisterMethod(setLandsacpeMethod_, PARAM_NONE);
584 }
585
OnPopListener()586 void Player::OnPopListener()
587 {
588 onPreparedListener_.pop_back();
589 onPlayStatusListener_.pop_back();
590 onCurrentPosListener_.pop_back();
591 onCompletionListener_.pop_back();
592 if (!onCurrentPosListener_.empty()) {
593 onCurrentPosListener_.back()(currentPos_);
594 }
595 }
596
SetFullScreenChange(bool isFullScreen)597 void Player::SetFullScreenChange(bool isFullScreen)
598 {
599 std::stringstream paramStream;
600 paramStream << PARAM_VALUE << PARAM_EQUALS << (isFullScreen ? "1" : "0");
601
602 std::string param = paramStream.str();
603 CallResRegisterMethod(fullscreenMethod_, param);
604 }
605
Release(const std::function<void (bool)> & onRelease)606 void Player::Release(const std::function<void(bool)>& onRelease)
607 {
608 // The destructor will be executed at platform thread, so destroy scheduler at here.
609 if (scheduler_) {
610 scheduler_.Reset();
611 }
612
613 auto context = context_.Upgrade();
614 if (!context) {
615 LOGE("fail to get context");
616 return;
617 }
618 auto platformTaskExecutor = SingleTaskExecutor::Make(context->GetTaskExecutor(), TaskExecutor::TaskType::PLATFORM);
619 if (platformTaskExecutor.IsRunOnCurrentThread()) {
620 UnregisterEvent();
621 } else {
622 platformTaskExecutor.PostTask(
623 [weak = WeakClaim(this)] {
624 auto player = weak.Upgrade();
625 if (player) {
626 player->UnregisterEvent();
627 }
628 },
629 "ArkUIVideoPlayerUnregisterEvent");
630 }
631
632 Resource::Release(onRelease);
633
634 isInit_ = false;
635 }
636 } // namespace OHOS::Ace