• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "core/components_ng/pattern/video/video_pattern.h"
17 
18 #include "base/geometry/dimension.h"
19 #include "base/geometry/ng/size_t.h"
20 #include "base/i18n/localization.h"
21 #include "base/json/json_util.h"
22 #include "base/thread/task_executor.h"
23 #include "base/utils/string_utils.h"
24 #include "base/utils/system_properties.h"
25 #include "base/utils/utils.h"
26 #include "core/components/common/layout/constants.h"
27 #include "core/components/common/properties/color.h"
28 #include "core/components/declaration/button/button_declaration.h"
29 #include "core/components/video/video_theme.h"
30 #include "core/components/video/video_utils.h"
31 #include "core/components_ng/pattern/button/button_event_hub.h"
32 #include "core/components_ng/pattern/button/button_layout_property.h"
33 #include "core/components_ng/pattern/button/button_pattern.h"
34 #include "core/components_ng/pattern/image/image_layout_property.h"
35 #include "core/components_ng/pattern/image/image_pattern.h"
36 #include "core/components_ng/pattern/linear_layout/linear_layout_pattern.h"
37 #include "core/components_ng/pattern/linear_layout/linear_layout_property.h"
38 #include "core/components_ng/pattern/slider/slider_event_hub.h"
39 #include "core/components_ng/pattern/slider/slider_layout_property.h"
40 #include "core/components_ng/pattern/slider/slider_paint_property.h"
41 #include "core/components_ng/pattern/slider/slider_pattern.h"
42 #include "core/components_ng/pattern/text/text_layout_property.h"
43 #include "core/components_ng/pattern/text/text_pattern.h"
44 #include "core/components_ng/pattern/video/video_event_hub.h"
45 #include "core/components_ng/pattern/video/video_layout_property.h"
46 #include "core/components_ng/property/property.h"
47 #include "core/components_v2/inspector/inspector_constants.h"
48 #include "core/pipeline_ng/pipeline_context.h"
49 
50 namespace OHOS::Ace::NG {
51 namespace {
52 constexpr int32_t SECONDS_PER_HOUR = 3600;
53 constexpr int32_t MILLISECONDS_TO_SECONDS = 1000;
54 constexpr uint32_t CURRENT_POS = 1;
55 constexpr uint32_t SLIDER_POS = 2;
56 constexpr uint32_t DURATION_POS = 3;
57 constexpr uint32_t FULL_SCREEN_POS = 4;
58 constexpr int32_t AVERAGE_VALUE = 2;
59 enum SliderChangeMode {
60     BEGIN = 0,
61     MOVING,
62     END,
63 };
64 
IntTimeToText(uint32_t time)65 std::string IntTimeToText(uint32_t time)
66 {
67     bool needShowHour = time > SECONDS_PER_HOUR;
68     return Localization::GetInstance()->FormatDuration(time, needShowHour);
69 }
70 
CalculateFitContain(const SizeF & videoSize,const SizeF & layoutSize)71 SizeF CalculateFitContain(const SizeF& videoSize, const SizeF& layoutSize)
72 {
73     double layoutRatio = NearZero(layoutSize.Height()) ? 0.0 : layoutSize.Width() / layoutSize.Height();
74     double sourceRatio = NearZero(videoSize.Height()) ? layoutRatio : videoSize.Width() / videoSize.Height();
75 
76     if (NearZero(layoutRatio) || NearZero(sourceRatio)) {
77         return layoutSize;
78     }
79     if (sourceRatio < layoutRatio) {
80         return { static_cast<float>(sourceRatio) * layoutSize.Height(), layoutSize.Height() };
81     }
82     return { layoutSize.Width(), static_cast<float>(layoutSize.Width() / sourceRatio) };
83 }
84 
CalculateFitFill(const SizeF & layoutSize)85 SizeF CalculateFitFill(const SizeF& layoutSize)
86 {
87     return layoutSize;
88 }
89 
CalculateFitCover(const SizeF & videoSize,const SizeF & layoutSize)90 SizeF CalculateFitCover(const SizeF& videoSize, const SizeF& layoutSize)
91 {
92     double layoutRatio = NearZero(layoutSize.Height()) ? 0.0 : layoutSize.Width() / layoutSize.Height();
93     double sourceRatio = NearZero(videoSize.Height()) ? layoutRatio : videoSize.Width() / videoSize.Height();
94 
95     if (NearZero(layoutRatio) || NearZero(sourceRatio)) {
96         return layoutSize;
97     }
98     if (sourceRatio < layoutRatio) {
99         return { layoutSize.Width(), static_cast<float>(layoutSize.Width() / sourceRatio) };
100     }
101     return { static_cast<float>(layoutSize.Height() * sourceRatio), layoutSize.Height() };
102 }
103 
CalculateFitNone(const SizeF & videoSize)104 SizeF CalculateFitNone(const SizeF& videoSize)
105 {
106     return videoSize;
107 }
108 
CalculateFitScaleDown(const SizeF & videoSize,const SizeF & layoutSize)109 SizeF CalculateFitScaleDown(const SizeF& videoSize, const SizeF& layoutSize)
110 {
111     if (layoutSize.Width() > videoSize.Width()) {
112         return CalculateFitNone(videoSize);
113     }
114     return CalculateFitContain(videoSize, layoutSize);
115 }
116 
MeasureVideoContentLayout(const SizeF & layoutSize,const RefPtr<VideoLayoutProperty> & layoutProperty)117 SizeF MeasureVideoContentLayout(const SizeF& layoutSize, const RefPtr<VideoLayoutProperty>& layoutProperty)
118 {
119     if (!layoutProperty || !layoutProperty->HasVideoSize()) {
120         LOGW("VideoSize has not set");
121         return layoutSize;
122     }
123 
124     auto videoSize = layoutProperty->GetVideoSizeValue(SizeF(0, 0));
125     LOGD("Video original size before fitting is %{public}s", videoSize.ToString().c_str());
126     auto imageFit = layoutProperty->GetObjectFitValue(ImageFit::COVER);
127     SizeF contentSize = { 0.0, 0.0 };
128     switch (imageFit) {
129         case ImageFit::CONTAIN:
130             contentSize = CalculateFitContain(videoSize, layoutSize);
131             break;
132         case ImageFit::FILL:
133             contentSize = CalculateFitFill(layoutSize);
134             break;
135         case ImageFit::COVER:
136             contentSize = CalculateFitCover(videoSize, layoutSize);
137             break;
138         case ImageFit::NONE:
139             contentSize = CalculateFitNone(videoSize);
140             break;
141         case ImageFit::SCALE_DOWN:
142             contentSize = CalculateFitScaleDown(videoSize, layoutSize);
143             break;
144         default:
145             contentSize = CalculateFitContain(videoSize, layoutSize);
146     }
147 
148     // Just return contentSize as the video frame area.
149     LOGD("Video contentSize after fitting is %{public}s", contentSize.ToString().c_str());
150     return contentSize;
151 }
152 } // namespace
153 
VideoPattern(const RefPtr<VideoControllerV2> & videoController)154 VideoPattern::VideoPattern(const RefPtr<VideoControllerV2>& videoController) : videoControllerV2_(videoController) {}
155 
ResetStatus()156 void VideoPattern::ResetStatus()
157 {
158     isInitialState_ = true;
159     isPlaying_ = false;
160 }
161 
UpdateMediaPlayer()162 void VideoPattern::UpdateMediaPlayer()
163 {
164     if (!mediaPlayer_->IsMediaPlayerValid()) {
165         mediaPlayer_->CreateMediaPlayer();
166         if (!mediaPlayer_->IsMediaPlayerValid()) {
167             LOGE("create media player failed");
168             return;
169         }
170     }
171     PrepareMediaPlayer();
172 }
173 
PrepareMediaPlayer()174 void VideoPattern::PrepareMediaPlayer()
175 {
176     auto videoLayoutProperty = GetLayoutProperty<VideoLayoutProperty>();
177     // src has not set/changed
178     if (!videoLayoutProperty->HasVideoSource() || videoLayoutProperty->GetVideoSource() == src_) {
179         return;
180     }
181 
182     if (!mediaPlayer_->IsMediaPlayerValid()) {
183         LOGE("media player is invalid.");
184         return;
185     }
186 
187     ResetStatus();
188     mediaPlayer_->ResetMediaPlayer();
189     float volume = muted_ ? 0.0f : 1.0f;
190     mediaPlayer_->SetVolume(volume, volume);
191     if (!SetSourceForMediaPlayer()) {
192         LOGE("set source for mediaPlayer failed");
193         return;
194     }
195 
196     RegisterMediaPlayerEvent();
197     PrepareSurface();
198     if (mediaPlayer_->PrepareAsync() != 0) {
199         LOGE("Player prepare failed");
200     }
201 }
202 
SetSourceForMediaPlayer()203 bool VideoPattern::SetSourceForMediaPlayer()
204 {
205     auto videoLayoutProperty = GetLayoutProperty<VideoLayoutProperty>();
206     auto videoSrc = videoLayoutProperty->GetVideoSource().value();
207     src_ = videoSrc;
208     return mediaPlayer_->SetSource(videoSrc);
209 }
210 
RegisterMediaPlayerEvent()211 void VideoPattern::RegisterMediaPlayerEvent()
212 {
213     auto context = PipelineContext::GetCurrentContext();
214     CHECK_NULL_VOID(context);
215 
216     auto uiTaskExecutor = SingleTaskExecutor::Make(context->GetTaskExecutor(), TaskExecutor::TaskType::UI);
217     auto videoPattern = WeakClaim(this);
218 
219     auto&& positionUpdatedEvent = [videoPattern, uiTaskExecutor](uint32_t currentPos) {
220         uiTaskExecutor.PostSyncTask([&videoPattern, currentPos] {
221             auto video = videoPattern.Upgrade();
222             CHECK_NULL_VOID_NOLOG(video);
223             video->OnCurrentTimeChange(currentPos);
224         });
225     };
226 
227     auto&& stateChangedEvent = [videoPattern, uiTaskExecutor](PlaybackStatus status) {
228         uiTaskExecutor.PostSyncTask([&videoPattern, status] {
229             auto video = videoPattern.Upgrade();
230             CHECK_NULL_VOID_NOLOG(video);
231             LOGI("OnPlayerStatus");
232             video->OnPlayerStatus(status);
233         });
234     };
235 
236     auto&& errorEvent = [videoPattern, uiTaskExecutor]() {
237         uiTaskExecutor.PostTask([&videoPattern] {
238             auto video = videoPattern.Upgrade();
239             CHECK_NULL_VOID_NOLOG(video);
240             LOGW("OnError");
241             video->OnError("");
242         });
243     };
244 
245     auto&& resolutionChangeEvent = [videoPattern, uiTaskExecutor]() {
246         uiTaskExecutor.PostSyncTask([&videoPattern] {
247             auto video = videoPattern.Upgrade();
248             CHECK_NULL_VOID_NOLOG(video);
249             video->OnResolutionChange();
250         });
251     };
252 
253     mediaPlayer_->RegisterMediaPlayerEvent(positionUpdatedEvent, stateChangedEvent, errorEvent, resolutionChangeEvent);
254 }
255 
OnCurrentTimeChange(uint32_t currentPos)256 void VideoPattern::OnCurrentTimeChange(uint32_t currentPos)
257 {
258     isInitialState_ = isInitialState_ ? currentPos == 0 : false;
259     if (currentPos == currentPos_ || isStop_) {
260         return;
261     }
262 
263     if (duration_ == 0) {
264         int32_t duration = 0;
265         if (mediaPlayer_->GetDuration(duration) == 0) {
266             duration_ = duration / MILLISECONDS_TO_SECONDS;
267             OnUpdateTime(duration_, DURATION_POS);
268         }
269     }
270 
271     OnUpdateTime(currentPos, CURRENT_POS);
272     currentPos_ = currentPos;
273     auto eventHub = GetEventHub<VideoEventHub>();
274     auto json = JsonUtil::Create(true);
275     json->Put("time", static_cast<double>(currentPos));
276     auto param = json->ToString();
277     eventHub->FireUpdateEvent(param);
278 }
279 
OnPlayerStatus(PlaybackStatus status)280 void VideoPattern::OnPlayerStatus(PlaybackStatus status)
281 {
282     bool isPlaying = (status == PlaybackStatus::STARTED);
283     if (isPlaying_ != isPlaying) {
284         isPlaying_ = isPlaying;
285         ChangePlayButtonTag();
286     }
287 
288     if (isInitialState_) {
289         isInitialState_ = !isPlaying;
290     }
291 
292     if (isPlaying) {
293         auto json = JsonUtil::Create(true);
294         json->Put("start", "");
295         auto param = json->ToString();
296         auto eventHub = GetEventHub<VideoEventHub>();
297         eventHub->FireStartEvent(param);
298     } else {
299         auto json = JsonUtil::Create(true);
300         json->Put("pause", "");
301         auto param = json->ToString();
302         auto eventHub = GetEventHub<VideoEventHub>();
303         eventHub->FirePauseEvent(param);
304     }
305 
306     if (status == PlaybackStatus::PREPARED) {
307         auto context = PipelineContext::GetCurrentContext();
308         CHECK_NULL_VOID(context);
309         if (!mediaPlayer_->IsMediaPlayerValid()) {
310             return;
311         }
312 
313         auto uiTaskExecutor = SingleTaskExecutor::Make(context->GetTaskExecutor(), TaskExecutor::TaskType::UI);
314         Size videoSize = Size(mediaPlayer_->GetVideoWidth(), mediaPlayer_->GetVideoHeight());
315         int32_t milliSecondDuration = 0;
316         mediaPlayer_->GetDuration(milliSecondDuration);
317         uiTaskExecutor.PostSyncTask([this, videoSize, duration = milliSecondDuration / MILLISECONDS_TO_SECONDS] {
318             LOGI("Video OnPrepared video size: %{public}s", videoSize.ToString().c_str());
319             this->OnPrepared(videoSize.Width(), videoSize.Height(), duration, 0, true);
320         });
321         return;
322     }
323 
324     if (status == PlaybackStatus::PLAYBACK_COMPLETE) {
325         OnCompletion();
326     }
327 }
328 
OnError(const std::string & errorId)329 void VideoPattern::OnError(const std::string& errorId)
330 {
331     std::string errorcode = Localization::GetInstance()->GetErrorDescription(errorId);
332     auto json = JsonUtil::Create(true);
333     json->Put("error", "");
334     auto param = json->ToString();
335     auto eventHub = GetEventHub<VideoEventHub>();
336     eventHub->FireErrorEvent(param);
337 }
338 
OnResolutionChange() const339 void VideoPattern::OnResolutionChange() const
340 {
341     if (!mediaPlayer_->IsMediaPlayerValid()) {
342         return;
343     }
344     auto host = GetHost();
345     CHECK_NULL_VOID(host);
346     SizeF videoSize =
347         SizeF(static_cast<float>(mediaPlayer_->GetVideoWidth()), static_cast<float>(mediaPlayer_->GetVideoHeight()));
348     auto videoLayoutProperty = host->GetLayoutProperty<VideoLayoutProperty>();
349     videoLayoutProperty->UpdateVideoSize(videoSize);
350     LOGI("OnResolutionChange video size: %{public}s", videoSize.ToString().c_str());
351     host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
352 }
353 
OnPrepared(double width,double height,uint32_t duration,uint32_t currentPos,bool needFireEvent)354 void VideoPattern::OnPrepared(double width, double height, uint32_t duration, uint32_t currentPos, bool needFireEvent)
355 {
356     auto host = GetHost();
357     CHECK_NULL_VOID(host);
358     auto videoLayoutProperty = host->GetLayoutProperty<VideoLayoutProperty>();
359     videoLayoutProperty->UpdateVideoSize(SizeF(static_cast<float>(width), static_cast<float>(height)));
360     host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
361 
362     duration_ = duration;
363     currentPos_ = currentPos;
364     isInitialState_ = currentPos != 0 ? false : isInitialState_;
365     isPlaying_ = mediaPlayer_->IsPlaying();
366 
367     OnUpdateTime(duration_, DURATION_POS);
368     OnUpdateTime(currentPos_, CURRENT_POS);
369 
370     auto needControlBar = videoLayoutProperty->GetControlsValue(true);
371     if (needControlBar) {
372         RefPtr<UINode> controlBar = nullptr;
373         auto children = host->GetChildren();
374         for (const auto& child : children) {
375             if (child->GetTag() == V2::ROW_ETS_TAG) {
376                 controlBar = child;
377                 break;
378             }
379         }
380         CHECK_NULL_VOID(controlBar);
381         auto sliderNode = DynamicCast<FrameNode>(controlBar->GetChildAtIndex(SLIDER_POS));
382         auto sliderPaintProperty = sliderNode->GetPaintProperty<SliderPaintProperty>();
383         CHECK_NULL_VOID(sliderPaintProperty);
384         sliderPaintProperty->UpdateMin(0.0f);
385         sliderPaintProperty->UpdateMax(static_cast<float>(duration_));
386         sliderNode->MarkModifyDone();
387         auto playBtn = DynamicCast<FrameNode>(controlBar->GetChildAtIndex(0));
388         ChangePlayButtonTag(playBtn);
389     }
390 
391     if (needFireEvent) {
392         auto json = JsonUtil::Create(true);
393         json->Put("duration", static_cast<double>(duration_));
394         auto param = json->ToString();
395         auto eventHub = GetEventHub<VideoEventHub>();
396         eventHub->FirePreparedEvent(param);
397     }
398     UpdateLooping();
399     SetSpeed();
400 
401     if (isStop_) {
402         isStop_ = false;
403         Start();
404     }
405 
406     if (autoPlay_) {
407         Start();
408     }
409 }
410 
OnCompletion()411 void VideoPattern::OnCompletion()
412 {
413     isPlaying_ = false;
414     currentPos_ = duration_;
415     OnUpdateTime(currentPos_, CURRENT_POS);
416     auto json = JsonUtil::Create(true);
417     json->Put("finish", "");
418     auto param = json->ToString();
419     auto eventHub = GetEventHub<VideoEventHub>();
420     eventHub->FireFinishEvent(param);
421 }
422 
HasPlayer() const423 bool VideoPattern::HasPlayer() const
424 {
425     return mediaPlayer_ != nullptr;
426 }
427 
HiddenChange(bool hidden)428 void VideoPattern::HiddenChange(bool hidden)
429 {
430     if (isPlaying_ && hidden && HasPlayer()) {
431         pastPlayingStatus_ = isPlaying_;
432         Pause();
433         return;
434     }
435 
436     if (!hidden && pastPlayingStatus_) {
437         pastPlayingStatus_ = false;
438         Start();
439     }
440 }
441 
OnVisibleChange(bool isVisible)442 void VideoPattern::OnVisibleChange(bool isVisible)
443 {
444     if (hiddenChangeEvent_) {
445         hiddenChangeEvent_(!isVisible);
446     }
447 }
448 
UpdateLooping()449 void VideoPattern::UpdateLooping()
450 {
451     if (mediaPlayer_->IsMediaPlayerValid()) {
452         mediaPlayer_->SetLooping(loop_);
453     }
454 }
455 
SetSpeed()456 void VideoPattern::SetSpeed()
457 {
458     if (mediaPlayer_->IsMediaPlayerValid()) {
459         mediaPlayer_->SetPlaybackSpeed(static_cast<float>(progressRate_));
460     }
461 }
462 
UpdateMuted()463 void VideoPattern::UpdateMuted()
464 {
465     if (mediaPlayer_->IsMediaPlayerValid()) {
466         float volume = muted_ ? 0.0f : 1.0f;
467         mediaPlayer_->SetVolume(volume, volume);
468     }
469 }
470 
OnUpdateTime(uint32_t time,int pos) const471 void VideoPattern::OnUpdateTime(uint32_t time, int pos) const
472 {
473     auto host = GetHost();
474     CHECK_NULL_VOID(host);
475     auto layoutProperty = host->GetLayoutProperty<VideoLayoutProperty>();
476     CHECK_NULL_VOID(layoutProperty);
477     bool needControlBar = layoutProperty->GetControlsValue(true);
478     if (!needControlBar) {
479         return;
480     }
481 
482     RefPtr<UINode> controlBar = nullptr;
483     auto children = host->GetChildren();
484     for (const auto& child : children) {
485         if (child->GetTag() == V2::ROW_ETS_TAG) {
486             controlBar = child;
487             break;
488         }
489     }
490 
491     CHECK_NULL_VOID(controlBar);
492     auto durationNode = DynamicCast<FrameNode>(controlBar->GetChildAtIndex(pos));
493     auto textLayoutProperty = durationNode->GetLayoutProperty<TextLayoutProperty>();
494     CHECK_NULL_VOID(textLayoutProperty);
495     std::string timeText = IntTimeToText(time);
496     textLayoutProperty->UpdateContent(timeText);
497     durationNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
498     durationNode->MarkModifyDone();
499     if (pos == CURRENT_POS) {
500         auto sliderNode = DynamicCast<FrameNode>(controlBar->GetChildAtIndex(SLIDER_POS));
501         auto sliderPaintProperty = sliderNode->GetPaintProperty<SliderPaintProperty>();
502         CHECK_NULL_VOID(sliderPaintProperty);
503         sliderPaintProperty->UpdateValue(static_cast<float>(time));
504         sliderNode->MarkModifyDone();
505     }
506 }
507 
PrepareSurface()508 void VideoPattern::PrepareSurface()
509 {
510     if (renderSurface_->IsSurfaceValid()) {
511         return;
512     }
513     if (!SystemProperties::GetExtSurfaceEnabled()) {
514         renderSurface_->SetRenderContext(renderContextForMediaPlayer_);
515     }
516     renderSurface_->InitSurface();
517     mediaPlayer_->SetRenderSurface(renderSurface_);
518     if (mediaPlayer_->SetSurface() != 0) {
519         LOGE("Player SetVideoSurface failed");
520         return;
521     }
522 }
523 
OnAttachToFrameNode()524 void VideoPattern::OnAttachToFrameNode()
525 {
526     SetMethodCall();
527     auto host = GetHost();
528     CHECK_NULL_VOID(host);
529     auto renderContext = host->GetRenderContext();
530     CHECK_NULL_VOID(renderContext);
531     renderContextForMediaPlayer_->InitContext(false, "MediaPlayerSurface");
532     renderContext->UpdateBackgroundColor(Color::BLACK);
533     renderContextForMediaPlayer_->UpdateBackgroundColor(Color::BLACK);
534     renderContext->SetClipToBounds(true);
535 }
536 
OnModifyDone()537 void VideoPattern::OnModifyDone()
538 {
539     if (!hiddenChangeEvent_) {
540         SetHiddenChangeEvent([weak = WeakClaim(this)](bool hidden) {
541             auto videoPattern = weak.Upgrade();
542             CHECK_NULL_VOID_NOLOG(videoPattern);
543             videoPattern->HiddenChange(hidden);
544         });
545     }
546     AddPreviewNodeIfNeeded();
547     // Create the control bar
548     AddControlBarNodeIfNeeded();
549     UpdateMediaPlayer();
550     UpdateVideoProperty();
551     if (SystemProperties::GetExtSurfaceEnabled()) {
552         auto pipelineContext = PipelineContext::GetCurrentContext();
553         CHECK_NULL_VOID(pipelineContext);
554         auto host = GetHost();
555         CHECK_NULL_VOID(host);
556         pipelineContext->AddOnAreaChangeNode(host->GetId());
557     }
558 }
559 
AddPreviewNodeIfNeeded()560 void VideoPattern::AddPreviewNodeIfNeeded()
561 {
562     auto layoutProperty = GetLayoutProperty<VideoLayoutProperty>();
563     if (!isInitialState_ || !layoutProperty->HasPosterImageInfo()) {
564         return;
565     }
566 
567     auto host = GetHost();
568     CHECK_NULL_VOID(host);
569     bool isExist = false;
570     auto children = host->GetChildren();
571     auto posterSourceInfo = layoutProperty->GetPosterImageInfo().value();
572     auto imageFit = layoutProperty->GetObjectFitValue(ImageFit::COVER);
573 
574     for (const auto& child : children) {
575         if (child->GetTag() == V2::IMAGE_ETS_TAG) {
576             isExist = true;
577             auto image = AceType::DynamicCast<FrameNode>(child);
578             auto posterLayoutProperty = image->GetLayoutProperty<ImageLayoutProperty>();
579             posterLayoutProperty->UpdateImageSourceInfo(posterSourceInfo);
580             posterLayoutProperty->UpdateImageFit(imageFit);
581             image->MarkModifyDone();
582             break;
583         }
584     }
585 
586     if (!isExist) {
587         auto posterNode = FrameNode::CreateFrameNode(V2::IMAGE_ETS_TAG, -1, AceType::MakeRefPtr<ImagePattern>());
588         CHECK_NULL_VOID(posterNode);
589         auto posterLayoutProperty = posterNode->GetLayoutProperty<ImageLayoutProperty>();
590         posterLayoutProperty->UpdateImageSourceInfo(posterSourceInfo);
591         posterLayoutProperty->UpdateImageFit(imageFit);
592         host->AddChild(posterNode);
593         posterNode->MarkModifyDone();
594     }
595 }
596 
AddControlBarNodeIfNeeded()597 void VideoPattern::AddControlBarNodeIfNeeded()
598 {
599     auto layoutProperty = GetLayoutProperty<VideoLayoutProperty>();
600     auto host = GetHost();
601     CHECK_NULL_VOID(host);
602     auto children = host->GetChildren();
603     if (layoutProperty->GetControlsValue(true)) {
604         bool isExist = false;
605         for (const auto& child : children) {
606             if (child->GetTag() == V2::ROW_ETS_TAG) {
607                 isExist = true;
608                 break;
609             }
610         }
611         if (!isExist) {
612             auto controlBar = CreateControlBar();
613             host->AddChild(controlBar);
614         }
615     } else {
616         auto iter = children.begin();
617         while (iter != children.end()) {
618             if ((*iter)->GetTag() == V2::ROW_ETS_TAG) {
619                 host->RemoveChild(*iter);
620                 host->RebuildRenderContextTree();
621                 auto context = PipelineContext::GetCurrentContext();
622                 CHECK_NULL_VOID(context);
623                 context->RequestFrame();
624                 break;
625             }
626             ++iter;
627         }
628     }
629 }
630 
UpdateVideoProperty()631 void VideoPattern::UpdateVideoProperty()
632 {
633     if (isInitialState_ && autoPlay_) {
634         Start();
635     }
636 
637     SetSpeed();
638     UpdateLooping();
639     UpdateMuted();
640 }
641 
OnRebuildFrame()642 void VideoPattern::OnRebuildFrame()
643 {
644     if (!renderSurface_->IsSurfaceValid()) {
645         LOGE("surface not valid");
646         return;
647     }
648     auto host = GetHost();
649     CHECK_NULL_VOID(host);
650     auto renderContext = host->GetRenderContext();
651     CHECK_NULL_VOID(renderContext);
652     renderContext->AddChild(renderContextForMediaPlayer_, 0);
653 }
654 
OnDirtyLayoutWrapperSwap(const RefPtr<LayoutWrapper> & dirty,const DirtySwapConfig & config)655 bool VideoPattern::OnDirtyLayoutWrapperSwap(const RefPtr<LayoutWrapper>& dirty, const DirtySwapConfig& config)
656 {
657     if (config.skipMeasure || dirty->SkipMeasureContent()) {
658         return false;
659     }
660 
661     auto geometryNode = dirty->GetGeometryNode();
662     CHECK_NULL_RETURN(geometryNode, false);
663     auto videoNodeSize = geometryNode->GetContentSize();
664     auto videoNodeOffset = geometryNode->GetContentOffset();
665     auto layoutProperty = GetLayoutProperty<VideoLayoutProperty>();
666     CHECK_NULL_RETURN(layoutProperty, false);
667     auto videoFrameSize = MeasureVideoContentLayout(videoNodeSize, layoutProperty);
668     // Change the surface layout for drawing video frames
669     renderContextForMediaPlayer_->SetBounds(
670         videoNodeOffset.GetX() + (videoNodeSize.Width() - videoFrameSize.Width()) / AVERAGE_VALUE,
671         videoNodeOffset.GetY() + (videoNodeSize.Height() - videoFrameSize.Height()) / AVERAGE_VALUE,
672         videoFrameSize.Width(), videoFrameSize.Height());
673     auto host = GetHost();
674     CHECK_NULL_RETURN(host, false);
675     host->MarkNeedSyncRenderTree();
676     return false;
677 }
678 
OnAreaChangedInner()679 void VideoPattern::OnAreaChangedInner()
680 {
681     if (SystemProperties::GetExtSurfaceEnabled()) {
682         auto host = GetHost();
683         CHECK_NULL_VOID(host);
684         auto geometryNode = host->GetGeometryNode();
685         CHECK_NULL_VOID(geometryNode);
686         auto videoNodeSize = geometryNode->GetContentSize();
687         auto videoNodeOffset = geometryNode->GetContentOffset();
688         auto layoutProperty = GetLayoutProperty<VideoLayoutProperty>();
689         CHECK_NULL_VOID(layoutProperty);
690         auto videoFrameSize = MeasureVideoContentLayout(videoNodeSize, layoutProperty);
691         auto transformRelativeOffset = host->GetTransformRelativeOffset();
692 
693         Rect rect = Rect(transformRelativeOffset.GetX() + videoNodeOffset.GetX() +
694                              (videoNodeSize.Width() - videoFrameSize.Width()) / AVERAGE_VALUE,
695             transformRelativeOffset.GetY() + videoNodeOffset.GetY() +
696                 (videoNodeSize.Height() - videoFrameSize.Height()) / AVERAGE_VALUE,
697             videoFrameSize.Width(), videoFrameSize.Height());
698         if (rect != lastBoundsRect_) {
699             renderSurface_->SetExtSurfaceBounds(rect.Left(), rect.Top(), rect.Width(), rect.Height());
700             lastBoundsRect_ = rect;
701         }
702     }
703 }
704 
CreateControlBar()705 RefPtr<FrameNode> VideoPattern::CreateControlBar()
706 {
707     auto pipelineContext = PipelineBase::GetCurrentContext();
708     CHECK_NULL_RETURN(pipelineContext, nullptr);
709     auto videoTheme = pipelineContext->GetTheme<VideoTheme>();
710     CHECK_NULL_RETURN(videoTheme, nullptr);
711     auto controlBar = FrameNode::CreateFrameNode(V2::ROW_ETS_TAG, -1, AceType::MakeRefPtr<LinearLayoutPattern>(false));
712     CHECK_NULL_RETURN(controlBar, nullptr);
713 
714     auto playButton = CreateSVG();
715     CHECK_NULL_RETURN(playButton, nullptr);
716     ChangePlayButtonTag(playButton);
717     controlBar->AddChild(playButton);
718 
719     auto currentPosText = CreateText(currentPos_);
720     CHECK_NULL_RETURN(currentPosText, nullptr);
721     controlBar->AddChild(currentPosText);
722 
723     auto slider = CreateSlider();
724     CHECK_NULL_RETURN(currentPosText, nullptr);
725     controlBar->AddChild(slider);
726 
727     auto durationText = CreateText(duration_);
728     CHECK_NULL_RETURN(durationText, nullptr);
729     controlBar->AddChild(durationText);
730 
731     auto fullScreenButton = CreateSVG();
732     CHECK_NULL_RETURN(fullScreenButton, nullptr);
733     SetFullScreenButtonCallBack(fullScreenButton);
734     ChangeFullScreenButtonTag(isFullScreen_, fullScreenButton);
735     controlBar->AddChild(fullScreenButton);
736 
737     auto renderContext = controlBar->GetRenderContext();
738     renderContext->UpdateBackgroundColor(videoTheme->GetBkgColor());
739     auto controlBarLayoutProperty = controlBar->GetLayoutProperty<LinearLayoutProperty>();
740     controlBarLayoutProperty->UpdateMainAxisAlign(FlexAlign::SPACE_BETWEEN);
741     return controlBar;
742 }
743 
CreateSlider()744 RefPtr<FrameNode> VideoPattern::CreateSlider()
745 {
746     auto pipelineContext = PipelineBase::GetCurrentContext();
747     CHECK_NULL_RETURN(pipelineContext, nullptr);
748     auto videoTheme = pipelineContext->GetTheme<VideoTheme>();
749     CHECK_NULL_RETURN(videoTheme, nullptr);
750 
751     auto sliderNode = FrameNode::CreateFrameNode(V2::SLIDER_ETS_TAG, -1, AceType::MakeRefPtr<SliderPattern>());
752     CHECK_NULL_RETURN(sliderNode, nullptr);
753     auto sliderLayoutProperty = sliderNode->GetLayoutProperty<SliderLayoutProperty>();
754     CHECK_NULL_RETURN(sliderLayoutProperty, nullptr);
755 
756     auto sliderEdge = videoTheme->GetSliderEdge();
757     PaddingProperty padding;
758     padding.left = CalcLength(sliderEdge.Left());
759     padding.right = CalcLength(sliderEdge.Right());
760     padding.top = CalcLength(sliderEdge.Top());
761     padding.bottom = CalcLength(sliderEdge.Bottom());
762     sliderLayoutProperty->UpdatePadding(padding);
763     sliderLayoutProperty->UpdateLayoutWeight(1.0);
764 
765     SliderOnChangeEvent sliderOnChangeEvent = [weak = WeakClaim(this)](float value, int32_t mode) {
766         auto videoPattern = weak.Upgrade();
767         CHECK_NULL_VOID(videoPattern);
768         videoPattern->SetCurrentTime(value);
769         videoPattern->OnSliderChange(value, mode);
770     };
771     auto sliderEventHub = sliderNode->GetEventHub<SliderEventHub>();
772     sliderEventHub->SetOnChange(std::move(sliderOnChangeEvent));
773 
774     auto sliderPaintProperty = sliderNode->GetPaintProperty<SliderPaintProperty>();
775     CHECK_NULL_RETURN(sliderPaintProperty, nullptr);
776     sliderPaintProperty->UpdateMax(static_cast<float>(duration_));
777     sliderPaintProperty->UpdateSelectColor(Color::BLACK);
778     sliderPaintProperty->UpdateValue(static_cast<float>(currentPos_));
779     sliderNode->MarkModifyDone();
780     return sliderNode;
781 }
782 
CreateText(uint32_t time)783 RefPtr<FrameNode> VideoPattern::CreateText(uint32_t time)
784 {
785     auto pipelineContext = PipelineBase::GetCurrentContext();
786     CHECK_NULL_RETURN(pipelineContext, nullptr);
787     auto videoTheme = pipelineContext->GetTheme<VideoTheme>();
788     CHECK_NULL_RETURN(videoTheme, nullptr);
789 
790     auto textNode = FrameNode::CreateFrameNode(V2::TEXT_ETS_TAG, -1, AceType::MakeRefPtr<TextPattern>());
791     CHECK_NULL_RETURN(textNode, nullptr);
792     auto textLayoutProperty = textNode->GetLayoutProperty<TextLayoutProperty>();
793     CHECK_NULL_RETURN(textLayoutProperty, nullptr);
794     std::string label = IntTimeToText(time);
795     textLayoutProperty->UpdateContent(label);
796     auto textEdge = videoTheme->GetTextEdge();
797     PaddingProperty padding;
798     padding.left = CalcLength(textEdge.Left());
799     padding.right = CalcLength(textEdge.Right());
800     padding.top = CalcLength(textEdge.Top());
801     padding.bottom = CalcLength(textEdge.Bottom());
802     textLayoutProperty->UpdatePadding(padding);
803     auto textStyle = videoTheme->GetTimeTextStyle();
804     textLayoutProperty->UpdateFontSize(textStyle.GetFontSize());
805     textLayoutProperty->UpdateTextColor(textStyle.GetTextColor());
806     return textNode;
807 }
808 
CreateSVG()809 RefPtr<FrameNode> VideoPattern::CreateSVG()
810 {
811     auto pipelineContext = PipelineBase::GetCurrentContext();
812     CHECK_NULL_RETURN(pipelineContext, nullptr);
813     auto videoTheme = pipelineContext->GetTheme<VideoTheme>();
814     CHECK_NULL_RETURN(videoTheme, nullptr);
815 
816     auto svgNode = FrameNode::CreateFrameNode(V2::IMAGE_ETS_TAG, -1, AceType::MakeRefPtr<ImagePattern>());
817     CHECK_NULL_RETURN(svgNode, nullptr);
818     auto svgLayoutProperty = svgNode->GetLayoutProperty<ImageLayoutProperty>();
819 
820     auto btnEdge = videoTheme->GetBtnEdge();
821     PaddingProperty padding;
822     padding.left = CalcLength(btnEdge.Left());
823     padding.right = CalcLength(btnEdge.Right());
824     padding.top = CalcLength(btnEdge.Top());
825     padding.bottom = CalcLength(btnEdge.Bottom());
826     svgLayoutProperty->UpdatePadding(padding);
827 
828     auto btnSize = videoTheme->GetBtnSize();
829     SizeF size { static_cast<float>(btnSize.Width()), static_cast<float>(btnSize.Height()) };
830     svgLayoutProperty->UpdateMarginSelfIdealSize(size);
831     auto width = Dimension(btnSize.Width(), DimensionUnit::VP).ConvertToPx();
832     auto height = Dimension(btnSize.Height(), DimensionUnit::VP).ConvertToPx();
833     CalcSize idealSize = { CalcLength(width), CalcLength(height) };
834     MeasureProperty layoutConstraint;
835     layoutConstraint.selfIdealSize = idealSize;
836     layoutConstraint.maxSize = idealSize;
837     svgNode->UpdateLayoutConstraint(layoutConstraint);
838     return svgNode;
839 }
840 
SetMethodCall()841 void VideoPattern::SetMethodCall()
842 {
843     auto videoController = AceType::MakeRefPtr<VideoController>();
844     auto context = PipelineContext::GetCurrentContext();
845     CHECK_NULL_VOID(context);
846     auto uiTaskExecutor = SingleTaskExecutor::Make(context->GetTaskExecutor(), TaskExecutor::TaskType::UI);
847     videoController->SetStartImpl([weak = WeakClaim(this), uiTaskExecutor]() {
848         uiTaskExecutor.PostTask([weak]() {
849             auto pattern = weak.Upgrade();
850             CHECK_NULL_VOID(pattern);
851             pattern->Start();
852         });
853     });
854     videoController->SetPausetImpl([weak = WeakClaim(this), uiTaskExecutor]() {
855         uiTaskExecutor.PostTask([weak]() {
856             auto pattern = weak.Upgrade();
857             CHECK_NULL_VOID(pattern);
858             pattern->Pause();
859         });
860     });
861     videoController->SetStopImpl([weak = WeakClaim(this), uiTaskExecutor]() {
862         uiTaskExecutor.PostTask([weak]() {
863             auto pattern = weak.Upgrade();
864             CHECK_NULL_VOID(pattern);
865             pattern->Stop();
866         });
867     });
868     videoController->SetSeekToImpl([weak = WeakClaim(this), uiTaskExecutor](float pos, SeekMode seekMode) {
869         uiTaskExecutor.PostTask([weak, pos, seekMode]() {
870             auto pattern = weak.Upgrade();
871             CHECK_NULL_VOID(pattern);
872             pattern->SetCurrentTime(pos, seekMode);
873         });
874     });
875     videoController->SetRequestFullscreenImpl([weak = WeakClaim(this), uiTaskExecutor](bool isFullScreen) {
876         uiTaskExecutor.PostTask([weak, isFullScreen]() {
877             auto pattern = weak.Upgrade();
878             CHECK_NULL_VOID(pattern);
879             if (isFullScreen) {
880                 pattern->FullScreen();
881             } else {
882                 pattern->ExitFullScreen();
883             }
884         });
885     });
886     videoController->SetExitFullscreenImpl([weak = WeakClaim(this), uiTaskExecutor](bool isSync) {
887         if (isSync) {
888             auto pattern = weak.Upgrade();
889             CHECK_NULL_VOID(pattern);
890             pattern->ExitFullScreen();
891             return;
892         }
893         uiTaskExecutor.PostTask([weak]() {
894             auto pattern = weak.Upgrade();
895             CHECK_NULL_VOID(pattern);
896             pattern->ExitFullScreen();
897         });
898     });
899     CHECK_NULL_VOID_NOLOG(videoControllerV2_);
900     videoControllerV2_->AddVideoController(videoController);
901 }
902 
Start()903 void VideoPattern::Start()
904 {
905     LOGI("Video start to play.");
906     if (!mediaPlayer_->IsMediaPlayerValid()) {
907         LOGE("media player is invalid.");
908         return;
909     }
910 
911     if (isStop_ && mediaPlayer_->PrepareAsync() != 0) {
912         LOGE("Player has not prepared");
913         return;
914     }
915 
916     if (isPlaying_) {
917         LOGI("Already isPlaying");
918         return;
919     }
920 
921     auto context = PipelineContext::GetCurrentContext();
922     CHECK_NULL_VOID(context);
923     auto host = GetHost();
924     CHECK_NULL_VOID(host);
925     const auto& children = host->GetChildren();
926     auto iter = children.begin();
927     while (iter != children.end()) {
928         if ((*iter)->GetTag() == V2::IMAGE_ETS_TAG) {
929             iter = host->RemoveChild(*iter);
930             host->RebuildRenderContextTree();
931             context->RequestFrame();
932             break;
933         }
934 
935         ++iter;
936     }
937 
938     auto platformTask = SingleTaskExecutor::Make(context->GetTaskExecutor(), TaskExecutor::TaskType::BACKGROUND);
939     platformTask.PostTask([weak = WeakClaim(RawPtr(mediaPlayer_))] {
940         auto mediaPlayer = weak.Upgrade();
941         CHECK_NULL_VOID(mediaPlayer);
942         mediaPlayer->Play();
943     });
944 }
945 
Pause()946 void VideoPattern::Pause()
947 {
948     if (!mediaPlayer_->IsMediaPlayerValid()) {
949         LOGE("media player is invalid.");
950         return;
951     }
952 
953     if (!isPlaying_) {
954         LOGI("Already pause");
955         return;
956     }
957 
958     LOGD("Video Pause");
959     mediaPlayer_->Pause();
960 }
961 
Stop()962 void VideoPattern::Stop()
963 {
964     if (!mediaPlayer_->IsMediaPlayerValid()) {
965         LOGE("media player is invalid.");
966         return;
967     }
968 
969     OnCurrentTimeChange(0);
970     OnPlayerStatus(PlaybackStatus::STOPPED);
971     LOGD("Video Stop");
972     mediaPlayer_->Stop();
973     isStop_ = true;
974 }
975 
ChangePlayButtonTag()976 void VideoPattern::ChangePlayButtonTag()
977 {
978     auto context = PipelineContext::GetCurrentContext();
979     CHECK_NULL_VOID(context);
980     auto host = GetHost();
981     CHECK_NULL_VOID(host);
982     const auto& children = host->GetChildren();
983     for (const auto& child : children) {
984         if (child->GetTag() == V2::ROW_ETS_TAG) {
985             auto playBtn = DynamicCast<FrameNode>(child->GetChildAtIndex(0));
986             ChangePlayButtonTag(playBtn);
987             break;
988         }
989     }
990 }
991 
ChangePlayButtonTag(RefPtr<FrameNode> & playBtn)992 void VideoPattern::ChangePlayButtonTag(RefPtr<FrameNode>& playBtn)
993 {
994     CHECK_NULL_VOID(playBtn);
995     auto playClickCallback = [weak = WeakClaim(this), playing = isPlaying_](GestureEvent& /* info */) {
996         auto videoPattern = weak.Upgrade();
997         CHECK_NULL_VOID(videoPattern);
998         if (playing) {
999             videoPattern->Pause();
1000         } else {
1001             videoPattern->Start();
1002         }
1003     };
1004     auto playBtnEvent = playBtn->GetOrCreateGestureEventHub();
1005     playBtnEvent->SetUserOnClick(std::move(playClickCallback));
1006     auto svgLayoutProperty = playBtn->GetLayoutProperty<ImageLayoutProperty>();
1007     auto resourceId = isPlaying_ ? InternalResource::ResourceId::PAUSE_SVG : InternalResource::ResourceId::PLAY_SVG;
1008     auto svgSourceInfo = ImageSourceInfo("");
1009     svgSourceInfo.SetResourceId(resourceId);
1010     svgLayoutProperty->UpdateImageSourceInfo(svgSourceInfo);
1011     playBtn->MarkModifyDone();
1012     playBtn->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
1013 }
1014 
SetFullScreenButtonCallBack(RefPtr<FrameNode> & fullScreenBtn)1015 void VideoPattern::SetFullScreenButtonCallBack(RefPtr<FrameNode>& fullScreenBtn)
1016 {
1017     CHECK_NULL_VOID(fullScreenBtn);
1018     auto fsClickCallback = [weak = WeakClaim(this), &isFullScreen = isFullScreen_](GestureEvent& /* info */) {
1019         auto videoPattern = weak.Upgrade();
1020         CHECK_NULL_VOID(videoPattern);
1021         if (isFullScreen) {
1022             videoPattern->ExitFullScreen();
1023         } else {
1024             videoPattern->FullScreen();
1025         }
1026     };
1027     auto fullScreenBtnEvent = fullScreenBtn->GetOrCreateGestureEventHub();
1028     fullScreenBtnEvent->SetUserOnClick(std::move(fsClickCallback));
1029 }
1030 
ChangeFullScreenButtonTag(bool isFullScreen,RefPtr<FrameNode> & fullScreenBtn)1031 void VideoPattern::ChangeFullScreenButtonTag(bool isFullScreen, RefPtr<FrameNode>& fullScreenBtn)
1032 {
1033     CHECK_NULL_VOID(fullScreenBtn);
1034     auto svgLayoutProperty = fullScreenBtn->GetLayoutProperty<ImageLayoutProperty>();
1035     auto resourceId =
1036         isFullScreen ? InternalResource::ResourceId::QUIT_FULLSCREEN_SVG : InternalResource::ResourceId::FULLSCREEN_SVG;
1037     auto svgSourceInfo = ImageSourceInfo("");
1038     svgSourceInfo.SetResourceId(resourceId);
1039     svgLayoutProperty->UpdateImageSourceInfo(svgSourceInfo);
1040     fullScreenBtn->MarkModifyDone();
1041     fullScreenBtn->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
1042 }
1043 
SetCurrentTime(float currentPos,OHOS::Ace::SeekMode seekMode)1044 void VideoPattern::SetCurrentTime(float currentPos, OHOS::Ace::SeekMode seekMode)
1045 {
1046     LOGD("pos: %{public}lf, mode: %{public}d", currentPos, seekMode);
1047     if (!mediaPlayer_->IsMediaPlayerValid()) {
1048         return;
1049     }
1050     if (GreatOrEqual(currentPos, 0.0) && LessOrEqual(currentPos, duration_)) {
1051         LOGD("Video Seek");
1052         mediaPlayer_->Seek(static_cast<int32_t>(currentPos * MILLISECONDS_TO_SECONDS), seekMode);
1053     }
1054 }
1055 
OnSliderChange(float posTime,int32_t mode)1056 void VideoPattern::OnSliderChange(float posTime, int32_t mode)
1057 {
1058     LOGD("posTime: %{public}lf, mode: %{public}d", posTime, mode);
1059     SetCurrentTime(posTime);
1060     auto eventHub = GetEventHub<VideoEventHub>();
1061     auto json = JsonUtil::Create(true);
1062     json->Put("time", static_cast<double>(posTime));
1063     auto param = json->ToString();
1064     CHECK_NULL_VOID(eventHub);
1065     if (mode == SliderChangeMode::BEGIN || mode == SliderChangeMode::MOVING) {
1066         eventHub->FireSeekingEvent(param);
1067     } else if (mode == SliderChangeMode::END) {
1068         eventHub->FireSeekedEvent(param);
1069     }
1070 }
1071 
OnFullScreenChange(bool isFullScreen)1072 void VideoPattern::OnFullScreenChange(bool isFullScreen)
1073 {
1074     auto json = JsonUtil::Create(true);
1075     json->Put("fullscreen", isFullScreen);
1076     auto param = json->ToString();
1077     auto eventHub = GetEventHub<VideoEventHub>();
1078     eventHub->FireFullScreenChangeEvent(param);
1079     auto host = GetHost();
1080     CHECK_NULL_VOID(host);
1081     const auto& children = host->GetChildren();
1082     for (const auto& child : children) {
1083         if (child->GetTag() == V2::ROW_ETS_TAG) {
1084             auto fsBtn = DynamicCast<FrameNode>(child->GetChildAtIndex(FULL_SCREEN_POS));
1085             ChangeFullScreenButtonTag(isFullScreen, fsBtn);
1086             break;
1087         }
1088     }
1089 }
1090 
FullScreen()1091 void VideoPattern::FullScreen()
1092 {
1093     if (isFullScreen_) {
1094         LOGE("The video is already full screen when FullScreen");
1095         return;
1096     }
1097 
1098     auto context = PipelineContext::GetCurrentContext();
1099     CHECK_NULL_VOID(context);
1100     auto host = GetHost();
1101     CHECK_NULL_VOID(host);
1102     auto fullScreenManager = context->GetFullScreenManager();
1103     CHECK_NULL_VOID(fullScreenManager);
1104     fullScreenManager->RequestFullScreen(host);
1105     isFullScreen_ = true;
1106     OnFullScreenChange(true);
1107 }
1108 
ExitFullScreen()1109 void VideoPattern::ExitFullScreen()
1110 {
1111     if (!isFullScreen_) {
1112         LOGE("The video is not full screen when ExitFullScreen");
1113         return;
1114     }
1115 
1116     auto context = PipelineContext::GetCurrentContext();
1117     CHECK_NULL_VOID(context);
1118     auto host = GetHost();
1119     CHECK_NULL_VOID(host);
1120     auto fullScreenManager = context->GetFullScreenManager();
1121     CHECK_NULL_VOID(fullScreenManager);
1122     fullScreenManager->ExitFullScreen(host);
1123     isFullScreen_ = false;
1124     OnFullScreenChange(false);
1125 }
1126 
OnBackPressed()1127 bool VideoPattern::OnBackPressed()
1128 {
1129     if (!isFullScreen_) {
1130         LOGE("The video is not full screen when OnBackPressed");
1131         return false;
1132     }
1133 
1134     LOGI("Exit full screen when OnBackPressed");
1135     ExitFullScreen();
1136     return true;
1137 }
1138 
1139 } // namespace OHOS::Ace::NG
1140