• 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 
26 namespace OHOS::Ace::NG {
27 namespace {
28 constexpr int32_t LONG_PRESS_DELAY = 300;
29 constexpr int32_t ANIMATION_DURATION_300 = 300;
30 constexpr int32_t ANIMATION_DURATION_400 = 400;
31 constexpr float NORMAL_SCALE = 1.0f;
32 constexpr float ZOOM_IN_SCALE = 1.1f;
33 constexpr double NORMAL_PLAY_SPEED = 1.0;
34 constexpr int32_t HALF = 2;
35 constexpr int64_t PERIOD_START = 0;
36 constexpr int32_t PREPARE_RETURN = 0;
37 constexpr int64_t VIDEO_PLAYTIME_START_POSITION = 0;
38 constexpr int32_t IMAGE_LOADING_COMPLETE = 0;
39 constexpr int32_t DURATION_FLAG = -1;
40 const std::string THUMBNAIL_MEDIUM_JOINT = "?&oper=thumbnail&width=-1&height=-1&path=";
41 const std::string COVER_POSITION = "cover_positon";
42 const std::string IMAGE_URI = "uri";
43 const std::string VIDEO_SCALE = "video_scale_type";
44 constexpr int32_t ANALYZER_DELAY_TIME = 100;
45 constexpr int32_t ANALYZER_CAPTURE_DELAY_TIME = 1000;
46 constexpr int32_t AVERAGE_VALUE = 2;
47 }
MovingPhotoPattern(const RefPtr<MovingPhotoController> & controller)48 MovingPhotoPattern::MovingPhotoPattern(const RefPtr<MovingPhotoController>& controller)
49     : instanceId_(Container::CurrentId()), controller_(controller)
50 {}
51 
OnModifyDone()52 void MovingPhotoPattern::OnModifyDone()
53 {
54     TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "movingphoto onModifydone start.");
55     Pattern::OnModifyDone();
56     UpdateImageNode();
57     UpdateVideoNode();
58     if (SystemProperties::GetExtSurfaceEnabled()) {
59         auto pipelineContext = PipelineContext::GetCurrentContext();
60         CHECK_NULL_VOID(pipelineContext);
61         auto host = GetHost();
62         CHECK_NULL_VOID(host);
63         pipelineContext->AddOnAreaChangeNode(host->GetId());
64     }
65     InitEvent();
66     UpdatePlayMode();
67     HandleImageAnalyzerMode();
68 }
69 
OnAttachToFrameNode()70 void MovingPhotoPattern::OnAttachToFrameNode()
71 {
72     auto host = GetHost();
73     CHECK_NULL_VOID(host);
74     auto renderContext = host->GetRenderContext();
75     CHECK_NULL_VOID(renderContext);
76     static RenderContext::ContextParam param = { RenderContext::ContextType::HARDWARE_SURFACE, "MediaPlayerSurface",
77                                                  RenderContext::PatternType::VIDEO };
78     renderContextForMediaPlayer_->InitContext(false, param);
79     renderContext->UpdateBackgroundColor(Color::TRANSPARENT);
80     renderContextForMediaPlayer_->UpdateBackgroundColor(Color::TRANSPARENT);
81     renderContext->SetClipToBounds(true);
82 
83     auto pipelineContext = PipelineContext::GetCurrentContext();
84     CHECK_NULL_VOID(pipelineContext);
85     pipelineContext->AddWindowStateChangedCallback(host->GetId());
86 
87     CHECK_NULL_VOID(controller_);
88     ContainerScope scope(instanceId_);
89     auto context = PipelineContext::GetCurrentContext();
90     CHECK_NULL_VOID(context);
91     auto uiTaskExecutor = SingleTaskExecutor::Make(context->GetTaskExecutor(), TaskExecutor::TaskType::UI);
92     controller_->SetStartPlaybackImpl([weak = WeakClaim(this), uiTaskExecutor]() {
93         uiTaskExecutor.PostTask(
94             [weak]() {
95                 auto pattern = weak.Upgrade();
96                 CHECK_NULL_VOID(pattern);
97                 ContainerScope scope(pattern->instanceId_);
98                 pattern->StartPlayback();
99             }, "ArkUIMovingPhotoStart");
100     });
101 
102     controller_->SetStopPlaybackImpl([weak = WeakClaim(this), uiTaskExecutor]() {
103         uiTaskExecutor.PostTask(
104             [weak]() {
105                 auto pattern = weak.Upgrade();
106                 CHECK_NULL_VOID(pattern);
107                 ContainerScope scope(pattern->instanceId_);
108                 pattern->StopPlayback();
109             }, "ArkUIMovingPhotoStop");
110     });
111 
112     controller_->SetRefreshMovingPhotoImpl([weak = WeakClaim(this), uiTaskExecutor]() {
113         uiTaskExecutor.PostTask(
114             [weak]() {
115                 auto pattern = weak.Upgrade();
116                 CHECK_NULL_VOID(pattern);
117                 ContainerScope scope(pattern->instanceId_);
118                 pattern->RefreshMovingPhoto();
119             }, "RefreshMovingPhoto");
120     });
121 
122     RegisterVisibleAreaChange();
123 }
124 
OnDetachFromFrameNode(FrameNode * frameNode)125 void MovingPhotoPattern::OnDetachFromFrameNode(FrameNode* frameNode)
126 {
127     auto id = frameNode->GetId();
128     auto pipeline = AceType::DynamicCast<PipelineContext>(PipelineBase::GetCurrentContext());
129     CHECK_NULL_VOID(pipeline);
130     pipeline->RemoveWindowStateChangedCallback(id);
131     hasVisibleChangeRegistered_ = false;
132 }
133 
OnDetachFromMainTree()134 void MovingPhotoPattern::OnDetachFromMainTree()
135 {
136     auto host = GetHost();
137     CHECK_NULL_VOID(host);
138     if (host->GetNodeStatus() == NodeStatus::BUILDER_NODE_OFF_MAINTREE) {
139         Stop();
140     }
141 }
142 
OnRebuildFrame()143 void MovingPhotoPattern::OnRebuildFrame()
144 {
145     if (!renderSurface_ || !renderSurface_->IsSurfaceValid()) {
146         return;
147     }
148     auto host = GetHost();
149     CHECK_NULL_VOID(host);
150     auto movingPhotoNode = AceType::DynamicCast<MovingPhotoNode>(host);
151     CHECK_NULL_VOID(movingPhotoNode);
152     auto video = AceType::DynamicCast<FrameNode>(movingPhotoNode->GetVideo());
153     CHECK_NULL_VOID(video);
154     auto renderContext = video->GetRenderContext();
155     renderContext->AddChild(renderContextForMediaPlayer_, 0);
156 }
157 
InitEvent()158 void MovingPhotoPattern::InitEvent()
159 {
160     auto host = GetHost();
161     CHECK_NULL_VOID(host);
162     auto gestureHub = host->GetOrCreateGestureEventHub();
163     CHECK_NULL_VOID(gestureHub);
164     if (longPressEvent_) {
165         if (isEnableAnalyzer_) {
166             gestureHub->SetLongPressEvent(nullptr);
167             longPressEvent_ = nullptr;
168         } else {
169             gestureHub->SetLongPressEvent(longPressEvent_, false, false, LONG_PRESS_DELAY);
170         }
171     }
172     if (!isEnableAnalyzer_) {
173         auto longPressCallback = [weak = WeakClaim(this)](GestureEvent& info) {
174             auto pattern = weak.Upgrade();
175             CHECK_NULL_VOID(pattern);
176             pattern->HandleLongPress(info);
177         };
178         longPressEvent_ = MakeRefPtr<LongPressEvent>(std::move(longPressCallback));
179         gestureHub->SetLongPressEvent(longPressEvent_, false, false, LONG_PRESS_DELAY);
180     }
181 
182     if (touchEvent_) {
183         gestureHub->AddTouchEvent(touchEvent_);
184         return;
185     }
186     auto touchTask = [weak = WeakClaim(this)](TouchEventInfo& info) {
187         auto pattern = weak.Upgrade();
188         CHECK_NULL_VOID(pattern);
189         pattern->HandleTouchEvent(info);
190     };
191     touchEvent_ = MakeRefPtr<TouchEventImpl>(std::move(touchTask));
192     gestureHub->AddTouchEvent(touchEvent_);
193 }
194 
LongPressEventModify(bool status)195 void MovingPhotoPattern::LongPressEventModify(bool status)
196 {
197     auto host = GetHost();
198     CHECK_NULL_VOID(host);
199     auto gestureHub = host->GetOrCreateGestureEventHub();
200     CHECK_NULL_VOID(gestureHub);
201     if (status) {
202         auto longPressCallback = [weak = WeakClaim(this)](GestureEvent& info) {
203             auto pattern = weak.Upgrade();
204             CHECK_NULL_VOID(pattern);
205             pattern->HandleLongPress(info);
206         };
207         longPressEvent_ = MakeRefPtr<LongPressEvent>(std::move(longPressCallback));
208         gestureHub->SetLongPressEvent(longPressEvent_, false, false, LONG_PRESS_DELAY);
209     } else {
210         gestureHub->SetLongPressEvent(nullptr);
211         longPressEvent_ = nullptr;
212     }
213 }
214 
HandleLongPress(GestureEvent & info)215 void MovingPhotoPattern::HandleLongPress(GestureEvent& info)
216 {
217     isFastKeyUp_ = false;
218     if (currentPlayStatus_ == PlaybackStatus::STARTED || !isPrepared_ || isPlayByController_) {
219         return;
220     }
221     if (autoAndRepeatLevel_ == PlaybackMode::NONE && isEnableAnalyzer_) {
222         TAG_LOGW(AceLogTag::ACE_MOVING_PHOTO, "HandleLongPress isEnableAnalyzer_ return.");
223         return;
224     }
225     if (isRefreshMovingPhoto_) {
226         if (autoAndRepeatLevel_ == PlaybackMode::REPEAT) {
227             TAG_LOGW(AceLogTag::ACE_MOVING_PHOTO, "HandleLongPress IsRefreshMovingPhotoReturn:%{public}d.",
228                 isRefreshMovingPhoto_);
229             return;
230         }
231         isRefreshMovingPhotoPlaying_ = true;
232     } else {
233         if (autoAndRepeatLevel_ != PlaybackMode::NONE) {
234             TAG_LOGW(AceLogTag::ACE_MOVING_PHOTO, "HandleLongPress IsRefreshMovingPhotoReturn not:%{public}d.",
235                 isRefreshMovingPhoto_);
236             return;
237         }
238     }
239     TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "movingphoto HandleLongPress start.");
240     if (!mediaPlayer_ || !mediaPlayer_->IsMediaPlayerValid()) {
241         TAG_LOGW(AceLogTag::ACE_MOVING_PHOTO, "MediaPlayer is null or invalid.");
242         FireMediaPlayerError();
243         return;
244     }
245     if (currentPlayStatus_ == PlaybackStatus::STOPPED) {
246         mediaPlayer_->PrepareAsync();
247     }
248     if (isSetAutoPlayPeriod_ && (currentPlayStatus_ == PlaybackStatus::PLAYBACK_COMPLETE ||
249         currentPlayStatus_ == PlaybackStatus::PAUSED)) {
250         int32_t duration = DURATION_FLAG;
251         mediaPlayer_->GetDuration(duration);
252         SetAutoPlayPeriod(PERIOD_START, duration);
253     }
254     Start();
255 }
256 
HandleTouchEvent(TouchEventInfo & info)257 void MovingPhotoPattern::HandleTouchEvent(TouchEventInfo& info)
258 {
259     if (currentPlayStatus_ == PlaybackStatus::ERROR) {
260         ResetMediaPlayer();
261     }
262     if (IsRefreshMovingPhotoReturn(isRefreshMovingPhotoPlaying_)) {
263         TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "HandleTouchEvent IsRefreshMovingPhotoReturn.");
264         return;
265     }
266     if (!isPrepared_ || isPlayByController_) {
267         return;
268     }
269     if (autoAndRepeatLevel_ == PlaybackMode::NONE && isEnableAnalyzer_ && isAnalyzerPlaying_) {
270         TAG_LOGW(AceLogTag::ACE_MOVING_PHOTO, "HandleTouchEvent isEnableAnalyzer_ return.");
271         return;
272     }
273     auto touchList = info.GetChangedTouches();
274     CHECK_NULL_VOID(!touchList.empty());
275     auto touchInfo = touchList.front();
276     auto touchType = touchInfo.GetTouchType();
277     isFastKeyUp_ = false;
278     if (touchType == TouchType::UP || touchType == TouchType::CANCEL) {
279         if (currentPlayStatus_ == PlaybackStatus::STARTED) {
280             PausePlayback();
281         } else if (currentPlayStatus_ == PlaybackStatus::PLAYBACK_COMPLETE) {
282             currentPlayStatus_ = PlaybackStatus::NONE;
283             StopAnimation();
284         } else {
285             isFastKeyUp_ = true;
286         }
287     }
288 }
289 
UpdateImageNode()290 void MovingPhotoPattern::UpdateImageNode()
291 {
292     TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "UpdateImageNode start.%{public}d", movingPhotoFormat_);
293     if (startAnimationFlag_) {
294         needUpdateImageNode_ = true;
295         return;
296     }
297     auto host = GetHost();
298     CHECK_NULL_VOID(host);
299     auto movingPhoto = AceType::DynamicCast<MovingPhotoNode>(host);
300     CHECK_NULL_VOID(movingPhoto);
301     auto image = AceType::DynamicCast<FrameNode>(movingPhoto->GetImage());
302     CHECK_NULL_VOID(image);
303     UpdateImageHdrMode(image);
304     auto imagePattern = image->GetPattern<ImagePattern>();
305     CHECK_NULL_VOID(imagePattern);
306     imagePattern->SetOrientation(ImageRotateOrientation::AUTO);
307     TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "movingphoto set HDR.%{public}d", dynamicRangeMode_);
308     auto layoutProperty = GetLayoutProperty<MovingPhotoLayoutProperty>();
309     CHECK_NULL_VOID(layoutProperty);
310     if (!layoutProperty->HasImageSourceInfo()) {
311         TAG_LOGW(AceLogTag::ACE_MOVING_PHOTO, "image info is null.");
312         auto posterLayoutProperty = image->GetLayoutProperty<ImageLayoutProperty>();
313         posterLayoutProperty->UpdateVisibility(VisibleType::INVISIBLE);
314         image->MarkModifyDone();
315         return;
316     }
317     auto imageSourceInfo = layoutProperty->GetImageSourceInfo().value();
318     auto imageFit = layoutProperty->GetObjectFitValue(ImageFit::COVER);
319     if (!imageSourceInfo.IsValid()) {
320         TAG_LOGW(AceLogTag::ACE_MOVING_PHOTO, "image info is invalid.");
321         auto posterLayoutProperty = image->GetLayoutProperty<ImageLayoutProperty>();
322         posterLayoutProperty->UpdateVisibility(VisibleType::INVISIBLE);
323         image->MarkModifyDone();
324         return;
325     }
326     if (image) {
327         image->SetDraggable(false);
328         auto imageLayoutProperty = image->GetLayoutProperty<ImageLayoutProperty>();
329         imageLayoutProperty->UpdateVisibility(VisibleType::VISIBLE);
330         imageLayoutProperty->UpdateImageSourceInfo(imageSourceInfo);
331         MovingPhotoFormatConvert(movingPhotoFormat_);
332         imagePattern->SetExternalDecodeFormat(imageFormat_);
333         imageLayoutProperty->UpdateImageFit(imageFit);
334         image->MarkModifyDone();
335     }
336     RegisterImageEvent();
337 }
338 
UpdateImageHdrMode(const RefPtr<FrameNode> & imageNode)339 void MovingPhotoPattern::UpdateImageHdrMode(const RefPtr<FrameNode>& imageNode)
340 {
341     if (dynamicRangeMode_ == DynamicRangeMode::STANDARD) {
342         ACE_RESET_NODE_PAINT_PROPERTY(ImageRenderProperty, DynamicMode, imageNode);
343         ACE_RESET_NODE_RENDER_CONTEXT(RenderContext, DynamicRangeMode, imageNode);
344     } else {
345         DynamicRangeModeConvert(dynamicRangeMode_);
346         ACE_UPDATE_NODE_PAINT_PROPERTY(ImageRenderProperty, DynamicMode, dynamicRangeMode_, imageNode);
347         ACE_UPDATE_NODE_RENDER_CONTEXT(DynamicRangeMode, dynamicRangeMode_, imageNode);
348     }
349 }
350 
MovingPhotoFormatConvert(MovingPhotoFormat format)351 void MovingPhotoPattern::MovingPhotoFormatConvert(MovingPhotoFormat format)
352 {
353     TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "MovingPhotoFormatConvert %{public}d.", format);
354     switch (format) {
355         case MovingPhotoFormat::RGBA_8888:
356             imageFormat_ = PixelFormat::RGBA_8888;
357             break;
358         case MovingPhotoFormat::NV21:
359             imageFormat_ = PixelFormat::NV21;
360             break;
361         case MovingPhotoFormat::RGBA_1010102:
362             imageFormat_ = PixelFormat::RGBA_1010102;
363             break;
364         case MovingPhotoFormat::YCBCR_P010:
365             imageFormat_ = PixelFormat::YCBCR_P010;
366             break;
367         case MovingPhotoFormat::YCRCB_P010:
368             imageFormat_ = PixelFormat::YCRCB_P010;
369             break;
370         default:
371             imageFormat_ = PixelFormat::UNKNOWN;
372             break;
373     }
374 }
375 
DynamicRangeModeConvert(DynamicRangeMode rangeMode)376 void MovingPhotoPattern::DynamicRangeModeConvert(DynamicRangeMode rangeMode)
377 {
378     switch (rangeMode) {
379         case DynamicRangeMode::HIGH:
380             dynamicRangeMode_ = DynamicRangeMode::HIGH;
381             break;
382         case DynamicRangeMode::CONSTRAINT:
383             dynamicRangeMode_ = DynamicRangeMode::CONSTRAINT;
384             break;
385         case DynamicRangeMode::STANDARD:
386             dynamicRangeMode_ = DynamicRangeMode::STANDARD;
387             break;
388         default:
389             dynamicRangeMode_ = DynamicRangeMode::HIGH;
390             break;
391     }
392     TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "DynamicRangeModeConvert %{public}d.", rangeMode);
393 }
394 
RegisterImageEvent()395 void MovingPhotoPattern::RegisterImageEvent()
396 {
397     TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "MovingPhoto RegisterImageEvent start.");
398     auto host = GetHost();
399     CHECK_NULL_VOID(host);
400     auto movingPhoto = AceType::DynamicCast<MovingPhotoNode>(host);
401     CHECK_NULL_VOID(movingPhoto);
402     auto image = AceType::DynamicCast<FrameNode>(movingPhoto->GetImage());
403     CHECK_NULL_VOID(image);
404     auto imageHub = image->GetEventHub<ImageEventHub>();
405     CHECK_NULL_VOID(imageHub);
406     auto imageCompleteEventCallback = [weak = WeakClaim(this)](const LoadImageSuccessEvent& info) {
407         auto pattern = weak.Upgrade();
408         CHECK_NULL_VOID(pattern);
409         pattern->HandleImageCompleteEvent(info);
410     };
411     imageHub->SetOnComplete(imageCompleteEventCallback);
412 }
413 
HandleImageCompleteEvent(const LoadImageSuccessEvent & info)414 void MovingPhotoPattern::HandleImageCompleteEvent(const LoadImageSuccessEvent& info)
415 {
416     auto loadingStatus = info.GetLoadingStatus();
417     TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "HandleImageCompleteEvent start:%{public}d.", loadingStatus);
418     if (loadingStatus == IMAGE_LOADING_COMPLETE) {
419         FireMediaPlayerImageComplete();
420     }
421 }
422 
UpdateVideoNode()423 void MovingPhotoPattern::UpdateVideoNode()
424 {
425     ContainerScope scope(instanceId_);
426     auto pipelineContext = PipelineContext::GetCurrentContext();
427     CHECK_NULL_VOID(pipelineContext);
428     auto uiTaskExecutor = SingleTaskExecutor::Make(pipelineContext->GetTaskExecutor(), TaskExecutor::TaskType::UI);
429     uiTaskExecutor.PostTask(
430         [weak = WeakClaim(this)]() {
431             auto movingPhotoPattern = weak.Upgrade();
432             CHECK_NULL_VOID(movingPhotoPattern);
433             ContainerScope scope(movingPhotoPattern->instanceId_);
434             movingPhotoPattern->PrepareMediaPlayer();
435             movingPhotoPattern->UpdateMediaPlayerSpeed();
436             movingPhotoPattern->UpdateMediaPlayerMuted();
437         },
438         "ArkUIMovingPhotoUpdateVideo");
439 }
440 
PrepareMediaPlayer()441 void MovingPhotoPattern::PrepareMediaPlayer()
442 {
443     auto layoutProperty = GetLayoutProperty<MovingPhotoLayoutProperty>();
444     CHECK_NULL_VOID(layoutProperty);
445     if (!layoutProperty->HasMovingPhotoUri() || !layoutProperty->HasVideoSource()) {
446         TAG_LOGW(AceLogTag::ACE_MOVING_PHOTO, "MovingPhoto source is null.");
447         return;
448     }
449     if (layoutProperty->GetMovingPhotoUri().value() == uri_ &&
450         layoutProperty->GetVideoSource().value() == fd_.GetValue()) {
451         TAG_LOGW(AceLogTag::ACE_MOVING_PHOTO, "MediaPlayer source has not changed.");
452         return;
453     }
454     uri_ = layoutProperty->GetMovingPhotoUri().value();
455     fd_ = layoutProperty->GetVideoSource().value();
456     if (!mediaPlayer_) {
457         TAG_LOGW(AceLogTag::ACE_MOVING_PHOTO, "MediaPlayer is null.");
458         FireMediaPlayerError();
459         return;
460     }
461     if (!mediaPlayer_->IsMediaPlayerValid()) {
462         mediaPlayer_->CreateMediaPlayer();
463     }
464     if (!mediaPlayer_->IsMediaPlayerValid()) {
465         TAG_LOGW(AceLogTag::ACE_MOVING_PHOTO, "MediaPlayer is invalid.");
466         FireMediaPlayerError();
467         return;
468     }
469     ContainerScope scope(instanceId_);
470     auto context = PipelineContext::GetCurrentContext();
471     CHECK_NULL_VOID(context);
472     auto uiTaskExecutor = SingleTaskExecutor::Make(context->GetTaskExecutor(), TaskExecutor::TaskType::UI);
473     uiTaskExecutor.PostTask(
474         [weak = WeakClaim(this)] {
475             auto movingPhotoPattern = weak.Upgrade();
476             CHECK_NULL_VOID(movingPhotoPattern);
477             movingPhotoPattern->ResetMediaPlayer();
478         },
479         "ArkUIMovingPhotoPrepare");
480 }
481 
ResetMediaPlayer()482 void MovingPhotoPattern::ResetMediaPlayer()
483 {
484     CHECK_NULL_VOID(mediaPlayer_);
485     isPrepared_ = false;
486     ContainerScope scope(instanceId_);
487     auto context = PipelineContext::GetCurrentContext();
488     CHECK_NULL_VOID(context);
489     if (isRefreshMovingPhoto_ && isUsedMediaPlayerStatusChanged_) {
490         TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "ArkUIMovingPhotoResetMediaPlayerAsync.");
491         auto bgTaskExecutor = SingleTaskExecutor::Make(context->GetTaskExecutor(), TaskExecutor::TaskType::BACKGROUND);
492         bgTaskExecutor.PostTask(
493             [weak = WeakClaim(RawPtr(mediaPlayer_)), fd = fd_] {
494                 auto mediaPlayer = weak.Upgrade();
495                 CHECK_NULL_VOID(mediaPlayer);
496                 mediaPlayer->ResetMediaPlayer();
497                 if (!mediaPlayer->SetSourceByFd(fd.GetValue())) {
498                     TAG_LOGW(AceLogTag::ACE_MOVING_PHOTO, "set source for MediaPlayer Async failed.");
499                 }
500             },
501             "ArkUIMovingPhotoResetMediaPlayerAsync");
502     } else {
503         mediaPlayer_->ResetMediaPlayer();
504         RegisterMediaPlayerEvent();
505         if (!mediaPlayer_->SetSourceByFd(fd_.GetValue())) {
506             TAG_LOGW(AceLogTag::ACE_MOVING_PHOTO, "set source for MediaPlayer failed.");
507             auto uiTaskExecutor = SingleTaskExecutor::Make(context->GetTaskExecutor(), TaskExecutor::TaskType::UI);
508             uiTaskExecutor.PostTask(
509                 [weak = WeakClaim(this)] {
510                     auto pattern = weak.Upgrade();
511                     CHECK_NULL_VOID(pattern);
512                     ContainerScope scope(pattern->instanceId_);
513                     pattern->FireMediaPlayerError();
514                 },
515                 "ArkUIMovingPhotoResetMediaPlayer");
516         }
517     }
518 }
519 
RegisterMediaPlayerEvent()520 void MovingPhotoPattern::RegisterMediaPlayerEvent()
521 {
522     if (fd_.GetValue() == -1 || !mediaPlayer_) {
523         return;
524     }
525     ContainerScope scope(instanceId_);
526     auto context = PipelineContext::GetCurrentContext();
527     CHECK_NULL_VOID(context);
528     auto uiTaskExecutor = SingleTaskExecutor::Make(context->GetTaskExecutor(), TaskExecutor::TaskType::UI);
529     auto movingPhotoPattern = WeakClaim(this);
530 
531     auto&& positionUpdatedEvent = [movingPhotoPattern, uiTaskExecutor](uint32_t currentPos) {
532         uiTaskExecutor.PostTask([movingPhotoPattern, currentPos] {
533             auto movingPhoto = movingPhotoPattern.Upgrade();
534             CHECK_NULL_VOID(movingPhoto);
535             ContainerScope scope(movingPhoto->instanceId_);
536             movingPhoto->OnPlayPositionChanged(currentPos);
537         }, "ArkUIMovingPhotoPositionChanged");
538     };
539 
540     auto&& stateChangedEvent = [movingPhotoPattern, uiTaskExecutor](PlaybackStatus status) {
541         uiTaskExecutor.PostTask([movingPhotoPattern, status] {
542             auto movingPhoto = movingPhotoPattern.Upgrade();
543             CHECK_NULL_VOID(movingPhoto);
544             ContainerScope scope(movingPhoto->instanceId_);
545             movingPhoto->OnMediaPlayerStatusChanged(status);
546         }, "ArkUIMovingPhotoStatusChanged");
547     };
548 
549     auto&& errorEvent = [movingPhotoPattern, uiTaskExecutor]() {
550         uiTaskExecutor.PostSyncTask([movingPhotoPattern] {
551             auto movingPhoto = movingPhotoPattern.Upgrade();
552             CHECK_NULL_VOID(movingPhoto);
553             ContainerScope scope(movingPhoto->instanceId_);
554             movingPhoto->FireMediaPlayerError();
555         }, "ArkUIMovingPhotoOnError");
556     };
557 
558     auto&& resolutionChangeEvent = [movingPhotoPattern, uiTaskExecutor]() {
559         uiTaskExecutor.PostTask([movingPhotoPattern] {
560             auto movingPhoto = movingPhotoPattern.Upgrade();
561             CHECK_NULL_VOID(movingPhoto);
562             ContainerScope scope(movingPhoto->instanceId_);
563             movingPhoto->OnResolutionChange();
564         }, "ArkUIMovingPhotoResolutionChanged");
565     };
566 
567     auto&& startRenderFrameEvent = [movingPhotoPattern, uiTaskExecutor]() {
568         uiTaskExecutor.PostTask([movingPhotoPattern] {
569             auto movingPhoto = movingPhotoPattern.Upgrade();
570             CHECK_NULL_VOID(movingPhoto);
571             ContainerScope scope(movingPhoto->instanceId_);
572             movingPhoto->OnStartRenderFrame();
573         }, "ArkUIMovingPhotoStartRender");
574     };
575 
576     mediaPlayer_->RegisterMediaPlayerEvent(
577         positionUpdatedEvent, stateChangedEvent, errorEvent, resolutionChangeEvent, startRenderFrameEvent);
578 }
579 
PrepareSurface()580 void MovingPhotoPattern::PrepareSurface()
581 {
582     if (!mediaPlayer_ || renderSurface_->IsSurfaceValid()) {
583         return;
584     }
585     if (!SystemProperties::GetExtSurfaceEnabled()) {
586         renderSurface_->SetRenderContext(renderContextForMediaPlayer_);
587     }
588     renderSurface_->InitSurface();
589     mediaPlayer_->SetRenderSurface(renderSurface_);
590     if (mediaPlayer_->SetSurface() != 0) {
591         TAG_LOGW(AceLogTag::ACE_MOVING_PHOTO, "prepare MediaPlayer failed.");
592     }
593 }
594 
UpdatePlayMode()595 void MovingPhotoPattern::UpdatePlayMode()
596 {
597     TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "movingphoto UpdatePlayMode.%{public}d", isChangePlayMode_);
598     if (isChangePlayMode_) {
599         if (historyAutoAndRepeatLevel_ == PlaybackMode::AUTO) {
600             SetAutoPlayPeriod(autoPlayPeriodStartTime_, autoPlayPeriodEndTime_);
601         }
602         if (autoAndRepeatLevel_ == PlaybackMode::AUTO && currentPlayStatus_ == PlaybackStatus::PREPARED) {
603             isSetAutoPlayPeriod_ = false;
604             ResetMediaPlayer();
605         } else {
606             MediaResetToPlay();
607         }
608         isChangePlayMode_ = false;
609     }
610 }
611 
HandleImageAnalyzerMode()612 void MovingPhotoPattern::HandleImageAnalyzerMode()
613 {
614     TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "movingphoto HandleImageAnalyzerMode.");
615     if (isEnableAnalyzer_ && autoAndRepeatLevel_ == PlaybackMode::NONE) {
616         if (!imageAnalyzerManager_) {
617             EnableAnalyzer(isEnableAnalyzer_);
618         }
619         if (imageAnalyzerManager_ && !GetAnalyzerState()) {
620             StartImageAnalyzer();
621         }
622     }
623     if (!isEnableAnalyzer_ && IsSupportImageAnalyzer() && imageAnalyzerManager_) {
624         DestroyAnalyzerOverlay();
625         LongPressEventModify(true);
626     }
627 }
628 
MediaResetToPlay()629 void MovingPhotoPattern::MediaResetToPlay()
630 {
631     autoAndRepeatLevel_ = historyAutoAndRepeatLevel_;
632     if (currentPlayStatus_ == PlaybackStatus::STOPPED) {
633         mediaPlayer_->PrepareAsync();
634     } else if (currentPlayStatus_ == PlaybackStatus::PLAYBACK_COMPLETE ||
635         currentPlayStatus_ == PlaybackStatus::PAUSED ||
636         currentPlayStatus_ == PlaybackStatus::PREPARED) {
637             SelectPlaybackMode(historyAutoAndRepeatLevel_);
638     }
639 }
640 
FireMediaPlayerImageComplete()641 void MovingPhotoPattern::FireMediaPlayerImageComplete()
642 {
643     auto eventHub = GetEventHub<MovingPhotoEventHub>();
644     CHECK_NULL_VOID(eventHub);
645     eventHub->FireCompleteEvent();
646 }
647 
FireMediaPlayerStart()648 void MovingPhotoPattern::FireMediaPlayerStart()
649 {
650     auto eventHub = GetEventHub<MovingPhotoEventHub>();
651     CHECK_NULL_VOID(eventHub);
652     eventHub->FireStartEvent();
653     if (isFastKeyUp_) {
654         isFastKeyUp_ = false;
655         PausePlayback();
656     }
657 }
658 
FireMediaPlayerStop()659 void MovingPhotoPattern::FireMediaPlayerStop()
660 {
661     auto eventHub = GetEventHub<MovingPhotoEventHub>();
662     CHECK_NULL_VOID(eventHub);
663     eventHub->FireStopEvent();
664 }
665 
FireMediaPlayerPause()666 void MovingPhotoPattern::FireMediaPlayerPause()
667 {
668     auto eventHub = GetEventHub<MovingPhotoEventHub>();
669     CHECK_NULL_VOID(eventHub);
670     eventHub->FirePauseEvent();
671 }
672 
FireMediaPlayerFinish()673 void MovingPhotoPattern::FireMediaPlayerFinish()
674 {
675     auto eventHub = GetEventHub<MovingPhotoEventHub>();
676     CHECK_NULL_VOID(eventHub);
677     eventHub->FireFinishEvent();
678 }
679 
FireMediaPlayerError()680 void MovingPhotoPattern::FireMediaPlayerError()
681 {
682     auto eventHub = GetEventHub<MovingPhotoEventHub>();
683     CHECK_NULL_VOID(eventHub);
684     eventHub->FireErrorEvent();
685 }
686 
OnResolutionChange()687 void MovingPhotoPattern::OnResolutionChange()
688 {
689     if (!mediaPlayer_ || !mediaPlayer_->IsMediaPlayerValid()) {
690         TAG_LOGW(AceLogTag::ACE_MOVING_PHOTO, "MediaPlayer is null or invalid.");
691         return;
692     }
693     auto host = GetHost();
694     CHECK_NULL_VOID(host);
695     SizeF videoSize =
696         SizeF(static_cast<float>(mediaPlayer_->GetVideoWidth()), static_cast<float>(mediaPlayer_->GetVideoHeight()));
697     auto movingPhotoLayoutProperty = host->GetLayoutProperty<MovingPhotoLayoutProperty>();
698     CHECK_NULL_VOID(movingPhotoLayoutProperty);
699     movingPhotoLayoutProperty->UpdateVideoSize(videoSize);
700     host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
701 }
702 
OnStartRenderFrame()703 void MovingPhotoPattern::OnStartRenderFrame()
704 {
705     TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "MediaPlayer OnStartRenderFrame.");
706 }
707 
OnStartedStatusCallback()708 void MovingPhotoPattern::OnStartedStatusCallback()
709 {
710     TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "MediaPlayer OnStartedStatusCallback.");
711     ACE_FUNCTION_TRACE();
712     auto host = GetHost();
713     CHECK_NULL_VOID(host);
714     auto movingPhoto = AceType::DynamicCast<MovingPhotoNode>(host);
715     CHECK_NULL_VOID(movingPhoto);
716     auto image = AceType::DynamicCast<FrameNode>(movingPhoto->GetImage());
717     CHECK_NULL_VOID(image);
718     StartAnimation();
719 }
720 
OnDirtyLayoutWrapperSwap(const RefPtr<LayoutWrapper> & dirty,const DirtySwapConfig & config)721 bool MovingPhotoPattern::OnDirtyLayoutWrapperSwap(const RefPtr<LayoutWrapper>& dirty, const DirtySwapConfig& config)
722 {
723     TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "MediaPlayer OnStartedStatusCallback.");
724     if (config.skipMeasure || dirty->SkipMeasureContent()) {
725         return false;
726     }
727     auto geometryNode = dirty->GetGeometryNode();
728     CHECK_NULL_RETURN(geometryNode, false);
729     auto movingPhotoNodeSize = geometryNode->GetContentSize();
730     auto layoutProperty = GetLayoutProperty<MovingPhotoLayoutProperty>();
731     CHECK_NULL_RETURN(layoutProperty, false);
732     auto videoFrameSize = MeasureContentLayout(movingPhotoNodeSize, layoutProperty);
733     if (renderContextForMediaPlayer_) {
734         renderContextForMediaPlayer_->SetBounds((movingPhotoNodeSize.Width() - videoFrameSize.Width()) / HALF,
735             (movingPhotoNodeSize.Height() - videoFrameSize.Height()) / HALF, videoFrameSize.Width(),
736             videoFrameSize.Height());
737     }
738 
739     if (IsSupportImageAnalyzer() && isEnableAnalyzer_ && autoAndRepeatLevel_ == PlaybackMode::NONE) {
740         if (imageAnalyzerManager_ && !GetAnalyzerState()) {
741             StartImageAnalyzer();
742         } else {
743             Rect tmpRect;
744             auto padding = layoutProperty->CreatePaddingAndBorder();
745             auto imageFit = layoutProperty->GetObjectFitValue(ImageFit::COVER);
746             if (imageFit == ImageFit::COVER || imageFit == ImageFit::NONE) {
747                 tmpRect = Rect(padding.left.value_or(0), padding.top.value_or(0),
748                                movingPhotoNodeSize.Width(), movingPhotoNodeSize.Height());
749             } else {
750                 tmpRect = Rect(
751                     (movingPhotoNodeSize.Width() - videoFrameSize.Width()) / AVERAGE_VALUE + padding.left.value_or(0),
752                     (movingPhotoNodeSize.Height() - videoFrameSize.Height()) / AVERAGE_VALUE + padding.top.value_or(0),
753                     videoFrameSize.Width(), videoFrameSize.Height());
754             }
755             contentRect_ = tmpRect;
756             UpdateAnalyzerUIConfig(geometryNode);
757         }
758     }
759     if (imageAnalyzerManager_ && !isEnableAnalyzer_) {
760         DestroyAnalyzerOverlay();
761         LongPressEventModify(true);
762     }
763 
764     auto host = GetHost();
765     CHECK_NULL_RETURN(host, false);
766     host->MarkNeedSyncRenderTree();
767     auto movingPhoto = AceType::DynamicCast<MovingPhotoNode>(host);
768     CHECK_NULL_RETURN(movingPhoto, false);
769     auto video = AceType::DynamicCast<FrameNode>(movingPhoto->GetVideo());
770     CHECK_NULL_RETURN(video, false);
771     video->GetRenderContext()->SetClipToBounds(true);
772     return false;
773 }
774 
CalculateFitContain(const SizeF & rawSize,const SizeF & layoutSize)775 SizeF MovingPhotoPattern::CalculateFitContain(const SizeF& rawSize, const SizeF& layoutSize)
776 {
777     if (NearZero(rawSize.Height()) || NearZero(rawSize.Width()) || NearZero(layoutSize.Height())) {
778         return layoutSize;
779     }
780     double sourceRatio = rawSize.Width() / rawSize.Height();
781     double layoutRatio = layoutSize.Width() / layoutSize.Height();
782     if (sourceRatio < layoutRatio) {
783         float ratio = layoutSize.Height() / rawSize.Height();
784         return { rawSize.Width() * ratio, layoutSize.Height() };
785     } else {
786         float ratio = layoutSize.Width() / rawSize.Width();
787         return { layoutSize.Width(), rawSize.Height() * ratio };
788     }
789 }
790 
CalculateFitFill(const SizeF & layoutSize)791 SizeF MovingPhotoPattern::CalculateFitFill(const SizeF& layoutSize)
792 {
793     return layoutSize;
794 }
795 
CalculateFitCover(const SizeF & rawSize,const SizeF & layoutSize)796 SizeF MovingPhotoPattern::CalculateFitCover(const SizeF& rawSize, const SizeF& layoutSize)
797 {
798     if (NearZero(rawSize.Height()) || NearZero(rawSize.Width()) || NearZero(layoutSize.Height())) {
799         return layoutSize;
800     }
801     double sourceRatio = rawSize.Width() / rawSize.Height();
802     double layoutRatio = layoutSize.Width() / layoutSize.Height();
803     float ratio = 1.0;
804     if (sourceRatio < layoutRatio) {
805         ratio = static_cast<float>(layoutSize.Width() / rawSize.Width());
806     } else {
807         ratio = static_cast<float>(layoutSize.Height() / rawSize.Height());
808     }
809     return { rawSize.Width() * ratio, rawSize.Height() * ratio};
810 }
811 
CalculateFitNone(const SizeF & rawSize)812 SizeF MovingPhotoPattern::CalculateFitNone(const SizeF& rawSize)
813 {
814     return rawSize;
815 }
816 
CalculateFitScaleDown(const SizeF & rawSize,const SizeF & layoutSize)817 SizeF MovingPhotoPattern::CalculateFitScaleDown(const SizeF& rawSize, const SizeF& layoutSize)
818 {
819     if ((rawSize.Width() <= layoutSize.Width()) && (rawSize.Height() <= layoutSize.Height())) {
820         return CalculateFitNone(rawSize);
821     } else {
822         return CalculateFitContain(rawSize, layoutSize);
823     }
824 }
825 
CalculateFitAuto(const SizeF & rawSize,const SizeF & layoutSize)826 SizeF MovingPhotoPattern::CalculateFitAuto(const SizeF& rawSize, const SizeF& layoutSize)
827 {
828     if (NearZero(rawSize.Width()) || NearZero(rawSize.Height())) {
829         return layoutSize;
830     }
831     if ((rawSize.Width() <= layoutSize.Width()) && (rawSize.Height() <= layoutSize.Height())) {
832         double widthRatio = layoutSize.Width() / rawSize.Width();
833         double heightRatio = layoutSize.Height() / rawSize.Height();
834         float ratio = static_cast<float>(std::min(widthRatio, heightRatio));
835         return { rawSize.Width() * ratio, rawSize.Height() * ratio };
836     } else if ((rawSize.Width() > layoutSize.Width()) && (rawSize.Height() <= layoutSize.Height())) {
837         return CalculateFitContain(rawSize, layoutSize);
838     } else {
839         return CalculateFitCover(rawSize, layoutSize);
840     }
841 }
842 
GetRawImageSize()843 SizeF MovingPhotoPattern::GetRawImageSize()
844 {
845     auto host = GetHost();
846     CHECK_NULL_RETURN(host, SizeF(-1, -1));
847     auto movingPhoto = AceType::DynamicCast<MovingPhotoNode>(host);
848     CHECK_NULL_RETURN(movingPhoto, SizeF(-1, -1));
849     auto image = AceType::DynamicCast<FrameNode>(movingPhoto->GetImage());
850     CHECK_NULL_RETURN(image, SizeF(-1, -1));
851     auto imagePattern = image->GetPattern<ImagePattern>();
852     CHECK_NULL_RETURN(image, SizeF(-1, -1));
853     return imagePattern->GetRawImageSize();
854 }
855 
MeasureContentLayout(const SizeF & layoutSize,const RefPtr<MovingPhotoLayoutProperty> & layoutProperty)856 SizeF MovingPhotoPattern::MeasureContentLayout(const SizeF& layoutSize,
857     const RefPtr<MovingPhotoLayoutProperty>& layoutProperty)
858 {
859     if (!layoutProperty || !layoutProperty->HasVideoSize()) {
860         return layoutSize;
861     }
862 
863     auto rawImageSize = GetRawImageSize();
864     auto imageFit = layoutProperty->GetObjectFitValue(ImageFit::COVER);
865     SizeF contentSize = { 0.0, 0.0 };
866     switch (imageFit) {
867         case ImageFit::CONTAIN:
868             contentSize = CalculateFitContain(rawImageSize, layoutSize);
869             break;
870         case ImageFit::FILL:
871             contentSize = CalculateFitFill(layoutSize);
872             break;
873         case ImageFit::COVER:
874             contentSize = CalculateFitCover(rawImageSize, layoutSize);
875             break;
876         case ImageFit::NONE:
877             contentSize = CalculateFitNone(rawImageSize);
878             break;
879         case ImageFit::SCALE_DOWN:
880             contentSize = CalculateFitScaleDown(rawImageSize, layoutSize);
881             break;
882         default:
883             contentSize = CalculateFitAuto(rawImageSize, layoutSize);
884     }
885 
886     return contentSize;
887 }
888 
OnMediaPlayerStatusChanged(PlaybackStatus status)889 void MovingPhotoPattern::OnMediaPlayerStatusChanged(PlaybackStatus status)
890 {
891     isUsedMediaPlayerStatusChanged_ = true;
892     currentPlayStatus_ = status;
893     TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "Player current status is %{public}d.", status);
894     switch (status) {
895         case PlaybackStatus::ERROR:
896             TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "Player current status is ERROR.");
897             FireMediaPlayerError();
898             break;
899         case PlaybackStatus::IDLE:
900             TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "Player current status is IDLE.");
901             break;
902         case PlaybackStatus::INITIALIZED:
903             TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "Player current status is INITIALIZED.");
904             OnMediaPlayerInitialized();
905             break;
906         case PlaybackStatus::PREPARED:
907             TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "Player current status is PREPARED.");
908             OnMediaPlayerPrepared();
909             break;
910         case PlaybackStatus::STARTED:
911             TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "Player current status is STARTED.");
912             OnStartedStatusCallback();
913             FireMediaPlayerStart();
914             break;
915         case PlaybackStatus::PAUSED:
916             TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "Player current status is PAUSED.");
917             FireMediaPlayerPause();
918             break;
919         case PlaybackStatus::STOPPED:
920             TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "Player current status is STOPPED.");
921             OnMediaPlayerStoped();
922             break;
923         case PlaybackStatus::PLAYBACK_COMPLETE:
924             TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "Player current status is PLAYBACK_COMPLETE.");
925             OnMediaPlayerCompletion();
926             break;
927         case PlaybackStatus::NONE:
928             TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "Player current status is NONE.");
929             break;
930         default:
931             TAG_LOGW(AceLogTag::ACE_MOVING_PHOTO, "Invalid player status.");
932             break;
933     }
934 }
935 
OnMediaPlayerInitialized()936 void MovingPhotoPattern::OnMediaPlayerInitialized()
937 {
938     TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "MediaPlayer OnMediaPlayerInitialized.");
939     if (!isSetAutoPlayPeriod_ && autoAndRepeatLevel_ == PlaybackMode::AUTO && !isAutoChangePlayMode_) {
940         isSetAutoPlayPeriod_ = true;
941         SetAutoPlayPeriod(autoPlayPeriodStartTime_, autoPlayPeriodEndTime_);
942     }
943     isAutoChangePlayMode_ = false;
944     PrepareSurface();
945     if (mediaPlayer_->PrepareAsync() != PREPARE_RETURN) {
946         TAG_LOGW(AceLogTag::ACE_MOVING_PHOTO, "prepare MediaPlayer failed.");
947     }
948 }
949 
OnMediaPlayerPrepared()950 void MovingPhotoPattern::OnMediaPlayerPrepared()
951 {
952     ContainerScope scope(instanceId_);
953     auto context = PipelineContext::GetCurrentContext();
954     CHECK_NULL_VOID(context);
955     if (!mediaPlayer_ || !mediaPlayer_->IsMediaPlayerValid()) {
956         TAG_LOGW(AceLogTag::ACE_MOVING_PHOTO, "MediaPlayer is null or invalid.");
957         return;
958     }
959     isPrepared_ = true;
960     Size videoSize = Size(mediaPlayer_->GetVideoWidth(), mediaPlayer_->GetVideoHeight());
961     auto host = GetHost();
962     CHECK_NULL_VOID(host);
963     auto videoLayoutProperty = host->GetLayoutProperty<MovingPhotoLayoutProperty>();
964     CHECK_NULL_VOID(videoLayoutProperty);
965     CHECK_NULL_VOID(mediaPlayer_);
966     videoLayoutProperty->UpdateVideoSize(
967         SizeF(static_cast<float>(videoSize.Width()), static_cast<float>(videoSize.Height())));
968     host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
969     mediaPlayer_->SetParameter(VIDEO_SCALE, 1);
970     UpdateMediaPlayerSpeed();
971     UpdateMediaPlayerMuted();
972     VisiblePlayback();
973 }
974 
OnMediaPlayerStoped()975 void MovingPhotoPattern::OnMediaPlayerStoped()
976 {
977     isPlayByController_ = false;
978     FireMediaPlayerStop();
979 }
980 
OnMediaPlayerCompletion()981 void MovingPhotoPattern::OnMediaPlayerCompletion()
982 {
983     if (!isRefreshMovingPhotoPlaying_) {
984         if (isPlayByController_ || autoAndRepeatLevel_ != PlaybackMode::NONE) {
985             isPlayByController_ = false;
986             StopAnimation();
987         }
988     }
989 
990     FireMediaPlayerFinish();
991 }
992 
HideImageNode()993 void MovingPhotoPattern::HideImageNode()
994 {
995     auto host = GetHost();
996     CHECK_NULL_VOID(host);
997     auto movingPhoto = AceType::DynamicCast<MovingPhotoNode>(host);
998     CHECK_NULL_VOID(movingPhoto);
999     auto image = AceType::DynamicCast<FrameNode>(movingPhoto->GetImage());
1000     CHECK_NULL_VOID(image);
1001     auto imageLayoutProperty = image->GetLayoutProperty<ImageLayoutProperty>();
1002     CHECK_NULL_VOID(imageLayoutProperty);
1003     imageLayoutProperty->UpdateVisibility(VisibleType::INVISIBLE);
1004     image->MarkModifyDone();
1005 }
1006 
VisiblePlayback()1007 void MovingPhotoPattern::VisiblePlayback()
1008 {
1009     TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "movingphoto VisiblePlayback.");
1010     if (!isVisible_) {
1011         return;
1012     }
1013     if (isRepeatChangePlayMode_ && historyAutoAndRepeatLevel_ == PlaybackMode::NONE &&
1014         autoAndRepeatLevel_ == PlaybackMode::NONE) {
1015         autoAndRepeatLevel_ = PlaybackMode::REPEAT;
1016         historyAutoAndRepeatLevel_ = PlaybackMode::REPEAT;
1017         isRepeatChangePlayMode_ = false;
1018     }
1019     if (historyAutoAndRepeatLevel_ != PlaybackMode::NONE &&
1020         autoAndRepeatLevel_ == PlaybackMode::NONE) {
1021         SelectPlaybackMode(historyAutoAndRepeatLevel_);
1022     } else {
1023         SelectPlaybackMode(autoAndRepeatLevel_);
1024     }
1025 }
1026 
SelectPlaybackMode(PlaybackMode mode)1027 void MovingPhotoPattern::SelectPlaybackMode(PlaybackMode mode)
1028 {
1029     if (mode == PlaybackMode::REPEAT) {
1030         StartRepeatPlay();
1031     } else if (mode == PlaybackMode::AUTO) {
1032         StartAutoPlay();
1033     }
1034 }
1035 
StartPlayback()1036 void MovingPhotoPattern::StartPlayback()
1037 {
1038     if (currentPlayStatus_ == PlaybackStatus::STARTED || !isPrepared_) {
1039         return;
1040     }
1041     if (IsRefreshMovingPhotoReturn(isRefreshMovingPhoto_)) {
1042         TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "HandleTouchEvent IsRefreshMovingPhotoReturn.");
1043         return;
1044     }
1045     if (currentPlayStatus_ == PlaybackStatus::STOPPED) {
1046         mediaPlayer_->PrepareAsync();
1047     }
1048     isPlayByController_ = true;
1049     isFastKeyUp_ = false;
1050     if (isSetAutoPlayPeriod_ && (currentPlayStatus_ == PlaybackStatus::PLAYBACK_COMPLETE ||
1051         currentPlayStatus_ == PlaybackStatus::PAUSED)) {
1052         int32_t duration = DURATION_FLAG;
1053         mediaPlayer_->GetDuration(duration);
1054         TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "StartPlayback duration:%{public}d.",
1055             duration);
1056         SetAutoPlayPeriod(PERIOD_START, duration);
1057     }
1058     Start();
1059 }
1060 
StartAnimation()1061 void MovingPhotoPattern::StartAnimation()
1062 {
1063     if (historyAutoAndRepeatLevel_ == PlaybackMode::REPEAT) {
1064         if (!isFirstRepeatPlay_) {
1065             return;
1066         }
1067         isFirstRepeatPlay_ = false;
1068     }
1069     auto host = GetHost();
1070     CHECK_NULL_VOID(host);
1071     auto movingPhoto = AceType::DynamicCast<MovingPhotoNode>(host);
1072     CHECK_NULL_VOID(movingPhoto);
1073     auto image = AceType::DynamicCast<FrameNode>(movingPhoto->GetImage());
1074     CHECK_NULL_VOID(image);
1075     auto imageRsContext = image->GetRenderContext();
1076     CHECK_NULL_VOID(imageRsContext);
1077     auto video = AceType::DynamicCast<FrameNode>(movingPhoto->GetVideo());
1078     CHECK_NULL_VOID(video);
1079     auto videoRsContext = video->GetRenderContext();
1080     CHECK_NULL_VOID(videoRsContext);
1081 
1082     imageRsContext->UpdateOpacity(1.0);
1083     imageRsContext->UpdateTransformScale({NORMAL_SCALE, NORMAL_SCALE});
1084     videoRsContext->UpdateTransformScale({NORMAL_SCALE, NORMAL_SCALE});
1085     auto movingPhotoPattern = WeakClaim(this);
1086     AnimationOption animationOption;
1087     animationOption.SetDuration(ANIMATION_DURATION_400);
1088     animationOption.SetCurve(Curves::FRICTION);
1089     animationOption.SetOnFinishEvent([movingPhotoPattern]() {
1090         auto movingPhoto = movingPhotoPattern.Upgrade();
1091         TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "movingphoto StartAnimation OnFinishEvent.");
1092         CHECK_NULL_VOID(movingPhoto);
1093         if (movingPhoto->currentPlayStatus_ == PlaybackStatus::PAUSED
1094             || movingPhoto->currentPlayStatus_ == PlaybackStatus::STOPPED
1095             || !movingPhoto->startAnimationFlag_) {
1096             return;
1097         }
1098         movingPhoto->HideImageNode();
1099     });
1100     startAnimationFlag_ = true;
1101     AnimationUtils::Animate(animationOption,
1102         [imageRsContext, videoRsContext, flag = autoAndRepeatLevel_, movingPhotoPattern]() {
1103             imageRsContext->UpdateOpacity(0.0);
1104             auto movingPhoto = movingPhotoPattern.Upgrade();
1105             CHECK_NULL_VOID(movingPhoto);
1106             movingPhoto->RsContextUpdateTransformScale(imageRsContext, videoRsContext, flag);
1107         }, animationOption.GetOnFinishEvent());
1108 }
1109 
RsContextUpdateTransformScale(const RefPtr<RenderContext> & imageRsContext,const RefPtr<RenderContext> & videoRsContext,PlaybackMode playbackMode)1110 void MovingPhotoPattern::RsContextUpdateTransformScale(const RefPtr<RenderContext>& imageRsContext,
1111     const RefPtr<RenderContext>& videoRsContext, PlaybackMode playbackMode)
1112 {
1113     if (playbackMode == PlaybackMode::REPEAT) {
1114         videoRsContext->UpdateTransformScale({NORMAL_SCALE, NORMAL_SCALE});
1115         imageRsContext->UpdateTransformScale({ZOOM_IN_SCALE, ZOOM_IN_SCALE});
1116     } else if (playbackMode == PlaybackMode::AUTO) {
1117         videoRsContext->UpdateTransformScale({NORMAL_SCALE, NORMAL_SCALE});
1118         imageRsContext->UpdateTransformScale({NORMAL_SCALE, NORMAL_SCALE});
1119     } else {
1120         videoRsContext->UpdateTransformScale({ZOOM_IN_SCALE, ZOOM_IN_SCALE});
1121         imageRsContext->UpdateTransformScale({ZOOM_IN_SCALE, ZOOM_IN_SCALE});
1122     }
1123 }
1124 
StopPlayback()1125 void MovingPhotoPattern::StopPlayback()
1126 {
1127     TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "movingphoto StopPlayback");
1128     isFastKeyUp_ = false;
1129     isPlayByController_ = false;
1130     Pause();
1131     autoAndRepeatLevel_ = PlaybackMode::NONE;
1132     if (historyAutoAndRepeatLevel_ != PlaybackMode::REPEAT) {
1133         StopAnimation();
1134     }
1135 }
1136 
PausePlayback()1137 void MovingPhotoPattern::PausePlayback()
1138 {
1139     TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "movingphoto PausePlayback");
1140     isFastKeyUp_ = false;
1141     if (currentPlayStatus_ != PlaybackStatus::STARTED || !isPrepared_) {
1142         return;
1143     }
1144     if (IsRefreshMovingPhotoReturn(isRefreshMovingPhotoPlaying_)) {
1145         TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "HandleTouchEvent IsRefreshMovingPhotoReturn.");
1146         return;
1147     }
1148     isPlayByController_ = false;
1149     Pause();
1150     StopAnimation();
1151 }
1152 
RefreshMovingPhoto()1153 void MovingPhotoPattern::RefreshMovingPhoto()
1154 {
1155     TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "movingphoto RefreshMovingPhoto start.");
1156     if (uri_ == "") {
1157         TAG_LOGW(AceLogTag::ACE_MOVING_PHOTO, "movingphoto RefreshMovingPhoto uri is null.");
1158         return;
1159     }
1160     auto host = GetHost();
1161     CHECK_NULL_VOID(host);
1162     auto layoutProperty = GetLayoutProperty<MovingPhotoLayoutProperty>();
1163     CHECK_NULL_VOID(layoutProperty);
1164     auto pipeline = PipelineBase::GetCurrentContext();
1165     CHECK_NULL_VOID(pipeline);
1166     auto dataProvider = AceType::DynamicCast<DataProviderManagerStandard>(pipeline->GetDataProviderManager());
1167     CHECK_NULL_VOID(dataProvider);
1168     if (!layoutProperty->HasMovingPhotoUri() || !layoutProperty->HasVideoSource()) {
1169         TAG_LOGW(AceLogTag::ACE_MOVING_PHOTO, "movingphoto source is null.");
1170         return;
1171     }
1172     std::string imageSrc = dataProvider->GetMovingPhotoImageUri(uri_);
1173     auto imageCache = pipeline->GetImageCache();
1174     if (imageCache) {
1175         ImageSourceInfo srcKey;
1176         srcKey.SetSrc(imageSrc);
1177         imageCache->ClearCacheImgObj(srcKey.GetKey());
1178     }
1179     imageSrc += "?date_modified = " + std::to_string(GetMicroTickCount());
1180     ImageSourceInfo src;
1181     src.SetSrc(imageSrc);
1182     ACE_UPDATE_NODE_LAYOUT_PROPERTY(MovingPhotoLayoutProperty, ImageSourceInfo, src, host);
1183     UpdateImageNode();
1184     fd_ = dataProvider->ReadMovingPhotoVideo(uri_);
1185     ACE_UPDATE_NODE_LAYOUT_PROPERTY(MovingPhotoLayoutProperty, VideoSource, fd_.GetValue(), host);
1186     isRefreshMovingPhoto_ = true;
1187     isSetAutoPlayPeriod_ = false;
1188     RefreshMovingPhotoSceneManager();
1189     ResetMediaPlayer();
1190     if (IsSupportImageAnalyzer() && isEnableAnalyzer_ && imageAnalyzerManager_) {
1191         UpdateAnalyzerOverlay();
1192     }
1193 }
1194 
RefreshMovingPhotoSceneManager()1195 void MovingPhotoPattern::RefreshMovingPhotoSceneManager()
1196 {
1197     auto host = GetHost();
1198     CHECK_NULL_VOID(host);
1199     if (historyAutoAndRepeatLevel_ == PlaybackMode::REPEAT) {
1200         autoAndRepeatLevel_ = PlaybackMode::NONE;
1201         historyAutoAndRepeatLevel_ = PlaybackMode::NONE;
1202         isRepeatChangePlayMode_ = true;
1203         Pause();
1204     } else if (historyAutoAndRepeatLevel_ == PlaybackMode::AUTO) {
1205         autoAndRepeatLevel_ = PlaybackMode::AUTO;
1206         isAutoChangePlayMode_ = true;
1207     }
1208 }
1209 
StopAnimation()1210 void MovingPhotoPattern::StopAnimation()
1211 {
1212     startAnimationFlag_ = false;
1213     if (historyAutoAndRepeatLevel_ == PlaybackMode::REPEAT) {
1214         StopAnimationCallback();
1215         return;
1216     }
1217     if (isRefreshMovingPhotoPlaying_) {
1218         isRefreshMovingPhotoPlaying_ = false;
1219     }
1220     auto host = GetHost();
1221     CHECK_NULL_VOID(host);
1222     auto movingPhoto = AceType::DynamicCast<MovingPhotoNode>(host);
1223     CHECK_NULL_VOID(movingPhoto);
1224     auto image = AceType::DynamicCast<FrameNode>(movingPhoto->GetImage());
1225     CHECK_NULL_VOID(image);
1226     auto imageLayoutProperty = image->GetLayoutProperty<ImageLayoutProperty>();
1227     CHECK_NULL_VOID(imageLayoutProperty);
1228     auto imageRsContext = image->GetRenderContext();
1229     CHECK_NULL_VOID(imageRsContext);
1230     auto video = AceType::DynamicCast<FrameNode>(movingPhoto->GetVideo());
1231     CHECK_NULL_VOID(video);
1232     auto videoRsContext = video->GetRenderContext();
1233     CHECK_NULL_VOID(videoRsContext);
1234 
1235     imageLayoutProperty->UpdateVisibility(VisibleType::VISIBLE);
1236     imageRsContext->UpdateOpacity(0.0);
1237     RsContextUpdateTransformScale(imageRsContext, videoRsContext, autoAndRepeatLevel_);
1238     image->MarkModifyDone();
1239     video->MarkModifyDone();
1240     auto movingPhotoPattern = WeakClaim(this);
1241     AnimationOption option;
1242     option.SetDuration(ANIMATION_DURATION_300);
1243     option.SetCurve(Curves::FRICTION);
1244     option.SetOnFinishEvent([movingPhotoPattern]() {
1245         auto movingPhoto = movingPhotoPattern.Upgrade();
1246         CHECK_NULL_VOID(movingPhoto);
1247         movingPhoto->StopAnimationCallback();
1248     });
1249     AnimationUtils::Animate(option, [imageRsContext, videoRsContext]() {
1250             imageRsContext->UpdateOpacity(1.0);
1251             imageRsContext->UpdateTransformScale({NORMAL_SCALE, NORMAL_SCALE});
1252             videoRsContext->UpdateTransformScale({NORMAL_SCALE, NORMAL_SCALE});
1253         }, option.GetOnFinishEvent());
1254 }
1255 
StopAnimationCallback()1256 void MovingPhotoPattern::StopAnimationCallback()
1257 {
1258     if (historyAutoAndRepeatLevel_ == PlaybackMode::AUTO && autoPlayPeriodStartTime_ >= 0) {
1259         Seek(static_cast<int32_t>(autoPlayPeriodStartTime_));
1260     } else {
1261         Seek(0);
1262     }
1263     TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "StopAnimation OnFinishEvent:%{public}d.", autoAndRepeatLevel_);
1264     if (needUpdateImageNode_) {
1265         UpdateImageNode();
1266         needUpdateImageNode_ = false;
1267     }
1268     if (autoAndRepeatLevel_ == PlaybackMode::REPEAT) {
1269         StartRepeatPlay();
1270     } else if (autoAndRepeatLevel_ == PlaybackMode::AUTO) {
1271         autoAndRepeatLevel_ = PlaybackMode::NONE;
1272     }
1273     if (historyAutoAndRepeatLevel_ == PlaybackMode::AUTO) {
1274         HandleImageAnalyzerMode();
1275     }
1276 }
1277 
AutoPlay(bool isAutoPlay)1278 void MovingPhotoPattern::AutoPlay(bool isAutoPlay)
1279 {
1280     TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "movingphoto AutoPlay: %{public}d.", isAutoPlay);
1281     if (isAutoPlay) {
1282         if (historyAutoAndRepeatLevel_ == PlaybackMode::AUTO) {
1283             return;
1284         }
1285         isChangePlayMode_ = true;
1286         if (autoAndRepeatLevel_ != PlaybackMode::REPEAT) {
1287             historyAutoAndRepeatLevel_ = PlaybackMode::AUTO;
1288             autoAndRepeatLevel_ = PlaybackMode::AUTO;
1289             if (!isSetAutoPlayPeriod_ && (currentPlayStatus_ == PlaybackStatus::PLAYBACK_COMPLETE ||
1290                 currentPlayStatus_ == PlaybackStatus::PAUSED)) {
1291                 isSetAutoPlayPeriod_ = true;
1292                 SetAutoPlayPeriod(autoPlayPeriodStartTime_, autoPlayPeriodEndTime_);
1293             }
1294         }
1295     }
1296 }
1297 
StartAutoPlay()1298 void MovingPhotoPattern::StartAutoPlay()
1299 {
1300     TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "movingphoto StartAutoPlay in.");
1301     isFastKeyUp_ = false;
1302     if (!mediaPlayer_ || !mediaPlayer_->IsMediaPlayerValid()) {
1303         return;
1304     }
1305 
1306     if (currentPlayStatus_ == PlaybackStatus::STOPPED) {
1307         mediaPlayer_->PrepareAsync();
1308     }
1309     Start();
1310 }
1311 
StartRepeatPlay()1312 void MovingPhotoPattern::StartRepeatPlay()
1313 {
1314     TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "movingphoto StartRepeatPlay in.");
1315     isFastKeyUp_ = false;
1316     if (!mediaPlayer_ || !mediaPlayer_->IsMediaPlayerValid()) {
1317         return;
1318     }
1319 
1320     if (currentPlayStatus_ == PlaybackStatus::STOPPED) {
1321         mediaPlayer_->PrepareAsync();
1322     }
1323     if (!isFirstRepeatPlay_ && isSetAutoPlayPeriod_) {
1324         int32_t duration = DURATION_FLAG;
1325         mediaPlayer_->GetDuration(duration);
1326         SetAutoPlayPeriod(PERIOD_START, duration);
1327     }
1328     Start();
1329 }
1330 
RepeatPlay(bool isRepeatPlay)1331 void MovingPhotoPattern::RepeatPlay(bool isRepeatPlay)
1332 {
1333     TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "movingphoto RepeatPlay status: %{public}d.", isRepeatPlay);
1334     if (isRepeatPlay && historyAutoAndRepeatLevel_ != PlaybackMode::REPEAT) {
1335         isChangePlayMode_ = true;
1336         isFirstRepeatPlay_ = true;
1337     }
1338     if (!isRepeatPlay && historyAutoAndRepeatLevel_ == PlaybackMode::REPEAT) {
1339         isChangePlayMode_ = true;
1340         historyAutoAndRepeatLevel_ = PlaybackMode::NONE;
1341         Pause();
1342         StopAnimation();
1343     }
1344     if (isRepeatPlay) {
1345         historyAutoAndRepeatLevel_ = PlaybackMode::REPEAT;
1346         autoAndRepeatLevel_ = PlaybackMode::REPEAT;
1347     }
1348 }
1349 
AutoPlayPeriod(int64_t startTime,int64_t endTime)1350 void MovingPhotoPattern::AutoPlayPeriod(int64_t startTime, int64_t endTime)
1351 {
1352     TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "movingphoto AutoPlayPeriod: [%{public}lld, %{public}lld].",
1353         static_cast<long long>(startTime), static_cast<long long>(endTime));
1354     if (startTime >= VIDEO_PLAYTIME_START_POSITION && startTime < endTime) {
1355         autoPlayPeriodStartTime_ = startTime;
1356         autoPlayPeriodEndTime_ = endTime;
1357     }
1358 }
1359 
SetAutoPlayPeriod(int64_t startTime,int64_t endTime)1360 void MovingPhotoPattern::SetAutoPlayPeriod(int64_t startTime, int64_t endTime)
1361 {
1362     TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "movingphoto SetAutoPlayPeriod: [%{public}lld, %{public}lld].",
1363         static_cast<long long>(startTime), static_cast<long long>(endTime));
1364     if (startTime < VIDEO_PLAYTIME_START_POSITION || startTime >= endTime) {
1365         TAG_LOGW(AceLogTag::ACE_MOVING_PHOTO, "MediaPlayer SetAutoPlayPeriod error.");
1366         return;
1367     }
1368     if (!mediaPlayer_ || !mediaPlayer_->IsMediaPlayerValid()) {
1369         TAG_LOGW(AceLogTag::ACE_MOVING_PHOTO, "MediaPlayer is null or invalid.");
1370         return;
1371     }
1372     mediaPlayer_->SetPlayRangeWithMode(startTime, endTime, SeekMode::SEEK_CLOSEST);
1373 }
1374 
HandleImageAnalyzerPlayCallBack()1375 void MovingPhotoPattern::HandleImageAnalyzerPlayCallBack()
1376 {
1377     TAG_LOGW(AceLogTag::ACE_MOVING_PHOTO, "HandleImageAnalyzerPlayCallBack start.");
1378     isFastKeyUp_ = false;
1379     if (currentPlayStatus_ == PlaybackStatus::STARTED || !isPrepared_ || isPlayByController_) {
1380         return;
1381     }
1382     if (IsRefreshMovingPhotoReturn(isRefreshMovingPhoto_)) {
1383         TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "HandleTouchEvent IsRefreshMovingPhotoReturn.");
1384         return;
1385     }
1386     if (!mediaPlayer_ || !mediaPlayer_->IsMediaPlayerValid()) {
1387         TAG_LOGW(AceLogTag::ACE_MOVING_PHOTO, "MediaPlayer is null or invalid.");
1388         FireMediaPlayerError();
1389         return;
1390     }
1391     if (currentPlayStatus_ == PlaybackStatus::STOPPED) {
1392         mediaPlayer_->PrepareAsync();
1393     }
1394     if (isSetAutoPlayPeriod_ && (currentPlayStatus_ == PlaybackStatus::PLAYBACK_COMPLETE ||
1395         currentPlayStatus_ == PlaybackStatus::PAUSED)) {
1396         int32_t duration = DURATION_FLAG;
1397         mediaPlayer_->GetDuration(duration);
1398         SetAutoPlayPeriod(PERIOD_START, duration);
1399     }
1400     Start();
1401 }
1402 
Start()1403 void MovingPhotoPattern::Start()
1404 {
1405     TAG_LOGW(AceLogTag::ACE_MOVING_PHOTO, "movingphoto start play.");
1406     if (!mediaPlayer_ || !mediaPlayer_->IsMediaPlayerValid()) {
1407         TAG_LOGW(AceLogTag::ACE_MOVING_PHOTO, "MediaPlayer is null or invalid.");
1408         return;
1409     }
1410     if (isRefreshMovingPhoto_) {
1411         isRefreshMovingPhoto_ = false;
1412     }
1413     if (currentPlayStatus_ == PlaybackStatus::STOPPED) {
1414         mediaPlayer_->PrepareAsync();
1415     }
1416     ContainerScope scope(instanceId_);
1417     auto context = PipelineContext::GetCurrentContext();
1418     CHECK_NULL_VOID(context);
1419 
1420     auto platformTask = SingleTaskExecutor::Make(context->GetTaskExecutor(), TaskExecutor::TaskType::BACKGROUND);
1421     platformTask.PostTask(
1422         [weak = WeakClaim(RawPtr(mediaPlayer_))] {
1423             auto mediaPlayer = weak.Upgrade();
1424             CHECK_NULL_VOID(mediaPlayer);
1425             mediaPlayer->Play();
1426         },
1427         "ArkUIMovingPhotoStartPlay");
1428 }
1429 
Pause()1430 void MovingPhotoPattern::Pause()
1431 {
1432     if (!mediaPlayer_ || !mediaPlayer_->IsMediaPlayerValid()) {
1433         TAG_LOGW(AceLogTag::ACE_MOVING_PHOTO, "MediaPlayer is null or invalid.");
1434         return;
1435     }
1436     ContainerScope scope(instanceId_);
1437     auto context = PipelineContext::GetCurrentContext();
1438     CHECK_NULL_VOID(context);
1439 
1440     auto platformTask = SingleTaskExecutor::Make(context->GetTaskExecutor(), TaskExecutor::TaskType::BACKGROUND);
1441     platformTask.PostTask(
1442         [weak = WeakClaim(RawPtr(mediaPlayer_))] {
1443             auto mediaPlayer = weak.Upgrade();
1444             CHECK_NULL_VOID(mediaPlayer);
1445             mediaPlayer->Pause();
1446         },
1447         "ArkUIMovingPhotoPausePlay");
1448 }
1449 
Stop()1450 void MovingPhotoPattern::Stop()
1451 {
1452     if (!mediaPlayer_ || !mediaPlayer_->IsMediaPlayerValid()) {
1453         TAG_LOGW(AceLogTag::ACE_MOVING_PHOTO, "MediaPlayer is null or invalid.");
1454         return;
1455     }
1456     ContainerScope scope(instanceId_);
1457     auto context = PipelineContext::GetCurrentContext();
1458     CHECK_NULL_VOID(context);
1459 
1460     auto platformTask = SingleTaskExecutor::Make(context->GetTaskExecutor(), TaskExecutor::TaskType::BACKGROUND);
1461     platformTask.PostTask(
1462         [weak = WeakClaim(RawPtr(mediaPlayer_))] {
1463             auto mediaPlayer = weak.Upgrade();
1464             CHECK_NULL_VOID(mediaPlayer);
1465             mediaPlayer->Stop();
1466         },
1467         "ArkUIMovingPhotoStopPlay");
1468 }
1469 
Seek(int32_t position)1470 void MovingPhotoPattern::Seek(int32_t position)
1471 {
1472     if (!mediaPlayer_ || !mediaPlayer_->IsMediaPlayerValid()) {
1473         TAG_LOGW(AceLogTag::ACE_MOVING_PHOTO, "MediaPlayer is null or invalid.");
1474         return;
1475     }
1476     ContainerScope scope(instanceId_);
1477     auto context = PipelineContext::GetCurrentContext();
1478     CHECK_NULL_VOID(context);
1479 
1480     auto platformTask = SingleTaskExecutor::Make(context->GetTaskExecutor(), TaskExecutor::TaskType::BACKGROUND);
1481     platformTask.PostTask(
1482         [weak = WeakClaim(RawPtr(mediaPlayer_)), pos = position] {
1483             auto mediaPlayer = weak.Upgrade();
1484             CHECK_NULL_VOID(mediaPlayer);
1485             mediaPlayer->Seek(pos, SeekMode::SEEK_PREVIOUS_SYNC);
1486         },
1487         "ArkUIMovingPhotoSeek");
1488 }
1489 
UpdateMediaPlayerSpeed()1490 void MovingPhotoPattern::UpdateMediaPlayerSpeed()
1491 {
1492     if (!mediaPlayer_ || !mediaPlayer_->IsMediaPlayerValid()) {
1493         TAG_LOGW(AceLogTag::ACE_MOVING_PHOTO, "MediaPlayer is null or invalid.");
1494         return;
1495     }
1496     ContainerScope scope(instanceId_);
1497     auto context = PipelineContext::GetCurrentContext();
1498     CHECK_NULL_VOID(context);
1499     auto platformTask = SingleTaskExecutor::Make(context->GetTaskExecutor(), TaskExecutor::TaskType::BACKGROUND);
1500     platformTask.PostTask(
1501         [weak = WeakClaim(RawPtr(mediaPlayer_))] {
1502             auto mediaPlayer = weak.Upgrade();
1503             CHECK_NULL_VOID(mediaPlayer);
1504             mediaPlayer->SetPlaybackSpeed(static_cast<float>(NORMAL_PLAY_SPEED));
1505         },
1506         "ArkUIMovingPhotoUpdateSpeed");
1507 }
1508 
UpdateMediaPlayerMuted()1509 void MovingPhotoPattern::UpdateMediaPlayerMuted()
1510 {
1511     if (!mediaPlayer_ || !mediaPlayer_->IsMediaPlayerValid()) {
1512         TAG_LOGW(AceLogTag::ACE_MOVING_PHOTO, "MediaPlayer is null or invalid.");
1513         return;
1514     }
1515     ContainerScope scope(instanceId_);
1516     float volume = isMuted_ ? 0.0f : 1.0f;
1517     auto context = PipelineContext::GetCurrentContext();
1518     CHECK_NULL_VOID(context);
1519     auto platformTask = SingleTaskExecutor::Make(context->GetTaskExecutor(), TaskExecutor::TaskType::BACKGROUND);
1520     platformTask.PostTask(
1521         [weak = WeakClaim(RawPtr(mediaPlayer_)), videoVolume = volume] {
1522             auto mediaPlayer = weak.Upgrade();
1523             CHECK_NULL_VOID(mediaPlayer);
1524             mediaPlayer->SetVolume(videoVolume, videoVolume);
1525         },
1526         "ArkUIMovingPhotoUpdateMuted");
1527 }
1528 
OnAreaChangedInner()1529 void MovingPhotoPattern::OnAreaChangedInner()
1530 {
1531     if (!SystemProperties::GetExtSurfaceEnabled()) {
1532         return;
1533     }
1534     auto host = GetHost();
1535     CHECK_NULL_VOID(host);
1536     auto geometryNode = host->GetGeometryNode();
1537     CHECK_NULL_VOID(geometryNode);
1538     auto videoNodeSize = geometryNode->GetContentSize();
1539     auto layoutProperty = GetLayoutProperty<MovingPhotoLayoutProperty>();
1540     CHECK_NULL_VOID(layoutProperty);
1541     auto videoFrameSize = MeasureContentLayout(videoNodeSize, layoutProperty);
1542     auto transformRelativeOffset = host->GetTransformRelativeOffset();
1543 
1544     Rect rect = Rect(transformRelativeOffset.GetX() + (videoNodeSize.Width() - videoFrameSize.Width()) / HALF,
1545         transformRelativeOffset.GetY() + (videoNodeSize.Height() - videoFrameSize.Height()) / HALF,
1546         videoFrameSize.Width(), videoFrameSize.Height());
1547     if (renderSurface_ && (rect != lastBoundsRect_)) {
1548         renderSurface_->SetExtSurfaceBounds(rect.Left(), rect.Top(), rect.Width(), rect.Height());
1549         lastBoundsRect_ = rect;
1550     }
1551 }
1552 
OnVisibleChange(bool isVisible)1553 void MovingPhotoPattern::OnVisibleChange(bool isVisible)
1554 {
1555     CHECK_NULL_VOID(mediaPlayer_);
1556     if (!isVisible) {
1557         StopPlayback();
1558     }
1559 }
1560 
OnWindowHide()1561 void MovingPhotoPattern::OnWindowHide()
1562 {
1563     TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "movingphoto OnWindowHide.");
1564     if (historyAutoAndRepeatLevel_ == PlaybackMode::AUTO) {
1565         PausePlayback();
1566     } else if (historyAutoAndRepeatLevel_ == PlaybackMode::REPEAT) {
1567         StopPlayback();
1568         return;
1569     }
1570     auto host = GetHost();
1571     CHECK_NULL_VOID(host);
1572     auto movingPhoto = AceType::DynamicCast<MovingPhotoNode>(host);
1573     CHECK_NULL_VOID(movingPhoto);
1574     auto image = AceType::DynamicCast<FrameNode>(movingPhoto->GetImage());
1575     CHECK_NULL_VOID(image);
1576     auto imageLayoutProperty = image->GetLayoutProperty<ImageLayoutProperty>();
1577     CHECK_NULL_VOID(imageLayoutProperty);
1578     imageLayoutProperty->UpdateVisibility(VisibleType::VISIBLE);
1579     auto rsContext = image->GetRenderContext();
1580     CHECK_NULL_VOID(rsContext);
1581     rsContext->UpdateOpacity(1.0);
1582     image->MarkModifyDone();
1583 }
1584 
OnWindowShow()1585 void MovingPhotoPattern::OnWindowShow()
1586 {
1587     TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "movingphoto OnWindowShow.");
1588     CHECK_NULL_VOID(mediaPlayer_);
1589     if (autoAndRepeatLevel_ == PlaybackMode::REPEAT && currentPlayStatus_ == PlaybackStatus::STOPPED) {
1590         mediaPlayer_->PrepareAsync();
1591     }
1592 }
1593 
RegisterVisibleAreaChange()1594 void MovingPhotoPattern::RegisterVisibleAreaChange()
1595 {
1596     TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "movingphoto RegisterVisibleAreaChange.");
1597     if (hasVisibleChangeRegistered_) {
1598         return;
1599     }
1600     auto pipeline = PipelineContext::GetCurrentContextSafely();
1601     CHECK_NULL_VOID(pipeline);
1602     auto callback = [weak = WeakClaim(this)](bool visible, double ratio) {
1603         auto pattern = weak.Upgrade();
1604         CHECK_NULL_VOID(pattern);
1605         pattern->isVisible_ = visible;
1606         pattern->VisibleAreaCallback(visible);
1607     };
1608     auto host = GetHost();
1609     CHECK_NULL_VOID(host);
1610     std::vector<double> ratioList = {1.0};
1611     pipeline->AddVisibleAreaChangeNode(host, ratioList, callback, false);
1612     hasVisibleChangeRegistered_ = true;
1613 }
1614 
VisibleAreaCallback(bool visible)1615 void MovingPhotoPattern::VisibleAreaCallback(bool visible)
1616 {
1617     TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "movingphoto VisibleAreaCallback:%{public}d.", visible);
1618     if (visible) {
1619         if (historyAutoAndRepeatLevel_ == PlaybackMode::AUTO &&
1620             (currentPlayStatus_ == PlaybackStatus::PLAYBACK_COMPLETE ||
1621             currentPlayStatus_ == PlaybackStatus::PAUSED)) {
1622             isSetAutoPlayPeriod_ = true;
1623             SetAutoPlayPeriod(autoPlayPeriodStartTime_, autoPlayPeriodEndTime_);
1624         }
1625         MediaResetToPlay();
1626     } else {
1627         if (historyAutoAndRepeatLevel_ == PlaybackMode::AUTO) {
1628             PausePlayback();
1629         } else if (historyAutoAndRepeatLevel_ == PlaybackMode::REPEAT) {
1630             StopPlayback();
1631         }
1632         if (isRefreshMovingPhoto_) {
1633             isSetAutoPlayPeriod_ = false;
1634             ResetMediaPlayer();
1635         }
1636     }
1637 }
1638 
EnableAnalyzer(bool enabled)1639 void MovingPhotoPattern::EnableAnalyzer(bool enabled)
1640 {
1641     TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "movingphoto EnableAnalyzer:%{public}d.", enabled);
1642     isEnableAnalyzer_ = enabled;
1643     if (!isEnableAnalyzer_) {
1644         DestroyAnalyzerOverlay();
1645         LongPressEventModify(true);
1646         return;
1647     }
1648 
1649     CHECK_NULL_VOID(!imageAnalyzerManager_);
1650     auto host = GetHost();
1651     CHECK_NULL_VOID(host);
1652     imageAnalyzerManager_ = std::make_shared<ImageAnalyzerManager>(host, ImageAnalyzerHolder::MOVINGPHOTO);
1653 }
1654 
SetImageAIOptions(void * options)1655 void MovingPhotoPattern::SetImageAIOptions(void* options)
1656 {
1657     TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "movingphoto SetImageAIOptions");
1658     if (!imageAnalyzerManager_) {
1659         imageAnalyzerManager_ = std::make_shared<ImageAnalyzerManager>(GetHost(), ImageAnalyzerHolder::MOVINGPHOTO);
1660     }
1661     CHECK_NULL_VOID(imageAnalyzerManager_);
1662     imageAnalyzerManager_->SetImageAIOptions(options);
1663 }
1664 
IsSupportImageAnalyzer()1665 bool MovingPhotoPattern::IsSupportImageAnalyzer()
1666 {
1667     TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "movingphoto IsSupportImageAnalyzer");
1668     auto host = GetHost();
1669     CHECK_NULL_RETURN(host, false);
1670     auto layoutProperty = host->GetLayoutProperty<MovingPhotoLayoutProperty>();
1671     CHECK_NULL_RETURN(layoutProperty, false);
1672     CHECK_NULL_RETURN(imageAnalyzerManager_, false);
1673     return imageAnalyzerManager_->IsSupportImageAnalyzerFeature();
1674 }
1675 
ShouldUpdateImageAnalyzer()1676 bool MovingPhotoPattern::ShouldUpdateImageAnalyzer()
1677 {
1678     TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "movingphoto ShouldUpdateImageAnalyzer");
1679     auto layoutProperty = GetLayoutProperty<MovingPhotoLayoutProperty>();
1680     CHECK_NULL_RETURN(layoutProperty, false);
1681     const auto& constraint = layoutProperty->GetCalcLayoutConstraint();
1682     if (!constraint || !constraint->selfIdealSize.has_value() || !constraint->selfIdealSize->IsValid()) {
1683         return false;
1684     }
1685     auto selfIdealSize = constraint->selfIdealSize;
1686     if (!selfIdealSize->PercentWidth() && !selfIdealSize->PercentHeight()) {
1687         return false;
1688     }
1689     auto imageFit = layoutProperty->GetObjectFit().value_or(ImageFit::COVER);
1690     if (imageFit != ImageFit::COVER && imageFit != ImageFit::NONE) {
1691         return false;
1692     }
1693     return true;
1694 }
1695 
StartImageAnalyzer()1696 void MovingPhotoPattern::StartImageAnalyzer()
1697 {
1698     TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "movingphoto StartImageAnalyzer");
1699     if (!IsSupportImageAnalyzer() || !imageAnalyzerManager_) {
1700         return;
1701     }
1702 
1703     if (imageAnalyzerManager_->IsOverlayCreated()) {
1704         DestroyAnalyzerOverlay();
1705         LongPressEventModify(true);
1706     }
1707 
1708     ContainerScope scope(instanceId_);
1709     auto host = GetHost();
1710     CHECK_NULL_VOID(host);
1711     auto context = host->GetContext();
1712     CHECK_NULL_VOID(context);
1713     auto uiTaskExecutor = SingleTaskExecutor::Make(context->GetTaskExecutor(), TaskExecutor::TaskType::UI);
1714     uiTaskExecutor.PostDelayedTask([weak = WeakClaim(this)] {
1715         auto pattern = weak.Upgrade();
1716         CHECK_NULL_VOID(pattern);
1717         pattern->CreateAnalyzerOverlay();
1718         }, ANALYZER_DELAY_TIME, "ArkUIMovingPhotoCreateAnalyzerOverlay");
1719     LongPressEventModify(false);
1720 }
1721 
CreateAnalyzerOverlay()1722 void MovingPhotoPattern::CreateAnalyzerOverlay()
1723 {
1724     TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "movingphoto CreateAnalyzerOverlay");
1725     CHECK_NULL_VOID(imageAnalyzerManager_);
1726     if (imageAnalyzerManager_->IsOverlayCreated()) {
1727         return;
1728     }
1729     GetPixelMap();
1730     int64_t coverPosition = GetUriCoverPosition();
1731     auto onCanPlay = [weak = AceType::WeakClaim(this)](bool canPlay) {
1732         auto pattern = weak.Upgrade();
1733         CHECK_NULL_VOID(pattern);
1734         pattern->HandleAnalyzerPlayEvent(canPlay);
1735     };
1736     auto host = GetHost();
1737     CHECK_NULL_VOID(host);
1738     auto geometryNode = host->GetGeometryNode();
1739     CHECK_NULL_VOID(geometryNode);
1740     auto movingPhotoNodeSize = geometryNode->GetContentSize();
1741     MovingPhotoAnalyzerInfo info = {uri_, coverPosition,
1742                                     movingPhotoNodeSize.Width(),
1743                                     movingPhotoNodeSize.Height()};
1744     imageAnalyzerManager_->SetOnCanPlayCallback(std::move(onCanPlay));
1745     imageAnalyzerManager_->CreateMovingPhotoAnalyzerOverlay(pixelMap_, info);
1746 }
1747 
StartUpdateImageAnalyzer()1748 void MovingPhotoPattern::StartUpdateImageAnalyzer()
1749 {
1750     TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "movingphoto StartUpdateImageAnalyzer");
1751     CHECK_NULL_VOID(imageAnalyzerManager_);
1752     if (!imageAnalyzerManager_->IsOverlayCreated()) {
1753         return;
1754     }
1755 
1756     UpdateOverlayVisibility(VisibleType::GONE);
1757     ContainerScope scope(instanceId_);
1758     auto host = GetHost();
1759     CHECK_NULL_VOID(host);
1760     auto context = host->GetContext();
1761     CHECK_NULL_VOID(context);
1762     auto uiTaskExecutor = SingleTaskExecutor::Make(context->GetTaskExecutor(), TaskExecutor::TaskType::UI);
1763     uiTaskExecutor.PostDelayedTask([weak = WeakClaim(this)] {
1764         auto pattern = weak.Upgrade();
1765         CHECK_NULL_VOID(pattern);
1766         if (!pattern->isContentSizeChanged_) {
1767             return;
1768         }
1769         pattern->UpdateAnalyzerOverlay();
1770         pattern->isContentSizeChanged_ = false;
1771         }, ANALYZER_CAPTURE_DELAY_TIME, "ArkUIMovingPhotoUpdateAnalyzerOverlay");
1772     isContentSizeChanged_ = true;
1773 }
1774 
UpdateAnalyzerOverlay()1775 void MovingPhotoPattern::UpdateAnalyzerOverlay()
1776 {
1777     TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "movingphoto UpdateAnalyzerOverlay");
1778     CHECK_NULL_VOID(imageAnalyzerManager_);
1779     if (!IsSupportImageAnalyzer() || !imageAnalyzerManager_->IsOverlayCreated()) {
1780         return;
1781     }
1782     GetPixelMap();
1783     int64_t coverPosition = GetUriCoverPosition();
1784     UpdateOverlayVisibility(VisibleType::VISIBLE);
1785     auto host = GetHost();
1786     CHECK_NULL_VOID(host);
1787     auto geometryNode = host->GetGeometryNode();
1788     CHECK_NULL_VOID(geometryNode);
1789     auto movingPhotoNodeSize = geometryNode->GetContentSize();
1790     MovingPhotoAnalyzerInfo info = {uri_, coverPosition,
1791                                     movingPhotoNodeSize.Width(),
1792                                     movingPhotoNodeSize.Height()};
1793     imageAnalyzerManager_->UpdateMovingPhotoAnalyzerOverlay(pixelMap_, info);
1794 }
1795 
UpdateAnalyzerUIConfig(const RefPtr<NG::GeometryNode> & geometryNode)1796 void MovingPhotoPattern::UpdateAnalyzerUIConfig(const RefPtr<NG::GeometryNode>& geometryNode)
1797 {
1798     TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "movingphoto UpdateAnalyzerUIConfig");
1799     if (IsSupportImageAnalyzer()) {
1800         auto layoutProperty = GetLayoutProperty<MovingPhotoLayoutProperty>();
1801         CHECK_NULL_VOID(layoutProperty);
1802         auto padding  = layoutProperty->CreatePaddingAndBorder();
1803         OffsetF contentOffset = { contentRect_.Left() - padding.left.value_or(0),
1804                                   contentRect_.Top() - padding.top.value_or(0) };
1805         PixelMapInfo info = { contentRect_.GetSize().Width(), contentRect_.GetSize().Height(), contentOffset };
1806         CHECK_NULL_VOID(imageAnalyzerManager_);
1807         imageAnalyzerManager_->UpdateAnalyzerUIConfig(geometryNode, info);
1808     }
1809 }
1810 
DestroyAnalyzerOverlay()1811 void MovingPhotoPattern::DestroyAnalyzerOverlay()
1812 {
1813     TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "movingphoto DestroyAnalyzerOverlay");
1814     CHECK_NULL_VOID(imageAnalyzerManager_);
1815     imageAnalyzerManager_->DestroyAnalyzerOverlay();
1816 }
1817 
GetAnalyzerState()1818 bool MovingPhotoPattern::GetAnalyzerState()
1819 {
1820     TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "movingphoto GetAnalyzerState");
1821     CHECK_NULL_RETURN(imageAnalyzerManager_, false);
1822     return imageAnalyzerManager_->IsOverlayCreated();
1823 }
1824 
UpdateOverlayVisibility(VisibleType type)1825 void MovingPhotoPattern::UpdateOverlayVisibility(VisibleType type)
1826 {
1827     auto host = GetHost();
1828     CHECK_NULL_VOID(host);
1829     auto overlayNode = host->GetOverlayNode();
1830     CHECK_NULL_VOID(overlayNode);
1831     auto prop = overlayNode->GetLayoutProperty();
1832     CHECK_NULL_VOID(prop);
1833     prop->UpdateVisibility(type);
1834 }
1835 
GetPixelMap()1836 void MovingPhotoPattern::GetPixelMap()
1837 {
1838     auto layoutProperty = GetLayoutProperty<MovingPhotoLayoutProperty>();
1839     CHECK_NULL_VOID(layoutProperty);
1840     if (!layoutProperty->HasMovingPhotoUri() || !layoutProperty->HasVideoSource()) {
1841         TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "GetPixelMap MovingPhoto source is null.");
1842         return;
1843     }
1844     auto pipeline = PipelineBase::GetCurrentContext();
1845     CHECK_NULL_VOID(pipeline);
1846     auto dataProvider = AceType::DynamicCast<DataProviderManagerStandard>(pipeline->GetDataProviderManager());
1847     CHECK_NULL_VOID(dataProvider);
1848     std::string imageSrc = dataProvider->GetMovingPhotoImagePath(uri_);
1849     std::string thumbnailUrl = uri_ + THUMBNAIL_MEDIUM_JOINT + imageSrc;
1850     void* pixelMapMediauniquePtr = dataProvider->GetDataProviderThumbnailResFromUri(thumbnailUrl);
1851     CHECK_NULL_VOID(pixelMapMediauniquePtr);
1852     auto pixelMap = PixelMap::CreatePixelMapFromDataAbility(pixelMapMediauniquePtr);
1853     CHECK_NULL_VOID(pixelMap);
1854     pixelMap_ = pixelMap;
1855 }
1856 
GetUriCoverPosition()1857 int64_t MovingPhotoPattern::GetUriCoverPosition()
1858 {
1859     auto pipeline = PipelineBase::GetCurrentContext();
1860     CHECK_NULL_RETURN(pipeline, -1);
1861     auto dataProvider = AceType::DynamicCast<DataProviderManagerStandard>(pipeline->GetDataProviderManager());
1862     CHECK_NULL_RETURN(dataProvider, -1);
1863     std::vector<std::string> columns = {COVER_POSITION};
1864     auto result = dataProvider->GetMovingPhotoCoverPosition(IMAGE_URI, uri_, columns);
1865     return result;
1866 }
1867 
HandleAnalyzerPlayEvent(bool canPlay)1868 void MovingPhotoPattern::HandleAnalyzerPlayEvent(bool canPlay)
1869 {
1870     TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "MovingPhoto HandleAnalyzerPlayEvent:%{public}d", canPlay);
1871     if (isAnalyzerPlaying_ == canPlay || isPlayByController_) {
1872         return;
1873     }
1874     if (isAnalyzerPlaying_ && !canPlay) {
1875         Pause();
1876         StopAnimation();
1877     }
1878     isAnalyzerPlaying_ = canPlay;
1879     if (canPlay) {
1880         if (isRefreshMovingPhoto_) {
1881             isRefreshMovingPhotoPlaying_ = true;
1882         }
1883         HandleImageAnalyzerPlayCallBack();
1884     }
1885 }
1886 
IsRefreshMovingPhotoReturn(bool status)1887 bool MovingPhotoPattern::IsRefreshMovingPhotoReturn(bool status)
1888 {
1889     if (status) {
1890         if (autoAndRepeatLevel_ == PlaybackMode::REPEAT) {
1891             TAG_LOGW(AceLogTag::ACE_MOVING_PHOTO, "IsRefreshMovingPhotoReturn:%{public}d.", status);
1892             return true;
1893         }
1894     } else {
1895         if (autoAndRepeatLevel_ != PlaybackMode::NONE) {
1896             TAG_LOGW(AceLogTag::ACE_MOVING_PHOTO, "IsRefreshMovingPhotoReturn not:%{public}d.", status);
1897             return true;
1898         }
1899     }
1900     return false;
1901 }
1902 
~MovingPhotoPattern()1903 MovingPhotoPattern::~MovingPhotoPattern()
1904 {
1905     if (IsSupportImageAnalyzer()) {
1906         TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "~MovingPhotoPattern DestroyAnalyzerOverlay.");
1907         DestroyAnalyzerOverlay();
1908     }
1909 }
1910 } // namespace OHOS::Ace::NG