• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2023 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/video_element.h"
17 
18 #include <algorithm>
19 #include <iomanip>
20 #include <regex>
21 #include <sstream>
22 #include <string>
23 #include <sys/stat.h>
24 #include <sys/types.h>
25 
26 #include "base/i18n/localization.h"
27 #include "base/image/file_uri_helper.h"
28 #include "base/json/json_util.h"
29 #include "base/log/dump_log.h"
30 #include "base/log/log.h"
31 #include "base/resource/asset_manager.h"
32 #include "base/resource/internal_resource.h"
33 #include "base/utils/system_properties.h"
34 #include "base/utils/utils.h"
35 #include "core/common/container_scope.h"
36 #include "core/components/align/align_component.h"
37 #include "core/components/box/box_component.h"
38 #include "core/components/button/button_component.h"
39 #include "core/components/flex/flex_component.h"
40 #include "core/components/flex/flex_item_component.h"
41 #include "core/components/gesture_listener/gesture_listener_component.h"
42 #include "core/components/image/image_component.h"
43 #include "core/components/padding/padding_component.h"
44 #include "core/components/slider/slider_component.h"
45 #include "core/components/stage/stage_element.h"
46 #include "core/components/text/text_component.h"
47 #include "core/components/theme/resource_adapter.h"
48 #include "core/components/theme/theme_manager.h"
49 #include "core/components/video/render_texture.h"
50 #include "core/event/ace_event_helper.h"
51 #include "core/event/back_end_event_manager.h"
52 #include "core/pipeline/base/composed_component.h"
53 #include "core/pipeline/pipeline_context.h"
54 
55 #ifdef OHOS_STANDARD_SYSTEM
56 #include <securec.h>
57 
58 #include "display_type.h"
59 #include "surface.h"
60 
61 #ifdef ENABLE_ROSEN_BACKEND
62 #include "core/components/video/rosen_render_texture.h"
63 #endif
64 
65 #endif
66 
67 namespace OHOS::Ace {
68 namespace {
69 
70 const char* PLAY_LABEL = "play";
71 const char* PAUSE_LABEL = "pause";
72 const char* FULLSCREEN_LABEL = "fullscreen";
73 const char* EXIT_FULLSCREEN_LABEL = "exitFullscreen";
74 
75 #ifdef OHOS_STANDARD_SYSTEM
76 const char* SURFACE_STRIDE_ALIGNMENT = "8";
77 constexpr int32_t SURFACE_QUEUE_SIZE = 5;
78 constexpr uint32_t MEDIA_RESOURCE_MATCH_SIZE = 2;
79 const int32_t RAWFILE_PREFIX_LENGTH = strlen("resource://RAWFILE/");
80 const std::regex MEDIA_RES_ID_REGEX(R"(^resource://\w+/([0-9]+)\.\w+$)", std::regex::icase);
81 const std::regex MEDIA_APP_RES_ID_REGEX(R"(^resource://.*/([0-9]+)\.\w+$)", std::regex::icase);
82 #endif
83 constexpr float ILLEGAL_SPEED = 0.0f;
84 constexpr int32_t COMPATIBLE_VERSION = 5;
85 
86 #ifdef OHOS_STANDARD_SYSTEM
87 constexpr float SPEED_0_75_X = 0.75;
88 constexpr float SPEED_1_00_X = 1.00;
89 constexpr float SPEED_1_25_X = 1.25;
90 constexpr float SPEED_1_75_X = 1.75;
91 constexpr float SPEED_2_00_X = 2.00;
92 
ConvertToMediaSeekMode(SeekMode seekMode)93 OHOS::Media::PlayerSeekMode ConvertToMediaSeekMode(SeekMode seekMode)
94 {
95     OHOS::Media::PlayerSeekMode mode = OHOS::Media::SEEK_PREVIOUS_SYNC;
96     if (seekMode == SeekMode::SEEK_NEXT_SYNC) {
97         mode = OHOS::Media::SEEK_NEXT_SYNC;
98     } else if (seekMode == SeekMode::SEEK_CLOSEST_SYNC) {
99         mode = OHOS::Media::SEEK_CLOSEST_SYNC;
100     } else if (seekMode == SeekMode::SEEK_CLOSEST) {
101         mode = OHOS::Media::SEEK_CLOSEST;
102     }
103     return mode;
104 }
105 
ConvertToMediaPlaybackSpeed(float speed)106 OHOS::Media::PlaybackRateMode ConvertToMediaPlaybackSpeed(float speed)
107 {
108     OHOS::Media::PlaybackRateMode mode = OHOS::Media::SPEED_FORWARD_1_00_X;
109     if (NearEqual(speed, SPEED_0_75_X)) {
110         mode = OHOS::Media::PlaybackRateMode::SPEED_FORWARD_0_75_X;
111     } else if (NearEqual(speed, SPEED_1_00_X)) {
112         mode = OHOS::Media::PlaybackRateMode::SPEED_FORWARD_1_00_X;
113     } else if (NearEqual(speed, SPEED_1_25_X)) {
114         mode = OHOS::Media::PlaybackRateMode::SPEED_FORWARD_1_25_X;
115     } else if (NearEqual(speed, SPEED_1_75_X)) {
116         mode = OHOS::Media::PlaybackRateMode::SPEED_FORWARD_1_75_X;
117     } else if (NearEqual(speed, SPEED_2_00_X)) {
118         mode = OHOS::Media::PlaybackRateMode::SPEED_FORWARD_2_00_X;
119     } else {
120         LOGW("speed is not supported yet.");
121     }
122     return mode;
123 }
124 #endif
125 
126 } // namespace
127 
~VideoElement()128 VideoElement::~VideoElement()
129 {
130     if (!startBtnClickId_.IsEmpty()) {
131         BackEndEventManager<void()>::GetInstance().RemoveBackEndEvent(startBtnClickId_);
132     }
133 
134     if (!sliderMovedCallbackId_.IsEmpty()) {
135         BackEndEventManager<void(const std::string&)>::GetInstance().RemoveBackEndEvent(sliderMovedCallbackId_);
136     }
137 
138     if (!sliderMovingCallbackId_.IsEmpty()) {
139         BackEndEventManager<void(const std::string&)>::GetInstance().RemoveBackEndEvent(sliderMovingCallbackId_);
140     }
141 
142     if (!fullscreenBtnClickId_.IsEmpty()) {
143         BackEndEventManager<void()>::GetInstance().RemoveBackEndEvent(fullscreenBtnClickId_);
144     }
145 
146     if (!shieldId_.IsEmpty()) {
147         BackEndEventManager<void()>::GetInstance().RemoveBackEndEvent(startBtnClickId_);
148     }
149 
150     if (isMediaPlayerFullStatus_) {
151         ExitFullScreen();
152     }
153 
154     if (!isExternalResource_) {
155         if (isFullScreen_) {
156             ExitFullScreen();
157         }
158         UnSubscribeMultiModal();
159     } else {
160         if (player_) {
161             player_->PopListener();
162         }
163     }
164     ReleasePlatformResource();
165 #ifdef OHOS_STANDARD_SYSTEM
166     if (mediaPlayer_ != nullptr) {
167         mediaPlayer_->Release();
168     }
169     if (SystemProperties::GetExtSurfaceEnabled() && surfaceDelegate_) {
170         surfaceDelegate_->ReleaseSurface();
171     }
172 #endif
173 }
174 
PerformBuild()175 void VideoElement::PerformBuild()
176 {
177     RefPtr<VideoComponent> videoComponent = AceType::DynamicCast<VideoComponent>(component_);
178 
179     if (videoComponent == nullptr) {
180         return;
181     }
182     const auto& child = children_.empty() ? nullptr : children_.front();
183     UpdateChild(child, videoComponent->GetChild());
184 }
185 
InitStatus(const RefPtr<VideoComponent> & videoComponent)186 void VideoElement::InitStatus(const RefPtr<VideoComponent>& videoComponent)
187 {
188     imageFit_ = videoComponent->GetFit();
189     imagePosition_ = videoComponent->GetImagePosition();
190     needControls_ = videoComponent->NeedControls();
191     isAutoPlay_ = videoComponent->IsAutoPlay();
192     isMute_ = videoComponent->IsMute();
193     src_ = videoComponent->GetSrc();
194     poster_ = videoComponent->GetPoster();
195     posterImage_ = videoComponent->GetPosterImage();
196     isFullScreen_ = videoComponent->IsFullscreen();
197     direction_ = videoComponent->GetDirection();
198     startTime_ = videoComponent->GetStartTime();
199     isMediaPlayerFullStatus_ = videoComponent->GetMediaPlayerFullStatus();
200     if (isMediaPlayerFullStatus_) {
201         pastPlayingStatus_ = videoComponent->GetPastPlayingStatus();
202         if (startTime_ != 0) {
203             currentPos_ = startTime_;
204             IntTimeToText(currentPos_, currentPosText_);
205         }
206     }
207     if (isLoop_ != videoComponent->IsLoop()) {
208         isLoop_ = videoComponent->IsLoop();
209         EnableLooping(isLoop_);
210     }
211 
212     if (speed_ != videoComponent->GetSpeed()) {
213         speed_ = videoComponent->GetSpeed();
214         SetSpeed(speed_);
215     }
216 
217 #ifdef OHOS_STANDARD_SYSTEM
218     PreparePlayer();
219     if (isMediaPlayerFullStatus_) {
220         isExternalResource_ = true;
221     }
222 #endif
223 
224     if (!videoComponent->GetPlayer().Invalid() && !videoComponent->GetTexture().Invalid()) {
225         player_ = videoComponent->GetPlayer().Upgrade();
226         texture_ = videoComponent->GetTexture().Upgrade();
227 
228         if (player_ && texture_) {
229             isExternalResource_ = true;
230             videoComponent->SetPlayer(nullptr);
231             videoComponent->SetTexture(nullptr);
232             InitListener();
233         }
234     }
235 }
236 
237 #ifdef OHOS_STANDARD_SYSTEM
RegisterMediaPlayerEvent()238 void VideoElement::RegisterMediaPlayerEvent()
239 {
240     auto context = context_.Upgrade();
241     if (context == nullptr) {
242         LOGE("context is nullptr");
243         return;
244     }
245 
246     auto uiTaskExecutor = SingleTaskExecutor::Make(context->GetTaskExecutor(), TaskExecutor::TaskType::UI);
247     auto videoElement = WeakClaim(this);
248 
249     auto&& positionUpdatedEvent = [videoElement, uiTaskExecutor](uint32_t currentPos) {
250         uiTaskExecutor.PostSyncTask([&videoElement, currentPos] {
251             auto video = videoElement.Upgrade();
252             if (video != nullptr) {
253                 video->OnCurrentTimeChange(currentPos);
254             }
255         });
256     };
257 
258     auto&& stateChangedEvent = [videoElement, uiTaskExecutor](PlaybackStatus status) {
259         uiTaskExecutor.PostSyncTask([&videoElement, status] {
260             auto video = videoElement.Upgrade();
261             if (video) {
262                 video->OnPlayerStatus(status);
263             }
264         });
265     };
266 
267     auto&& errorEvent = [videoElement, uiTaskExecutor]() {
268         uiTaskExecutor.PostTask([&videoElement] {
269             auto video = videoElement.Upgrade();
270             if (video) {
271                 video->OnError("", "");
272             }
273         });
274     };
275 
276     auto&& resolutionChangeEvent = [videoElement, uiTaskExecutor]() {
277         uiTaskExecutor.PostSyncTask([&videoElement] {
278             auto video = videoElement.Upgrade();
279             if (video) {
280                 video->OnResolutionChange();
281             }
282         });
283     };
284 
285     mediaPlayerCallback_ = std::make_shared<MediaPlayerCallback>(ContainerScope::CurrentId());
286     mediaPlayerCallback_->SetPositionUpdatedEvent(positionUpdatedEvent);
287     mediaPlayerCallback_->SetStateChangedEvent(stateChangedEvent);
288     mediaPlayerCallback_->SetErrorEvent(errorEvent);
289     mediaPlayerCallback_->SetResolutionChangeEvent(resolutionChangeEvent);
290     mediaPlayer_->SetPlayerCallback(mediaPlayerCallback_);
291 }
292 
CreateMediaPlayer()293 void VideoElement::CreateMediaPlayer()
294 {
295     if (mediaPlayer_ != nullptr) {
296         return;
297     }
298 
299     mediaPlayer_ = OHOS::Media::PlayerFactory::CreatePlayer();
300     if (mediaPlayer_ == nullptr) {
301         LOGE("Create player failed");
302         return;
303     }
304 
305     PreparePlayer();
306 }
307 
PreparePlayer()308 void VideoElement::PreparePlayer()
309 {
310     SetVolume(isMute_ ? 0.0f : 1.0f);
311     CHECK_NULL_VOID(hasSrcChanged_);
312     CHECK_NULL_VOID(mediaPlayer_);
313     (void)mediaPlayer_->Reset();
314     std::string filePath = src_;
315 
316     int32_t fd = -1;
317     SetMediaSource(filePath, fd);
318 
319     if (fd >= 0) {
320         // get size of file.
321         struct stat statBuf;
322         auto statRes = fstat(fd, &statBuf);
323         if (statRes != 0) {
324             LOGE("get stat fail");
325             close(fd);
326             return;
327         }
328         auto size = statBuf.st_size;
329         if (mediaPlayer_->SetSource(fd, 0, size) != 0) {
330             LOGE("Player SetSource failed");
331             close(fd);
332             return;
333         }
334         close(fd);
335     }
336 
337     RegisterMediaPlayerEvent();
338 
339     sptr<Surface> producerSurface;
340     if (SystemProperties::GetExtSurfaceEnabled()) {
341         auto context = context_.Upgrade();
342         uint32_t windowId = 0;
343         if (context && !surfaceDelegate_) {
344             windowId = context->GetWindowId();
345             surfaceDelegate_ = new OHOS::SurfaceDelegate(windowId);
346             surfaceDelegate_->CreateSurface();
347             producerSurface = surfaceDelegate_->GetSurface();
348         }
349     } else {
350 #ifdef ENABLE_ROSEN_BACKEND
351         if (renderNode_) {
352             auto rosenTexture = AceType::DynamicCast<RosenRenderTexture>(renderNode_);
353             if (rosenTexture) {
354                 producerSurface = rosenTexture->GetSurface();
355             }
356         }
357 #endif
358     }
359 
360     if (producerSurface == nullptr) {
361         LOGE("producerSurface is nullptr");
362         return;
363     }
364     producerSurface->SetQueueSize(SURFACE_QUEUE_SIZE);
365     producerSurface->SetUserData("SURFACE_STRIDE_ALIGNMENT", SURFACE_STRIDE_ALIGNMENT);
366     producerSurface->SetUserData("SURFACE_FORMAT", std::to_string(PIXEL_FMT_RGBA_8888));
367     if (mediaPlayer_->SetVideoSurface(producerSurface) != 0) {
368         LOGE("Player SetVideoSurface failed");
369         return;
370     }
371     if (!SystemProperties::GetExtSurfaceEnabled() && mediaPlayer_->PrepareAsync() != 0) {
372         LOGE("Player prepare failed");
373         return;
374     }
375     hasSrcChanged_ = false;
376 }
377 
378 // Interim programme
MediaPlay(const std::string & filePath)379 void VideoElement::MediaPlay(const std::string& filePath)
380 {
381     auto assetManager = PipelineBase::GetCurrentContext()->GetAssetManager();
382     uint32_t resId = 0;
383     if (GetResourceId(filePath, resId)) {
384         auto themeManager = PipelineBase::GetCurrentContext()->GetThemeManager();
385         auto themeConstants = themeManager->GetThemeConstants();
386         std::string mediaPath;
387         auto state1 = themeConstants->GetMediaById(resId, mediaPath);
388         if (!state1) {
389             LOGE("GetMediaById failed");
390             return;
391         }
392         MediaFileInfo fileInfo;
393         auto state2 = assetManager->GetFileInfo(mediaPath.substr(mediaPath.find("resources/base")), fileInfo);
394         if (!state2) {
395             LOGE("GetMediaFileInfo failed");
396             return;
397         }
398         auto hapPath = Container::Current()->GetHapPath();
399         auto hapFd = open(hapPath.c_str(), O_RDONLY);
400         if (hapFd < 0) {
401             LOGE("Open hap file failed");
402             return;
403         }
404         if (mediaPlayer_->SetSource(hapFd, fileInfo.offset, fileInfo.length) != 0) {
405             LOGE("Player SetSource failed");
406             close(hapFd);
407             return;
408         }
409         close(hapFd);
410     }
411 }
412 
RawFilePlay(const std::string & filePath)413 void VideoElement::RawFilePlay(const std::string& filePath)
414 {
415     auto assetManager = PipelineBase::GetCurrentContext()->GetAssetManager();
416     auto path = "resources/rawfile/" + filePath.substr(RAWFILE_PREFIX_LENGTH);
417     MediaFileInfo fileInfo;
418     auto state1 = assetManager->GetFileInfo(path, fileInfo);
419     if (!state1) {
420         LOGE("GetMediaFileInfo failed");
421         return;
422     }
423     auto hapPath = Container::Current()->GetHapPath();
424     auto hapFd = open(hapPath.c_str(), O_RDONLY);
425     if (hapFd < 0) {
426         LOGE("Open hap file failed");
427         return;
428     }
429     if (mediaPlayer_->SetSource(hapFd, fileInfo.offset, fileInfo.length) != 0) {
430         LOGE("Player SetSource failed");
431         close(hapFd);
432         return;
433     }
434     close(hapFd);
435 }
436 
RelativePathPlay(const std::string & filePath)437 void VideoElement::RelativePathPlay(const std::string& filePath)
438 {
439     // relative path
440     auto assetManager = PipelineBase::GetCurrentContext()->GetAssetManager();
441     MediaFileInfo fileInfo;
442     auto state = assetManager->GetFileInfo(assetManager->GetAssetPath(filePath, false), fileInfo);
443     if (!state) {
444         LOGE("GetMediaFileInfo failed");
445         return;
446     }
447     auto hapPath = Container::Current()->GetHapPath();
448     auto hapFd = open(hapPath.c_str(), O_RDONLY);
449     if (hapFd < 0) {
450         LOGE("Open hap file failed");
451         return;
452     }
453     if (mediaPlayer_->SetSource(hapFd, fileInfo.offset, fileInfo.length) != 0) {
454         LOGE("Player SetSource failed");
455         close(hapFd);
456         return;
457     }
458     close(hapFd);
459 }
460 
GetResourceId(const std::string & path,uint32_t & resId)461 bool VideoElement::GetResourceId(const std::string& path, uint32_t& resId)
462 {
463     std::smatch matches;
464     if (std::regex_match(path, matches, MEDIA_RES_ID_REGEX) && matches.size() == MEDIA_RESOURCE_MATCH_SIZE) {
465         resId = static_cast<uint32_t>(std::stoul(matches[1].str()));
466         return true;
467     }
468 
469     std::smatch appMatches;
470     if (std::regex_match(path, appMatches, MEDIA_APP_RES_ID_REGEX) && appMatches.size() == MEDIA_RESOURCE_MATCH_SIZE) {
471         resId = static_cast<uint32_t>(std::stoul(appMatches[1].str()));
472         return true;
473     }
474 
475     return false;
476 }
477 
SetMediaSource(std::string & filePath,int32_t & fd)478 void VideoElement::SetMediaSource(std::string& filePath, int32_t& fd)
479 {
480     if (StringUtils::StartWith(filePath, "dataability://") || StringUtils::StartWith(filePath, "datashare://") ||
481         StringUtils::StartWith(filePath, "file://media")) {
482         // dataability:// or datashare://
483         auto context = context_.Upgrade();
484         CHECK_NULL_VOID(context);
485         auto dataProvider = AceType::DynamicCast<DataProviderManagerStandard>(context->GetDataProviderManager());
486         CHECK_NULL_VOID(dataProvider);
487         fd = dataProvider->GetDataProviderFile(filePath, "r");
488     } else if (StringUtils::StartWith(filePath, "file://")) {
489         filePath = FileUriHelper::GetRealPath(filePath);
490         fd = open(filePath.c_str(), O_RDONLY);
491     } else if (StringUtils::StartWith(filePath, "resource:///")) {
492         // file path: resources/base/media/xxx.xx --> resource:///xxx.xx
493         MediaPlay(filePath);
494     } else if (StringUtils::StartWith(filePath, "resource://RAWFILE")) {
495         // file path: resource/rawfile/xxx.xx --> resource://rawfile/xxx.xx
496         RawFilePlay(filePath);
497     } else if (StringUtils::StartWith(filePath, "http")) {
498         // http or https
499         if (mediaPlayer_->SetSource(filePath) != 0) {
500             LOGE("Player SetSource failed");
501             return;
502         }
503     } else {
504         // relative path
505         if (StringUtils::StartWith(filePath, "/")) {
506             filePath = filePath.substr(1);
507         }
508         RelativePathPlay(filePath);
509     }
510 }
511 
GetAssetAbsolutePath(const std::string & fileName)512 std::string VideoElement::GetAssetAbsolutePath(const std::string& fileName)
513 {
514     const auto pipelineContext = GetContext().Upgrade();
515     if (!pipelineContext) {
516         LOGW("the pipeline context is null");
517         return fileName;
518     }
519     auto assetManager = pipelineContext->GetAssetManager();
520     if (!assetManager) {
521         LOGW("the assetManager is null");
522         return fileName;
523     }
524     std::string filePath = assetManager->GetAssetPath(fileName, true);
525     std::string absolutePath = filePath + fileName;
526     return absolutePath;
527 }
528 
OnTextureOffset(int64_t textureId,int32_t x,int32_t y)529 void VideoElement::OnTextureOffset(int64_t textureId, int32_t x, int32_t y)
530 {
531     if (SystemProperties::GetExtSurfaceEnabled() && surfaceDelegate_) {
532         const auto pipelineContext = GetContext().Upgrade();
533         if (!pipelineContext) {
534             LOGW("pipelineContext is null!");
535             return;
536         }
537         float viewScale = pipelineContext->GetViewScale();
538         textureOffsetX_ = x * viewScale;
539         textureOffsetY_ = y * viewScale;
540         surfaceDelegate_->SetBounds(textureOffsetX_, textureOffsetY_, textureWidth_, textureHeight_);
541         LOGI("OnTextureSize x = %{public}d y = %{public}d textureWidth_ = %{public}d textureHeight_ = %{public}d",
542             textureOffsetX_, textureOffsetY_, textureWidth_, textureHeight_);
543     }
544 }
545 #endif
546 
ResetStatus()547 void VideoElement::ResetStatus()
548 {
549     needControls_ = true;
550     isAutoPlay_ = false;
551     isMute_ = false;
552     duration_ = 0;
553     currentPos_ = 0;
554     isPlaying_ = false;
555     isReady_ = false;
556     isInitialState_ = true;
557     isError_ = false;
558     videoWidth_ = 0.0;
559     videoHeight_ = 0.0;
560     isLoop_ = false;
561     startTime_ = 0;
562     durationText_ = Localization::GetInstance()->FormatDuration(0);
563     currentPosText_ = Localization::GetInstance()->FormatDuration(0);
564 }
565 
Prepare(const WeakPtr<Element> & parent)566 void VideoElement::Prepare(const WeakPtr<Element>& parent)
567 {
568     auto themeManager = GetThemeManager();
569     if (!themeManager) {
570         return;
571     }
572     auto videoComponent = AceType::DynamicCast<VideoComponent>(component_);
573     theme_ = themeManager->GetTheme<VideoTheme>();
574     sliderTheme_ = themeManager->GetTheme<SliderTheme>();
575     if (videoComponent) {
576         textDirection_ = videoComponent->GetTextDirection();
577 
578         ResetStatus();
579         InitStatus(videoComponent);
580         InitEvent(videoComponent);
581         SetRespondChildEvent();
582         if (!isExternalResource_) {
583             SetMethodCall(videoComponent);
584             CreatePlatformResource();
585             PrepareMultiModalEvent();
586             SubscribeMultiModal();
587         }
588         videoComponent->SetChild(CreateChild());
589         fullscreenEvent_ = videoComponent->GetFullscreenEvent();
590         if (!mediaFullscreenEvent_) {
591             mediaFullscreenEvent_ = videoComponent->GetMediaFullscreenEvent();
592         }
593         if (!mediaExitFullscreenEvent_ && isMediaPlayerFullStatus_) {
594             mediaExitFullscreenEvent_ = videoComponent->GetMediaExitFullscreenEvent();
595         }
596     }
597 
598     RenderElement::Prepare(parent);
599     if (renderNode_) {
600         auto renderTexture = AceType::DynamicCast<RenderTexture>(renderNode_);
601         if (renderTexture) {
602             renderTexture->SetHiddenChangeEvent([weak = WeakClaim(this)](bool hidden) {
603                 auto videoElement = weak.Upgrade();
604                 if (videoElement) {
605                     videoElement->HiddenChange(hidden);
606                 }
607             });
608             renderTexture->SetTextureSizeChange(
609                 [weak = WeakClaim(this)](int64_t textureId, int32_t textureWidth, int32_t textureHeight) {
610                     auto videoElement = weak.Upgrade();
611                     if (videoElement) {
612                         videoElement->OnTextureSize(textureId, textureWidth, textureHeight);
613                     }
614                 });
615         }
616 #ifdef OHOS_STANDARD_SYSTEM
617         if (renderTexture && SystemProperties::GetExtSurfaceEnabled()) {
618             renderTexture->SetTextureOffsetChange([weak = WeakClaim(this)](int64_t textureId, int32_t x, int32_t y) {
619                 auto videoElement = weak.Upgrade();
620                 if (videoElement) {
621                     videoElement->OnTextureOffset(textureId, x, y);
622                 }
623             });
624         }
625         CreateMediaPlayer();
626 #endif
627     }
628     isElementPrepared_ = true;
629 }
630 
OnTextureSize(int64_t textureId,int32_t textureWidth,int32_t textureHeight)631 void VideoElement::OnTextureSize(int64_t textureId, int32_t textureWidth, int32_t textureHeight)
632 {
633 #ifndef OHOS_STANDARD_SYSTEM
634     if (texture_) {
635         texture_->OnSize(textureId, textureWidth, textureHeight);
636     }
637 #else
638     if (SystemProperties::GetExtSurfaceEnabled() && surfaceDelegate_) {
639         const auto pipelineContext = GetContext().Upgrade();
640         if (!pipelineContext) {
641             LOGW("pipelineContext is null!");
642             return;
643         }
644         float viewScale = pipelineContext->GetViewScale();
645         textureWidth_ = textureWidth * viewScale + 1;
646         textureHeight_ = textureHeight * viewScale + 1;
647         surfaceDelegate_->SetBounds(textureOffsetX_, textureOffsetY_, textureWidth_, textureHeight_);
648         LOGI("OnTextureSize x = %{public}d y = %{public}d textureWidth_ = %{public}d textureHeight_ = %{public}d",
649             textureOffsetX_, textureOffsetY_, textureWidth_, textureHeight_);
650         if (hasMediaPrepared_) {
651             return;
652         }
653         if (mediaPlayer_->PrepareAsync() != 0) {
654             LOGE("Player prepare failed");
655         } else {
656             hasMediaPrepared_ = true;
657         }
658     }
659 #endif
660 }
661 
HasPlayer() const662 bool VideoElement::HasPlayer() const
663 {
664 #ifdef OHOS_STANDARD_SYSTEM
665     return mediaPlayer_ != nullptr;
666 #else
667     return player_ != nullptr;
668 #endif
669 }
670 
HiddenChange(bool hidden)671 void VideoElement::HiddenChange(bool hidden)
672 {
673     if (isPlaying_ && hidden && HasPlayer()) {
674         pastPlayingStatus_ = isPlaying_;
675         Pause();
676         return;
677     }
678 
679     if (!hidden && pastPlayingStatus_) {
680         isPlaying_ = !pastPlayingStatus_;
681         pastPlayingStatus_ = false;
682         Start();
683     }
684 }
685 
PrepareMultiModalEvent()686 void VideoElement::PrepareMultiModalEvent()
687 {
688     if (!multimodalEventFullscreen_) {
689         multimodalEventFullscreen_ = [weak = WeakClaim(this)](const AceMultimodalEvent&) {
690             auto videoElement = weak.Upgrade();
691             if (videoElement) {
692                 videoElement->FullScreen();
693             }
694         };
695     }
696 
697     if (!multimodalEventPause_) {
698         multimodalEventPause_ = [weak = WeakClaim(this)](const AceMultimodalEvent&) {
699             auto videoElement = weak.Upgrade();
700             if (videoElement) {
701                 videoElement->Pause();
702             }
703         };
704     }
705 
706     if (!multimodalEventPlay_) {
707         multimodalEventPlay_ = [weak = WeakClaim(this)](const AceMultimodalEvent&) {
708             auto videoElement = weak.Upgrade();
709             if (videoElement) {
710                 videoElement->Start();
711             }
712         };
713     }
714 
715     if (!multimodalEventFullscreenExit_) {
716         multimodalEventFullscreenExit_ = [weak = WeakClaim(this)](const AceMultimodalEvent&) {
717             auto videoElement = weak.Upgrade();
718             if (videoElement) {
719                 videoElement->ExitFullScreen();
720             }
721         };
722     };
723 }
724 
SubscribeMultiModal()725 bool VideoElement::SubscribeMultiModal()
726 {
727     if (isSubscribeMultimodal_) {
728         return true;
729     }
730     if (multiModalScene_.Invalid()) {
731         const auto pipelineContext = GetContext().Upgrade();
732         if (!pipelineContext) {
733             LOGW("the pipeline context is null");
734             return false;
735         }
736         const auto multimodalManager = pipelineContext->GetMultiModalManager();
737         if (!multimodalManager) {
738             LOGW("the multimodal manager is null");
739             return false;
740         }
741         const auto scene = multimodalManager->GetCurrentMultiModalScene();
742         if (!scene) {
743             return false;
744         }
745 
746         playVoiceEvent_ = VoiceEvent(PLAY_LABEL, SceneLabel::VIDEO);
747         scene->SubscribeVoiceEvent(playVoiceEvent_, multimodalEventPlay_);
748 
749         pauseVoiceEvent_ = VoiceEvent(PAUSE_LABEL, SceneLabel::VIDEO);
750         scene->SubscribeVoiceEvent(pauseVoiceEvent_, multimodalEventPause_);
751 
752         fullscreenVoiceEvent_ = VoiceEvent(FULLSCREEN_LABEL, SceneLabel::VIDEO);
753         scene->SubscribeVoiceEvent(fullscreenVoiceEvent_, multimodalEventFullscreen_);
754 
755         exitFullscreenVoiceEvent_ = VoiceEvent(EXIT_FULLSCREEN_LABEL, SceneLabel::VIDEO);
756         scene->SubscribeVoiceEvent(exitFullscreenVoiceEvent_, multimodalEventFullscreenExit_);
757         multiModalScene_ = scene;
758         isSubscribeMultimodal_ = true;
759     }
760     return true;
761 }
762 
UnSubscribeMultiModal()763 bool VideoElement::UnSubscribeMultiModal()
764 {
765     if (!isSubscribeMultimodal_) {
766         return true;
767     }
768     auto multiModalScene = multiModalScene_.Upgrade();
769     if (!multiModalScene) {
770         LOGE("fail to destroy multimodal event due to multiModalScene is null");
771         return false;
772     }
773     if (!playVoiceEvent_.GetVoiceContent().empty()) {
774         multiModalScene->UnSubscribeVoiceEvent(playVoiceEvent_);
775     }
776     if (!pauseVoiceEvent_.GetVoiceContent().empty()) {
777         multiModalScene->UnSubscribeVoiceEvent(pauseVoiceEvent_);
778     }
779     if (!exitFullscreenVoiceEvent_.GetVoiceContent().empty()) {
780         multiModalScene->UnSubscribeVoiceEvent(exitFullscreenVoiceEvent_);
781     }
782     if (!fullscreenVoiceEvent_.GetVoiceContent().empty()) {
783         multiModalScene->UnSubscribeVoiceEvent(fullscreenVoiceEvent_);
784     }
785     isSubscribeMultimodal_ = false;
786     return true;
787 }
788 
SetNewComponent(const RefPtr<Component> & newComponent)789 void VideoElement::SetNewComponent(const RefPtr<Component>& newComponent)
790 {
791     if (newComponent == nullptr || !isElementPrepared_) {
792         Element::SetNewComponent(newComponent);
793         return;
794     }
795     auto videoComponent = AceType::DynamicCast<VideoComponent>(newComponent);
796     if (videoComponent) {
797         if (src_ == videoComponent->GetSrc()) {
798             if (isError_) {
799                 return;
800             }
801             hasSrcChanged_ = false;
802             InitStatus(videoComponent);
803 
804             // When the video is in the initial state and the attribute is auto play, start playing.
805             if (isInitialState_ && isAutoPlay_) {
806                 Start();
807             }
808         } else {
809             hasSrcChanged_ = true;
810             ResetStatus();
811             InitStatus(videoComponent);
812             CreatePlatformResource();
813         }
814         if (texture_) {
815 #ifndef OHOS_STANDARD_SYSTEM
816             videoComponent->SetTextureId(texture_->GetId());
817 #endif
818             videoComponent->SetSrcWidth(videoWidth_);
819             videoComponent->SetSrcHeight(videoHeight_);
820             videoComponent->SetFit(imageFit_);
821             videoComponent->SetImagePosition(imagePosition_);
822         }
823         videoComponent->SetChild(CreateChild());
824 
825         Element::SetNewComponent(videoComponent);
826     }
827 }
828 
InitEvent(const RefPtr<VideoComponent> & videoComponent)829 void VideoElement::InitEvent(const RefPtr<VideoComponent>& videoComponent)
830 {
831     if (!videoComponent->GetPreparedEventId().IsEmpty()) {
832         onPrepared_ = AceAsyncEvent<void(const std::string&)>::Create(videoComponent->GetPreparedEventId(), context_);
833     }
834 
835     if (!videoComponent->GetFinishEventId().IsEmpty()) {
836         onFinish_ = AceAsyncEvent<void(const std::string&)>::Create(videoComponent->GetFinishEventId(), context_);
837     }
838 
839     if (!videoComponent->GetErrorEventId().IsEmpty()) {
840         onError_ = AceAsyncEvent<void(const std::string&)>::Create(videoComponent->GetErrorEventId(), context_);
841     }
842 
843     if (!videoComponent->GetTimeUpdateEventId().IsEmpty()) {
844         onTimeUpdate_ =
845             AceAsyncEvent<void(const std::string&)>::Create(videoComponent->GetTimeUpdateEventId(), context_);
846     }
847 
848     if (!videoComponent->GetStartEventId().IsEmpty()) {
849         onStart_ = AceAsyncEvent<void(const std::string&)>::Create(videoComponent->GetStartEventId(), context_);
850     }
851 
852     if (!videoComponent->GetPauseEventId().IsEmpty()) {
853         onPause_ = AceAsyncEvent<void(const std::string&)>::Create(videoComponent->GetPauseEventId(), context_);
854     }
855 
856     if (!videoComponent->GetStopEventId().IsEmpty()) {
857         onStop_ = AceAsyncEvent<void(const std::string&)>::Create(videoComponent->GetStopEventId(), context_);
858     }
859 
860     if (!videoComponent->GetSeekingEventId().IsEmpty()) {
861         onSeeking_ = AceAsyncEvent<void(const std::string&)>::Create(videoComponent->GetSeekingEventId(), context_);
862     }
863 
864     if (!videoComponent->GetSeekedEventId().IsEmpty()) {
865         onSeeked_ = AceAsyncEvent<void(const std::string&)>::Create(videoComponent->GetSeekedEventId(), context_);
866     }
867 
868     if (!videoComponent->GetFullscreenChangeEventId().IsEmpty()) {
869         onFullScreenChange_ =
870             AceAsyncEvent<void(const std::string&)>::Create(videoComponent->GetFullscreenChangeEventId(), context_);
871     }
872 }
873 
SetMethodCall(const RefPtr<VideoComponent> & videoComponent)874 void VideoElement::SetMethodCall(const RefPtr<VideoComponent>& videoComponent)
875 {
876     auto videoController = videoComponent->GetVideoController();
877     if (videoController) {
878         auto context = context_.Upgrade();
879         if (!context) {
880             return;
881         }
882         auto uiTaskExecutor = SingleTaskExecutor::Make(context->GetTaskExecutor(), TaskExecutor::TaskType::UI);
883         videoController->SetStartImpl([weak = WeakClaim(this), uiTaskExecutor]() {
884             uiTaskExecutor.PostTask([weak]() {
885                 auto videoElement = weak.Upgrade();
886                 if (videoElement) {
887                     videoElement->Start();
888                 }
889             });
890         });
891         videoController->SetPausetImpl([weak = WeakClaim(this), uiTaskExecutor]() {
892             uiTaskExecutor.PostTask([weak]() {
893                 auto videoElement = weak.Upgrade();
894                 if (videoElement) {
895                     videoElement->Pause();
896                 }
897             });
898         });
899         videoController->SetStopImpl([weak = WeakClaim(this), uiTaskExecutor]() {
900             uiTaskExecutor.PostTask([weak]() {
901                 auto videoElement = weak.Upgrade();
902                 if (videoElement) {
903                     videoElement->Stop();
904                 }
905             });
906         });
907         videoController->SetSeekToImpl([weak = WeakClaim(this), uiTaskExecutor](float pos, SeekMode seekMode) {
908             uiTaskExecutor.PostTask([weak, pos, seekMode]() {
909                 auto videoElement = weak.Upgrade();
910                 if (videoElement) {
911                     videoElement->SetCurrentTime(pos, seekMode);
912                 }
913             });
914         });
915         videoController->SetRequestFullscreenImpl([weak = WeakClaim(this), uiTaskExecutor](bool isPortrait) {
916             uiTaskExecutor.PostTask([weak, isPortrait]() {
917                 auto videoElement = weak.Upgrade();
918                 if (videoElement) {
919                     videoElement->OnPreFullScreen(isPortrait);
920                     videoElement->FullScreen();
921                 }
922             });
923         });
924         videoController->SetExitFullscreenImpl([weak = WeakClaim(this), uiTaskExecutor](bool isSync) {
925             if (isSync) {
926                 auto videoElement = weak.Upgrade();
927                 if (videoElement) {
928                     videoElement->ExitFullScreen();
929                 }
930                 return;
931             }
932             uiTaskExecutor.PostTask([weak]() {
933                 auto videoElement = weak.Upgrade();
934                 if (videoElement) {
935                     videoElement->ExitFullScreen();
936                 }
937             });
938         });
939     }
940 }
941 
SetRespondChildEvent()942 void VideoElement::SetRespondChildEvent()
943 {
944     shieldId_ = BackEndEventManager<void()>::GetInstance().GetAvailableMarker();
945     startBtnClickId_ = BackEndEventManager<void()>::GetInstance().GetAvailableMarker();
946     BackEndEventManager<void()>::GetInstance().BindBackendEvent(startBtnClickId_, [weak = WeakClaim(this)]() {
947         auto videoElement = weak.Upgrade();
948         if (videoElement) {
949             videoElement->OnStartBtnClick();
950         }
951     });
952     sliderMovedCallbackId_ = BackEndEventManager<void(const std::string&)>::GetInstance().GetAvailableMarker();
953     BackEndEventManager<void(const std::string&)>::GetInstance().BindBackendEvent(
954         sliderMovedCallbackId_, [weak = WeakClaim(this)](const std::string& param) {
955             auto videoElement = weak.Upgrade();
956             if (videoElement) {
957                 videoElement->OnSliderChange(param);
958             }
959         });
960     sliderMovingCallbackId_ = BackEndEventManager<void(const std::string&)>::GetInstance().GetAvailableMarker();
961     BackEndEventManager<void(const std::string&)>::GetInstance().BindBackendEvent(
962         sliderMovingCallbackId_, [weak = WeakClaim(this)](const std::string& param) {
963             auto videoElement = weak.Upgrade();
964             if (videoElement) {
965                 videoElement->OnSliderMoving(param);
966             }
967         });
968     fullscreenBtnClickId_ = BackEndEventManager<void()>::GetInstance().GetAvailableMarker();
969     BackEndEventManager<void()>::GetInstance().BindBackendEvent(fullscreenBtnClickId_, [weak = WeakClaim(this)]() {
970         auto videoElement = weak.Upgrade();
971         if (videoElement) {
972             videoElement->OnFullScreenBtnClick();
973         }
974     });
975 }
976 
CreatePlatformResource()977 void VideoElement::CreatePlatformResource()
978 {
979     ReleasePlatformResource();
980 
981     auto context = context_.Upgrade();
982     if (!context) {
983         return;
984     }
985     auto uiTaskExecutor = SingleTaskExecutor::Make(context->GetTaskExecutor(), TaskExecutor::TaskType::UI);
986 
987     auto errorCallback = [weak = WeakClaim(this), uiTaskExecutor](
988                              const std::string& errorId, const std::string& param) {
989         uiTaskExecutor.PostTask([weak, errorId, param] {
990             auto videoElement = weak.Upgrade();
991             if (videoElement) {
992                 videoElement->OnError(errorId, param);
993             }
994         });
995     };
996     texture_ = AceType::MakeRefPtr<Texture>(context_, errorCallback);
997 
998     texture_->Create([weak = WeakClaim(this), errorCallback](int64_t id) mutable {
999         auto videoElement = weak.Upgrade();
1000         if (videoElement) {
1001             videoElement->CreatePlayer(id, std::move(errorCallback));
1002         }
1003     });
1004 }
1005 
CreatePlayer(int64_t id,ErrorCallback && errorCallback)1006 void VideoElement::CreatePlayer(int64_t id, ErrorCallback&& errorCallback)
1007 {
1008     player_ = AceType::MakeRefPtr<Player>(id, src_, context_, std::move(errorCallback));
1009     player_->SetMute(isMute_);
1010     player_->SetAutoPlay(isAutoPlay_);
1011     InitListener();
1012     player_->Create(nullptr);
1013 }
1014 
InitListener()1015 void VideoElement::InitListener()
1016 {
1017     auto context = context_.Upgrade();
1018     if (!context) {
1019         return;
1020     }
1021 
1022     auto uiTaskExecutor = SingleTaskExecutor::Make(context->GetTaskExecutor(), TaskExecutor::TaskType::UI);
1023     auto videoElement = WeakClaim(this);
1024     if (!isExternalResource_) {
1025         auto onTextureRefresh = [videoElement, uiTaskExecutor]() {
1026             if (!videoElement.Upgrade()) {
1027                 return;
1028             }
1029             uiTaskExecutor.PostSyncTask([&videoElement] {
1030                 auto video = videoElement.Upgrade();
1031                 if (video) {
1032                     video->OnTextureRefresh();
1033                 }
1034             });
1035         };
1036         texture_->SetRefreshListener(onTextureRefresh);
1037     }
1038 
1039     auto onPrepared = [videoElement, uiTaskExecutor](uint32_t width, uint32_t height, bool isPlaying, uint32_t duration,
1040                           uint32_t currentPos, bool needFireEvent) {
1041         if (!videoElement.Upgrade()) {
1042             return;
1043         }
1044         uiTaskExecutor.PostSyncTask([&videoElement, width, height, isPlaying, duration, currentPos, needFireEvent] {
1045             auto video = videoElement.Upgrade();
1046             if (video) {
1047                 video->OnPrepared(width, height, isPlaying, duration, currentPos, needFireEvent);
1048             }
1049         });
1050     };
1051 
1052     auto onPlayerStatus = [videoElement, uiTaskExecutor](bool isPlaying) {
1053         if (!videoElement.Upgrade()) {
1054             return;
1055         }
1056         uiTaskExecutor.PostSyncTask([&videoElement, isPlaying] {
1057             auto video = videoElement.Upgrade();
1058             if (video) {
1059                 video->OnPlayerStatus(isPlaying ? PlaybackStatus::STARTED : PlaybackStatus::NONE);
1060             }
1061         });
1062     };
1063 
1064     auto onCurrentTimeChange = [videoElement, uiTaskExecutor](uint32_t currentPos) {
1065         if (!videoElement.Upgrade()) {
1066             return;
1067         }
1068         uiTaskExecutor.PostSyncTask([&videoElement, currentPos] {
1069             auto video = videoElement.Upgrade();
1070             if (video) {
1071                 video->OnCurrentTimeChange(currentPos);
1072             }
1073         });
1074     };
1075 
1076     auto onCompletion = [videoElement, uiTaskExecutor] {
1077         if (!videoElement.Upgrade()) {
1078             return;
1079         }
1080         uiTaskExecutor.PostSyncTask([&videoElement] {
1081             auto video = videoElement.Upgrade();
1082             if (video) {
1083                 video->OnCompletion();
1084             }
1085         });
1086     };
1087 
1088     player_->AddPreparedListener(onPrepared);
1089     player_->AddPlayStatusListener(onPlayerStatus);
1090     player_->AddCurrentPosListener(onCurrentTimeChange);
1091     player_->AddCompletionListener(onCompletion);
1092 
1093     player_->AddRefreshRenderListener([videoElement]() {
1094         auto video = videoElement.Upgrade();
1095         if (video) {
1096             video->OnTextureRefresh();
1097         }
1098     });
1099 }
1100 
ReleasePlatformResource()1101 void VideoElement::ReleasePlatformResource()
1102 {
1103 #ifndef OHOS_STANDARD_SYSTEM
1104     auto context = context_.Upgrade();
1105     if (!context) {
1106         return;
1107     }
1108 
1109     // Reusing texture will cause a problem that last frame of last video will be display.
1110     if (texture_) {
1111         auto platformTaskExecutor =
1112             SingleTaskExecutor::Make(context->GetTaskExecutor(), TaskExecutor::TaskType::PLATFORM);
1113 
1114         // Release player first.
1115         if (player_) {
1116             if (!isExternalResource_) {
1117                 player_->Stop();
1118                 player_->Release();
1119             }
1120 
1121             if (platformTaskExecutor.IsRunOnCurrentThread()) {
1122                 player_.Reset();
1123             } else {
1124                 // Make sure it's destroyed when it's release task done.
1125                 platformTaskExecutor.PostTask([player = player_]() {});
1126             }
1127         }
1128 
1129         if (platformTaskExecutor.IsRunOnCurrentThread()) {
1130             if (!isExternalResource_) {
1131                 texture_->Release();
1132             }
1133             texture_.Reset();
1134         } else {
1135             if (!isExternalResource_) {
1136 #if defined(ENABLE_NATIVE_VIEW)
1137                 texture_->Release();
1138             }
1139             // Make sure it's destroyed when it's release task done.
1140             platformTaskExecutor.PostTask([texture = texture_]() {});
1141 #else
1142                 auto gpuTaskExecutor =
1143                     SingleTaskExecutor::Make(context->GetTaskExecutor(), TaskExecutor::TaskType::GPU);
1144                 // Release texture after paint.
1145                 auto weak = AceType::WeakClaim(AceType::RawPtr(texture_));
1146                 gpuTaskExecutor.PostTask([weak, platformTaskExecutor]() {
1147                     auto texture = weak.Upgrade();
1148                     if (texture == nullptr) {
1149                         LOGE("texture is nullptr");
1150                         return;
1151                     }
1152                     texture->Release();
1153                     // Make sure it's destroyed when it's release task done.
1154                     platformTaskExecutor.PostTask([texture]() {});
1155                 });
1156             } else {
1157                 // Make sure it's destroyed when it's release task done.
1158                 platformTaskExecutor.PostTask([texture = texture_]() {});
1159             }
1160 #endif
1161         }
1162     }
1163 #endif
1164 }
1165 
UpdateChildInner(const RefPtr<Component> & childComponent)1166 void VideoElement::UpdateChildInner(const RefPtr<Component>& childComponent)
1167 {
1168     const auto& child = children_.empty() ? nullptr : children_.front();
1169     UpdateChild(child, childComponent);
1170 }
1171 
OnError(const std::string & errorId,const std::string & param)1172 void VideoElement::OnError(const std::string& errorId, const std::string& param)
1173 {
1174     isError_ = true;
1175     std::string errorcode = Localization::GetInstance()->GetErrorDescription(errorId);
1176     UpdateChildInner(CreateErrorText(errorcode));
1177 
1178     if (onError_) {
1179         std::string param;
1180         if (IsDeclarativePara()) {
1181             auto json = JsonUtil::Create(true);
1182             json->Put("error", "");
1183             param = json->ToString();
1184         } else {
1185             param = std::string("\"error\",{").append("}");
1186         }
1187         onError_(param);
1188     }
1189 }
1190 
OnResolutionChange() const1191 void VideoElement::OnResolutionChange() const
1192 {
1193 #if defined(ENABLE_ROSEN_BACKEND) && defined(OHOS_STANDARD_SYSTEM)
1194     if (!mediaPlayer_ || !renderNode_) {
1195         LOGE("player or render is null");
1196         return;
1197     }
1198 
1199     auto rosenTexture = DynamicCast<RosenRenderTexture>(renderNode_);
1200     if (!rosenTexture) {
1201         LOGE("backend is not rosen.");
1202         return;
1203     }
1204 
1205     Size videoSize = Size(mediaPlayer_->GetVideoWidth(), mediaPlayer_->GetVideoHeight());
1206     LOGI("OnResolutionChange video size: %{public}s", videoSize.ToString().c_str());
1207     rosenTexture->SyncProperties(videoSize, imageFit_, imagePosition_);
1208 #endif
1209 }
1210 
OnPrepared(uint32_t width,uint32_t height,bool isPlaying,uint32_t duration,uint32_t currentPos,bool needFireEvent)1211 void VideoElement::OnPrepared(
1212     uint32_t width, uint32_t height, bool isPlaying, uint32_t duration, uint32_t currentPos, bool needFireEvent)
1213 {
1214     isPlaying_ = isPlaying;
1215     isReady_ = true;
1216     videoWidth_ = width;
1217     videoHeight_ = height;
1218     duration_ = duration;
1219     currentPos_ = std::max(startTime_, static_cast<int32_t>(currentPos));
1220 
1221     IntTimeToText(duration_, durationText_);
1222     IntTimeToText(currentPos_, currentPosText_);
1223 
1224     auto video = AceType::MakeRefPtr<VideoComponent>();
1225 #ifndef OHOS_STANDARD_SYSTEM
1226     video->SetTextureId(texture_->GetId());
1227 #endif
1228     video->SetSrcWidth(videoWidth_);
1229     video->SetSrcHeight(videoHeight_);
1230     video->SetFit(imageFit_);
1231     video->SetImagePosition(imagePosition_);
1232 
1233     if (isPlaying || currentPos != 0) {
1234         isInitialState_ = false;
1235     }
1236 
1237     if (renderNode_ != nullptr) {
1238         video->SetNeedControls(needControls_);
1239         renderNode_->Update(video);
1240     }
1241     UpdateChildInner(CreateChild());
1242 
1243     if (needFireEvent && onPrepared_) {
1244         std::string param;
1245         if (IsDeclarativePara()) {
1246             auto json = JsonUtil::Create(true);
1247             json->Put("duration", static_cast<double>(duration_));
1248             param = json->ToString();
1249         } else {
1250             param = std::string("\"prepared\",{\"duration\":").append(std::to_string(duration_)).append("}");
1251         }
1252         LOGI("video onPrepared event: %s ", param.c_str());
1253         onPrepared_(param);
1254     }
1255 
1256     if (!isExternalResource_ || isMediaPlayerFullStatus_) {
1257         SetCurrentTime(startTime_, SeekMode::SEEK_CLOSEST);
1258         EnableLooping(isLoop_);
1259         SetSpeed(speed_);
1260     }
1261 
1262     if (isStop_) {
1263         isStop_ = false;
1264         Start();
1265     }
1266 
1267 #ifdef OHOS_STANDARD_SYSTEM
1268     if (isAutoPlay_) {
1269         Start();
1270     } else if (isMediaPlayerFullStatus_ && pastPlayingStatus_) {
1271         Start();
1272         pastPlayingStatus_ = false;
1273     }
1274 #endif
1275 }
1276 
OnPlayerStatus(PlaybackStatus status)1277 void VideoElement::OnPlayerStatus(PlaybackStatus status)
1278 {
1279     bool isPlaying = (status == PlaybackStatus::STARTED);
1280     if (isInitialState_) {
1281         isInitialState_ = !isPlaying;
1282     }
1283 
1284     isPlaying_ = isPlaying;
1285     if (!isFullScreen_ || isExternalResource_) {
1286         UpdateChildInner(CreateChild());
1287     }
1288 
1289     if (isPlaying) {
1290         if (onStart_) {
1291             std::string param;
1292             if (IsDeclarativePara()) {
1293                 auto json = JsonUtil::Create(true);
1294                 json->Put("start", "");
1295                 param = json->ToString();
1296             } else {
1297                 param = std::string("\"start\",{").append("}");
1298             }
1299             LOGE("video onStart event: %s ", param.c_str());
1300             onStart_(param);
1301         }
1302     } else {
1303         if (onPause_) {
1304             std::string param;
1305             if (IsDeclarativePara()) {
1306                 auto json = JsonUtil::Create(true);
1307                 json->Put("pause", "");
1308                 param = json->ToString();
1309             } else {
1310                 param = std::string("\"pause\",{").append("}");
1311             }
1312             LOGE("video onPause event: %s ", param.c_str());
1313             onPause_(param);
1314         }
1315     }
1316 
1317 #ifdef OHOS_STANDARD_SYSTEM
1318     if (status == PlaybackStatus::PREPARED) {
1319         auto context = context_.Upgrade();
1320         if (context == nullptr) {
1321             LOGE("context is nullptr");
1322             return;
1323         }
1324         if (!mediaPlayer_) {
1325             return;
1326         }
1327         auto uiTaskExecutor = SingleTaskExecutor::Make(context->GetTaskExecutor(), TaskExecutor::TaskType::UI);
1328         auto videoElement = WeakClaim(this);
1329         Size videoSize = Size(mediaPlayer_->GetVideoWidth(), mediaPlayer_->GetVideoHeight());
1330         int32_t milliSecondDuration = 0;
1331         mediaPlayer_->GetDuration(milliSecondDuration);
1332         uiTaskExecutor.PostSyncTask([&videoElement, videoSize, duration = milliSecondDuration / MILLISECONDS_TO_SECONDS,
1333                                         startTime = startTime_] {
1334             auto video = videoElement.Upgrade();
1335             if (video) {
1336                 LOGI("Video OnPrepared video size: %{public}s", videoSize.ToString().c_str());
1337                 video->OnPrepared(videoSize.Width(), videoSize.Height(), false, duration, startTime, true);
1338             }
1339         });
1340     } else if (status == PlaybackStatus::PLAYBACK_COMPLETE) {
1341         OnCompletion();
1342     }
1343 #endif
1344 }
1345 
OnCurrentTimeChange(uint32_t currentPos)1346 void VideoElement::OnCurrentTimeChange(uint32_t currentPos)
1347 {
1348 #ifdef OHOS_STANDARD_SYSTEM
1349     if (isMediaPlayerFullStatus_ && startTime_ != 0) {
1350         if (GreatNotEqual(startTime_, currentPos)) {
1351             currentPos = startTime_;
1352         }
1353     }
1354     if (currentPos == currentPos_ || isStop_) {
1355         return;
1356     }
1357     if (duration_ == 0) {
1358         int32_t duration = 0;
1359         if (mediaPlayer_->GetDuration(duration) == 0) {
1360             duration_ = duration / MILLISECONDS_TO_SECONDS;
1361             IntTimeToText(duration_, durationText_);
1362         }
1363     }
1364 #endif
1365 
1366     isInitialState_ = isInitialState_ ? currentPos == 0 : false;
1367     IntTimeToText(currentPos, currentPosText_);
1368     currentPos_ = currentPos;
1369 
1370     UpdateChildInner(CreateChild());
1371 
1372     if (onTimeUpdate_) {
1373         std::string param;
1374         if (IsDeclarativePara()) {
1375             auto json = JsonUtil::Create(true);
1376             json->Put("time", static_cast<double>(currentPos));
1377             param = json->ToString();
1378         } else {
1379             param = std::string("\"timeupdate\",{\"currenttime\":").append(std::to_string(currentPos)).append("}");
1380         }
1381         LOGI("video onTimeUpdate event: %s ", param.c_str());
1382         onTimeUpdate_(param);
1383     }
1384 }
1385 
OnCompletion()1386 void VideoElement::OnCompletion()
1387 {
1388     LOGI("VideoElement::OnCompletion");
1389     currentPos_ = duration_;
1390     IntTimeToText(currentPos_, currentPosText_);
1391 
1392     isPlaying_ = false;
1393     UpdateChildInner(CreateChild());
1394 
1395     if (onFinish_) {
1396         std::string param;
1397         if (IsDeclarativePara()) {
1398             auto json = JsonUtil::Create(true);
1399             json->Put("finish", "");
1400             param = json->ToString();
1401         } else {
1402             param = std::string("\"finish\",{").append("}");
1403         }
1404         LOGI("video onFinish event: %s ", param.c_str());
1405         onFinish_(param);
1406     }
1407 }
1408 
CreateErrorText(const std::string & errorMsg)1409 const RefPtr<Component> VideoElement::CreateErrorText(const std::string& errorMsg)
1410 {
1411     auto text = AceType::MakeRefPtr<TextComponent>(errorMsg);
1412     text->SetTextStyle(theme_->GetErrorTextStyle());
1413     text->SetTextDirection(textDirection_);
1414 
1415     std::list<RefPtr<Component>> childrenAlign;
1416     childrenAlign.emplace_back(text);
1417 
1418     return AceType::MakeRefPtr<AlignComponent>(childrenAlign, Alignment::TOP_CENTER);
1419 }
1420 
CreateCurrentText()1421 const RefPtr<Component> VideoElement::CreateCurrentText()
1422 {
1423     auto textPos = AceType::MakeRefPtr<TextComponent>(currentPosText_);
1424     textPos->SetTextStyle(theme_->GetTimeTextStyle());
1425     return textPos;
1426 }
1427 
CreateDurationText()1428 const RefPtr<Component> VideoElement::CreateDurationText()
1429 {
1430     auto textDuration = AceType::MakeRefPtr<TextComponent>(durationText_);
1431     textDuration->SetTextStyle(theme_->GetTimeTextStyle());
1432     return textDuration;
1433 }
1434 
CreateSlider()1435 const RefPtr<Component> VideoElement::CreateSlider()
1436 {
1437     auto slider = AceType::MakeRefPtr<SliderComponent>(currentPos_, 1.0, 0.0, duration_);
1438     slider->InitStyle(sliderTheme_);
1439     slider->SetOnMoveEndEventId(sliderMovedCallbackId_);
1440     slider->SetOnMovingEventId(sliderMovingCallbackId_);
1441     slider->SetTextDirection(textDirection_);
1442     return slider;
1443 }
1444 
CreatePlayBtn()1445 const RefPtr<Component> VideoElement::CreatePlayBtn()
1446 {
1447     auto imageIcon = InternalResource::ResourceId::PLAY_SVG;
1448 
1449     if (pastPlayingStatus_ || isPlaying_) {
1450         imageIcon = InternalResource::ResourceId::PAUSE_SVG;
1451     }
1452 
1453     auto image = AceType::MakeRefPtr<ImageComponent>(imageIcon);
1454     const Size& btnSize = theme_->GetBtnSize();
1455     image->SetWidth(Dimension(btnSize.Width(), DimensionUnit::VP));
1456     image->SetHeight(Dimension(btnSize.Height(), DimensionUnit::VP));
1457     image->SetTextDirection(textDirection_);
1458     image->SetMatchTextDirection(true);
1459     std::list<RefPtr<Component>> btnChildren;
1460     btnChildren.emplace_back(image);
1461 
1462     auto button = AceType::MakeRefPtr<ButtonComponent>(btnChildren);
1463     button->SetWidth(Dimension(btnSize.Width(), DimensionUnit::VP));
1464     button->SetHeight(Dimension(btnSize.Height(), DimensionUnit::VP));
1465     button->SetType(ButtonType::ICON);
1466 
1467     if (IsDeclarativePara()) {
1468         button->SetClickFunction([weak = WeakClaim(this)]() {
1469             auto videoElement = weak.Upgrade();
1470             if (videoElement) {
1471                 videoElement->OnStartBtnClick();
1472             }
1473         });
1474     } else {
1475         button->SetClickedEventId(startBtnClickId_);
1476     }
1477     return button;
1478 }
1479 
CreateFullScreenBtn()1480 const RefPtr<Component> VideoElement::CreateFullScreenBtn()
1481 {
1482     auto imageIcon = InternalResource::ResourceId::FULLSCREEN_SVG;
1483 
1484     if (isFullScreen_) {
1485         imageIcon = InternalResource::ResourceId::QUIT_FULLSCREEN_SVG;
1486     }
1487 
1488     auto image = AceType::MakeRefPtr<ImageComponent>(imageIcon);
1489     const Size& btnSize = theme_->GetBtnSize();
1490     image->SetWidth(Dimension(btnSize.Width(), DimensionUnit::VP));
1491     image->SetHeight(Dimension(btnSize.Height(), DimensionUnit::VP));
1492     image->SetTextDirection(textDirection_);
1493     image->SetMatchTextDirection(true);
1494 
1495     std::list<RefPtr<Component>> btnChildren;
1496     btnChildren.emplace_back(image);
1497 
1498     auto button = AceType::MakeRefPtr<ButtonComponent>(btnChildren);
1499     button->SetWidth(Dimension(btnSize.Width(), DimensionUnit::VP));
1500     button->SetHeight(Dimension(btnSize.Height(), DimensionUnit::VP));
1501     button->SetType(ButtonType::ICON);
1502 
1503     if (IsDeclarativePara()) {
1504         button->SetClickFunction([weak = WeakClaim(this), isFullScreen = isFullScreen_]() {
1505             auto videoElement = weak.Upgrade();
1506             if (videoElement) {
1507                 videoElement->OnFullScreenBtnClick();
1508             }
1509         });
1510     } else {
1511         button->SetClickedEventId(fullscreenBtnClickId_);
1512     }
1513     return button;
1514 }
1515 
SetPadding(const RefPtr<Component> & component,Edge && edge)1516 const RefPtr<Component> VideoElement::SetPadding(const RefPtr<Component>& component, Edge&& edge)
1517 {
1518     auto paddingComponent = AceType::MakeRefPtr<PaddingComponent>();
1519     paddingComponent->SetPadding(std::move(edge));
1520     paddingComponent->SetChild(component);
1521 
1522     return paddingComponent;
1523 }
1524 
CreateControl()1525 const RefPtr<Component> VideoElement::CreateControl()
1526 {
1527     std::list<RefPtr<Component>> rowChildren;
1528 
1529     rowChildren.emplace_back(SetPadding(CreatePlayBtn(), Edge(theme_->GetBtnEdge())));
1530 
1531     rowChildren.emplace_back(SetPadding(CreateCurrentText(), Edge(theme_->GetTextEdge())));
1532 
1533     rowChildren.emplace_back(
1534         AceType::MakeRefPtr<FlexItemComponent>(VIDEO_CHILD_COMMON_FLEX_GROW, VIDEO_CHILD_COMMON_FLEX_SHRINK,
1535             VIDEO_CHILD_COMMON_FLEX_BASIS, SetPadding(CreateSlider(), Edge(theme_->GetSliderEdge()))));
1536 
1537     rowChildren.emplace_back(SetPadding(CreateDurationText(), Edge(theme_->GetTextEdge())));
1538 
1539 #ifndef OHOS_STANDARD_SYSTEM
1540     rowChildren.emplace_back(SetPadding(CreateFullScreenBtn(), Edge(theme_->GetBtnEdge())));
1541 #endif
1542 
1543     auto decoration = AceType::MakeRefPtr<Decoration>();
1544     decoration->SetBackgroundColor(theme_->GetBkgColor());
1545     auto box = AceType::MakeRefPtr<BoxComponent>();
1546     box->SetBackDecoration(decoration);
1547     auto row = AceType::MakeRefPtr<RowComponent>(FlexAlign::CENTER, FlexAlign::CENTER, rowChildren);
1548     row->SetTextDirection(textDirection_);
1549     box->SetChild(row);
1550 
1551     auto gestureListener = AceType::MakeRefPtr<GestureListenerComponent>(box);
1552     gestureListener->SetOnClickId(shieldId_);
1553     gestureListener->SetOnLongPressId(shieldId_);
1554 
1555     return gestureListener;
1556 }
1557 
CreatePoster()1558 const RefPtr<Component> VideoElement::CreatePoster()
1559 {
1560     RefPtr<ImageComponent> image;
1561     if (posterImage_) {
1562         image = posterImage_;
1563     } else {
1564         image = AceType::MakeRefPtr<ImageComponent>(poster_);
1565     }
1566     if (!image) {
1567         LOGE("create poster image fail");
1568         return nullptr;
1569     }
1570     image->SetImageFit(imageFit_);
1571     image->SetImageObjectPosition(imagePosition_);
1572     image->SetFitMaxSize(true);
1573 
1574     std::list<RefPtr<Component>> childrenAlign;
1575     childrenAlign.emplace_back(image);
1576 
1577     auto box = AceType::MakeRefPtr<BoxComponent>();
1578     box->SetChild(AceType::MakeRefPtr<AlignComponent>(childrenAlign, Alignment::CENTER));
1579     return box;
1580 }
1581 
CreateChild()1582 const RefPtr<Component> VideoElement::CreateChild()
1583 {
1584     RefPtr<Component> child;
1585     if (isInitialState_ && (!poster_.empty() || posterImage_)) {
1586         std::list<RefPtr<Component>> columnChildren;
1587 #ifndef OHOS_STANDARD_SYSTEM
1588         columnChildren.emplace_back(AceType::MakeRefPtr<FlexItemComponent>(VIDEO_CHILD_COMMON_FLEX_GROW,
1589             VIDEO_CHILD_COMMON_FLEX_SHRINK, VIDEO_CHILD_COMMON_FLEX_BASIS, CreatePoster()));
1590 #else
1591         if (startTime_ == 0) {
1592             columnChildren.emplace_back(AceType::MakeRefPtr<FlexItemComponent>(VIDEO_CHILD_COMMON_FLEX_GROW,
1593                 VIDEO_CHILD_COMMON_FLEX_SHRINK, VIDEO_CHILD_COMMON_FLEX_BASIS, CreatePoster()));
1594         }
1595 #endif
1596         if (needControls_) {
1597             columnChildren.emplace_back(CreateControl());
1598         } else if (IsDeclarativePara()) {
1599             columnChildren.emplace_back(AceType::MakeRefPtr<BoxComponent>());
1600         }
1601         child = AceType::MakeRefPtr<ColumnComponent>(FlexAlign::FLEX_END, FlexAlign::SPACE_AROUND, columnChildren);
1602     } else if (needControls_) {
1603         std::list<RefPtr<Component>> childrenAlign;
1604         childrenAlign.emplace_back(CreateControl());
1605         child = AceType::MakeRefPtr<AlignComponent>(childrenAlign, Alignment::BOTTOM_RIGHT);
1606     }
1607 
1608     if (child) {
1609         auto display = AceType::MakeRefPtr<DisplayComponent>(child);
1610         if (!display) {
1611             LOGE("Create display component failed. display is null.");
1612             return display;
1613         }
1614         auto textureRender = GetRenderNode();
1615         if (!textureRender) {
1616             return display;
1617         }
1618         auto displayRender = AceType::DynamicCast<RenderDisplay>(textureRender->GetFirstChild());
1619         if (!displayRender) {
1620             return display;
1621         }
1622         uint8_t opacity = displayRender->GetOpacity();
1623         display->SetOpacity(opacity * 1.0 / UINT8_MAX);
1624         return display;
1625     } else {
1626         return child;
1627     }
1628 }
1629 
IsDeclarativePara()1630 bool VideoElement::IsDeclarativePara()
1631 {
1632     auto context = context_.Upgrade();
1633     if (!context) {
1634         return false;
1635     }
1636 
1637     return context->GetIsDeclarative();
1638 }
1639 
OnStartBtnClick()1640 void VideoElement::OnStartBtnClick()
1641 {
1642 #ifdef OHOS_STANDARD_SYSTEM
1643     if (!mediaPlayer_) {
1644         LOGE("Media Player is empty");
1645         return;
1646     }
1647     if (mediaPlayer_->IsPlaying()) {
1648 #else
1649     if (isPlaying_) {
1650 #endif
1651         Pause();
1652     } else {
1653         Start();
1654     }
1655 }
1656 
1657 void VideoElement::OnFullScreenBtnClick()
1658 {
1659     if (!isFullScreen_) {
1660         FullScreen();
1661     } else {
1662         ExitFullScreen();
1663     }
1664 }
1665 
1666 void VideoElement::OnSliderChange(const std::string& param)
1667 {
1668     size_t pos = param.find("\"value\":");
1669     if (pos != std::string::npos) {
1670         if (pastPlayingStatus_) {
1671             isPlaying_ = false;
1672             Start();
1673             pastPlayingStatus_ = false;
1674         }
1675         std::stringstream ss;
1676         uint32_t value = 0;
1677 
1678         ss << param.substr(pos + 8); // Need to add the length of "\"value\":".
1679         ss >> value;
1680 
1681         SetCurrentTime(value);
1682         if (onSeeked_) {
1683             std::string param;
1684             if (IsDeclarativePara()) {
1685                 auto json = JsonUtil::Create(true);
1686                 json->Put("time", static_cast<double>(value));
1687                 param = json->ToString();
1688             } else {
1689                 param = std::string("\"seeked\",{\"currenttime\":").append(std::to_string(value)).append("}");
1690             }
1691             onSeeked_(param);
1692         }
1693     }
1694 }
1695 
1696 void VideoElement::OnSliderMoving(const std::string& param)
1697 {
1698     size_t pos = param.find("\"value\":");
1699     if (pos != std::string::npos) {
1700         if (isPlaying_ && !pastPlayingStatus_) {
1701             Pause();
1702             pastPlayingStatus_ = true;
1703         }
1704         std::stringstream ss;
1705         uint32_t value = 0;
1706 
1707         // Need to add the length of "\"value\":".
1708         if (param.size() > (pos + 8)) {
1709             ss << param.substr(pos + 8);
1710             ss >> value;
1711         }
1712 
1713         SetCurrentTime(value);
1714         if (onSeeking_) {
1715             std::string param;
1716             if (IsDeclarativePara()) {
1717                 auto json = JsonUtil::Create(true);
1718                 json->Put("time", static_cast<double>(value));
1719                 param = json->ToString();
1720             } else {
1721                 param = std::string("\"seeking\",{\"currenttime\":").append(std::to_string(value)).append("}");
1722             }
1723             onSeeking_(param);
1724         }
1725     }
1726 }
1727 
1728 void VideoElement::IntTimeToText(uint32_t time, std::string& timeText)
1729 {
1730     // Whether the duration is longer than 1 hour.
1731     bool needShowHour = duration_ > 3600;
1732     timeText = Localization::GetInstance()->FormatDuration(time, needShowHour);
1733 }
1734 
1735 void VideoElement::Start()
1736 {
1737 #ifdef OHOS_STANDARD_SYSTEM
1738     if (mediaPlayer_ == nullptr) {
1739         LOGE("player is null");
1740         return;
1741     }
1742     if (isStop_) {
1743         if (mediaPlayer_->PrepareAsync() != 0) {
1744             LOGE("Player prepare failed");
1745             return;
1746         }
1747     }
1748     if (!mediaPlayer_->IsPlaying()) {
1749         LOGI("Video Start");
1750         auto context = context_.Upgrade();
1751         if (context == nullptr) {
1752             LOGE("context is nullptr");
1753             return;
1754         }
1755         auto platformTask = SingleTaskExecutor::Make(context->GetTaskExecutor(), TaskExecutor::TaskType::BACKGROUND);
1756         platformTask.PostTask([mediaPlayer = mediaPlayer_] { mediaPlayer->Play(); });
1757     }
1758 #else
1759     if (isStop_) {
1760         CreatePlatformResource();
1761         return;
1762     }
1763     if (!isPlaying_ && player_) {
1764         player_->Start();
1765     }
1766 #endif
1767 }
1768 
1769 void VideoElement::Pause()
1770 {
1771 #ifdef OHOS_STANDARD_SYSTEM
1772     if (mediaPlayer_ != nullptr && mediaPlayer_->IsPlaying()) {
1773         LOGI("Video Pause");
1774         mediaPlayer_->Pause();
1775     }
1776 #else
1777     if (isPlaying_ && player_) {
1778         player_->Pause();
1779     }
1780 #endif
1781 }
1782 
1783 void VideoElement::Stop()
1784 {
1785     startTime_ = 0;
1786     OnCurrentTimeChange(0);
1787     OnPlayerStatus(PlaybackStatus::STOPPED);
1788 #ifndef OHOS_STANDARD_SYSTEM
1789     ReleasePlatformResource();
1790 #else
1791     if (mediaPlayer_ != nullptr) {
1792         LOGI("Video Stop");
1793         mediaPlayer_->Stop();
1794     }
1795 #endif
1796     isStop_ = true;
1797 }
1798 
1799 void VideoElement::SetCurrentTime(float currentPos, SeekMode seekMode)
1800 {
1801     LOGI("pos: %{public}lf, mode: %{public}d", currentPos, seekMode);
1802 #ifdef OHOS_STANDARD_SYSTEM
1803     if (mediaPlayer_ != nullptr && GreatOrEqual(currentPos, 0.0) && LessOrEqual(currentPos, duration_)) {
1804         LOGI("Video Seek");
1805         startTime_ = currentPos;
1806         mediaPlayer_->Seek(currentPos * MILLISECONDS_TO_SECONDS, ConvertToMediaSeekMode(seekMode));
1807     }
1808 #else
1809     if (currentPos >= 0 && currentPos < duration_ && player_) {
1810         player_->SeekTo(currentPos);
1811     }
1812 #endif
1813 }
1814 
1815 void VideoElement::FullScreen()
1816 {
1817     if (!isFullScreen_ && !isError_) {
1818         RefPtr<Component> component;
1819 #ifdef OHOS_STANDARD_SYSTEM
1820         if (mediaFullscreenEvent_) {
1821             component = mediaFullscreenEvent_(true, isPlaying_, texture_);
1822         }
1823 #else
1824         if (fullscreenEvent_) {
1825             component = fullscreenEvent_(true, player_, texture_);
1826         }
1827 #endif
1828         if (component) {
1829             auto context = context_.Upgrade();
1830             CHECK_NULL_VOID(context);
1831 
1832             auto stackElement = context->GetLastStack();
1833             CHECK_NULL_VOID(stackElement);
1834 
1835             // add fullscreen component cover component
1836             if (IsDeclarativePara()) {
1837 #ifdef OHOS_STANDARD_SYSTEM
1838                 if (mediaPlayer_ != nullptr && mediaPlayer_->IsPlaying()) {
1839                     mediaPlayer_->Pause();
1840                 }
1841 #endif
1842                 stackElement->PushComponent(AceType::MakeRefPtr<ComposedComponent>("0", "fullscreen", component));
1843             } else {
1844                 auto composedComponent = AceType::DynamicCast<ComposedComponent>(component);
1845                 if (!composedComponent) {
1846                     LOGE("VideoElement::FullScreen: is not ComposedComponent");
1847                     return;
1848                 }
1849                 if (composedComponent->IsInspector()) {
1850                     LOGE("VideoElement::FullScreen: is InspectorComposedComponent");
1851                     return;
1852                 }
1853                 stackElement->PushComponent(
1854                     AceType::MakeRefPtr<ComposedComponent>(composedComponent->GetId() + "fullscreen",
1855                         composedComponent->GetName() + "fullscreen", composedComponent->GetChild()));
1856             }
1857             isFullScreen_ = true;
1858             currentPlatformVersion_ = context->GetMinPlatformVersion();
1859             if (player_ && currentPlatformVersion_ > COMPATIBLE_VERSION) {
1860 #ifndef OHOS_STANDARD_SYSTEM
1861                 player_->SetDirection(direction_);
1862 #endif
1863             }
1864             if (onFullScreenChange_) {
1865                 std::string param;
1866                 if (IsDeclarativePara()) {
1867                     auto json = JsonUtil::Create(true);
1868                     json->Put("fullscreen", isFullScreen_);
1869                     param = json->ToString();
1870                 } else {
1871                     param = std::string("\"fullscreenchange\",{\"fullscreen\":")
1872                                 .append(std::to_string(isFullScreen_))
1873                                 .append("}");
1874                 }
1875                 onFullScreenChange_(param);
1876             }
1877         }
1878     }
1879 }
1880 
1881 void VideoElement::ExitFullScreen()
1882 {
1883 #ifdef OHOS_STANDARD_SYSTEM
1884     if (mediaExitFullscreenEvent_ && isFullScreen_) {
1885         mediaExitFullscreenEvent_(false, isPlaying_, currentPos_);
1886     }
1887 #else
1888     if (fullscreenEvent_) {
1889         fullscreenEvent_(false, nullptr, nullptr);
1890     }
1891 #endif
1892 
1893     if ((!isExternalResource_ && isFullScreen_) || isMediaPlayerFullStatus_) {
1894         auto context = context_.Upgrade();
1895         if (!context) {
1896             return;
1897         }
1898 
1899         auto stackElement = context->GetLastStack();
1900         if (!stackElement) {
1901             return;
1902         }
1903         stackElement->PopVideo();
1904         currentPlatformVersion_ = context->GetMinPlatformVersion();
1905         if (player_ && currentPlatformVersion_ > COMPATIBLE_VERSION) {
1906 #ifndef OHOS_STANDARD_SYSTEM
1907             player_->SetLandscape();
1908 #endif
1909         }
1910         isFullScreen_ = false;
1911         if (onFullScreenChange_) {
1912             std::string param;
1913             if (IsDeclarativePara()) {
1914                 auto json = JsonUtil::Create(true);
1915                 json->Put("fullscreen", isFullScreen_);
1916                 param = json->ToString();
1917             } else {
1918                 param = std::string("\"fullscreenchange\",{\"fullscreen\":")
1919                             .append(std::to_string(isFullScreen_))
1920                             .append("}");
1921             }
1922             onFullScreenChange_(param);
1923         }
1924         if (renderNode_) {
1925             renderNode_->MarkNeedLayout();
1926         }
1927     }
1928 }
1929 
1930 void VideoElement::SetVolume(float volume)
1931 {
1932     LOGI("volume: %{public}lf", volume);
1933 #ifdef OHOS_STANDARD_SYSTEM
1934     if (mediaPlayer_ != nullptr) {
1935         mediaPlayer_->SetVolume(volume, volume);
1936     }
1937 #else
1938     if (player_) {
1939         player_->SetVolume(volume);
1940     }
1941 #endif
1942 }
1943 
1944 void VideoElement::EnableLooping(bool loop)
1945 {
1946     LOGI("loop: %{public}d", loop);
1947 #ifdef OHOS_STANDARD_SYSTEM
1948     if (mediaPlayer_) {
1949         mediaPlayer_->SetLooping(loop);
1950     }
1951 #else
1952     if (player_) {
1953         player_->EnableLooping(loop);
1954     }
1955 #endif
1956 }
1957 
1958 void VideoElement::SetSpeed(float speed)
1959 {
1960     LOGI("speed: %{public}lf", speed);
1961     if (speed <= ILLEGAL_SPEED) {
1962         LOGE("speed is not valid: %{public}lf", speed);
1963         return;
1964     }
1965 #ifdef OHOS_STANDARD_SYSTEM
1966     if (mediaPlayer_ != nullptr) {
1967         mediaPlayer_->SetPlaybackSpeed(ConvertToMediaPlaybackSpeed(speed));
1968     }
1969 #else
1970     if (player_) {
1971         player_->SetSpeed(speed);
1972     }
1973 #endif
1974 }
1975 
1976 void VideoElement::Dump()
1977 {
1978     if (texture_) {
1979         DumpLog::GetInstance().AddDesc("texture:", texture_->GetHashCode());
1980     }
1981     if (player_) {
1982         DumpLog::GetInstance().AddDesc("player:", player_->GetHashCode());
1983     }
1984     DumpLog::GetInstance().AddDesc("isError:", isError_);
1985     DumpLog::GetInstance().AddDesc("poster:", poster_);
1986     DumpLog::GetInstance().AddDesc("isInitialState_:", isInitialState_);
1987     DumpLog::GetInstance().AddDesc("videoWidth:", videoWidth_);
1988     DumpLog::GetInstance().AddDesc("videoHeight:", videoHeight_);
1989     DumpLog::GetInstance().AddDesc("isReady:", isReady_);
1990     DumpLog::GetInstance().AddDesc("src:", src_);
1991     DumpLog::GetInstance().AddDesc("isAutoPlay:", isAutoPlay_);
1992     DumpLog::GetInstance().AddDesc("needControls:", needControls_);
1993     DumpLog::GetInstance().AddDesc("isMute:", isMute_);
1994 }
1995 
1996 bool VideoElement::OnKeyEvent(const KeyEvent& keyEvent)
1997 {
1998     if (keyEvent.action != KeyAction::UP) {
1999         return false;
2000     }
2001     switch (keyEvent.code) {
2002         case KeyCode::KEY_BACK:
2003         case KeyCode::KEY_ESCAPE: {
2004             if (isFullScreen_) {
2005                 ExitFullScreen();
2006                 return true;
2007             }
2008             break;
2009         }
2010         case KeyCode::KEY_ENTER: {
2011             if (!isFullScreen_) {
2012                 FullScreen();
2013             } else {
2014                 OnStartBtnClick();
2015             }
2016             return true;
2017         }
2018         case KeyCode::TV_CONTROL_MEDIA_PLAY: {
2019             OnStartBtnClick();
2020             return true;
2021         }
2022         case KeyCode::TV_CONTROL_LEFT: {
2023             if (isFullScreen_) {
2024                 OnKeyLeft();
2025                 if (!isPlaying_) {
2026                     Start();
2027                 }
2028                 return true;
2029             }
2030             break;
2031         }
2032         case KeyCode::TV_CONTROL_RIGHT: {
2033             if (isFullScreen_) {
2034                 OnKeyRight();
2035                 if (!isPlaying_) {
2036                     Start();
2037                 }
2038                 return true;
2039             }
2040             break;
2041         }
2042         default:
2043             break;
2044     }
2045     return false;
2046 }
2047 
2048 void VideoElement::OnKeyLeft()
2049 {
2050     SetCurrentTime(currentPos_ > VIDEO_SEEK_STEP ? currentPos_ - VIDEO_SEEK_STEP : 0);
2051 }
2052 
2053 void VideoElement::OnKeyRight()
2054 {
2055     if (currentPos_ + VIDEO_SEEK_STEP < duration_) {
2056         SetCurrentTime(currentPos_ + VIDEO_SEEK_STEP);
2057     }
2058 }
2059 
2060 void VideoElement::OnTextureRefresh()
2061 {
2062     auto context = context_.Upgrade();
2063     if (context) {
2064         context->MarkForcedRefresh();
2065     }
2066 }
2067 
2068 } // namespace OHOS::Ace
2069