• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "core/components_ng/pattern/video/video_pattern.h"
17 
18 #include "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