• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2024 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 <unistd.h>
17 
18 #include "movingphoto_pattern.h"
19 #include "movingphoto_node.h"
20 #include "movingphoto_utils.h"
21 
22 #include "base/image/pixel_map.h"
23 #include "core/components_ng/pattern/image/image_pattern.h"
24 #include "core/pipeline_ng/pipeline_context.h"
25 #include "core/pipeline/base/element_register.h"
26 
27 namespace OHOS::Ace::NG {
28 namespace {
29 constexpr int32_t LONG_PRESS_DELAY = 300;
30 constexpr int32_t ANIMATION_DURATION_300 = 300;
31 constexpr int32_t ANIMATION_DURATION_400 = 400;
32 constexpr float NORMAL_SCALE = 1.0f;
33 constexpr float ZOOM_IN_SCALE = 1.1f;
34 constexpr double NORMAL_PLAY_SPEED = 1.0;
35 constexpr int32_t HALF = 2;
36 constexpr int32_t ROUND_XMAGE_MODE_VALUE = 0;
37 constexpr int64_t PERIOD_START = 0;
38 constexpr int32_t PREPARE_RETURN = 0;
39 constexpr int64_t VIDEO_PLAYTIME_START_POSITION = 0;
40 constexpr int32_t IMAGE_DECODE_COMPLETE = 1;
41 constexpr int32_t DURATION_FLAG = -1;
42 const std::string THUMBNAIL_MEDIUM_JOINT = "?&oper=thumbnail&width=-1&height=-1&path=";
43 const std::string COVER_POSITION = "cover_positon";
44 const std::string IMAGE_URI = "uri";
45 const std::string VIDEO_SCALE = "video_scale_type";
46 const std::string IMAGE_LENGTH = "ImageLength";
47 const std::string IMAGE_WIDTH = "ImageWidth";
48 const std::string HW_MNOTE_XMAGE_MODE = "HwMnoteXmageMode";
49 const std::string HW_MNOTE_XMAGE_LEFT = "HwMnoteXmageLeft";
50 const std::string HW_MNOTE_XMAGE_TOP = "HwMnoteXmageTop";
51 const std::string HW_MNOTE_XMAGE_RIGHT = "HwMnoteXmageRight";
52 const std::string HW_MNOTE_XMAGE_BOTTOM = "HwMnoteXmageBottom";
53 const std::string DEFAULT_EXIF_VALUE = "default_exif_value";
54 constexpr int32_t ANALYZER_DELAY_TIME = 100;
55 constexpr int32_t ANALYZER_CAPTURE_DELAY_TIME = 1000;
56 constexpr int32_t AVERAGE_VALUE = 2;
57 constexpr int32_t US_CONVERT = 1000;
58 constexpr int32_t ROUND_XMAGE_PIXEL_GAP = 2;
59 constexpr int32_t EIGHTY_TO_HUNDRED_TIME = 3000;
60 }
MovingPhotoPattern(const RefPtr<MovingPhotoController> & controller)61 MovingPhotoPattern::MovingPhotoPattern(const RefPtr<MovingPhotoController>& controller)
62     : instanceId_(Container::CurrentId()), controller_(controller)
63 {}
64 
OnModifyDone()65 void MovingPhotoPattern::OnModifyDone()
66 {
67     TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "movingphoto onModifydone start.");
68     Pattern::OnModifyDone();
69     UpdateImageNode();
70     UpdateVideoNode();
71     if (SystemProperties::GetExtSurfaceEnabled()) {
72         auto pipelineContext = PipelineContext::GetCurrentContext();
73         CHECK_NULL_VOID(pipelineContext);
74         auto host = GetHost();
75         CHECK_NULL_VOID(host);
76         pipelineContext->AddOnAreaChangeNode(host->GetId());
77     }
78     InitEvent();
79     UpdatePlayMode();
80     HandleImageAnalyzerMode();
81 }
82 
OnAttachToFrameNode()83 void MovingPhotoPattern::OnAttachToFrameNode()
84 {
85     auto host = GetHost();
86     CHECK_NULL_VOID(host);
87     auto renderContext = host->GetRenderContext();
88     CHECK_NULL_VOID(renderContext);
89     static RenderContext::ContextParam cParam = { RenderContext::ContextType::HARDWARE_SURFACE, "MediaPlayerSurface",
90                                                   RenderContext::PatternType::DEFAULT };
91     columnRenderContext_->InitContext(false, cParam);
92     columnRenderContext_->UpdateBackgroundColor(Color::TRANSPARENT);
93     static RenderContext::ContextParam param = { RenderContext::ContextType::HARDWARE_SURFACE, "MediaPlayerSurface",
94                                                  RenderContext::PatternType::VIDEO };
95     renderContextForMediaPlayer_->InitContext(false, param);
96     renderContext->UpdateBackgroundColor(Color::TRANSPARENT);
97     renderContextForMediaPlayer_->UpdateBackgroundColor(Color::TRANSPARENT);
98     renderContext->SetClipToBounds(true);
99 
100     CHECK_NULL_VOID(controller_);
101     ContainerScope scope(instanceId_);
102     auto context = PipelineContext::GetCurrentContext();
103     CHECK_NULL_VOID(context);
104     auto uiTaskExecutor = SingleTaskExecutor::Make(context->GetTaskExecutor(), TaskExecutor::TaskType::UI);
105     SetStartPlaybackImpl(uiTaskExecutor);
106     SetStopPlaybackImpl(uiTaskExecutor);
107     SetRefreshMovingPhotoImpl(uiTaskExecutor);
108     SetPauseImpl(uiTaskExecutor);
109     SetResetImpl(uiTaskExecutor);
110     SetRestartImpl(uiTaskExecutor);
111     SetEnableTransitionImpl(uiTaskExecutor);
112     SetPlaybackPeriodImpl(uiTaskExecutor);
113     SetEnableAutoPlayImpl(uiTaskExecutor);
114     SetNotifyTransitionImpl(uiTaskExecutor);
115     RegisterVisibleAreaChange();
116 }
117 
SetStartPlaybackImpl(const SingleTaskExecutor & uiTaskExecutor)118 void MovingPhotoPattern::SetStartPlaybackImpl(const SingleTaskExecutor& uiTaskExecutor)
119 {
120     controller_->SetStartPlaybackImpl([weak = WeakClaim(this), uiTaskExecutor]() {
121         uiTaskExecutor.PostTask(
122             [weak]() {
123                 auto pattern = weak.Upgrade();
124                 CHECK_NULL_VOID(pattern);
125                 ContainerScope scope(pattern->instanceId_);
126                 pattern->StartPlayback();
127             }, "ArkUIMovingPhotoStart");
128     });
129 }
130 
SetStopPlaybackImpl(const SingleTaskExecutor & uiTaskExecutor)131 void MovingPhotoPattern::SetStopPlaybackImpl(const SingleTaskExecutor& uiTaskExecutor)
132 {
133     controller_->SetStopPlaybackImpl([weak = WeakClaim(this), uiTaskExecutor]() {
134         uiTaskExecutor.PostTask(
135             [weak]() {
136                 auto pattern = weak.Upgrade();
137                 CHECK_NULL_VOID(pattern);
138                 ContainerScope scope(pattern->instanceId_);
139                 pattern->StopPlayback();
140             }, "ArkUIMovingPhotoStop");
141     });
142 }
143 
SetRefreshMovingPhotoImpl(const SingleTaskExecutor & uiTaskExecutor)144 void MovingPhotoPattern::SetRefreshMovingPhotoImpl(const SingleTaskExecutor& uiTaskExecutor)
145 {
146     controller_->SetRefreshMovingPhotoImpl([weak = WeakClaim(this), uiTaskExecutor]() {
147         uiTaskExecutor.PostTask(
148             [weak]() {
149                 auto pattern = weak.Upgrade();
150                 CHECK_NULL_VOID(pattern);
151                 ContainerScope scope(pattern->instanceId_);
152                 pattern->RefreshMovingPhoto();
153             }, "ArkUIRefreshMovingPhoto");
154     });
155 }
156 
SetPauseImpl(const SingleTaskExecutor & uiTaskExecutor)157 void MovingPhotoPattern::SetPauseImpl(const SingleTaskExecutor& uiTaskExecutor)
158 {
159     controller_->SetPauseImpl([weak = WeakClaim(this), uiTaskExecutor]() {
160         uiTaskExecutor.PostTask(
161             [weak]() {
162                 auto pattern = weak.Upgrade();
163                 CHECK_NULL_VOID(pattern);
164                 ContainerScope scope(pattern->instanceId_);
165                 pattern->PauseVideo();
166             }, "ArkUIPauseVideo");
167     });
168 }
169 
SetResetImpl(const SingleTaskExecutor & uiTaskExecutor)170 void MovingPhotoPattern::SetResetImpl(const SingleTaskExecutor& uiTaskExecutor)
171 {
172     controller_->SetResetImpl([weak = WeakClaim(this), uiTaskExecutor]() {
173         uiTaskExecutor.PostTask(
174             [weak]() {
175                 auto pattern = weak.Upgrade();
176                 CHECK_NULL_VOID(pattern);
177                 ContainerScope scope(pattern->instanceId_);
178                 pattern->ResetVideo();
179             }, "ArkUIResetVideo");
180     });
181 }
182 
SetRestartImpl(const SingleTaskExecutor & uiTaskExecutor)183 void MovingPhotoPattern::SetRestartImpl(const SingleTaskExecutor& uiTaskExecutor)
184 {
185     controller_->SetRestartImpl([weak = WeakClaim(this), uiTaskExecutor]() {
186         uiTaskExecutor.PostTask(
187             [weak]() {
188                 auto pattern = weak.Upgrade();
189                 CHECK_NULL_VOID(pattern);
190                 ContainerScope scope(pattern->instanceId_);
191                 pattern->RestartVideo();
192             }, "ArkUIRestartVideo");
193     });
194 }
195 
SetEnableTransitionImpl(const SingleTaskExecutor & uiTaskExecutor)196 void MovingPhotoPattern::SetEnableTransitionImpl(const SingleTaskExecutor& uiTaskExecutor)
197 {
198     controller_->SetEnableTransitionImpl([weak = WeakClaim(this), uiTaskExecutor](bool enabled) {
199         uiTaskExecutor.PostTask(
200             [weak, enabled]() {
201                 auto pattern = weak.Upgrade();
202                 CHECK_NULL_VOID(pattern);
203                 ContainerScope scope(pattern->instanceId_);
204                 pattern->SetEnableTransition(enabled);
205             }, "ArkUISetEnableTransition");
206     });
207 }
208 
SetPlaybackPeriodImpl(const SingleTaskExecutor & uiTaskExecutor)209 void MovingPhotoPattern::SetPlaybackPeriodImpl(const SingleTaskExecutor& uiTaskExecutor)
210 {
211     controller_->SetPlaybackPeriodImpl([weak = WeakClaim(this), uiTaskExecutor](int64_t startTime, int64_t endTime) {
212         uiTaskExecutor.PostTask(
213             [weak, startTime, endTime]() {
214                 auto pattern = weak.Upgrade();
215                 CHECK_NULL_VOID(pattern);
216                 ContainerScope scope(pattern->instanceId_);
217                 bool isSetPeriod = false;
218                 isSetPeriod = pattern->SetPlaybackPeriod(startTime, endTime);
219                 if (!isSetPeriod) {
220                     pattern->FireMediaPlayerError();
221                 }
222             }, "ArkUISetPlaybackPeriod");
223     });
224 }
225 
SetEnableAutoPlayImpl(const SingleTaskExecutor & uiTaskExecutor)226 void MovingPhotoPattern::SetEnableAutoPlayImpl(const SingleTaskExecutor& uiTaskExecutor)
227 {
228     controller_->SetEnableAutoPlayImpl([weak = WeakClaim(this), uiTaskExecutor](bool enabled) {
229         uiTaskExecutor.PostTask(
230             [weak, enabled]() {
231                 auto pattern = weak.Upgrade();
232                 CHECK_NULL_VOID(pattern);
233                 ContainerScope scope(pattern->instanceId_);
234                 pattern->EnableAutoPlay(enabled);
235             }, "ArkUIEnableAutoPlay");
236     });
237 }
238 
SetNotifyTransitionImpl(const SingleTaskExecutor & uiTaskExecutor)239 void MovingPhotoPattern::SetNotifyTransitionImpl(const SingleTaskExecutor& uiTaskExecutor)
240 {
241     controller_->SetNotifyTransitionImpl([weak = WeakClaim(this), uiTaskExecutor]() {
242         uiTaskExecutor.PostTask(
243             [weak]() {
244                 auto pattern = weak.Upgrade();
245                 CHECK_NULL_VOID(pattern);
246                 ContainerScope scope(pattern->instanceId_);
247                 pattern->NotifyTransition();
248             }, "ArkUINotifyTransition");
249     });
250 }
251 
OnDetachFromFrameNode(FrameNode * frameNode)252 void MovingPhotoPattern::OnDetachFromFrameNode(FrameNode* frameNode)
253 {
254     auto id = frameNode->GetId();
255     auto pipeline = AceType::DynamicCast<PipelineContext>(PipelineBase::GetCurrentContext());
256     CHECK_NULL_VOID(pipeline);
257     pipeline->RemoveWindowStateChangedCallback(id);
258     hasVisibleChangeRegistered_ = false;
259 }
260 
OnDetachFromMainTree()261 void MovingPhotoPattern::OnDetachFromMainTree()
262 {
263     auto host = GetHost();
264     CHECK_NULL_VOID(host);
265     if (host->GetNodeStatus() == NodeStatus::BUILDER_NODE_OFF_MAINTREE) {
266         Stop();
267     }
268 }
269 
OnRebuildFrame()270 void MovingPhotoPattern::OnRebuildFrame()
271 {
272     if (!renderSurface_ || !renderSurface_->IsSurfaceValid()) {
273         return;
274     }
275     auto host = GetHost();
276     CHECK_NULL_VOID(host);
277     int32_t childCount = host->GetTotalChildCount();
278     CHECK_NULL_VOID(childCount >= 1);
279     auto movingPhotoNode = AceType::DynamicCast<MovingPhotoNode>(host);
280     CHECK_NULL_VOID(movingPhotoNode);
281     auto column = AceType::DynamicCast<FrameNode>(movingPhotoNode->GetColumn(childCount - 1));
282     CHECK_NULL_VOID(column);
283     auto columnRenderContext = column->GetRenderContext();
284     columnRenderContext->AddChild(columnRenderContext_, 0);
285     columnRenderContext->SetClipToBounds(true);
286     auto video = AceType::DynamicCast<FrameNode>(movingPhotoNode->GetVideo(childCount - 1));
287     CHECK_NULL_VOID(video);
288     auto renderContext = video->GetRenderContext();
289     renderContext->AddChild(renderContextForMediaPlayer_, 0);
290 }
291 
InitEvent()292 void MovingPhotoPattern::InitEvent()
293 {
294     auto host = GetHost();
295     CHECK_NULL_VOID(host);
296     auto gestureHub = host->GetOrCreateGestureEventHub();
297     CHECK_NULL_VOID(gestureHub);
298     if (longPressEvent_) {
299         if (isEnableAnalyzer_) {
300             gestureHub->SetLongPressEvent(nullptr);
301             longPressEvent_ = nullptr;
302         } else {
303             gestureHub->SetLongPressEvent(longPressEvent_, false, false, LONG_PRESS_DELAY);
304         }
305     }
306     if (!isEnableAnalyzer_) {
307         auto longPressCallback = [weak = WeakClaim(this)](GestureEvent& info) {
308             auto pattern = weak.Upgrade();
309             CHECK_NULL_VOID(pattern);
310             pattern->HandleLongPress(info);
311         };
312         longPressEvent_ = MakeRefPtr<LongPressEvent>(std::move(longPressCallback));
313         gestureHub->SetLongPressEvent(longPressEvent_, false, false, LONG_PRESS_DELAY);
314     }
315 
316     if (touchEvent_) {
317         gestureHub->AddTouchEvent(touchEvent_);
318         return;
319     }
320     auto touchTask = [weak = WeakClaim(this)](TouchEventInfo& info) {
321         auto pattern = weak.Upgrade();
322         CHECK_NULL_VOID(pattern);
323         pattern->HandleTouchEvent(info);
324     };
325     touchEvent_ = MakeRefPtr<TouchEventImpl>(std::move(touchTask));
326     gestureHub->AddTouchEvent(touchEvent_);
327 }
328 
LongPressEventModify(bool status)329 void MovingPhotoPattern::LongPressEventModify(bool status)
330 {
331     auto host = GetHost();
332     CHECK_NULL_VOID(host);
333     auto gestureHub = host->GetOrCreateGestureEventHub();
334     CHECK_NULL_VOID(gestureHub);
335     if (status) {
336         auto longPressCallback = [weak = WeakClaim(this)](GestureEvent& info) {
337             auto pattern = weak.Upgrade();
338             CHECK_NULL_VOID(pattern);
339             pattern->HandleLongPress(info);
340         };
341         longPressEvent_ = MakeRefPtr<LongPressEvent>(std::move(longPressCallback));
342         gestureHub->SetLongPressEvent(longPressEvent_, false, false, LONG_PRESS_DELAY);
343     } else {
344         gestureHub->SetLongPressEvent(nullptr);
345         longPressEvent_ = nullptr;
346     }
347 }
348 
HandleLongPress(GestureEvent & info)349 void MovingPhotoPattern::HandleLongPress(GestureEvent& info)
350 {
351     isFastKeyUp_ = false;
352     if (currentPlayStatus_ == PlaybackStatus::STARTED || !isPrepared_ || isPlayByController_) {
353         return;
354     }
355     if (autoAndRepeatLevel_ == PlaybackMode::NONE && isEnableAnalyzer_) {
356         TAG_LOGW(AceLogTag::ACE_MOVING_PHOTO, "HandleLongPress isEnableAnalyzer_ return.");
357         return;
358     }
359     if (isRefreshMovingPhoto_) {
360         if (autoAndRepeatLevel_ == PlaybackMode::REPEAT) {
361             TAG_LOGW(AceLogTag::ACE_MOVING_PHOTO, "HandleLongPress IsRefreshMovingPhotoReturn:%{public}d.",
362                 isRefreshMovingPhoto_);
363             return;
364         }
365         isRefreshMovingPhotoPlaying_ = true;
366     } else {
367         if (autoAndRepeatLevel_ != PlaybackMode::NONE) {
368             TAG_LOGW(AceLogTag::ACE_MOVING_PHOTO, "HandleLongPress IsRefreshMovingPhotoReturn not:%{public}d.",
369                 isRefreshMovingPhoto_);
370             return;
371         }
372     }
373     TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "movingphoto HandleLongPress start.");
374     if (!mediaPlayer_ || !mediaPlayer_->IsMediaPlayerValid()) {
375         TAG_LOGW(AceLogTag::ACE_MOVING_PHOTO, "MediaPlayer is null or invalid.");
376         FireMediaPlayerError();
377         return;
378     }
379     if (currentPlayStatus_ == PlaybackStatus::STOPPED) {
380         mediaPlayer_->PrepareAsync();
381     }
382     if (currentPlayStatus_ == PlaybackStatus::PLAYBACK_COMPLETE || currentPlayStatus_ == PlaybackStatus::PAUSED) {
383         int32_t duration = DURATION_FLAG;
384         mediaPlayer_->GetDuration(duration);
385         SetAutoPlayPeriod(PERIOD_START, duration * US_CONVERT);
386     }
387     isGestureTriggeredLongPress_ = true;
388     Start();
389 }
390 
HandleTouchEvent(TouchEventInfo & info)391 void MovingPhotoPattern::HandleTouchEvent(TouchEventInfo& info)
392 {
393     if (currentPlayStatus_ == PlaybackStatus::ERROR) {
394         ResetMediaPlayer();
395     }
396     if (IsRefreshMovingPhotoReturn(isRefreshMovingPhotoPlaying_)) {
397         TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "HandleTouchEvent IsRefreshMovingPhotoReturn.");
398         return;
399     }
400     if (!isPrepared_ || isPlayByController_) {
401         return;
402     }
403     if (autoAndRepeatLevel_ == PlaybackMode::NONE && isEnableAnalyzer_ && isAnalyzerPlaying_) {
404         TAG_LOGW(AceLogTag::ACE_MOVING_PHOTO, "HandleTouchEvent isEnableAnalyzer_ return.");
405         return;
406     }
407     auto touchList = info.GetChangedTouches();
408     CHECK_NULL_VOID(!touchList.empty());
409     auto touchInfo = touchList.front();
410     auto touchType = touchInfo.GetTouchType();
411     isFastKeyUp_ = false;
412     if (touchType == TouchType::UP || touchType == TouchType::CANCEL) {
413         if (currentPlayStatus_ == PlaybackStatus::STARTED) {
414             PausePlayback();
415         } else if (currentPlayStatus_ == PlaybackStatus::PLAYBACK_COMPLETE) {
416             currentPlayStatus_ = PlaybackStatus::NONE;
417             StopAnimation();
418         } else {
419             isFastKeyUp_ = true;
420         }
421     }
422 }
423 
UpdateImageNode()424 void MovingPhotoPattern::UpdateImageNode()
425 {
426     TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "UpdateImageNode start.%{public}d", movingPhotoFormat_);
427     if (startAnimationFlag_) {
428         needUpdateImageNode_ = true;
429         return;
430     }
431     auto host = GetHost();
432     CHECK_NULL_VOID(host);
433     auto movingPhoto = AceType::DynamicCast<MovingPhotoNode>(host);
434     CHECK_NULL_VOID(movingPhoto);
435     auto image = AceType::DynamicCast<FrameNode>(movingPhoto->GetImage());
436     CHECK_NULL_VOID(image);
437     UpdateImageHdrMode(image);
438     auto imagePattern = image->GetPattern<ImagePattern>();
439     CHECK_NULL_VOID(imagePattern);
440     imagePattern->SetOrientation(ImageRotateOrientation::AUTO);
441     TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "movingphoto set HDR.%{public}d", dynamicRangeMode_);
442     auto layoutProperty = GetLayoutProperty<MovingPhotoLayoutProperty>();
443     CHECK_NULL_VOID(layoutProperty);
444     auto imageLayoutProperty = image->GetLayoutProperty<ImageLayoutProperty>();
445     CHECK_NULL_VOID(imageLayoutProperty);
446     if (!layoutProperty->HasImageSourceInfo()) {
447         TAG_LOGW(AceLogTag::ACE_MOVING_PHOTO, "image info is null.");
448         imageLayoutProperty->UpdateVisibility(VisibleType::INVISIBLE);
449         image->MarkModifyDone();
450         return;
451     }
452     auto imageSourceInfo = layoutProperty->GetImageSourceInfo().value();
453     auto imageFit = layoutProperty->GetObjectFitValue(ImageFit::COVER);
454     if (!imageSourceInfo.IsValid()) {
455         TAG_LOGW(AceLogTag::ACE_MOVING_PHOTO, "image info is invalid.");
456         imageLayoutProperty->UpdateVisibility(VisibleType::INVISIBLE);
457         image->MarkModifyDone();
458         return;
459     }
460     if (image) {
461         image->SetDraggable(false);
462         imageLayoutProperty->UpdateVisibility(VisibleType::VISIBLE);
463         imageLayoutProperty->UpdateImageSourceInfo(imageSourceInfo);
464         MovingPhotoFormatConvert(movingPhotoFormat_);
465         imagePattern->SetExternalDecodeFormat(imageFormat_);
466         imageLayoutProperty->UpdateImageFit(imageFit);
467         image->MarkModifyDone();
468     }
469     RegisterImageEvent(image);
470 }
471 
UpdateTempImageNode(const ImageSourceInfo & imageSourceInfo)472 void MovingPhotoPattern::UpdateTempImageNode(const ImageSourceInfo& imageSourceInfo)
473 {
474     TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "UpdateTempImageNode start.%{public}d", movingPhotoFormat_);
475     if (startAnimationFlag_) {
476         needUpdateImageNode_ = true;
477         return;
478     }
479     auto image = GetTempNode();
480     CHECK_NULL_VOID(image);
481     UpdateImageHdrMode(image);
482     auto imagePattern = image->GetPattern<ImagePattern>();
483     CHECK_NULL_VOID(imagePattern);
484     imagePattern->SetOrientation(ImageRotateOrientation::AUTO);
485     TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "UpdateTempImageNode set HDR.%{public}d", dynamicRangeMode_);
486     auto layoutProperty = GetLayoutProperty<MovingPhotoLayoutProperty>();
487     CHECK_NULL_VOID(layoutProperty);
488     auto imageLayoutProperty = image->GetLayoutProperty<ImageLayoutProperty>();
489     CHECK_NULL_VOID(imageLayoutProperty);
490     if (!layoutProperty->HasImageSourceInfo()) {
491         TAG_LOGW(AceLogTag::ACE_MOVING_PHOTO, "UpdateTempImageNode imageInfo is null.");
492         imageLayoutProperty->UpdateVisibility(VisibleType::INVISIBLE);
493         image->MarkModifyDone();
494         return;
495     }
496     auto imageFit = layoutProperty->GetObjectFitValue(ImageFit::COVER);
497     if (!imageSourceInfo.IsValid()) {
498         TAG_LOGW(AceLogTag::ACE_MOVING_PHOTO, "UpdateTempImageNode imageInfo is invalid.");
499         imageLayoutProperty->UpdateVisibility(VisibleType::INVISIBLE);
500         image->MarkModifyDone();
501         return;
502     }
503     if (image) {
504         image->SetDraggable(false);
505         imageLayoutProperty->UpdateVisibility(VisibleType::VISIBLE);
506         imageLayoutProperty->UpdateImageSourceInfo(imageSourceInfo);
507         MovingPhotoFormatConvert(movingPhotoFormat_);
508         imagePattern->SetExternalDecodeFormat(imageFormat_);
509         imageLayoutProperty->UpdateImageFit(imageFit);
510         image->MarkModifyDone();
511     }
512     RegisterImageEvent(image);
513 }
514 
UpdateImageHdrMode(const RefPtr<FrameNode> & imageNode)515 void MovingPhotoPattern::UpdateImageHdrMode(const RefPtr<FrameNode>& imageNode)
516 {
517     DynamicRangeModeConvert(dynamicRangeMode_);
518     ACE_UPDATE_NODE_PAINT_PROPERTY(ImageRenderProperty, DynamicMode, dynamicRangeMode_, imageNode);
519     ACE_UPDATE_NODE_RENDER_CONTEXT(DynamicRangeMode, dynamicRangeMode_, imageNode);
520     if (dynamicRangeMode_ == DynamicRangeMode::STANDARD) {
521         ACE_RESET_NODE_PAINT_PROPERTY(ImageRenderProperty, DynamicMode, imageNode);
522         ACE_RESET_NODE_RENDER_CONTEXT(RenderContext, DynamicRangeMode, imageNode);
523     }
524 }
525 
MovingPhotoFormatConvert(MovingPhotoFormat format)526 void MovingPhotoPattern::MovingPhotoFormatConvert(MovingPhotoFormat format)
527 {
528     TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "MovingPhotoFormatConvert %{public}d.", format);
529     switch (format) {
530         case MovingPhotoFormat::RGBA_8888:
531             imageFormat_ = PixelFormat::RGBA_8888;
532             break;
533         case MovingPhotoFormat::NV21:
534             imageFormat_ = PixelFormat::NV21;
535             break;
536         case MovingPhotoFormat::RGBA_1010102:
537             imageFormat_ = PixelFormat::RGBA_1010102;
538             break;
539         case MovingPhotoFormat::YCBCR_P010:
540             imageFormat_ = PixelFormat::YCBCR_P010;
541             break;
542         case MovingPhotoFormat::YCRCB_P010:
543             imageFormat_ = PixelFormat::YCRCB_P010;
544             break;
545         default:
546             imageFormat_ = PixelFormat::UNKNOWN;
547             break;
548     }
549 }
550 
DynamicRangeModeConvert(DynamicRangeMode rangeMode)551 void MovingPhotoPattern::DynamicRangeModeConvert(DynamicRangeMode rangeMode)
552 {
553     switch (rangeMode) {
554         case DynamicRangeMode::HIGH:
555             dynamicRangeMode_ = DynamicRangeMode::HIGH;
556             break;
557         case DynamicRangeMode::CONSTRAINT:
558             dynamicRangeMode_ = DynamicRangeMode::CONSTRAINT;
559             break;
560         case DynamicRangeMode::STANDARD:
561             dynamicRangeMode_ = DynamicRangeMode::STANDARD;
562             break;
563         default:
564             dynamicRangeMode_ = DynamicRangeMode::HIGH;
565             break;
566     }
567     TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "DynamicRangeModeConvert %{public}d.", rangeMode);
568 }
569 
RegisterImageEvent(const RefPtr<FrameNode> & imageNode)570 void MovingPhotoPattern::RegisterImageEvent(const RefPtr<FrameNode>& imageNode)
571 {
572     TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "MovingPhoto RegisterImageEvent start.");
573     CHECK_NULL_VOID(imageNode);
574     auto imageHub = imageNode->GetOrCreateEventHub<ImageEventHub>();
575     CHECK_NULL_VOID(imageHub);
576     auto imageCompleteEventCallback = [weak = WeakClaim(this)](const LoadImageSuccessEvent& info) {
577         auto pattern = weak.Upgrade();
578         CHECK_NULL_VOID(pattern);
579         pattern->HandleImageCompleteEvent(info);
580     };
581     imageHub->SetOnComplete(imageCompleteEventCallback);
582 }
583 
HandleImageCompleteEvent(const LoadImageSuccessEvent & info)584 void MovingPhotoPattern::HandleImageCompleteEvent(const LoadImageSuccessEvent& info)
585 {
586     auto loadingStatus = info.GetLoadingStatus();
587     TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "HandleImageCompleteEvent start:%{public}d.", loadingStatus);
588     if (loadingStatus == IMAGE_DECODE_COMPLETE) {
589         FireMediaPlayerImageComplete();
590         if (notifyTransitionFlag_) {
591             TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "HandleImageCompleteEvent EightyToHundredAnimation.");
592             EightyToHundredAnimation();
593         }
594     }
595 }
596 
UpdateVideoNode()597 void MovingPhotoPattern::UpdateVideoNode()
598 {
599     ContainerScope scope(instanceId_);
600     auto pipelineContext = PipelineContext::GetCurrentContext();
601     CHECK_NULL_VOID(pipelineContext);
602     auto uiTaskExecutor = SingleTaskExecutor::Make(pipelineContext->GetTaskExecutor(), TaskExecutor::TaskType::UI);
603     uiTaskExecutor.PostTask(
604         [weak = WeakClaim(this)]() {
605             auto movingPhotoPattern = weak.Upgrade();
606             CHECK_NULL_VOID(movingPhotoPattern);
607             ContainerScope scope(movingPhotoPattern->instanceId_);
608             movingPhotoPattern->PrepareMediaPlayer();
609             movingPhotoPattern->UpdateMediaPlayerSpeed();
610             movingPhotoPattern->UpdateMediaPlayerMuted();
611         },
612         "ArkUIMovingPhotoUpdateVideo");
613 }
614 
PrepareMediaPlayer()615 void MovingPhotoPattern::PrepareMediaPlayer()
616 {
617     auto layoutProperty = GetLayoutProperty<MovingPhotoLayoutProperty>();
618     CHECK_NULL_VOID(layoutProperty);
619     if (!layoutProperty->HasMovingPhotoUri() || !layoutProperty->HasVideoSource()) {
620         TAG_LOGW(AceLogTag::ACE_MOVING_PHOTO, "MovingPhoto source is null.");
621         return;
622     }
623     if (layoutProperty->GetMovingPhotoUri().value() == uri_ &&
624         layoutProperty->GetVideoSource().value() == fd_.GetValue()) {
625         TAG_LOGW(AceLogTag::ACE_MOVING_PHOTO, "MediaPlayer source has not changed.");
626         return;
627     }
628     uri_ = layoutProperty->GetMovingPhotoUri().value();
629     fd_ = layoutProperty->GetVideoSource().value();
630     if (!mediaPlayer_) {
631         TAG_LOGW(AceLogTag::ACE_MOVING_PHOTO, "MediaPlayer is null.");
632         FireMediaPlayerError();
633         return;
634     }
635     if (!mediaPlayer_->IsMediaPlayerValid()) {
636         mediaPlayer_->CreateMediaPlayer();
637     }
638     if (!mediaPlayer_->IsMediaPlayerValid()) {
639         TAG_LOGW(AceLogTag::ACE_MOVING_PHOTO, "MediaPlayer is invalid.");
640         FireMediaPlayerError();
641         return;
642     }
643     ContainerScope scope(instanceId_);
644     auto context = PipelineContext::GetCurrentContext();
645     CHECK_NULL_VOID(context);
646     auto uiTaskExecutor = SingleTaskExecutor::Make(context->GetTaskExecutor(), TaskExecutor::TaskType::UI);
647     uiTaskExecutor.PostTask(
648         [weak = WeakClaim(this)] {
649             auto movingPhotoPattern = weak.Upgrade();
650             CHECK_NULL_VOID(movingPhotoPattern);
651             movingPhotoPattern->ResetMediaPlayer();
652         },
653         "ArkUIMovingPhotoPrepare");
654 }
655 
ResetMediaPlayer()656 void MovingPhotoPattern::ResetMediaPlayer()
657 {
658     CHECK_NULL_VOID(mediaPlayer_);
659     isPrepared_ = false;
660     isStopAnimation_ = false;
661     ContainerScope scope(instanceId_);
662     auto context = PipelineContext::GetCurrentContext();
663     CHECK_NULL_VOID(context);
664     if (isRefreshMovingPhoto_ && isUsedMediaPlayerStatusChanged_) {
665         TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "ArkUIMovingPhotoResetMediaPlayerAsync.");
666         auto bgTaskExecutor = SingleTaskExecutor::Make(context->GetTaskExecutor(), TaskExecutor::TaskType::BACKGROUND);
667         bgTaskExecutor.PostTask(
668             [weak = WeakClaim(RawPtr(mediaPlayer_)), fd = fd_] {
669                 auto mediaPlayer = weak.Upgrade();
670                 CHECK_NULL_VOID(mediaPlayer);
671                 mediaPlayer->ResetMediaPlayer();
672                 if (!mediaPlayer->SetSourceByFd(fd.GetValue())) {
673                     TAG_LOGW(AceLogTag::ACE_MOVING_PHOTO, "set source for MediaPlayer Async failed.");
674                 }
675             },
676             "ArkUIMovingPhotoResetMediaPlayerAsync");
677     } else {
678         mediaPlayer_->ResetMediaPlayer();
679         RegisterMediaPlayerEvent();
680         if (!mediaPlayer_->SetSourceByFd(fd_.GetValue())) {
681             TAG_LOGW(AceLogTag::ACE_MOVING_PHOTO, "set source for MediaPlayer failed.");
682             auto uiTaskExecutor = SingleTaskExecutor::Make(context->GetTaskExecutor(), TaskExecutor::TaskType::UI);
683             uiTaskExecutor.PostTask(
684                 [weak = WeakClaim(this)] {
685                     auto pattern = weak.Upgrade();
686                     CHECK_NULL_VOID(pattern);
687                     ContainerScope scope(pattern->instanceId_);
688                     pattern->FireMediaPlayerError();
689                 },
690                 "ArkUIMovingPhotoResetMediaPlayer");
691         }
692     }
693 }
694 
RegisterMediaPlayerEvent()695 void MovingPhotoPattern::RegisterMediaPlayerEvent()
696 {
697     if (fd_.GetValue() == -1 || !mediaPlayer_) {
698         return;
699     }
700     ContainerScope scope(instanceId_);
701     auto context = PipelineContext::GetCurrentContext();
702     CHECK_NULL_VOID(context);
703     auto uiTaskExecutor = SingleTaskExecutor::Make(context->GetTaskExecutor(), TaskExecutor::TaskType::UI);
704     auto movingPhotoPattern = WeakClaim(this);
705 
706     auto&& positionUpdatedEvent = [movingPhotoPattern, uiTaskExecutor](uint32_t currentPos) {
707         uiTaskExecutor.PostTask([movingPhotoPattern, currentPos] {
708             auto movingPhoto = movingPhotoPattern.Upgrade();
709             CHECK_NULL_VOID(movingPhoto);
710             ContainerScope scope(movingPhoto->instanceId_);
711             movingPhoto->OnPlayPositionChanged(currentPos);
712         }, "ArkUIMovingPhotoPositionChanged");
713     };
714 
715     auto&& stateChangedEvent = [movingPhotoPattern, uiTaskExecutor](PlaybackStatus status) {
716         uiTaskExecutor.PostTask([movingPhotoPattern, status] {
717             auto movingPhoto = movingPhotoPattern.Upgrade();
718             CHECK_NULL_VOID(movingPhoto);
719             ContainerScope scope(movingPhoto->instanceId_);
720             movingPhoto->OnMediaPlayerStatusChanged(status);
721         }, "ArkUIMovingPhotoStatusChanged");
722     };
723 
724     auto&& errorEvent = [movingPhotoPattern, uiTaskExecutor]() {
725         uiTaskExecutor.PostSyncTask([movingPhotoPattern] {
726             auto movingPhoto = movingPhotoPattern.Upgrade();
727             CHECK_NULL_VOID(movingPhoto);
728             ContainerScope scope(movingPhoto->instanceId_);
729             movingPhoto->FireMediaPlayerError();
730         }, "ArkUIMovingPhotoOnError");
731     };
732 
733     auto&& resolutionChangeEvent = [movingPhotoPattern, uiTaskExecutor]() {
734         uiTaskExecutor.PostTask([movingPhotoPattern] {
735             auto movingPhoto = movingPhotoPattern.Upgrade();
736             CHECK_NULL_VOID(movingPhoto);
737             ContainerScope scope(movingPhoto->instanceId_);
738             movingPhoto->OnResolutionChange();
739         }, "ArkUIMovingPhotoResolutionChanged");
740     };
741 
742     auto&& startRenderFrameEvent = [movingPhotoPattern, uiTaskExecutor]() {
743         uiTaskExecutor.PostTask([movingPhotoPattern] {
744             auto movingPhoto = movingPhotoPattern.Upgrade();
745             CHECK_NULL_VOID(movingPhoto);
746             ContainerScope scope(movingPhoto->instanceId_);
747             movingPhoto->OnStartRenderFrame();
748         }, "ArkUIMovingPhotoStartRender");
749     };
750 
751     mediaPlayer_->RegisterMediaPlayerEvent(
752         positionUpdatedEvent, stateChangedEvent, errorEvent, resolutionChangeEvent, startRenderFrameEvent);
753 }
754 
PrepareSurface()755 void MovingPhotoPattern::PrepareSurface()
756 {
757     if (!mediaPlayer_ || renderSurface_->IsSurfaceValid()) {
758         return;
759     }
760     if (!SystemProperties::GetExtSurfaceEnabled()) {
761         renderSurface_->SetRenderContext(renderContextForMediaPlayer_);
762     }
763     renderSurface_->InitSurface();
764     mediaPlayer_->SetRenderSurface(renderSurface_);
765     if (mediaPlayer_->SetSurface() != 0) {
766         TAG_LOGW(AceLogTag::ACE_MOVING_PHOTO, "prepare MediaPlayer failed.");
767     }
768 }
769 
UpdatePlayMode()770 void MovingPhotoPattern::UpdatePlayMode()
771 {
772     TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "movingphoto UpdatePlayMode.%{public}d", isChangePlayMode_);
773     if (isChangePlayMode_) {
774         if (historyAutoAndRepeatLevel_ == PlaybackMode::AUTO) {
775             SetAutoPlayPeriod(autoPlayPeriodStartTime_, autoPlayPeriodEndTime_);
776         }
777         MediaResetToPlay();
778         isChangePlayMode_ = false;
779     }
780 }
781 
HandleImageAnalyzerMode()782 void MovingPhotoPattern::HandleImageAnalyzerMode()
783 {
784     TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "movingphoto HandleImageAnalyzerMode.");
785     if (isEnableAnalyzer_ && autoAndRepeatLevel_ == PlaybackMode::NONE) {
786         if (!imageAnalyzerManager_) {
787             EnableAnalyzer(isEnableAnalyzer_);
788         }
789         if (imageAnalyzerManager_ && !GetAnalyzerState()) {
790             StartImageAnalyzer();
791         }
792     }
793     if (!isEnableAnalyzer_ && IsSupportImageAnalyzer() && imageAnalyzerManager_) {
794         DestroyAnalyzerOverlay();
795         LongPressEventModify(true);
796     }
797 }
798 
MediaResetToPlay()799 void MovingPhotoPattern::MediaResetToPlay()
800 {
801     autoAndRepeatLevel_ = historyAutoAndRepeatLevel_;
802     if (currentPlayStatus_ == PlaybackStatus::STOPPED) {
803         mediaPlayer_->PrepareAsync();
804     } else if (currentPlayStatus_ == PlaybackStatus::PLAYBACK_COMPLETE ||
805         currentPlayStatus_ == PlaybackStatus::PAUSED ||
806         currentPlayStatus_ == PlaybackStatus::PREPARED) {
807             SelectPlaybackMode(historyAutoAndRepeatLevel_);
808     }
809 }
810 
FireMediaPlayerImageComplete()811 void MovingPhotoPattern::FireMediaPlayerImageComplete()
812 {
813     auto eventHub = GetOrCreateEventHub<MovingPhotoEventHub>();
814     CHECK_NULL_VOID(eventHub);
815     eventHub->FireCompleteEvent();
816 }
817 
FireMediaPlayerStart()818 void MovingPhotoPattern::FireMediaPlayerStart()
819 {
820     auto eventHub = GetOrCreateEventHub<MovingPhotoEventHub>();
821     CHECK_NULL_VOID(eventHub);
822     eventHub->FireStartEvent();
823     if (isFastKeyUp_) {
824         isFastKeyUp_ = false;
825         PausePlayback();
826     }
827 }
828 
FireMediaPlayerStop()829 void MovingPhotoPattern::FireMediaPlayerStop()
830 {
831     auto eventHub = GetOrCreateEventHub<MovingPhotoEventHub>();
832     CHECK_NULL_VOID(eventHub);
833     eventHub->FireStopEvent();
834 }
835 
FireMediaPlayerPause()836 void MovingPhotoPattern::FireMediaPlayerPause()
837 {
838     auto eventHub = GetOrCreateEventHub<MovingPhotoEventHub>();
839     CHECK_NULL_VOID(eventHub);
840     eventHub->FirePauseEvent();
841 }
842 
FireMediaPlayerFinish()843 void MovingPhotoPattern::FireMediaPlayerFinish()
844 {
845     auto eventHub = GetOrCreateEventHub<MovingPhotoEventHub>();
846     CHECK_NULL_VOID(eventHub);
847     eventHub->FireFinishEvent();
848 }
849 
FireMediaPlayerError()850 void MovingPhotoPattern::FireMediaPlayerError()
851 {
852     auto eventHub = GetOrCreateEventHub<MovingPhotoEventHub>();
853     CHECK_NULL_VOID(eventHub);
854     eventHub->FireErrorEvent();
855 }
856 
FireMediaPlayerPrepared()857 void MovingPhotoPattern::FireMediaPlayerPrepared()
858 {
859     auto eventHub = GetOrCreateEventHub<MovingPhotoEventHub>();
860     CHECK_NULL_VOID(eventHub);
861     eventHub->FirePreparedEvent();
862 }
863 
OnResolutionChange()864 void MovingPhotoPattern::OnResolutionChange()
865 {
866     if (!mediaPlayer_ || !mediaPlayer_->IsMediaPlayerValid()) {
867         TAG_LOGW(AceLogTag::ACE_MOVING_PHOTO, "MediaPlayer is null or invalid.");
868         return;
869     }
870     auto host = GetHost();
871     CHECK_NULL_VOID(host);
872     SizeF videoSize =
873         SizeF(static_cast<float>(mediaPlayer_->GetVideoWidth()), static_cast<float>(mediaPlayer_->GetVideoHeight()));
874     auto movingPhotoLayoutProperty = host->GetLayoutProperty<MovingPhotoLayoutProperty>();
875     CHECK_NULL_VOID(movingPhotoLayoutProperty);
876     movingPhotoLayoutProperty->UpdateVideoSize(videoSize);
877     host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
878 }
879 
OnStartRenderFrame()880 void MovingPhotoPattern::OnStartRenderFrame()
881 {
882     TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "MediaPlayer OnStartRenderFrame.");
883 }
884 
OnStartedStatusCallback()885 void MovingPhotoPattern::OnStartedStatusCallback()
886 {
887     TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "MediaPlayer OnStartedStatusCallback.");
888     ACE_FUNCTION_TRACE();
889     auto host = GetHost();
890     CHECK_NULL_VOID(host);
891     auto movingPhoto = AceType::DynamicCast<MovingPhotoNode>(host);
892     CHECK_NULL_VOID(movingPhoto);
893     auto image = AceType::DynamicCast<FrameNode>(movingPhoto->GetImage());
894     CHECK_NULL_VOID(image);
895     if (isStopAnimation_) {
896         TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "MediaPlayer OnStartedStatusCallback stop startAnimation.");
897         isStopAnimation_ = false;
898         return;
899     }
900     StartAnimation();
901 }
902 
OnDirtyLayoutWrapperSwap(const RefPtr<LayoutWrapper> & dirty,const DirtySwapConfig & config)903 bool MovingPhotoPattern::OnDirtyLayoutWrapperSwap(const RefPtr<LayoutWrapper>& dirty, const DirtySwapConfig& config)
904 {
905     TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "OnDirtyLayoutWrapperSwap.");
906     if (config.skipMeasure || dirty->SkipMeasureContent()) {
907         return false;
908     }
909     auto geometryNode = dirty->GetGeometryNode();
910     CHECK_NULL_RETURN(geometryNode, false);
911     auto movingPhotoNodeSize = geometryNode->GetContentSize();
912     auto layoutProperty = GetLayoutProperty<MovingPhotoLayoutProperty>();
913     CHECK_NULL_RETURN(layoutProperty, false);
914     SizeF videoFrameSize;
915     if (isXmageMode_) {
916         videoFrameSize = MeasureModeContentLayout(movingPhotoNodeSize, layoutProperty);
917     } else {
918         videoFrameSize = MeasureContentLayout(movingPhotoNodeSize, layoutProperty);
919     }
920     if (xmageModeValue_ != ROUND_XMAGE_MODE_VALUE) {
921         SetRenderContextBoundsInXmage(movingPhotoNodeSize, videoFrameSize);
922     } else {
923         SetRenderContextBounds(movingPhotoNodeSize, videoFrameSize);
924     }
925 
926     if (IsSupportImageAnalyzer() && isEnableAnalyzer_ && autoAndRepeatLevel_ == PlaybackMode::NONE) {
927         if (imageAnalyzerManager_ && !GetAnalyzerState()) {
928             StartImageAnalyzer();
929         } else {
930             UpdateAnalyzerUIConfig(geometryNode);
931         }
932     }
933     if (imageAnalyzerManager_ && !isEnableAnalyzer_) {
934         DestroyAnalyzerOverlay();
935         LongPressEventModify(true);
936     }
937 
938     auto host = GetHost();
939     CHECK_NULL_RETURN(host, false);
940     host->MarkNeedSyncRenderTree();
941     auto movingPhoto = AceType::DynamicCast<MovingPhotoNode>(host);
942     CHECK_NULL_RETURN(movingPhoto, false);
943     int32_t childCount = movingPhoto->GetTotalChildCount();
944     CHECK_NULL_RETURN(childCount >= 1, false);
945     auto video = AceType::DynamicCast<FrameNode>(movingPhoto->GetVideo(childCount - 1));
946     CHECK_NULL_RETURN(video, false);
947     video->GetRenderContext()->SetClipToBounds(true);
948     if (currentPlayStatus_ != PlaybackStatus::STARTED) {
949         video->GetRenderContext()->UpdateOpacity(0.0);
950     }
951     return false;
952 }
953 
SetRenderContextBounds(const SizeF & movingPhotoNodeSize,const SizeF & videoFrameSize)954 void MovingPhotoPattern::SetRenderContextBounds(const SizeF& movingPhotoNodeSize, const SizeF& videoFrameSize)
955 {
956     auto layoutProperty = GetLayoutProperty<MovingPhotoLayoutProperty>();
957     CHECK_NULL_VOID(layoutProperty);
958     float xmageHeight = 0;
959     float ratio = 0;
960     if (layoutProperty->HasXmageHeight()) {
961         xmageHeight = layoutProperty->GetXmageHeight().value();
962         ratio = CalculateRatio(movingPhotoNodeSize);
963     }
964     if (columnRenderContext_) {
965         columnRenderContext_->SetBounds((movingPhotoNodeSize.Width() - videoFrameSize.Width()) / HALF,
966             (movingPhotoNodeSize.Height() - videoFrameSize.Height()) / HALF,
967             videoFrameSize.Width(), videoFrameSize.Height());
968     }
969     if (renderContextForMediaPlayer_) {
970         renderContextForMediaPlayer_->SetBounds((movingPhotoNodeSize.Width() - videoFrameSize.Width()) / HALF,
971             (movingPhotoNodeSize.Height() - videoFrameSize.Height()) / HALF,
972             videoFrameSize.Width(), videoFrameSize.Height());
973     }
974 }
975 
SetRenderContextBoundsInXmage(const SizeF & movingPhotoNodeSize,const SizeF & videoFrameSize)976 void MovingPhotoPattern::SetRenderContextBoundsInXmage(
977     const SizeF& movingPhotoNodeSize, const SizeF& videoFrameSize)
978 {
979     auto layoutProperty = GetLayoutProperty<MovingPhotoLayoutProperty>();
980     CHECK_NULL_VOID(layoutProperty);
981     auto host = GetHost();
982     CHECK_NULL_VOID(host);
983     auto pattern = DynamicCast<MovingPhotoPattern>(host->GetPattern());
984     CHECK_NULL_VOID(pattern);
985     SizeF xmageOffset = SizeF(0, 0);
986     SizeF imageSize = SizeF(0, 0);
987     SizeF xmageOffsetRatio = SizeF(0, 0);
988     if (layoutProperty->HasXmageOffset()) {
989         xmageOffset = layoutProperty->GetXmageOffset().value();
990     }
991     if (layoutProperty->HasImageSize()) {
992         imageSize = layoutProperty->GetImageSize().value();
993         xmageOffsetRatio = pattern->CalculateXmageOffsetRatio(movingPhotoNodeSize);
994     }
995 
996     if (columnRenderContext_) {
997         columnRenderContext_->SetBounds(0, 0, imageSize.Width() * xmageOffsetRatio.Width() + ROUND_XMAGE_PIXEL_GAP,
998             imageSize.Height() * xmageOffsetRatio.Height() + ROUND_XMAGE_PIXEL_GAP);
999     }
1000     if (renderContextForMediaPlayer_) {
1001         renderContextForMediaPlayer_->SetBounds(0, 0,
1002             imageSize.Width() * xmageOffsetRatio.Width() + ROUND_XMAGE_PIXEL_GAP,
1003             imageSize.Height() * xmageOffsetRatio.Height() + ROUND_XMAGE_PIXEL_GAP);
1004     }
1005 }
1006 
CalculateFitContain(const SizeF & rawSize,const SizeF & layoutSize)1007 SizeF MovingPhotoPattern::CalculateFitContain(const SizeF& rawSize, const SizeF& layoutSize)
1008 {
1009     if (NearZero(rawSize.Height()) || NearZero(rawSize.Width()) || NearZero(layoutSize.Height())) {
1010         return layoutSize;
1011     }
1012     double sourceRatio = rawSize.Width() / rawSize.Height();
1013     double layoutRatio = layoutSize.Width() / layoutSize.Height();
1014     if (sourceRatio < layoutRatio) {
1015         float ratio = layoutSize.Height() / rawSize.Height();
1016         return { rawSize.Width() * ratio, layoutSize.Height() };
1017     } else {
1018         float ratio = layoutSize.Width() / rawSize.Width();
1019         return { layoutSize.Width(), rawSize.Height() * ratio };
1020     }
1021 }
1022 
CalculateFitFill(const SizeF & layoutSize)1023 SizeF MovingPhotoPattern::CalculateFitFill(const SizeF& layoutSize)
1024 {
1025     return layoutSize;
1026 }
1027 
CalculateFitCover(const SizeF & rawSize,const SizeF & layoutSize)1028 SizeF MovingPhotoPattern::CalculateFitCover(const SizeF& rawSize, const SizeF& layoutSize)
1029 {
1030     if (NearZero(rawSize.Height()) || NearZero(rawSize.Width()) || NearZero(layoutSize.Height())) {
1031         return layoutSize;
1032     }
1033     double sourceRatio = rawSize.Width() / rawSize.Height();
1034     double layoutRatio = layoutSize.Width() / layoutSize.Height();
1035     float ratio = 1.0;
1036     if (sourceRatio < layoutRatio) {
1037         ratio = static_cast<float>(layoutSize.Width() / rawSize.Width());
1038     } else {
1039         ratio = static_cast<float>(layoutSize.Height() / rawSize.Height());
1040     }
1041     return { rawSize.Width() * ratio, rawSize.Height() * ratio };
1042 }
1043 
CalculateFitNone(const SizeF & rawSize)1044 SizeF MovingPhotoPattern::CalculateFitNone(const SizeF& rawSize)
1045 {
1046     return rawSize;
1047 }
1048 
CalculateFitScaleDown(const SizeF & rawSize,const SizeF & layoutSize)1049 SizeF MovingPhotoPattern::CalculateFitScaleDown(const SizeF& rawSize, const SizeF& layoutSize)
1050 {
1051     if ((rawSize.Width() <= layoutSize.Width()) && (rawSize.Height() <= layoutSize.Height())) {
1052         return CalculateFitNone(rawSize);
1053     } else {
1054         return CalculateFitContain(rawSize, layoutSize);
1055     }
1056 }
1057 
CalculateFitAuto(const SizeF & rawSize,const SizeF & layoutSize)1058 SizeF MovingPhotoPattern::CalculateFitAuto(const SizeF& rawSize, const SizeF& layoutSize)
1059 {
1060     if (NearZero(rawSize.Width()) || NearZero(rawSize.Height())) {
1061         return layoutSize;
1062     }
1063     if ((rawSize.Width() <= layoutSize.Width()) && (rawSize.Height() <= layoutSize.Height())) {
1064         double widthRatio = layoutSize.Width() / rawSize.Width();
1065         double heightRatio = layoutSize.Height() / rawSize.Height();
1066         float ratio = static_cast<float>(std::min(widthRatio, heightRatio));
1067         return { rawSize.Width() * ratio, rawSize.Height() * ratio };
1068     } else if ((rawSize.Width() > layoutSize.Width()) && (rawSize.Height() <= layoutSize.Height())) {
1069         return CalculateFitContain(rawSize, layoutSize);
1070     } else {
1071         return CalculateFitCover(rawSize, layoutSize);
1072     }
1073 }
1074 
CalculateModeFitContain(const SizeF & rawSize,const SizeF & layoutSize)1075 SizeF MovingPhotoPattern::CalculateModeFitContain(const SizeF& rawSize, const SizeF& layoutSize)
1076 {
1077     if (NearZero(rawSize.Height()) || NearZero(rawSize.Width()) || NearZero(layoutSize.Height())) {
1078         return layoutSize;
1079     }
1080     double sourceRatio = rawSize.Width() / rawSize.Height();
1081     double layoutRatio = layoutSize.Width() / layoutSize.Height();
1082     if (sourceRatio < layoutRatio) {
1083         float ratio = layoutSize.Height() / rawSize.Height();
1084         return { rawSize.Width() * ratio, layoutSize.Height() };
1085     } else {
1086         float ratio = layoutSize.Width() / rawSize.Width();
1087         return { layoutSize.Width(), rawSize.Height() * ratio };
1088     }
1089 }
1090 
CalculateModeFitFill(const SizeF & layoutSize)1091 SizeF MovingPhotoPattern::CalculateModeFitFill(const SizeF& layoutSize)
1092 {
1093     return layoutSize;
1094 }
1095 
CalculateModeFitCover(const SizeF & rawSize,const SizeF & layoutSize)1096 SizeF MovingPhotoPattern::CalculateModeFitCover(const SizeF& rawSize, const SizeF& layoutSize)
1097 {
1098     if (NearZero(rawSize.Height()) || NearZero(rawSize.Width()) || NearZero(layoutSize.Height())) {
1099         return layoutSize;
1100     }
1101     double sourceRatio = rawSize.Width() / rawSize.Height();
1102     double layoutRatio = layoutSize.Width() / layoutSize.Height();
1103     float ratio = 1.0;
1104     if (sourceRatio < layoutRatio) {
1105         ratio = static_cast<float>(layoutSize.Width() / rawSize.Width());
1106     } else {
1107         ratio = static_cast<float>(layoutSize.Height() / rawSize.Height());
1108     }
1109     return { rawSize.Width() * ratio, rawSize.Height() * ratio };
1110 }
1111 
CalculateModeFitNone(const SizeF & rawSize)1112 SizeF MovingPhotoPattern::CalculateModeFitNone(const SizeF& rawSize)
1113 {
1114     return rawSize;
1115 }
1116 
CalculateModeFitScaleDown(const SizeF & rawSize,const SizeF & layoutSize)1117 SizeF MovingPhotoPattern::CalculateModeFitScaleDown(const SizeF& rawSize, const SizeF& layoutSize)
1118 {
1119     if ((rawSize.Width() <= layoutSize.Width()) && (rawSize.Height() <= layoutSize.Height())) {
1120         return CalculateModeFitNone(rawSize);
1121     } else {
1122         return CalculateModeFitContain(rawSize, layoutSize);
1123     }
1124 }
1125 
CalculateModeFitAuto(const SizeF & rawSize,const SizeF & layoutSize)1126 SizeF MovingPhotoPattern::CalculateModeFitAuto(const SizeF& rawSize, const SizeF& layoutSize)
1127 {
1128     if (NearZero(rawSize.Width()) || NearZero(rawSize.Height())) {
1129         return layoutSize;
1130     }
1131     if ((rawSize.Width() <= layoutSize.Width()) && (rawSize.Height() <= layoutSize.Height())) {
1132         double widthRatio = layoutSize.Width() / rawSize.Width();
1133         double heightRatio = layoutSize.Height() / rawSize.Height();
1134         float ratio = static_cast<float>(std::min(widthRatio, heightRatio));
1135         return { rawSize.Width() * ratio, rawSize.Height() * ratio };
1136     } else if ((rawSize.Width() > layoutSize.Width()) && (rawSize.Height() <= layoutSize.Height())) {
1137         return CalculateModeFitContain(rawSize, layoutSize);
1138     } else {
1139         return CalculateModeFitCover(rawSize, layoutSize);
1140     }
1141 }
1142 
CalculateRatio(SizeF layoutSize)1143 float MovingPhotoPattern::CalculateRatio(SizeF layoutSize)
1144 {
1145     TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "movingPhoto calculateRatio layoutSize.%{public}f, %{public}f",
1146         layoutSize.Width(), layoutSize.Height());
1147     auto layoutProperty = GetLayoutProperty<MovingPhotoLayoutProperty>();
1148     CHECK_NULL_RETURN(layoutProperty, 0);
1149     if (!layoutProperty->HasImageSize()) {
1150         TAG_LOGE(AceLogTag::ACE_MOVING_PHOTO, "movingPhoto imageSize is null.");
1151         return 0;
1152     }
1153     SizeF rawSize = layoutProperty->GetImageSize().value();
1154     TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "movingPhoto calculateRatio rawSize.%{public}f, %{public}f",
1155         rawSize.Width(), rawSize.Height());
1156     double sourceRatio = rawSize.Width() / rawSize.Height();
1157     double layoutRatio = layoutSize.Width() / layoutSize.Height();
1158     float ratio = 0;
1159     if (sourceRatio > layoutRatio) {
1160         ratio = static_cast<float>(layoutSize.Width() / rawSize.Width());
1161     } else {
1162         ratio = static_cast<float>(layoutSize.Height() / rawSize.Height());
1163     }
1164     return ratio;
1165 }
1166 
CalculateXmageOffsetRatio(SizeF layoutSize)1167 SizeF MovingPhotoPattern::CalculateXmageOffsetRatio(SizeF layoutSize)
1168 {
1169     TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "movingPhoto CalculateXmageOffsetRatio layoutSize.%{public}f, %{public}f",
1170         layoutSize.Width(), layoutSize.Height());
1171     SizeF ret = SizeF(0, 0);
1172     auto layoutProperty = GetLayoutProperty<MovingPhotoLayoutProperty>();
1173     CHECK_NULL_RETURN(layoutProperty, ret);
1174     if (!layoutProperty->HasXmageRawSize()) {
1175         TAG_LOGE(AceLogTag::ACE_MOVING_PHOTO, "movingPhoto xmageRawSize is null.");
1176         return ret;
1177     }
1178     if (!layoutProperty->HasXmageRawSize()) {
1179         return ret;
1180     }
1181     SizeF rawSize = layoutProperty->GetXmageRawSize().value();
1182     TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "movingPhoto CalculateXmageOffsetRatio rawSize.%{public}f, %{public}f",
1183         rawSize.Width(), rawSize.Height());
1184 
1185     if (rawSize.Width() == 0.0 || rawSize.Height() == 0.0) {
1186         TAG_LOGE(AceLogTag::ACE_MOVING_PHOTO, "movingPhoto xmageRawSize is 0.");
1187         return ret;
1188     }
1189     double widthRatio = layoutSize.Width() / rawSize.Width();
1190     double heightRatio = layoutSize.Height() / rawSize.Height();
1191     return SizeF(widthRatio, heightRatio);
1192 }
1193 
GetRawImageSize()1194 SizeF MovingPhotoPattern::GetRawImageSize()
1195 {
1196     auto host = GetHost();
1197     CHECK_NULL_RETURN(host, SizeF(-1, -1));
1198     auto movingPhoto = AceType::DynamicCast<MovingPhotoNode>(host);
1199     CHECK_NULL_RETURN(movingPhoto, SizeF(-1, -1));
1200     auto image = AceType::DynamicCast<FrameNode>(movingPhoto->GetImage());
1201     CHECK_NULL_RETURN(image, SizeF(-1, -1));
1202     auto imagePattern = image->GetPattern<ImagePattern>();
1203     CHECK_NULL_RETURN(image, SizeF(-1, -1));
1204     return imagePattern->GetRawImageSize();
1205 }
1206 
GetImageFd() const1207 int32_t MovingPhotoPattern::GetImageFd() const
1208 {
1209     if (!isPlayWithMask_) {
1210         TAG_LOGE(AceLogTag::ACE_MOVING_PHOTO, "movingPhoto GetImageFd.%{public}d", isPlayWithMask_);
1211         return -1;
1212     }
1213     auto host = GetHost();
1214     CHECK_NULL_RETURN(host, -1);
1215     auto layoutProperty = GetLayoutProperty<MovingPhotoLayoutProperty>();
1216     CHECK_NULL_RETURN(layoutProperty, -1);
1217     auto pipeline = PipelineBase::GetCurrentContext();
1218     CHECK_NULL_RETURN(pipeline, -1);
1219     auto dataProvider = AceType::DynamicCast<DataProviderManagerStandard>(pipeline->GetDataProviderManager());
1220     CHECK_NULL_RETURN(dataProvider, -1);
1221 
1222     if (!layoutProperty->HasMovingPhotoUri()) {
1223         TAG_LOGE(AceLogTag::ACE_MOVING_PHOTO, "movingPhoto GetImageFd uri is null");
1224         return -1;
1225     }
1226     std::string uriValue = layoutProperty->GetMovingPhotoUri().value();
1227     int32_t fd = dataProvider->GetDataProviderFile(uriValue, "r");
1228     return fd;
1229 }
1230 
SetXmagePosition()1231 void MovingPhotoPattern::SetXmagePosition()
1232 {
1233     TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "movingPhoto SetXmagePosition");
1234     int32_t fd = GetImageFd();
1235     CHECK_NULL_VOID(fd >= 0);
1236     auto imageSrc = ImageSource::Create(fd);
1237     close(fd);
1238     CHECK_NULL_VOID(imageSrc);
1239     auto host = GetHost();
1240     CHECK_NULL_VOID(host);
1241     auto imageLength = imageSrc->GetProperty(IMAGE_LENGTH);
1242     auto imageWidth = imageSrc->GetProperty(IMAGE_WIDTH);
1243     if (imageLength.empty() || imageWidth.empty() || imageLength == DEFAULT_EXIF_VALUE ||
1244         imageWidth == DEFAULT_EXIF_VALUE) {
1245         TAG_LOGE(AceLogTag::ACE_MOVING_PHOTO, "movingPhoto imageLength or imageWidth is null");
1246         return;
1247     }
1248 
1249     float imageW = StringUtils::StringToFloat(imageWidth);
1250     float imageL = StringUtils::StringToFloat(imageLength);
1251     TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "movingPhoto imageW.%{public}f, imageL %{public}f",
1252              imageW, imageL);
1253 
1254     std::string modeValue = imageSrc->GetProperty(HW_MNOTE_XMAGE_MODE);
1255     SizeF imageSize = SizeF(-1, -1);
1256     if (!modeValue.empty() && modeValue != DEFAULT_EXIF_VALUE && !IsAllZeroPositionInXmage(imageSrc)) {
1257         isXmageMode_ = true;
1258         xmageModeValue_ = StringUtils::StringToInt(modeValue);
1259         TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "movingPhoto xmageModeValue_ = %{public}d", xmageModeValue_);
1260         if (xmageModeValue_ != ROUND_XMAGE_MODE_VALUE) {
1261             UpdateXmageProperty(imageSrc, imageSize, imageW, imageL, host);
1262         }
1263     } else {
1264         isXmageMode_ = false;
1265         xmageModeValue_ = 0;
1266         imageSize = SizeF(imageW, imageL);
1267     }
1268     ACE_UPDATE_NODE_LAYOUT_PROPERTY(MovingPhotoLayoutProperty, ImageSize, imageSize, host);
1269     TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "movingPhoto imageSize imageW.%{public}f, imageL %{public}f",
1270             imageSize.Width(), imageSize.Height());
1271 }
1272 
IsAllZeroPositionInXmage(const RefPtr<ImageSource> & imageSrc)1273 bool MovingPhotoPattern::IsAllZeroPositionInXmage(const RefPtr<ImageSource>& imageSrc)
1274 {
1275     return imageSrc->GetProperty(HW_MNOTE_XMAGE_LEFT) == "0" &&
1276            imageSrc->GetProperty(HW_MNOTE_XMAGE_TOP) == "0" &&
1277            imageSrc->GetProperty(HW_MNOTE_XMAGE_RIGHT) == "0" &&
1278            imageSrc->GetProperty(HW_MNOTE_XMAGE_BOTTOM) == "0";
1279 }
1280 
UpdateXmageProperty(RefPtr<ImageSource> imageSrc,SizeF & imageSize,float imageW,float imageL,RefPtr<FrameNode> & host)1281 void MovingPhotoPattern::UpdateXmageProperty(
1282     RefPtr<ImageSource> imageSrc, SizeF& imageSize, float imageW, float imageL, RefPtr<FrameNode>& host)
1283 {
1284     std::string xmageLeft = imageSrc->GetProperty(HW_MNOTE_XMAGE_LEFT);
1285     std::string xmageTop = imageSrc->GetProperty(HW_MNOTE_XMAGE_TOP);
1286     std::string xmageRight = imageSrc->GetProperty(HW_MNOTE_XMAGE_RIGHT);
1287     std::string xmageBottom = imageSrc->GetProperty(HW_MNOTE_XMAGE_BOTTOM);
1288     if (xmageBottom.empty() || xmageBottom == DEFAULT_EXIF_VALUE) {
1289         TAG_LOGE(AceLogTag::ACE_MOVING_PHOTO, "movingPhoto xmageBottom is null");
1290         return;
1291     }
1292     float xLeft = StringUtils::StringToFloat(xmageLeft);
1293     float xTop = StringUtils::StringToFloat(xmageTop);
1294     float xRight = StringUtils::StringToFloat(xmageRight);
1295     float xBottom = StringUtils::StringToFloat(xmageBottom);
1296     imageSize = SizeF(xRight - xLeft, xBottom - xTop);
1297     SizeF xmageOffset = SizeF(xLeft, xTop);
1298     SizeF xmageRawSize = SizeF(imageW, imageL);
1299     TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "movingPhoto Xmage(%{public}f, %{public}f, %{public}f, %{public}f)",
1300         xLeft, xTop, xRight, xBottom);
1301     ACE_UPDATE_NODE_LAYOUT_PROPERTY(MovingPhotoLayoutProperty, XmageOffset, xmageOffset, host);
1302     ACE_UPDATE_NODE_LAYOUT_PROPERTY(MovingPhotoLayoutProperty, XmageRawSize, xmageRawSize, host);
1303 }
1304 
MeasureContentLayout(const SizeF & layoutSize,const RefPtr<MovingPhotoLayoutProperty> & layoutProperty)1305 SizeF MovingPhotoPattern::MeasureContentLayout(const SizeF& layoutSize,
1306     const RefPtr<MovingPhotoLayoutProperty>& layoutProperty)
1307 {
1308     if (!layoutProperty || !layoutProperty->HasVideoSize()) {
1309         return layoutSize;
1310     }
1311 
1312     auto rawImageSize = GetRawImageSize();
1313     auto imageFit = layoutProperty->GetObjectFitValue(ImageFit::COVER);
1314     SizeF contentSize = { 0.0, 0.0 };
1315     switch (imageFit) {
1316         case ImageFit::CONTAIN:
1317             contentSize = CalculateFitContain(rawImageSize, layoutSize);
1318             break;
1319         case ImageFit::FILL:
1320             contentSize = CalculateFitFill(layoutSize);
1321             break;
1322         case ImageFit::COVER:
1323             contentSize = CalculateFitCover(rawImageSize, layoutSize);
1324             break;
1325         case ImageFit::NONE:
1326             contentSize = CalculateFitNone(rawImageSize);
1327             break;
1328         case ImageFit::SCALE_DOWN:
1329             contentSize = CalculateFitScaleDown(rawImageSize, layoutSize);
1330             break;
1331         default:
1332             contentSize = CalculateFitAuto(rawImageSize, layoutSize);
1333     }
1334 
1335     TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "movingPhoto MeasureContentLayout.%{public}f, %{public}f",
1336         contentSize.Width(), contentSize.Height());
1337     return contentSize;
1338 }
1339 
MeasureModeContentLayout(const SizeF & layoutSize,const RefPtr<MovingPhotoLayoutProperty> & layoutProperty)1340 SizeF MovingPhotoPattern::MeasureModeContentLayout(const SizeF& layoutSize,
1341     const RefPtr<MovingPhotoLayoutProperty>& layoutProperty)
1342 {
1343     if (!layoutProperty || !layoutProperty->HasVideoSize()) {
1344         return layoutSize;
1345     }
1346 
1347     auto rawImageSize = GetRawImageSize();
1348     auto imageFit = layoutProperty->GetObjectFitValue(ImageFit::COVER);
1349     SizeF contentSize = { 0.0, 0.0 };
1350     switch (imageFit) {
1351         case ImageFit::CONTAIN:
1352             contentSize = CalculateModeFitContain(rawImageSize, layoutSize);
1353             break;
1354         case ImageFit::FILL:
1355             contentSize = CalculateModeFitFill(layoutSize);
1356             break;
1357         case ImageFit::COVER:
1358             contentSize = CalculateModeFitCover(rawImageSize, layoutSize);
1359             break;
1360         case ImageFit::NONE:
1361             contentSize = CalculateModeFitNone(rawImageSize);
1362             break;
1363         case ImageFit::SCALE_DOWN:
1364             contentSize = CalculateModeFitScaleDown(rawImageSize, layoutSize);
1365             break;
1366         default:
1367             contentSize = CalculateModeFitAuto(rawImageSize, layoutSize);
1368     }
1369 
1370     TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "movingPhoto MeasureModeContentLayout.%{public}f, %{public}f",
1371         contentSize.Width(), contentSize.Height());
1372     return contentSize;
1373 }
1374 
OnMediaPlayerStatusChanged(PlaybackStatus status)1375 void MovingPhotoPattern::OnMediaPlayerStatusChanged(PlaybackStatus status)
1376 {
1377     isUsedMediaPlayerStatusChanged_ = true;
1378     currentPlayStatus_ = status;
1379     TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "Player current status is %{public}d.", status);
1380     switch (status) {
1381         case PlaybackStatus::ERROR:
1382             TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "Player current status is ERROR.");
1383             FireMediaPlayerError();
1384             break;
1385         case PlaybackStatus::IDLE:
1386             TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "Player current status is IDLE.");
1387             break;
1388         case PlaybackStatus::INITIALIZED:
1389             TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "Player current status is INITIALIZED.");
1390             OnMediaPlayerInitialized();
1391             break;
1392         case PlaybackStatus::PREPARED:
1393             TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "Player current status is PREPARED.");
1394             OnMediaPlayerPrepared();
1395             break;
1396         case PlaybackStatus::STARTED:
1397             TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "Player current status is STARTED.");
1398             OnStartedStatusCallback();
1399             FireMediaPlayerStart();
1400             break;
1401         case PlaybackStatus::PAUSED:
1402             TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "Player current status is PAUSED.");
1403             FireMediaPlayerPause();
1404             break;
1405         case PlaybackStatus::STOPPED:
1406             TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "Player current status is STOPPED.");
1407             OnMediaPlayerStoped();
1408             break;
1409         case PlaybackStatus::PLAYBACK_COMPLETE:
1410             TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "Player current status is PLAYBACK_COMPLETE.");
1411             OnMediaPlayerCompletion();
1412             break;
1413         case PlaybackStatus::NONE:
1414             TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "Player current status is NONE.");
1415             break;
1416         default:
1417             TAG_LOGW(AceLogTag::ACE_MOVING_PHOTO, "Invalid player status.");
1418             break;
1419     }
1420 }
1421 
OnMediaPlayerInitialized()1422 void MovingPhotoPattern::OnMediaPlayerInitialized()
1423 {
1424     TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "MediaPlayer OnMediaPlayerInitialized.");
1425     if (!isSetAutoPlayPeriod_ && autoAndRepeatLevel_ == PlaybackMode::AUTO) {
1426         isSetAutoPlayPeriod_ = true;
1427         SetAutoPlayPeriod(autoPlayPeriodStartTime_, autoPlayPeriodEndTime_);
1428     }
1429     isAutoChangePlayMode_ = false;
1430     PrepareSurface();
1431     if (cameraPostprocessingEnabled_) {
1432         mediaPlayer_->EnableCameraPostprocessing();
1433     }
1434     if (mediaPlayer_->PrepareAsync() != PREPARE_RETURN) {
1435         TAG_LOGW(AceLogTag::ACE_MOVING_PHOTO, "prepare MediaPlayer failed.");
1436     }
1437 }
1438 
OnMediaPlayerPrepared()1439 void MovingPhotoPattern::OnMediaPlayerPrepared()
1440 {
1441     ContainerScope scope(instanceId_);
1442     auto context = PipelineContext::GetCurrentContext();
1443     CHECK_NULL_VOID(context);
1444     if (!mediaPlayer_ || !mediaPlayer_->IsMediaPlayerValid()) {
1445         TAG_LOGW(AceLogTag::ACE_MOVING_PHOTO, "MediaPlayer is null or invalid.");
1446         return;
1447     }
1448     isPrepared_ = true;
1449     Size videoSize = Size(mediaPlayer_->GetVideoWidth(), mediaPlayer_->GetVideoHeight());
1450     auto host = GetHost();
1451     CHECK_NULL_VOID(host);
1452     auto videoLayoutProperty = host->GetLayoutProperty<MovingPhotoLayoutProperty>();
1453     CHECK_NULL_VOID(videoLayoutProperty);
1454     CHECK_NULL_VOID(mediaPlayer_);
1455     videoLayoutProperty->UpdateVideoSize(
1456         SizeF(static_cast<float>(videoSize.Width()), static_cast<float>(videoSize.Height())));
1457     host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
1458     mediaPlayer_->SetParameter(VIDEO_SCALE, 1);
1459     UpdateMediaPlayerSpeed();
1460     UpdateMediaPlayerMuted();
1461     PreparedToPlay();
1462     FireMediaPlayerPrepared();
1463 }
1464 
OnMediaPlayerStoped()1465 void MovingPhotoPattern::OnMediaPlayerStoped()
1466 {
1467     isPlayByController_ = false;
1468     FireMediaPlayerStop();
1469 }
1470 
OnMediaPlayerCompletion()1471 void MovingPhotoPattern::OnMediaPlayerCompletion()
1472 {
1473     if (!isRefreshMovingPhotoPlaying_) {
1474         if (isPlayByController_ || autoAndRepeatLevel_ != PlaybackMode::NONE) {
1475             isPlayByController_ = false;
1476             StopAnimation();
1477         }
1478     }
1479     isStopAnimation_ = false;
1480     FireMediaPlayerFinish();
1481 }
1482 
HideImageNode()1483 void MovingPhotoPattern::HideImageNode()
1484 {
1485     auto host = GetHost();
1486     CHECK_NULL_VOID(host);
1487     auto movingPhoto = AceType::DynamicCast<MovingPhotoNode>(host);
1488     CHECK_NULL_VOID(movingPhoto);
1489     auto image = AceType::DynamicCast<FrameNode>(movingPhoto->GetImage());
1490     CHECK_NULL_VOID(image);
1491     auto imageLayoutProperty = image->GetLayoutProperty<ImageLayoutProperty>();
1492     CHECK_NULL_VOID(imageLayoutProperty);
1493     imageLayoutProperty->UpdateVisibility(VisibleType::INVISIBLE);
1494     image->MarkModifyDone();
1495 }
1496 
PreparedToPlay()1497 void MovingPhotoPattern::PreparedToPlay()
1498 {
1499     TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "movingphoto PreparedToPlay.");
1500     if (!isVisible_) {
1501         return;
1502     }
1503     if (isRepeatChangePlayMode_ && historyAutoAndRepeatLevel_ == PlaybackMode::NONE &&
1504         autoAndRepeatLevel_ == PlaybackMode::NONE) {
1505         autoAndRepeatLevel_ = PlaybackMode::REPEAT;
1506         historyAutoAndRepeatLevel_ = PlaybackMode::REPEAT;
1507         isRepeatChangePlayMode_ = false;
1508     }
1509     if (historyAutoAndRepeatLevel_ != PlaybackMode::NONE &&
1510         autoAndRepeatLevel_ == PlaybackMode::NONE) {
1511         SelectPlaybackMode(historyAutoAndRepeatLevel_);
1512     } else {
1513         SelectPlaybackMode(autoAndRepeatLevel_);
1514     }
1515 }
1516 
SelectPlaybackMode(PlaybackMode mode)1517 void MovingPhotoPattern::SelectPlaybackMode(PlaybackMode mode)
1518 {
1519     if (mode == PlaybackMode::REPEAT) {
1520         StartRepeatPlay();
1521     } else if (mode == PlaybackMode::AUTO) {
1522         StartAutoPlay();
1523     }
1524 }
1525 
StartPlayback()1526 void MovingPhotoPattern::StartPlayback()
1527 {
1528     if (currentPlayStatus_ == PlaybackStatus::STARTED || !isPrepared_) {
1529         return;
1530     }
1531     if (IsRefreshMovingPhotoReturn(isRefreshMovingPhoto_)) {
1532         TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "HandleTouchEvent IsRefreshMovingPhotoReturn.");
1533         return;
1534     }
1535 
1536     if (currentPlayStatus_ == PlaybackStatus::STOPPED) {
1537         mediaPlayer_->PrepareAsync();
1538     }
1539     isPlayByController_ = true;
1540     isFastKeyUp_ = false;
1541     if (isSetAutoPlayPeriod_ && (currentPlayStatus_ == PlaybackStatus::PLAYBACK_COMPLETE ||
1542         currentPlayStatus_ == PlaybackStatus::PAUSED)) {
1543         int32_t duration = DURATION_FLAG;
1544         mediaPlayer_->GetDuration(duration);
1545         TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "StartPlayback duration:%{public}d.",
1546             duration);
1547         SetAutoPlayPeriod(PERIOD_START, duration * US_CONVERT);
1548     }
1549     Start();
1550 }
1551 
StartAnimation()1552 void MovingPhotoPattern::StartAnimation()
1553 {
1554     TAG_LOGD(AceLogTag::ACE_MOVING_PHOTO, "movingphoto StartAnimation start");
1555     auto host = GetHost();
1556     CHECK_NULL_VOID(host);
1557     auto movingPhoto = AceType::DynamicCast<MovingPhotoNode>(host);
1558     CHECK_NULL_VOID(movingPhoto);
1559     int32_t childCount = movingPhoto->GetTotalChildCount();
1560     CHECK_NULL_VOID(childCount >= 1);
1561     auto image = AceType::DynamicCast<FrameNode>(movingPhoto->GetImage());
1562     CHECK_NULL_VOID(image);
1563     auto imageRsContext = image->GetRenderContext();
1564     CHECK_NULL_VOID(imageRsContext);
1565     auto video = AceType::DynamicCast<FrameNode>(movingPhoto->GetVideo(childCount - 1));
1566     CHECK_NULL_VOID(video);
1567     auto videoRsContext = video->GetRenderContext();
1568     CHECK_NULL_VOID(videoRsContext);
1569     if (historyAutoAndRepeatLevel_ == PlaybackMode::REPEAT) {
1570         if (!isFirstRepeatPlay_) {
1571             videoRsContext->UpdateOpacity(1.0);
1572             return;
1573         }
1574         isFirstRepeatPlay_ = false;
1575     }
1576 
1577     videoRsContext->UpdateOpacity(0.0);
1578     imageRsContext->UpdateTransformScale({NORMAL_SCALE, NORMAL_SCALE});
1579     videoRsContext->UpdateTransformScale({NORMAL_SCALE, NORMAL_SCALE});
1580     auto movingPhotoPattern = WeakClaim(this);
1581     AnimationOption animationOption;
1582     animationOption.SetDuration(ANIMATION_DURATION_400);
1583     animationOption.SetCurve(Curves::FRICTION);
1584     animationOption.SetOnFinishEvent([movingPhotoPattern]() {
1585         auto movingPhoto = movingPhotoPattern.Upgrade();
1586         TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "movingphoto StartAnimation OnFinishEvent.");
1587         CHECK_NULL_VOID(movingPhoto);
1588         if (movingPhoto->currentPlayStatus_ == PlaybackStatus::PAUSED
1589             || movingPhoto->currentPlayStatus_ == PlaybackStatus::STOPPED
1590             || !movingPhoto->startAnimationFlag_) {
1591             return;
1592         }
1593     });
1594     startAnimationFlag_ = true;
1595     AnimationUtils::Animate(animationOption,
1596         [imageRsContext, videoRsContext, flag = autoAndRepeatLevel_, movingPhotoPattern]() {
1597             videoRsContext->UpdateOpacity(1.0);
1598             auto movingPhoto = movingPhotoPattern.Upgrade();
1599             CHECK_NULL_VOID(movingPhoto);
1600             movingPhoto->RsContextUpdateTransformScale(imageRsContext, videoRsContext, flag);
1601         }, animationOption.GetOnFinishEvent());
1602 }
1603 
RsContextUpdateTransformScale(const RefPtr<RenderContext> & imageRsContext,const RefPtr<RenderContext> & videoRsContext,PlaybackMode playbackMode)1604 void MovingPhotoPattern::RsContextUpdateTransformScale(const RefPtr<RenderContext>& imageRsContext,
1605     const RefPtr<RenderContext>& videoRsContext, PlaybackMode playbackMode)
1606 {
1607     if (playbackMode == PlaybackMode::REPEAT || playbackMode == PlaybackMode::AUTO || !isEnableTransition_) {
1608         videoRsContext->UpdateTransformScale({NORMAL_SCALE, NORMAL_SCALE});
1609         imageRsContext->UpdateTransformScale({NORMAL_SCALE, NORMAL_SCALE});
1610     } else {
1611         if (isXmageMode_) {
1612             videoRsContext->UpdateTransformScale({ZOOM_IN_SCALE, ZOOM_IN_SCALE});
1613             imageRsContext->UpdateTransformScale({NORMAL_SCALE, NORMAL_SCALE});
1614         } else {
1615             videoRsContext->UpdateTransformScale({ZOOM_IN_SCALE, ZOOM_IN_SCALE});
1616             imageRsContext->UpdateTransformScale({ZOOM_IN_SCALE, ZOOM_IN_SCALE});
1617         }
1618     }
1619 }
1620 
StopPlayback()1621 void MovingPhotoPattern::StopPlayback()
1622 {
1623     TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "movingphoto StopPlayback");
1624     isFastKeyUp_ = false;
1625     isPlayByController_ = false;
1626     Pause();
1627     autoAndRepeatLevel_ = PlaybackMode::NONE;
1628     if (historyAutoAndRepeatLevel_ != PlaybackMode::REPEAT) {
1629         StopAnimation();
1630     }
1631 }
1632 
PausePlayback()1633 void MovingPhotoPattern::PausePlayback()
1634 {
1635     TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "movingphoto PausePlayback");
1636     isFastKeyUp_ = false;
1637     if (currentPlayStatus_ != PlaybackStatus::STARTED || !isPrepared_) {
1638         return;
1639     }
1640     if (IsRefreshMovingPhotoReturn(isRefreshMovingPhotoPlaying_)) {
1641         TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "HandleTouchEvent IsRefreshMovingPhotoReturn.");
1642         return;
1643     }
1644     isPlayByController_ = false;
1645     Pause();
1646     StopAnimation();
1647 }
1648 
PauseVideo()1649 void MovingPhotoPattern::PauseVideo()
1650 {
1651     isFastKeyUp_ = false;
1652     if (currentPlayStatus_ != PlaybackStatus::STARTED || !isPrepared_) {
1653         TAG_LOGE(AceLogTag::ACE_MOVING_PHOTO, "movingphoto Pause return.");
1654         return;
1655     }
1656     if (isRefreshMovingPhotoPlaying_ && autoAndRepeatLevel_ == PlaybackMode::REPEAT) {
1657         TAG_LOGE(AceLogTag::ACE_MOVING_PHOTO, "HandleTouchEvent IsRefreshMovingPhotoReturn.");
1658         return;
1659     }
1660     TAG_LOGE(AceLogTag::ACE_MOVING_PHOTO, "movingphoto Pause video.");
1661     isStopAnimation_ = true;
1662     Pause();
1663 }
1664 
ResetVideo()1665 void MovingPhotoPattern::ResetVideo()
1666 {
1667     isFastKeyUp_ = false;
1668     if (currentPlayStatus_ == PlaybackStatus::ERROR) {
1669         ResetMediaPlayer();
1670         return;
1671     }
1672     if (currentPlayStatus_ == PlaybackStatus::STOPPED) {
1673         mediaPlayer_->PrepareAsync();
1674     }
1675     int32_t duration = DURATION_FLAG;
1676     mediaPlayer_->GetDuration(duration);
1677     autoPlayPeriodStartTime_ = PERIOD_START;
1678     autoPlayPeriodEndTime_ = duration * US_CONVERT;
1679     if (currentPlayStatus_ == PlaybackStatus::STARTED) {
1680         Pause();
1681     }
1682     SetAutoPlayPeriod(autoPlayPeriodStartTime_, autoPlayPeriodEndTime_);
1683     TAG_LOGE(AceLogTag::ACE_MOVING_PHOTO, "movingphoto reset video.");
1684     historyAutoAndRepeatLevel_ = PlaybackMode::NONE;
1685     autoAndRepeatLevel_ = PlaybackMode::NONE;
1686     isSetAutoPlayPeriod_ = false;
1687     StopAnimation();
1688 }
1689 
RestartVideo()1690 void MovingPhotoPattern::RestartVideo()
1691 {
1692     if (!mediaPlayer_ || !mediaPlayer_->IsMediaPlayerValid()) {
1693         TAG_LOGW(AceLogTag::ACE_MOVING_PHOTO, "MediaPlayer is null or invalid.");
1694         return;
1695     }
1696     if (currentPlayStatus_ == PlaybackStatus::STOPPED) {
1697         mediaPlayer_->PrepareAsync();
1698     }
1699     TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "movingphoto restart video.");
1700     isPlayByController_ = true;
1701     ContainerScope scope(instanceId_);
1702     auto context = PipelineContext::GetCurrentContext();
1703     CHECK_NULL_VOID(context);
1704     auto platformTask = SingleTaskExecutor::Make(context->GetTaskExecutor(), TaskExecutor::TaskType::BACKGROUND);
1705     platformTask.PostTask(
1706         [weak = WeakClaim(RawPtr(mediaPlayer_))] {
1707             auto mediaPlayer = weak.Upgrade();
1708             CHECK_NULL_VOID(mediaPlayer);
1709             mediaPlayer->Play();
1710         },
1711         "ArkUIMovingPhotoUpdateMuted");
1712 }
1713 
SetEnableTransition(bool enabled)1714 void MovingPhotoPattern::SetEnableTransition(bool enabled)
1715 {
1716     TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "movingphoto SetEnableTransition %{public}d.", enabled);
1717     isEnableTransition_ = enabled;
1718 }
1719 
GetEnableTransition()1720 bool MovingPhotoPattern::GetEnableTransition()
1721 {
1722     TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "movingphoto GetEnableTransition %{public}d.", isEnableTransition_);
1723     return isEnableTransition_;
1724 }
1725 
SetPlaybackPeriod(int64_t startTime,int64_t endTime)1726 bool MovingPhotoPattern::SetPlaybackPeriod(int64_t startTime, int64_t endTime)
1727 {
1728     TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "movingphoto setPlaybackPeriod.");
1729     if (startTime < VIDEO_PLAYTIME_START_POSITION || startTime >= endTime) {
1730         TAG_LOGW(AceLogTag::ACE_MOVING_PHOTO, "MeidaPlayer SetPlaybackPeriod error.");
1731         return false;
1732     }
1733     if (!mediaPlayer_ || !mediaPlayer_->IsMediaPlayerValid() || currentPlayStatus_ == PlaybackStatus::STARTED) {
1734         TAG_LOGW(AceLogTag::ACE_MOVING_PHOTO, "MediaPlayer is invalid or currentPlayStatus is STARTED.");
1735         return false;
1736     }
1737     TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "movingphoto SetPlaybackPeriod.");
1738     autoPlayPeriodStartTime_ = startTime;
1739     autoPlayPeriodEndTime_ = endTime;
1740     mediaPlayer_->SetPlayRangeUsWithMode(startTime, endTime, SeekMode::SEEK_CLOSEST);
1741     return true;
1742 }
1743 
EnableAutoPlay(bool enabled)1744 void MovingPhotoPattern::EnableAutoPlay(bool enabled)
1745 {
1746     TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "movingphoto enable AutoPlay : %{public}d.", enabled);
1747     if (!enabled || autoAndRepeatLevel_ == PlaybackMode::REPEAT || !mediaPlayer_ ||
1748         !mediaPlayer_->IsMediaPlayerValid()) {
1749         return;
1750     }
1751     if (currentPlayStatus_ == PlaybackStatus::PLAYBACK_COMPLETE || currentPlayStatus_ == PlaybackStatus::PAUSED) {
1752         SetAutoPlayPeriod(autoPlayPeriodStartTime_, autoPlayPeriodEndTime_);
1753     }
1754     if (currentPlayStatus_ == PlaybackStatus::STARTED || !isPrepared_) {
1755         TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "movingphoto play status is STARTED or isPrepared is :%{public}d",
1756             isPrepared_);
1757         return;
1758     }
1759     if (currentPlayStatus_ == PlaybackStatus::STOPPED) {
1760         mediaPlayer_->PrepareAsync();
1761     }
1762     TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "movingphoto autoplay set success.");
1763     isPlayByController_ = true;
1764     isFastKeyUp_ = false;
1765     Start();
1766 }
1767 
RefreshMovingPhoto()1768 void MovingPhotoPattern::RefreshMovingPhoto()
1769 {
1770     TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "movingphoto RefreshMovingPhoto start.");
1771     if (uri_ == "") {
1772         TAG_LOGW(AceLogTag::ACE_MOVING_PHOTO, "movingphoto RefreshMovingPhoto uri is null.");
1773         return;
1774     }
1775     auto host = GetHost();
1776     CHECK_NULL_VOID(host);
1777     auto layoutProperty = GetLayoutProperty<MovingPhotoLayoutProperty>();
1778     CHECK_NULL_VOID(layoutProperty);
1779     auto pipeline = PipelineBase::GetCurrentContext();
1780     CHECK_NULL_VOID(pipeline);
1781     auto dataProvider = AceType::DynamicCast<DataProviderManagerStandard>(pipeline->GetDataProviderManager());
1782     CHECK_NULL_VOID(dataProvider);
1783     if (!layoutProperty->HasMovingPhotoUri() || !layoutProperty->HasVideoSource()) {
1784         TAG_LOGW(AceLogTag::ACE_MOVING_PHOTO, "movingphoto source is null.");
1785         return;
1786     }
1787     std::string imageSrc = dataProvider->GetMovingPhotoImageUri(uri_);
1788     auto imageCache = pipeline->GetImageCache();
1789     if (imageCache) {
1790         ImageSourceInfo srcKey;
1791         srcKey.SetSrc(imageSrc);
1792         imageCache->ClearCacheImgObj(srcKey.GetKey());
1793     }
1794     imageSrc += "?date_modified = " + std::to_string(GetMicroTickCount());
1795     ImageSourceInfo src;
1796     src.SetSrc(imageSrc);
1797     ACE_UPDATE_NODE_LAYOUT_PROPERTY(MovingPhotoLayoutProperty, ImageSourceInfo, src, host);
1798     UpdateImageNode();
1799     fd_ = dataProvider->ReadMovingPhotoVideo(uri_);
1800     ACE_UPDATE_NODE_LAYOUT_PROPERTY(MovingPhotoLayoutProperty, VideoSource, fd_.GetValue(), host);
1801     isRefreshMovingPhoto_ = true;
1802     isSetAutoPlayPeriod_ = false;
1803     RefreshMovingPhotoSceneManager();
1804     ResetMediaPlayer();
1805     if (IsSupportImageAnalyzer() && isEnableAnalyzer_ && imageAnalyzerManager_) {
1806         UpdateAnalyzerOverlay();
1807     }
1808 }
1809 
RefreshMovingPhotoSceneManager()1810 void MovingPhotoPattern::RefreshMovingPhotoSceneManager()
1811 {
1812     auto host = GetHost();
1813     CHECK_NULL_VOID(host);
1814     if (historyAutoAndRepeatLevel_ == PlaybackMode::REPEAT) {
1815         autoAndRepeatLevel_ = PlaybackMode::NONE;
1816         historyAutoAndRepeatLevel_ = PlaybackMode::NONE;
1817         isRepeatChangePlayMode_ = true;
1818         Pause();
1819         auto movingPhoto = AceType::DynamicCast<MovingPhotoNode>(host);
1820         CHECK_NULL_VOID(movingPhoto);
1821         int32_t childCount = movingPhoto->GetTotalChildCount();
1822         CHECK_NULL_VOID(childCount >= 1);
1823         auto video = AceType::DynamicCast<FrameNode>(movingPhoto->GetVideo(childCount - 1));
1824         CHECK_NULL_VOID(video);
1825         video->GetRenderContext()->SetClipToBounds(true);
1826         video->GetRenderContext()->UpdateOpacity(0.0);
1827     } else if (historyAutoAndRepeatLevel_ == PlaybackMode::AUTO) {
1828         autoAndRepeatLevel_ = PlaybackMode::AUTO;
1829         isAutoChangePlayMode_ = true;
1830     }
1831     autoPlayPeriodStartTime_ = -1;
1832     autoPlayPeriodEndTime_ = -1;
1833 }
1834 
NotifyTransition()1835 void MovingPhotoPattern::NotifyTransition()
1836 {
1837     TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "movingphoto NotifyTransition start.");
1838     if (notifyTransitionFlag_) {
1839         TAG_LOGE(AceLogTag::ACE_MOVING_PHOTO, "movingphoto notifyTransition started.");
1840         return;
1841     }
1842     notifyTransitionFlag_ = true;
1843     auto host = GetHost();
1844     CHECK_NULL_VOID(host);
1845     auto movingPhoto = AceType::DynamicCast<MovingPhotoNode>(host);
1846     CHECK_NULL_VOID(movingPhoto);
1847     auto image = AceType::DynamicCast<FrameNode>(movingPhoto->GetImage());
1848     CHECK_NULL_VOID(image);
1849     AddTempNode(image, host);
1850     auto pipeline = PipelineBase::GetCurrentContext();
1851     CHECK_NULL_VOID(pipeline);
1852     auto dataProvider = AceType::DynamicCast<DataProviderManagerStandard>(pipeline->GetDataProviderManager());
1853     CHECK_NULL_VOID(dataProvider);
1854     std::string imageSrc = dataProvider->GetMovingPhotoImageUri(uri_);
1855     auto imageCache = pipeline->GetImageCache();
1856     if (imageCache) {
1857         ImageSourceInfo srcKey;
1858         srcKey.SetSrc(imageSrc);
1859         imageCache->ClearCacheImgObj(srcKey.GetKey());
1860     }
1861     imageSrc += "?date_modified = " + std::to_string(GetMicroTickCount());
1862     ImageSourceInfo src;
1863     src.SetSrc(imageSrc);
1864     UpdateTempImageNode(src);
1865 }
1866 
EightyToHundredAnimation()1867 void MovingPhotoPattern::EightyToHundredAnimation()
1868 {
1869     TAG_LOGD(AceLogTag::ACE_MOVING_PHOTO, "movingphoto EightyToHundredAnimation start.");
1870     auto image = GetTempNode();
1871     CHECK_NULL_VOID(image);
1872     auto imageLayoutProperty = image->GetLayoutProperty<ImageLayoutProperty>();
1873     CHECK_NULL_VOID(imageLayoutProperty);
1874     auto imageRsContext = image->GetRenderContext();
1875     CHECK_NULL_VOID(imageRsContext);
1876 
1877     imageRsContext->UpdateOpacity(0);
1878     image->MarkModifyDone();
1879     auto movingPhotoPattern = WeakClaim(this);
1880     AnimationOption option;
1881     option.SetDuration(EIGHTY_TO_HUNDRED_TIME);
1882     option.SetCurve(Curves::EASE);
1883     option.SetOnFinishEvent([movingPhotoPattern]() {
1884         TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "movingphoto EightyToHundredAnimation finish.");
1885         auto movingPhoto = movingPhotoPattern.Upgrade();
1886         CHECK_NULL_VOID(movingPhoto);
1887         movingPhoto->DetachFirstImageFromFrameNode();
1888         movingPhoto->notifyTransitionFlag_ = false;
1889     });
1890     AnimationUtils::Animate(option, [imageRsContext]() {
1891             imageRsContext->UpdateOpacity(1.0);
1892         }, option.GetOnFinishEvent());
1893 }
1894 
AddTempNode(const RefPtr<FrameNode> & imageNode,const RefPtr<FrameNode> & movingPhotoNode)1895 void MovingPhotoPattern::AddTempNode(const RefPtr<FrameNode>& imageNode,
1896                                      const RefPtr<FrameNode>& movingPhotoNode)
1897 {
1898     CHECK_NULL_VOID(imageNode);
1899     CHECK_NULL_VOID(movingPhotoNode);
1900     std::optional<int32_t> tempImageId_ = ElementRegister::GetInstance()->MakeUniqueId();
1901     CHECK_NULL_VOID(tempImageId_.has_value());
1902     auto tempImageNode = FrameNode::GetOrCreateFrameNode(
1903         V2::IMAGE_ETS_TAG, tempImageId_.value(), []() { return AceType::MakeRefPtr<ImagePattern>(); });
1904     movingPhotoNode->AddChildAfter(tempImageNode, imageNode);
1905 }
1906 
DetachFirstImageFromFrameNode()1907 void MovingPhotoPattern::DetachFirstImageFromFrameNode()
1908 {
1909     TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "movingphoto DetachFirstImageFromFrameNode.");
1910     auto host = GetHost();
1911     CHECK_NULL_VOID(host);
1912     auto movingPhoto = AceType::DynamicCast<MovingPhotoNode>(host);
1913     CHECK_NULL_VOID(movingPhoto);
1914     auto image = AceType::DynamicCast<FrameNode>(movingPhoto->GetImage());
1915     CHECK_NULL_VOID(image);
1916     host->RemoveChild(image);
1917 }
1918 
GetTempNode()1919 RefPtr<FrameNode> MovingPhotoPattern::GetTempNode()
1920 {
1921     auto host = GetHost();
1922     CHECK_NULL_RETURN(host, nullptr);
1923     auto movingPhoto = AceType::DynamicCast<MovingPhotoNode>(host);
1924     CHECK_NULL_RETURN(movingPhoto, nullptr);
1925     auto firstImage = AceType::DynamicCast<FrameNode>(movingPhoto->GetImage());
1926     CHECK_NULL_RETURN(firstImage, nullptr);
1927     auto imageIndex = movingPhoto->GetChildIndex(firstImage);
1928     CHECK_NULL_RETURN(imageIndex < movingPhoto->GetTotalChildCount() - 1, nullptr);
1929     auto image = AceType::DynamicCast<FrameNode>(movingPhoto->GetChildAtIndex(imageIndex + 1));
1930     return image;
1931 }
1932 
StopAnimation()1933 void MovingPhotoPattern::StopAnimation()
1934 {
1935     isStopAnimation_ = false;
1936     startAnimationFlag_ = false;
1937     if (historyAutoAndRepeatLevel_ == PlaybackMode::REPEAT) {
1938         StopAnimationCallback();
1939         return;
1940     }
1941     if (isRefreshMovingPhotoPlaying_) {
1942         isRefreshMovingPhotoPlaying_ = false;
1943     }
1944     auto host = GetHost();
1945     CHECK_NULL_VOID(host);
1946     auto movingPhoto = AceType::DynamicCast<MovingPhotoNode>(host);
1947     CHECK_NULL_VOID(movingPhoto);
1948     auto image = AceType::DynamicCast<FrameNode>(movingPhoto->GetImage());
1949     CHECK_NULL_VOID(image);
1950     auto imageLayoutProperty = image->GetLayoutProperty<ImageLayoutProperty>();
1951     CHECK_NULL_VOID(imageLayoutProperty);
1952     auto imageRsContext = image->GetRenderContext();
1953     CHECK_NULL_VOID(imageRsContext);
1954     int32_t childCount = movingPhoto->GetTotalChildCount();
1955     CHECK_NULL_VOID(childCount >= 1);
1956     auto video = AceType::DynamicCast<FrameNode>(movingPhoto->GetVideo(childCount - 1));
1957     CHECK_NULL_VOID(video);
1958     auto videoRsContext = video->GetRenderContext();
1959     CHECK_NULL_VOID(videoRsContext);
1960 
1961     videoRsContext->UpdateOpacity(1.0);
1962     RsContextUpdateTransformScale(imageRsContext, videoRsContext, autoAndRepeatLevel_);
1963     image->MarkModifyDone();
1964     video->MarkModifyDone();
1965     auto movingPhotoPattern = WeakClaim(this);
1966     AnimationOption option;
1967     option.SetDuration(ANIMATION_DURATION_300);
1968     option.SetCurve(Curves::FRICTION);
1969     option.SetOnFinishEvent([movingPhotoPattern]() {
1970         auto movingPhoto = movingPhotoPattern.Upgrade();
1971         CHECK_NULL_VOID(movingPhoto);
1972         movingPhoto->StopAnimationCallback();
1973     });
1974     AnimationUtils::Animate(option, [imageRsContext, videoRsContext]() {
1975             videoRsContext->UpdateOpacity(0.0);
1976             imageRsContext->UpdateTransformScale({NORMAL_SCALE, NORMAL_SCALE});
1977             videoRsContext->UpdateTransformScale({NORMAL_SCALE, NORMAL_SCALE});
1978         }, option.GetOnFinishEvent());
1979 }
1980 
StopAnimationCallback()1981 void MovingPhotoPattern::StopAnimationCallback()
1982 {
1983     if (autoPlayPeriodStartTime_ >= 0) {
1984         Seek(static_cast<int32_t>(autoPlayPeriodStartTime_ / US_CONVERT));
1985     } else {
1986         Seek(0);
1987     }
1988     TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "StopAnimation OnFinishEvent:%{public}d.", autoAndRepeatLevel_);
1989     if (needUpdateImageNode_) {
1990         UpdateImageNode();
1991         needUpdateImageNode_ = false;
1992     }
1993     if (autoAndRepeatLevel_ == PlaybackMode::REPEAT) {
1994         StartRepeatPlay();
1995     } else if (autoAndRepeatLevel_ == PlaybackMode::AUTO) {
1996         autoAndRepeatLevel_ = PlaybackMode::NONE;
1997     }
1998     if (historyAutoAndRepeatLevel_ == PlaybackMode::AUTO) {
1999         HandleImageAnalyzerMode();
2000     }
2001 }
2002 
AutoPlay(bool isAutoPlay)2003 void MovingPhotoPattern::AutoPlay(bool isAutoPlay)
2004 {
2005     TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "movingphoto AutoPlay: %{public}d.", isAutoPlay);
2006     if (isAutoPlay) {
2007         if (historyAutoAndRepeatLevel_ == PlaybackMode::AUTO) {
2008             return;
2009         }
2010         isChangePlayMode_ = true;
2011         if (autoAndRepeatLevel_ != PlaybackMode::REPEAT) {
2012             historyAutoAndRepeatLevel_ = PlaybackMode::AUTO;
2013             autoAndRepeatLevel_ = PlaybackMode::AUTO;
2014             if (!isSetAutoPlayPeriod_ && (currentPlayStatus_ == PlaybackStatus::PLAYBACK_COMPLETE ||
2015                 currentPlayStatus_ == PlaybackStatus::PAUSED)) {
2016                 isSetAutoPlayPeriod_ = true;
2017                 SetAutoPlayPeriod(autoPlayPeriodStartTime_, autoPlayPeriodEndTime_);
2018             }
2019         }
2020     }
2021 }
2022 
StartAutoPlay()2023 void MovingPhotoPattern::StartAutoPlay()
2024 {
2025     TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "movingphoto StartAutoPlay in.");
2026     isFastKeyUp_ = false;
2027     if (!mediaPlayer_ || !mediaPlayer_->IsMediaPlayerValid()) {
2028         return;
2029     }
2030 
2031     if (currentPlayStatus_ == PlaybackStatus::STOPPED) {
2032         mediaPlayer_->PrepareAsync();
2033     }
2034     Start();
2035 }
2036 
StartRepeatPlay()2037 void MovingPhotoPattern::StartRepeatPlay()
2038 {
2039     TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "movingphoto StartRepeatPlay in.");
2040     isFastKeyUp_ = false;
2041     if (!mediaPlayer_ || !mediaPlayer_->IsMediaPlayerValid()) {
2042         return;
2043     }
2044 
2045     if (currentPlayStatus_ == PlaybackStatus::STOPPED) {
2046         mediaPlayer_->PrepareAsync();
2047     }
2048     if (!isFirstRepeatPlay_ && isSetAutoPlayPeriod_) {
2049         int32_t duration = DURATION_FLAG;
2050         mediaPlayer_->GetDuration(duration);
2051         SetAutoPlayPeriod(PERIOD_START, duration * US_CONVERT);
2052     }
2053     Start();
2054 }
2055 
RepeatPlay(bool isRepeatPlay)2056 void MovingPhotoPattern::RepeatPlay(bool isRepeatPlay)
2057 {
2058     TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "movingphoto RepeatPlay status: %{public}d.", isRepeatPlay);
2059     if (isRepeatPlay && historyAutoAndRepeatLevel_ != PlaybackMode::REPEAT) {
2060         isChangePlayMode_ = true;
2061         isFirstRepeatPlay_ = true;
2062     }
2063     if (!isRepeatPlay && historyAutoAndRepeatLevel_ == PlaybackMode::REPEAT) {
2064         isChangePlayMode_ = true;
2065         historyAutoAndRepeatLevel_ = PlaybackMode::NONE;
2066         Pause();
2067         StopAnimation();
2068     }
2069     if (isRepeatPlay) {
2070         historyAutoAndRepeatLevel_ = PlaybackMode::REPEAT;
2071         autoAndRepeatLevel_ = PlaybackMode::REPEAT;
2072     }
2073 }
2074 
AutoPlayPeriod(int64_t startTime,int64_t endTime)2075 void MovingPhotoPattern::AutoPlayPeriod(int64_t startTime, int64_t endTime)
2076 {
2077     TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "movingphoto AutoPlayPeriod: [%{public}lld, %{public}lld].",
2078         static_cast<long long>(startTime), static_cast<long long>(endTime));
2079     if (startTime >= VIDEO_PLAYTIME_START_POSITION && startTime < endTime) {
2080         autoPlayPeriodStartTime_ = startTime;
2081         autoPlayPeriodEndTime_ = endTime;
2082     }
2083 }
2084 
SetAutoPlayPeriod(int64_t startTime,int64_t endTime)2085 void MovingPhotoPattern::SetAutoPlayPeriod(int64_t startTime, int64_t endTime)
2086 {
2087     TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "movingphoto SetAutoPlayPeriod: [%{public}lld, %{public}lld].",
2088         static_cast<long long>(startTime), static_cast<long long>(endTime));
2089     if (startTime < VIDEO_PLAYTIME_START_POSITION || startTime >= endTime) {
2090         TAG_LOGW(AceLogTag::ACE_MOVING_PHOTO, "MediaPlayer SetAutoPlayPeriod error.");
2091         return;
2092     }
2093     if (!mediaPlayer_ || !mediaPlayer_->IsMediaPlayerValid()) {
2094         TAG_LOGW(AceLogTag::ACE_MOVING_PHOTO, "MediaPlayer is null or invalid.");
2095         return;
2096     }
2097     mediaPlayer_->SetPlayRangeUsWithMode(startTime, endTime, SeekMode::SEEK_CLOSEST);
2098 }
2099 
HandleImageAnalyzerPlayCallBack()2100 void MovingPhotoPattern::HandleImageAnalyzerPlayCallBack()
2101 {
2102     TAG_LOGW(AceLogTag::ACE_MOVING_PHOTO, "HandleImageAnalyzerPlayCallBack start.");
2103     isFastKeyUp_ = false;
2104     if (currentPlayStatus_ == PlaybackStatus::STARTED || !isPrepared_ || isPlayByController_) {
2105         return;
2106     }
2107     if (IsRefreshMovingPhotoReturn(isRefreshMovingPhoto_)) {
2108         TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "HandleTouchEvent IsRefreshMovingPhotoReturn.");
2109         return;
2110     }
2111     if (!mediaPlayer_ || !mediaPlayer_->IsMediaPlayerValid()) {
2112         TAG_LOGW(AceLogTag::ACE_MOVING_PHOTO, "MediaPlayer is null or invalid.");
2113         FireMediaPlayerError();
2114         return;
2115     }
2116     if (currentPlayStatus_ == PlaybackStatus::STOPPED) {
2117         mediaPlayer_->PrepareAsync();
2118     }
2119     if (isSetAutoPlayPeriod_ && (currentPlayStatus_ == PlaybackStatus::PLAYBACK_COMPLETE ||
2120         currentPlayStatus_ == PlaybackStatus::PAUSED)) {
2121         int32_t duration = DURATION_FLAG;
2122         mediaPlayer_->GetDuration(duration);
2123         SetAutoPlayPeriod(PERIOD_START, duration * US_CONVERT);
2124     }
2125     Start();
2126 }
2127 
Start()2128 void MovingPhotoPattern::Start()
2129 {
2130     TAG_LOGW(AceLogTag::ACE_MOVING_PHOTO, "movingphoto start play.");
2131     if (!mediaPlayer_ || !mediaPlayer_->IsMediaPlayerValid()) {
2132         TAG_LOGW(AceLogTag::ACE_MOVING_PHOTO, "MediaPlayer is null or invalid.");
2133         return;
2134     }
2135     if (isRefreshMovingPhoto_) {
2136         isRefreshMovingPhoto_ = false;
2137     }
2138     if (currentPlayStatus_ == PlaybackStatus::STOPPED) {
2139         mediaPlayer_->PrepareAsync();
2140     }
2141     ContainerScope scope(instanceId_);
2142     auto context = PipelineContext::GetCurrentContext();
2143     CHECK_NULL_VOID(context);
2144     if (cameraPostprocessingEnabled_) {
2145         mediaPlayer_->SetCameraPostprocessing(isGestureTriggeredLongPress_);
2146         isGestureTriggeredLongPress_ = false;
2147     }
2148 
2149     auto platformTask = SingleTaskExecutor::Make(context->GetTaskExecutor(), TaskExecutor::TaskType::BACKGROUND);
2150     platformTask.PostTask(
2151         [weak = WeakClaim(RawPtr(mediaPlayer_))] {
2152             auto mediaPlayer = weak.Upgrade();
2153             CHECK_NULL_VOID(mediaPlayer);
2154             mediaPlayer->Play();
2155         },
2156         "ArkUIMovingPhotoStartPlay");
2157 }
2158 
Pause()2159 void MovingPhotoPattern::Pause()
2160 {
2161     if (!mediaPlayer_ || !mediaPlayer_->IsMediaPlayerValid()) {
2162         TAG_LOGW(AceLogTag::ACE_MOVING_PHOTO, "MediaPlayer is null or invalid.");
2163         return;
2164     }
2165     ContainerScope scope(instanceId_);
2166     auto context = PipelineContext::GetCurrentContext();
2167     CHECK_NULL_VOID(context);
2168 
2169     auto platformTask = SingleTaskExecutor::Make(context->GetTaskExecutor(), TaskExecutor::TaskType::BACKGROUND);
2170     platformTask.PostTask(
2171         [weak = WeakClaim(RawPtr(mediaPlayer_))] {
2172             auto mediaPlayer = weak.Upgrade();
2173             CHECK_NULL_VOID(mediaPlayer);
2174             mediaPlayer->Pause();
2175         },
2176         "ArkUIMovingPhotoPausePlay");
2177 }
2178 
Stop()2179 void MovingPhotoPattern::Stop()
2180 {
2181     if (!mediaPlayer_ || !mediaPlayer_->IsMediaPlayerValid()) {
2182         TAG_LOGW(AceLogTag::ACE_MOVING_PHOTO, "MediaPlayer is null or invalid.");
2183         return;
2184     }
2185     ContainerScope scope(instanceId_);
2186     auto context = PipelineContext::GetCurrentContext();
2187     CHECK_NULL_VOID(context);
2188 
2189     auto platformTask = SingleTaskExecutor::Make(context->GetTaskExecutor(), TaskExecutor::TaskType::BACKGROUND);
2190     platformTask.PostTask(
2191         [weak = WeakClaim(RawPtr(mediaPlayer_))] {
2192             auto mediaPlayer = weak.Upgrade();
2193             CHECK_NULL_VOID(mediaPlayer);
2194             mediaPlayer->Stop();
2195         },
2196         "ArkUIMovingPhotoStopPlay");
2197 }
2198 
Seek(int32_t position)2199 void MovingPhotoPattern::Seek(int32_t position)
2200 {
2201     if (!mediaPlayer_ || !mediaPlayer_->IsMediaPlayerValid()) {
2202         TAG_LOGW(AceLogTag::ACE_MOVING_PHOTO, "MediaPlayer is null or invalid.");
2203         return;
2204     }
2205     ContainerScope scope(instanceId_);
2206     auto context = PipelineContext::GetCurrentContext();
2207     CHECK_NULL_VOID(context);
2208 
2209     auto platformTask = SingleTaskExecutor::Make(context->GetTaskExecutor(), TaskExecutor::TaskType::BACKGROUND);
2210     platformTask.PostTask(
2211         [weak = WeakClaim(RawPtr(mediaPlayer_)), pos = position] {
2212             auto mediaPlayer = weak.Upgrade();
2213             CHECK_NULL_VOID(mediaPlayer);
2214             mediaPlayer->Seek(pos, SeekMode::SEEK_PREVIOUS_SYNC);
2215         },
2216         "ArkUIMovingPhotoSeek");
2217 }
2218 
UpdateMediaPlayerSpeed()2219 void MovingPhotoPattern::UpdateMediaPlayerSpeed()
2220 {
2221     if (!mediaPlayer_ || !mediaPlayer_->IsMediaPlayerValid()) {
2222         TAG_LOGW(AceLogTag::ACE_MOVING_PHOTO, "MediaPlayer is null or invalid.");
2223         return;
2224     }
2225     ContainerScope scope(instanceId_);
2226     auto context = PipelineContext::GetCurrentContext();
2227     CHECK_NULL_VOID(context);
2228     auto platformTask = SingleTaskExecutor::Make(context->GetTaskExecutor(), TaskExecutor::TaskType::BACKGROUND);
2229     platformTask.PostTask(
2230         [weak = WeakClaim(RawPtr(mediaPlayer_))] {
2231             auto mediaPlayer = weak.Upgrade();
2232             CHECK_NULL_VOID(mediaPlayer);
2233             mediaPlayer->SetPlaybackSpeed(static_cast<float>(NORMAL_PLAY_SPEED));
2234         },
2235         "ArkUIMovingPhotoUpdateSpeed");
2236 }
2237 
UpdateMediaPlayerMuted()2238 void MovingPhotoPattern::UpdateMediaPlayerMuted()
2239 {
2240     if (!mediaPlayer_ || !mediaPlayer_->IsMediaPlayerValid()) {
2241         TAG_LOGW(AceLogTag::ACE_MOVING_PHOTO, "MediaPlayer is null or invalid.");
2242         return;
2243     }
2244     ContainerScope scope(instanceId_);
2245     float volume = isMuted_ ? 0.0f : 1.0f;
2246     auto context = PipelineContext::GetCurrentContext();
2247     CHECK_NULL_VOID(context);
2248     auto platformTask = SingleTaskExecutor::Make(context->GetTaskExecutor(), TaskExecutor::TaskType::BACKGROUND);
2249     platformTask.PostTask(
2250         [weak = WeakClaim(RawPtr(mediaPlayer_)), videoVolume = volume] {
2251             auto mediaPlayer = weak.Upgrade();
2252             CHECK_NULL_VOID(mediaPlayer);
2253             mediaPlayer->SetVolume(videoVolume, videoVolume);
2254         },
2255         "ArkUIMovingPhotoUpdateMuted");
2256 }
2257 
OnAreaChangedInner()2258 void MovingPhotoPattern::OnAreaChangedInner()
2259 {
2260 }
2261 
OnVisibleChange(bool isVisible)2262 void MovingPhotoPattern::OnVisibleChange(bool isVisible)
2263 {
2264     CHECK_NULL_VOID(mediaPlayer_);
2265     if (!isVisible) {
2266         StopPlayback();
2267     }
2268 }
2269 
OnWindowHide()2270 void MovingPhotoPattern::OnWindowHide()
2271 {
2272     TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "movingphoto OnWindowHide.");
2273     if (historyAutoAndRepeatLevel_ == PlaybackMode::AUTO) {
2274         PausePlayback();
2275     } else if (historyAutoAndRepeatLevel_ == PlaybackMode::REPEAT) {
2276         StopPlayback();
2277         return;
2278     }
2279     auto host = GetHost();
2280     CHECK_NULL_VOID(host);
2281     auto movingPhoto = AceType::DynamicCast<MovingPhotoNode>(host);
2282     CHECK_NULL_VOID(movingPhoto);
2283     auto image = AceType::DynamicCast<FrameNode>(movingPhoto->GetImage());
2284     CHECK_NULL_VOID(image);
2285     auto imageLayoutProperty = image->GetLayoutProperty<ImageLayoutProperty>();
2286     CHECK_NULL_VOID(imageLayoutProperty);
2287     imageLayoutProperty->UpdateVisibility(VisibleType::VISIBLE);
2288     auto rsContext = image->GetRenderContext();
2289     CHECK_NULL_VOID(rsContext);
2290     rsContext->UpdateOpacity(1.0);
2291     image->MarkModifyDone();
2292 }
2293 
OnWindowShow()2294 void MovingPhotoPattern::OnWindowShow()
2295 {
2296     TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "movingphoto OnWindowShow.");
2297     CHECK_NULL_VOID(mediaPlayer_);
2298     if (autoAndRepeatLevel_ == PlaybackMode::REPEAT && currentPlayStatus_ == PlaybackStatus::STOPPED) {
2299         mediaPlayer_->PrepareAsync();
2300     }
2301 }
2302 
AddWindowStateChangedCallback()2303 void MovingPhotoPattern::AddWindowStateChangedCallback()
2304 {
2305     auto host = GetHost();
2306     CHECK_NULL_VOID(host);
2307     auto pipelineContext = PipelineContext::GetCurrentContext();
2308     CHECK_NULL_VOID(pipelineContext);
2309     pipelineContext->AddWindowStateChangedCallback(host->GetId());
2310 }
2311 
RegisterVisibleAreaChange()2312 void MovingPhotoPattern::RegisterVisibleAreaChange()
2313 {
2314     TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "movingphoto RegisterVisibleAreaChange.");
2315     if (hasVisibleChangeRegistered_) {
2316         return;
2317     }
2318     auto pipeline = PipelineContext::GetCurrentContextSafely();
2319     CHECK_NULL_VOID(pipeline);
2320     auto callback = [weak = WeakClaim(this)](bool visible, double ratio) {
2321         auto pattern = weak.Upgrade();
2322         CHECK_NULL_VOID(pattern);
2323         pattern->isVisible_ = visible;
2324         pattern->VisibleAreaCallback(visible);
2325     };
2326     auto host = GetHost();
2327     CHECK_NULL_VOID(host);
2328     std::vector<double> ratioList = {1.0};
2329     pipeline->AddVisibleAreaChangeNode(host, ratioList, callback, false, true);
2330     hasVisibleChangeRegistered_ = true;
2331 }
2332 
VisibleAreaCallback(bool visible)2333 void MovingPhotoPattern::VisibleAreaCallback(bool visible)
2334 {
2335     TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "movingphoto VisibleAreaCallback:%{public}d.", visible);
2336     if (visible) {
2337         if (historyAutoAndRepeatLevel_ == PlaybackMode::AUTO) {
2338             isSetAutoPlayPeriod_ = true;
2339             SetAutoPlayPeriod(autoPlayPeriodStartTime_, autoPlayPeriodEndTime_);
2340         }
2341         MediaResetToPlay();
2342     } else {
2343         if (historyAutoAndRepeatLevel_ == PlaybackMode::AUTO) {
2344             PausePlayback();
2345         } else if (historyAutoAndRepeatLevel_ == PlaybackMode::REPEAT) {
2346             StopPlayback();
2347         }
2348         if (isRefreshMovingPhoto_) {
2349             isSetAutoPlayPeriod_ = false;
2350             ResetMediaPlayer();
2351         }
2352     }
2353 }
2354 
EnableAnalyzer(bool enabled)2355 void MovingPhotoPattern::EnableAnalyzer(bool enabled)
2356 {
2357     TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "movingphoto EnableAnalyzer:%{public}d.", enabled);
2358     isEnableAnalyzer_ = enabled;
2359     if (!isEnableAnalyzer_) {
2360         DestroyAnalyzerOverlay();
2361         LongPressEventModify(true);
2362         return;
2363     }
2364 
2365     CHECK_NULL_VOID(!imageAnalyzerManager_);
2366     auto host = GetHost();
2367     CHECK_NULL_VOID(host);
2368     imageAnalyzerManager_ = std::make_shared<ImageAnalyzerManager>(host, ImageAnalyzerHolder::MOVINGPHOTO);
2369 }
2370 
SetImageAIOptions(void * options)2371 void MovingPhotoPattern::SetImageAIOptions(void* options)
2372 {
2373     TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "movingphoto SetImageAIOptions");
2374     if (!imageAnalyzerManager_) {
2375         imageAnalyzerManager_ = std::make_shared<ImageAnalyzerManager>(GetHost(), ImageAnalyzerHolder::MOVINGPHOTO);
2376     }
2377     CHECK_NULL_VOID(imageAnalyzerManager_);
2378     imageAnalyzerManager_->SetImageAIOptions(options);
2379 }
2380 
IsSupportImageAnalyzer()2381 bool MovingPhotoPattern::IsSupportImageAnalyzer()
2382 {
2383     TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "movingphoto IsSupportImageAnalyzer");
2384     auto host = GetHost();
2385     CHECK_NULL_RETURN(host, false);
2386     auto layoutProperty = host->GetLayoutProperty<MovingPhotoLayoutProperty>();
2387     CHECK_NULL_RETURN(layoutProperty, false);
2388     CHECK_NULL_RETURN(imageAnalyzerManager_, false);
2389     return imageAnalyzerManager_->IsSupportImageAnalyzerFeature();
2390 }
2391 
ShouldUpdateImageAnalyzer()2392 bool MovingPhotoPattern::ShouldUpdateImageAnalyzer()
2393 {
2394     TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "movingphoto ShouldUpdateImageAnalyzer");
2395     auto layoutProperty = GetLayoutProperty<MovingPhotoLayoutProperty>();
2396     CHECK_NULL_RETURN(layoutProperty, false);
2397     const auto& constraint = layoutProperty->GetCalcLayoutConstraint();
2398     if (!constraint || !constraint->selfIdealSize.has_value() || !constraint->selfIdealSize->IsValid()) {
2399         return false;
2400     }
2401     auto selfIdealSize = constraint->selfIdealSize;
2402     if (!selfIdealSize->PercentWidth() && !selfIdealSize->PercentHeight()) {
2403         return false;
2404     }
2405     auto imageFit = layoutProperty->GetObjectFit().value_or(ImageFit::COVER);
2406     if (imageFit != ImageFit::COVER && imageFit != ImageFit::NONE) {
2407         return false;
2408     }
2409     return true;
2410 }
2411 
StartImageAnalyzer()2412 void MovingPhotoPattern::StartImageAnalyzer()
2413 {
2414     TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "movingphoto StartImageAnalyzer");
2415     if (!IsSupportImageAnalyzer() || !imageAnalyzerManager_) {
2416         return;
2417     }
2418 
2419     if (imageAnalyzerManager_->IsOverlayCreated()) {
2420         DestroyAnalyzerOverlay();
2421         LongPressEventModify(true);
2422     }
2423 
2424     ContainerScope scope(instanceId_);
2425     auto host = GetHost();
2426     CHECK_NULL_VOID(host);
2427     auto context = host->GetContext();
2428     CHECK_NULL_VOID(context);
2429     auto uiTaskExecutor = SingleTaskExecutor::Make(context->GetTaskExecutor(), TaskExecutor::TaskType::UI);
2430     uiTaskExecutor.PostDelayedTask([weak = WeakClaim(this)] {
2431         auto pattern = weak.Upgrade();
2432         CHECK_NULL_VOID(pattern);
2433         pattern->CreateAnalyzerOverlay();
2434         }, ANALYZER_DELAY_TIME, "ArkUIMovingPhotoCreateAnalyzerOverlay");
2435     LongPressEventModify(false);
2436 }
2437 
CreateAnalyzerOverlay()2438 void MovingPhotoPattern::CreateAnalyzerOverlay()
2439 {
2440     TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "movingphoto CreateAnalyzerOverlay");
2441     CHECK_NULL_VOID(imageAnalyzerManager_);
2442     if (imageAnalyzerManager_->IsOverlayCreated()) {
2443         return;
2444     }
2445     GetPixelMap();
2446     int64_t coverPosition = GetUriCoverPosition();
2447     auto onCanPlay = [weak = AceType::WeakClaim(this)](bool canPlay) {
2448         auto pattern = weak.Upgrade();
2449         CHECK_NULL_VOID(pattern);
2450         pattern->HandleAnalyzerPlayEvent(canPlay);
2451     };
2452     auto host = GetHost();
2453     CHECK_NULL_VOID(host);
2454     auto geometryNode = host->GetGeometryNode();
2455     CHECK_NULL_VOID(geometryNode);
2456     auto movingPhotoNodeSize = geometryNode->GetContentSize();
2457     MovingPhotoAnalyzerInfo info = {uri_, coverPosition,
2458                                     movingPhotoNodeSize.Width(),
2459                                     movingPhotoNodeSize.Height()};
2460     imageAnalyzerManager_->SetOnCanPlayCallback(std::move(onCanPlay));
2461     imageAnalyzerManager_->CreateMovingPhotoAnalyzerOverlay(pixelMap_, info);
2462 }
2463 
StartUpdateImageAnalyzer()2464 void MovingPhotoPattern::StartUpdateImageAnalyzer()
2465 {
2466     TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "movingphoto StartUpdateImageAnalyzer");
2467     CHECK_NULL_VOID(imageAnalyzerManager_);
2468     if (!imageAnalyzerManager_->IsOverlayCreated()) {
2469         return;
2470     }
2471 
2472     UpdateOverlayVisibility(VisibleType::GONE);
2473     ContainerScope scope(instanceId_);
2474     auto host = GetHost();
2475     CHECK_NULL_VOID(host);
2476     auto context = host->GetContext();
2477     CHECK_NULL_VOID(context);
2478     auto uiTaskExecutor = SingleTaskExecutor::Make(context->GetTaskExecutor(), TaskExecutor::TaskType::UI);
2479     uiTaskExecutor.PostDelayedTask([weak = WeakClaim(this)] {
2480         auto pattern = weak.Upgrade();
2481         CHECK_NULL_VOID(pattern);
2482         if (!pattern->isContentSizeChanged_) {
2483             return;
2484         }
2485         pattern->UpdateAnalyzerOverlay();
2486         pattern->isContentSizeChanged_ = false;
2487         }, ANALYZER_CAPTURE_DELAY_TIME, "ArkUIMovingPhotoUpdateAnalyzerOverlay");
2488     isContentSizeChanged_ = true;
2489 }
2490 
UpdateAnalyzerOverlay()2491 void MovingPhotoPattern::UpdateAnalyzerOverlay()
2492 {
2493     TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "movingphoto UpdateAnalyzerOverlay");
2494     CHECK_NULL_VOID(imageAnalyzerManager_);
2495     if (!IsSupportImageAnalyzer() || !imageAnalyzerManager_->IsOverlayCreated()) {
2496         return;
2497     }
2498     GetPixelMap();
2499     int64_t coverPosition = GetUriCoverPosition();
2500     UpdateOverlayVisibility(VisibleType::VISIBLE);
2501     auto host = GetHost();
2502     CHECK_NULL_VOID(host);
2503     auto geometryNode = host->GetGeometryNode();
2504     CHECK_NULL_VOID(geometryNode);
2505     auto movingPhotoNodeSize = geometryNode->GetContentSize();
2506     MovingPhotoAnalyzerInfo info = {uri_, coverPosition,
2507                                     movingPhotoNodeSize.Width(),
2508                                     movingPhotoNodeSize.Height()};
2509     imageAnalyzerManager_->UpdateMovingPhotoAnalyzerOverlay(pixelMap_, info);
2510 }
2511 
UpdateAnalyzerUIConfig(const RefPtr<NG::GeometryNode> & geometryNode)2512 void MovingPhotoPattern::UpdateAnalyzerUIConfig(const RefPtr<NG::GeometryNode>& geometryNode)
2513 {
2514     TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "movingphoto UpdateAnalyzerUIConfig");
2515     auto movingPhotoNodeSize = geometryNode->GetContentSize();
2516     auto layoutProperty = GetLayoutProperty<MovingPhotoLayoutProperty>();
2517     CHECK_NULL_VOID(layoutProperty);
2518     auto videoFrameSize = MeasureContentLayout(movingPhotoNodeSize, layoutProperty);
2519     Rect tmpRect;
2520     auto padding = layoutProperty->CreatePaddingAndBorder();
2521     auto imageFit = layoutProperty->GetObjectFitValue(ImageFit::COVER);
2522     if (imageFit == ImageFit::COVER || imageFit == ImageFit::NONE) {
2523         tmpRect = Rect(padding.left.value_or(0), padding.top.value_or(0),
2524                        movingPhotoNodeSize.Width(), movingPhotoNodeSize.Height());
2525     } else {
2526         tmpRect = Rect(
2527             (movingPhotoNodeSize.Width() - videoFrameSize.Width()) / AVERAGE_VALUE + padding.left.value_or(0),
2528             (movingPhotoNodeSize.Height() - videoFrameSize.Height()) / AVERAGE_VALUE + padding.top.value_or(0),
2529             videoFrameSize.Width(), videoFrameSize.Height());
2530     }
2531     contentRect_ = tmpRect;
2532     if (IsSupportImageAnalyzer()) {
2533         auto layoutProperty = GetLayoutProperty<MovingPhotoLayoutProperty>();
2534         CHECK_NULL_VOID(layoutProperty);
2535         auto padding  = layoutProperty->CreatePaddingAndBorder();
2536         OffsetF contentOffset = { contentRect_.Left() - padding.left.value_or(0),
2537                                   contentRect_.Top() - padding.top.value_or(0) };
2538         PixelMapInfo info = { contentRect_.GetSize().Width(), contentRect_.GetSize().Height(), contentOffset };
2539         CHECK_NULL_VOID(imageAnalyzerManager_);
2540         imageAnalyzerManager_->UpdateAnalyzerUIConfig(geometryNode, info);
2541     }
2542 }
2543 
DestroyAnalyzerOverlay()2544 void MovingPhotoPattern::DestroyAnalyzerOverlay()
2545 {
2546     TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "movingphoto DestroyAnalyzerOverlay");
2547     CHECK_NULL_VOID(imageAnalyzerManager_);
2548     imageAnalyzerManager_->DestroyAnalyzerOverlay();
2549 }
2550 
GetAnalyzerState()2551 bool MovingPhotoPattern::GetAnalyzerState()
2552 {
2553     TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "movingphoto GetAnalyzerState");
2554     CHECK_NULL_RETURN(imageAnalyzerManager_, false);
2555     return imageAnalyzerManager_->IsOverlayCreated();
2556 }
2557 
UpdateOverlayVisibility(VisibleType type)2558 void MovingPhotoPattern::UpdateOverlayVisibility(VisibleType type)
2559 {
2560     auto host = GetHost();
2561     CHECK_NULL_VOID(host);
2562     auto overlayNode = host->GetOverlayNode();
2563     CHECK_NULL_VOID(overlayNode);
2564     auto prop = overlayNode->GetLayoutProperty();
2565     CHECK_NULL_VOID(prop);
2566     prop->UpdateVisibility(type);
2567 }
2568 
GetPixelMap()2569 void MovingPhotoPattern::GetPixelMap()
2570 {
2571     auto layoutProperty = GetLayoutProperty<MovingPhotoLayoutProperty>();
2572     CHECK_NULL_VOID(layoutProperty);
2573     if (!layoutProperty->HasMovingPhotoUri() || !layoutProperty->HasVideoSource()) {
2574         TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "GetPixelMap MovingPhoto source is null.");
2575         return;
2576     }
2577     auto pipeline = PipelineBase::GetCurrentContext();
2578     CHECK_NULL_VOID(pipeline);
2579     auto dataProvider = AceType::DynamicCast<DataProviderManagerStandard>(pipeline->GetDataProviderManager());
2580     CHECK_NULL_VOID(dataProvider);
2581     std::string imageSrc = dataProvider->GetMovingPhotoImagePath(uri_);
2582     std::string thumbnailUrl = uri_ + THUMBNAIL_MEDIUM_JOINT + imageSrc;
2583     void* pixelMapMediauniquePtr = dataProvider->GetDataProviderThumbnailResFromUri(thumbnailUrl);
2584     CHECK_NULL_VOID(pixelMapMediauniquePtr);
2585     auto pixelMap = PixelMap::CreatePixelMapFromDataAbility(pixelMapMediauniquePtr);
2586     CHECK_NULL_VOID(pixelMap);
2587     pixelMap_ = pixelMap;
2588 }
2589 
GetUriCoverPosition()2590 int64_t MovingPhotoPattern::GetUriCoverPosition()
2591 {
2592     auto pipeline = PipelineBase::GetCurrentContext();
2593     CHECK_NULL_RETURN(pipeline, -1);
2594     auto dataProvider = AceType::DynamicCast<DataProviderManagerStandard>(pipeline->GetDataProviderManager());
2595     CHECK_NULL_RETURN(dataProvider, -1);
2596     std::vector<std::string> columns = {COVER_POSITION};
2597     auto result = dataProvider->GetMovingPhotoCoverPosition(IMAGE_URI, uri_, columns);
2598     return result;
2599 }
2600 
HandleAnalyzerPlayEvent(bool canPlay)2601 void MovingPhotoPattern::HandleAnalyzerPlayEvent(bool canPlay)
2602 {
2603     TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "MovingPhoto HandleAnalyzerPlayEvent:%{public}d", canPlay);
2604     if (isAnalyzerPlaying_ == canPlay || isPlayByController_) {
2605         return;
2606     }
2607     if (isAnalyzerPlaying_ && !canPlay) {
2608         Pause();
2609         StopAnimation();
2610     }
2611     isAnalyzerPlaying_ = canPlay;
2612     if (canPlay) {
2613         if (isRefreshMovingPhoto_) {
2614             isRefreshMovingPhotoPlaying_ = true;
2615         }
2616         HandleImageAnalyzerPlayCallBack();
2617     }
2618 }
2619 
IsRefreshMovingPhotoReturn(bool status)2620 bool MovingPhotoPattern::IsRefreshMovingPhotoReturn(bool status)
2621 {
2622     if (status) {
2623         if (autoAndRepeatLevel_ == PlaybackMode::REPEAT) {
2624             TAG_LOGW(AceLogTag::ACE_MOVING_PHOTO, "IsRefreshMovingPhotoReturn:%{public}d.", status);
2625             return true;
2626         }
2627     } else {
2628         if (autoAndRepeatLevel_ != PlaybackMode::NONE && !isStopAnimation_) {
2629             TAG_LOGW(AceLogTag::ACE_MOVING_PHOTO, "IsRefreshMovingPhotoReturn not:%{public}d.", status);
2630             return true;
2631         }
2632     }
2633     return false;
2634 }
2635 
SetHdrBrightness(float hdrBrightness)2636 void MovingPhotoPattern::SetHdrBrightness(float hdrBrightness)
2637 {
2638     TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "SetHdrBrightness:%{public}f.", hdrBrightness);
2639     auto host = GetHost();
2640     CHECK_NULL_VOID(host);
2641     auto movingPhotoNode = AceType::DynamicCast<MovingPhotoNode>(host);
2642     CHECK_NULL_VOID(movingPhotoNode);
2643     auto imageNode = AceType::DynamicCast<FrameNode>(movingPhotoNode->GetImage());
2644     CHECK_NULL_VOID(imageNode);
2645     auto imageRenderContext = imageNode->GetRenderContext();
2646     CHECK_NULL_VOID(imageRenderContext);
2647     imageRenderContext->SetImageHDRBrightness(hdrBrightness);
2648     imageRenderContext->SetImageHDRPresent(true);
2649     ACE_UPDATE_NODE_PAINT_PROPERTY(ImageRenderProperty, HdrBrightness, hdrBrightness, imageNode);
2650     hdrBrightness_ = hdrBrightness;
2651 }
2652 
~MovingPhotoPattern()2653 MovingPhotoPattern::~MovingPhotoPattern()
2654 {
2655     if (IsSupportImageAnalyzer()) {
2656         TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "~MovingPhotoPattern DestroyAnalyzerOverlay.");
2657         DestroyAnalyzerOverlay();
2658     }
2659 }
2660 } // namespace OHOS::Ace::NG