X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=dali-toolkit%2Finternal%2Fvisuals%2Fanimated-vector-image%2Fvector-animation-task.cpp;h=a202747e3404b47ce97a711c0fc822df988b12c1;hb=6da98d4f526029d51c8404964dd954afe9752401;hp=c229a99c9c4e7c0c1f7eed3a8d27a521d22bdcd9;hpb=c052b6678e2c6d8a65545dbbe4531ea7057c1999;p=platform%2Fcore%2Fuifw%2Fdali-toolkit.git diff --git a/dali-toolkit/internal/visuals/animated-vector-image/vector-animation-task.cpp b/dali-toolkit/internal/visuals/animated-vector-image/vector-animation-task.cpp index c229a99..a202747 100644 --- a/dali-toolkit/internal/visuals/animated-vector-image/vector-animation-task.cpp +++ b/dali-toolkit/internal/visuals/animated-vector-image/vector-animation-task.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Samsung Electronics Co., Ltd. + * Copyright (c) 2022 Samsung Electronics Co., Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -37,7 +37,7 @@ namespace Internal namespace { constexpr auto LOOP_FOREVER = -1; -constexpr auto NANOSECONDS_PER_SECOND(1e+9); +constexpr auto MICROSECONDS_PER_SECOND(1e+6); #if defined(DEBUG_ENABLED) Debug::Filter* gVectorAnimationLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_VECTOR_ANIMATION"); @@ -45,23 +45,26 @@ Debug::Filter* gVectorAnimationLogFilter = Debug::Filter::New(Debug::NoLogging, } // unnamed namespace -VectorAnimationTask::VectorAnimationTask(VisualFactoryCache& factoryCache, const std::string& url) -: mUrl(url), - mVectorRenderer(), +VectorAnimationTask::VectorAnimationTask(VisualFactoryCache& factoryCache) +: mUrl(), + mVectorRenderer(VectorAnimationRenderer::New()), mAnimationData(), mVectorAnimationThread(factoryCache.GetVectorAnimationManager().GetVectorAnimationThread()), mConditionalWait(), + mResourceReadySignal(), mAnimationFinishedTrigger(), + mLoadCompletedTrigger(new EventThreadCallback(MakeCallback(this, &VectorAnimationTask::OnLoadCompleted))), mPlayState(PlayState::STOPPED), mStopBehavior(DevelImageVisual::StopBehavior::CURRENT_FRAME), mLoopingMode(DevelImageVisual::LoopingMode::RESTART), mNextFrameStartTime(), - mFrameDurationNanoSeconds(0), + mFrameDurationMicroSeconds(MICROSECONDS_PER_SECOND / 60.0f), mFrameRate(60.0f), mCurrentFrame(0), mTotalFrame(0), mStartFrame(0), mEndFrame(0), + mDroppedFrames(0), mWidth(0), mHeight(0), mAnimationDataIndex(0), @@ -71,9 +74,11 @@ VectorAnimationTask::VectorAnimationTask(VisualFactoryCache& factoryCache, const mUpdateFrameNumber(false), mNeedAnimationFinishedTrigger(true), mAnimationDataUpdated(false), - mDestroyTask(false) + mDestroyTask(false), + mLoadRequest(false), + mLoadFailed(false) { - Initialize(); + mVectorRenderer.UploadCompletedSignal().Connect(this, &VectorAnimationTask::OnUploadCompleted); } VectorAnimationTask::~VectorAnimationTask() @@ -90,12 +95,42 @@ void VectorAnimationTask::Finalize() { mAnimationFinishedTrigger.reset(); } + if(mLoadCompletedTrigger) + { + mLoadCompletedTrigger.reset(); + } mVectorRenderer.Finalize(); mDestroyTask = true; } +bool VectorAnimationTask::Load() +{ + if(!mVectorRenderer.Load(mUrl)) + { + DALI_LOG_ERROR("VectorAnimationTask::Load: Load failed [%s]\n", mUrl.c_str()); + mLoadRequest = false; + mLoadFailed = true; + mLoadCompletedTrigger->Trigger(); + return false; + } + + mTotalFrame = mVectorRenderer.GetTotalFrameNumber(); + + mEndFrame = mTotalFrame - 1; + + mFrameRate = mVectorRenderer.GetFrameRate(); + mFrameDurationMicroSeconds = MICROSECONDS_PER_SECOND / mFrameRate; + + mLoadRequest = false; + mLoadCompletedTrigger->Trigger(); + + DALI_LOG_INFO(gVectorAnimationLogFilter, Debug::Verbose, "VectorAnimationTask::Load: file = %s [%d frames, %f fps] [%p]\n", mUrl.c_str(), mTotalFrame, mFrameRate, this); + + return true; +} + void VectorAnimationTask::SetRenderer(Renderer renderer) { ConditionalWait::ScopedLock lock(mConditionalWait); @@ -105,6 +140,19 @@ void VectorAnimationTask::SetRenderer(Renderer renderer) DALI_LOG_INFO(gVectorAnimationLogFilter, Debug::Verbose, "VectorAnimationTask::SetRenderer [%p]\n", this); } +void VectorAnimationTask::RequestLoad(const std::string& url) +{ + mUrl = url; + mLoadRequest = true; + + mVectorAnimationThread.AddTask(this); +} + +bool VectorAnimationTask::IsLoadRequested() const +{ + return mLoadRequest; +} + void VectorAnimationTask::SetAnimationData(const AnimationData& data) { ConditionalWait::ScopedLock lock(mConditionalWait); @@ -227,9 +275,8 @@ void VectorAnimationTask::SetPlayRange(const Property::Array& playRange) std::string marker; if(playRange.GetElementAt(0).Get(marker)) { - if(mVectorRenderer) + if(mVectorRenderer && mVectorRenderer.GetMarkerInfo(marker, startFrame, endFrame)) { - mVectorRenderer.GetMarkerInfo(marker, startFrame, endFrame); valid = true; } } @@ -242,38 +289,33 @@ void VectorAnimationTask::SetPlayRange(const Property::Array& playRange) } // Make sure the range specified is between 0 and the total frame number - if(startFrame < mTotalFrame && endFrame < mTotalFrame) + startFrame = std::min(startFrame, mTotalFrame - 1); + endFrame = std::min(endFrame, mTotalFrame - 1); + + // If the range is not in order swap values + if(startFrame > endFrame) + { + uint32_t temp = startFrame; + startFrame = endFrame; + endFrame = temp; + } + + if(startFrame != mStartFrame || endFrame != mEndFrame) { - // If the range is not in order swap values - if(startFrame > endFrame) + mStartFrame = startFrame; + mEndFrame = endFrame; + + // If the current frame is out of the range, change the current frame also. + if(mStartFrame > mCurrentFrame) { - uint32_t temp = startFrame; - startFrame = endFrame; - endFrame = temp; + mCurrentFrame = mStartFrame; } - - if(startFrame != mStartFrame || endFrame != mEndFrame) + else if(mEndFrame < mCurrentFrame) { - mStartFrame = startFrame; - mEndFrame = endFrame; - - // If the current frame is out of the range, change the current frame also. - if(mStartFrame > mCurrentFrame) - { - mCurrentFrame = mStartFrame; - } - else if(mEndFrame < mCurrentFrame) - { - mCurrentFrame = mEndFrame; - } - - DALI_LOG_INFO(gVectorAnimationLogFilter, Debug::Verbose, "VectorAnimationTask::SetPlayRange: [%d, %d] [%p]\n", mStartFrame, mEndFrame, this); + mCurrentFrame = mEndFrame; } - } - else - { - DALI_LOG_ERROR("VectorAnimationTask::SetPlayRange: Invalid range (%d, %d) [%p]\n", startFrame, endFrame, this); - return; + + DALI_LOG_INFO(gVectorAnimationLogFilter, Debug::Verbose, "VectorAnimationTask::SetPlayRange: [%d, %d] [%s] [%p]\n", mStartFrame, mEndFrame, mUrl.c_str(), this); } } @@ -300,7 +342,7 @@ void VectorAnimationTask::SetCurrentFrameNumber(uint32_t frameNumber) } else { - DALI_LOG_ERROR("Invalid frame number [%d (%d, %d)]\n", frameNumber, mStartFrame, mEndFrame); + DALI_LOG_ERROR("Invalid frame number [%d (%d, %d)] [%p]\n", frameNumber, mStartFrame, mEndFrame, this); } } @@ -338,34 +380,16 @@ void VectorAnimationTask::GetLayerInfo(Property::Map& map) const mVectorRenderer.GetLayerInfo(map); } -VectorAnimationTask::UploadCompletedSignalType& VectorAnimationTask::UploadCompletedSignal() +VectorAnimationTask::ResourceReadySignalType& VectorAnimationTask::ResourceReadySignal() { - return mVectorRenderer.UploadCompletedSignal(); + return mResourceReadySignal; } -void VectorAnimationTask::Initialize() -{ - mVectorRenderer = VectorAnimationRenderer::New(mUrl); - - mTotalFrame = mVectorRenderer.GetTotalFrameNumber(); - - mEndFrame = mTotalFrame - 1; - - mFrameRate = mVectorRenderer.GetFrameRate(); - mFrameDurationNanoSeconds = NANOSECONDS_PER_SECOND / mFrameRate; - - uint32_t width, height; - mVectorRenderer.GetDefaultSize(width, height); - - SetSize(width, height); - - DALI_LOG_INFO(gVectorAnimationLogFilter, Debug::Verbose, "VectorAnimationTask::Initialize: file = %s [%d frames, %f fps] [%p]\n", mUrl.c_str(), mTotalFrame, mFrameRate, this); -} - -bool VectorAnimationTask::Rasterize() +bool VectorAnimationTask::Rasterize(bool& keepAnimation) { bool stopped = false; uint32_t currentFrame; + keepAnimation = false; { ConditionalWait::ScopedLock lock(mConditionalWait); @@ -374,13 +398,23 @@ bool VectorAnimationTask::Rasterize() // The task will be destroyed. We don't need rasterization. return false; } + + if(mLoadRequest) + { + return Load(); + } + } + + if(mLoadFailed) + { + return false; } ApplyAnimationData(); if(mPlayState == PlayState::PLAYING && mUpdateFrameNumber) { - mCurrentFrame = mForward ? mCurrentFrame + 1 : mCurrentFrame - 1; + mCurrentFrame = mForward ? mCurrentFrame + mDroppedFrames + 1 : (mCurrentFrame > mDroppedFrames ? mCurrentFrame - mDroppedFrames - 1 : 0); Dali::ClampInPlace(mCurrentFrame, mStartFrame, mEndFrame); } @@ -472,13 +506,12 @@ bool VectorAnimationTask::Rasterize() DALI_LOG_INFO(gVectorAnimationLogFilter, Debug::Verbose, "VectorAnimationTask::Rasterize: Animation is finished [current = %d] [%p]\n", currentFrame, this); } - bool keepAnimation = true; - if(mPlayState == PlayState::PAUSED || mPlayState == PlayState::STOPPED) + if(mPlayState != PlayState::PAUSED && mPlayState != PlayState::STOPPED) { - keepAnimation = false; + keepAnimation = true; } - return keepAnimation; + return true; } uint32_t VectorAnimationTask::GetStoppedFrame(uint32_t startFrame, uint32_t endFrame, uint32_t currentFrame) @@ -514,22 +547,37 @@ uint32_t VectorAnimationTask::GetStoppedFrame(uint32_t startFrame, uint32_t endF return frame; } -std::chrono::time_point VectorAnimationTask::CalculateNextFrameTime(bool renderNow) +VectorAnimationTask::TimePoint VectorAnimationTask::CalculateNextFrameTime(bool renderNow) { - // std::chrono::time_point template has second parameter duration which defaults to the std::chrono::system_clock supported + // std::chrono::time_point template has second parameter duration which defaults to the std::chrono::steady_clock supported // duration. In some C++11 implementations it is a milliseconds duration, so it fails to compile unless mNextFrameStartTime // is casted to use the default duration. - mNextFrameStartTime = std::chrono::time_point_cast::duration>( - mNextFrameStartTime + std::chrono::nanoseconds(mFrameDurationNanoSeconds)); - auto current = std::chrono::system_clock::now(); - if(renderNow || mNextFrameStartTime < current) + mNextFrameStartTime = std::chrono::time_point_cast(mNextFrameStartTime + std::chrono::microseconds(mFrameDurationMicroSeconds)); + auto current = std::chrono::steady_clock::now(); + mDroppedFrames = 0; + + if(renderNow) { mNextFrameStartTime = current; } + else if(mNextFrameStartTime < current) + { + uint32_t droppedFrames = 0; + + while(current > std::chrono::time_point_cast(mNextFrameStartTime + std::chrono::microseconds(mFrameDurationMicroSeconds)) && droppedFrames < mTotalFrame) + { + droppedFrames++; + mNextFrameStartTime = std::chrono::time_point_cast(mNextFrameStartTime + std::chrono::microseconds(mFrameDurationMicroSeconds)); + } + + mNextFrameStartTime = current; + mDroppedFrames = droppedFrames; + } + return mNextFrameStartTime; } -std::chrono::time_point VectorAnimationTask::GetNextFrameTime() +VectorAnimationTask::TimePoint VectorAnimationTask::GetNextFrameTime() { return mNextFrameStartTime; } @@ -578,6 +626,19 @@ void VectorAnimationTask::ApplyAnimationData() SetCurrentFrameNumber(mAnimationData[index].currentFrame); } + if(mAnimationData[index].resendFlag & VectorAnimationTask::RESEND_NEED_RESOURCE_READY) + { + mVectorRenderer.InvalidateBuffer(); + } + + if(mAnimationData[index].resendFlag & VectorAnimationTask::RESEND_DYNAMIC_PROPERTY) + { + for(auto&& iter : mAnimationData[index].dynamicProperties) + { + mVectorRenderer.AddPropertyValueCallback(iter.keyPath, static_cast(iter.property), iter.callback, iter.id); + } + } + if(mAnimationData[index].resendFlag & VectorAnimationTask::RESEND_PLAY_STATE) { if(mAnimationData[index].playState == DevelImageVisual::PlayState::PLAYING) @@ -594,9 +655,27 @@ void VectorAnimationTask::ApplyAnimationData() } } + // reset data + mAnimationData[index].dynamicProperties.clear(); mAnimationData[index].resendFlag = 0; } +void VectorAnimationTask::OnUploadCompleted() +{ + mResourceReadySignal.Emit(ResourceStatus::READY); +} + +void VectorAnimationTask::OnLoadCompleted() +{ + if(!mLoadFailed) + { + mResourceReadySignal.Emit(ResourceStatus::LOADED); + } + else + { + mResourceReadySignal.Emit(ResourceStatus::FAILED); + } +} } // namespace Internal } // namespace Toolkit