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");
} // 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(),
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),
mAnimationDataUpdated(false),
mDestroyTask(false)
{
- Initialize();
}
VectorAnimationTask::~VectorAnimationTask()
mDestroyTask = true;
}
+bool VectorAnimationTask::Load(const std::string& url)
+{
+ mUrl = url;
+
+ if(!mVectorRenderer.Load(mUrl))
+ {
+ DALI_LOG_ERROR("VectorAnimationTask::Load: Load failed [%s]\n", mUrl.c_str());
+ return false;
+ }
+
+ mTotalFrame = mVectorRenderer.GetTotalFrameNumber();
+
+ mEndFrame = mTotalFrame - 1;
+
+ mFrameRate = mVectorRenderer.GetFrameRate();
+ mFrameDurationMicroSeconds = MICROSECONDS_PER_SECOND / mFrameRate;
+
+ uint32_t width, height;
+ mVectorRenderer.GetDefaultSize(width, height);
+
+ SetSize(width, height);
+
+ 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);
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;
}
}
return mVectorRenderer.UploadCompletedSignal();
}
-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 stopped = false;
if(mPlayState == PlayState::PLAYING && mUpdateFrameNumber)
{
- mCurrentFrame = mForward ? mCurrentFrame + 1 : mCurrentFrame - 1;
+ mCurrentFrame = mForward ? mCurrentFrame + mDroppedFrames + 1 : mCurrentFrame - mDroppedFrames - 1;
Dali::ClampInPlace(mCurrentFrame, mStartFrame, mEndFrame);
}
return frame;
}
-std::chrono::time_point<std::chrono::system_clock> 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<std::chrono::time_point<std::chrono::system_clock>::duration>(
- mNextFrameStartTime + std::chrono::nanoseconds(mFrameDurationNanoSeconds));
- auto current = std::chrono::system_clock::now();
- if(renderNow || mNextFrameStartTime < current)
+ mNextFrameStartTime = std::chrono::time_point_cast<TimePoint::duration>(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<TimePoint::duration>(mNextFrameStartTime + std::chrono::microseconds(mFrameDurationMicroSeconds)) && droppedFrames < mTotalFrame)
+ {
+ droppedFrames++;
+ mNextFrameStartTime = std::chrono::time_point_cast<TimePoint::duration>(mNextFrameStartTime + std::chrono::microseconds(mFrameDurationMicroSeconds));
+ }
+
mNextFrameStartTime = current;
+ mDroppedFrames = droppedFrames;
}
+
return mNextFrameStartTime;
}
-std::chrono::time_point<std::chrono::system_clock> VectorAnimationTask::GetNextFrameTime()
+VectorAnimationTask::TimePoint VectorAnimationTask::GetNextFrameTime()
{
return mNextFrameStartTime;
}