* Copyright (c) 2024 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <unistd.h>
#include "movingphoto_pattern.h"
#include "core/common/container.h"
#include "movingphoto_node.h"
#include "movingphoto_utils.h"
#include "base/image/pixel_map.h"
#include "base/resource/data_provider_manager.h"
#include "core/components_ng/pattern/image/image_pattern.h"
#include "core/image/image_cache.h"
#include "core/pipeline_ng/pipeline_context.h"
#include "core/pipeline/base/element_register.h"
#if defined(PLAYER_FRAMEWORK_EXISTS)
#include "meta/meta.h"
#endif
namespace OHOS::Ace::NG {
namespace {
constexpr int32_t LONG_PRESS_DELAY = 300;
constexpr int32_t ANIMATION_DURATION_300 = 300;
constexpr int32_t ANIMATION_DURATION_400 = 400;
constexpr float NORMAL_SCALE = 1.0f;
constexpr float ZOOM_IN_SCALE = 1.1f;
constexpr double NORMAL_PLAY_SPEED = 1.0;
constexpr int32_t HALF = 2;
constexpr int32_t ROUND_XMAGE_MODE_VALUE = 0;
constexpr int64_t PERIOD_START = 0;
constexpr int32_t PREPARE_RETURN = 0;
constexpr int64_t VIDEO_PLAYTIME_START_POSITION = 0;
constexpr int32_t IMAGE_DECODE_COMPLETE = 1;
constexpr int32_t DURATION_FLAG = -1;
const std::string THUMBNAIL_MEDIUM_JOINT = "?&oper=thumbnail&width=-1&height=-1&path=";
const std::string COVER_POSITION = "cover_positon";
const std::string IMAGE_URI = "uri";
const std::string VIDEO_SCALE = "video_scale_type";
const std::string IMAGE_LENGTH = "ImageLength";
const std::string IMAGE_WIDTH = "ImageWidth";
const std::string HW_MNOTE_XMAGE_MODE = "HwMnoteXmageMode";
const std::string HW_MNOTE_XMAGE_LEFT = "HwMnoteXmageLeft";
const std::string HW_MNOTE_XMAGE_TOP = "HwMnoteXmageTop";
const std::string HW_MNOTE_XMAGE_RIGHT = "HwMnoteXmageRight";
const std::string HW_MNOTE_XMAGE_BOTTOM = "HwMnoteXmageBottom";
const std::string DEFAULT_EXIF_VALUE = "default_exif_value";
const std::string SCALING_FACTOR = "com.openharmony.scaling_factor";
constexpr int32_t ANALYZER_DELAY_TIME = 100;
constexpr int32_t ANALYZER_CAPTURE_DELAY_TIME = 1000;
constexpr int32_t AVERAGE_VALUE = 2;
constexpr int32_t US_CONVERT = 1000;
constexpr int32_t ROUND_XMAGE_PIXEL_GAP = 2;
constexpr int32_t EIGHTY_TO_HUNDRED_TIME = 3000;
constexpr int32_t NODE_COUNT = 2;
}
MovingPhotoPattern::MovingPhotoPattern(const RefPtr<MovingPhotoController>& controller)
: instanceId_(Container::CurrentId()), controller_(controller)
{}
void MovingPhotoPattern::OnModifyDone()
{
TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "movingphoto onModifydone start.");
Pattern::OnModifyDone();
UpdateImageNode();
UpdateVideoNode();
if (SystemProperties::GetExtSurfaceEnabled()) {
auto pipelineContext = PipelineContext::GetCurrentContext();
CHECK_NULL_VOID(pipelineContext);
auto host = GetHost();
CHECK_NULL_VOID(host);
pipelineContext->AddOnAreaChangeNode(host->GetId());
}
InitEvent();
UpdatePlayMode();
HandleImageAnalyzerMode();
}
void MovingPhotoPattern::OnAttachToFrameNode()
{
auto host = GetHost();
CHECK_NULL_VOID(host);
auto renderContext = host->GetRenderContext();
CHECK_NULL_VOID(renderContext);
static RenderContext::ContextParam param = { RenderContext::ContextType::HARDWARE_SURFACE, "MediaPlayerSurface",
RenderContext::PatternType::VIDEO };
renderContextForMediaPlayer_->InitContext(false, param);
renderContext->UpdateBackgroundColor(Color::TRANSPARENT);
renderContextForMediaPlayer_->UpdateBackgroundColor(Color::TRANSPARENT);
renderContext->SetClipToBounds(true);
CHECK_NULL_VOID(controller_);
ContainerScope scope(instanceId_);
auto context = PipelineContext::GetCurrentContext();
CHECK_NULL_VOID(context);
auto uiTaskExecutor = SingleTaskExecutor::Make(context->GetTaskExecutor(), TaskExecutor::TaskType::UI);
SetStartPlaybackImpl(uiTaskExecutor);
SetStopPlaybackImpl(uiTaskExecutor);
SetRefreshMovingPhotoImpl(uiTaskExecutor);
SetPauseImpl(uiTaskExecutor);
SetResetImpl(uiTaskExecutor);
SetRestartImpl(uiTaskExecutor);
SetEnableTransitionImpl(uiTaskExecutor);
SetPlaybackPeriodImpl(uiTaskExecutor);
SetEnableAutoPlayImpl(uiTaskExecutor);
SetNotifyTransitionImpl(uiTaskExecutor);
RegisterVisibleAreaChange();
}
void MovingPhotoPattern::SetStartPlaybackImpl(const SingleTaskExecutor& uiTaskExecutor)
{
controller_->SetStartPlaybackImpl([weak = WeakClaim(this), uiTaskExecutor]() {
uiTaskExecutor.PostTask(
[weak]() {
auto pattern = weak.Upgrade();
CHECK_NULL_VOID(pattern);
ContainerScope scope(pattern->instanceId_);
pattern->StartPlayback();
}, "ArkUIMovingPhotoStart");
});
}
void MovingPhotoPattern::SetStopPlaybackImpl(const SingleTaskExecutor& uiTaskExecutor)
{
controller_->SetStopPlaybackImpl([weak = WeakClaim(this), uiTaskExecutor]() {
uiTaskExecutor.PostTask(
[weak]() {
auto pattern = weak.Upgrade();
CHECK_NULL_VOID(pattern);
ContainerScope scope(pattern->instanceId_);
pattern->StopPlayback();
}, "ArkUIMovingPhotoStop");
});
}
void MovingPhotoPattern::SetRefreshMovingPhotoImpl(const SingleTaskExecutor& uiTaskExecutor)
{
controller_->SetRefreshMovingPhotoImpl([weak = WeakClaim(this), uiTaskExecutor]() {
uiTaskExecutor.PostTask(
[weak]() {
auto pattern = weak.Upgrade();
CHECK_NULL_VOID(pattern);
ContainerScope scope(pattern->instanceId_);
pattern->RefreshMovingPhoto();
}, "ArkUIRefreshMovingPhoto");
});
}
void MovingPhotoPattern::SetPauseImpl(const SingleTaskExecutor& uiTaskExecutor)
{
controller_->SetPauseImpl([weak = WeakClaim(this), uiTaskExecutor]() {
uiTaskExecutor.PostTask(
[weak]() {
auto pattern = weak.Upgrade();
CHECK_NULL_VOID(pattern);
ContainerScope scope(pattern->instanceId_);
pattern->PauseVideo();
}, "ArkUIPauseVideo");
});
}
void MovingPhotoPattern::SetResetImpl(const SingleTaskExecutor& uiTaskExecutor)
{
controller_->SetResetImpl([weak = WeakClaim(this), uiTaskExecutor]() {
uiTaskExecutor.PostTask(
[weak]() {
auto pattern = weak.Upgrade();
CHECK_NULL_VOID(pattern);
ContainerScope scope(pattern->instanceId_);
pattern->ResetVideo();
}, "ArkUIResetVideo");
});
}
void MovingPhotoPattern::SetRestartImpl(const SingleTaskExecutor& uiTaskExecutor)
{
controller_->SetRestartImpl([weak = WeakClaim(this), uiTaskExecutor]() {
uiTaskExecutor.PostTask(
[weak]() {
auto pattern = weak.Upgrade();
CHECK_NULL_VOID(pattern);
ContainerScope scope(pattern->instanceId_);
pattern->RestartVideo();
}, "ArkUIRestartVideo");
});
}
void MovingPhotoPattern::SetEnableTransitionImpl(const SingleTaskExecutor& uiTaskExecutor)
{
controller_->SetEnableTransitionImpl([weak = WeakClaim(this), uiTaskExecutor](bool enabled) {
uiTaskExecutor.PostTask(
[weak, enabled]() {
auto pattern = weak.Upgrade();
CHECK_NULL_VOID(pattern);
ContainerScope scope(pattern->instanceId_);
pattern->SetEnableTransition(enabled);
}, "ArkUISetEnableTransition");
});
}
void MovingPhotoPattern::SetPlaybackPeriodImpl(const SingleTaskExecutor& uiTaskExecutor)
{
controller_->SetPlaybackPeriodImpl([weak = WeakClaim(this), uiTaskExecutor](int64_t startTime, int64_t endTime) {
uiTaskExecutor.PostTask(
[weak, startTime, endTime]() {
auto pattern = weak.Upgrade();
CHECK_NULL_VOID(pattern);
ContainerScope scope(pattern->instanceId_);
bool isSetPeriod = false;
isSetPeriod = pattern->SetPlaybackPeriod(startTime, endTime);
if (!isSetPeriod) {
pattern->FireMediaPlayerError();
}
}, "ArkUISetPlaybackPeriod");
});
}
void MovingPhotoPattern::SetEnableAutoPlayImpl(const SingleTaskExecutor& uiTaskExecutor)
{
controller_->SetEnableAutoPlayImpl([weak = WeakClaim(this), uiTaskExecutor](bool enabled) {
uiTaskExecutor.PostTask(
[weak, enabled]() {
auto pattern = weak.Upgrade();
CHECK_NULL_VOID(pattern);
ContainerScope scope(pattern->instanceId_);
pattern->EnableAutoPlay(enabled);
}, "ArkUIEnableAutoPlay");
});
}
void MovingPhotoPattern::SetNotifyTransitionImpl(const SingleTaskExecutor& uiTaskExecutor)
{
controller_->SetNotifyTransitionImpl([weak = WeakClaim(this), uiTaskExecutor]() {
uiTaskExecutor.PostTask(
[weak]() {
auto pattern = weak.Upgrade();
CHECK_NULL_VOID(pattern);
ContainerScope scope(pattern->instanceId_);
pattern->NotifyTransition();
}, "ArkUINotifyTransition");
});
}
void MovingPhotoPattern::OnDetachFromFrameNode(FrameNode* frameNode)
{
auto id = frameNode->GetId();
auto pipeline = AceType::DynamicCast<PipelineContext>(PipelineBase::GetCurrentContext());
CHECK_NULL_VOID(pipeline);
pipeline->RemoveWindowStateChangedCallback(id);
hasVisibleChangeRegistered_ = false;
}
void MovingPhotoPattern::OnDetachFromMainTree()
{
auto host = GetHost();
CHECK_NULL_VOID(host);
if (host->GetNodeStatus() == NodeStatus::BUILDER_NODE_OFF_MAINTREE) {
Stop();
}
}
void MovingPhotoPattern::OnRebuildFrame()
{
if (!renderSurface_ || !renderSurface_->IsSurfaceValid()) {
return;
}
auto host = GetHost();
CHECK_NULL_VOID(host);
auto movingPhotoNode = AceType::DynamicCast<MovingPhotoNode>(host);
CHECK_NULL_VOID(movingPhotoNode);
int32_t childCount = movingPhotoNode->GetTotalChildCount();
CHECK_NULL_VOID(childCount >= 1);
auto column = AceType::DynamicCast<FrameNode>(movingPhotoNode->GetColumn(childCount - 1));
CHECK_NULL_VOID(column);
auto columnRenderContext = column->GetRenderContext();
columnRenderContext->SetClipToBounds(true);
auto video = AceType::DynamicCast<FrameNode>(movingPhotoNode->GetVideo(childCount - 1));
CHECK_NULL_VOID(video);
auto renderContext = video->GetRenderContext();
renderContext->AddChild(renderContextForMediaPlayer_, 0);
}
void MovingPhotoPattern::InitEvent()
{
auto host = GetHost();
CHECK_NULL_VOID(host);
auto gestureHub = host->GetOrCreateGestureEventHub();
CHECK_NULL_VOID(gestureHub);
if (longPressEvent_) {
if (isEnableAnalyzer_) {
gestureHub->SetLongPressEvent(nullptr);
longPressEvent_ = nullptr;
} else {
gestureHub->SetLongPressEvent(longPressEvent_, false, false, LONG_PRESS_DELAY);
}
}
if (!isEnableAnalyzer_) {
auto longPressCallback = [weak = WeakClaim(this)](GestureEvent& info) {
auto pattern = weak.Upgrade();
CHECK_NULL_VOID(pattern);
pattern->HandleLongPress(info);
};
longPressEvent_ = MakeRefPtr<LongPressEvent>(std::move(longPressCallback));
gestureHub->SetLongPressEvent(longPressEvent_, false, false, LONG_PRESS_DELAY);
}
if (touchEvent_) {
gestureHub->AddTouchEvent(touchEvent_);
return;
}
auto touchTask = [weak = WeakClaim(this)](TouchEventInfo& info) {
auto pattern = weak.Upgrade();
CHECK_NULL_VOID(pattern);
pattern->HandleTouchEvent(info);
};
touchEvent_ = MakeRefPtr<TouchEventImpl>(std::move(touchTask));
gestureHub->AddTouchEvent(touchEvent_);
}
void MovingPhotoPattern::LongPressEventModify(bool status)
{
auto host = GetHost();
CHECK_NULL_VOID(host);
auto gestureHub = host->GetOrCreateGestureEventHub();
CHECK_NULL_VOID(gestureHub);
if (status) {
auto longPressCallback = [weak = WeakClaim(this)](GestureEvent& info) {
auto pattern = weak.Upgrade();
CHECK_NULL_VOID(pattern);
pattern->HandleLongPress(info);
};
longPressEvent_ = MakeRefPtr<LongPressEvent>(std::move(longPressCallback));
gestureHub->SetLongPressEvent(longPressEvent_, false, false, LONG_PRESS_DELAY);
} else {
gestureHub->SetLongPressEvent(nullptr);
longPressEvent_ = nullptr;
}
}
void MovingPhotoPattern::HandleLongPress(GestureEvent& info)
{
isFastKeyUp_ = false;
if (currentPlayStatus_ == PlaybackStatus::STARTED || !isPrepared_ || isPlayByController_) {
return;
}
if (autoAndRepeatLevel_ == PlaybackMode::NONE && isEnableAnalyzer_) {
TAG_LOGW(AceLogTag::ACE_MOVING_PHOTO, "HandleLongPress isEnableAnalyzer_ return.");
return;
}
if (isRefreshMovingPhoto_) {
if (autoAndRepeatLevel_ == PlaybackMode::REPEAT) {
TAG_LOGW(AceLogTag::ACE_MOVING_PHOTO, "HandleLongPress IsRefreshMovingPhotoReturn:%{public}d.",
isRefreshMovingPhoto_);
return;
}
isRefreshMovingPhotoPlaying_ = true;
} else {
if (autoAndRepeatLevel_ != PlaybackMode::NONE) {
TAG_LOGW(AceLogTag::ACE_MOVING_PHOTO, "HandleLongPress IsRefreshMovingPhotoReturn not:%{public}d.",
isRefreshMovingPhoto_);
return;
}
}
TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "movingphoto HandleLongPress start.");
if (!mediaPlayer_ || !mediaPlayer_->IsMediaPlayerValid()) {
TAG_LOGW(AceLogTag::ACE_MOVING_PHOTO, "MediaPlayer is null or invalid.");
FireMediaPlayerError();
return;
}
if (currentPlayStatus_ == PlaybackStatus::STOPPED) {
mediaPlayer_->PrepareAsync();
}
if (currentPlayStatus_ == PlaybackStatus::PLAYBACK_COMPLETE || currentPlayStatus_ == PlaybackStatus::PAUSED) {
int32_t duration = DURATION_FLAG;
mediaPlayer_->GetDuration(duration);
SetAutoPlayPeriod(PERIOD_START, duration * US_CONVERT);
}
isGestureTriggeredLongPress_ = true;
Start();
}
void MovingPhotoPattern::HandleTouchEvent(TouchEventInfo& info)
{
if (currentPlayStatus_ == PlaybackStatus::ERROR) {
ResetMediaPlayer();
}
if (IsRefreshMovingPhotoReturn(isRefreshMovingPhotoPlaying_)) {
TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "HandleTouchEvent IsRefreshMovingPhotoReturn.");
return;
}
if (!isPrepared_ || isPlayByController_) {
return;
}
if (autoAndRepeatLevel_ == PlaybackMode::NONE && isEnableAnalyzer_ && isAnalyzerPlaying_) {
TAG_LOGW(AceLogTag::ACE_MOVING_PHOTO, "HandleTouchEvent isEnableAnalyzer_ return.");
return;
}
auto touchList = info.GetChangedTouches();
CHECK_NULL_VOID(!touchList.empty());
auto touchInfo = touchList.front();
auto touchType = touchInfo.GetTouchType();
isFastKeyUp_ = false;
if (touchType == TouchType::UP || touchType == TouchType::CANCEL) {
if (currentPlayStatus_ == PlaybackStatus::STARTED) {
PausePlayback();
} else if (currentPlayStatus_ == PlaybackStatus::PLAYBACK_COMPLETE) {
currentPlayStatus_ = PlaybackStatus::NONE;
StopAnimation();
} else {
isFastKeyUp_ = true;
}
}
}
void MovingPhotoPattern::UpdateImageNode()
{
if (startAnimationFlag_) {
needUpdateImageNode_ = true;
return;
}
auto host = GetHost();
CHECK_NULL_VOID(host);
auto movingPhoto = AceType::DynamicCast<MovingPhotoNode>(host);
CHECK_NULL_VOID(movingPhoto);
auto image = AceType::DynamicCast<FrameNode>(movingPhoto->GetImage());
CHECK_NULL_VOID(image);
UpdateImageHdrMode(image);
auto imagePattern = image->GetPattern<ImagePattern>();
CHECK_NULL_VOID(imagePattern);
imagePattern->SetOrientation(ImageRotateOrientation::AUTO);
TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "UpdateImageNode set HDR. %{public}d, format. %{public}d",
dynamicRangeMode_, movingPhotoFormat_);
auto layoutProperty = GetLayoutProperty<MovingPhotoLayoutProperty>();
CHECK_NULL_VOID(layoutProperty);
auto imageLayoutProperty = image->GetLayoutProperty<ImageLayoutProperty>();
CHECK_NULL_VOID(imageLayoutProperty);
if (!layoutProperty->HasImageSourceInfo()) {
TAG_LOGW(AceLogTag::ACE_MOVING_PHOTO, "image info is null.");
imageLayoutProperty->UpdateVisibility(VisibleType::INVISIBLE);
image->MarkModifyDone();
return;
}
auto imageSourceInfo = layoutProperty->GetImageSourceInfo().value();
auto imageFit = layoutProperty->GetObjectFitValue(ImageFit::COVER);
if (!imageSourceInfo.IsValid()) {
TAG_LOGW(AceLogTag::ACE_MOVING_PHOTO, "image info is invalid.");
imageLayoutProperty->UpdateVisibility(VisibleType::INVISIBLE);
image->MarkModifyDone();
return;
}
if (image) {
image->SetDraggable(false);
imageLayoutProperty->UpdateVisibility(VisibleType::VISIBLE);
imageLayoutProperty->UpdateImageSourceInfo(imageSourceInfo);
MovingPhotoFormatConvert(movingPhotoFormat_);
imagePattern->SetExternalDecodeFormat(imageFormat_);
imageLayoutProperty->UpdateImageFit(imageFit);
image->MarkModifyDone();
}
RegisterImageEvent(image);
}
void MovingPhotoPattern::UpdateTempImageNode(const ImageSourceInfo& imageSourceInfo)
{
if (startAnimationFlag_) {
needUpdateImageNode_ = true;
return;
}
auto image = GetTempNode();
CHECK_NULL_VOID(image);
UpdateImageHdrMode(image);
auto imagePattern = image->GetPattern<ImagePattern>();
CHECK_NULL_VOID(imagePattern);
imagePattern->SetOrientation(ImageRotateOrientation::AUTO);
TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "UpdateTempImageNode set HDR. %{public}d, format. %{public}d",
dynamicRangeMode_, movingPhotoFormat_);
auto layoutProperty = GetLayoutProperty<MovingPhotoLayoutProperty>();
CHECK_NULL_VOID(layoutProperty);
auto imageLayoutProperty = image->GetLayoutProperty<ImageLayoutProperty>();
CHECK_NULL_VOID(imageLayoutProperty);
if (!layoutProperty->HasImageSourceInfo()) {
TAG_LOGW(AceLogTag::ACE_MOVING_PHOTO, "UpdateTempImageNode imageInfo is null.");
imageLayoutProperty->UpdateVisibility(VisibleType::INVISIBLE);
image->MarkModifyDone();
return;
}
auto imageFit = layoutProperty->GetObjectFitValue(ImageFit::COVER);
if (!imageSourceInfo.IsValid()) {
TAG_LOGW(AceLogTag::ACE_MOVING_PHOTO, "UpdateTempImageNode imageInfo is invalid.");
imageLayoutProperty->UpdateVisibility(VisibleType::INVISIBLE);
image->MarkModifyDone();
return;
}
if (image) {
image->SetDraggable(false);
imageLayoutProperty->UpdateVisibility(VisibleType::VISIBLE);
imageLayoutProperty->UpdateImageSourceInfo(imageSourceInfo);
MovingPhotoFormatConvert(movingPhotoFormat_);
imagePattern->SetExternalDecodeFormat(imageFormat_);
imageLayoutProperty->UpdateImageFit(imageFit);
image->MarkModifyDone();
}
RegisterTransitionImageEvent(image);
}
void MovingPhotoPattern::UpdateImageHdrMode(const RefPtr<FrameNode>& imageNode)
{
DynamicRangeModeConvert(dynamicRangeMode_);
ACE_UPDATE_NODE_PAINT_PROPERTY(ImageRenderProperty, DynamicMode, dynamicRangeMode_, imageNode);
ACE_UPDATE_NODE_RENDER_CONTEXT(DynamicRangeMode, dynamicRangeMode_, imageNode);
if (dynamicRangeMode_ == DynamicRangeMode::STANDARD) {
ACE_RESET_NODE_PAINT_PROPERTY(ImageRenderProperty, DynamicMode, imageNode);
ACE_RESET_NODE_RENDER_CONTEXT(RenderContext, DynamicRangeMode, imageNode);
}
}
void MovingPhotoPattern::MovingPhotoFormatConvert(MovingPhotoFormat format)
{
TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "MovingPhotoFormatConvert1 %{public}d.", format);
switch (format) {
case MovingPhotoFormat::RGBA_8888:
imageFormat_ = PixelFormat::RGBA_8888;
break;
case MovingPhotoFormat::NV21:
imageFormat_ = PixelFormat::NV21;
break;
case MovingPhotoFormat::RGBA_1010102:
imageFormat_ = PixelFormat::RGBA_1010102;
break;
case MovingPhotoFormat::YCBCR_P010:
imageFormat_ = PixelFormat::YCBCR_P010;
break;
case MovingPhotoFormat::YCRCB_P010:
imageFormat_ = PixelFormat::YCRCB_P010;
break;
default:
imageFormat_ = PixelFormat::UNKNOWN;
break;
}
}
void MovingPhotoPattern::DynamicRangeModeConvert(DynamicRangeMode rangeMode)
{
switch (rangeMode) {
case DynamicRangeMode::HIGH:
dynamicRangeMode_ = DynamicRangeMode::HIGH;
break;
case DynamicRangeMode::CONSTRAINT:
dynamicRangeMode_ = DynamicRangeMode::CONSTRAINT;
break;
case DynamicRangeMode::STANDARD:
dynamicRangeMode_ = DynamicRangeMode::STANDARD;
break;
default:
dynamicRangeMode_ = DynamicRangeMode::HIGH;
break;
}
TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "DynamicRangeModeConvert %{public}d.", rangeMode);
}
void MovingPhotoPattern::RegisterImageEvent(const RefPtr<FrameNode>& imageNode)
{
TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "MovingPhoto RegisterImageEvent start.");
CHECK_NULL_VOID(imageNode);
auto imageHub = imageNode->GetEventHub<ImageEventHub>();
CHECK_NULL_VOID(imageHub);
auto imageCompleteEventCallback = [weak = WeakClaim(this)](const LoadImageSuccessEvent& info) {
auto pattern = weak.Upgrade();
CHECK_NULL_VOID(pattern);
pattern->HandleImageCompleteEvent(info);
};
imageHub->SetOnComplete(imageCompleteEventCallback);
auto imageErrorEventCallback = [weak = WeakClaim(this)](const LoadImageFailEvent& info) {
auto pattern = weak.Upgrade();
CHECK_NULL_VOID(pattern);
pattern->HandleImageErrorEvent(info);
};
imageHub->SetOnError(imageErrorEventCallback);
}
void MovingPhotoPattern::RegisterTransitionImageEvent(const RefPtr<FrameNode>& imageNode)
{
TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "MovingPhoto RegisterImageEvent Transition start.");
CHECK_NULL_VOID(imageNode);
auto imageHub = imageNode->GetEventHub<ImageEventHub>();
CHECK_NULL_VOID(imageHub);
auto imageCompleteEventCallback = [weak = WeakClaim(this)](const LoadImageSuccessEvent& info) {
auto pattern = weak.Upgrade();
CHECK_NULL_VOID(pattern);
pattern->HandleTransitionImageCompleteEvent(info);
};
imageHub->SetOnComplete(imageCompleteEventCallback);
auto imageErrorEventCallback = [weak = WeakClaim(this)](const LoadImageFailEvent& info) {
auto pattern = weak.Upgrade();
CHECK_NULL_VOID(pattern);
pattern->HandleImageErrorEvent(info);
};
imageHub->SetOnError(imageErrorEventCallback);
}
void MovingPhotoPattern::HandleImageCompleteEvent(const LoadImageSuccessEvent& info)
{
auto loadingStatus = info.GetLoadingStatus();
TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "HandleImageCompleteEvent start:%{public}d.", loadingStatus);
if (loadingStatus == IMAGE_DECODE_COMPLETE) {
FireMediaPlayerImageComplete();
}
}
void MovingPhotoPattern::HandleImageErrorEvent(const LoadImageFailEvent& info)
{
auto errorStatus = info.GetErrorInfo();
TAG_LOGE(AceLogTag::ACE_MOVING_PHOTO, "OnHandleImageErrorEventCallback Start.");
CHECK_NULL_VOID(errorStatus.errorMessage.c_str());
TAG_LOGE(AceLogTag::ACE_MOVING_PHOTO, "HandleImageErrorEvent errorCode:%{public}d. errorMessage:%{public}s.",
errorStatus.errorCode, errorStatus.errorMessage.c_str());
FireMediaPlayerImageError();
}
void MovingPhotoPattern::HandleTransitionImageCompleteEvent(const LoadImageSuccessEvent& info)
{
auto loadingStatus = info.GetLoadingStatus();
TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "HandleTransitionImageCompleteEvent start:%{public}d.", loadingStatus);
if (loadingStatus == IMAGE_DECODE_COMPLETE) {
FireMediaPlayerImageComplete();
if (notifyTransitionFlag_) {
TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "HandleTransitionImageCompleteEvent EightyToHundredAnimation.");
EightyToHundredAnimation();
}
}
}
void MovingPhotoPattern::UpdateVideoNode()
{
ContainerScope scope(instanceId_);
auto pipelineContext = PipelineContext::GetCurrentContext();
CHECK_NULL_VOID(pipelineContext);
auto uiTaskExecutor = SingleTaskExecutor::Make(pipelineContext->GetTaskExecutor(), TaskExecutor::TaskType::UI);
uiTaskExecutor.PostTask(
[weak = WeakClaim(this)]() {
auto movingPhotoPattern = weak.Upgrade();
CHECK_NULL_VOID(movingPhotoPattern);
ContainerScope scope(movingPhotoPattern->instanceId_);
movingPhotoPattern->PrepareMediaPlayer();
movingPhotoPattern->UpdateMediaPlayerSpeed();
movingPhotoPattern->UpdateMediaPlayerMuted();
},
"ArkUIMovingPhotoUpdateVideo");
}
void MovingPhotoPattern::PrepareMediaPlayer()
{
auto layoutProperty = GetLayoutProperty<MovingPhotoLayoutProperty>();
CHECK_NULL_VOID(layoutProperty);
if (!layoutProperty->HasMovingPhotoUri() || !layoutProperty->HasVideoSource()) {
TAG_LOGW(AceLogTag::ACE_MOVING_PHOTO, "MovingPhoto source is null.");
return;
}
if (layoutProperty->GetMovingPhotoUri().value() == uri_ &&
layoutProperty->GetVideoSource().value() == fd_.GetValue()) {
TAG_LOGW(AceLogTag::ACE_MOVING_PHOTO, "MediaPlayer source has not changed.");
return;
}
uri_ = layoutProperty->GetMovingPhotoUri().value();
fd_ = layoutProperty->GetVideoSource().value();
if (!mediaPlayer_) {
TAG_LOGW(AceLogTag::ACE_MOVING_PHOTO, "MediaPlayer is null.");
FireMediaPlayerError();
return;
}
if (!mediaPlayer_->IsMediaPlayerValid()) {
mediaPlayer_->CreateMediaPlayer();
}
if (!mediaPlayer_->IsMediaPlayerValid()) {
TAG_LOGW(AceLogTag::ACE_MOVING_PHOTO, "MediaPlayer is invalid.");
FireMediaPlayerError();
return;
}
ContainerScope scope(instanceId_);
auto context = PipelineContext::GetCurrentContext();
CHECK_NULL_VOID(context);
auto uiTaskExecutor = SingleTaskExecutor::Make(context->GetTaskExecutor(), TaskExecutor::TaskType::UI);
uiTaskExecutor.PostTask(
[weak = WeakClaim(this)] {
auto movingPhotoPattern = weak.Upgrade();
CHECK_NULL_VOID(movingPhotoPattern);
movingPhotoPattern->ResetMediaPlayer();
},
"ArkUIMovingPhotoPrepare");
}
void MovingPhotoPattern::ResetMediaPlayer()
{
CHECK_NULL_VOID(mediaPlayer_);
isPrepared_ = false;
isStopAnimation_ = false;
ContainerScope scope(instanceId_);
auto context = PipelineContext::GetCurrentContext();
CHECK_NULL_VOID(context);
if (isRefreshMovingPhoto_ && isUsedMediaPlayerStatusChanged_) {
TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "ArkUIMovingPhotoResetMediaPlayerAsync.");
auto bgTaskExecutor = SingleTaskExecutor::Make(context->GetTaskExecutor(), TaskExecutor::TaskType::BACKGROUND);
bgTaskExecutor.PostTask(
[weak = WeakClaim(RawPtr(mediaPlayer_)), fd = fd_] {
auto mediaPlayer = weak.Upgrade();
CHECK_NULL_VOID(mediaPlayer);
mediaPlayer->ResetMediaPlayer();
if (!mediaPlayer->SetSourceByFd(fd.GetValue())) {
TAG_LOGW(AceLogTag::ACE_MOVING_PHOTO, "set source for MediaPlayer Async failed.");
}
},
"ArkUIMovingPhotoResetMediaPlayerAsync");
} else {
mediaPlayer_->ResetMediaPlayer();
RegisterMediaPlayerEvent();
if (!mediaPlayer_->SetSourceByFd(fd_.GetValue())) {
TAG_LOGW(AceLogTag::ACE_MOVING_PHOTO, "set source for MediaPlayer failed.");
auto uiTaskExecutor = SingleTaskExecutor::Make(context->GetTaskExecutor(), TaskExecutor::TaskType::UI);
uiTaskExecutor.PostTask(
[weak = WeakClaim(this)] {
auto pattern = weak.Upgrade();
CHECK_NULL_VOID(pattern);
ContainerScope scope(pattern->instanceId_);
pattern->FireMediaPlayerError();
},
"ArkUIMovingPhotoResetMediaPlayer");
}
}
}
void MovingPhotoPattern::RegisterMediaPlayerEvent()
{
if (fd_.GetValue() == -1 || !mediaPlayer_) {
return;
}
ContainerScope scope(instanceId_);
auto context = PipelineContext::GetCurrentContext();
CHECK_NULL_VOID(context);
auto uiTaskExecutor = SingleTaskExecutor::Make(context->GetTaskExecutor(), TaskExecutor::TaskType::UI);
auto movingPhotoPattern = WeakClaim(this);
auto&& positionUpdatedEvent = [movingPhotoPattern, uiTaskExecutor](uint32_t currentPos) {
uiTaskExecutor.PostTask([movingPhotoPattern, currentPos] {
auto movingPhoto = movingPhotoPattern.Upgrade();
CHECK_NULL_VOID(movingPhoto);
ContainerScope scope(movingPhoto->instanceId_);
movingPhoto->OnPlayPositionChanged(currentPos);
}, "ArkUIMovingPhotoPositionChanged");
};
auto&& stateChangedEvent = [movingPhotoPattern, uiTaskExecutor](PlaybackStatus status) {
uiTaskExecutor.PostTask([movingPhotoPattern, status] {
auto movingPhoto = movingPhotoPattern.Upgrade();
CHECK_NULL_VOID(movingPhoto);
ContainerScope scope(movingPhoto->instanceId_);
movingPhoto->OnMediaPlayerStatusChanged(status);
}, "ArkUIMovingPhotoStatusChanged");
};
auto&& errorEvent = [movingPhotoPattern, uiTaskExecutor]() {
uiTaskExecutor.PostTask([movingPhotoPattern] {
auto movingPhoto = movingPhotoPattern.Upgrade();
CHECK_NULL_VOID(movingPhoto);
ContainerScope scope(movingPhoto->instanceId_);
movingPhoto->FireMediaPlayerError();
}, "ArkUIMovingPhotoOnError");
};
auto&& resolutionChangeEvent = [movingPhotoPattern, uiTaskExecutor]() {
uiTaskExecutor.PostTask([movingPhotoPattern] {
auto movingPhoto = movingPhotoPattern.Upgrade();
CHECK_NULL_VOID(movingPhoto);
ContainerScope scope(movingPhoto->instanceId_);
movingPhoto->OnResolutionChange();
}, "ArkUIMovingPhotoResolutionChanged");
};
auto&& startRenderFrameEvent = [movingPhotoPattern, uiTaskExecutor]() {
uiTaskExecutor.PostTask([movingPhotoPattern] {
auto movingPhoto = movingPhotoPattern.Upgrade();
CHECK_NULL_VOID(movingPhoto);
ContainerScope scope(movingPhoto->instanceId_);
movingPhoto->OnStartRenderFrame();
}, "ArkUIMovingPhotoStartRender");
};
mediaPlayer_->RegisterMediaPlayerEvent(
positionUpdatedEvent, stateChangedEvent, errorEvent, resolutionChangeEvent, startRenderFrameEvent);
}
void MovingPhotoPattern::PrepareSurface()
{
if (!mediaPlayer_ || renderSurface_->IsSurfaceValid()) {
return;
}
if (!SystemProperties::GetExtSurfaceEnabled()) {
renderSurface_->SetRenderContext(renderContextForMediaPlayer_);
}
renderSurface_->InitSurface();
mediaPlayer_->SetRenderSurface(renderSurface_);
if (mediaPlayer_->SetSurface() != 0) {
TAG_LOGW(AceLogTag::ACE_MOVING_PHOTO, "prepare MediaPlayer failed.");
}
}
void MovingPhotoPattern::UpdatePlayMode()
{
TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "movingphoto UpdatePlayMode.%{public}d", isChangePlayMode_);
if (isChangePlayMode_) {
if (historyAutoAndRepeatLevel_ == PlaybackMode::AUTO) {
SetAutoPlayPeriod(autoPlayPeriodStartTime_, autoPlayPeriodEndTime_);
}
MediaResetToPlay();
isChangePlayMode_ = false;
}
}
void MovingPhotoPattern::HandleImageAnalyzerMode()
{
TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "movingphoto HandleImageAnalyzerMode.");
if (isEnableAnalyzer_ && autoAndRepeatLevel_ == PlaybackMode::NONE) {
if (!imageAnalyzerManager_) {
EnableAnalyzer(isEnableAnalyzer_);
}
if (imageAnalyzerManager_ && !GetAnalyzerState()) {
StartImageAnalyzer();
}
}
if (!isEnableAnalyzer_ && IsSupportImageAnalyzer() && imageAnalyzerManager_) {
DestroyAnalyzerOverlay();
LongPressEventModify(true);
}
}
void MovingPhotoPattern::MediaResetToPlay()
{
autoAndRepeatLevel_ = historyAutoAndRepeatLevel_;
if (currentPlayStatus_ == PlaybackStatus::STOPPED) {
mediaPlayer_->PrepareAsync();
} else if (currentPlayStatus_ == PlaybackStatus::PLAYBACK_COMPLETE ||
currentPlayStatus_ == PlaybackStatus::PAUSED ||
currentPlayStatus_ == PlaybackStatus::PREPARED) {
SelectPlaybackMode(historyAutoAndRepeatLevel_);
}
}
void MovingPhotoPattern::FireMediaPlayerImageComplete()
{
auto eventHub = GetEventHub<MovingPhotoEventHub>();
CHECK_NULL_VOID(eventHub);
eventHub->FireCompleteEvent();
}
void MovingPhotoPattern::FireMediaPlayerImageError()
{
auto eventHub = GetEventHub<MovingPhotoEventHub>();
CHECK_NULL_VOID(eventHub);
eventHub->FireErrorEvent();
}
void MovingPhotoPattern::FireMediaPlayerStart()
{
auto eventHub = GetEventHub<MovingPhotoEventHub>();
CHECK_NULL_VOID(eventHub);
eventHub->FireStartEvent();
if (isFastKeyUp_) {
isFastKeyUp_ = false;
PausePlayback();
}
}
void MovingPhotoPattern::FireMediaPlayerStop()
{
auto eventHub = GetEventHub<MovingPhotoEventHub>();
CHECK_NULL_VOID(eventHub);
eventHub->FireStopEvent();
}
void MovingPhotoPattern::FireMediaPlayerPause()
{
auto eventHub = GetEventHub<MovingPhotoEventHub>();
CHECK_NULL_VOID(eventHub);
eventHub->FirePauseEvent();
}
void MovingPhotoPattern::FireMediaPlayerFinish()
{
auto eventHub = GetEventHub<MovingPhotoEventHub>();
CHECK_NULL_VOID(eventHub);
eventHub->FireFinishEvent();
}
void MovingPhotoPattern::FireMediaPlayerError()
{
auto eventHub = GetEventHub<MovingPhotoEventHub>();
CHECK_NULL_VOID(eventHub);
eventHub->FireErrorEvent();
}
void MovingPhotoPattern::FireMediaPlayerPrepared()
{
auto eventHub = GetEventHub<MovingPhotoEventHub>();
CHECK_NULL_VOID(eventHub);
eventHub->FirePreparedEvent();
}
void MovingPhotoPattern::OnResolutionChange()
{
if (!mediaPlayer_ || !mediaPlayer_->IsMediaPlayerValid()) {
TAG_LOGW(AceLogTag::ACE_MOVING_PHOTO, "MediaPlayer is null or invalid.");
return;
}
auto host = GetHost();
CHECK_NULL_VOID(host);
SizeF videoSize =
SizeF(static_cast<float>(mediaPlayer_->GetVideoWidth()), static_cast<float>(mediaPlayer_->GetVideoHeight()));
auto movingPhotoLayoutProperty = host->GetLayoutProperty<MovingPhotoLayoutProperty>();
CHECK_NULL_VOID(movingPhotoLayoutProperty);
movingPhotoLayoutProperty->UpdateVideoSize(videoSize);
host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
}
void MovingPhotoPattern::OnStartRenderFrame()
{
}
void MovingPhotoPattern::OnStartedStatusCallback()
{
TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "MediaPlayer OnStartedStatusCallback.");
ACE_FUNCTION_TRACE();
auto host = GetHost();
CHECK_NULL_VOID(host);
auto movingPhoto = AceType::DynamicCast<MovingPhotoNode>(host);
CHECK_NULL_VOID(movingPhoto);
auto image = AceType::DynamicCast<FrameNode>(movingPhoto->GetImage());
CHECK_NULL_VOID(image);
if (isStopAnimation_) {
TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "MediaPlayer OnStartedStatusCallback stop startAnimation.");
isStopAnimation_ = false;
return;
}
StartAnimation();
}
bool MovingPhotoPattern::OnDirtyLayoutWrapperSwap(const RefPtr<LayoutWrapper>& dirty, const DirtySwapConfig& config)
{
TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "OnDirtyLayoutWrapperSwap.");
if (config.skipMeasure || dirty->SkipMeasureContent()) {
return false;
}
auto geometryNode = dirty->GetGeometryNode();
CHECK_NULL_RETURN(geometryNode, false);
auto movingPhotoNodeSize = geometryNode->GetContentSize();
auto layoutProperty = GetLayoutProperty<MovingPhotoLayoutProperty>();
CHECK_NULL_RETURN(layoutProperty, false);
SizeF videoFrameSize = SetVideoFrameSize(movingPhotoNodeSize, layoutProperty);
if (xmageModeValue_ != ROUND_XMAGE_MODE_VALUE) {
SetRenderContextBoundsInXmage(movingPhotoNodeSize, videoFrameSize);
} else {
SetRenderContextBounds(movingPhotoNodeSize, videoFrameSize);
}
if (IsSupportImageAnalyzer() && isEnableAnalyzer_ && autoAndRepeatLevel_ == PlaybackMode::NONE) {
if (imageAnalyzerManager_ && !GetAnalyzerState()) {
StartImageAnalyzer();
} else {
UpdateAnalyzerUIConfig(geometryNode);
}
}
if (imageAnalyzerManager_ && !isEnableAnalyzer_) {
DestroyAnalyzerOverlay();
LongPressEventModify(true);
}
auto host = GetHost();
CHECK_NULL_RETURN(host, false);
host->MarkNeedSyncRenderTree();
auto movingPhoto = AceType::DynamicCast<MovingPhotoNode>(host);
CHECK_NULL_RETURN(movingPhoto, false);
int32_t childCount = movingPhoto->GetTotalChildCount();
CHECK_NULL_RETURN(childCount >= 1, false);
auto video = AceType::DynamicCast<FrameNode>(movingPhoto->GetVideo(childCount - 1));
CHECK_NULL_RETURN(video, false);
video->GetRenderContext()->SetClipToBounds(true);
if (currentPlayStatus_ != PlaybackStatus::STARTED) {
video->GetRenderContext()->UpdateOpacity(0.0);
}
return false;
}
void MovingPhotoPattern::SetRenderContextBounds(const SizeF& movingPhotoNodeSize, const SizeF& videoFrameSize)
{
auto layoutProperty = GetLayoutProperty<MovingPhotoLayoutProperty>();
CHECK_NULL_VOID(layoutProperty);
float xmageHeight = 0;
float ratio = 0;
if (layoutProperty->HasXmageHeight()) {
xmageHeight = layoutProperty->GetXmageHeight().value();
ratio = CalculateRatio(movingPhotoNodeSize);
}
if (columnRenderContext_) {
columnRenderContext_->SetBounds((movingPhotoNodeSize.Width() - videoFrameSize.Width()) / HALF,
(movingPhotoNodeSize.Height() - videoFrameSize.Height()) / HALF,
videoFrameSize.Width(), videoFrameSize.Height());
}
if (renderContextForMediaPlayer_) {
renderContextForMediaPlayer_->SetBounds((movingPhotoNodeSize.Width() - videoFrameSize.Width()) / HALF,
(movingPhotoNodeSize.Height() - videoFrameSize.Height()) / HALF,
videoFrameSize.Width(), videoFrameSize.Height());
}
}
void MovingPhotoPattern::SetRenderContextBoundsInXmage(
const SizeF& movingPhotoNodeSize, const SizeF& videoFrameSize)
{
auto layoutProperty = GetLayoutProperty<MovingPhotoLayoutProperty>();
CHECK_NULL_VOID(layoutProperty);
auto host = GetHost();
CHECK_NULL_VOID(host);
auto pattern = DynamicCast<MovingPhotoPattern>(host->GetPattern());
CHECK_NULL_VOID(pattern);
SizeF xmageOffset = SizeF(0, 0);
SizeF imageSize = SizeF(0, 0);
SizeF xmageOffsetRatio = SizeF(0, 0);
if (layoutProperty->HasXmageOffset()) {
xmageOffset = layoutProperty->GetXmageOffset().value();
}
if (layoutProperty->HasImageSize()) {
imageSize = layoutProperty->GetImageSize().value();
xmageOffsetRatio = pattern->CalculateXmageOffsetRatio(movingPhotoNodeSize);
}
if (columnRenderContext_) {
columnRenderContext_->SetBounds(0, 0, imageSize.Width() * xmageOffsetRatio.Width() + ROUND_XMAGE_PIXEL_GAP,
imageSize.Height() * xmageOffsetRatio.Height() + ROUND_XMAGE_PIXEL_GAP);
}
if (renderContextForMediaPlayer_) {
renderContextForMediaPlayer_->SetBounds(0, 0,
imageSize.Width() * xmageOffsetRatio.Width() + ROUND_XMAGE_PIXEL_GAP,
imageSize.Height() * xmageOffsetRatio.Height() + ROUND_XMAGE_PIXEL_GAP);
}
}
SizeF MovingPhotoPattern::SetVideoFrameSize(const SizeF& layoutSize,
const RefPtr<MovingPhotoLayoutProperty>& layoutProperty)
{
if (isXmageMode_) {
return MeasureModeContentLayout(layoutSize, layoutProperty);
} else {
if (autoAndRepeatLevel_ == PlaybackMode::REPEAT) {
return CalculateFitFill(layoutSize);
} else {
return MeasureContentLayout(layoutSize, layoutProperty);
}
}
}
SizeF MovingPhotoPattern::CalculateFitContain(const SizeF& rawSize, const SizeF& layoutSize)
{
if (NearZero(rawSize.Height()) || NearZero(rawSize.Width()) || NearZero(layoutSize.Height())) {
return layoutSize;
}
double sourceRatio = rawSize.Width() / rawSize.Height();
double layoutRatio = layoutSize.Width() / layoutSize.Height();
if (sourceRatio < layoutRatio) {
float ratio = layoutSize.Height() / rawSize.Height();
return { rawSize.Width() * ratio, layoutSize.Height() };
} else {
float ratio = layoutSize.Width() / rawSize.Width();
return { layoutSize.Width(), rawSize.Height() * ratio };
}
}
SizeF MovingPhotoPattern::CalculateFitFill(const SizeF& layoutSize)
{
return layoutSize;
}
SizeF MovingPhotoPattern::CalculateFitCover(const SizeF& rawSize, const SizeF& layoutSize)
{
if (NearZero(rawSize.Height()) || NearZero(rawSize.Width()) || NearZero(layoutSize.Height())) {
return layoutSize;
}
double sourceRatio = rawSize.Width() / rawSize.Height();
double layoutRatio = layoutSize.Width() / layoutSize.Height();
float ratio = 1.0;
if (sourceRatio < layoutRatio) {
ratio = static_cast<float>(layoutSize.Width() / rawSize.Width());
} else {
ratio = static_cast<float>(layoutSize.Height() / rawSize.Height());
}
return { rawSize.Width() * ratio, rawSize.Height() * ratio };
}
SizeF MovingPhotoPattern::CalculateFitNone(const SizeF& rawSize)
{
return rawSize;
}
SizeF MovingPhotoPattern::CalculateFitScaleDown(const SizeF& rawSize, const SizeF& layoutSize)
{
if ((rawSize.Width() <= layoutSize.Width()) && (rawSize.Height() <= layoutSize.Height())) {
return CalculateFitNone(rawSize);
} else {
return CalculateFitContain(rawSize, layoutSize);
}
}
SizeF MovingPhotoPattern::CalculateFitAuto(const SizeF& rawSize, const SizeF& layoutSize)
{
if (NearZero(rawSize.Width()) || NearZero(rawSize.Height())) {
return layoutSize;
}
if ((rawSize.Width() <= layoutSize.Width()) && (rawSize.Height() <= layoutSize.Height())) {
double widthRatio = layoutSize.Width() / rawSize.Width();
double heightRatio = layoutSize.Height() / rawSize.Height();
float ratio = static_cast<float>(std::min(widthRatio, heightRatio));
return { rawSize.Width() * ratio, rawSize.Height() * ratio };
} else if ((rawSize.Width() > layoutSize.Width()) && (rawSize.Height() <= layoutSize.Height())) {
return CalculateFitContain(rawSize, layoutSize);
} else {
return CalculateFitCover(rawSize, layoutSize);
}
}
SizeF MovingPhotoPattern::CalculateModeFitContain(const SizeF& rawSize, const SizeF& layoutSize)
{
if (NearZero(rawSize.Height()) || NearZero(rawSize.Width()) || NearZero(layoutSize.Height())) {
return layoutSize;
}
double sourceRatio = rawSize.Width() / rawSize.Height();
double layoutRatio = layoutSize.Width() / layoutSize.Height();
if (sourceRatio < layoutRatio) {
float ratio = layoutSize.Height() / rawSize.Height();
return { rawSize.Width() * ratio, layoutSize.Height() };
} else {
float ratio = layoutSize.Width() / rawSize.Width();
return { layoutSize.Width(), rawSize.Height() * ratio };
}
}
SizeF MovingPhotoPattern::CalculateModeFitFill(const SizeF& layoutSize)
{
return layoutSize;
}
SizeF MovingPhotoPattern::CalculateModeFitCover(const SizeF& rawSize, const SizeF& layoutSize)
{
if (NearZero(rawSize.Height()) || NearZero(rawSize.Width()) || NearZero(layoutSize.Height())) {
return layoutSize;
}
double sourceRatio = rawSize.Width() / rawSize.Height();
double layoutRatio = layoutSize.Width() / layoutSize.Height();
float ratio = 1.0;
if (sourceRatio < layoutRatio) {
ratio = static_cast<float>(layoutSize.Width() / rawSize.Width());
} else {
ratio = static_cast<float>(layoutSize.Height() / rawSize.Height());
}
return { rawSize.Width() * ratio, rawSize.Height() * ratio };
}
SizeF MovingPhotoPattern::CalculateModeFitNone(const SizeF& rawSize)
{
return rawSize;
}
SizeF MovingPhotoPattern::CalculateModeFitScaleDown(const SizeF& rawSize, const SizeF& layoutSize)
{
if ((rawSize.Width() <= layoutSize.Width()) && (rawSize.Height() <= layoutSize.Height())) {
return CalculateModeFitNone(rawSize);
} else {
return CalculateModeFitContain(rawSize, layoutSize);
}
}
SizeF MovingPhotoPattern::CalculateModeFitAuto(const SizeF& rawSize, const SizeF& layoutSize)
{
if (NearZero(rawSize.Width()) || NearZero(rawSize.Height())) {
return layoutSize;
}
if ((rawSize.Width() <= layoutSize.Width()) && (rawSize.Height() <= layoutSize.Height())) {
double widthRatio = layoutSize.Width() / rawSize.Width();
double heightRatio = layoutSize.Height() / rawSize.Height();
float ratio = static_cast<float>(std::min(widthRatio, heightRatio));
return { rawSize.Width() * ratio, rawSize.Height() * ratio };
} else if ((rawSize.Width() > layoutSize.Width()) && (rawSize.Height() <= layoutSize.Height())) {
return CalculateModeFitContain(rawSize, layoutSize);
} else {
return CalculateModeFitCover(rawSize, layoutSize);
}
}
float MovingPhotoPattern::CalculateRatio(SizeF layoutSize)
{
TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "movingPhoto calculateRatio layoutSize.%{public}f, %{public}f",
layoutSize.Width(), layoutSize.Height());
auto layoutProperty = GetLayoutProperty<MovingPhotoLayoutProperty>();
CHECK_NULL_RETURN(layoutProperty, 0);
if (!layoutProperty->HasImageSize()) {
TAG_LOGE(AceLogTag::ACE_MOVING_PHOTO, "movingPhoto imageSize is null.");
return 0;
}
SizeF rawSize = layoutProperty->GetImageSize().value();
TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "movingPhoto calculateRatio rawSize.%{public}f, %{public}f",
rawSize.Width(), rawSize.Height());
double sourceRatio = rawSize.Width() / rawSize.Height();
double layoutRatio = layoutSize.Width() / layoutSize.Height();
float ratio = 0;
if (sourceRatio > layoutRatio) {
ratio = static_cast<float>(layoutSize.Width() / rawSize.Width());
} else {
ratio = static_cast<float>(layoutSize.Height() / rawSize.Height());
}
return ratio;
}
SizeF MovingPhotoPattern::CalculateXmageOffsetRatio(SizeF layoutSize)
{
TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "movingPhoto CalculateXmageOffsetRatio layoutSize.%{public}f, %{public}f",
layoutSize.Width(), layoutSize.Height());
SizeF ret = SizeF(0, 0);
auto layoutProperty = GetLayoutProperty<MovingPhotoLayoutProperty>();
CHECK_NULL_RETURN(layoutProperty, ret);
if (!layoutProperty->HasXmageRawSize()) {
TAG_LOGE(AceLogTag::ACE_MOVING_PHOTO, "movingPhoto xmageRawSize is null.");
return ret;
}
if (!layoutProperty->HasXmageRawSize()) {
return ret;
}
SizeF rawSize = layoutProperty->GetXmageRawSize().value();
TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "movingPhoto CalculateXmageOffsetRatio rawSize.%{public}f, %{public}f",
rawSize.Width(), rawSize.Height());
if (rawSize.Width() == 0.0 || rawSize.Height() == 0.0) {
TAG_LOGE(AceLogTag::ACE_MOVING_PHOTO, "movingPhoto xmageRawSize is 0.");
return ret;
}
double widthRatio = layoutSize.Width() / rawSize.Width();
double heightRatio = layoutSize.Height() / rawSize.Height();
return SizeF(widthRatio, heightRatio);
}
SizeF MovingPhotoPattern::GetRawImageSize()
{
auto host = GetHost();
CHECK_NULL_RETURN(host, SizeF(-1, -1));
auto movingPhoto = AceType::DynamicCast<MovingPhotoNode>(host);
CHECK_NULL_RETURN(movingPhoto, SizeF(-1, -1));
auto image = AceType::DynamicCast<FrameNode>(movingPhoto->GetImage());
CHECK_NULL_RETURN(image, SizeF(-1, -1));
auto imagePattern = image->GetPattern<ImagePattern>();
CHECK_NULL_RETURN(image, SizeF(-1, -1));
return imagePattern->GetRawImageSize();
}
int32_t MovingPhotoPattern::GetImageFd() const
{
if (!isPlayWithMask_) {
TAG_LOGE(AceLogTag::ACE_MOVING_PHOTO, "movingPhoto GetImageFd.%{public}d", isPlayWithMask_);
return -1;
}
auto host = GetHost();
CHECK_NULL_RETURN(host, -1);
auto layoutProperty = GetLayoutProperty<MovingPhotoLayoutProperty>();
CHECK_NULL_RETURN(layoutProperty, -1);
auto pipeline = PipelineBase::GetCurrentContext();
CHECK_NULL_RETURN(pipeline, -1);
auto dataProvider = AceType::DynamicCast<DataProviderManagerStandard>(pipeline->GetDataProviderManager());
CHECK_NULL_RETURN(dataProvider, -1);
if (!layoutProperty->HasMovingPhotoUri()) {
TAG_LOGE(AceLogTag::ACE_MOVING_PHOTO, "movingPhoto GetImageFd uri is null");
return -1;
}
std::string uriValue = layoutProperty->GetMovingPhotoUri().value();
int32_t fd = dataProvider->GetDataProviderFile(uriValue, "r");
return fd;
}
void MovingPhotoPattern::SetXmagePosition()
{
TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "movingPhoto SetXmagePosition");
int32_t fd = GetImageFd();
CHECK_NULL_VOID(fd >= 0);
auto imageSrc = ImageSource::Create(fd);
close(fd);
CHECK_NULL_VOID(imageSrc);
auto host = GetHost();
CHECK_NULL_VOID(host);
auto imageLength = imageSrc->GetProperty(IMAGE_LENGTH);
auto imageWidth = imageSrc->GetProperty(IMAGE_WIDTH);
if (imageLength.empty() || imageWidth.empty() || imageLength == DEFAULT_EXIF_VALUE ||
imageWidth == DEFAULT_EXIF_VALUE) {
TAG_LOGE(AceLogTag::ACE_MOVING_PHOTO, "movingPhoto imageLength or imageWidth is null");
return;
}
float imageW = StringUtils::StringToFloat(imageWidth);
float imageL = StringUtils::StringToFloat(imageLength);
std::string modeValue = imageSrc->GetProperty(HW_MNOTE_XMAGE_MODE);
SizeF imageSize = SizeF(-1, -1);
if (!modeValue.empty() && modeValue != DEFAULT_EXIF_VALUE && !IsAllZeroPositionInXmage(imageSrc)) {
isXmageMode_ = true;
xmageModeValue_ = StringUtils::StringToInt(modeValue);
TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "movingPhoto xmageModeValue_ = %{public}d", xmageModeValue_);
if (xmageModeValue_ != ROUND_XMAGE_MODE_VALUE) {
UpdateXmageProperty(imageSrc, imageSize, imageW, imageL, host);
}
} else {
isXmageMode_ = false;
xmageModeValue_ = 0;
imageSize = SizeF(imageW, imageL);
}
ACE_UPDATE_NODE_LAYOUT_PROPERTY(MovingPhotoLayoutProperty, ImageSize, imageSize, host);
TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "movingPhoto imageSize imageW.%{public}f, imageL %{public}f",
imageSize.Width(), imageSize.Height());
}
bool MovingPhotoPattern::IsAllZeroPositionInXmage(const RefPtr<ImageSource>& imageSrc)
{
return imageSrc->GetProperty(HW_MNOTE_XMAGE_LEFT) == "0" &&
imageSrc->GetProperty(HW_MNOTE_XMAGE_TOP) == "0" &&
imageSrc->GetProperty(HW_MNOTE_XMAGE_RIGHT) == "0" &&
imageSrc->GetProperty(HW_MNOTE_XMAGE_BOTTOM) == "0";
}
void MovingPhotoPattern::UpdateXmageProperty(
RefPtr<ImageSource> imageSrc, SizeF& imageSize, float imageW, float imageL, RefPtr<FrameNode>& host)
{
std::string xmageLeft = imageSrc->GetProperty(HW_MNOTE_XMAGE_LEFT);
std::string xmageTop = imageSrc->GetProperty(HW_MNOTE_XMAGE_TOP);
std::string xmageRight = imageSrc->GetProperty(HW_MNOTE_XMAGE_RIGHT);
std::string xmageBottom = imageSrc->GetProperty(HW_MNOTE_XMAGE_BOTTOM);
if (xmageBottom.empty() || xmageBottom == DEFAULT_EXIF_VALUE) {
TAG_LOGE(AceLogTag::ACE_MOVING_PHOTO, "movingPhoto xmageBottom is null");
return;
}
float xLeft = StringUtils::StringToFloat(xmageLeft);
float xTop = StringUtils::StringToFloat(xmageTop);
float xRight = StringUtils::StringToFloat(xmageRight);
float xBottom = StringUtils::StringToFloat(xmageBottom);
imageSize = SizeF(xRight - xLeft, xBottom - xTop);
SizeF xmageOffset = SizeF(xLeft, xTop);
SizeF xmageRawSize = SizeF(imageW, imageL);
TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "movingPhoto Xmage(%{public}f, %{public}f, %{public}f, %{public}f)",
xLeft, xTop, xRight, xBottom);
ACE_UPDATE_NODE_LAYOUT_PROPERTY(MovingPhotoLayoutProperty, XmageOffset, xmageOffset, host);
ACE_UPDATE_NODE_LAYOUT_PROPERTY(MovingPhotoLayoutProperty, XmageRawSize, xmageRawSize, host);
}
SizeF MovingPhotoPattern::MeasureContentLayout(const SizeF& layoutSize,
const RefPtr<MovingPhotoLayoutProperty>& layoutProperty)
{
if (!layoutProperty || !layoutProperty->HasVideoSize()) {
return layoutSize;
}
auto rawImageSize = GetRawImageSize();
auto imageFit = layoutProperty->GetObjectFitValue(ImageFit::COVER);
SizeF contentSize = { 0.0, 0.0 };
switch (imageFit) {
case ImageFit::CONTAIN:
contentSize = CalculateFitContain(rawImageSize, layoutSize);
break;
case ImageFit::FILL:
contentSize = CalculateFitFill(layoutSize);
break;
case ImageFit::COVER:
contentSize = CalculateFitCover(rawImageSize, layoutSize);
break;
case ImageFit::NONE:
contentSize = CalculateFitNone(rawImageSize);
break;
case ImageFit::SCALE_DOWN:
contentSize = CalculateFitScaleDown(rawImageSize, layoutSize);
break;
default:
contentSize = CalculateFitAuto(rawImageSize, layoutSize);
}
TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "movingPhoto MeasureContentLayout.%{public}f, %{public}f",
contentSize.Width(), contentSize.Height());
return contentSize;
}
SizeF MovingPhotoPattern::MeasureModeContentLayout(const SizeF& layoutSize,
const RefPtr<MovingPhotoLayoutProperty>& layoutProperty)
{
if (!layoutProperty || !layoutProperty->HasVideoSize()) {
return layoutSize;
}
auto rawImageSize = GetRawImageSize();
auto imageFit = layoutProperty->GetObjectFitValue(ImageFit::COVER);
SizeF contentSize = { 0.0, 0.0 };
switch (imageFit) {
case ImageFit::CONTAIN:
contentSize = CalculateModeFitContain(rawImageSize, layoutSize);
break;
case ImageFit::FILL:
contentSize = CalculateModeFitFill(layoutSize);
break;
case ImageFit::COVER:
contentSize = CalculateModeFitCover(rawImageSize, layoutSize);
break;
case ImageFit::NONE:
contentSize = CalculateModeFitNone(rawImageSize);
break;
case ImageFit::SCALE_DOWN:
contentSize = CalculateModeFitScaleDown(rawImageSize, layoutSize);
break;
default:
contentSize = CalculateModeFitAuto(rawImageSize, layoutSize);
}
TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "movingPhoto MeasureModeContentLayout.%{public}f, %{public}f",
contentSize.Width(), contentSize.Height());
return contentSize;
}
void MovingPhotoPattern::OnMediaPlayerStatusChanged(PlaybackStatus status)
{
isUsedMediaPlayerStatusChanged_ = true;
currentPlayStatus_ = status;
switch (status) {
case PlaybackStatus::ERROR:
TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "Player current status is ERROR.");
FireMediaPlayerError();
break;
case PlaybackStatus::IDLE:
TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "Player current status is IDLE.");
break;
case PlaybackStatus::INITIALIZED:
TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "Player current status is INITIALIZED.");
OnMediaPlayerInitialized();
break;
case PlaybackStatus::PREPARED:
TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "Player current status is PREPARED.");
OnMediaPlayerPrepared();
break;
case PlaybackStatus::STARTED:
TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "Player current status is STARTED.");
OnStartedStatusCallback();
FireMediaPlayerStart();
break;
case PlaybackStatus::PAUSED:
TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "Player current status is PAUSED.");
FireMediaPlayerPause();
break;
case PlaybackStatus::STOPPED:
TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "Player current status is STOPPED.");
OnMediaPlayerStoped();
break;
case PlaybackStatus::PLAYBACK_COMPLETE:
TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "Player current status is PLAYBACK_COMPLETE.");
OnMediaPlayerCompletion();
break;
case PlaybackStatus::NONE:
TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "Player current status is NONE.");
break;
default:
TAG_LOGW(AceLogTag::ACE_MOVING_PHOTO, "Invalid player status.");
break;
}
}
void MovingPhotoPattern::OnMediaPlayerInitialized()
{
TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "MediaPlayer OnMediaPlayerInitialized.");
if (!isSetAutoPlayPeriod_ && autoAndRepeatLevel_ == PlaybackMode::AUTO) {
isSetAutoPlayPeriod_ = true;
SetAutoPlayPeriod(autoPlayPeriodStartTime_, autoPlayPeriodEndTime_);
}
isAutoChangePlayMode_ = false;
PrepareSurface();
if (cameraPostprocessingEnabled_) {
mediaPlayer_->EnableCameraPostprocessing();
}
if (mediaPlayer_->PrepareAsync() != PREPARE_RETURN) {
TAG_LOGW(AceLogTag::ACE_MOVING_PHOTO, "prepare MediaPlayer failed.");
}
}
void MovingPhotoPattern::OnMediaPlayerPrepared()
{
ContainerScope scope(instanceId_);
auto context = PipelineContext::GetCurrentContext();
CHECK_NULL_VOID(context);
if (!mediaPlayer_ || !mediaPlayer_->IsMediaPlayerValid()) {
TAG_LOGW(AceLogTag::ACE_MOVING_PHOTO, "MediaPlayer is null or invalid.");
return;
}
isPrepared_ = true;
Size videoSize = Size(mediaPlayer_->GetVideoWidth(), mediaPlayer_->GetVideoHeight());
auto host = GetHost();
CHECK_NULL_VOID(host);
auto videoLayoutProperty = host->GetLayoutProperty<MovingPhotoLayoutProperty>();
CHECK_NULL_VOID(videoLayoutProperty);
CHECK_NULL_VOID(mediaPlayer_);
videoLayoutProperty->UpdateVideoSize(
SizeF(static_cast<float>(videoSize.Width()), static_cast<float>(videoSize.Height())));
host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
mediaPlayer_->SetParameter(VIDEO_SCALE, 1);
UpdateMediaPlayerSpeed();
UpdateMediaPlayerMuted();
PreparedToPlay();
FireMediaPlayerPrepared();
}
void MovingPhotoPattern::OnMediaPlayerStoped()
{
isPlayByController_ = false;
FireMediaPlayerStop();
}
void MovingPhotoPattern::OnMediaPlayerCompletion()
{
if (!isRefreshMovingPhotoPlaying_) {
if (isPlayByController_ || autoAndRepeatLevel_ != PlaybackMode::NONE) {
isPlayByController_ = false;
StopAnimation();
}
}
isStopAnimation_ = false;
FireMediaPlayerFinish();
}
void MovingPhotoPattern::HideImageNode()
{
auto host = GetHost();
CHECK_NULL_VOID(host);
auto movingPhoto = AceType::DynamicCast<MovingPhotoNode>(host);
CHECK_NULL_VOID(movingPhoto);
auto image = AceType::DynamicCast<FrameNode>(movingPhoto->GetImage());
CHECK_NULL_VOID(image);
auto imageLayoutProperty = image->GetLayoutProperty<ImageLayoutProperty>();
CHECK_NULL_VOID(imageLayoutProperty);
imageLayoutProperty->UpdateVisibility(VisibleType::INVISIBLE);
image->MarkModifyDone();
}
void MovingPhotoPattern::PreparedToPlay()
{
TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "movingphoto PreparedToPlay.");
if (!isVisible_) {
return;
}
if (isRepeatChangePlayMode_ && historyAutoAndRepeatLevel_ == PlaybackMode::NONE &&
autoAndRepeatLevel_ == PlaybackMode::NONE) {
autoAndRepeatLevel_ = PlaybackMode::REPEAT;
historyAutoAndRepeatLevel_ = PlaybackMode::REPEAT;
}
if (historyAutoAndRepeatLevel_ != PlaybackMode::NONE &&
autoAndRepeatLevel_ == PlaybackMode::NONE) {
SelectPlaybackMode(historyAutoAndRepeatLevel_);
} else {
SelectPlaybackMode(autoAndRepeatLevel_);
}
isRepeatChangePlayMode_ = false;
}
void MovingPhotoPattern::SelectPlaybackMode(PlaybackMode mode)
{
if (mode == PlaybackMode::REPEAT) {
StartRepeatPlay();
} else if (mode == PlaybackMode::AUTO) {
StartAutoPlay();
}
}
void MovingPhotoPattern::StartPlayback()
{
if (currentPlayStatus_ == PlaybackStatus::STARTED || !isPrepared_) {
return;
}
if (IsRefreshMovingPhotoReturn(isRefreshMovingPhoto_)) {
TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "HandleTouchEvent IsRefreshMovingPhotoReturn.");
return;
}
if (currentPlayStatus_ == PlaybackStatus::STOPPED) {
mediaPlayer_->PrepareAsync();
}
isPlayByController_ = true;
isFastKeyUp_ = false;
if (isSetAutoPlayPeriod_ && (currentPlayStatus_ == PlaybackStatus::PLAYBACK_COMPLETE ||
currentPlayStatus_ == PlaybackStatus::PAUSED ||
currentPlayStatus_ == PlaybackStatus::PREPARED)) {
int32_t duration = DURATION_FLAG;
mediaPlayer_->GetDuration(duration);
TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "StartPlayback duration:%{public}d.",
duration);
SetAutoPlayPeriod(PERIOD_START, duration * US_CONVERT);
}
Start();
}
void MovingPhotoPattern::StartAnimation()
{
TAG_LOGD(AceLogTag::ACE_MOVING_PHOTO, "movingphoto StartAnimation start");
auto host = GetHost();
CHECK_NULL_VOID(host);
auto movingPhoto = AceType::DynamicCast<MovingPhotoNode>(host);
CHECK_NULL_VOID(movingPhoto);
int32_t childCount = movingPhoto->GetTotalChildCount();
CHECK_NULL_VOID(childCount >= 1);
auto image = AceType::DynamicCast<FrameNode>(movingPhoto->GetImage());
CHECK_NULL_VOID(image);
auto imageRsContext = image->GetRenderContext();
CHECK_NULL_VOID(imageRsContext);
auto video = AceType::DynamicCast<FrameNode>(movingPhoto->GetVideo(childCount - 1));
CHECK_NULL_VOID(video);
auto videoRsContext = video->GetRenderContext();
CHECK_NULL_VOID(videoRsContext);
if (historyAutoAndRepeatLevel_ == PlaybackMode::REPEAT) {
if (!isFirstRepeatPlay_) {
videoRsContext->UpdateOpacity(1.0);
return;
}
isFirstRepeatPlay_ = false;
}
videoRsContext->UpdateOpacity(0.0);
imageRsContext->UpdateTransformScale({NORMAL_SCALE, NORMAL_SCALE});
videoRsContext->UpdateTransformScale({NORMAL_SCALE, NORMAL_SCALE});
auto movingPhotoPattern = WeakClaim(this);
AnimationOption animationOption;
animationOption.SetDuration(ANIMATION_DURATION_400);
animationOption.SetCurve(Curves::FRICTION);
animationOption.SetOnFinishEvent([movingPhotoPattern]() {
auto movingPhoto = movingPhotoPattern.Upgrade();
CHECK_NULL_VOID(movingPhoto);
if (movingPhoto->currentPlayStatus_ == PlaybackStatus::PAUSED
|| movingPhoto->currentPlayStatus_ == PlaybackStatus::STOPPED
|| !movingPhoto->startAnimationFlag_) {
return;
}
});
startAnimationFlag_ = true;
AnimationUtils::Animate(animationOption,
[imageRsContext, videoRsContext, flag = autoAndRepeatLevel_, movingPhotoPattern]() {
videoRsContext->UpdateOpacity(1.0);
auto movingPhoto = movingPhotoPattern.Upgrade();
CHECK_NULL_VOID(movingPhoto);
movingPhoto->RsContextUpdateTransformScale(imageRsContext, videoRsContext, flag);
}, animationOption.GetOnFinishEvent());
}
void MovingPhotoPattern::RsContextUpdateTransformScale(const RefPtr<RenderContext>& imageRsContext,
const RefPtr<RenderContext>& videoRsContext, PlaybackMode playbackMode)
{
if (playbackMode == PlaybackMode::REPEAT || playbackMode == PlaybackMode::AUTO ||
isRefreshMovingPhoto_ || !isEnableTransition_) {
videoRsContext->UpdateTransformScale({NORMAL_SCALE, NORMAL_SCALE});
imageRsContext->UpdateTransformScale({NORMAL_SCALE, NORMAL_SCALE});
} else {
#if defined(PLAYER_FRAMEWORK_EXISTS)
float scale = isEnableTransition_ ? GetGlobalInfo() : ZOOM_IN_SCALE;
if (isXmageMode_) {
videoRsContext->UpdateTransformScale({scale, scale});
imageRsContext->UpdateTransformScale({NORMAL_SCALE, NORMAL_SCALE});
} else {
videoRsContext->UpdateTransformScale({scale, scale});
imageRsContext->UpdateTransformScale({scale, scale});
}
#else
if (isXmageMode_) {
videoRsContext->UpdateTransformScale({ZOOM_IN_SCALE, ZOOM_IN_SCALE});
imageRsContext->UpdateTransformScale({NORMAL_SCALE, NORMAL_SCALE});
} else {
videoRsContext->UpdateTransformScale({ZOOM_IN_SCALE, ZOOM_IN_SCALE});
imageRsContext->UpdateTransformScale({ZOOM_IN_SCALE, ZOOM_IN_SCALE});
}
#endif
}
}
void MovingPhotoPattern::StopPlayback()
{
TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "movingphoto StopPlayback");
isFastKeyUp_ = false;
isPlayByController_ = false;
Pause();
autoAndRepeatLevel_ = PlaybackMode::NONE;
if (historyAutoAndRepeatLevel_ != PlaybackMode::REPEAT) {
StopAnimation();
}
}
void MovingPhotoPattern::PausePlayback()
{
TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "movingphoto PausePlayback");
isFastKeyUp_ = false;
if (currentPlayStatus_ != PlaybackStatus::STARTED || !isPrepared_) {
return;
}
if (IsRefreshMovingPhotoReturn(isRefreshMovingPhotoPlaying_)) {
TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "HandleTouchEvent IsRefreshMovingPhotoReturn.");
return;
}
isPlayByController_ = false;
Pause();
StopAnimation();
}
void MovingPhotoPattern::PauseVideo()
{
isFastKeyUp_ = false;
if (currentPlayStatus_ != PlaybackStatus::STARTED || !isPrepared_) {
TAG_LOGE(AceLogTag::ACE_MOVING_PHOTO, "movingphoto Pause return.");
return;
}
if (isRefreshMovingPhotoPlaying_ && autoAndRepeatLevel_ == PlaybackMode::REPEAT) {
TAG_LOGE(AceLogTag::ACE_MOVING_PHOTO, "HandleTouchEvent IsRefreshMovingPhotoReturn.");
return;
}
TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "movingphoto Pause video.");
isStopAnimation_ = true;
Pause();
}
void MovingPhotoPattern::ResetVideo()
{
isFastKeyUp_ = false;
if (currentPlayStatus_ == PlaybackStatus::ERROR) {
ResetMediaPlayer();
return;
}
if (currentPlayStatus_ == PlaybackStatus::STOPPED) {
mediaPlayer_->PrepareAsync();
}
int32_t duration = DURATION_FLAG;
mediaPlayer_->GetDuration(duration);
autoPlayPeriodStartTime_ = PERIOD_START;
autoPlayPeriodEndTime_ = duration * US_CONVERT;
if (currentPlayStatus_ == PlaybackStatus::STARTED) {
Pause();
}
SetAutoPlayPeriod(autoPlayPeriodStartTime_, autoPlayPeriodEndTime_);
TAG_LOGE(AceLogTag::ACE_MOVING_PHOTO, "movingphoto reset video.");
historyAutoAndRepeatLevel_ = PlaybackMode::NONE;
autoAndRepeatLevel_ = PlaybackMode::NONE;
isSetAutoPlayPeriod_ = false;
StopAnimation();
}
void MovingPhotoPattern::RestartVideo()
{
isFastKeyUp_ = false;
if (!mediaPlayer_ || !mediaPlayer_->IsMediaPlayerValid()) {
TAG_LOGW(AceLogTag::ACE_MOVING_PHOTO, "MediaPlayer is null or invalid.");
return;
}
if (currentPlayStatus_ == PlaybackStatus::STOPPED) {
mediaPlayer_->PrepareAsync();
}
TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "movingphoto restart video.");
isPlayByController_ = true;
autoAndRepeatLevel_ = historyAutoAndRepeatLevel_;
ContainerScope scope(instanceId_);
auto context = PipelineContext::GetCurrentContext();
CHECK_NULL_VOID(context);
auto platformTask = SingleTaskExecutor::Make(context->GetTaskExecutor(), TaskExecutor::TaskType::BACKGROUND);
platformTask.PostTask(
[weak = WeakClaim(RawPtr(mediaPlayer_))] {
auto mediaPlayer = weak.Upgrade();
CHECK_NULL_VOID(mediaPlayer);
mediaPlayer->Play();
},
"ArkUIMovingPhotoUpdateMuted");
}
float MovingPhotoPattern::GetGlobalInfo()
{
float scale = ZOOM_IN_SCALE;
#if defined(PLAYER_FRAMEWORK_EXISTS)
if (!mediaPlayer_ || !mediaPlayer_->IsMediaPlayerValid()) {
TAG_LOGW(AceLogTag::ACE_MOVING_PHOTO, "MediaPlayer is null or invalid.");
return ZOOM_IN_SCALE;
}
std::shared_ptr<OHOS::Media::Meta> meta = std::make_shared<OHOS::Media::Meta>();
mediaPlayer_->GetGlobalInfo(meta);
if (meta && meta->GetData(SCALING_FACTOR, scale)) {
TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "movingphoto get scale: %{public}f", scale);
} else {
TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "movingphoto scale use default data");
}
#endif
return scale;
}
void MovingPhotoPattern::SetEnableTransition(bool enabled)
{
TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "movingphoto SetEnableTransition %{public}d.", enabled);
isEnableTransition_ = enabled;
}
bool MovingPhotoPattern::GetEnableTransition()
{
return isEnableTransition_;
}
bool MovingPhotoPattern::SetPlaybackPeriod(int64_t startTime, int64_t endTime)
{
TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "movingphoto setPlaybackPeriod.");
if (startTime < VIDEO_PLAYTIME_START_POSITION || startTime >= endTime) {
TAG_LOGW(AceLogTag::ACE_MOVING_PHOTO, "MeidaPlayer SetPlaybackPeriod error.");
return false;
}
if (!mediaPlayer_ || !mediaPlayer_->IsMediaPlayerValid() || currentPlayStatus_ == PlaybackStatus::STARTED) {
TAG_LOGW(AceLogTag::ACE_MOVING_PHOTO, "MediaPlayer is invalid or currentPlayStatus is STARTED.");
return false;
}
autoPlayPeriodStartTime_ = startTime;
autoPlayPeriodEndTime_ = endTime;
isSetAutoPlayPeriod_ = true;
mediaPlayer_->SetPlayRangeUsWithMode(startTime, endTime, SeekMode::SEEK_CLOSEST);
return true;
}
void MovingPhotoPattern::EnableAutoPlay(bool enabled)
{
TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "movingphoto enable AutoPlay : %{public}d.", enabled);
if (!enabled || autoAndRepeatLevel_ == PlaybackMode::REPEAT || !mediaPlayer_ ||
!mediaPlayer_->IsMediaPlayerValid()) {
return;
}
if (currentPlayStatus_ == PlaybackStatus::STARTED || !isPrepared_) {
TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "movingphoto play status is STARTED or isPrepared is :%{public}d",
isPrepared_);
return;
}
if (!isPlayByController_ &&
(currentPlayStatus_ == PlaybackStatus::PLAYBACK_COMPLETE || currentPlayStatus_ == PlaybackStatus::PAUSED)) {
TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "movingphoto set autoplay period.");
SetAutoPlayPeriod(autoPlayPeriodStartTime_, autoPlayPeriodEndTime_);
}
if (currentPlayStatus_ == PlaybackStatus::STOPPED) {
mediaPlayer_->PrepareAsync();
}
TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "movingphoto autoplay set success.");
isPlayByController_ = true;
isFastKeyUp_ = false;
Start();
}
void MovingPhotoPattern::RefreshMovingPhoto()
{
TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "movingphoto RefreshMovingPhoto start.");
if (uri_ == "") {
TAG_LOGW(AceLogTag::ACE_MOVING_PHOTO, "movingphoto RefreshMovingPhoto uri is null.");
return;
}
if (notifyTransitionFlag_) {
refreshTransitionFlag_ = true;
DetachTempImageFromFrameNode();
}
isRefreshMovingPhoto_ = true;
auto host = GetHost();
CHECK_NULL_VOID(host);
auto layoutProperty = GetLayoutProperty<MovingPhotoLayoutProperty>();
CHECK_NULL_VOID(layoutProperty);
auto pipeline = PipelineBase::GetCurrentContext();
CHECK_NULL_VOID(pipeline);
auto dataProvider = AceType::DynamicCast<DataProviderManagerStandard>(pipeline->GetDataProviderManager());
CHECK_NULL_VOID(dataProvider);
if (!layoutProperty->HasMovingPhotoUri() || !layoutProperty->HasVideoSource()) {
TAG_LOGW(AceLogTag::ACE_MOVING_PHOTO, "movingphoto source is null.");
return;
}
std::string imageSrc = dataProvider->GetMovingPhotoImageUri(uri_);
auto imageCache = pipeline->GetImageCache();
if (imageCache) {
ImageSourceInfo srcKey;
srcKey.SetSrc(imageSrc);
imageCache->ClearCacheImgObj(srcKey.GetKey());
}
imageSrc += "?date_modified = " + std::to_string(GetMicroTickCount());
ImageSourceInfo src;
handleImageError_ = false;
src.SetSrc(imageSrc);
ACE_UPDATE_NODE_LAYOUT_PROPERTY(MovingPhotoLayoutProperty, ImageSourceInfo, src, host);
UpdateImageNode();
fd_ = dataProvider->ReadMovingPhotoVideo(uri_);
ACE_UPDATE_NODE_LAYOUT_PROPERTY(MovingPhotoLayoutProperty, VideoSource, fd_.GetValue(), host);
isSetAutoPlayPeriod_ = false;
RefreshMovingPhotoSceneManager();
ResetMediaPlayer();
if (IsSupportImageAnalyzer() && isEnableAnalyzer_ && imageAnalyzerManager_) {
UpdateAnalyzerOverlay();
}
}
void MovingPhotoPattern::RefreshMovingPhotoSceneManager()
{
auto host = GetHost();
CHECK_NULL_VOID(host);
if (historyAutoAndRepeatLevel_ == PlaybackMode::REPEAT) {
autoAndRepeatLevel_ = PlaybackMode::NONE;
historyAutoAndRepeatLevel_ = PlaybackMode::NONE;
isRepeatChangePlayMode_ = true;
Pause();
auto movingPhoto = AceType::DynamicCast<MovingPhotoNode>(host);
CHECK_NULL_VOID(movingPhoto);
int32_t childCount = movingPhoto->GetTotalChildCount();
CHECK_NULL_VOID(childCount >= 1);
auto video = AceType::DynamicCast<FrameNode>(movingPhoto->GetVideo(childCount - 1));
CHECK_NULL_VOID(video);
video->GetRenderContext()->SetClipToBounds(true);
video->GetRenderContext()->UpdateOpacity(0.0);
} else if (historyAutoAndRepeatLevel_ == PlaybackMode::AUTO) {
autoAndRepeatLevel_ = PlaybackMode::AUTO;
isAutoChangePlayMode_ = true;
}
autoPlayPeriodStartTime_ = -1;
autoPlayPeriodEndTime_ = -1;
}
void MovingPhotoPattern::NotifyTransition()
{
TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "movingphoto NotifyTransition start.");
if (notifyTransitionFlag_) {
TAG_LOGE(AceLogTag::ACE_MOVING_PHOTO, "movingphoto notifyTransition started.");
return;
}
notifyTransitionFlag_ = true;
auto host = GetHost();
CHECK_NULL_VOID(host);
auto movingPhoto = AceType::DynamicCast<MovingPhotoNode>(host);
CHECK_NULL_VOID(movingPhoto);
auto image = AceType::DynamicCast<FrameNode>(movingPhoto->GetImage());
CHECK_NULL_VOID(image);
AddTempNode(image, host);
auto pipeline = PipelineBase::GetCurrentContext();
CHECK_NULL_VOID(pipeline);
auto dataProvider = AceType::DynamicCast<DataProviderManagerStandard>(pipeline->GetDataProviderManager());
CHECK_NULL_VOID(dataProvider);
std::string imageSrc = dataProvider->GetMovingPhotoImageUri(uri_);
auto imageCache = pipeline->GetImageCache();
if (imageCache) {
ImageSourceInfo srcKey;
srcKey.SetSrc(imageSrc);
imageCache->ClearCacheImgObj(srcKey.GetKey());
}
imageSrc += "?date_modified = " + std::to_string(GetMicroTickCount());
ImageSourceInfo src;
src.SetSrc(imageSrc);
UpdateTempImageNode(src);
}
void MovingPhotoPattern::EightyToHundredAnimation()
{
TAG_LOGD(AceLogTag::ACE_MOVING_PHOTO, "movingphoto EightyToHundredAnimation start.");
auto image = GetTempNode();
CHECK_NULL_VOID(image);
auto imageLayoutProperty = image->GetLayoutProperty<ImageLayoutProperty>();
CHECK_NULL_VOID(imageLayoutProperty);
auto imageRsContext = image->GetRenderContext();
CHECK_NULL_VOID(imageRsContext);
imageRsContext->UpdateOpacity(0);
image->MarkModifyDone();
auto movingPhotoPattern = WeakClaim(this);
AnimationOption option;
option.SetDuration(EIGHTY_TO_HUNDRED_TIME);
option.SetCurve(Curves::EASE);
option.SetOnFinishEvent([movingPhotoPattern]() {
TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "movingphoto EightyToHundredAnimation finish.");
auto movingPhoto = movingPhotoPattern.Upgrade();
CHECK_NULL_VOID(movingPhoto);
movingPhoto->notifyTransitionFlag_ = false;
if (!movingPhoto->refreshTransitionFlag_) {
movingPhoto->DetachFirstImageFromFrameNode();
}
movingPhoto->refreshTransitionFlag_ = false;
});
AnimationUtils::Animate(option, [imageRsContext]() {
imageRsContext->UpdateOpacity(1.0);
}, option.GetOnFinishEvent());
}
void MovingPhotoPattern::AddTempNode(const RefPtr<FrameNode>& imageNode,
const RefPtr<FrameNode>& movingPhotoNode)
{
CHECK_NULL_VOID(imageNode);
CHECK_NULL_VOID(movingPhotoNode);
std::optional<int32_t> tempImageId_ = ElementRegister::GetInstance()->MakeUniqueId();
CHECK_NULL_VOID(tempImageId_.has_value());
auto tempImageNode = FrameNode::GetOrCreateFrameNode(
V2::IMAGE_ETS_TAG, tempImageId_.value(), []() { return AceType::MakeRefPtr<ImagePattern>(); });
movingPhotoNode->AddChildAfter(tempImageNode, imageNode);
}
void MovingPhotoPattern::DetachFirstImageFromFrameNode()
{
TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "movingphoto DetachFirstImageFromFrameNode.");
auto host = GetHost();
CHECK_NULL_VOID(host);
auto movingPhoto = AceType::DynamicCast<MovingPhotoNode>(host);
CHECK_NULL_VOID(movingPhoto);
CHECK_NULL_VOID(movingPhoto->GetTotalChildCount() > NODE_COUNT);
auto image = AceType::DynamicCast<FrameNode>(movingPhoto->GetImage());
CHECK_NULL_VOID(image);
host->RemoveChild(image);
}
void MovingPhotoPattern::DetachTempImageFromFrameNode()
{
TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "movingphoto DetachTempImageFromFrameNode.");
auto host = GetHost();
CHECK_NULL_VOID(host);
auto image = GetTempNode();
CHECK_NULL_VOID(image);
host->RemoveChild(image);
}
RefPtr<FrameNode> MovingPhotoPattern::GetTempNode()
{
auto host = GetHost();
CHECK_NULL_RETURN(host, nullptr);
auto movingPhoto = AceType::DynamicCast<MovingPhotoNode>(host);
CHECK_NULL_RETURN(movingPhoto, nullptr);
CHECK_NULL_RETURN(movingPhoto->GetTotalChildCount() > NODE_COUNT, nullptr);
auto firstImage = AceType::DynamicCast<FrameNode>(movingPhoto->GetImage());
CHECK_NULL_RETURN(firstImage, nullptr);
auto imageIndex = movingPhoto->GetChildIndex(firstImage);
CHECK_NULL_RETURN(imageIndex < movingPhoto->GetTotalChildCount() - 1, nullptr);
auto image = AceType::DynamicCast<FrameNode>(movingPhoto->GetChildAtIndex(imageIndex + 1));
return image;
}
void MovingPhotoPattern::StopAnimation()
{
if (handleImageError_) {
return;
}
isStopAnimation_ = false;
startAnimationFlag_ = false;
if (historyAutoAndRepeatLevel_ == PlaybackMode::REPEAT) {
StopAnimationCallback();
return;
}
if (isRefreshMovingPhotoPlaying_) {
isRefreshMovingPhotoPlaying_ = false;
}
auto host = GetHost();
CHECK_NULL_VOID(host);
auto movingPhoto = AceType::DynamicCast<MovingPhotoNode>(host);
CHECK_NULL_VOID(movingPhoto);
int32_t childCount = movingPhoto->GetTotalChildCount();
CHECK_NULL_VOID(childCount >= 1);
auto image = AceType::DynamicCast<FrameNode>(movingPhoto->GetImage());
CHECK_NULL_VOID(image);
auto imageLayoutProperty = image->GetLayoutProperty<ImageLayoutProperty>();
CHECK_NULL_VOID(imageLayoutProperty);
auto imageRsContext = image->GetRenderContext();
CHECK_NULL_VOID(imageRsContext);
auto video = AceType::DynamicCast<FrameNode>(movingPhoto->GetVideo(childCount - 1));
CHECK_NULL_VOID(video);
auto videoRsContext = video->GetRenderContext();
CHECK_NULL_VOID(videoRsContext);
videoRsContext->UpdateOpacity(1.0);
RsContextUpdateTransformScale(imageRsContext, videoRsContext, autoAndRepeatLevel_);
image->MarkModifyDone();
video->MarkModifyDone();
auto movingPhotoPattern = WeakClaim(this);
AnimationOption option;
option.SetDuration(ANIMATION_DURATION_300);
option.SetCurve(Curves::FRICTION);
option.SetOnFinishEvent([movingPhotoPattern]() {
auto movingPhoto = movingPhotoPattern.Upgrade();
CHECK_NULL_VOID(movingPhoto);
movingPhoto->StopAnimationCallback();
});
AnimationUtils::Animate(option, [imageRsContext, videoRsContext]() {
videoRsContext->UpdateOpacity(0.0);
imageRsContext->UpdateTransformScale({NORMAL_SCALE, NORMAL_SCALE});
videoRsContext->UpdateTransformScale({NORMAL_SCALE, NORMAL_SCALE});
}, option.GetOnFinishEvent());
}
void MovingPhotoPattern::StopAnimationCallback()
{
if (autoPlayPeriodStartTime_ >= 0) {
Seek(static_cast<int32_t>(autoPlayPeriodStartTime_ / US_CONVERT));
} else {
Seek(0);
}
TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "StopAnimation OnFinishEvent:%{public}d.", autoAndRepeatLevel_);
if (needUpdateImageNode_) {
UpdateImageNode();
needUpdateImageNode_ = false;
}
if (autoAndRepeatLevel_ == PlaybackMode::REPEAT) {
StartRepeatPlay();
} else if (autoAndRepeatLevel_ == PlaybackMode::AUTO) {
autoAndRepeatLevel_ = PlaybackMode::NONE;
}
if (historyAutoAndRepeatLevel_ == PlaybackMode::AUTO) {
HandleImageAnalyzerMode();
}
}
void MovingPhotoPattern::AutoPlay(bool isAutoPlay)
{
TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "movingphoto AutoPlay: %{public}d.", isAutoPlay);
if (isAutoPlay) {
if (historyAutoAndRepeatLevel_ == PlaybackMode::AUTO) {
return;
}
isChangePlayMode_ = true;
if (autoAndRepeatLevel_ != PlaybackMode::REPEAT) {
historyAutoAndRepeatLevel_ = PlaybackMode::AUTO;
autoAndRepeatLevel_ = PlaybackMode::AUTO;
if (!isSetAutoPlayPeriod_ && (currentPlayStatus_ == PlaybackStatus::PLAYBACK_COMPLETE ||
currentPlayStatus_ == PlaybackStatus::PAUSED)) {
isSetAutoPlayPeriod_ = true;
SetAutoPlayPeriod(autoPlayPeriodStartTime_, autoPlayPeriodEndTime_);
}
}
}
}
void MovingPhotoPattern::StartAutoPlay()
{
TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "movingphoto StartAutoPlay in.");
isFastKeyUp_ = false;
if (!mediaPlayer_ || !mediaPlayer_->IsMediaPlayerValid()) {
return;
}
if (currentPlayStatus_ == PlaybackStatus::STOPPED) {
mediaPlayer_->PrepareAsync();
}
Start();
}
void MovingPhotoPattern::StartRepeatPlay()
{
TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "movingphoto StartRepeatPlay in.");
isFastKeyUp_ = false;
if (!mediaPlayer_ || !mediaPlayer_->IsMediaPlayerValid()) {
return;
}
if (currentPlayStatus_ == PlaybackStatus::STOPPED) {
mediaPlayer_->PrepareAsync();
}
if (!isFirstRepeatPlay_ && isSetAutoPlayPeriod_) {
int32_t duration = DURATION_FLAG;
mediaPlayer_->GetDuration(duration);
SetAutoPlayPeriod(PERIOD_START, duration * US_CONVERT);
}
Start();
}
void MovingPhotoPattern::RepeatPlay(bool isRepeatPlay)
{
TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "movingphoto RepeatPlay status: %{public}d.", isRepeatPlay);
if (isRepeatPlay && historyAutoAndRepeatLevel_ != PlaybackMode::REPEAT) {
isChangePlayMode_ = true;
isFirstRepeatPlay_ = true;
}
if (!isRepeatPlay && historyAutoAndRepeatLevel_ == PlaybackMode::REPEAT) {
isChangePlayMode_ = true;
autoAndRepeatLevel_ = PlaybackMode::NONE;
historyAutoAndRepeatLevel_ = PlaybackMode::NONE;
Pause();
StopAnimation();
}
if (isRepeatPlay) {
historyAutoAndRepeatLevel_ = PlaybackMode::REPEAT;
autoAndRepeatLevel_ = PlaybackMode::REPEAT;
}
}
FocusPattern MovingPhotoPattern::GetFocusPattern() const
{
return { FocusType::NODE, false };
}
void MovingPhotoPattern::AutoPlayPeriod(int64_t startTime, int64_t endTime)
{
TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "movingphoto AutoPlayPeriod: [%{public}lld, %{public}lld].",
static_cast<long long>(startTime), static_cast<long long>(endTime));
if (startTime >= VIDEO_PLAYTIME_START_POSITION && startTime < endTime) {
autoPlayPeriodStartTime_ = startTime;
autoPlayPeriodEndTime_ = endTime;
}
}
void MovingPhotoPattern::SetAutoPlayPeriod(int64_t startTime, int64_t endTime)
{
TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "movingphoto SetAutoPlayPeriod: [%{public}lld, %{public}lld].",
static_cast<long long>(startTime), static_cast<long long>(endTime));
if (startTime < VIDEO_PLAYTIME_START_POSITION || startTime >= endTime) {
TAG_LOGW(AceLogTag::ACE_MOVING_PHOTO, "MediaPlayer SetAutoPlayPeriod error.");
return;
}
if (!mediaPlayer_ || !mediaPlayer_->IsMediaPlayerValid()) {
TAG_LOGW(AceLogTag::ACE_MOVING_PHOTO, "MediaPlayer is null or invalid.");
return;
}
mediaPlayer_->SetPlayRangeUsWithMode(startTime, endTime, SeekMode::SEEK_CLOSEST);
}
void MovingPhotoPattern::HandleImageAnalyzerPlayCallBack()
{
TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "HandleImageAnalyzerPlayCallBack start.");
isFastKeyUp_ = false;
if (currentPlayStatus_ == PlaybackStatus::STARTED || !isPrepared_ || isPlayByController_) {
return;
}
if (IsRefreshMovingPhotoReturn(isRefreshMovingPhoto_)) {
TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "HandleTouchEvent IsRefreshMovingPhotoReturn.");
return;
}
if (!mediaPlayer_ || !mediaPlayer_->IsMediaPlayerValid()) {
TAG_LOGW(AceLogTag::ACE_MOVING_PHOTO, "MediaPlayer is null or invalid.");
FireMediaPlayerError();
return;
}
if (currentPlayStatus_ == PlaybackStatus::STOPPED) {
mediaPlayer_->PrepareAsync();
}
if (isSetAutoPlayPeriod_ && (currentPlayStatus_ == PlaybackStatus::PLAYBACK_COMPLETE ||
currentPlayStatus_ == PlaybackStatus::PAUSED)) {
int32_t duration = DURATION_FLAG;
mediaPlayer_->GetDuration(duration);
SetAutoPlayPeriod(PERIOD_START, duration * US_CONVERT);
}
Start();
}
void MovingPhotoPattern::Start()
{
if (handleImageError_) {
TAG_LOGE(AceLogTag::ACE_MOVING_PHOTO, "movingphoto HandleImageError %{public}d.", handleImageError_);
return;
}
TAG_LOGW(AceLogTag::ACE_MOVING_PHOTO, "movingphoto start play.");
if (!mediaPlayer_ || !mediaPlayer_->IsMediaPlayerValid()) {
TAG_LOGW(AceLogTag::ACE_MOVING_PHOTO, "MediaPlayer is null or invalid.");
return;
}
if (isRefreshMovingPhoto_) {
isRefreshMovingPhoto_ = false;
}
if (currentPlayStatus_ == PlaybackStatus::STOPPED) {
mediaPlayer_->PrepareAsync();
}
ContainerScope scope(instanceId_);
auto context = PipelineContext::GetCurrentContext();
CHECK_NULL_VOID(context);
if (cameraPostprocessingEnabled_) {
if (isGestureTriggeredLongPress_) {
mediaPlayer_->SetCameraPostprocessing(true);
isGestureTriggeredLongPress_ = false;
}
mediaPlayer_->SetCameraPostprocessing(false);
}
auto platformTask = SingleTaskExecutor::Make(context->GetTaskExecutor(), TaskExecutor::TaskType::BACKGROUND);
platformTask.PostTask(
[weak = WeakClaim(RawPtr(mediaPlayer_))] {
auto mediaPlayer = weak.Upgrade();
CHECK_NULL_VOID(mediaPlayer);
mediaPlayer->Play();
},
"ArkUIMovingPhotoStartPlay");
}
void MovingPhotoPattern::Pause()
{
if (!mediaPlayer_ || !mediaPlayer_->IsMediaPlayerValid()) {
TAG_LOGW(AceLogTag::ACE_MOVING_PHOTO, "MediaPlayer is null or invalid.");
return;
}
ContainerScope scope(instanceId_);
auto context = PipelineContext::GetCurrentContext();
CHECK_NULL_VOID(context);
auto platformTask = SingleTaskExecutor::Make(context->GetTaskExecutor(), TaskExecutor::TaskType::BACKGROUND);
platformTask.PostTask(
[weak = WeakClaim(RawPtr(mediaPlayer_))] {
auto mediaPlayer = weak.Upgrade();
CHECK_NULL_VOID(mediaPlayer);
mediaPlayer->Pause();
},
"ArkUIMovingPhotoPausePlay");
}
void MovingPhotoPattern::Stop()
{
if (!mediaPlayer_ || !mediaPlayer_->IsMediaPlayerValid()) {
TAG_LOGW(AceLogTag::ACE_MOVING_PHOTO, "MediaPlayer is null or invalid.");
return;
}
ContainerScope scope(instanceId_);
auto context = PipelineContext::GetCurrentContext();
CHECK_NULL_VOID(context);
auto platformTask = SingleTaskExecutor::Make(context->GetTaskExecutor(), TaskExecutor::TaskType::BACKGROUND);
platformTask.PostTask(
[weak = WeakClaim(RawPtr(mediaPlayer_))] {
auto mediaPlayer = weak.Upgrade();
CHECK_NULL_VOID(mediaPlayer);
mediaPlayer->Stop();
},
"ArkUIMovingPhotoStopPlay");
}
void MovingPhotoPattern::Seek(int32_t position)
{
if (!mediaPlayer_ || !mediaPlayer_->IsMediaPlayerValid()) {
TAG_LOGW(AceLogTag::ACE_MOVING_PHOTO, "MediaPlayer is null or invalid.");
return;
}
ContainerScope scope(instanceId_);
auto context = PipelineContext::GetCurrentContext();
CHECK_NULL_VOID(context);
auto platformTask = SingleTaskExecutor::Make(context->GetTaskExecutor(), TaskExecutor::TaskType::BACKGROUND);
platformTask.PostTask(
[weak = WeakClaim(RawPtr(mediaPlayer_)), pos = position] {
auto mediaPlayer = weak.Upgrade();
CHECK_NULL_VOID(mediaPlayer);
mediaPlayer->Seek(pos, SeekMode::SEEK_PREVIOUS_SYNC);
},
"ArkUIMovingPhotoSeek");
}
void MovingPhotoPattern::UpdateMediaPlayerSpeed()
{
if (!mediaPlayer_ || !mediaPlayer_->IsMediaPlayerValid()) {
TAG_LOGW(AceLogTag::ACE_MOVING_PHOTO, "MediaPlayer is null or invalid.");
return;
}
ContainerScope scope(instanceId_);
auto context = PipelineContext::GetCurrentContext();
CHECK_NULL_VOID(context);
auto platformTask = SingleTaskExecutor::Make(context->GetTaskExecutor(), TaskExecutor::TaskType::BACKGROUND);
platformTask.PostTask(
[weak = WeakClaim(RawPtr(mediaPlayer_))] {
auto mediaPlayer = weak.Upgrade();
CHECK_NULL_VOID(mediaPlayer);
mediaPlayer->SetPlaybackSpeed(static_cast<float>(NORMAL_PLAY_SPEED));
},
"ArkUIMovingPhotoUpdateSpeed");
}
void MovingPhotoPattern::UpdateMediaPlayerMuted()
{
if (!mediaPlayer_ || !mediaPlayer_->IsMediaPlayerValid()) {
TAG_LOGW(AceLogTag::ACE_MOVING_PHOTO, "MediaPlayer is null or invalid.");
return;
}
ContainerScope scope(instanceId_);
float volume = isMuted_ ? 0.0f : 1.0f;
auto context = PipelineContext::GetCurrentContext();
CHECK_NULL_VOID(context);
auto platformTask = SingleTaskExecutor::Make(context->GetTaskExecutor(), TaskExecutor::TaskType::BACKGROUND);
platformTask.PostTask(
[weak = WeakClaim(RawPtr(mediaPlayer_)), videoVolume = volume] {
auto mediaPlayer = weak.Upgrade();
CHECK_NULL_VOID(mediaPlayer);
mediaPlayer->SetVolume(videoVolume, videoVolume);
},
"ArkUIMovingPhotoUpdateMuted");
}
void MovingPhotoPattern::OnAreaChangedInner()
{
}
void MovingPhotoPattern::OnVisibleChange(bool isVisible)
{
CHECK_NULL_VOID(mediaPlayer_);
TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "OnVisibleChange status: %{public}d.", isVisible);
}
void MovingPhotoPattern::OnWindowHide()
{
if (historyAutoAndRepeatLevel_ == PlaybackMode::AUTO) {
PausePlayback();
} else if (historyAutoAndRepeatLevel_ == PlaybackMode::REPEAT) {
StopPlayback();
return;
}
auto host = GetHost();
CHECK_NULL_VOID(host);
auto movingPhoto = AceType::DynamicCast<MovingPhotoNode>(host);
CHECK_NULL_VOID(movingPhoto);
auto image = AceType::DynamicCast<FrameNode>(movingPhoto->GetImage());
CHECK_NULL_VOID(image);
auto imageLayoutProperty = image->GetLayoutProperty<ImageLayoutProperty>();
CHECK_NULL_VOID(imageLayoutProperty);
imageLayoutProperty->UpdateVisibility(VisibleType::VISIBLE);
auto rsContext = image->GetRenderContext();
CHECK_NULL_VOID(rsContext);
rsContext->UpdateOpacity(1.0);
image->MarkModifyDone();
}
void MovingPhotoPattern::OnWindowShow()
{
CHECK_NULL_VOID(mediaPlayer_);
if (autoAndRepeatLevel_ == PlaybackMode::REPEAT && currentPlayStatus_ == PlaybackStatus::STOPPED) {
mediaPlayer_->PrepareAsync();
}
}
void MovingPhotoPattern::AddWindowStateChangedCallback()
{
auto host = GetHost();
CHECK_NULL_VOID(host);
auto pipelineContext = PipelineContext::GetCurrentContext();
CHECK_NULL_VOID(pipelineContext);
pipelineContext->AddWindowStateChangedCallback(host->GetId());
}
void MovingPhotoPattern::RegisterVisibleAreaChange()
{
if (hasVisibleChangeRegistered_) {
return;
}
auto pipeline = PipelineContext::GetCurrentContextSafely();
CHECK_NULL_VOID(pipeline);
auto callback = [weak = WeakClaim(this)](bool visible, double ratio) {
auto pattern = weak.Upgrade();
CHECK_NULL_VOID(pattern);
pattern->isVisible_ = visible;
pattern->VisibleAreaCallback(visible);
};
auto host = GetHost();
CHECK_NULL_VOID(host);
std::vector<double> ratioList = {1.0};
pipeline->AddVisibleAreaChangeNode(host, ratioList, callback, false, true);
hasVisibleChangeRegistered_ = true;
}
void MovingPhotoPattern::VisibleAreaCallback(bool visible)
{
TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "movingphoto VisibleAreaCallback:%{public}d.", visible);
if (visible) {
if (historyAutoAndRepeatLevel_ == PlaybackMode::AUTO) {
isSetAutoPlayPeriod_ = true;
SetAutoPlayPeriod(autoPlayPeriodStartTime_, autoPlayPeriodEndTime_);
}
MediaResetToPlay();
} else {
if (historyAutoAndRepeatLevel_ == PlaybackMode::AUTO) {
PausePlayback();
} else if (historyAutoAndRepeatLevel_ == PlaybackMode::REPEAT) {
StopPlayback();
}
if (isRefreshMovingPhoto_) {
isSetAutoPlayPeriod_ = false;
ResetMediaPlayer();
}
}
}
void MovingPhotoPattern::EnableAnalyzer(bool enabled)
{
TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "movingphoto EnableAnalyzer:%{public}d.", enabled);
isEnableAnalyzer_ = enabled;
if (!isEnableAnalyzer_) {
DestroyAnalyzerOverlay();
LongPressEventModify(true);
return;
}
CHECK_NULL_VOID(!imageAnalyzerManager_);
auto host = GetHost();
CHECK_NULL_VOID(host);
imageAnalyzerManager_ = std::make_shared<ImageAnalyzerManager>(host, ImageAnalyzerHolder::MOVINGPHOTO);
}
void MovingPhotoPattern::SetImageAIOptions(void* options)
{
if (!imageAnalyzerManager_) {
imageAnalyzerManager_ = std::make_shared<ImageAnalyzerManager>(GetHost(), ImageAnalyzerHolder::MOVINGPHOTO);
}
CHECK_NULL_VOID(imageAnalyzerManager_);
imageAnalyzerManager_->SetImageAIOptions(options);
}
bool MovingPhotoPattern::IsSupportImageAnalyzer()
{
auto host = GetHost();
CHECK_NULL_RETURN(host, false);
auto layoutProperty = host->GetLayoutProperty<MovingPhotoLayoutProperty>();
CHECK_NULL_RETURN(layoutProperty, false);
CHECK_NULL_RETURN(imageAnalyzerManager_, false);
return imageAnalyzerManager_->IsSupportImageAnalyzerFeature();
}
bool MovingPhotoPattern::ShouldUpdateImageAnalyzer()
{
auto layoutProperty = GetLayoutProperty<MovingPhotoLayoutProperty>();
CHECK_NULL_RETURN(layoutProperty, false);
const auto& constraint = layoutProperty->GetCalcLayoutConstraint();
if (!constraint || !constraint->selfIdealSize.has_value() || !constraint->selfIdealSize->IsValid()) {
return false;
}
auto selfIdealSize = constraint->selfIdealSize;
if (!selfIdealSize->PercentWidth() && !selfIdealSize->PercentHeight()) {
return false;
}
auto imageFit = layoutProperty->GetObjectFit().value_or(ImageFit::COVER);
if (imageFit != ImageFit::COVER && imageFit != ImageFit::NONE) {
return false;
}
return true;
}
void MovingPhotoPattern::StartImageAnalyzer()
{
if (!IsSupportImageAnalyzer() || !imageAnalyzerManager_) {
return;
}
if (imageAnalyzerManager_->IsOverlayCreated()) {
DestroyAnalyzerOverlay();
LongPressEventModify(true);
}
ContainerScope scope(instanceId_);
auto host = GetHost();
CHECK_NULL_VOID(host);
auto context = host->GetContext();
CHECK_NULL_VOID(context);
auto uiTaskExecutor = SingleTaskExecutor::Make(context->GetTaskExecutor(), TaskExecutor::TaskType::UI);
uiTaskExecutor.PostDelayedTask([weak = WeakClaim(this)] {
auto pattern = weak.Upgrade();
CHECK_NULL_VOID(pattern);
pattern->CreateAnalyzerOverlay();
}, ANALYZER_DELAY_TIME, "ArkUIMovingPhotoCreateAnalyzerOverlay");
LongPressEventModify(false);
}
void MovingPhotoPattern::CreateAnalyzerOverlay()
{
CHECK_NULL_VOID(imageAnalyzerManager_);
if (imageAnalyzerManager_->IsOverlayCreated()) {
return;
}
GetPixelMap();
int64_t coverPosition = GetUriCoverPosition();
auto onCanPlay = [weak = AceType::WeakClaim(this)](bool canPlay) {
auto pattern = weak.Upgrade();
CHECK_NULL_VOID(pattern);
pattern->HandleAnalyzerPlayEvent(canPlay);
};
auto host = GetHost();
CHECK_NULL_VOID(host);
auto geometryNode = host->GetGeometryNode();
CHECK_NULL_VOID(geometryNode);
auto movingPhotoNodeSize = geometryNode->GetContentSize();
MovingPhotoAnalyzerInfo info = {uri_, coverPosition,
movingPhotoNodeSize.Width(),
movingPhotoNodeSize.Height()};
imageAnalyzerManager_->SetOnCanPlayCallback(std::move(onCanPlay));
imageAnalyzerManager_->CreateMovingPhotoAnalyzerOverlay(pixelMap_, info);
}
void MovingPhotoPattern::StartUpdateImageAnalyzer()
{
CHECK_NULL_VOID(imageAnalyzerManager_);
if (!imageAnalyzerManager_->IsOverlayCreated()) {
return;
}
UpdateOverlayVisibility(VisibleType::GONE);
ContainerScope scope(instanceId_);
auto host = GetHost();
CHECK_NULL_VOID(host);
auto context = host->GetContext();
CHECK_NULL_VOID(context);
auto uiTaskExecutor = SingleTaskExecutor::Make(context->GetTaskExecutor(), TaskExecutor::TaskType::UI);
uiTaskExecutor.PostDelayedTask([weak = WeakClaim(this)] {
auto pattern = weak.Upgrade();
CHECK_NULL_VOID(pattern);
if (!pattern->isContentSizeChanged_) {
return;
}
pattern->UpdateAnalyzerOverlay();
pattern->isContentSizeChanged_ = false;
}, ANALYZER_CAPTURE_DELAY_TIME, "ArkUIMovingPhotoUpdateAnalyzerOverlay");
isContentSizeChanged_ = true;
}
void MovingPhotoPattern::UpdateAnalyzerOverlay()
{
CHECK_NULL_VOID(imageAnalyzerManager_);
if (!IsSupportImageAnalyzer() || !imageAnalyzerManager_->IsOverlayCreated()) {
return;
}
GetPixelMap();
int64_t coverPosition = GetUriCoverPosition();
UpdateOverlayVisibility(VisibleType::VISIBLE);
auto host = GetHost();
CHECK_NULL_VOID(host);
auto geometryNode = host->GetGeometryNode();
CHECK_NULL_VOID(geometryNode);
auto movingPhotoNodeSize = geometryNode->GetContentSize();
MovingPhotoAnalyzerInfo info = {uri_, coverPosition,
movingPhotoNodeSize.Width(),
movingPhotoNodeSize.Height()};
imageAnalyzerManager_->UpdateMovingPhotoAnalyzerOverlay(pixelMap_, info);
}
void MovingPhotoPattern::UpdateAnalyzerUIConfig(const RefPtr<NG::GeometryNode>& geometryNode)
{
auto movingPhotoNodeSize = geometryNode->GetContentSize();
auto layoutProperty = GetLayoutProperty<MovingPhotoLayoutProperty>();
CHECK_NULL_VOID(layoutProperty);
auto videoFrameSize = MeasureContentLayout(movingPhotoNodeSize, layoutProperty);
Rect tmpRect;
auto padding = layoutProperty->CreatePaddingAndBorder();
auto imageFit = layoutProperty->GetObjectFitValue(ImageFit::COVER);
if (imageFit == ImageFit::COVER || imageFit == ImageFit::NONE) {
tmpRect = Rect(padding.left.value_or(0), padding.top.value_or(0),
movingPhotoNodeSize.Width(), movingPhotoNodeSize.Height());
} else {
tmpRect = Rect(
(movingPhotoNodeSize.Width() - videoFrameSize.Width()) / AVERAGE_VALUE + padding.left.value_or(0),
(movingPhotoNodeSize.Height() - videoFrameSize.Height()) / AVERAGE_VALUE + padding.top.value_or(0),
videoFrameSize.Width(), videoFrameSize.Height());
}
contentRect_ = tmpRect;
if (IsSupportImageAnalyzer()) {
auto layoutProperty = GetLayoutProperty<MovingPhotoLayoutProperty>();
CHECK_NULL_VOID(layoutProperty);
auto padding = layoutProperty->CreatePaddingAndBorder();
OffsetF contentOffset = { contentRect_.Left() - padding.left.value_or(0),
contentRect_.Top() - padding.top.value_or(0) };
PixelMapInfo info = { contentRect_.GetSize().Width(), contentRect_.GetSize().Height(),
{ contentOffset.GetX(), contentOffset.GetY() } };
CHECK_NULL_VOID(imageAnalyzerManager_);
imageAnalyzerManager_->UpdateAnalyzerUIConfig(geometryNode, info);
}
}
void MovingPhotoPattern::DestroyAnalyzerOverlay()
{
TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "movingphoto DestroyAnalyzerOverlay");
CHECK_NULL_VOID(imageAnalyzerManager_);
imageAnalyzerManager_->DestroyAnalyzerOverlay();
}
bool MovingPhotoPattern::GetAnalyzerState()
{
CHECK_NULL_RETURN(imageAnalyzerManager_, false);
return imageAnalyzerManager_->IsOverlayCreated();
}
void MovingPhotoPattern::UpdateOverlayVisibility(VisibleType type)
{
auto host = GetHost();
CHECK_NULL_VOID(host);
auto overlayNode = host->GetOverlayNode();
CHECK_NULL_VOID(overlayNode);
auto prop = overlayNode->GetLayoutProperty();
CHECK_NULL_VOID(prop);
prop->UpdateVisibility(type);
}
void MovingPhotoPattern::GetPixelMap()
{
auto layoutProperty = GetLayoutProperty<MovingPhotoLayoutProperty>();
CHECK_NULL_VOID(layoutProperty);
if (!layoutProperty->HasMovingPhotoUri() || !layoutProperty->HasVideoSource()) {
TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "GetPixelMap MovingPhoto source is null.");
return;
}
auto pipeline = PipelineBase::GetCurrentContext();
CHECK_NULL_VOID(pipeline);
auto dataProvider = AceType::DynamicCast<DataProviderManagerStandard>(pipeline->GetDataProviderManager());
CHECK_NULL_VOID(dataProvider);
std::string imageSrc = dataProvider->GetMovingPhotoImagePath(uri_);
std::string thumbnailUrl = uri_ + THUMBNAIL_MEDIUM_JOINT + imageSrc;
void* pixelMapMediauniquePtr = dataProvider->GetDataProviderThumbnailResFromUri(thumbnailUrl);
CHECK_NULL_VOID(pixelMapMediauniquePtr);
auto pixelMap = PixelMap::CreatePixelMapFromDataAbility(pixelMapMediauniquePtr);
CHECK_NULL_VOID(pixelMap);
pixelMap_ = pixelMap;
}
int64_t MovingPhotoPattern::GetUriCoverPosition()
{
auto pipeline = PipelineBase::GetCurrentContext();
CHECK_NULL_RETURN(pipeline, -1);
auto dataProvider = AceType::DynamicCast<DataProviderManagerStandard>(pipeline->GetDataProviderManager());
CHECK_NULL_RETURN(dataProvider, -1);
std::vector<std::string> columns = {COVER_POSITION};
auto result = dataProvider->GetMovingPhotoCoverPosition(IMAGE_URI, uri_, columns);
return result;
}
void MovingPhotoPattern::HandleAnalyzerPlayEvent(bool canPlay)
{
TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "MovingPhoto HandleAnalyzerPlayEvent:%{public}d", canPlay);
if (isAnalyzerPlaying_ == canPlay || isPlayByController_) {
return;
}
if (isAnalyzerPlaying_ && !canPlay) {
Pause();
StopAnimation();
}
isAnalyzerPlaying_ = canPlay;
if (canPlay) {
if (isRefreshMovingPhoto_) {
isRefreshMovingPhotoPlaying_ = true;
}
HandleImageAnalyzerPlayCallBack();
}
}
bool MovingPhotoPattern::IsRefreshMovingPhotoReturn(bool status)
{
if (status) {
if (autoAndRepeatLevel_ == PlaybackMode::REPEAT) {
TAG_LOGW(AceLogTag::ACE_MOVING_PHOTO, "IsRefreshMovingPhotoReturn:%{public}d.", status);
return true;
}
} else {
if (autoAndRepeatLevel_ != PlaybackMode::NONE && !isStopAnimation_) {
TAG_LOGW(AceLogTag::ACE_MOVING_PHOTO, "IsRefreshMovingPhotoReturn not:%{public}d.", status);
return true;
}
}
return false;
}
void MovingPhotoPattern::SetHdrBrightness(float hdrBrightness)
{
TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "SetHdrBrightness:%{public}f.", hdrBrightness);
auto host = GetHost();
CHECK_NULL_VOID(host);
auto movingPhotoNode = AceType::DynamicCast<MovingPhotoNode>(host);
CHECK_NULL_VOID(movingPhotoNode);
auto imageNode = AceType::DynamicCast<FrameNode>(movingPhotoNode->GetImage());
CHECK_NULL_VOID(imageNode);
auto imageRenderContext = imageNode->GetRenderContext();
CHECK_NULL_VOID(imageRenderContext);
imageRenderContext->SetImageHDRBrightness(hdrBrightness);
imageRenderContext->SetImageHDRPresent(true);
ACE_UPDATE_NODE_PAINT_PROPERTY(ImageRenderProperty, HdrBrightness, hdrBrightness, imageNode);
hdrBrightness_ = hdrBrightness;
}
MovingPhotoPattern::~MovingPhotoPattern()
{
if (IsSupportImageAnalyzer()) {
TAG_LOGI(AceLogTag::ACE_MOVING_PHOTO, "~MovingPhotoPattern DestroyAnalyzerOverlay.");
DestroyAnalyzerOverlay();
}
}
void MovingPhotoPattern::SetMovingPhotoController(const RefPtr<MovingPhotoController>& movingPhotoController)
{
if (controller_) {
return;
}
CHECK_NULL_VOID(movingPhotoController);
controller_ = movingPhotoController;
ContainerScope scope(instanceId_);
auto context = PipelineContext::GetCurrentContext();
CHECK_NULL_VOID(context);
auto uiTaskExecutor = SingleTaskExecutor::Make(context->GetTaskExecutor(), TaskExecutor::TaskType::UI);
SetStartPlaybackImpl(uiTaskExecutor);
SetStopPlaybackImpl(uiTaskExecutor);
SetRefreshMovingPhotoImpl(uiTaskExecutor);
SetPauseImpl(uiTaskExecutor);
SetResetImpl(uiTaskExecutor);
SetRestartImpl(uiTaskExecutor);
SetEnableTransitionImpl(uiTaskExecutor);
SetPlaybackPeriodImpl(uiTaskExecutor);
SetEnableAutoPlayImpl(uiTaskExecutor);
RegisterVisibleAreaChange();
}
RefPtr<MovingPhotoController> MovingPhotoPattern::GetMovingPhotoController()
{
return controller_;
}
}