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 "video_node.h"
19
20 #include "base/geometry/dimension.h"
21 #include "base/geometry/ng/size_t.h"
22 #include "base/i18n/localization.h"
23 #include "base/json/json_util.h"
24 #include "base/thread/task_executor.h"
25 #include "base/utils/string_utils.h"
26 #include "base/utils/system_properties.h"
27 #include "base/utils/utils.h"
28 #include "core/components/common/layout/constants.h"
29 #include "core/components/common/properties/color.h"
30 #include "core/components/declaration/button/button_declaration.h"
31 #include "core/components/video/video_theme.h"
32 #include "core/components/video/video_utils.h"
33 #include "core/components_ng/pattern/button/button_event_hub.h"
34 #include "core/components_ng/pattern/button/button_layout_property.h"
35 #include "core/components_ng/pattern/button/button_pattern.h"
36 #include "core/components_ng/pattern/image/image_layout_property.h"
37 #include "core/components_ng/pattern/image/image_pattern.h"
38 #include "core/components_ng/pattern/linear_layout/linear_layout_pattern.h"
39 #include "core/components_ng/pattern/linear_layout/linear_layout_property.h"
40 #include "core/components_ng/pattern/slider/slider_event_hub.h"
41 #include "core/components_ng/pattern/slider/slider_layout_property.h"
42 #include "core/components_ng/pattern/slider/slider_paint_property.h"
43 #include "core/components_ng/pattern/slider/slider_pattern.h"
44 #include "core/components_ng/pattern/text/text_layout_property.h"
45 #include "core/components_ng/pattern/text/text_pattern.h"
46 #include "core/components_ng/pattern/video/video_event_hub.h"
47 #include "core/components_ng/pattern/video/video_full_screen_node.h"
48 #include "core/components_ng/pattern/video/video_full_screen_pattern.h"
49 #include "core/components_ng/pattern/video/video_layout_property.h"
50 #include "core/components_ng/pattern/video/video_node.h"
51 #include "core/components_ng/property/property.h"
52 #include "core/components_v2/inspector/inspector_constants.h"
53 #include "core/pipeline_ng/pipeline_context.h"
54
55 #ifdef ENABLE_DRAG_FRAMEWORK
56 #include "core/common/udmf/udmf_client.h"
57 #endif
58 namespace OHOS::Ace::NG {
59 namespace {
60 constexpr int32_t SECONDS_PER_HOUR = 3600;
61 constexpr int32_t MILLISECONDS_TO_SECONDS = 1000;
62 constexpr uint32_t CURRENT_POS = 1;
63 constexpr uint32_t SLIDER_POS = 2;
64 constexpr uint32_t DURATION_POS = 3;
65 constexpr uint32_t FULL_SCREEN_POS = 4;
66 constexpr int32_t AVERAGE_VALUE = 2;
67
68 // Default error, empty string.
69 const std::string ERROR = "";
70
71 enum SliderChangeMode {
72 BEGIN = 0,
73 MOVING,
74 END,
75 };
76
IntTimeToText(uint32_t time)77 std::string IntTimeToText(uint32_t time)
78 {
79 bool needShowHour = time > SECONDS_PER_HOUR;
80 return Localization::GetInstance()->FormatDuration(time, needShowHour);
81 }
82
CalculateFitContain(const SizeF & videoSize,const SizeF & layoutSize)83 SizeF CalculateFitContain(const SizeF& videoSize, const SizeF& layoutSize)
84 {
85 double layoutRatio = NearZero(layoutSize.Height()) ? 0.0 : layoutSize.Width() / layoutSize.Height();
86 double sourceRatio = NearZero(videoSize.Height()) ? layoutRatio : videoSize.Width() / videoSize.Height();
87
88 if (NearZero(layoutRatio) || NearZero(sourceRatio)) {
89 return layoutSize;
90 }
91 if (sourceRatio < layoutRatio) {
92 return { static_cast<float>(sourceRatio) * layoutSize.Height(), layoutSize.Height() };
93 }
94 return { layoutSize.Width(), static_cast<float>(layoutSize.Width() / sourceRatio) };
95 }
96
CalculateFitFill(const SizeF & layoutSize)97 SizeF CalculateFitFill(const SizeF& layoutSize)
98 {
99 return layoutSize;
100 }
101
CalculateFitCover(const SizeF & videoSize,const SizeF & layoutSize)102 SizeF CalculateFitCover(const SizeF& videoSize, const SizeF& layoutSize)
103 {
104 double layoutRatio = NearZero(layoutSize.Height()) ? 0.0 : layoutSize.Width() / layoutSize.Height();
105 double sourceRatio = NearZero(videoSize.Height()) ? layoutRatio : videoSize.Width() / videoSize.Height();
106
107 if (NearZero(layoutRatio) || NearZero(sourceRatio)) {
108 return layoutSize;
109 }
110 if (sourceRatio < layoutRatio) {
111 return { layoutSize.Width(), static_cast<float>(layoutSize.Width() / sourceRatio) };
112 }
113 return { static_cast<float>(layoutSize.Height() * sourceRatio), layoutSize.Height() };
114 }
115
CalculateFitNone(const SizeF & videoSize)116 SizeF CalculateFitNone(const SizeF& videoSize)
117 {
118 return videoSize;
119 }
120
CalculateFitScaleDown(const SizeF & videoSize,const SizeF & layoutSize)121 SizeF CalculateFitScaleDown(const SizeF& videoSize, const SizeF& layoutSize)
122 {
123 if (layoutSize.Width() > videoSize.Width()) {
124 return CalculateFitNone(videoSize);
125 }
126 return CalculateFitContain(videoSize, layoutSize);
127 }
128
MeasureVideoContentLayout(const SizeF & layoutSize,const RefPtr<VideoLayoutProperty> & layoutProperty)129 SizeF MeasureVideoContentLayout(const SizeF& layoutSize, const RefPtr<VideoLayoutProperty>& layoutProperty)
130 {
131 LOGD("Video start measure video content layout.");
132 if (!layoutProperty || !layoutProperty->HasVideoSize()) {
133 LOGW("VideoSize has not set");
134 return layoutSize;
135 }
136
137 auto videoSize = layoutProperty->GetVideoSizeValue(SizeF(0, 0));
138 LOGD("Video original size before fitting is %{public}s", videoSize.ToString().c_str());
139 auto imageFit = layoutProperty->GetObjectFitValue(ImageFit::COVER);
140 SizeF contentSize = { 0.0, 0.0 };
141 switch (imageFit) {
142 case ImageFit::CONTAIN:
143 contentSize = CalculateFitContain(videoSize, layoutSize);
144 break;
145 case ImageFit::FILL:
146 contentSize = CalculateFitFill(layoutSize);
147 break;
148 case ImageFit::COVER:
149 contentSize = CalculateFitCover(videoSize, layoutSize);
150 break;
151 case ImageFit::NONE:
152 contentSize = CalculateFitNone(videoSize);
153 break;
154 case ImageFit::SCALE_DOWN:
155 contentSize = CalculateFitScaleDown(videoSize, layoutSize);
156 break;
157 default:
158 contentSize = CalculateFitContain(videoSize, layoutSize);
159 }
160
161 // Just return contentSize as the video frame area.
162 LOGD("Video contentSize after fitting is %{public}s", contentSize.ToString().c_str());
163 return contentSize;
164 }
165 } // namespace
166
VideoPattern(const RefPtr<VideoControllerV2> & videoController)167 VideoPattern::VideoPattern(const RefPtr<VideoControllerV2>& videoController) : videoControllerV2_(videoController) {}
168
ResetStatus()169 void VideoPattern::ResetStatus()
170 {
171 isInitialState_ = true;
172 isPlaying_ = false;
173 #ifndef OHOS_PLATFORM
174 isStop_ = false;
175 #endif
176 }
177
ResetMediaPlayer()178 void VideoPattern::ResetMediaPlayer()
179 {
180 mediaPlayer_->ResetMediaPlayer();
181 if (!SetSourceForMediaPlayer()) {
182 LOGE("Video set source for mediaPlayer failed.");
183
184 // It need post on ui thread.
185 FireError();
186 return;
187 }
188
189 RegisterMediaPlayerEvent();
190 PrepareSurface();
191 if (mediaPlayer_->PrepareAsync() != 0) {
192 LOGE("Player prepare failed");
193 }
194 }
195
UpdateMediaPlayerOnBg()196 void VideoPattern::UpdateMediaPlayerOnBg()
197 {
198 PrepareMediaPlayer();
199 UpdateSpeed();
200 UpdateLooping();
201 UpdateMuted();
202 if (isInitialState_ && autoPlay_) {
203 // When video is autoPlay, start playing the video when it is initial state.
204 LOGI("Video set autoPlay, begin start.");
205 Start();
206 }
207 }
208
PrepareMediaPlayer()209 void VideoPattern::PrepareMediaPlayer()
210 {
211 auto videoLayoutProperty = GetLayoutProperty<VideoLayoutProperty>();
212 CHECK_NULL_VOID(videoLayoutProperty);
213 // src has not set/changed
214 if (!videoLayoutProperty->HasVideoSource() || videoLayoutProperty->GetVideoSource().value() == src_) {
215 LOGW("Video source is null or the source has not changed.");
216 return;
217 }
218 src_ = videoLayoutProperty->GetVideoSource().value();
219 if (!mediaPlayer_->IsMediaPlayerValid()) {
220 mediaPlayer_->CreateMediaPlayer();
221 if (!mediaPlayer_->IsMediaPlayerValid()) {
222 LOGE("Video create media player failed");
223 return;
224 }
225 }
226
227 if (!mediaPlayer_->IsMediaPlayerValid()) {
228 LOGE("Video media player is invalid.");
229
230 // It need post on ui thread.
231 FireError();
232 return;
233 }
234
235 ResetStatus();
236 auto context = PipelineContext::GetCurrentContext();
237 CHECK_NULL_VOID(context);
238 auto platformTask = SingleTaskExecutor::Make(context->GetTaskExecutor(), TaskExecutor::TaskType::BACKGROUND);
239 platformTask.PostTask([weak = WeakClaim(this)] {
240 auto video = weak.Upgrade();
241 CHECK_NULL_VOID(video);
242 auto targetPattern = video->GetTargetVideoPattern();
243 CHECK_NULL_VOID(targetPattern);
244 targetPattern->ResetMediaPlayer();
245 });
246 }
247
SetSourceForMediaPlayer()248 bool VideoPattern::SetSourceForMediaPlayer()
249 {
250 LOGI("Video Set src for media, it is : %{public}s", src_.c_str());
251 if (mediaPlayer_ == nullptr) {
252 LOGE("mediaPlayer is nullptr");
253 return false;
254 }
255 return mediaPlayer_->SetSource(src_);
256 }
257
RegisterMediaPlayerEvent()258 void VideoPattern::RegisterMediaPlayerEvent()
259 {
260 if (src_.empty()) {
261 LOGD("Video src is empty, RegisterMediaPlayerEvent return");
262 return;
263 }
264 auto context = PipelineContext::GetCurrentContext();
265 CHECK_NULL_VOID(context);
266
267 auto uiTaskExecutor = SingleTaskExecutor::Make(context->GetTaskExecutor(), TaskExecutor::TaskType::UI);
268 auto videoPattern = WeakClaim(this);
269
270 auto&& positionUpdatedEvent = [videoPattern, uiTaskExecutor](uint32_t currentPos) {
271 uiTaskExecutor.PostSyncTask([&videoPattern, currentPos] {
272 auto video = videoPattern.Upgrade();
273 CHECK_NULL_VOID_NOLOG(video);
274 video->OnCurrentTimeChange(currentPos);
275 });
276 };
277
278 auto&& stateChangedEvent = [videoPattern, uiTaskExecutor](PlaybackStatus status) {
279 uiTaskExecutor.PostSyncTask([&videoPattern, status] {
280 auto video = videoPattern.Upgrade();
281 CHECK_NULL_VOID_NOLOG(video);
282 LOGI("OnPlayerStatus");
283 video->OnPlayerStatus(status);
284 });
285 };
286
287 auto&& errorEvent = [videoPattern, uiTaskExecutor]() {
288 uiTaskExecutor.PostTask([&videoPattern] {
289 auto video = videoPattern.Upgrade();
290 CHECK_NULL_VOID_NOLOG(video);
291 LOGW("OnError");
292 video->OnError("");
293 });
294 };
295
296 auto&& resolutionChangeEvent = [videoPattern, uiTaskExecutor]() {
297 uiTaskExecutor.PostSyncTask([&videoPattern] {
298 auto video = videoPattern.Upgrade();
299 CHECK_NULL_VOID_NOLOG(video);
300 video->OnResolutionChange();
301 });
302 };
303
304 auto&& startRenderFrameEvent = [videoPattern, uiTaskExecutor]() {
305 uiTaskExecutor.PostSyncTask([&videoPattern] {
306 auto video = videoPattern.Upgrade();
307 CHECK_NULL_VOID_NOLOG(video);
308 video->OnStartRenderFrameCb();
309 });
310 };
311
312 mediaPlayer_->RegisterMediaPlayerEvent(
313 positionUpdatedEvent, stateChangedEvent, errorEvent, resolutionChangeEvent, startRenderFrameEvent);
314 }
315
PrintPlayerStatus(PlaybackStatus status)316 void VideoPattern::PrintPlayerStatus(PlaybackStatus status)
317 {
318 switch (status) {
319 case PlaybackStatus::ERROR:
320 LOGI("Player current status is ERROR.");
321 break;
322 case PlaybackStatus::IDLE:
323 LOGI("Player current status is IDLE.");
324 break;
325 case PlaybackStatus::PREPARED:
326 LOGI("Player current status is PREPARED.");
327 break;
328 case PlaybackStatus::STARTED:
329 LOGI("Player current status is STARTED.");
330 break;
331 case PlaybackStatus::PAUSED:
332 LOGI("Player current status is PAUSED.");
333 break;
334 case PlaybackStatus::STOPPED:
335 LOGI("Player current status is STOPPED.");
336 break;
337 case PlaybackStatus::PLAYBACK_COMPLETE:
338 LOGI("Player current status is PLAYBACK_COMPLETE.");
339 break;
340 case PlaybackStatus::NONE:
341 LOGI("Player current status is NONE.");
342 break;
343 default:
344 LOGI("Invalid player status.");
345 break;
346 }
347 }
348
OnCurrentTimeChange(uint32_t currentPos)349 void VideoPattern::OnCurrentTimeChange(uint32_t currentPos)
350 {
351 LOGD("Video current position is %{public}d", currentPos);
352 isInitialState_ = isInitialState_ ? currentPos == 0 : false;
353 if (currentPos == currentPos_ || isStop_) {
354 return;
355 }
356
357 if (duration_ == 0) {
358 int32_t duration = 0;
359 if (mediaPlayer_->GetDuration(duration) == 0) {
360 duration_ = duration / MILLISECONDS_TO_SECONDS;
361 OnUpdateTime(duration_, DURATION_POS);
362 }
363 }
364
365 OnUpdateTime(currentPos, CURRENT_POS);
366 currentPos_ = currentPos;
367 auto eventHub = GetEventHub<VideoEventHub>();
368 CHECK_NULL_VOID(eventHub);
369 auto json = JsonUtil::Create(true);
370 json->Put("time", static_cast<double>(currentPos));
371 auto param = json->ToString();
372 eventHub->FireUpdateEvent(param);
373 }
374
OnPlayerStatus(PlaybackStatus status)375 void VideoPattern::OnPlayerStatus(PlaybackStatus status)
376 {
377 PrintPlayerStatus(status);
378 bool isPlaying = (status == PlaybackStatus::STARTED);
379 if (isPlaying_ != isPlaying) {
380 isPlaying_ = isPlaying;
381 ChangePlayButtonTag();
382 }
383
384 if (isInitialState_) {
385 isInitialState_ = !isPlaying;
386 }
387
388 if (isPlaying) {
389 auto json = JsonUtil::Create(true);
390 json->Put("start", "");
391 auto param = json->ToString();
392 auto eventHub = GetEventHub<VideoEventHub>();
393 CHECK_NULL_VOID(eventHub);
394 eventHub->FireStartEvent(param);
395 }
396
397 if (status == PlaybackStatus::PAUSED) {
398 auto json = JsonUtil::Create(true);
399 json->Put("pause", "");
400 auto param = json->ToString();
401 auto eventHub = GetEventHub<VideoEventHub>();
402 CHECK_NULL_VOID(eventHub);
403 eventHub->FirePauseEvent(param);
404 }
405
406 if (status == PlaybackStatus::PREPARED) {
407 auto context = PipelineContext::GetCurrentContext();
408 CHECK_NULL_VOID(context);
409 if (!mediaPlayer_ || !mediaPlayer_->IsMediaPlayerValid()) {
410 return;
411 }
412 auto uiTaskExecutor = SingleTaskExecutor::Make(context->GetTaskExecutor(), TaskExecutor::TaskType::UI);
413 Size videoSize = Size(mediaPlayer_->GetVideoWidth(), mediaPlayer_->GetVideoHeight());
414 int32_t milliSecondDuration = 0;
415 mediaPlayer_->GetDuration(milliSecondDuration);
416 uiTaskExecutor.PostSyncTask([this, videoSize, duration = milliSecondDuration / MILLISECONDS_TO_SECONDS] {
417 LOGI("Video OnPrepared video size: %{public}s", videoSize.ToString().c_str());
418 this->OnPrepared(videoSize.Width(), videoSize.Height(), duration, 0, true);
419 });
420 return;
421 }
422
423 if (status == PlaybackStatus::PLAYBACK_COMPLETE) {
424 OnCompletion();
425 }
426 }
427
OnError(const std::string & errorId)428 void VideoPattern::OnError(const std::string& errorId)
429 {
430 std::string errorcode = Localization::GetInstance()->GetErrorDescription(errorId);
431 auto json = JsonUtil::Create(true);
432 json->Put("error", "");
433 auto param = json->ToString();
434 auto eventHub = GetEventHub<VideoEventHub>();
435 CHECK_NULL_VOID(eventHub);
436 eventHub->FireErrorEvent(param);
437 }
438
OnResolutionChange() const439 void VideoPattern::OnResolutionChange() const
440 {
441 if (!mediaPlayer_ || !mediaPlayer_->IsMediaPlayerValid()) {
442 return;
443 }
444 auto host = GetHost();
445 CHECK_NULL_VOID(host);
446 SizeF videoSize =
447 SizeF(static_cast<float>(mediaPlayer_->GetVideoWidth()), static_cast<float>(mediaPlayer_->GetVideoHeight()));
448 auto videoLayoutProperty = host->GetLayoutProperty<VideoLayoutProperty>();
449 CHECK_NULL_VOID(videoLayoutProperty);
450 videoLayoutProperty->UpdateVideoSize(videoSize);
451 LOGI("OnResolutionChange video size: %{public}s", videoSize.ToString().c_str());
452 host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
453 }
454
OnStartRenderFrameCb() const455 void VideoPattern::OnStartRenderFrameCb() const
456 {
457 auto host = GetHost();
458 CHECK_NULL_VOID(host);
459 auto video = AceType::DynamicCast<VideoNode>(host);
460 CHECK_NULL_VOID(video);
461 auto image = AceType::DynamicCast<FrameNode>(video->GetPreviewImage());
462 CHECK_NULL_VOID(image);
463 auto posterLayoutProperty = image->GetLayoutProperty<ImageLayoutProperty>();
464 posterLayoutProperty->UpdateVisibility(VisibleType::INVISIBLE);
465 image->MarkModifyDone();
466 }
467
OnPrepared(double width,double height,uint32_t duration,uint32_t currentPos,bool needFireEvent)468 void VideoPattern::OnPrepared(double width, double height, uint32_t duration, uint32_t currentPos, bool needFireEvent)
469 {
470 auto host = GetHost();
471 CHECK_NULL_VOID(host);
472 auto videoLayoutProperty = host->GetLayoutProperty<VideoLayoutProperty>();
473 CHECK_NULL_VOID(videoLayoutProperty);
474 videoLayoutProperty->UpdateVideoSize(SizeF(static_cast<float>(width), static_cast<float>(height)));
475 host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
476
477 duration_ = duration;
478 currentPos_ = currentPos;
479 isInitialState_ = currentPos != 0 ? false : isInitialState_;
480 isPlaying_ = mediaPlayer_->IsPlaying();
481 OnUpdateTime(duration_, DURATION_POS);
482 OnUpdateTime(currentPos_, CURRENT_POS);
483
484 RefPtr<UINode> controlBar = nullptr;
485 auto children = host->GetChildren();
486 for (const auto& child : children) {
487 if (child->GetTag() == V2::ROW_ETS_TAG) {
488 controlBar = child;
489 break;
490 }
491 }
492 CHECK_NULL_VOID(controlBar);
493 auto sliderNode = DynamicCast<FrameNode>(controlBar->GetChildAtIndex(SLIDER_POS));
494 auto sliderPaintProperty = sliderNode->GetPaintProperty<SliderPaintProperty>();
495 CHECK_NULL_VOID(sliderPaintProperty);
496 sliderPaintProperty->UpdateMin(0.0f);
497 sliderPaintProperty->UpdateMax(static_cast<float>(duration_));
498 sliderNode->MarkModifyDone();
499 auto playBtn = DynamicCast<FrameNode>(controlBar->GetChildAtIndex(0));
500 ChangePlayButtonTag(playBtn);
501
502 if (needFireEvent) {
503 auto json = JsonUtil::Create(true);
504 json->Put("duration", static_cast<double>(duration_));
505 auto param = json->ToString();
506 auto eventHub = GetEventHub<VideoEventHub>();
507 CHECK_NULL_VOID(eventHub);
508 eventHub->FirePreparedEvent(param);
509 }
510 UpdateLooping();
511 UpdateSpeed();
512 UpdateMuted();
513
514 checkNeedAutoPlay();
515 }
516
checkNeedAutoPlay()517 void VideoPattern::checkNeedAutoPlay()
518 {
519 if (isStop_) {
520 isStop_ = false;
521 Start();
522 }
523 if (dragEndAutoPlay_) {
524 dragEndAutoPlay_ = false;
525 Start();
526 }
527 if (autoPlay_) {
528 Start();
529 }
530 }
531
OnCompletion()532 void VideoPattern::OnCompletion()
533 {
534 isPlaying_ = false;
535 currentPos_ = duration_;
536 OnUpdateTime(currentPos_, CURRENT_POS);
537 auto json = JsonUtil::Create(true);
538 json->Put("finish", "");
539 auto param = json->ToString();
540 auto eventHub = GetEventHub<VideoEventHub>();
541 CHECK_NULL_VOID(eventHub);
542 eventHub->FireFinishEvent(param);
543 }
544
HasPlayer() const545 bool VideoPattern::HasPlayer() const
546 {
547 return mediaPlayer_ != nullptr;
548 }
549
HiddenChange(bool hidden)550 void VideoPattern::HiddenChange(bool hidden)
551 {
552 if (isPlaying_ && hidden && HasPlayer()) {
553 pastPlayingStatus_ = isPlaying_;
554 Pause();
555 return;
556 }
557
558 if (!hidden && pastPlayingStatus_) {
559 pastPlayingStatus_ = false;
560 Start();
561 }
562 }
563
OnVisibleChange(bool isVisible)564 void VideoPattern::OnVisibleChange(bool isVisible)
565 {
566 if (hiddenChangeEvent_) {
567 hiddenChangeEvent_(!isVisible);
568 }
569 }
570
UpdateLooping()571 void VideoPattern::UpdateLooping()
572 {
573 if (mediaPlayer_->IsMediaPlayerValid()) {
574 LOGI("Video media player set the loop.");
575 auto context = PipelineContext::GetCurrentContext();
576 CHECK_NULL_VOID(context);
577 auto platformTask = SingleTaskExecutor::Make(context->GetTaskExecutor(), TaskExecutor::TaskType::BACKGROUND);
578 platformTask.PostTask([weak = WeakClaim(RawPtr(mediaPlayer_)), loop = loop_] {
579 auto mediaPlayer = weak.Upgrade();
580 CHECK_NULL_VOID(mediaPlayer);
581 mediaPlayer->SetLooping(loop);
582 });
583 } else {
584 LOGW("Video media player is invalid.");
585 }
586 }
587
UpdateSpeed()588 void VideoPattern::UpdateSpeed()
589 {
590 if (mediaPlayer_->IsMediaPlayerValid()) {
591 LOGI("Video media player set the speed.");
592 auto context = PipelineContext::GetCurrentContext();
593 CHECK_NULL_VOID(context);
594 auto platformTask = SingleTaskExecutor::Make(context->GetTaskExecutor(), TaskExecutor::TaskType::BACKGROUND);
595 platformTask.PostTask([weak = WeakClaim(RawPtr(mediaPlayer_)), progress = progressRate_] {
596 auto mediaPlayer = weak.Upgrade();
597 CHECK_NULL_VOID(mediaPlayer);
598 mediaPlayer->SetPlaybackSpeed(static_cast<float>(progress));
599 });
600 } else {
601 LOGW("Video media player is invalid.");
602 }
603 }
604
UpdateMuted()605 void VideoPattern::UpdateMuted()
606 {
607 if (mediaPlayer_->IsMediaPlayerValid()) {
608 float volume = muted_ ? 0.0f : 1.0f;
609 LOGI("Video media player set the volume.");
610 auto context = PipelineContext::GetCurrentContext();
611 CHECK_NULL_VOID(context);
612 auto platformTask = SingleTaskExecutor::Make(context->GetTaskExecutor(), TaskExecutor::TaskType::BACKGROUND);
613 platformTask.PostTask([weak = WeakClaim(RawPtr(mediaPlayer_)), videoVolume = volume] {
614 auto mediaPlayer = weak.Upgrade();
615 CHECK_NULL_VOID(mediaPlayer);
616 mediaPlayer->SetVolume(videoVolume, videoVolume);
617 });
618 } else {
619 LOGW("Video media player is invalid.");
620 }
621 }
622
OnUpdateTime(uint32_t time,int pos) const623 void VideoPattern::OnUpdateTime(uint32_t time, int pos) const
624 {
625 auto host = GetHost();
626 CHECK_NULL_VOID(host);
627 auto layoutProperty = host->GetLayoutProperty<VideoLayoutProperty>();
628 CHECK_NULL_VOID(layoutProperty);
629 bool needControlBar = layoutProperty->GetControlsValue(true);
630 if (!needControlBar) {
631 return;
632 }
633
634 RefPtr<UINode> controlBar = nullptr;
635 auto children = host->GetChildren();
636 for (const auto& child : children) {
637 if (child->GetTag() == V2::ROW_ETS_TAG) {
638 controlBar = child;
639 break;
640 }
641 }
642
643 CHECK_NULL_VOID(controlBar);
644 auto durationNode = DynamicCast<FrameNode>(controlBar->GetChildAtIndex(pos));
645 CHECK_NULL_VOID(durationNode);
646 auto textLayoutProperty = durationNode->GetLayoutProperty<TextLayoutProperty>();
647 CHECK_NULL_VOID(textLayoutProperty);
648 std::string timeText = IntTimeToText(time);
649 textLayoutProperty->UpdateContent(timeText);
650 durationNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
651 durationNode->MarkModifyDone();
652 if (pos == CURRENT_POS) {
653 auto sliderNode = DynamicCast<FrameNode>(controlBar->GetChildAtIndex(SLIDER_POS));
654 CHECK_NULL_VOID(sliderNode);
655 auto sliderPattern = sliderNode->GetPattern<SliderPattern>();
656 CHECK_NULL_VOID(sliderPattern);
657 sliderPattern->UpdateValue(static_cast<float>(time));
658 sliderNode->MarkModifyDone();
659 }
660 }
661
PrepareSurface()662 void VideoPattern::PrepareSurface()
663 {
664 if (renderSurface_->IsSurfaceValid()) {
665 return;
666 }
667 if (!SystemProperties::GetExtSurfaceEnabled()) {
668 renderSurface_->SetRenderContext(renderContextForMediaPlayer_);
669 }
670 renderSurface_->InitSurface();
671 mediaPlayer_->SetRenderSurface(renderSurface_);
672 if (mediaPlayer_->SetSurface() != 0) {
673 LOGE("Player SetVideoSurface failed");
674 return;
675 }
676 }
677
OnAttachToFrameNode()678 void VideoPattern::OnAttachToFrameNode()
679 {
680 // full screen node is not supposed to register js controller event
681 if (!InstanceOf<VideoFullScreenPattern>(this)) {
682 SetMethodCall();
683 }
684 auto host = GetHost();
685 CHECK_NULL_VOID(host);
686 auto renderContext = host->GetRenderContext();
687 CHECK_NULL_VOID(renderContext);
688 static RenderContext::ContextParam param = { RenderContext::ContextType::HARDWARE_SURFACE, "MediaPlayerSurface" };
689 renderContextForMediaPlayer_->InitContext(false, param);
690 auto isFullScreen = IsFullScreen();
691 if (SystemProperties::GetExtSurfaceEnabled() && !isFullScreen) {
692 auto OnAreaChangedCallBack = [weak = WeakClaim(this)](float x, float y, float w, float h) mutable {
693 auto videoPattern = weak.Upgrade();
694 CHECK_NULL_VOID_NOLOG(videoPattern);
695
696 auto host = videoPattern->GetHost();
697 CHECK_NULL_VOID(host);
698 auto geometryNode = host->GetGeometryNode();
699 CHECK_NULL_VOID(geometryNode);
700 auto videoNodeSize = geometryNode->GetContentSize();
701 auto layoutProperty = videoPattern->GetLayoutProperty<VideoLayoutProperty>();
702 CHECK_NULL_VOID(layoutProperty);
703 auto videoFrameSize = MeasureVideoContentLayout(videoNodeSize, layoutProperty);
704
705 Rect rect = Rect(x + (videoNodeSize.Width() - videoFrameSize.Width()) / AVERAGE_VALUE,
706 y + (videoNodeSize.Height() - videoFrameSize.Height()) / AVERAGE_VALUE, videoFrameSize.Width(),
707 videoFrameSize.Height());
708
709 if (videoPattern->renderSurface_) {
710 if (videoPattern->renderSurface_->SetExtSurfaceBoundsSync(rect.Left(),
711 rect.Top(), rect.Width(), rect.Height())) {
712 videoPattern->lastBoundsRect_ = rect;
713 }
714 }
715 };
716 renderContextForMediaPlayer_->SetSurfaceChangedCallBack(OnAreaChangedCallBack);
717 }
718 renderContext->UpdateBackgroundColor(Color::BLACK);
719 renderContextForMediaPlayer_->UpdateBackgroundColor(Color::BLACK);
720 renderContext->SetClipToBounds(true);
721 }
722
OnModifyDone()723 void VideoPattern::OnModifyDone()
724 {
725 Pattern::OnModifyDone();
726 if (!hiddenChangeEvent_) {
727 SetHiddenChangeEvent([weak = WeakClaim(this)](bool hidden) {
728 auto videoPattern = weak.Upgrade();
729 CHECK_NULL_VOID_NOLOG(videoPattern);
730 auto fullScreenNode = videoPattern->GetFullScreenNode();
731 if (fullScreenNode) {
732 auto fullScreenPattern = AceType::DynamicCast<VideoFullScreenPattern>(fullScreenNode->GetPattern());
733 CHECK_NULL_VOID(fullScreenPattern);
734 fullScreenPattern->HiddenChange(hidden);
735 return;
736 }
737 videoPattern->HiddenChange(hidden);
738 });
739 }
740
741 // update full screen pattern state
742 UpdateFsState();
743
744 // Update the control bar and preview image.
745 UpdatePreviewImage();
746 UpdateControllerBar();
747
748 // Update the media player when video node is not in full screen or current node is full screen node
749 if (!fullScreenNodeId_.has_value() || InstanceOf<VideoFullScreenNode>(this)) {
750 LOGI("trigger modify media player");
751 UpdateMediaPlayerOnBg();
752 }
753
754 if (SystemProperties::GetExtSurfaceEnabled()) {
755 auto pipelineContext = PipelineContext::GetCurrentContext();
756 CHECK_NULL_VOID(pipelineContext);
757 auto host = GetHost();
758 CHECK_NULL_VOID(host);
759 pipelineContext->AddOnAreaChangeNode(host->GetId());
760 }
761 EnableDrag();
762 }
763
UpdatePreviewImage()764 void VideoPattern::UpdatePreviewImage()
765 {
766 auto layoutProperty = GetLayoutProperty<VideoLayoutProperty>();
767 CHECK_NULL_VOID(layoutProperty);
768 if (!layoutProperty->HasPosterImageInfo()) {
769 return;
770 }
771 auto posterSourceInfo = layoutProperty->GetPosterImageInfo().value();
772 auto imageFit = layoutProperty->GetObjectFitValue(ImageFit::COVER);
773 auto host = GetHost();
774 CHECK_NULL_VOID(host);
775
776 auto video = AceType::DynamicCast<VideoNode>(host);
777 CHECK_NULL_VOID(video);
778 auto image = AceType::DynamicCast<FrameNode>(video->GetPreviewImage());
779 CHECK_NULL_VOID(image);
780 if (!isInitialState_ || !layoutProperty->HasPosterImageInfo()) {
781 auto posterLayoutProperty = image->GetLayoutProperty<ImageLayoutProperty>();
782 posterLayoutProperty->UpdateVisibility(VisibleType::INVISIBLE);
783 image->MarkModifyDone();
784 return;
785 }
786
787 if (!posterSourceInfo.IsValid()) {
788 auto posterLayoutProperty = image->GetLayoutProperty<ImageLayoutProperty>();
789 posterLayoutProperty->UpdateVisibility(VisibleType::INVISIBLE);
790 image->MarkModifyDone();
791 LOGI("Src image is not valid.");
792 return;
793 }
794
795 if (image) {
796 auto posterLayoutProperty = image->GetLayoutProperty<ImageLayoutProperty>();
797 posterLayoutProperty->UpdateVisibility(VisibleType::VISIBLE);
798 posterLayoutProperty->UpdateImageSourceInfo(posterSourceInfo);
799 posterLayoutProperty->UpdateImageFit(imageFit);
800 image->MarkModifyDone();
801 }
802 }
803
UpdateControllerBar()804 void VideoPattern::UpdateControllerBar()
805 {
806 auto layoutProperty = GetLayoutProperty<VideoLayoutProperty>();
807 CHECK_NULL_VOID(layoutProperty);
808 auto host = GetHost();
809 CHECK_NULL_VOID(host);
810 auto children = host->GetChildren();
811 if (layoutProperty->GetControlsValue(true)) {
812 auto video = AceType::DynamicCast<VideoNode>(host);
813 CHECK_NULL_VOID(video);
814 auto controller = AceType::DynamicCast<FrameNode>(video->GetControllerRow());
815 if (controller) {
816 auto sliderNode = DynamicCast<FrameNode>(controller->GetChildAtIndex(SLIDER_POS));
817 CHECK_NULL_VOID(sliderNode);
818 auto sliderPattern = sliderNode->GetPattern<SliderPattern>();
819 CHECK_NULL_VOID(sliderPattern);
820 sliderPattern->UpdateValue(static_cast<float>(currentPos_));
821 sliderNode->MarkModifyDone();
822
823 auto textNode = DynamicCast<FrameNode>(controller->GetChildAtIndex(CURRENT_POS));
824 CHECK_NULL_VOID(textNode);
825 auto textLayoutProperty = textNode->GetLayoutProperty<TextLayoutProperty>();
826 CHECK_NULL_VOID(textLayoutProperty);
827 std::string label = IntTimeToText(currentPos_);
828 textLayoutProperty->UpdateContent(label);
829
830 auto durationNode = DynamicCast<FrameNode>(controller->GetChildAtIndex(DURATION_POS));
831 CHECK_NULL_VOID(durationNode);
832 auto durationTextLayoutProperty = durationNode->GetLayoutProperty<TextLayoutProperty>();
833 CHECK_NULL_VOID(durationTextLayoutProperty);
834 std::string durationText = IntTimeToText(duration_);
835 durationTextLayoutProperty->UpdateContent(durationText);
836
837 textNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
838 textNode->MarkModifyDone();
839 durationNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
840 durationNode->MarkModifyDone();
841 auto controllerLayoutProperty = controller->GetLayoutProperty<LinearLayoutProperty>();
842 controllerLayoutProperty->UpdateVisibility(VisibleType::VISIBLE);
843 controller->MarkModifyDone();
844 }
845 } else {
846 auto video = AceType::DynamicCast<VideoNode>(host);
847 CHECK_NULL_VOID(video);
848 auto controller = AceType::DynamicCast<FrameNode>(video->GetControllerRow());
849 CHECK_NULL_VOID(controller);
850 if (controller) {
851 auto controllerLayoutProperty = controller->GetLayoutProperty<LinearLayoutProperty>();
852 controllerLayoutProperty->UpdateVisibility(VisibleType::INVISIBLE);
853 controller->MarkModifyDone();
854 }
855 }
856 }
857
UpdateVideoProperty()858 void VideoPattern::UpdateVideoProperty()
859 {
860 if (isInitialState_ && autoPlay_) {
861 Start();
862 }
863
864 UpdateSpeed();
865 UpdateLooping();
866 UpdateMuted();
867 }
868
OnRebuildFrame()869 void VideoPattern::OnRebuildFrame()
870 {
871 if (!renderSurface_ || !renderSurface_->IsSurfaceValid()) {
872 LOGE("surface not valid");
873 return;
874 }
875 auto host = GetHost();
876 CHECK_NULL_VOID(host);
877 auto video = AceType::DynamicCast<VideoNode>(host);
878 CHECK_NULL_VOID(video);
879 auto column = AceType::DynamicCast<FrameNode>(video->GetMediaColumn());
880 CHECK_NULL_VOID(column);
881 auto renderContext = column->GetRenderContext();
882 renderContext->AddChild(renderContextForMediaPlayer_, 0);
883 }
884
OnDirtyLayoutWrapperSwap(const RefPtr<LayoutWrapper> & dirty,const DirtySwapConfig & config)885 bool VideoPattern::OnDirtyLayoutWrapperSwap(const RefPtr<LayoutWrapper>& dirty, const DirtySwapConfig& config)
886 {
887 if (config.skipMeasure || dirty->SkipMeasureContent()) {
888 LOGD("Video skill measure.");
889 return false;
890 }
891 auto geometryNode = dirty->GetGeometryNode();
892 CHECK_NULL_RETURN(geometryNode, false);
893 auto videoNodeSize = geometryNode->GetContentSize();
894 auto layoutProperty = GetLayoutProperty<VideoLayoutProperty>();
895 CHECK_NULL_RETURN(layoutProperty, false);
896 LOGD("Video node size is %{public}s", videoNodeSize.ToString().c_str());
897 auto videoFrameSize = MeasureVideoContentLayout(videoNodeSize, layoutProperty);
898 // Change the surface layout for drawing video frames
899 if (renderContextForMediaPlayer_) {
900 renderContextForMediaPlayer_->SetBounds((videoNodeSize.Width() - videoFrameSize.Width()) / AVERAGE_VALUE,
901 (videoNodeSize.Height() - videoFrameSize.Height()) / AVERAGE_VALUE, videoFrameSize.Width(),
902 videoFrameSize.Height());
903 LOGD("Video renderContext for mediaPlayer position x is %{public}lf,y is %{public}lf,width is "
904 "%{public}lf,height "
905 "is %{public}lf.",
906 (videoNodeSize.Width() - videoFrameSize.Width()) / AVERAGE_VALUE,
907 (videoNodeSize.Height() - videoFrameSize.Height()) / AVERAGE_VALUE, videoFrameSize.Width(),
908 videoFrameSize.Height());
909 }
910 auto host = GetHost();
911 CHECK_NULL_RETURN(host, false);
912 host->MarkNeedSyncRenderTree();
913 auto video = AceType::DynamicCast<VideoNode>(host);
914 CHECK_NULL_RETURN(video, false);
915 auto column = AceType::DynamicCast<FrameNode>(video->GetMediaColumn());
916 CHECK_NULL_RETURN(column, false);
917 column->GetRenderContext()->SetClipToBounds(true);
918 return false;
919 }
920
OnAreaChangedInner()921 void VideoPattern::OnAreaChangedInner()
922 {
923 auto isFullScreen = IsFullScreen();
924 if (SystemProperties::GetExtSurfaceEnabled() && isFullScreen) {
925 auto host = GetHost();
926 CHECK_NULL_VOID(host);
927 auto geometryNode = host->GetGeometryNode();
928 CHECK_NULL_VOID(geometryNode);
929 auto videoNodeSize = geometryNode->GetContentSize();
930 auto layoutProperty = GetLayoutProperty<VideoLayoutProperty>();
931 CHECK_NULL_VOID(layoutProperty);
932 auto videoFrameSize = MeasureVideoContentLayout(videoNodeSize, layoutProperty);
933 auto transformRelativeOffset = host->GetTransformRelativeOffset();
934
935 Rect rect =
936 Rect(transformRelativeOffset.GetX() + (videoNodeSize.Width() - videoFrameSize.Width()) / AVERAGE_VALUE,
937 transformRelativeOffset.GetY() + (videoNodeSize.Height() - videoFrameSize.Height()) / AVERAGE_VALUE,
938 videoFrameSize.Width(), videoFrameSize.Height());
939 if (renderSurface_ && (rect != lastBoundsRect_)) {
940 renderSurface_->SetExtSurfaceBounds(rect.Left(), rect.Top(), rect.Width(), rect.Height());
941 lastBoundsRect_ = rect;
942 }
943 }
944 }
945
OnColorConfigurationUpdate()946 void VideoPattern::OnColorConfigurationUpdate()
947 {
948 auto host = GetHost();
949 CHECK_NULL_VOID(host);
950 auto pipelineContext = PipelineBase::GetCurrentContext();
951 CHECK_NULL_VOID(pipelineContext);
952 auto videoTheme = pipelineContext->GetTheme<VideoTheme>();
953 CHECK_NULL_VOID(videoTheme);
954 auto renderContext = controlBar_->GetRenderContext();
955 CHECK_NULL_VOID(renderContext);
956 renderContext->UpdateBackgroundColor(videoTheme->GetBkgColor());
957 for (const auto& child : controlBar_->GetChildren()) {
958 if (child->GetTag() == V2::TEXT_ETS_TAG) {
959 auto frameNode = AceType::DynamicCast<FrameNode>(child);
960 if (frameNode) {
961 auto textLayoutProperty = frameNode->GetLayoutProperty<TextLayoutProperty>();
962 if (textLayoutProperty) {
963 auto textStyle = videoTheme->GetTimeTextStyle();
964 textLayoutProperty->UpdateTextColor(textStyle.GetTextColor());
965 }
966 }
967 }
968 }
969 host->SetNeedCallChildrenUpdate(false);
970 host->MarkModifyDone();
971 host->MarkDirtyNode();
972 }
973
CreateControlBar(int32_t nodeId)974 RefPtr<FrameNode> VideoPattern::CreateControlBar(int32_t nodeId)
975 {
976 auto pipelineContext = PipelineBase::GetCurrentContext();
977 CHECK_NULL_RETURN(pipelineContext, nullptr);
978 auto videoTheme = pipelineContext->GetTheme<VideoTheme>();
979 CHECK_NULL_RETURN(videoTheme, nullptr);
980 auto controlBar = FrameNode::GetOrCreateFrameNode(
981 V2::ROW_ETS_TAG, nodeId, []() { return AceType::MakeRefPtr<LinearLayoutPattern>(false); });
982 CHECK_NULL_RETURN(controlBar, nullptr);
983 controlBar_ = controlBar;
984
985 auto playButton = CreateSVG();
986 CHECK_NULL_RETURN(playButton, nullptr);
987 ChangePlayButtonTag(playButton);
988 controlBar->AddChild(playButton);
989
990 auto currentPosText = CreateText(currentPos_);
991 CHECK_NULL_RETURN(currentPosText, nullptr);
992 controlBar->AddChild(currentPosText);
993
994 auto slider = CreateSlider();
995 CHECK_NULL_RETURN(currentPosText, nullptr);
996 controlBar->AddChild(slider);
997
998 auto durationText = CreateText(duration_);
999 CHECK_NULL_RETURN(durationText, nullptr);
1000 controlBar->AddChild(durationText);
1001
1002 auto fullScreenButton = CreateSVG();
1003 CHECK_NULL_RETURN(fullScreenButton, nullptr);
1004 SetFullScreenButtonCallBack(fullScreenButton);
1005 ChangeFullScreenButtonTag(InstanceOf<VideoFullScreenNode>(this), fullScreenButton);
1006 controlBar->AddChild(fullScreenButton);
1007
1008 auto renderContext = controlBar->GetRenderContext();
1009 renderContext->UpdateBackgroundColor(videoTheme->GetBkgColor());
1010 auto controlBarLayoutProperty = controlBar->GetLayoutProperty<LinearLayoutProperty>();
1011 controlBarLayoutProperty->UpdateMainAxisAlign(FlexAlign::SPACE_BETWEEN);
1012 return controlBar;
1013 }
1014
CreateSlider()1015 RefPtr<FrameNode> VideoPattern::CreateSlider()
1016 {
1017 auto pipelineContext = PipelineBase::GetCurrentContext();
1018 CHECK_NULL_RETURN(pipelineContext, nullptr);
1019 auto videoTheme = pipelineContext->GetTheme<VideoTheme>();
1020 CHECK_NULL_RETURN(videoTheme, nullptr);
1021
1022 auto sliderNode = FrameNode::CreateFrameNode(V2::SLIDER_ETS_TAG, -1, AceType::MakeRefPtr<SliderPattern>());
1023 CHECK_NULL_RETURN(sliderNode, nullptr);
1024 auto sliderLayoutProperty = sliderNode->GetLayoutProperty<SliderLayoutProperty>();
1025 CHECK_NULL_RETURN(sliderLayoutProperty, nullptr);
1026
1027 auto sliderEdge = videoTheme->GetSliderEdge();
1028 PaddingProperty padding;
1029 padding.left = CalcLength(sliderEdge.Left());
1030 padding.right = CalcLength(sliderEdge.Right());
1031 padding.top = CalcLength(sliderEdge.Top());
1032 padding.bottom = CalcLength(sliderEdge.Bottom());
1033 sliderLayoutProperty->UpdatePadding(padding);
1034 sliderLayoutProperty->UpdateLayoutWeight(1.0);
1035
1036 SliderOnChangeEvent sliderOnChangeEvent = [weak = WeakClaim(this)](float value, int32_t mode) {
1037 auto videoPattern = weak.Upgrade();
1038 CHECK_NULL_VOID(videoPattern);
1039 videoPattern->OnSliderChange(value, mode);
1040 };
1041 auto sliderEventHub = sliderNode->GetEventHub<SliderEventHub>();
1042 sliderEventHub->SetOnChange(std::move(sliderOnChangeEvent));
1043
1044 auto sliderPaintProperty = sliderNode->GetPaintProperty<SliderPaintProperty>();
1045 CHECK_NULL_RETURN(sliderPaintProperty, nullptr);
1046 sliderPaintProperty->UpdateMax(static_cast<float>(duration_));
1047 sliderPaintProperty->UpdateSelectColor(Color::BLACK);
1048 sliderPaintProperty->UpdateValue(static_cast<float>(currentPos_));
1049 sliderNode->MarkModifyDone();
1050 return sliderNode;
1051 }
1052
CreateText(uint32_t time)1053 RefPtr<FrameNode> VideoPattern::CreateText(uint32_t time)
1054 {
1055 auto pipelineContext = PipelineBase::GetCurrentContext();
1056 CHECK_NULL_RETURN(pipelineContext, nullptr);
1057 auto videoTheme = pipelineContext->GetTheme<VideoTheme>();
1058 CHECK_NULL_RETURN(videoTheme, nullptr);
1059
1060 auto textNode = FrameNode::CreateFrameNode(V2::TEXT_ETS_TAG, -1, AceType::MakeRefPtr<TextPattern>());
1061 CHECK_NULL_RETURN(textNode, nullptr);
1062 auto textLayoutProperty = textNode->GetLayoutProperty<TextLayoutProperty>();
1063 CHECK_NULL_RETURN(textLayoutProperty, nullptr);
1064 auto videoLayoutProperty = GetLayoutProperty<VideoLayoutProperty>();
1065 CHECK_NULL_RETURN(videoLayoutProperty, nullptr);
1066 std::string label = "";
1067 if (videoLayoutProperty->GetControlsValue(true)) {
1068 label = IntTimeToText(time);
1069 }
1070 textLayoutProperty->UpdateContent(label);
1071 auto textEdge = videoTheme->GetTextEdge();
1072 PaddingProperty padding;
1073 padding.left = CalcLength(textEdge.Left());
1074 padding.right = CalcLength(textEdge.Right());
1075 padding.top = CalcLength(textEdge.Top());
1076 padding.bottom = CalcLength(textEdge.Bottom());
1077 textLayoutProperty->UpdatePadding(padding);
1078 auto textStyle = videoTheme->GetTimeTextStyle();
1079 textLayoutProperty->UpdateFontSize(textStyle.GetFontSize());
1080 textLayoutProperty->UpdateTextColor(textStyle.GetTextColor());
1081 return textNode;
1082 }
1083
CreateSVG()1084 RefPtr<FrameNode> VideoPattern::CreateSVG()
1085 {
1086 auto pipelineContext = PipelineBase::GetCurrentContext();
1087 CHECK_NULL_RETURN(pipelineContext, nullptr);
1088 auto videoTheme = pipelineContext->GetTheme<VideoTheme>();
1089 CHECK_NULL_RETURN(videoTheme, nullptr);
1090
1091 auto svgNode = FrameNode::CreateFrameNode(V2::IMAGE_ETS_TAG, -1, AceType::MakeRefPtr<ImagePattern>());
1092 CHECK_NULL_RETURN(svgNode, nullptr);
1093 auto svgLayoutProperty = svgNode->GetLayoutProperty<ImageLayoutProperty>();
1094
1095 auto btnEdge = videoTheme->GetBtnEdge();
1096 PaddingProperty padding;
1097 padding.left = CalcLength(btnEdge.Left());
1098 padding.right = CalcLength(btnEdge.Right());
1099 padding.top = CalcLength(btnEdge.Top());
1100 padding.bottom = CalcLength(btnEdge.Bottom());
1101 svgLayoutProperty->UpdatePadding(padding);
1102
1103 auto btnSize = videoTheme->GetBtnSize();
1104 SizeF size { static_cast<float>(btnSize.Width()), static_cast<float>(btnSize.Height()) };
1105 svgLayoutProperty->UpdateMarginSelfIdealSize(size);
1106 auto width = Dimension(btnSize.Width(), DimensionUnit::VP).ConvertToPx();
1107 auto height = Dimension(btnSize.Height(), DimensionUnit::VP).ConvertToPx();
1108 CalcSize idealSize = { CalcLength(width), CalcLength(height) };
1109 MeasureProperty layoutConstraint;
1110 layoutConstraint.selfIdealSize = idealSize;
1111 layoutConstraint.maxSize = idealSize;
1112 svgNode->UpdateLayoutConstraint(layoutConstraint);
1113 return svgNode;
1114 }
1115
SetMethodCall()1116 void VideoPattern::SetMethodCall()
1117 {
1118 auto videoController = AceType::MakeRefPtr<VideoController>();
1119 auto context = PipelineContext::GetCurrentContext();
1120 CHECK_NULL_VOID(context);
1121 auto uiTaskExecutor = SingleTaskExecutor::Make(context->GetTaskExecutor(), TaskExecutor::TaskType::UI);
1122 videoController->SetStartImpl([weak = WeakClaim(this), uiTaskExecutor]() {
1123 uiTaskExecutor.PostTask([weak]() {
1124 auto pattern = weak.Upgrade();
1125 CHECK_NULL_VOID(pattern);
1126 auto targetPattern = pattern->GetTargetVideoPattern();
1127 CHECK_NULL_VOID(targetPattern);
1128 targetPattern->Start();
1129 });
1130 });
1131 videoController->SetPausetImpl([weak = WeakClaim(this), uiTaskExecutor]() {
1132 uiTaskExecutor.PostTask([weak]() {
1133 auto pattern = weak.Upgrade();
1134 CHECK_NULL_VOID(pattern);
1135 auto targetPattern = pattern->GetTargetVideoPattern();
1136 CHECK_NULL_VOID(targetPattern);
1137 targetPattern->Pause();
1138 });
1139 });
1140 videoController->SetStopImpl([weak = WeakClaim(this), uiTaskExecutor]() {
1141 uiTaskExecutor.PostTask([weak]() {
1142 auto pattern = weak.Upgrade();
1143 CHECK_NULL_VOID(pattern);
1144 auto targetPattern = pattern->GetTargetVideoPattern();
1145 CHECK_NULL_VOID(targetPattern);
1146 targetPattern->Stop();
1147 });
1148 });
1149 videoController->SetSeekToImpl([weak = WeakClaim(this), uiTaskExecutor](float pos, SeekMode seekMode) {
1150 uiTaskExecutor.PostTask([weak, pos, seekMode]() {
1151 auto pattern = weak.Upgrade();
1152 CHECK_NULL_VOID(pattern);
1153 auto targetPattern = pattern->GetTargetVideoPattern();
1154 CHECK_NULL_VOID(targetPattern);
1155 targetPattern->SetCurrentTime(pos, seekMode);
1156 });
1157 });
1158 videoController->SetRequestFullscreenImpl([weak = WeakClaim(this), uiTaskExecutor](bool isFullScreen) {
1159 uiTaskExecutor.PostTask([weak, isFullScreen]() {
1160 auto videoPattern = weak.Upgrade();
1161 CHECK_NULL_VOID(videoPattern);
1162 if (isFullScreen) {
1163 videoPattern->FullScreen();
1164 } else {
1165 videoPattern->ResetLastBoundsRect();
1166 auto targetPattern = videoPattern->GetTargetVideoPattern();
1167 CHECK_NULL_VOID(targetPattern);
1168 auto fullScreenPattern = AceType::DynamicCast<VideoFullScreenPattern>(targetPattern);
1169 CHECK_NULL_VOID(fullScreenPattern);
1170 fullScreenPattern->ExitFullScreen();
1171 }
1172 });
1173 });
1174 videoController->SetExitFullscreenImpl([weak = WeakClaim(this), uiTaskExecutor](bool isSync) {
1175 if (isSync) {
1176 auto pattern = weak.Upgrade();
1177 CHECK_NULL_VOID(pattern);
1178 auto targetPattern = pattern->GetTargetVideoPattern();
1179 CHECK_NULL_VOID(targetPattern);
1180 pattern->ResetLastBoundsRect();
1181 auto fullScreenPattern = AceType::DynamicCast<VideoFullScreenPattern>(targetPattern);
1182 fullScreenPattern->ExitFullScreen();
1183 return;
1184 }
1185 uiTaskExecutor.PostTask([weak]() {
1186 auto pattern = weak.Upgrade();
1187 CHECK_NULL_VOID(pattern);
1188 pattern->ResetLastBoundsRect();
1189 auto targetPattern = pattern->GetTargetVideoPattern();
1190 CHECK_NULL_VOID(targetPattern);
1191 auto fullScreenPattern = AceType::DynamicCast<VideoFullScreenPattern>(targetPattern);
1192 CHECK_NULL_VOID(fullScreenPattern);
1193 fullScreenPattern->ExitFullScreen();
1194 });
1195 });
1196 CHECK_NULL_VOID_NOLOG(videoControllerV2_);
1197 videoControllerV2_->AddVideoController(videoController);
1198 }
1199
Start()1200 void VideoPattern::Start()
1201 {
1202 LOGI("Video start to play");
1203 if (!mediaPlayer_ || !mediaPlayer_->IsMediaPlayerValid()) {
1204 return;
1205 }
1206
1207 if (isStop_ && mediaPlayer_->PrepareAsync() != 0) {
1208 LOGE("Player has not prepared");
1209 return;
1210 }
1211 auto context = PipelineContext::GetCurrentContext();
1212 CHECK_NULL_VOID(context);
1213
1214 auto platformTask = SingleTaskExecutor::Make(context->GetTaskExecutor(), TaskExecutor::TaskType::BACKGROUND);
1215 platformTask.PostTask([weak = WeakClaim(RawPtr(mediaPlayer_))] {
1216 auto mediaPlayer = weak.Upgrade();
1217 CHECK_NULL_VOID(mediaPlayer);
1218 LOGI("trigger mediaPlayer play");
1219 mediaPlayer->Play();
1220 });
1221 }
1222
Pause()1223 void VideoPattern::Pause()
1224 {
1225 if (!mediaPlayer_ || !mediaPlayer_->IsMediaPlayerValid()) {
1226 return;
1227 }
1228 LOGD("Video Pause");
1229 mediaPlayer_->Pause();
1230 }
1231
Stop()1232 void VideoPattern::Stop()
1233 {
1234 if (!mediaPlayer_ || !mediaPlayer_->IsMediaPlayerValid()) {
1235 return;
1236 }
1237
1238 OnCurrentTimeChange(0);
1239 LOGD("Video Stop");
1240 mediaPlayer_->Stop();
1241 isStop_ = true;
1242 }
1243
FireError()1244 void VideoPattern::FireError()
1245 {
1246 auto context = PipelineContext::GetCurrentContext();
1247 CHECK_NULL_VOID(context);
1248
1249 // OnError function must be excuted on ui, so get the uiTaskExecutor.
1250 auto uiTaskExecutor = SingleTaskExecutor::Make(context->GetTaskExecutor(), TaskExecutor::TaskType::UI);
1251 uiTaskExecutor.PostTask([weak = WeakClaim(this)] {
1252 auto videoPattern = weak.Upgrade();
1253 CHECK_NULL_VOID(videoPattern);
1254 videoPattern->OnError("");
1255 });
1256 }
1257
ChangePlayButtonTag()1258 void VideoPattern::ChangePlayButtonTag()
1259 {
1260 auto context = PipelineContext::GetCurrentContext();
1261 CHECK_NULL_VOID(context);
1262 auto host = GetHost();
1263 CHECK_NULL_VOID(host);
1264 const auto& children = host->GetChildren();
1265 for (const auto& child : children) {
1266 if (child->GetTag() == V2::ROW_ETS_TAG) {
1267 auto playBtn = DynamicCast<FrameNode>(child->GetChildAtIndex(0));
1268 ChangePlayButtonTag(playBtn);
1269 break;
1270 }
1271 }
1272 }
1273
ChangePlayButtonTag(RefPtr<FrameNode> & playBtn)1274 void VideoPattern::ChangePlayButtonTag(RefPtr<FrameNode>& playBtn)
1275 {
1276 CHECK_NULL_VOID(playBtn);
1277 auto playClickCallback = [weak = WeakClaim(this), playing = isPlaying_](GestureEvent& /* info */) {
1278 auto videoPattern = weak.Upgrade();
1279 CHECK_NULL_VOID(videoPattern);
1280 if (playing) {
1281 videoPattern->Pause();
1282 } else {
1283 videoPattern->Start();
1284 }
1285 };
1286 auto playBtnEvent = playBtn->GetOrCreateGestureEventHub();
1287 playBtnEvent->SetUserOnClick(std::move(playClickCallback));
1288 auto svgLayoutProperty = playBtn->GetLayoutProperty<ImageLayoutProperty>();
1289 auto resourceId = isPlaying_ ? InternalResource::ResourceId::PAUSE_SVG : InternalResource::ResourceId::PLAY_SVG;
1290 auto svgSourceInfo = ImageSourceInfo("");
1291 svgSourceInfo.SetResourceId(resourceId);
1292 svgLayoutProperty->UpdateImageSourceInfo(svgSourceInfo);
1293 playBtn->MarkModifyDone();
1294 playBtn->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
1295 }
1296
SetFullScreenButtonCallBack(RefPtr<FrameNode> & fullScreenBtn)1297 void VideoPattern::SetFullScreenButtonCallBack(RefPtr<FrameNode>& fullScreenBtn)
1298 {
1299 CHECK_NULL_VOID(fullScreenBtn);
1300 auto fsClickCallback = [weak = WeakClaim(this)](GestureEvent& /* info */) {
1301 auto videoPattern = weak.Upgrade();
1302 CHECK_NULL_VOID(videoPattern);
1303 if (InstanceOf<VideoFullScreenPattern>(videoPattern)) {
1304 auto pattern = AceType::DynamicCast<VideoFullScreenPattern>(videoPattern);
1305 CHECK_NULL_VOID(pattern);
1306 videoPattern->ResetLastBoundsRect();
1307 pattern->ExitFullScreen();
1308 } else {
1309 videoPattern->FullScreen();
1310 }
1311 };
1312 auto fullScreenBtnEvent = fullScreenBtn->GetOrCreateGestureEventHub();
1313 fullScreenBtnEvent->SetUserOnClick(std::move(fsClickCallback));
1314 }
1315
ChangeFullScreenButtonTag(bool isFullScreen,RefPtr<FrameNode> & fullScreenBtn)1316 void VideoPattern::ChangeFullScreenButtonTag(bool isFullScreen, RefPtr<FrameNode>& fullScreenBtn)
1317 {
1318 CHECK_NULL_VOID(fullScreenBtn);
1319 auto svgLayoutProperty = fullScreenBtn->GetLayoutProperty<ImageLayoutProperty>();
1320 auto resourceId =
1321 isFullScreen ? InternalResource::ResourceId::QUIT_FULLSCREEN_SVG : InternalResource::ResourceId::FULLSCREEN_SVG;
1322 auto svgSourceInfo = ImageSourceInfo("");
1323 svgSourceInfo.SetResourceId(resourceId);
1324 svgLayoutProperty->UpdateImageSourceInfo(svgSourceInfo);
1325 fullScreenBtn->MarkModifyDone();
1326 fullScreenBtn->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
1327 }
1328
SetCurrentTime(float currentPos,OHOS::Ace::SeekMode seekMode)1329 void VideoPattern::SetCurrentTime(float currentPos, OHOS::Ace::SeekMode seekMode)
1330 {
1331 LOGD("Set current pos: %{public}lf, mode: %{public}d", currentPos, seekMode);
1332 if (!mediaPlayer_ || !mediaPlayer_->IsMediaPlayerValid()) {
1333 return;
1334 }
1335 if (GreatOrEqual(currentPos, 0.0)) {
1336 LOGD("Video Seek");
1337 mediaPlayer_->Seek(static_cast<int32_t>(currentPos * MILLISECONDS_TO_SECONDS), seekMode);
1338 }
1339 }
1340
OnSliderChange(float posTime,int32_t mode)1341 void VideoPattern::OnSliderChange(float posTime, int32_t mode)
1342 {
1343 LOGD("posTime: %{public}lf, mode: %{public}d", posTime, mode);
1344 SetCurrentTime(posTime, OHOS::Ace::SeekMode::SEEK_PREVIOUS_SYNC);
1345 auto eventHub = GetEventHub<VideoEventHub>();
1346 CHECK_NULL_VOID(eventHub);
1347 auto json = JsonUtil::Create(true);
1348 json->Put("time", static_cast<double>(posTime));
1349 auto param = json->ToString();
1350 CHECK_NULL_VOID(eventHub);
1351 if (mode == SliderChangeMode::BEGIN || mode == SliderChangeMode::MOVING) {
1352 eventHub->FireSeekingEvent(param);
1353 } else if (mode == SliderChangeMode::END) {
1354 eventHub->FireSeekedEvent(param);
1355 }
1356 }
1357
OnFullScreenChange(bool isFullScreen)1358 void VideoPattern::OnFullScreenChange(bool isFullScreen)
1359 {
1360 auto json = JsonUtil::Create(true);
1361 json->Put("fullscreen", isFullScreen);
1362 auto param = json->ToString();
1363 auto eventHub = GetEventHub<VideoEventHub>();
1364 CHECK_NULL_VOID(eventHub);
1365 eventHub->FireFullScreenChangeEvent(param);
1366 auto host = GetHost();
1367 CHECK_NULL_VOID(host);
1368 const auto& children = host->GetChildren();
1369 for (const auto& child : children) {
1370 if (child->GetTag() == V2::ROW_ETS_TAG) {
1371 auto fsBtn = DynamicCast<FrameNode>(child->GetChildAtIndex(FULL_SCREEN_POS));
1372 ChangeFullScreenButtonTag(isFullScreen, fsBtn);
1373 break;
1374 }
1375 }
1376 if (!SystemProperties::GetExtSurfaceEnabled()) {
1377 return;
1378 }
1379 if (!fullScreenNodeId_.has_value()) {
1380 SetMediaFullScreen(isFullScreen);
1381 return;
1382 }
1383 auto fullScreenNode = FrameNode::GetFrameNode(V2::VIDEO_ETS_TAG, fullScreenNodeId_.value());
1384 CHECK_NULL_VOID(fullScreenNode);
1385 auto fullScreenPattern = AceType::DynamicCast<VideoFullScreenPattern>(fullScreenNode->GetPattern());
1386 CHECK_NULL_VOID(fullScreenPattern);
1387 fullScreenPattern->SetMediaFullScreen(isFullScreen);
1388 }
1389
FullScreen()1390 void VideoPattern::FullScreen()
1391 {
1392 if (fullScreenNodeId_.has_value()) {
1393 return;
1394 }
1395 ResetLastBoundsRect();
1396 auto host = GetHost();
1397 CHECK_NULL_VOID(host);
1398 auto videoNode = AceType::DynamicCast<VideoNode>(host);
1399 CHECK_NULL_VOID(videoNode);
1400 auto fullScreenPattern = AceType::MakeRefPtr<VideoFullScreenPattern>(videoControllerV2_);
1401 fullScreenPattern->InitFullScreenParam(
1402 AceType::Claim(this), renderSurface_, mediaPlayer_, renderContextForMediaPlayer_);
1403 fullScreenNodeId_ = ElementRegister::GetInstance()->MakeUniqueId();
1404 auto fullScreenNode =
1405 VideoFullScreenNode::CreateFullScreenNode(V2::VIDEO_ETS_TAG, fullScreenNodeId_.value(), fullScreenPattern);
1406 CHECK_NULL_VOID(fullScreenNode);
1407 fullScreenPattern->RequestFullScreen(videoNode);
1408 }
1409
EnableDrag()1410 void VideoPattern::EnableDrag()
1411 {
1412 auto host = GetHost();
1413 CHECK_NULL_VOID(host);
1414 auto layoutProperty = GetLayoutProperty<VideoLayoutProperty>();
1415 std::string videoSrcBefore = src_;
1416 std::string imageSrcBefore = "";
1417 if (layoutProperty->HasPosterImageInfo()) {
1418 imageSrcBefore = layoutProperty->GetPosterImageInfo().value().GetSrc();
1419 }
1420 #ifdef ENABLE_DRAG_FRAMEWORK
1421 auto dragEnd = [this, videoSrcBefore](const RefPtr<OHOS::Ace::DragEvent>& event, const std::string& extraParams) {
1422 auto videoLayoutProperty = this->GetLayoutProperty<VideoLayoutProperty>();
1423 CHECK_NULL_VOID(videoLayoutProperty);
1424 auto unifiedData = event->GetData();
1425 std::string videoSrc = "";
1426 if (unifiedData != nullptr) {
1427 int ret = UdmfClient::GetInstance()->GetVideoRecordUri(unifiedData, videoSrc);
1428 if (ret != 0) {
1429 LOGE("unifiedRecords is empty");
1430 return;
1431 }
1432 } else {
1433 auto json = JsonUtil::ParseJsonString(extraParams);
1434 std::string key = "extraInfo";
1435 videoSrc = json->GetString(key);
1436 }
1437
1438 if (videoSrc == videoSrcBefore) {
1439 return;
1440 }
1441
1442 dragEndAutoPlay_ = true;
1443 videoLayoutProperty->UpdateVideoSource(videoSrc);
1444
1445 auto frameNode = this->GetHost();
1446 frameNode->MarkModifyDone();
1447 };
1448 #else
1449 auto dragEnd = [this, videoSrcBefore, imageSrcBefore](
1450 const RefPtr<OHOS::Ace::DragEvent>& event, const std::string& extraParams) {
1451 if (extraParams.empty()) {
1452 LOGE("extraParams is empty");
1453 return;
1454 }
1455 auto videoLayoutProperty = this->GetLayoutProperty<VideoLayoutProperty>();
1456 CHECK_NULL_VOID(videoLayoutProperty);
1457 auto json = JsonUtil::ParseJsonString(extraParams);
1458 std::string key = "extraInfo";
1459 std::string extraInfo = json->GetString(key);
1460 if (extraInfo.empty()) {
1461 LOGE("extraInfo is empty");
1462 return;
1463 }
1464 int index = extraInfo.find("::");
1465 if (index < 0 || index == extraInfo.length() - 2) {
1466 LOGE("video source is empty");
1467 return;
1468 }
1469 std::string videoSrc = extraInfo.substr(index + 2); // 2 :the length of "::"
1470 std::string imageSrc = "";
1471 if (index != 0) {
1472 imageSrc = extraInfo.substr(0, index);
1473 }
1474
1475 bool isInitialState = this->isInitialState_;
1476 if ((!isInitialState && videoSrc == videoSrcBefore) ||
1477 (isInitialState && videoSrc == videoSrcBefore && imageSrc == imageSrcBefore)) {
1478 return;
1479 }
1480
1481 dragEndAutoPlay_ = true;
1482 videoLayoutProperty->UpdateVideoSource(videoSrc);
1483 ImageSourceInfo imageSourceInfo = ImageSourceInfo(imageSrc);
1484 videoLayoutProperty->UpdatePosterImageInfo(imageSourceInfo);
1485
1486 if (!isInitialState) {
1487 this->SetIsStop(true);
1488 }
1489 auto frameNode = this->GetHost();
1490 frameNode->MarkModifyDone();
1491 };
1492 #endif
1493 auto eventHub = host->GetEventHub<EventHub>();
1494 CHECK_NULL_VOID(eventHub);
1495 eventHub->SetOnDrop(std::move(dragEnd));
1496 }
1497
~VideoPattern()1498 VideoPattern::~VideoPattern()
1499 {
1500 if (renderContextForMediaPlayer_) {
1501 renderContextForMediaPlayer_->RemoveSurfaceChangedCallBack();
1502 }
1503 if (!fullScreenNodeId_.has_value()) {
1504 return;
1505 }
1506 auto fullScreenNode = FrameNode::GetFrameNode(V2::VIDEO_ETS_TAG, fullScreenNodeId_.value());
1507 CHECK_NULL_VOID(fullScreenNode);
1508 auto parent = fullScreenNode->GetParent();
1509 CHECK_NULL_VOID(parent);
1510 parent->RemoveChild(fullScreenNode);
1511 parent->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
1512 }
1513
RecoverState(const RefPtr<VideoPattern> & videoPattern)1514 void VideoPattern::RecoverState(const RefPtr<VideoPattern>& videoPattern)
1515 {
1516 CHECK_NULL_VOID(videoPattern);
1517 currentPos_ = videoPattern->GetCurrentPos();
1518 if (mediaPlayer_->IsMediaPlayerValid() && mediaPlayer_->IsPlaying() != isPlaying_) {
1519 isPlaying_ = mediaPlayer_->IsPlaying();
1520 ChangePlayButtonTag();
1521 }
1522 isInitialState_ = videoPattern->GetInitialState();
1523 auto layoutProperty = videoPattern->GetLayoutProperty<VideoLayoutProperty>();
1524 src_ = layoutProperty->GetVideoSourceValue("");
1525 isStop_ = videoPattern->GetIsStop();
1526 muted_ = videoPattern->GetMuted();
1527 autoPlay_ = videoPattern->GetAutoPlay();
1528 loop_ = videoPattern->GetLoop();
1529 duration_ = videoPattern->GetDuration();
1530 progressRate_ = videoPattern->GetProgressRate();
1531 fullScreenNodeId_.reset();
1532 RegisterMediaPlayerEvent();
1533 auto videoNode = GetHost();
1534 CHECK_NULL_VOID(videoNode);
1535 // change event hub to the origin video node
1536 videoPattern->GetEventHub<VideoEventHub>()->AttachHost(videoNode);
1537 videoNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF_AND_CHILD);
1538 }
1539
UpdateFsState()1540 void VideoPattern::UpdateFsState()
1541 {
1542 if (!fullScreenNodeId_.has_value()) {
1543 return;
1544 }
1545 auto videoNode = FrameNode::GetFrameNode(V2::VIDEO_ETS_TAG, fullScreenNodeId_.value());
1546 CHECK_NULL_VOID(videoNode);
1547 auto videoPattern = AceType::DynamicCast<VideoFullScreenPattern>(videoNode->GetPattern());
1548 CHECK_NULL_VOID(videoPattern);
1549 // update full screen state
1550 videoPattern->UpdateState();
1551 }
1552
IsFullScreen()1553 bool VideoPattern::IsFullScreen()
1554 {
1555 return fullScreenNodeId_.has_value();
1556 }
1557
GetTargetVideoPattern()1558 RefPtr<VideoPattern> VideoPattern::GetTargetVideoPattern()
1559 {
1560 auto isFullScreen = IsFullScreen();
1561 auto patternIsFullScreen = AceType::InstanceOf<VideoFullScreenPattern>(this);
1562 if ((isFullScreen && patternIsFullScreen) || (!isFullScreen && !patternIsFullScreen)) {
1563 return AceType::Claim(this);
1564 }
1565 if (patternIsFullScreen) {
1566 // current is full screen,need to be released
1567 auto fullScreenPattern = AceType::DynamicCast<VideoFullScreenPattern>(this);
1568 return fullScreenPattern->GetVideoPattern();
1569 }
1570 // current node is origin video node, need to operate full screen node
1571 auto fullScreenNode = GetFullScreenNode();
1572 CHECK_NULL_RETURN(fullScreenNode, nullptr);
1573 return fullScreenNode->GetPattern<VideoPattern>();
1574 }
1575 } // namespace OHOS::Ace::NG
1576