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