• 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/background_task_helper/background_task_helper.h"
21 #include "base/geometry/dimension.h"
22 #include "base/geometry/ng/size_t.h"
23 #include "base/i18n/localization.h"
24 #include "base/json/json_util.h"
25 #include "base/thread/task_executor.h"
26 #include "base/utils/string_utils.h"
27 #include "base/utils/system_properties.h"
28 #include "base/utils/utils.h"
29 #include "core/common/ace_engine.h"
30 #include "core/common/ace_view.h"
31 #include "core/common/ai/image_analyzer_manager.h"
32 #include "core/common/container.h"
33 #include "core/common/udmf/udmf_client.h"
34 #include "core/components/common/layout/constants.h"
35 #include "core/components/common/properties/color.h"
36 #include "core/components/declaration/button/button_declaration.h"
37 #include "core/components/video/video_theme.h"
38 #include "core/components/video/video_utils.h"
39 #include "core/components_ng/pattern/button/button_event_hub.h"
40 #include "core/components_ng/pattern/button/button_layout_property.h"
41 #include "core/components_ng/pattern/button/button_pattern.h"
42 #include "core/components_ng/pattern/image/image_layout_property.h"
43 #include "core/components_ng/pattern/image/image_pattern.h"
44 #include "core/components_ng/pattern/linear_layout/linear_layout_pattern.h"
45 #include "core/components_ng/pattern/linear_layout/linear_layout_property.h"
46 #include "core/components_ng/pattern/slider/slider_event_hub.h"
47 #include "core/components_ng/pattern/slider/slider_layout_property.h"
48 #include "core/components_ng/pattern/slider/slider_paint_property.h"
49 #include "core/components_ng/pattern/slider/slider_pattern.h"
50 #include "core/components_ng/pattern/text/text_layout_property.h"
51 #include "core/components_ng/pattern/text/text_pattern.h"
52 #include "core/components_ng/pattern/video/video_event_hub.h"
53 #include "core/components_ng/pattern/video/video_full_screen_node.h"
54 #include "core/components_ng/pattern/video/video_full_screen_pattern.h"
55 #include "core/components_ng/pattern/video/video_layout_property.h"
56 #include "core/components_ng/pattern/video/video_node.h"
57 #include "core/components_ng/property/gradient_property.h"
58 #include "core/components_ng/property/property.h"
59 #include "core/components_v2/inspector/inspector_constants.h"
60 #include "core/pipeline_ng/pipeline_context.h"
61 namespace OHOS::Ace::NG {
62 namespace {
63 using HiddenChangeEvent = std::function<void(bool)>;
64 constexpr uint32_t SECONDS_PER_HOUR = 3600;
65 constexpr uint32_t SECONDS_PER_MINUTE = 60;
66 const std::string FORMAT_HH_MM_SS = "%02d:%02d:%02d";
67 const std::string FORMAT_MM_SS = "%02d:%02d";
68 constexpr int32_t MILLISECONDS_TO_SECONDS = 1000;
69 constexpr uint32_t CURRENT_POS = 1;
70 constexpr uint32_t SLIDER_POS = 2;
71 constexpr uint32_t DURATION_POS = 3;
72 constexpr uint32_t FULL_SCREEN_POS = 4;
73 constexpr int32_t AVERAGE_VALUE = 2;
74 constexpr int32_t ANALYZER_DELAY_TIME = 100;
75 constexpr int32_t ANALYZER_CAPTURE_DELAY_TIME = 1000;
76 const Dimension LIFT_HEIGHT = 28.0_vp;
77 const std::string PNG_FILE_EXTENSION = "png";
78 constexpr int32_t MEDIA_TYPE_AUD = 0;
79 
80 // Default error, empty string.
81 const std::string ERROR = "";
82 
83 enum SliderChangeMode {
84     BEGIN = 0,
85     MOVING,
86     END,
87 };
88 
IntTimeToText(uint32_t time)89 std::string IntTimeToText(uint32_t time)
90 {
91     auto minutes = (time % SECONDS_PER_HOUR) / SECONDS_PER_MINUTE;
92     auto seconds = time % SECONDS_PER_MINUTE;
93     if (time >= SECONDS_PER_HOUR) {
94         auto hours = time / SECONDS_PER_HOUR;
95         return StringUtils::FormatString(FORMAT_HH_MM_SS.c_str(), hours, minutes, seconds);
96     }
97     return StringUtils::FormatString(FORMAT_MM_SS.c_str(), minutes, seconds);
98 }
99 
CalculateFitContain(const SizeF & videoSize,const SizeF & layoutSize)100 SizeF CalculateFitContain(const SizeF& videoSize, const SizeF& layoutSize)
101 {
102     double layoutRatio = NearZero(layoutSize.Height()) ? 0.0 : layoutSize.Width() / layoutSize.Height();
103     double sourceRatio = NearZero(videoSize.Height()) ? layoutRatio : videoSize.Width() / videoSize.Height();
104 
105     if (NearZero(layoutRatio) || NearZero(sourceRatio)) {
106         return layoutSize;
107     }
108     if (sourceRatio < layoutRatio) {
109         return { static_cast<float>(sourceRatio) * layoutSize.Height(), layoutSize.Height() };
110     }
111     return { layoutSize.Width(), static_cast<float>(layoutSize.Width() / sourceRatio) };
112 }
113 
CalculateFitFill(const SizeF & layoutSize)114 SizeF CalculateFitFill(const SizeF& layoutSize)
115 {
116     return layoutSize;
117 }
118 
CalculateFitCover(const SizeF & videoSize,const SizeF & layoutSize)119 SizeF CalculateFitCover(const SizeF& videoSize, const SizeF& layoutSize)
120 {
121     double layoutRatio = NearZero(layoutSize.Height()) ? 0.0 : layoutSize.Width() / layoutSize.Height();
122     double sourceRatio = NearZero(videoSize.Height()) ? layoutRatio : videoSize.Width() / videoSize.Height();
123 
124     if (NearZero(layoutRatio) || NearZero(sourceRatio)) {
125         return layoutSize;
126     }
127     if (sourceRatio < layoutRatio) {
128         return { layoutSize.Width(), static_cast<float>(layoutSize.Width() / sourceRatio) };
129     }
130     return { static_cast<float>(layoutSize.Height() * sourceRatio), layoutSize.Height() };
131 }
132 
CalculateFitNone(const SizeF & videoSize)133 SizeF CalculateFitNone(const SizeF& videoSize)
134 {
135     return videoSize;
136 }
137 
CalculateFitScaleDown(const SizeF & videoSize,const SizeF & layoutSize)138 SizeF CalculateFitScaleDown(const SizeF& videoSize, const SizeF& layoutSize)
139 {
140     if (layoutSize.Width() > videoSize.Width()) {
141         return CalculateFitNone(videoSize);
142     }
143     return CalculateFitContain(videoSize, layoutSize);
144 }
145 
MeasureVideoContentLayout(const SizeF & layoutSize,const RefPtr<VideoLayoutProperty> & layoutProperty)146 SizeF MeasureVideoContentLayout(const SizeF& layoutSize, const RefPtr<VideoLayoutProperty>& layoutProperty)
147 {
148     if (!layoutProperty || !layoutProperty->HasVideoSize()) {
149         return layoutSize;
150     }
151 
152     auto videoSize = layoutProperty->GetVideoSizeValue(SizeF(0, 0));
153     auto imageFit = layoutProperty->GetObjectFitValue(ImageFit::COVER);
154     SizeF contentSize = { 0.0, 0.0 };
155     switch (imageFit) {
156         case ImageFit::CONTAIN:
157             contentSize = CalculateFitContain(videoSize, layoutSize);
158             break;
159         case ImageFit::FILL:
160             contentSize = CalculateFitFill(layoutSize);
161             break;
162         case ImageFit::COVER:
163             contentSize = CalculateFitCover(videoSize, layoutSize);
164             break;
165         case ImageFit::NONE:
166             contentSize = CalculateFitNone(videoSize);
167             break;
168         case ImageFit::SCALE_DOWN:
169             contentSize = CalculateFitScaleDown(videoSize, layoutSize);
170             break;
171         default:
172             contentSize = CalculateFitContain(videoSize, layoutSize);
173     }
174 
175     // Just return contentSize as the video frame area.
176     return contentSize;
177 }
178 
RoundValueToPixelGrid(float value,bool isRound,bool forceCeil,bool forceFloor)179 float RoundValueToPixelGrid(float value, bool isRound, bool forceCeil, bool forceFloor)
180 {
181     float fractials = fmod(value, 1.0f);
182     if (fractials < 0.0f) {
183         ++fractials;
184     }
185     if (forceCeil) {
186         return (value - fractials + 1.0f);
187     } else if (forceFloor) {
188         return (value - fractials);
189     } else if (isRound) {
190         if (NearEqual(fractials, 1.0f) || GreatOrEqual(fractials, 0.50f)) {
191             return (value - fractials + 1.0f);
192         } else {
193             return (value - fractials);
194         }
195     }
196     return value;
197 }
198 
AdjustPaintRect(float positionX,float positionY,float width,float height,bool isRound)199 RectF AdjustPaintRect(float positionX, float positionY, float width, float height, bool isRound)
200 {
201     RectF rect;
202     float relativeLeft = positionX;
203     float relativeTop = positionY;
204     float nodeWidth = width;
205     float nodeHeight = height;
206     float absoluteRight = relativeLeft + nodeWidth;
207     float absoluteBottom = relativeTop + nodeHeight;
208     float roundToPixelErrorX = 0.0f;
209     float roundToPixelErrorY = 0.0f;
210 
211     float nodeLeftI = RoundValueToPixelGrid(relativeLeft, isRound, false, false);
212     float nodeTopI = RoundValueToPixelGrid(relativeTop, isRound, false, false);
213     roundToPixelErrorX += nodeLeftI - relativeLeft;
214     roundToPixelErrorY += nodeTopI - relativeTop;
215     rect.SetLeft(nodeLeftI);
216     rect.SetTop(nodeTopI);
217 
218     float nodeWidthI = RoundValueToPixelGrid(absoluteRight, isRound, false, false) - nodeLeftI;
219     float nodeWidthTemp = RoundValueToPixelGrid(nodeWidth, isRound, false, false);
220     roundToPixelErrorX += nodeWidthI - nodeWidth;
221     if (roundToPixelErrorX > 0.5f) {
222         nodeWidthI -= 1.0f;
223         roundToPixelErrorX -= 1.0f;
224     }
225     if (roundToPixelErrorX < -0.5f) {
226         nodeWidthI += 1.0f;
227         roundToPixelErrorX += 1.0f;
228     }
229     if (nodeWidthI < nodeWidthTemp) {
230         roundToPixelErrorX += nodeWidthTemp - nodeWidthI;
231         nodeWidthI = nodeWidthTemp;
232     }
233 
234     float nodeHeightI = RoundValueToPixelGrid(absoluteBottom, isRound, false, false) - nodeTopI;
235     float nodeHeightTemp = RoundValueToPixelGrid(nodeHeight, isRound, false, false);
236     roundToPixelErrorY += nodeHeightI - nodeHeight;
237     if (roundToPixelErrorY > 0.5f) {
238         nodeHeightI -= 1.0f;
239         roundToPixelErrorY -= 1.0f;
240     }
241     if (roundToPixelErrorY < -0.5f) {
242         nodeHeightI += 1.0f;
243         roundToPixelErrorY += 1.0f;
244     }
245     if (nodeHeightI < nodeHeightTemp) {
246         roundToPixelErrorY += nodeHeightTemp - nodeHeightI;
247         nodeHeightI = nodeHeightTemp;
248     }
249 
250     rect.SetWidth(nodeWidthI);
251     rect.SetHeight(nodeHeightI);
252     return rect;
253 }
ConvertToGradient(Color color)254 Gradient ConvertToGradient(Color color)
255 {
256     Gradient gradient;
257     GradientColor gradientColorBegin;
258     gradientColorBegin.SetLinearColor(LinearColor(color));
259     gradientColorBegin.SetDimension(Dimension(0.0f));
260     gradient.AddColor(gradientColorBegin);
261     OHOS::Ace::NG::GradientColor gradientColorEnd;
262     gradientColorEnd.SetLinearColor(LinearColor(color));
263     gradientColorEnd.SetDimension(Dimension(1.0f));
264     gradient.AddColor(gradientColorEnd);
265 
266     return gradient;
267 }
268 } // namespace
269 
VideoPattern(const RefPtr<VideoControllerV2> & videoController)270 VideoPattern::VideoPattern(const RefPtr<VideoControllerV2>& videoController)
271     : instanceId_(Container::CurrentId()), videoControllerV2_(videoController)
272 {}
273 
ResetStatus()274 void VideoPattern::ResetStatus()
275 {
276     isInitialState_ = true;
277     isPlaying_ = false;
278 #ifndef OHOS_PLATFORM
279     isStop_ = false;
280 #endif
281 }
282 
ResetMediaPlayer()283 void VideoPattern::ResetMediaPlayer()
284 {
285     CHECK_NULL_VOID(mediaPlayer_);
286     mediaPlayer_->ResetMediaPlayer();
287     if (!SetSourceForMediaPlayer()) {
288         TAG_LOGW(AceLogTag::ACE_VIDEO, "Video set source for mediaPlayer failed.");
289 
290         // It need post on ui thread.
291         FireError();
292         return;
293     }
294 
295     RegisterMediaPlayerEvent();
296     PrepareSurface();
297     if (mediaPlayer_ && mediaPlayer_->PrepareAsync() != 0) {
298         TAG_LOGE(AceLogTag::ACE_VIDEO, "Player prepare failed");
299     }
300 }
301 
UpdateMediaPlayerOnBg()302 void VideoPattern::UpdateMediaPlayerOnBg()
303 {
304     PrepareMediaPlayer();
305     UpdateSpeed();
306     UpdateLooping();
307     UpdateMuted();
308     if (isInitialState_ && autoPlay_) {
309         // When video is autoPlay, start playing the video when it is initial state.
310         Start();
311     }
312 }
313 
PrepareMediaPlayer()314 void VideoPattern::PrepareMediaPlayer()
315 {
316     auto videoLayoutProperty = GetLayoutProperty<VideoLayoutProperty>();
317     CHECK_NULL_VOID(videoLayoutProperty);
318     // src has not set/changed
319     if (!videoLayoutProperty->HasVideoSource() || videoLayoutProperty->GetVideoSource().value() == src_) {
320         TAG_LOGI(AceLogTag::ACE_VIDEO, "Video source is null or the source has not changed.");
321         return;
322     }
323     src_ = videoLayoutProperty->GetVideoSource().value();
324     if (mediaPlayer_ && !mediaPlayer_->IsMediaPlayerValid()) {
325         mediaPlayer_->CreateMediaPlayer();
326     }
327 
328     if (mediaPlayer_ && !mediaPlayer_->IsMediaPlayerValid()) {
329         // It need post on ui thread.
330         FireError();
331         return;
332     }
333 
334     ResetStatus();
335     ContainerScope scope(instanceId_);
336     auto host = GetHost();
337     CHECK_NULL_VOID(host);
338     auto context = host->GetContext();
339     CHECK_NULL_VOID(context);
340     auto platformTask = SingleTaskExecutor::Make(context->GetTaskExecutor(), TaskExecutor::TaskType::BACKGROUND);
341     platformTask.PostTask([weak = WeakClaim(this)] {
342         auto video = weak.Upgrade();
343         CHECK_NULL_VOID(video);
344         auto targetPattern = video->GetTargetVideoPattern();
345         CHECK_NULL_VOID(targetPattern);
346         targetPattern->ResetMediaPlayer();
347     }, "ArkUIVideoMediaPlayerReset");
348 }
349 
SetSourceForMediaPlayer()350 bool VideoPattern::SetSourceForMediaPlayer()
351 {
352     TAG_LOGI(AceLogTag::ACE_VIDEO, "Video Set src for media, it is : %{private}s", src_.c_str());
353     CHECK_NULL_RETURN(mediaPlayer_, false);
354     return mediaPlayer_->SetSource(src_);
355 }
356 
RegisterMediaPlayerEvent()357 void VideoPattern::RegisterMediaPlayerEvent()
358 {
359     if (src_.empty() || !mediaPlayer_) {
360         TAG_LOGW(AceLogTag::ACE_VIDEO, "Video src is empty or mediaPlayer is null, register mediaPlayerEvent fail");
361         return;
362     }
363     ContainerScope scope(instanceId_);
364     auto context = PipelineContext::GetCurrentContext();
365     CHECK_NULL_VOID(context);
366 
367     auto uiTaskExecutor = SingleTaskExecutor::Make(context->GetTaskExecutor(), TaskExecutor::TaskType::UI);
368     auto videoPattern = WeakClaim(this);
369 
370     auto&& positionUpdatedEvent = [videoPattern, uiTaskExecutor](uint32_t currentPos) {
371         uiTaskExecutor.PostSyncTask([&videoPattern, currentPos] {
372             auto video = videoPattern.Upgrade();
373             CHECK_NULL_VOID(video);
374             ContainerScope scope(video->instanceId_);
375             video->OnCurrentTimeChange(currentPos);
376             video->StartUpdateImageAnalyzer();
377         }, "ArkUIVideoCurrentTimeChange");
378     };
379 
380     auto&& stateChangedEvent = [videoPattern, uiTaskExecutor](PlaybackStatus status) {
381         uiTaskExecutor.PostTask([videoPattern, status] {
382             auto video = videoPattern.Upgrade();
383             CHECK_NULL_VOID(video);
384             ContainerScope scope(video->instanceId_);
385             video->OnPlayerStatus(status);
386         }, "ArkUIVideoPlayerStatusChange");
387     };
388 
389     auto&& errorEvent = [videoPattern, uiTaskExecutor]() {
390         uiTaskExecutor.PostTask([videoPattern] {
391             auto video = videoPattern.Upgrade();
392             CHECK_NULL_VOID(video);
393             ContainerScope scope(video->instanceId_);
394             video->OnError("");
395         }, "ArkUIVideoError");
396     };
397 
398     auto&& resolutionChangeEvent = [videoPattern, uiTaskExecutor]() {
399         uiTaskExecutor.PostSyncTask([&videoPattern] {
400             auto video = videoPattern.Upgrade();
401             CHECK_NULL_VOID(video);
402             ContainerScope scope(video->instanceId_);
403             video->OnResolutionChange();
404         }, "ArkUIVideoResolutionChange");
405     };
406 
407     auto&& startRenderFrameEvent = [videoPattern, uiTaskExecutor]() {
408         uiTaskExecutor.PostSyncTask([&videoPattern] {
409             auto video = videoPattern.Upgrade();
410             CHECK_NULL_VOID(video);
411             ContainerScope scope(video->instanceId_);
412             video->OnStartRenderFrameCb();
413         }, "ArkUIVideoStartRenderFrame");
414     };
415 
416     mediaPlayer_->RegisterMediaPlayerEvent(
417         positionUpdatedEvent, stateChangedEvent, errorEvent, resolutionChangeEvent, startRenderFrameEvent);
418 
419     auto&& seekDoneEvent = [videoPattern, uiTaskExecutor](uint32_t currentPos) {
420         uiTaskExecutor.PostSyncTask(
421             [&videoPattern, currentPos] {
422                 auto video = videoPattern.Upgrade();
423                 CHECK_NULL_VOID(video);
424                 ContainerScope scope(video->instanceId_);
425                 video->SetIsSeeking(false);
426                 video->OnCurrentTimeChange(currentPos);
427             },
428             "ArkUIVideoSeekDone");
429     };
430     mediaPlayer_->RegisterMediaPlayerSeekDoneEvent(std::move(seekDoneEvent));
431 
432 #ifdef RENDER_EXTRACT_SUPPORTED
433     auto&& textureRefreshEvent = [videoPattern, uiTaskExecutor](int32_t instanceId, int64_t textureId) {
434         uiTaskExecutor.PostSyncTask([&videoPattern, instanceId, textureId] {
435             auto video = videoPattern.Upgrade();
436             CHECK_NULL_VOID(video);
437             void* nativeWindow = video->GetNativeWindow(instanceId, textureId);
438             if (!nativeWindow) {
439                 LOGE("the native window is nullptr.");
440                 return;
441             }
442             video->OnTextureRefresh(nativeWindow);
443         }, "ArkUIVideoTextureRefresh");
444     };
445     mediaPlayer_->RegisterTextureEvent(textureRefreshEvent);
446 #endif
447 }
448 
449 #ifdef RENDER_EXTRACT_SUPPORTED
GetNativeWindow(int32_t instanceId,int64_t textureId)450 void* VideoPattern::GetNativeWindow(int32_t instanceId, int64_t textureId)
451 {
452     auto container = AceEngine::Get().GetContainer(instanceId);
453     CHECK_NULL_RETURN(container, nullptr);
454     auto nativeView = container->GetAceView();
455     CHECK_NULL_RETURN(nativeView, nullptr);
456     return const_cast<void*>(nativeView->GetNativeWindowById(textureId));
457 }
458 
OnTextureRefresh(void * surface)459 void VideoPattern::OnTextureRefresh(void* surface)
460 {
461     CHECK_NULL_VOID(surface);
462     auto renderContextForMediaPlayer = renderContextForMediaPlayerWeakPtr_.Upgrade();
463     CHECK_NULL_VOID(renderContextForMediaPlayer);
464     renderContextForMediaPlayer->MarkNewFrameAvailable(surface);
465 }
466 #endif
467 
PrintPlayerStatus(PlaybackStatus status)468 void VideoPattern::PrintPlayerStatus(PlaybackStatus status)
469 {
470     switch (status) {
471         case PlaybackStatus::ERROR:
472             TAG_LOGI(AceLogTag::ACE_VIDEO, "Player current status is ERROR.");
473             break;
474         case PlaybackStatus::IDLE:
475             TAG_LOGI(AceLogTag::ACE_VIDEO, "Player current status is IDLE.");
476             break;
477         case PlaybackStatus::PREPARED:
478             TAG_LOGI(AceLogTag::ACE_VIDEO, "Player current status is PREPARED.");
479             break;
480         case PlaybackStatus::STARTED:
481             TAG_LOGI(AceLogTag::ACE_VIDEO, "Player current status is STARTED.");
482             break;
483         case PlaybackStatus::PAUSED:
484             TAG_LOGI(AceLogTag::ACE_VIDEO, "Player current status is PAUSED.");
485             break;
486         case PlaybackStatus::STOPPED:
487             TAG_LOGI(AceLogTag::ACE_VIDEO, "Player current status is STOPPED.");
488             break;
489         case PlaybackStatus::PLAYBACK_COMPLETE:
490             TAG_LOGI(AceLogTag::ACE_VIDEO, "Player current status is PLAYBACK_COMPLETE.");
491             break;
492         case PlaybackStatus::NONE:
493             TAG_LOGI(AceLogTag::ACE_VIDEO, "Player current status is NONE.");
494             break;
495         default:
496             TAG_LOGW(AceLogTag::ACE_VIDEO, "Invalid player status.");
497             break;
498     }
499 }
500 
OnCurrentTimeChange(uint32_t currentPos)501 void VideoPattern::OnCurrentTimeChange(uint32_t currentPos)
502 {
503     isInitialState_ = isInitialState_ ? currentPos == 0 : false;
504     if (currentPos == currentPos_ || isStop_) {
505         return;
506     }
507 
508     if (duration_ == 0) {
509         int32_t duration = 0;
510         if (mediaPlayer_ && mediaPlayer_->GetDuration(duration) == 0) {
511             duration_ = static_cast<uint32_t>(duration / MILLISECONDS_TO_SECONDS);
512             OnUpdateTime(duration_, DURATION_POS);
513         }
514     }
515 
516     OnUpdateTime(currentPos, CURRENT_POS);
517     currentPos_ = currentPos;
518     auto eventHub = GetEventHub<VideoEventHub>();
519     CHECK_NULL_VOID(eventHub);
520     auto json = JsonUtil::Create(true);
521     json->Put("time", static_cast<double>(currentPos));
522     auto param = json->ToString();
523     eventHub->FireUpdateEvent(param);
524 }
525 
ChangePlayerStatus(bool isPlaying,const PlaybackStatus & status)526 void VideoPattern::ChangePlayerStatus(bool isPlaying, const PlaybackStatus& status)
527 {
528     if (isPlaying) {
529         auto json = JsonUtil::Create(true);
530         json->Put("start", "");
531         auto param = json->ToString();
532         auto eventHub = GetEventHub<VideoEventHub>();
533         CHECK_NULL_VOID(eventHub);
534         eventHub->FireStartEvent(param);
535     }
536 
537     if (status == PlaybackStatus::PAUSED) {
538         auto json = JsonUtil::Create(true);
539         json->Put("pause", "");
540         auto param = json->ToString();
541         auto eventHub = GetEventHub<VideoEventHub>();
542         CHECK_NULL_VOID(eventHub);
543         eventHub->FirePauseEvent(param);
544     }
545 
546     if (status == PlaybackStatus::STOPPED) {
547         auto json = JsonUtil::Create(true);
548         json->Put("stop", "");
549         auto param = json->ToString();
550         auto eventHub = GetEventHub<VideoEventHub>();
551         CHECK_NULL_VOID(eventHub);
552         eventHub->FireStopEvent(param);
553     }
554 
555     if (status == PlaybackStatus::PREPARED) {
556         ContainerScope scope(instanceId_);
557         auto host = GetHost();
558         CHECK_NULL_VOID(host);
559         auto context = host->GetContext();
560         CHECK_NULL_VOID(context);
561         if (!mediaPlayer_ || !mediaPlayer_->IsMediaPlayerValid()) {
562             return;
563         }
564         auto uiTaskExecutor = SingleTaskExecutor::Make(context->GetTaskExecutor(), TaskExecutor::TaskType::UI);
565         int32_t milliSecondDuration = 0;
566         mediaPlayer_->GetDuration(milliSecondDuration);
567         OnPrepared(milliSecondDuration / MILLISECONDS_TO_SECONDS, 0, true);
568         return;
569     }
570 
571     if (status == PlaybackStatus::PLAYBACK_COMPLETE) {
572         OnCompletion();
573     }
574 }
575 
OnPlayerStatus(PlaybackStatus status)576 void VideoPattern::OnPlayerStatus(PlaybackStatus status)
577 {
578     PrintPlayerStatus(status);
579     bool isPlaying = (status == PlaybackStatus::STARTED);
580     if (isPlaying_ != isPlaying) {
581         isPlaying_ = isPlaying;
582         ChangePlayButtonTag();
583     }
584 
585     if (isInitialState_) {
586         isInitialState_ = !isPlaying;
587     }
588 
589     ChangePlayerStatus(isPlaying, status);
590 }
591 
OnError(const std::string & errorId)592 void VideoPattern::OnError(const std::string& errorId)
593 {
594     std::string errorcode = Localization::GetInstance()->GetErrorDescription(errorId);
595     auto json = JsonUtil::Create(true);
596     json->Put("error", "");
597     auto param = json->ToString();
598     auto eventHub = GetEventHub<VideoEventHub>();
599     CHECK_NULL_VOID(eventHub);
600     eventHub->FireErrorEvent(param);
601 }
602 
OnResolutionChange() const603 void VideoPattern::OnResolutionChange() const
604 {
605     if (!mediaPlayer_ || !mediaPlayer_->IsMediaPlayerValid()) {
606         return;
607     }
608     auto host = GetHost();
609     CHECK_NULL_VOID(host);
610     auto videoLayoutProperty = host->GetLayoutProperty<VideoLayoutProperty>();
611     CHECK_NULL_VOID(videoLayoutProperty);
612     auto preVideoSize = videoLayoutProperty->GetVideoSize();
613     if (!preVideoSize.has_value()) {
614         SizeF videoSize = SizeF(
615             static_cast<float>(mediaPlayer_->GetVideoWidth()),
616             static_cast<float>(mediaPlayer_->GetVideoHeight()));
617         videoLayoutProperty->UpdateVideoSize(videoSize);
618         host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
619     }
620 }
621 
OnStartRenderFrameCb() const622 void VideoPattern::OnStartRenderFrameCb() const
623 {
624     auto host = GetHost();
625     CHECK_NULL_VOID(host);
626     auto video = AceType::DynamicCast<VideoNode>(host);
627     CHECK_NULL_VOID(video);
628     auto image = AceType::DynamicCast<FrameNode>(video->GetPreviewImage());
629     CHECK_NULL_VOID(image);
630     auto posterLayoutProperty = image->GetLayoutProperty<ImageLayoutProperty>();
631     posterLayoutProperty->UpdateVisibility(VisibleType::INVISIBLE);
632     image->MarkModifyDone();
633     if (!mediaPlayer_ || !mediaPlayer_->IsMediaPlayerValid()) {
634         return;
635     }
636     auto videoLayoutProperty = host->GetLayoutProperty<VideoLayoutProperty>();
637     CHECK_NULL_VOID(videoLayoutProperty);
638     SizeF videoSize =
639         SizeF(static_cast<float>(mediaPlayer_->GetVideoWidth()), static_cast<float>(mediaPlayer_->GetVideoHeight()));
640     TAG_LOGI(AceLogTag::ACE_VIDEO, "start render frame size:%{public}s", videoSize.ToString().c_str());
641     videoLayoutProperty->UpdateVideoSize(videoSize);
642     host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
643 }
644 
OnPrepared(uint32_t duration,uint32_t currentPos,bool needFireEvent)645 void VideoPattern::OnPrepared(uint32_t duration, uint32_t currentPos, bool needFireEvent)
646 {
647     auto host = GetHost();
648     CHECK_NULL_VOID(host);
649     CHECK_NULL_VOID(mediaPlayer_);
650 
651     duration_ = duration;
652     currentPos_ = currentPos;
653     isInitialState_ = currentPos != 0 ? false : isInitialState_;
654     isPlaying_ = mediaPlayer_->IsPlaying();
655     OnUpdateTime(duration_, DURATION_POS);
656     OnUpdateTime(currentPos_, CURRENT_POS);
657 
658     RefPtr<UINode> controlBar = nullptr;
659     auto children = host->GetChildren();
660     for (const auto& child : children) {
661         if (child->GetTag() == V2::ROW_ETS_TAG) {
662             controlBar = child;
663             break;
664         }
665     }
666     CHECK_NULL_VOID(controlBar);
667     auto sliderNode = DynamicCast<FrameNode>(controlBar->GetChildAtIndex(SLIDER_POS));
668     auto sliderPaintProperty = sliderNode->GetPaintProperty<SliderPaintProperty>();
669     CHECK_NULL_VOID(sliderPaintProperty);
670     sliderPaintProperty->UpdateMin(0.0f);
671     sliderPaintProperty->UpdateMax(static_cast<float>(duration_));
672     sliderNode->MarkModifyDone();
673     auto playBtn = DynamicCast<FrameNode>(controlBar->GetChildAtIndex(0));
674     ChangePlayButtonTag(playBtn);
675 
676     if (needFireEvent) {
677         auto json = JsonUtil::Create(true);
678         json->Put("duration", static_cast<double>(duration_));
679         auto param = json->ToString();
680         auto eventHub = GetEventHub<VideoEventHub>();
681         CHECK_NULL_VOID(eventHub);
682         eventHub->FirePreparedEvent(param);
683     }
684     UpdateLooping();
685     UpdateSpeed();
686     UpdateMuted();
687 
688     checkNeedAutoPlay();
689 }
690 
checkNeedAutoPlay()691 void VideoPattern::checkNeedAutoPlay()
692 {
693     if (isStop_) {
694         isStop_ = false;
695     }
696     if (dragEndAutoPlay_) {
697         dragEndAutoPlay_ = false;
698         Start();
699     }
700     if (autoPlay_) {
701         Start();
702     }
703 }
704 
OnCompletion()705 void VideoPattern::OnCompletion()
706 {
707     isPlaying_ = false;
708     currentPos_ = duration_;
709     OnUpdateTime(currentPos_, CURRENT_POS);
710     auto json = JsonUtil::Create(true);
711     json->Put("finish", "");
712     auto param = json->ToString();
713     auto eventHub = GetEventHub<VideoEventHub>();
714     CHECK_NULL_VOID(eventHub);
715     eventHub->FireFinishEvent(param);
716 }
717 
HasPlayer() const718 bool VideoPattern::HasPlayer() const
719 {
720     return mediaPlayer_ != nullptr;
721 }
722 
HiddenChange(bool hidden)723 void VideoPattern::HiddenChange(bool hidden)
724 {
725     if (isPlaying_ && hidden && HasPlayer()) {
726         pastPlayingStatus_ = isPlaying_;
727         Pause();
728         return;
729     }
730 
731     if (!hidden && pastPlayingStatus_) {
732         pastPlayingStatus_ = false;
733         Start();
734     }
735 }
736 
OnVisibleChange(bool isVisible)737 void VideoPattern::OnVisibleChange(bool isVisible)
738 {
739     if (hiddenChangeEvent_) {
740         hiddenChangeEvent_(!isVisible);
741     }
742 }
743 
UpdateLooping()744 void VideoPattern::UpdateLooping()
745 {
746     if (mediaPlayer_ && mediaPlayer_->IsMediaPlayerValid()) {
747         ContainerScope scope(instanceId_);
748         auto host = GetHost();
749         CHECK_NULL_VOID(host);
750         auto context = host->GetContext();
751         CHECK_NULL_VOID(context);
752         auto platformTask = SingleTaskExecutor::Make(context->GetTaskExecutor(), TaskExecutor::TaskType::BACKGROUND);
753         platformTask.PostTask([weak = WeakClaim(RawPtr(mediaPlayer_)), loop = loop_] {
754             auto mediaPlayer = weak.Upgrade();
755             CHECK_NULL_VOID(mediaPlayer);
756             mediaPlayer->SetLooping(loop);
757         }, "ArkUIVideoUpdateLooping");
758     }
759 }
760 
UpdateSpeed()761 void VideoPattern::UpdateSpeed()
762 {
763     if (mediaPlayer_ && mediaPlayer_->IsMediaPlayerValid()) {
764         ContainerScope scope(instanceId_);
765         auto host = GetHost();
766         CHECK_NULL_VOID(host);
767         auto context = host->GetContext();
768         CHECK_NULL_VOID(context);
769         auto platformTask = SingleTaskExecutor::Make(context->GetTaskExecutor(), TaskExecutor::TaskType::BACKGROUND);
770         platformTask.PostTask([weak = WeakClaim(RawPtr(mediaPlayer_)), progress = progressRate_] {
771             auto mediaPlayer = weak.Upgrade();
772             CHECK_NULL_VOID(mediaPlayer);
773             mediaPlayer->SetPlaybackSpeed(static_cast<float>(progress));
774         }, "ArkUIVideoUpdateSpeed");
775     }
776 }
777 
UpdateMuted()778 void VideoPattern::UpdateMuted()
779 {
780     if (mediaPlayer_ && mediaPlayer_->IsMediaPlayerValid()) {
781         ContainerScope scope(instanceId_);
782         float volume = muted_ ? 0.0f : 1.0f;
783         auto host = GetHost();
784         CHECK_NULL_VOID(host);
785         auto context = host->GetContext();
786         CHECK_NULL_VOID(context);
787         auto platformTask = SingleTaskExecutor::Make(context->GetTaskExecutor(), TaskExecutor::TaskType::BACKGROUND);
788         platformTask.PostTask([weak = WeakClaim(RawPtr(mediaPlayer_)), videoVolume = volume] {
789             auto mediaPlayer = weak.Upgrade();
790             CHECK_NULL_VOID(mediaPlayer);
791             if (NearZero(videoVolume)) {
792                 mediaPlayer->SetMediaMuted(MEDIA_TYPE_AUD, true);
793             } else {
794                 mediaPlayer->SetMediaMuted(MEDIA_TYPE_AUD, false);
795                 mediaPlayer->SetVolume(videoVolume, videoVolume);
796             }
797         }, "ArkUIVideoUpdateMuted");
798     }
799 }
800 
OnUpdateTime(uint32_t time,int pos) const801 void VideoPattern::OnUpdateTime(uint32_t time, int pos) const
802 {
803     auto host = GetHost();
804     CHECK_NULL_VOID(host);
805     auto layoutProperty = host->GetLayoutProperty<VideoLayoutProperty>();
806     CHECK_NULL_VOID(layoutProperty);
807     bool needControlBar = layoutProperty->GetControlsValue(true);
808     if (!needControlBar) {
809         return;
810     }
811 
812     RefPtr<UINode> controlBar = nullptr;
813     auto children = host->GetChildren();
814     for (const auto& child : children) {
815         if (child->GetTag() == V2::ROW_ETS_TAG) {
816             controlBar = child;
817             break;
818         }
819     }
820 
821     CHECK_NULL_VOID(controlBar);
822     auto durationNode = DynamicCast<FrameNode>(controlBar->GetChildAtIndex(pos));
823     CHECK_NULL_VOID(durationNode);
824     auto textLayoutProperty = durationNode->GetLayoutProperty<TextLayoutProperty>();
825     CHECK_NULL_VOID(textLayoutProperty);
826     std::string timeText = IntTimeToText(time);
827     textLayoutProperty->UpdateContent(timeText);
828     durationNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
829     durationNode->MarkModifyDone();
830     // if current status is seeking, no need to update slider's value
831     if (pos == CURRENT_POS && !isSeeking_) {
832         auto sliderNode = DynamicCast<FrameNode>(controlBar->GetChildAtIndex(SLIDER_POS));
833         CHECK_NULL_VOID(sliderNode);
834         auto sliderPattern = sliderNode->GetPattern<SliderPattern>();
835         CHECK_NULL_VOID(sliderPattern);
836         sliderPattern->UpdateValue(static_cast<float>(time));
837         sliderNode->MarkModifyDone();
838     }
839 }
840 
PrepareSurface()841 void VideoPattern::PrepareSurface()
842 {
843     if (!mediaPlayer_ || renderSurface_->IsSurfaceValid()) {
844         return;
845     }
846     if (!SystemProperties::GetExtSurfaceEnabled()) {
847         renderSurface_->SetRenderContext(renderContextForMediaPlayer_);
848     }
849     renderSurface_->InitSurface();
850     mediaPlayer_->SetRenderSurface(renderSurface_);
851     if (mediaPlayer_->SetSurface() != 0) {
852         TAG_LOGW(AceLogTag::ACE_VIDEO, "mediaPlayer renderSurface set failed");
853     }
854 }
855 
OnAttachToFrameNode()856 void VideoPattern::OnAttachToFrameNode()
857 {
858     // full screen node is not supposed to register js controller event
859     if (!InstanceOf<VideoFullScreenPattern>(this)) {
860         SetMethodCall();
861     }
862     auto host = GetHost();
863     CHECK_NULL_VOID(host);
864     auto pipeline = host->GetContext();
865     CHECK_NULL_VOID(pipeline);
866     pipeline->AddWindowStateChangedCallback(host->GetId());
867     auto renderContext = host->GetRenderContext();
868     CHECK_NULL_VOID(renderContext);
869 
870 #ifdef RENDER_EXTRACT_SUPPORTED
871     CHECK_NULL_VOID(renderSurface_);
872     auto contextType = renderSurface_->IsTexture() ?
873         RenderContext::ContextType::HARDWARE_TEXTURE : RenderContext::ContextType::HARDWARE_SURFACE;
874     static RenderContext::ContextParam param = { contextType, "MediaPlayerSurface",
875                                                  RenderContext::PatternType::VIDEO };
876 #else
877     static RenderContext::ContextParam param = { RenderContext::ContextType::HARDWARE_SURFACE, "MediaPlayerSurface",
878                                                  RenderContext::PatternType::VIDEO };
879 #endif
880     renderContextForMediaPlayer_->InitContext(false, param);
881     renderContext->UpdateBackgroundColor(Color::BLACK);
882     renderContextForMediaPlayer_->UpdateBackgroundColor(Color::BLACK);
883     renderContext->SetClipToBounds(true);
884 }
885 
OnDetachFromFrameNode(FrameNode * frameNode)886 void VideoPattern::OnDetachFromFrameNode(FrameNode* frameNode)
887 {
888     CHECK_NULL_VOID(frameNode);
889     auto id = frameNode->GetId();
890     auto pipeline = frameNode->GetContext();
891     CHECK_NULL_VOID(pipeline);
892     pipeline->RemoveWindowStateChangedCallback(id);
893 }
894 
OnDetachFromMainTree()895 void VideoPattern::OnDetachFromMainTree()
896 {
897     auto host = GetHost();
898     if (host && host->GetNodeStatus() == NodeStatus::BUILDER_NODE_OFF_MAINTREE) {
899         Pause();
900     }
901 }
902 
OnModifyDone()903 void VideoPattern::OnModifyDone()
904 {
905     Pattern::OnModifyDone();
906 
907     if (!hiddenChangeEvent_) {
908         SetHiddenChangeEvent(CreateHiddenChangeEvent());
909     }
910 
911     // src has changed
912     auto layoutProperty = GetLayoutProperty<VideoLayoutProperty>();
913     if (Container::GreatOrEqualAPITargetVersion(PlatformVersion::VERSION_TWELVE) &&
914         (layoutProperty && layoutProperty->HasVideoSource() && layoutProperty->GetVideoSource().value() != src_)) {
915         ResetStatus();
916     }
917 
918     // update full screen pattern state
919     UpdateFsState();
920 
921     // Update the control bar and preview image.
922     UpdatePreviewImage();
923     UpdateControllerBar();
924     auto host = GetHost();
925     CHECK_NULL_VOID(host);
926     // Update the media player when video node is not in full screen or current node is full screen node
927     if (!fullScreenNodeId_.has_value() || InstanceOf<VideoFullScreenNode>(this)) {
928         ContainerScope scope(instanceId_);
929         auto pipelineContext = host->GetContext();
930         CHECK_NULL_VOID(pipelineContext);
931         auto uiTaskExecutor = SingleTaskExecutor::Make(pipelineContext->GetTaskExecutor(), TaskExecutor::TaskType::UI);
932         uiTaskExecutor.PostTask([weak = WeakClaim(this)]() {
933             auto videoPattern = weak.Upgrade();
934             CHECK_NULL_VOID(videoPattern);
935             ContainerScope scope(videoPattern->instanceId_);
936             videoPattern->UpdateMediaPlayerOnBg();
937         }, "ArkUIVideoUpdateMediaPlayer");
938     }
939 
940     if (SystemProperties::GetExtSurfaceEnabled()) {
941         auto pipelineContext = host->GetContext();
942         CHECK_NULL_VOID(pipelineContext);
943         pipelineContext->AddOnAreaChangeNode(host->GetId());
944     }
945     EnableDrag();
946     auto eventHub = GetEventHub<VideoEventHub>();
947     if (!AceType::InstanceOf<VideoFullScreenPattern>(this)) {
948         auto host = GetHost();
949         CHECK_NULL_VOID(host);
950         eventHub->SetInspectorId(host->GetInspectorIdValue(""));
951     }
952     if (!IsSupportImageAnalyzer()) {
953         DestroyAnalyzerOverlay();
954     } else if (isPaused_ && !isPlaying_ && !GetAnalyzerState()) {
955         StartImageAnalyzer();
956     }
957 }
958 
CreateHiddenChangeEvent()959 HiddenChangeEvent VideoPattern::CreateHiddenChangeEvent()
960 {
961     return [weak = WeakClaim(this)](bool hidden) {
962         auto videoPattern = weak.Upgrade();
963         CHECK_NULL_VOID(videoPattern);
964         auto fullScreenNode = videoPattern->GetFullScreenNode();
965         if (fullScreenNode) {
966             auto fullScreenPattern = AceType::DynamicCast<VideoFullScreenPattern>(fullScreenNode->GetPattern());
967             CHECK_NULL_VOID(fullScreenPattern);
968             fullScreenPattern->HiddenChange(hidden);
969             return;
970         }
971         videoPattern->HiddenChange(hidden);
972     };
973 }
974 
UpdatePreviewImage()975 void VideoPattern::UpdatePreviewImage()
976 {
977     auto layoutProperty = GetLayoutProperty<VideoLayoutProperty>();
978     CHECK_NULL_VOID(layoutProperty);
979     if (!layoutProperty->HasPosterImageInfo()) {
980         return;
981     }
982     auto posterSourceInfo = layoutProperty->GetPosterImageInfo().value();
983     auto imageFit = layoutProperty->GetObjectFitValue(ImageFit::COVER);
984     auto host = GetHost();
985     CHECK_NULL_VOID(host);
986 
987     auto video = AceType::DynamicCast<VideoNode>(host);
988     CHECK_NULL_VOID(video);
989     auto image = AceType::DynamicCast<FrameNode>(video->GetPreviewImage());
990     CHECK_NULL_VOID(image);
991     if (!isInitialState_) {
992         auto posterLayoutProperty = image->GetLayoutProperty<ImageLayoutProperty>();
993         posterLayoutProperty->UpdateVisibility(VisibleType::INVISIBLE);
994         image->MarkModifyDone();
995         return;
996     }
997 
998     if (!posterSourceInfo.IsValid()) {
999         auto posterLayoutProperty = image->GetLayoutProperty<ImageLayoutProperty>();
1000         posterLayoutProperty->UpdateVisibility(VisibleType::INVISIBLE);
1001         image->MarkModifyDone();
1002         TAG_LOGI(AceLogTag::ACE_VIDEO, "Src image is not valid.");
1003         return;
1004     }
1005 
1006     if (image) {
1007         image->SetDraggable(false);
1008         auto posterLayoutProperty = image->GetLayoutProperty<ImageLayoutProperty>();
1009         posterLayoutProperty->UpdateVisibility(VisibleType::VISIBLE);
1010         posterLayoutProperty->UpdateImageSourceInfo(posterSourceInfo);
1011         posterLayoutProperty->UpdateImageFit(imageFit);
1012         image->MarkModifyDone();
1013     }
1014 }
1015 
UpdateControllerBar()1016 void VideoPattern::UpdateControllerBar()
1017 {
1018     auto layoutProperty = GetLayoutProperty<VideoLayoutProperty>();
1019     CHECK_NULL_VOID(layoutProperty);
1020     auto host = GetHost();
1021     CHECK_NULL_VOID(host);
1022     auto children = host->GetChildren();
1023     if (layoutProperty->GetControlsValue(true)) {
1024         auto video = AceType::DynamicCast<VideoNode>(host);
1025         CHECK_NULL_VOID(video);
1026         auto controller = AceType::DynamicCast<FrameNode>(video->GetControllerRow());
1027         if (controller) {
1028             auto sliderNode = DynamicCast<FrameNode>(controller->GetChildAtIndex(SLIDER_POS));
1029             CHECK_NULL_VOID(sliderNode);
1030             auto sliderPattern = sliderNode->GetPattern<SliderPattern>();
1031             CHECK_NULL_VOID(sliderPattern);
1032             sliderPattern->UpdateValue(static_cast<float>(currentPos_));
1033             sliderNode->MarkModifyDone();
1034 
1035             auto textNode = DynamicCast<FrameNode>(controller->GetChildAtIndex(CURRENT_POS));
1036             CHECK_NULL_VOID(textNode);
1037             auto textLayoutProperty = textNode->GetLayoutProperty<TextLayoutProperty>();
1038             CHECK_NULL_VOID(textLayoutProperty);
1039             std::string label = IntTimeToText(currentPos_);
1040             textLayoutProperty->UpdateContent(label);
1041 
1042             auto durationNode = DynamicCast<FrameNode>(controller->GetChildAtIndex(DURATION_POS));
1043             CHECK_NULL_VOID(durationNode);
1044             auto durationTextLayoutProperty = durationNode->GetLayoutProperty<TextLayoutProperty>();
1045             CHECK_NULL_VOID(durationTextLayoutProperty);
1046             std::string durationText = IntTimeToText(duration_);
1047             durationTextLayoutProperty->UpdateContent(durationText);
1048 
1049             textNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
1050             textNode->MarkModifyDone();
1051             durationNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
1052             durationNode->MarkModifyDone();
1053             auto controllerLayoutProperty = controller->GetLayoutProperty<LinearLayoutProperty>();
1054             controllerLayoutProperty->UpdateVisibility(VisibleType::VISIBLE);
1055             controller->MarkModifyDone();
1056         }
1057     } else {
1058         auto video = AceType::DynamicCast<VideoNode>(host);
1059         CHECK_NULL_VOID(video);
1060         auto controller = AceType::DynamicCast<FrameNode>(video->GetControllerRow());
1061         CHECK_NULL_VOID(controller);
1062         if (controller) {
1063             auto controllerLayoutProperty = controller->GetLayoutProperty<LinearLayoutProperty>();
1064             controllerLayoutProperty->UpdateVisibility(VisibleType::INVISIBLE);
1065             controller->MarkModifyDone();
1066         }
1067     }
1068 }
1069 
UpdateVideoProperty()1070 void VideoPattern::UpdateVideoProperty()
1071 {
1072     if (isInitialState_ && autoPlay_) {
1073         Start();
1074     }
1075 
1076     UpdateSpeed();
1077     UpdateLooping();
1078     UpdateMuted();
1079 }
1080 
OnRebuildFrame()1081 void VideoPattern::OnRebuildFrame()
1082 {
1083     if (!renderSurface_ || !renderSurface_->IsSurfaceValid()) {
1084         TAG_LOGW(AceLogTag::ACE_VIDEO, "MediaPlayer surface is not valid");
1085         return;
1086     }
1087     auto host = GetHost();
1088     CHECK_NULL_VOID(host);
1089     auto video = AceType::DynamicCast<VideoNode>(host);
1090     CHECK_NULL_VOID(video);
1091     auto column = AceType::DynamicCast<FrameNode>(video->GetMediaColumn());
1092     CHECK_NULL_VOID(column);
1093     auto renderContext = column->GetRenderContext();
1094     CHECK_NULL_VOID(renderContext);
1095     renderContext->AddChild(renderContextForMediaPlayer_, 0);
1096 }
1097 
RemoveMediaPlayerSurfaceNode()1098 void VideoPattern::RemoveMediaPlayerSurfaceNode()
1099 {
1100     auto host = GetHost();
1101     CHECK_NULL_VOID(host);
1102     auto video = AceType::DynamicCast<VideoNode>(host);
1103     CHECK_NULL_VOID(video);
1104     auto column = AceType::DynamicCast<FrameNode>(video->GetMediaColumn());
1105     CHECK_NULL_VOID(column);
1106     auto renderContext = column->GetRenderContext();
1107     CHECK_NULL_VOID(renderContext);
1108     renderContext->RemoveChild(renderContextForMediaPlayer_);
1109 }
1110 
OnDirtyLayoutWrapperSwap(const RefPtr<LayoutWrapper> & dirty,const DirtySwapConfig & config)1111 bool VideoPattern::OnDirtyLayoutWrapperSwap(const RefPtr<LayoutWrapper>& dirty, const DirtySwapConfig& config)
1112 {
1113     if (config.skipMeasure || dirty->SkipMeasureContent()) {
1114         return false;
1115     }
1116     auto geometryNode = dirty->GetGeometryNode();
1117     CHECK_NULL_RETURN(geometryNode, false);
1118     auto videoNodeSize = geometryNode->GetContentSize();
1119     auto layoutProperty = GetLayoutProperty<VideoLayoutProperty>();
1120     CHECK_NULL_RETURN(layoutProperty, false);
1121     auto videoFrameSize = MeasureVideoContentLayout(videoNodeSize, layoutProperty);
1122     // Change the surface layout for drawing video frames
1123     if (renderContextForMediaPlayer_) {
1124         if (Container::GreatOrEqualAPITargetVersion(PlatformVersion::VERSION_TWELVE)) {
1125             auto rect = AdjustPaintRect((videoNodeSize.Width() - videoFrameSize.Width()) / AVERAGE_VALUE,
1126                 (videoNodeSize.Height() - videoFrameSize.Height()) / AVERAGE_VALUE, videoFrameSize.Width(),
1127                 videoFrameSize.Height(), true);
1128             renderContextForMediaPlayer_->SetBounds(rect.GetX(), rect.GetY(), rect.Width(), rect.Height());
1129         } else {
1130             renderContextForMediaPlayer_->SetBounds((videoNodeSize.Width() - videoFrameSize.Width()) / AVERAGE_VALUE,
1131                 (videoNodeSize.Height() - videoFrameSize.Height()) / AVERAGE_VALUE, videoFrameSize.Width(),
1132                 videoFrameSize.Height());
1133         }
1134     }
1135 
1136     if (IsSupportImageAnalyzer()) {
1137         Rect tmpRect;
1138         auto padding  = layoutProperty->CreatePaddingAndBorder();
1139         auto imageFit = layoutProperty->GetObjectFitValue(ImageFit::COVER);
1140         if (imageFit == ImageFit::COVER || imageFit == ImageFit::NONE) {
1141             tmpRect = Rect(padding.left.value_or(0), padding.top.value_or(0),
1142                            videoNodeSize.Width(), videoNodeSize.Height());
1143         } else {
1144             tmpRect = Rect((videoNodeSize.Width() - videoFrameSize.Width()) / AVERAGE_VALUE + padding.left.value_or(0),
1145                 (videoNodeSize.Height() - videoFrameSize.Height()) / AVERAGE_VALUE + padding.top.value_or(0),
1146                 videoFrameSize.Width(), videoFrameSize.Height());
1147         }
1148         if (contentRect_ != tmpRect && ShouldUpdateImageAnalyzer()) {
1149             StartUpdateImageAnalyzer();
1150         }
1151         contentRect_ = tmpRect;
1152         UpdateAnalyzerUIConfig(geometryNode);
1153     }
1154 
1155     auto host = GetHost();
1156     CHECK_NULL_RETURN(host, false);
1157     host->MarkNeedSyncRenderTree();
1158     auto video = AceType::DynamicCast<VideoNode>(host);
1159     CHECK_NULL_RETURN(video, false);
1160     auto column = AceType::DynamicCast<FrameNode>(video->GetMediaColumn());
1161     CHECK_NULL_RETURN(column, false);
1162     column->GetRenderContext()->SetClipToBounds(true);
1163     return false;
1164 }
1165 
OnAreaChangedInner()1166 void VideoPattern::OnAreaChangedInner()
1167 {
1168     if (SystemProperties::GetExtSurfaceEnabled()) {
1169         auto host = GetHost();
1170         CHECK_NULL_VOID(host);
1171         auto geometryNode = host->GetGeometryNode();
1172         CHECK_NULL_VOID(geometryNode);
1173         auto videoNodeSize = geometryNode->GetContentSize();
1174         auto layoutProperty = GetLayoutProperty<VideoLayoutProperty>();
1175         CHECK_NULL_VOID(layoutProperty);
1176         auto videoFrameSize = MeasureVideoContentLayout(videoNodeSize, layoutProperty);
1177         auto transformRelativeOffset = host->GetTransformRelativeOffset();
1178 
1179         Rect rect =
1180             Rect(transformRelativeOffset.GetX() + (videoNodeSize.Width() - videoFrameSize.Width()) / AVERAGE_VALUE,
1181                 transformRelativeOffset.GetY() + (videoNodeSize.Height() - videoFrameSize.Height()) / AVERAGE_VALUE,
1182                 videoFrameSize.Width(), videoFrameSize.Height());
1183         if (renderSurface_ && (rect != lastBoundsRect_)) {
1184             renderSurface_->SetExtSurfaceBounds(rect.Left(), rect.Top(), rect.Width(), rect.Height());
1185             lastBoundsRect_ = rect;
1186         }
1187     }
1188 }
1189 
OnColorConfigurationUpdate()1190 void VideoPattern::OnColorConfigurationUpdate()
1191 {
1192     ContainerScope scope(instanceId_);
1193     auto host = GetHost();
1194     CHECK_NULL_VOID(host);
1195     auto pipelineContext = PipelineBase::GetCurrentContext();
1196     CHECK_NULL_VOID(pipelineContext);
1197     auto videoTheme = pipelineContext->GetTheme<VideoTheme>();
1198     CHECK_NULL_VOID(videoTheme);
1199     auto renderContext = controlBar_->GetRenderContext();
1200     CHECK_NULL_VOID(renderContext);
1201     renderContext->UpdateBackgroundColor(videoTheme->GetBkgColor());
1202     for (const auto& child : controlBar_->GetChildren()) {
1203         if (child->GetTag() == V2::TEXT_ETS_TAG) {
1204             auto frameNode = AceType::DynamicCast<FrameNode>(child);
1205             if (frameNode) {
1206                 auto textLayoutProperty = frameNode->GetLayoutProperty<TextLayoutProperty>();
1207                 if (textLayoutProperty) {
1208                     auto textStyle = videoTheme->GetTimeTextStyle();
1209                     textLayoutProperty->UpdateTextColor(textStyle.GetTextColor());
1210                 }
1211             }
1212         }
1213     }
1214     host->SetNeedCallChildrenUpdate(false);
1215     host->MarkModifyDone();
1216     host->MarkDirtyNode();
1217 }
1218 
NeedLift() const1219 bool VideoPattern::NeedLift() const
1220 {
1221     auto host = GetHost();
1222     CHECK_NULL_RETURN(host, false);
1223     auto renderContext = host->GetRenderContext();
1224     CHECK_NULL_RETURN(renderContext, false);
1225     return IsFullScreen() && renderContext->IsUniRenderEnabled();
1226 }
1227 
CreateControlBar(int32_t nodeId)1228 RefPtr<FrameNode> VideoPattern::CreateControlBar(int32_t nodeId)
1229 {
1230     ContainerScope scope(instanceId_);
1231     auto pipelineContext = PipelineBase::GetCurrentContext();
1232     CHECK_NULL_RETURN(pipelineContext, nullptr);
1233     auto videoTheme = pipelineContext->GetTheme<VideoTheme>();
1234     CHECK_NULL_RETURN(videoTheme, nullptr);
1235     auto controlBar = FrameNode::GetOrCreateFrameNode(
1236         V2::ROW_ETS_TAG, nodeId, []() { return AceType::MakeRefPtr<LinearLayoutPattern>(false); });
1237     CHECK_NULL_RETURN(controlBar, nullptr);
1238     controlBar_ = controlBar;
1239 
1240     auto playButton = CreateSVG();
1241     CHECK_NULL_RETURN(playButton, nullptr);
1242     ChangePlayButtonTag(playButton);
1243     controlBar->AddChild(playButton);
1244 
1245     auto currentPosText = CreateText(currentPos_);
1246     CHECK_NULL_RETURN(currentPosText, nullptr);
1247     controlBar->AddChild(currentPosText);
1248 
1249     auto slider = CreateSlider();
1250     CHECK_NULL_RETURN(currentPosText, nullptr);
1251     controlBar->AddChild(slider);
1252 
1253     auto durationText = CreateText(duration_);
1254     CHECK_NULL_RETURN(durationText, nullptr);
1255     controlBar->AddChild(durationText);
1256 
1257     auto fullScreenButton = CreateSVG();
1258     CHECK_NULL_RETURN(fullScreenButton, nullptr);
1259     SetFullScreenButtonCallBack(fullScreenButton);
1260     ChangeFullScreenButtonTag(InstanceOf<VideoFullScreenNode>(this), fullScreenButton);
1261     controlBar->AddChild(fullScreenButton);
1262 
1263     auto renderContext = controlBar->GetRenderContext();
1264     renderContext->UpdateBackgroundColor(videoTheme->GetBkgColor());
1265     auto controlBarLayoutProperty = controlBar->GetLayoutProperty<LinearLayoutProperty>();
1266     controlBarLayoutProperty->UpdateMainAxisAlign(FlexAlign::SPACE_BETWEEN);
1267     if (NeedLift()) {
1268         PaddingProperty padding;
1269         padding.bottom = CalcLength(LIFT_HEIGHT);
1270         controlBarLayoutProperty->UpdatePadding(padding);
1271     }
1272     return controlBar;
1273 }
1274 
CreateSlider()1275 RefPtr<FrameNode> VideoPattern::CreateSlider()
1276 {
1277     auto pipelineContext = PipelineBase::GetCurrentContext();
1278     CHECK_NULL_RETURN(pipelineContext, nullptr);
1279     auto videoTheme = pipelineContext->GetTheme<VideoTheme>();
1280     CHECK_NULL_RETURN(videoTheme, nullptr);
1281 
1282     auto sliderNode = FrameNode::CreateFrameNode(V2::SLIDER_ETS_TAG, -1, AceType::MakeRefPtr<SliderPattern>());
1283     CHECK_NULL_RETURN(sliderNode, nullptr);
1284     auto sliderLayoutProperty = sliderNode->GetLayoutProperty<SliderLayoutProperty>();
1285     CHECK_NULL_RETURN(sliderLayoutProperty, nullptr);
1286 
1287     auto sliderEdge = videoTheme->GetSliderEdge();
1288     PaddingProperty padding;
1289     padding.left = CalcLength(sliderEdge.Left());
1290     padding.right = CalcLength(sliderEdge.Right());
1291     padding.top = CalcLength(sliderEdge.Top());
1292     padding.bottom = CalcLength(sliderEdge.Bottom());
1293     sliderLayoutProperty->UpdatePadding(padding);
1294     sliderLayoutProperty->UpdateLayoutWeight(1.0);
1295 
1296     SliderOnChangeEvent sliderOnChangeEvent = [weak = WeakClaim(this)](float value, int32_t mode) {
1297         auto videoPattern = weak.Upgrade();
1298         CHECK_NULL_VOID(videoPattern);
1299         videoPattern->OnSliderChange(value, mode);
1300     };
1301     auto sliderEventHub = sliderNode->GetEventHub<SliderEventHub>();
1302     sliderEventHub->SetOnChange(std::move(sliderOnChangeEvent));
1303     if (InstanceOf<VideoFullScreenPattern>(this)) {
1304         auto focusHub = sliderNode->GetOrCreateFocusHub();
1305         focusHub->SetIsDefaultFocus(true);
1306     }
1307 
1308     auto sliderPaintProperty = sliderNode->GetPaintProperty<SliderPaintProperty>();
1309     CHECK_NULL_RETURN(sliderPaintProperty, nullptr);
1310     sliderPaintProperty->UpdateMax(static_cast<float>(duration_));
1311     sliderPaintProperty->UpdateSelectColor(videoTheme->GetSelectColor());
1312     sliderPaintProperty->UpdateTrackBackgroundColor(ConvertToGradient(videoTheme->GetTrackBgColor()));
1313     sliderPaintProperty->UpdateTrackBackgroundIsResourceColor(true);
1314     sliderPaintProperty->UpdateValue(static_cast<float>(currentPos_));
1315     sliderNode->MarkModifyDone();
1316     return sliderNode;
1317 }
1318 
CreateText(uint32_t time)1319 RefPtr<FrameNode> VideoPattern::CreateText(uint32_t time)
1320 {
1321     auto pipelineContext = PipelineBase::GetCurrentContext();
1322     CHECK_NULL_RETURN(pipelineContext, nullptr);
1323     auto videoTheme = pipelineContext->GetTheme<VideoTheme>();
1324     CHECK_NULL_RETURN(videoTheme, nullptr);
1325 
1326     auto textNode = FrameNode::CreateFrameNode(V2::TEXT_ETS_TAG, -1, AceType::MakeRefPtr<TextPattern>());
1327     CHECK_NULL_RETURN(textNode, nullptr);
1328     auto textLayoutProperty = textNode->GetLayoutProperty<TextLayoutProperty>();
1329     CHECK_NULL_RETURN(textLayoutProperty, nullptr);
1330     auto videoLayoutProperty = GetLayoutProperty<VideoLayoutProperty>();
1331     CHECK_NULL_RETURN(videoLayoutProperty, nullptr);
1332     std::string label = "";
1333     if (videoLayoutProperty->GetControlsValue(true)) {
1334         label = IntTimeToText(time);
1335     }
1336     textLayoutProperty->UpdateContent(label);
1337     auto textEdge = videoTheme->GetTextEdge();
1338     PaddingProperty padding;
1339     padding.left = CalcLength(textEdge.Left());
1340     padding.right = CalcLength(textEdge.Right());
1341     padding.top = CalcLength(textEdge.Top());
1342     padding.bottom = CalcLength(textEdge.Bottom());
1343     textLayoutProperty->UpdatePadding(padding);
1344     auto textStyle = videoTheme->GetTimeTextStyle();
1345     textLayoutProperty->UpdateFontSize(textStyle.GetFontSize());
1346     textLayoutProperty->UpdateTextColor(textStyle.GetTextColor());
1347     return textNode;
1348 }
1349 
CreateSVG()1350 RefPtr<FrameNode> VideoPattern::CreateSVG()
1351 {
1352     auto pipelineContext = GetHost()->GetContext();
1353     CHECK_NULL_RETURN(pipelineContext, nullptr);
1354     auto videoTheme = pipelineContext->GetTheme<VideoTheme>();
1355     CHECK_NULL_RETURN(videoTheme, nullptr);
1356 
1357     auto svgNode = FrameNode::CreateFrameNode(V2::IMAGE_ETS_TAG, -1, AceType::MakeRefPtr<ImagePattern>());
1358     CHECK_NULL_RETURN(svgNode, nullptr);
1359 
1360     auto imageRenderProperty = svgNode->GetPaintPropertyPtr<ImageRenderProperty>();
1361     imageRenderProperty->UpdateSvgFillColor(videoTheme->GetIconColor());
1362     auto renderContext = svgNode->GetRenderContext();
1363     renderContext->UpdateForegroundColor(videoTheme->GetIconColor());
1364 
1365     auto svgLayoutProperty = svgNode->GetLayoutProperty<ImageLayoutProperty>();
1366 
1367     auto btnEdge = videoTheme->GetBtnEdge();
1368     PaddingProperty padding;
1369     padding.left = CalcLength(btnEdge.Left());
1370     padding.right = CalcLength(btnEdge.Right());
1371     padding.top = CalcLength(btnEdge.Top());
1372     padding.bottom = CalcLength(btnEdge.Bottom());
1373     svgLayoutProperty->UpdatePadding(padding);
1374 
1375     auto btnSize = videoTheme->GetBtnSize();
1376     SizeF size { static_cast<float>(btnSize.Width()), static_cast<float>(btnSize.Height()) };
1377     svgLayoutProperty->UpdateMarginSelfIdealSize(size);
1378     auto width = Dimension(btnSize.Width(), DimensionUnit::VP).ConvertToPx();
1379     auto height = Dimension(btnSize.Height(), DimensionUnit::VP).ConvertToPx();
1380     CalcSize idealSize = { CalcLength(width), CalcLength(height) };
1381     MeasureProperty layoutConstraint;
1382     layoutConstraint.selfIdealSize = idealSize;
1383     layoutConstraint.maxSize = idealSize;
1384     svgNode->UpdateLayoutConstraint(layoutConstraint);
1385     return svgNode;
1386 }
1387 
SetStartImpl(const RefPtr<VideoController> & videoController,const SingleTaskExecutor & uiTaskExecutor)1388 void VideoPattern::SetStartImpl(
1389     const RefPtr<VideoController>& videoController, const SingleTaskExecutor& uiTaskExecutor)
1390 {
1391     videoController->SetStartImpl([weak = WeakClaim(this), uiTaskExecutor]() {
1392         uiTaskExecutor.PostTask([weak]() {
1393             auto pattern = weak.Upgrade();
1394             CHECK_NULL_VOID(pattern);
1395             ContainerScope scope(pattern->instanceId_);
1396             auto targetPattern = pattern->GetTargetVideoPattern();
1397             CHECK_NULL_VOID(targetPattern);
1398             targetPattern->Start();
1399         }, "ArkUIVideoStart");
1400     });
1401 }
1402 
SetPausetImpl(const RefPtr<VideoController> & videoController,const SingleTaskExecutor & uiTaskExecutor)1403 void VideoPattern::SetPausetImpl(
1404     const RefPtr<VideoController>& videoController, const SingleTaskExecutor& uiTaskExecutor)
1405 {
1406     videoController->SetPausetImpl([weak = WeakClaim(this), uiTaskExecutor]() {
1407         uiTaskExecutor.PostTask([weak]() {
1408             auto pattern = weak.Upgrade();
1409             CHECK_NULL_VOID(pattern);
1410             ContainerScope scope(pattern->instanceId_);
1411             auto targetPattern = pattern->GetTargetVideoPattern();
1412             CHECK_NULL_VOID(targetPattern);
1413             targetPattern->Pause();
1414         }, "ArkUIVideoPause");
1415     });
1416 }
1417 
SetStopImpl(const RefPtr<VideoController> & videoController,const SingleTaskExecutor & uiTaskExecutor)1418 void VideoPattern::SetStopImpl(
1419     const RefPtr<VideoController>& videoController, const SingleTaskExecutor& uiTaskExecutor)
1420 {
1421     videoController->SetStopImpl([weak = WeakClaim(this), uiTaskExecutor]() {
1422         uiTaskExecutor.PostTask([weak]() {
1423             auto pattern = weak.Upgrade();
1424             CHECK_NULL_VOID(pattern);
1425             ContainerScope scope(pattern->instanceId_);
1426             auto targetPattern = pattern->GetTargetVideoPattern();
1427             CHECK_NULL_VOID(targetPattern);
1428             targetPattern->Stop();
1429         }, "ArkUIVideoStop");
1430     });
1431 }
1432 
SetSeekToImpl(const RefPtr<VideoController> & videoController,const SingleTaskExecutor & uiTaskExecutor)1433 void VideoPattern::SetSeekToImpl(
1434     const RefPtr<VideoController>& videoController, const SingleTaskExecutor& uiTaskExecutor)
1435 {
1436     videoController->SetSeekToImpl([weak = WeakClaim(this), uiTaskExecutor](float pos, SeekMode seekMode) {
1437         uiTaskExecutor.PostTask([weak, pos, seekMode]() {
1438             auto pattern = weak.Upgrade();
1439             CHECK_NULL_VOID(pattern);
1440             ContainerScope scope(pattern->instanceId_);
1441             auto targetPattern = pattern->GetTargetVideoPattern();
1442             CHECK_NULL_VOID(targetPattern);
1443             targetPattern->SetCurrentTime(pos, seekMode);
1444         }, "ArkUIVideoSetCurrentTime");
1445     });
1446 }
1447 
SetRequestFullscreenImpl(const RefPtr<VideoController> & videoController,const SingleTaskExecutor & uiTaskExecutor)1448 void VideoPattern::SetRequestFullscreenImpl(
1449     const RefPtr<VideoController>& videoController, const SingleTaskExecutor& uiTaskExecutor)
1450 {
1451     videoController->SetRequestFullscreenImpl([weak = WeakClaim(this), uiTaskExecutor](bool isFullScreen) {
1452         uiTaskExecutor.PostTask([weak, isFullScreen]() {
1453             auto videoPattern = weak.Upgrade();
1454             CHECK_NULL_VOID(videoPattern);
1455             ContainerScope scope(videoPattern->instanceId_);
1456             if (isFullScreen) {
1457                 videoPattern->FullScreen();
1458             } else {
1459                 videoPattern->ResetLastBoundsRect();
1460                 auto targetPattern = videoPattern->GetTargetVideoPattern();
1461                 CHECK_NULL_VOID(targetPattern);
1462                 auto fullScreenPattern = AceType::DynamicCast<VideoFullScreenPattern>(targetPattern);
1463                 CHECK_NULL_VOID(fullScreenPattern);
1464                 fullScreenPattern->ExitFullScreen();
1465             }
1466         }, "ArkUIVideoFullScreen");
1467     });
1468 }
1469 
SetExitFullscreenImpl(const RefPtr<VideoController> & videoController,const SingleTaskExecutor & uiTaskExecutor)1470 void VideoPattern::SetExitFullscreenImpl(
1471     const RefPtr<VideoController>& videoController, const SingleTaskExecutor& uiTaskExecutor)
1472 {
1473     videoController->SetExitFullscreenImpl([weak = WeakClaim(this), uiTaskExecutor](bool isSync) {
1474         if (isSync) {
1475             auto pattern = weak.Upgrade();
1476             CHECK_NULL_VOID(pattern);
1477             auto targetPattern = pattern->GetTargetVideoPattern();
1478             CHECK_NULL_VOID(targetPattern);
1479             pattern->ResetLastBoundsRect();
1480             auto fullScreenPattern = AceType::DynamicCast<VideoFullScreenPattern>(targetPattern);
1481             fullScreenPattern->ExitFullScreen();
1482             return;
1483         }
1484         uiTaskExecutor.PostTask([weak]() {
1485             auto pattern = weak.Upgrade();
1486             CHECK_NULL_VOID(pattern);
1487             ContainerScope scope(pattern->instanceId_);
1488             pattern->ResetLastBoundsRect();
1489             auto targetPattern = pattern->GetTargetVideoPattern();
1490             CHECK_NULL_VOID(targetPattern);
1491             auto fullScreenPattern = AceType::DynamicCast<VideoFullScreenPattern>(targetPattern);
1492             CHECK_NULL_VOID(fullScreenPattern);
1493             fullScreenPattern->ExitFullScreen();
1494         }, "ArkUIVideoExitFullScreen");
1495     });
1496 }
1497 
SetResetImpl(const RefPtr<VideoController> & videoController,const SingleTaskExecutor & uiTaskExecutor)1498 void VideoPattern::SetResetImpl(
1499     const RefPtr<VideoController>& videoController, const SingleTaskExecutor& uiTaskExecutor)
1500 {
1501     videoController->SetResetImpl([weak = WeakClaim(this), uiTaskExecutor]() {
1502         uiTaskExecutor.PostTask([weak]() {
1503             auto pattern = weak.Upgrade();
1504             CHECK_NULL_VOID(pattern);
1505             auto targetPattern = pattern->GetTargetVideoPattern();
1506             CHECK_NULL_VOID(targetPattern);
1507             targetPattern->ResetMediaPlayer();
1508         }, "ArkUIVideoReset");
1509     });
1510 }
1511 
SetMethodCall()1512 void VideoPattern::SetMethodCall()
1513 {
1514     ContainerScope scope(instanceId_);
1515     auto videoController = AceType::MakeRefPtr<VideoController>();
1516     auto host = GetHost();
1517     CHECK_NULL_VOID(host);
1518     auto context = host->GetContext();
1519     CHECK_NULL_VOID(context);
1520     auto uiTaskExecutor = SingleTaskExecutor::Make(context->GetTaskExecutor(), TaskExecutor::TaskType::UI);
1521 
1522     SetStartImpl(videoController, uiTaskExecutor);
1523     SetPausetImpl(videoController, uiTaskExecutor);
1524     SetStopImpl(videoController, uiTaskExecutor);
1525     SetSeekToImpl(videoController, uiTaskExecutor);
1526     SetRequestFullscreenImpl(videoController, uiTaskExecutor);
1527     SetExitFullscreenImpl(videoController, uiTaskExecutor);
1528     SetResetImpl(videoController, uiTaskExecutor);
1529 
1530     CHECK_NULL_VOID(videoControllerV2_);
1531     videoControllerV2_->AddVideoController(videoController);
1532 }
1533 
Start()1534 void VideoPattern::Start()
1535 {
1536     if (!mediaPlayer_ || !mediaPlayer_->IsMediaPlayerValid()) {
1537         return;
1538     }
1539 
1540     if (isStop_ && mediaPlayer_->PrepareAsync() != 0) {
1541         TAG_LOGW(AceLogTag::ACE_VIDEO, "Player has not prepared");
1542         return;
1543     }
1544     ContainerScope scope(instanceId_);
1545     auto host = GetHost();
1546     CHECK_NULL_VOID(host);
1547     auto context = host->GetContext();
1548     CHECK_NULL_VOID(context);
1549 
1550     DestroyAnalyzerOverlay();
1551     isPaused_ = false;
1552 
1553     auto platformTask = SingleTaskExecutor::Make(context->GetTaskExecutor(), TaskExecutor::TaskType::BACKGROUND);
1554     platformTask.PostTask([weak = WeakClaim(RawPtr(mediaPlayer_))] {
1555         auto mediaPlayer = weak.Upgrade();
1556         CHECK_NULL_VOID(mediaPlayer);
1557         TAG_LOGI(AceLogTag::ACE_VIDEO, "trigger mediaPlayer play");
1558         mediaPlayer->Play();
1559     }, "ArkUIVideoPlay");
1560 }
1561 
Pause()1562 void VideoPattern::Pause()
1563 {
1564     if (!mediaPlayer_ || !mediaPlayer_->IsMediaPlayerValid()) {
1565         return;
1566     }
1567     auto ret = mediaPlayer_->Pause();
1568     if (ret != -1 && !isPaused_) {
1569         isPaused_ = true;
1570         StartImageAnalyzer();
1571     }
1572 }
1573 
Stop()1574 void VideoPattern::Stop()
1575 {
1576     if (!mediaPlayer_ || !mediaPlayer_->IsMediaPlayerValid()) {
1577         return;
1578     }
1579 
1580     OnCurrentTimeChange(0);
1581     mediaPlayer_->Stop();
1582     isStop_ = true;
1583 }
1584 
FireError()1585 void VideoPattern::FireError()
1586 {
1587     ContainerScope scope(instanceId_);
1588     auto host = GetHost();
1589     CHECK_NULL_VOID(host);
1590     auto context = host->GetContext();
1591     CHECK_NULL_VOID(context);
1592 
1593     // OnError function must be excuted on ui, so get the uiTaskExecutor.
1594     auto uiTaskExecutor = SingleTaskExecutor::Make(context->GetTaskExecutor(), TaskExecutor::TaskType::UI);
1595     uiTaskExecutor.PostTask([weak = WeakClaim(this)] {
1596         auto videoPattern = weak.Upgrade();
1597         CHECK_NULL_VOID(videoPattern);
1598         ContainerScope scope(videoPattern->instanceId_);
1599         videoPattern->OnError("");
1600     }, "ArkUIVideoError");
1601 }
1602 
ChangePlayButtonTag()1603 void VideoPattern::ChangePlayButtonTag()
1604 {
1605     ContainerScope scope(instanceId_);
1606     auto host = GetHost();
1607     CHECK_NULL_VOID(host);
1608     auto context = host->GetContext();
1609     CHECK_NULL_VOID(context);
1610     const auto& children = host->GetChildren();
1611     for (const auto& child : children) {
1612         if (child->GetTag() == V2::ROW_ETS_TAG) {
1613             auto playBtn = DynamicCast<FrameNode>(child->GetChildAtIndex(0));
1614             ChangePlayButtonTag(playBtn);
1615             break;
1616         }
1617     }
1618 }
1619 
ChangePlayButtonTag(RefPtr<FrameNode> & playBtn)1620 void VideoPattern::ChangePlayButtonTag(RefPtr<FrameNode>& playBtn)
1621 {
1622     CHECK_NULL_VOID(playBtn);
1623     auto playClickCallback = [weak = WeakClaim(this), playing = isPlaying_](GestureEvent& /* info */) {
1624         auto videoPattern = weak.Upgrade();
1625         CHECK_NULL_VOID(videoPattern);
1626         if (playing) {
1627             videoPattern->Pause();
1628         } else {
1629             videoPattern->Start();
1630         }
1631     };
1632     auto playBtnEvent = playBtn->GetOrCreateGestureEventHub();
1633     playBtnEvent->SetUserOnClick(std::move(playClickCallback));
1634     auto svgLayoutProperty = playBtn->GetLayoutProperty<ImageLayoutProperty>();
1635     auto resourceId = isPlaying_ ? InternalResource::ResourceId::PAUSE_SVG : InternalResource::ResourceId::PLAY_SVG;
1636     auto svgSourceInfo = ImageSourceInfo("");
1637     svgSourceInfo.SetResourceId(resourceId);
1638     svgLayoutProperty->UpdateImageSourceInfo(svgSourceInfo);
1639     playBtn->MarkModifyDone();
1640     playBtn->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
1641 }
1642 
SetFullScreenButtonCallBack(RefPtr<FrameNode> & fullScreenBtn)1643 void VideoPattern::SetFullScreenButtonCallBack(RefPtr<FrameNode>& fullScreenBtn)
1644 {
1645     CHECK_NULL_VOID(fullScreenBtn);
1646     auto fsClickCallback = [weak = WeakClaim(this)](GestureEvent& /* info */) {
1647         auto videoPattern = weak.Upgrade();
1648         CHECK_NULL_VOID(videoPattern);
1649         if (InstanceOf<VideoFullScreenPattern>(videoPattern)) {
1650             auto pattern = AceType::DynamicCast<VideoFullScreenPattern>(videoPattern);
1651             CHECK_NULL_VOID(pattern);
1652             videoPattern->ResetLastBoundsRect();
1653             pattern->ExitFullScreen();
1654         } else {
1655             videoPattern->FullScreen();
1656         }
1657     };
1658     auto fullScreenBtnEvent = fullScreenBtn->GetOrCreateGestureEventHub();
1659     fullScreenBtnEvent->SetUserOnClick(std::move(fsClickCallback));
1660 }
1661 
ChangeFullScreenButtonTag(bool isFullScreen,RefPtr<FrameNode> & fullScreenBtn)1662 void VideoPattern::ChangeFullScreenButtonTag(bool isFullScreen, RefPtr<FrameNode>& fullScreenBtn)
1663 {
1664     CHECK_NULL_VOID(fullScreenBtn);
1665     auto svgLayoutProperty = fullScreenBtn->GetLayoutProperty<ImageLayoutProperty>();
1666     auto resourceId =
1667         isFullScreen ? InternalResource::ResourceId::QUIT_FULLSCREEN_SVG : InternalResource::ResourceId::FULLSCREEN_SVG;
1668     auto svgSourceInfo = ImageSourceInfo("");
1669     svgSourceInfo.SetResourceId(resourceId);
1670     svgLayoutProperty->UpdateImageSourceInfo(svgSourceInfo);
1671     fullScreenBtn->MarkModifyDone();
1672     fullScreenBtn->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
1673 }
1674 
SetCurrentTime(float currentPos,OHOS::Ace::SeekMode seekMode)1675 void VideoPattern::SetCurrentTime(float currentPos, OHOS::Ace::SeekMode seekMode)
1676 {
1677     if (!mediaPlayer_ || !mediaPlayer_->IsMediaPlayerValid()) {
1678         return;
1679     }
1680     if (GreatOrEqual(currentPos, 0.0)) {
1681         SetIsSeeking(true);
1682         mediaPlayer_->Seek(static_cast<int32_t>(currentPos * MILLISECONDS_TO_SECONDS), seekMode);
1683     }
1684 }
1685 
OnSliderChange(float posTime,int32_t mode)1686 void VideoPattern::OnSliderChange(float posTime, int32_t mode)
1687 {
1688     SetCurrentTime(posTime, OHOS::Ace::SeekMode::SEEK_CLOSEST);
1689     auto eventHub = GetEventHub<VideoEventHub>();
1690     CHECK_NULL_VOID(eventHub);
1691     auto json = JsonUtil::Create(true);
1692     json->Put("time", static_cast<double>(posTime));
1693     auto param = json->ToString();
1694     CHECK_NULL_VOID(eventHub);
1695     if (mode == SliderChangeMode::BEGIN || mode == SliderChangeMode::MOVING) {
1696         eventHub->FireSeekingEvent(param);
1697     } else if (mode == SliderChangeMode::END) {
1698         eventHub->FireSeekedEvent(param);
1699     }
1700 }
1701 
OnFullScreenChange(bool isFullScreen)1702 void VideoPattern::OnFullScreenChange(bool isFullScreen)
1703 {
1704     auto json = JsonUtil::Create(true);
1705     json->Put("fullscreen", isFullScreen);
1706     auto param = json->ToString();
1707     auto eventHub = GetEventHub<VideoEventHub>();
1708     CHECK_NULL_VOID(eventHub);
1709     eventHub->FireFullScreenChangeEvent(param);
1710     auto host = GetHost();
1711     CHECK_NULL_VOID(host);
1712     const auto& children = host->GetChildren();
1713     for (const auto& child : children) {
1714         if (child->GetTag() == V2::ROW_ETS_TAG) {
1715             auto fsBtn = DynamicCast<FrameNode>(child->GetChildAtIndex(FULL_SCREEN_POS));
1716             ChangeFullScreenButtonTag(isFullScreen, fsBtn);
1717             break;
1718         }
1719     }
1720     if (isEnableAnalyzer_) {
1721         if (!imageAnalyzerManager_) {
1722             EnableAnalyzer(isEnableAnalyzer_);
1723         }
1724         if (imageAnalyzerManager_ && isAnalyzerCreated_) {
1725             StartImageAnalyzer();
1726         }
1727     }
1728 
1729     if (!SystemProperties::GetExtSurfaceEnabled()) {
1730         return;
1731     }
1732     if (!fullScreenNodeId_.has_value()) {
1733         SetMediaFullScreen(isFullScreen);
1734         return;
1735     }
1736     auto fullScreenNode = FrameNode::GetFrameNode(V2::VIDEO_ETS_TAG, fullScreenNodeId_.value());
1737     CHECK_NULL_VOID(fullScreenNode);
1738     auto fullScreenPattern = AceType::DynamicCast<VideoFullScreenPattern>(fullScreenNode->GetPattern());
1739     CHECK_NULL_VOID(fullScreenPattern);
1740     fullScreenPattern->SetMediaFullScreen(isFullScreen);
1741 }
1742 
FullScreen()1743 void VideoPattern::FullScreen()
1744 {
1745     if (fullScreenNodeId_.has_value()) {
1746         return;
1747     }
1748     ResetLastBoundsRect();
1749     auto host = GetHost();
1750     CHECK_NULL_VOID(host);
1751     auto videoNode = AceType::DynamicCast<VideoNode>(host);
1752     CHECK_NULL_VOID(videoNode);
1753     auto fullScreenPattern = AceType::MakeRefPtr<VideoFullScreenPattern>(videoControllerV2_);
1754     fullScreenPattern->InitFullScreenParam(
1755         AceType::Claim(this), renderSurface_, mediaPlayer_, renderContextForMediaPlayer_);
1756     fullScreenNodeId_ = ElementRegister::GetInstance()->MakeUniqueId();
1757     auto fullScreenNode =
1758         VideoFullScreenNode::CreateFullScreenNode(V2::VIDEO_ETS_TAG, fullScreenNodeId_.value(), fullScreenPattern);
1759     CHECK_NULL_VOID(fullScreenNode);
1760     fullScreenPattern->RequestFullScreen(videoNode);
1761 }
1762 
EnableDrag()1763 void VideoPattern::EnableDrag()
1764 {
1765     auto host = GetHost();
1766     CHECK_NULL_VOID(host);
1767     auto layoutProperty = GetLayoutProperty<VideoLayoutProperty>();
1768     auto dragEnd = [wp = WeakClaim(this)](
1769                        const RefPtr<OHOS::Ace::DragEvent>& event, const std::string& extraParams) {
1770         auto videoPattern = wp.Upgrade();
1771         CHECK_NULL_VOID(videoPattern);
1772         auto videoLayoutProperty = videoPattern->GetLayoutProperty<VideoLayoutProperty>();
1773         CHECK_NULL_VOID(videoLayoutProperty);
1774         CHECK_NULL_VOID(event);
1775         auto unifiedData = event->GetData();
1776         std::string videoSrc;
1777         if (unifiedData != nullptr) {
1778             int ret = UdmfClient::GetInstance()->GetVideoRecordUri(unifiedData, videoSrc);
1779             if (ret != 0) {
1780                 TAG_LOGW(AceLogTag::ACE_VIDEO, "unifiedRecords is empty");
1781                 return;
1782             }
1783         } else {
1784             auto json = JsonUtil::ParseJsonString(extraParams);
1785             std::string key = "extraInfo";
1786             videoSrc = json->GetString(key);
1787         }
1788 
1789         if (videoSrc == videoPattern->GetSrc()) {
1790             return;
1791         }
1792 
1793         std::regex extensionRegex("\\.(" + PNG_FILE_EXTENSION + ")$");
1794         bool isPng = std::regex_search(videoSrc, extensionRegex);
1795         if (isPng) {
1796             event->SetResult(DragRet::DRAG_FAIL);
1797             return;
1798         }
1799 
1800         videoPattern->SetIsDragEndAutoPlay(true);
1801         videoLayoutProperty->UpdateVideoSource(videoSrc);
1802         auto frameNode = videoPattern->GetHost();
1803         CHECK_NULL_VOID(frameNode);
1804         frameNode->MarkModifyDone();
1805     };
1806     auto eventHub = host->GetEventHub<EventHub>();
1807     CHECK_NULL_VOID(eventHub);
1808     eventHub->SetOnDrop(std::move(dragEnd));
1809 }
1810 
~VideoPattern()1811 VideoPattern::~VideoPattern()
1812 {
1813     if (IsSupportImageAnalyzer()) {
1814         DestroyAnalyzerOverlay();
1815     }
1816     if (!fullScreenNodeId_.has_value()) {
1817         return;
1818     }
1819     auto fullScreenNode = FrameNode::GetFrameNode(V2::VIDEO_ETS_TAG, fullScreenNodeId_.value());
1820     CHECK_NULL_VOID(fullScreenNode);
1821     auto parent = fullScreenNode->GetParent();
1822     CHECK_NULL_VOID(parent);
1823     parent->RemoveChild(fullScreenNode);
1824     parent->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
1825 }
1826 
RecoverState(const RefPtr<VideoPattern> & videoPattern)1827 void VideoPattern::RecoverState(const RefPtr<VideoPattern>& videoPattern)
1828 {
1829     CHECK_NULL_VOID(videoPattern);
1830     currentPos_ = videoPattern->GetCurrentPos();
1831     if (mediaPlayer_ && mediaPlayer_->IsMediaPlayerValid() && mediaPlayer_->IsPlaying() != isPlaying_) {
1832         isPlaying_ = mediaPlayer_->IsPlaying();
1833         ChangePlayButtonTag();
1834     }
1835     isInitialState_ = videoPattern->GetInitialState();
1836     auto layoutProperty = videoPattern->GetLayoutProperty<VideoLayoutProperty>();
1837     src_ = layoutProperty->GetVideoSourceValue("");
1838     isStop_ = videoPattern->GetIsStop();
1839     muted_ = videoPattern->GetMuted();
1840     autoPlay_ = videoPattern->GetAutoPlay();
1841     loop_ = videoPattern->GetLoop();
1842     duration_ = videoPattern->GetDuration();
1843     progressRate_ = videoPattern->GetProgressRate();
1844     isAnalyzerCreated_ = videoPattern->GetAnalyzerState();
1845     isEnableAnalyzer_ = videoPattern->isEnableAnalyzer_;
1846     fullScreenNodeId_.reset();
1847     RegisterMediaPlayerEvent();
1848     auto videoNode = GetHost();
1849     CHECK_NULL_VOID(videoNode);
1850     // change event hub to the origin video node
1851     videoPattern->GetEventHub<VideoEventHub>()->AttachHost(videoNode);
1852     videoNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF_AND_CHILD);
1853 }
1854 
UpdateFsState()1855 void VideoPattern::UpdateFsState()
1856 {
1857     if (!fullScreenNodeId_.has_value()) {
1858         return;
1859     }
1860     auto videoNode = FrameNode::GetFrameNode(V2::VIDEO_ETS_TAG, fullScreenNodeId_.value());
1861     CHECK_NULL_VOID(videoNode);
1862     auto videoPattern = AceType::DynamicCast<VideoFullScreenPattern>(videoNode->GetPattern());
1863     CHECK_NULL_VOID(videoPattern);
1864     // update full screen state
1865     videoPattern->UpdateState();
1866 }
1867 
IsFullScreen() const1868 bool VideoPattern::IsFullScreen() const
1869 {
1870     return fullScreenNodeId_.has_value();
1871 }
1872 
GetTargetVideoPattern()1873 RefPtr<VideoPattern> VideoPattern::GetTargetVideoPattern()
1874 {
1875     auto isFullScreen = IsFullScreen();
1876     auto patternIsFullScreen = AceType::InstanceOf<VideoFullScreenPattern>(this);
1877     if ((isFullScreen && patternIsFullScreen) || (!isFullScreen && !patternIsFullScreen)) {
1878         return AceType::Claim(this);
1879     }
1880     if (patternIsFullScreen) {
1881         // current is full screen,need to be released
1882         auto fullScreenPattern = AceType::DynamicCast<VideoFullScreenPattern>(this);
1883         CHECK_NULL_RETURN(fullScreenPattern, nullptr);
1884         return fullScreenPattern->GetVideoPattern();
1885     }
1886     // current node is origin video node, need to operate full screen node
1887     auto fullScreenNode = GetFullScreenNode();
1888     CHECK_NULL_RETURN(fullScreenNode, nullptr);
1889     return fullScreenNode->GetPattern<VideoPattern>();
1890 }
1891 
EnableAnalyzer(bool enable)1892 void VideoPattern::EnableAnalyzer(bool enable)
1893 {
1894     isEnableAnalyzer_ = enable;
1895     if (!isEnableAnalyzer_) {
1896         DestroyAnalyzerOverlay();
1897         return;
1898     }
1899 
1900     CHECK_NULL_VOID(!imageAnalyzerManager_);
1901     auto host = GetHost();
1902     CHECK_NULL_VOID(host);
1903     imageAnalyzerManager_ = std::make_shared<ImageAnalyzerManager>(host, ImageAnalyzerHolder::VIDEO_CUSTOM);
1904 }
1905 
SetImageAnalyzerConfig(void * config)1906 void VideoPattern::SetImageAnalyzerConfig(void* config)
1907 {
1908     if (isEnableAnalyzer_) {
1909         CHECK_NULL_VOID(imageAnalyzerManager_);
1910         imageAnalyzerManager_->SetImageAnalyzerConfig(config);
1911     }
1912 }
1913 
SetImageAIOptions(void * options)1914 void VideoPattern::SetImageAIOptions(void* options)
1915 {
1916     if (!imageAnalyzerManager_) {
1917         imageAnalyzerManager_ = std::make_shared<ImageAnalyzerManager>(GetHost(), ImageAnalyzerHolder::VIDEO_CUSTOM);
1918     }
1919     CHECK_NULL_VOID(imageAnalyzerManager_);
1920     imageAnalyzerManager_->SetImageAIOptions(options);
1921 }
1922 
IsSupportImageAnalyzer()1923 bool VideoPattern::IsSupportImageAnalyzer()
1924 {
1925     auto host = GetHost();
1926     CHECK_NULL_RETURN(host, false);
1927     auto layoutProperty = host->GetLayoutProperty<VideoLayoutProperty>();
1928     CHECK_NULL_RETURN(layoutProperty, false);
1929     bool needControlBar = layoutProperty->GetControlsValue(true);
1930     CHECK_NULL_RETURN(imageAnalyzerManager_, false);
1931     return isEnableAnalyzer_ && !needControlBar && imageAnalyzerManager_->IsSupportImageAnalyzerFeature();
1932 }
1933 
ShouldUpdateImageAnalyzer()1934 bool VideoPattern::ShouldUpdateImageAnalyzer()
1935 {
1936     auto layoutProperty = GetLayoutProperty<VideoLayoutProperty>();
1937     CHECK_NULL_RETURN(layoutProperty, false);
1938     const auto& constraint = layoutProperty->GetCalcLayoutConstraint();
1939     if (!constraint || !constraint->selfIdealSize.has_value() || !constraint->selfIdealSize->IsValid()) {
1940         return false;
1941     }
1942     auto selfIdealSize = constraint->selfIdealSize;
1943     if (!selfIdealSize->PercentWidth() && !selfIdealSize->PercentHeight()) {
1944         return false;
1945     }
1946     auto imageFit = layoutProperty->GetObjectFit().value_or(ImageFit::COVER);
1947     if (imageFit != ImageFit::COVER && imageFit != ImageFit::NONE) {
1948         return false;
1949     }
1950     return true;
1951 }
1952 
StartImageAnalyzer()1953 void VideoPattern::StartImageAnalyzer()
1954 {
1955     if (!IsSupportImageAnalyzer() || !imageAnalyzerManager_) {
1956         return;
1957     }
1958 
1959     if (imageAnalyzerManager_->IsOverlayCreated()) {
1960         DestroyAnalyzerOverlay();
1961     }
1962 
1963     ContainerScope scope(instanceId_);
1964     auto host = GetHost();
1965     CHECK_NULL_VOID(host);
1966     auto context = host->GetContext();
1967     CHECK_NULL_VOID(context);
1968     auto uiTaskExecutor = SingleTaskExecutor::Make(context->GetTaskExecutor(), TaskExecutor::TaskType::UI);
1969     uiTaskExecutor.PostDelayedTask([weak = WeakClaim(this)] {
1970         auto pattern = weak.Upgrade();
1971         CHECK_NULL_VOID(pattern);
1972         pattern->CreateAnalyzerOverlay();
1973         }, ANALYZER_DELAY_TIME, "ArkUIVideoCreateAnalyzerOverlay");
1974 }
1975 
CreateAnalyzerOverlay()1976 void VideoPattern::CreateAnalyzerOverlay()
1977 {
1978     auto host = GetHost();
1979     CHECK_NULL_VOID(host);
1980     host->SetOverlayNode(nullptr);
1981     auto context = host->GetRenderContext();
1982     CHECK_NULL_VOID(context);
1983     auto nailPixelMap = context->GetThumbnailPixelMap();
1984     CHECK_NULL_VOID(nailPixelMap);
1985     auto pixelMap = nailPixelMap->GetCropPixelMap(contentRect_);
1986     CHECK_NULL_VOID(pixelMap);
1987     auto layoutProperty = GetLayoutProperty<VideoLayoutProperty>();
1988     CHECK_NULL_VOID(layoutProperty);
1989     auto padding  = layoutProperty->CreatePaddingAndBorder();
1990     OffsetF contentOffset = { contentRect_.Left() - padding.left.value_or(0),
1991                               contentRect_.Top() - padding.top.value_or(0) };
1992     CHECK_NULL_VOID(imageAnalyzerManager_);
1993     imageAnalyzerManager_->CreateAnalyzerOverlay(pixelMap, contentOffset);
1994 }
1995 
StartUpdateImageAnalyzer()1996 void VideoPattern::StartUpdateImageAnalyzer()
1997 {
1998     CHECK_NULL_VOID(imageAnalyzerManager_);
1999     if (!imageAnalyzerManager_->IsOverlayCreated()) {
2000         return;
2001     }
2002 
2003     UpdateOverlayVisibility(VisibleType::GONE);
2004     ContainerScope scope(instanceId_);
2005     auto host = GetHost();
2006     CHECK_NULL_VOID(host);
2007     auto context = host->GetContext();
2008     CHECK_NULL_VOID(context);
2009     auto uiTaskExecutor = SingleTaskExecutor::Make(context->GetTaskExecutor(), TaskExecutor::TaskType::UI);
2010     uiTaskExecutor.PostDelayedTask([weak = WeakClaim(this)] {
2011         auto pattern = weak.Upgrade();
2012         CHECK_NULL_VOID(pattern);
2013         if (!pattern->isContentSizeChanged_) {
2014             return;
2015         }
2016         pattern->UpdateAnalyzerOverlay();
2017         pattern->isContentSizeChanged_ = false;
2018         }, ANALYZER_CAPTURE_DELAY_TIME, "ArkUIVideoUpdateAnalyzerOverlay");
2019     isContentSizeChanged_ = true;
2020 }
2021 
UpdateAnalyzerOverlay()2022 void VideoPattern::UpdateAnalyzerOverlay()
2023 {
2024     auto host = GetHost();
2025     CHECK_NULL_VOID(host);
2026     auto context = host->GetRenderContext();
2027     CHECK_NULL_VOID(context);
2028     auto nailPixelMap = context->GetThumbnailPixelMap();
2029     CHECK_NULL_VOID(nailPixelMap);
2030     auto pixelMap = nailPixelMap->GetCropPixelMap(contentRect_);
2031     CHECK_NULL_VOID(pixelMap);
2032     UpdateOverlayVisibility(VisibleType::VISIBLE);
2033 
2034     auto layoutProperty = GetLayoutProperty<VideoLayoutProperty>();
2035     CHECK_NULL_VOID(layoutProperty);
2036     auto padding  = layoutProperty->CreatePaddingAndBorder();
2037     OffsetF contentOffset = { contentRect_.Left() - padding.left.value_or(0),
2038                               contentRect_.Top() - padding.top.value_or(0) };
2039     CHECK_NULL_VOID(imageAnalyzerManager_);
2040     imageAnalyzerManager_->UpdateAnalyzerOverlay(pixelMap, contentOffset);
2041 }
2042 
UpdateAnalyzerUIConfig(const RefPtr<NG::GeometryNode> & geometryNode)2043 void VideoPattern::UpdateAnalyzerUIConfig(const RefPtr<NG::GeometryNode>& geometryNode)
2044 {
2045     if (IsSupportImageAnalyzer()) {
2046         auto layoutProperty = GetLayoutProperty<VideoLayoutProperty>();
2047         CHECK_NULL_VOID(layoutProperty);
2048         auto padding  = layoutProperty->CreatePaddingAndBorder();
2049         OffsetF contentOffset = { contentRect_.Left() - padding.left.value_or(0),
2050                                   contentRect_.Top() - padding.top.value_or(0) };
2051         PixelMapInfo info = { contentRect_.GetSize().Width(), contentRect_.GetSize().Height(), contentOffset };
2052         CHECK_NULL_VOID(imageAnalyzerManager_);
2053         imageAnalyzerManager_->UpdateAnalyzerUIConfig(geometryNode, info);
2054     }
2055 }
2056 
DestroyAnalyzerOverlay()2057 void VideoPattern::DestroyAnalyzerOverlay()
2058 {
2059     CHECK_NULL_VOID(imageAnalyzerManager_);
2060     imageAnalyzerManager_->DestroyAnalyzerOverlay();
2061 }
2062 
GetAnalyzerState()2063 bool VideoPattern::GetAnalyzerState()
2064 {
2065     CHECK_NULL_RETURN(imageAnalyzerManager_, false);
2066     return imageAnalyzerManager_->IsOverlayCreated();
2067 }
2068 
UpdateOverlayVisibility(VisibleType type)2069 void VideoPattern::UpdateOverlayVisibility(VisibleType type)
2070 {
2071     auto host = GetHost();
2072     CHECK_NULL_VOID(host);
2073     auto overlayNode = host->GetOverlayNode();
2074     CHECK_NULL_VOID(overlayNode);
2075     auto prop = overlayNode->GetLayoutProperty();
2076     CHECK_NULL_VOID(prop);
2077     prop->UpdateVisibility(type);
2078 }
2079 
OnWindowHide()2080 void VideoPattern::OnWindowHide()
2081 {
2082 #if defined(OHOS_PLATFORM)
2083     if (!BackgroundTaskHelper::GetInstance().HasBackgroundTask()) {
2084         autoPlay_ = false;
2085         Pause();
2086     }
2087 #else
2088     Pause();
2089 #endif
2090 }
2091 
2092 } // namespace OHOS::Ace::NG
2093