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