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