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