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