X-Git-Url: http://review.tizen.org/git/?p=platform%2Fcore%2Fuifw%2Fdali-toolkit.git;a=blobdiff_plain;f=dali-toolkit%2Finternal%2Fvisuals%2Fanimated-vector-image%2Fvector-rasterize-thread.cpp;h=fead5debb835c65d6932c50855dd9acc186fd9be;hp=543ca0df8a075f243b93332cff94e742b9efb89a;hb=af8eb8d7c507d99a03155c2070a748dfc094833a;hpb=b97b29c76acefabbae2c0a4e9ecc261bf9dd8036 diff --git a/dali-toolkit/internal/visuals/animated-vector-image/vector-rasterize-thread.cpp b/dali-toolkit/internal/visuals/animated-vector-image/vector-rasterize-thread.cpp index 543ca0d..fead5de 100644 --- a/dali-toolkit/internal/visuals/animated-vector-image/vector-rasterize-thread.cpp +++ b/dali-toolkit/internal/visuals/animated-vector-image/vector-rasterize-thread.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018 Samsung Electronics Co., Ltd. + * Copyright (c) 2019 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. @@ -44,12 +44,13 @@ constexpr auto NANOSECONDS_PER_SECOND( 1e+9 ); Debug::Filter* gVectorAnimationLogFilter = Debug::Filter::New( Debug::NoLogging, false, "LOG_VECTOR_ANIMATION" ); #endif -inline void ResetToStart( bool& updated, uint32_t& value, uint32_t startValue, ConditionalWait& conditionalWait ) +inline void ResetValue( bool& updated, uint32_t& value, uint32_t newValue, ConditionalWait& conditionalWait ) { ConditionalWait::ScopedLock lock( conditionalWait ); if( !updated ) { - value = startValue; + value = newValue; + updated = true; } } @@ -61,10 +62,10 @@ VectorRasterizeThread::VectorRasterizeThread( const std::string& url ) mConditionalWait(), mResourceReadyTrigger(), mAnimationFinishedTrigger(), - mPlayRange( 0.0f, 1.0f ), - mPlayState( DevelImageVisual::PlayState::STOPPED ), + mPlayState( PlayState::STOPPED ), + mStopBehavior( DevelImageVisual::StopBehavior::CURRENT_FRAME ), + mLoopingMode( DevelImageVisual::LoopingMode::RESTART ), mFrameDurationNanoSeconds( 0 ), - mProgress( 0.0f ), mFrameRate( 60.0f ), mCurrentFrame( 0 ), mTotalFrame( 0 ), @@ -78,6 +79,8 @@ VectorRasterizeThread::VectorRasterizeThread( const std::string& url ) mDestroyThread( false ), mResourceReady( false ), mCurrentFrameUpdated( false ), + mForward( true ), + mUpdateFrameNumber( false ), mLogFactory( Dali::Adaptor::Get().GetLogFactory() ) { Initialize(); @@ -95,7 +98,7 @@ VectorRasterizeThread::~VectorRasterizeThread() mVectorRenderer.StopRender(); } - DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorRasterizeThread::~VectorRasterizeThread: Join\n" ); + DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorRasterizeThread::~VectorRasterizeThread: Join [%p]\n", this ); Join(); } @@ -110,7 +113,7 @@ void VectorRasterizeThread::Run() Rasterize(); } - DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorRasterizeThread::Run: End of thread\n" ); + DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorRasterizeThread::Run: End of thread [%p]\n", this ); } void VectorRasterizeThread::SetRenderer( Renderer renderer ) @@ -119,7 +122,7 @@ void VectorRasterizeThread::SetRenderer( Renderer renderer ) mVectorRenderer.SetRenderer( renderer ); - DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorRasterizeThread::SetRenderer\n" ); + DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorRasterizeThread::SetRenderer [%p]\n", this ); } void VectorRasterizeThread::SetSize( uint32_t width, uint32_t height ) @@ -134,7 +137,7 @@ void VectorRasterizeThread::SetSize( uint32_t width, uint32_t height ) mResourceReady = false; - DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorRasterizeThread::SetSize: width = %d, height = %d\n", width, height ); + DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorRasterizeThread::SetSize: width = %d, height = %d [%p]\n", width, height, this ); } } @@ -142,37 +145,38 @@ void VectorRasterizeThread::PlayAnimation() { ConditionalWait::ScopedLock lock( mConditionalWait ); - if( mPlayState != DevelImageVisual::PlayState::PLAYING ) + if( mPlayState != PlayState::PLAYING ) { - mPlayState = DevelImageVisual::PlayState::PLAYING; + mNeedRender = true; + mUpdateFrameNumber = false; + mPlayState = PlayState::PLAYING; mConditionalWait.Notify( lock ); - DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorRasterizeThread::PlayAnimation: Start\n" ); + DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorRasterizeThread::PlayAnimation: Play [%p]\n", this ); } } void VectorRasterizeThread::StopAnimation() { ConditionalWait::ScopedLock lock( mConditionalWait ); - if( mPlayState != DevelImageVisual::PlayState::STOPPED ) + if( mPlayState != PlayState::STOPPED && mPlayState != PlayState::STOPPING ) { - mPlayState = DevelImageVisual::PlayState::STOPPED; - - mCurrentFrame = mStartFrame; - mCurrentFrameUpdated = true; + mNeedRender = true; + mPlayState = PlayState::STOPPING; + mConditionalWait.Notify( lock ); - DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorRasterizeThread::StopAnimation: Stop\n" ); + DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorRasterizeThread::StopAnimation: Stop [%p]\n", this ); } } void VectorRasterizeThread::PauseAnimation() { ConditionalWait::ScopedLock lock( mConditionalWait ); - if( mPlayState == DevelImageVisual::PlayState::PLAYING ) + if( mPlayState == PlayState::PLAYING ) { - mPlayState = DevelImageVisual::PlayState::PAUSED; + mPlayState = PlayState::PAUSED; - DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorRasterizeThread::PauseAnimation: Pause\n" ); + DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorRasterizeThread::PauseAnimation: Pause [%p]\n", this ); } } @@ -185,7 +189,7 @@ void VectorRasterizeThread::RenderFrame() mNeedRender = true; mConditionalWait.Notify( lock ); - DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorRasterizeThread::RenderFrame: Render\n" ); + DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorRasterizeThread::RenderFrame: Render [%p]\n", this ); } } @@ -209,35 +213,29 @@ void VectorRasterizeThread::SetLoopCount( int32_t count ) mLoopCount = count; - DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorRasterizeThread::SetLoopCount: [%d]\n", count ); + DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorRasterizeThread::SetLoopCount: [%d] [%p]\n", count, this ); } } -int32_t VectorRasterizeThread::GetLoopCount() const -{ - return mLoopCount; -} - -void VectorRasterizeThread::SetPlayRange( Vector2 range ) +void VectorRasterizeThread::SetPlayRange( uint32_t startFrame, uint32_t endFrame ) { - // Make sure the range specified is between 0.0 and 1.0 - if( range.x >= 0.0f && range.x <= 1.0f && range.y >= 0.0f && range.y <= 1.0f ) + // Make sure the range specified is between 0 and the total frame number + if( ( startFrame < mTotalFrame ) && ( endFrame < mTotalFrame ) ) { - Vector2 orderedRange( range ); // If the range is not in order swap values - if( range.x > range.y ) + if( startFrame > endFrame ) { - orderedRange = Vector2( range.y, range.x ); + uint32_t temp = startFrame; + startFrame = endFrame; + endFrame = temp; } - if( mPlayRange != orderedRange ) + if( startFrame != mStartFrame || endFrame != mEndFrame ) { ConditionalWait::ScopedLock lock( mConditionalWait ); - mPlayRange = orderedRange; - - mStartFrame = static_cast< uint32_t >( mPlayRange.x * mTotalFrame + 0.5f ); - mEndFrame = static_cast< uint32_t >( mPlayRange.y * mTotalFrame + 0.5f ); + mStartFrame = startFrame; + mEndFrame = endFrame; // If the current frame is out of the range, change the current frame also. if( mStartFrame > mCurrentFrame ) @@ -255,36 +253,70 @@ void VectorRasterizeThread::SetPlayRange( Vector2 range ) mResourceReady = false; } - DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorRasterizeThread::SetPlayRange: [%d, %d]\n", mStartFrame, mEndFrame ); + DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorRasterizeThread::SetPlayRange: [%d, %d] [%p]\n", mStartFrame, mEndFrame, this ); } } } -Vector2 VectorRasterizeThread::GetPlayRange() const +DevelImageVisual::PlayState::Type VectorRasterizeThread::GetPlayState() const +{ + DevelImageVisual::PlayState::Type state = DevelImageVisual::PlayState::STOPPED; + + switch( mPlayState ) + { + case PlayState::PLAYING: + { + state = DevelImageVisual::PlayState::PLAYING; + break; + } + case PlayState::PAUSED: + { + state = DevelImageVisual::PlayState::PAUSED; + break; + } + case PlayState::STOPPING: + case PlayState::STOPPED: + { + state = DevelImageVisual::PlayState::STOPPED; + break; + } + } + + return state; +} + +bool VectorRasterizeThread::IsResourceReady() const { - return mPlayRange; + return mResourceReady; } -void VectorRasterizeThread::SetCurrentProgress( float progress ) +void VectorRasterizeThread::SetCurrentFrameNumber( uint32_t frameNumber ) { ConditionalWait::ScopedLock lock( mConditionalWait ); - if( progress >= mPlayRange.x && progress <= mPlayRange.y ) + if( frameNumber >= mStartFrame && frameNumber <= mEndFrame ) { - mProgress = progress; - - mCurrentFrame = static_cast< uint32_t >( mTotalFrame * progress + 0.5f ); + mCurrentFrame = frameNumber; mCurrentFrameUpdated = true; mResourceReady = false; - DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorRasterizeThread::SetCurrentProgress: progress = %f (%d)\n", progress, mCurrentFrame ); + DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorRasterizeThread::SetCurrentFrameNumber: frame number = %d [%p]\n", mCurrentFrame, this ); + } + else + { + DALI_LOG_ERROR( "Invalid frame number [%d (%d, %d)]\n", frameNumber, mStartFrame, mEndFrame ); } } -float VectorRasterizeThread::GetCurrentProgress() const +uint32_t VectorRasterizeThread::GetCurrentFrameNumber() const +{ + return mCurrentFrame; +} + +uint32_t VectorRasterizeThread::GetTotalFrameNumber() const { - return ( static_cast< float >( mCurrentFrame ) / static_cast< float >( mTotalFrame ) ); + return mTotalFrame; } void VectorRasterizeThread::GetDefaultSize( uint32_t& width, uint32_t& height ) const @@ -292,14 +324,20 @@ void VectorRasterizeThread::GetDefaultSize( uint32_t& width, uint32_t& height ) mVectorRenderer.GetDefaultSize( width, height ); } -DevelImageVisual::PlayState VectorRasterizeThread::GetPlayState() const +void VectorRasterizeThread::SetStopBehavior( DevelImageVisual::StopBehavior::Type stopBehavior ) { - return mPlayState; + ConditionalWait::ScopedLock lock( mConditionalWait ); + mStopBehavior = stopBehavior; + + DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorRasterizeThread::SetStopBehavior: stop behavor = %d [%p]\n", mStopBehavior, this ); } -bool VectorRasterizeThread::IsResourceReady() const +void VectorRasterizeThread::SetLoopingMode( DevelImageVisual::LoopingMode::Type loopingMode ) { - return mResourceReady; + ConditionalWait::ScopedLock lock( mConditionalWait ); + mLoopingMode = loopingMode; + + DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorRasterizeThread::SetLoopingMode: looping mode = %d [%p]\n", mLoopingMode, this ); } void VectorRasterizeThread::Initialize() @@ -308,10 +346,7 @@ void VectorRasterizeThread::Initialize() mTotalFrame = mVectorRenderer.GetTotalFrameNumber(); - mStartFrame = static_cast< uint32_t >( mPlayRange.x * mTotalFrame + 0.5f ); - mEndFrame = static_cast< uint32_t >( mPlayRange.y * mTotalFrame + 0.5f ); - - mCurrentFrame = std::max( static_cast< uint32_t >( mTotalFrame * mProgress + 0.5f ), mStartFrame ); + mEndFrame = mTotalFrame - 1; mFrameRate = mVectorRenderer.GetFrameRate(); mFrameDurationNanoSeconds = NANOSECONDS_PER_SECOND / mFrameRate; @@ -321,97 +356,168 @@ void VectorRasterizeThread::Initialize() SetSize( width, height ); - DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorRasterizeThread::Initialize: file = %s [%d frames, %f fps]\n", mUrl.c_str(), mTotalFrame, mFrameRate ); + DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorRasterizeThread::Initialize: file = %s [%d frames, %f fps] [%p]\n", mUrl.c_str(), mTotalFrame, mFrameRate, this ); } void VectorRasterizeThread::Rasterize() { - bool resourceReady; + bool resourceReady, stopped = false; uint32_t currentFrame, startFrame, endFrame; int32_t loopCount; - DevelImageVisual::PlayState playState; { ConditionalWait::ScopedLock lock( mConditionalWait ); - if( mPlayState != DevelImageVisual::PlayState::PLAYING && !mNeedRender && !mDestroyThread ) + if( ( mPlayState == PlayState::PAUSED || mPlayState == PlayState::STOPPED ) && !mNeedRender && !mDestroyThread ) { - DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorRasterizeThread::Rasterize: Wait\n" ); - - if( mPlayState == DevelImageVisual::PlayState::STOPPED ) - { - // Reset the current loop - mCurrentLoop = 0; - } + DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorRasterizeThread::Rasterize: Wait [%p]\n", this ); mConditionalWait.Wait( lock ); } + if( mPlayState == PlayState::PLAYING && mUpdateFrameNumber ) + { + mCurrentFrame = mForward ? mCurrentFrame + 1 : mCurrentFrame - 1; + } + resourceReady = mResourceReady; - currentFrame = mCurrentFrame++; + currentFrame = mCurrentFrame; startFrame = mStartFrame; endFrame = mEndFrame; loopCount = mLoopCount; - playState = mPlayState; mNeedRender = false; mResourceReady = true; mCurrentFrameUpdated = false; + mUpdateFrameNumber = true; } auto currentFrameStartTime = std::chrono::system_clock::now(); - // Rasterize - mVectorRenderer.Render( currentFrame ); + if( mPlayState == PlayState::STOPPING ) + { + currentFrame = GetStoppedFrame( startFrame, endFrame, currentFrame ); + ResetValue( mCurrentFrameUpdated, mCurrentFrame, currentFrame, mConditionalWait ); - if( playState == DevelImageVisual::PlayState::PLAYING ) + stopped = true; + } + else if( mPlayState == PlayState::PLAYING ) { - if( currentFrame >= endFrame ) + bool animationFinished = false; + + if( currentFrame >= endFrame ) // last frame { - if( loopCount < 0 ) + if( mLoopingMode == DevelImageVisual::LoopingMode::AUTO_REVERSE ) { - // repeat forever - ResetToStart( mCurrentFrameUpdated, mCurrentFrame, startFrame, mConditionalWait ); // If the current frame is changed in the event thread, don't overwrite it. + mForward = false; } else { - mCurrentLoop++; - if( mCurrentLoop >= loopCount ) + if( loopCount < 0 || ++mCurrentLoop < loopCount ) // repeat forever or before the last loop { - mPlayState = DevelImageVisual::PlayState::STOPPED; - - ResetToStart( mCurrentFrameUpdated, mCurrentFrame, startFrame, mConditionalWait ); - - // Animation is finished - mAnimationFinishedTrigger->Trigger(); - - DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorRasterizeThread::Rasterize: Animation is finished\n" ); + ResetValue( mCurrentFrameUpdated, mCurrentFrame, startFrame, mConditionalWait ); // If the current frame is changed in the event thread, don't overwrite it. + mUpdateFrameNumber = false; } else { - ResetToStart( mCurrentFrameUpdated, mCurrentFrame, startFrame, mConditionalWait ); + animationFinished = true; // end of animation } } } + else if( currentFrame == startFrame && !mForward ) // first frame + { + if( loopCount < 0 || ++mCurrentLoop < loopCount ) // repeat forever or before the last loop + { + mForward = true; + } + else + { + animationFinished = true; // end of animation + } + } + + if( animationFinished ) + { + if( mStopBehavior == DevelImageVisual::StopBehavior::CURRENT_FRAME ) + { + stopped = true; + } + else + { + mPlayState = PlayState::STOPPING; + } + } + } + + // Rasterize + if( !mVectorRenderer.Render( currentFrame ) ) + { + DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorRasterizeThread::Rasterize: Rendering failed. Try again later.[%d] [%p]\n", currentFrame, this ); + mUpdateFrameNumber = false; } if( !resourceReady ) { - DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorRasterizeThread::Rasterize: Resource ready trigger\n" ); + DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorRasterizeThread::Rasterize: Resource ready trigger [%p]\n", this ); mResourceReadyTrigger->Trigger(); } + if( stopped ) + { + mPlayState = PlayState::STOPPED; + mForward = true; + mCurrentLoop = 0; + + // Animation is finished + mAnimationFinishedTrigger->Trigger(); + + DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorRasterizeThread::Rasterize: Animation is finished [%p]\n", this ); + } + auto timeToSleepUntil = currentFrameStartTime + std::chrono::nanoseconds( mFrameDurationNanoSeconds ); #if defined(DEBUG_ENABLED) auto sleepDuration = std::chrono::duration_cast< std::chrono::milliseconds >( timeToSleepUntil - std::chrono::system_clock::now() ); - DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorRasterizeThread::Rasterize: [current = %d, sleep duration = %lld]\n", currentFrame, sleepDuration.count() ); + DALI_LOG_INFO( gVectorAnimationLogFilter, Debug::Verbose, "VectorRasterizeThread::Rasterize: [current = %d, sleep duration = %lld] [%p]\n", currentFrame, sleepDuration.count(), this ); #endif std::this_thread::sleep_until( timeToSleepUntil ); } +uint32_t VectorRasterizeThread::GetStoppedFrame( uint32_t startFrame, uint32_t endFrame, uint32_t currentFrame ) +{ + uint32_t frame = currentFrame; + + switch( mStopBehavior ) + { + case DevelImageVisual::StopBehavior::FIRST_FRAME: + { + frame = startFrame; + break; + } + case DevelImageVisual::StopBehavior::LAST_FRAME: + { + if( mLoopingMode == DevelImageVisual::LoopingMode::AUTO_REVERSE ) + { + frame = startFrame; + } + else + { + frame = endFrame; + } + break; + } + case DevelImageVisual::StopBehavior::CURRENT_FRAME: + { + frame = currentFrame; + break; + } + } + + return frame; +} + } // namespace Internal } // namespace Toolkit