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