This patch is to support the synchronization between video player and UI.
To do that, video player's changing function as resize/move should be called before calling eglSwapBuffers.
Change-Id: Icfe0e0c2fee9d65a9df10827ed91faf38b09e720
*/
#include <dali/devel-api/adaptor-framework/video-player.h>
+#include <dali/devel-api/adaptor-framework/video-sync-mode.h>
#include <dali/public-api/object/any.h>
#include <dali/public-api/object/base-object.h>
#include <toolkit-application.h>
return NULL;
}
+ void StartSynchronization()
+ {
+
+ }
+
+ void FinishSynchronization()
+ {
+
+ }
public:
return VideoPlayer( player );
}
+VideoPlayer VideoPlayer::New( Dali::Actor actor, Dali::VideoSyncMode syncMode )
+{
+ Internal::Adaptor::VideoPlayer* player = new Internal::Adaptor::VideoPlayer();
+
+ return VideoPlayer( player );
+}
+
VideoPlayer::VideoPlayer( const VideoPlayer& player )
: BaseHandle( player )
{
return Internal::Adaptor::GetImplementation( *this ).GetMediaPlayer();
}
+void VideoPlayer::StartSynchronization()
+{
+ Internal::Adaptor::GetImplementation( *this ).StartSynchronization();
+}
+
+void VideoPlayer::FinishSynchronization()
+{
+ Internal::Adaptor::GetImplementation( *this ).FinishSynchronization();
+}
+
} // namespace Dali;
return Dali::Window( windowImpl );
}
+void AddFrameRenderedCallback( Window window, std::unique_ptr< CallbackBase > callback, int32_t frameId )
+{
+ CallbackBase::Execute( *callback, frameId );
+}
+
+void AddFramePresentedCallback( Window window, std::unique_ptr< CallbackBase > callback, int32_t frameId )
+{
+ CallbackBase::Execute( *callback, frameId );
+}
+
EventProcessingFinishedSignalType& EventProcessingFinishedSignal( Window window )
{
return GetImplementation( window ).GetScene().EventProcessingFinishedSignal();
Dali::Window Get( Actor actor );
Dali::Window DownCast( BaseHandle handle );
+void AddFrameRenderedCallback( Window window, std::unique_ptr< CallbackBase > callback, int32_t frameId );
+void AddFramePresentedCallback( Window window, std::unique_ptr< CallbackBase > callback, int32_t frameId );
EventProcessingFinishedSignalType& EventProcessingFinishedSignal( Window window );
KeyEventGeneratedSignalType& KeyEventGeneratedSignal( Dali::Window window );
#include <dali-toolkit/dali-toolkit.h>
#include <dali-toolkit/public-api/controls/video-view/video-view.h>
#include <dali-toolkit/devel-api/controls/video-view/video-view-devel.h>
+#include <dali/devel-api/adaptor-framework/video-sync-mode.h>
using namespace Dali;
using namespace Dali::Toolkit;
const char* const VOLUME_LEFT( "volumeLeft" );
const char* const VOLUME_RIGHT( "volumeRight" );
const char* const RENDERING_TYPE( "renderingTarget" );
+const char* const DUMMY_STRING( "dummy string" );
const char* VERTEX_SHADER = DALI_COMPOSE_SHADER(
attribute mediump vec2 aPosition;\n
Toolkit::VideoView view = Toolkit::VideoView::New();
DALI_TEST_CHECK( view );
- Toolkit::VideoView view2 = Toolkit::VideoView::New( "" );
+ const std::string url( DUMMY_STRING );
+ Toolkit::VideoView view2 = Toolkit::VideoView::New( url );
DALI_TEST_CHECK( view2 );
END_TEST;
}
ToolkitTestApplication application;
tet_infoline( "VideoView with custom shader" );
- VideoView view = VideoView::New();
+ VideoView view = VideoView::New( false );
DALI_TEST_CHECK( view );
ToolkitApplication::DECODED_IMAGES_SUPPORTED = true;
END_TEST;
}
+
+// Functor to test whether a Finish signal is emitted
+struct AnimationFinishCheck
+{
+ AnimationFinishCheck(bool& signalReceived)
+ : mSignalReceived(signalReceived)
+ {
+ }
+
+ void operator()(Animation& animation)
+ {
+ mSignalReceived = true;
+ }
+
+ void Reset()
+ {
+ mSignalReceived = false;
+ }
+
+ void CheckSignalReceived()
+ {
+ if (!mSignalReceived)
+ {
+ tet_printf("Expected Finish signal was not received\n");
+ tet_result(TET_FAIL);
+ }
+ else
+ {
+ tet_result(TET_PASS);
+ }
+ }
+
+ void CheckSignalNotReceived()
+ {
+ if (mSignalReceived)
+ {
+ tet_printf("Unexpected Finish signal was received\n");
+ tet_result(TET_FAIL);
+ }
+ else
+ {
+ tet_result(TET_PASS);
+ }
+ }
+
+ bool& mSignalReceived; // owned by individual tests
+};
+
+int UtcDaliVideoViewSyncAniamtionForCoverage(void)
+{
+ ToolkitTestApplication application;
+
+ VideoView videoView = DevelVideoView::New( Dali::VideoSyncMode::ENABLED );
+ DALI_TEST_CHECK( videoView );
+
+ // Build the animation
+ float durationSeconds(1.0f);
+ Animation animation = Animation::New(durationSeconds);
+
+ // Start the animation
+ Vector3 targetPosition(10.0f, 10.0f, 10.0f);
+ animation.AnimateTo(Property(videoView, Actor::Property::POSITION), targetPosition, AlphaFunction::LINEAR);
+ DevelVideoView::PlayAnimation( videoView, animation );
+
+ bool signalReceived(false);
+ AnimationFinishCheck finishCheck(signalReceived);
+ animation.FinishedSignal().Connect(&application, finishCheck);
+
+ application.SendNotification();
+ application.Render(static_cast<unsigned int>(durationSeconds*1000.0f) - 1u/*just less than the animation duration*/);
+
+ // We didn't expect the animation to finish yet
+ application.SendNotification();
+ finishCheck.CheckSignalNotReceived();
+
+ application.Render(2u/*just beyond the animation duration*/);
+
+ // We did expect the animation to finish
+ application.SendNotification();
+ finishCheck.CheckSignalReceived();
+ DALI_TEST_EQUALS( targetPosition, videoView.GetCurrentProperty< Vector3 >( Actor::Property::POSITION ), TEST_LOCATION );
+
+ // Restart the animation, with a different duration
+ finishCheck.Reset();
+
+ END_TEST;
+}
+
+int UtcDaliVideoViewASyncAniamtionForCoverage(void)
+{
+ ToolkitTestApplication application;
+
+ VideoView videoView = DevelVideoView::New( Dali::VideoSyncMode::DISABLED );
+ DALI_TEST_CHECK( videoView );
+
+ // Build the animation
+ float durationSeconds(1.0f);
+ Animation animation = Animation::New(durationSeconds);
+
+ // Start the animation
+ Vector3 targetPosition(10.0f, 10.0f, 10.0f);
+ animation.AnimateTo(Property(videoView, Actor::Property::POSITION), targetPosition, AlphaFunction::LINEAR);
+ DevelVideoView::PlayAnimation( videoView, animation );
+
+ bool signalReceived(false);
+ AnimationFinishCheck finishCheck(signalReceived);
+ animation.FinishedSignal().Connect(&application, finishCheck);
+
+ application.SendNotification();
+ application.Render(static_cast<unsigned int>(durationSeconds*1000.0f) - 1u/*just less than the animation duration*/);
+
+ // We didn't expect the animation to finish yet
+ application.SendNotification();
+ finishCheck.CheckSignalNotReceived();
+
+ application.Render(2u/*just beyond the animation duration*/);
+
+ // We did expect the animation to finish
+ application.SendNotification();
+ finishCheck.CheckSignalReceived();
+ DALI_TEST_EQUALS( targetPosition, videoView.GetCurrentProperty< Vector3 >( Actor::Property::POSITION ), TEST_LOCATION );
+
+ // Restart the animation, with a different duration
+ finishCheck.Reset();
+
+ END_TEST;
+}
+
+int UtcDaliVideoViewResizeWithSynchronization(void)
+{
+ ToolkitTestApplication application;
+ VideoView videoView = DevelVideoView::New( Dali::VideoSyncMode::ENABLED );
+ DALI_TEST_CHECK( videoView );
+
+ application.GetScene().Add( videoView );
+
+ Vector3 vector(50.0f, 200.0f, 0.0f);
+ videoView.SetProperty( Actor::Property::SIZE, vector );
+
+ application.SendNotification();
+ application.Render();
+
+ DALI_TEST_CHECK(vector == videoView.GetCurrentProperty< Vector3 >( Actor::Property::SIZE ));
+
+ END_TEST;
+}
return Dali::Toolkit::GetImpl( videoView ).GetMediaPlayer();\r
}\r
\r
+VideoView New( VideoSyncMode syncMode )\r
+{\r
+ VideoView videoView = Internal::VideoView::New( syncMode );\r
+ return videoView;\r
+}\r
+\r
+void PlayAnimation( VideoView videoView, Animation animation )\r
+{\r
+ Dali::Toolkit::GetImpl( videoView ).PlayAnimation( animation );\r
+}\r
\r
} // namespace DevelVideoView\r
\r
*\r
*/\r
\r
+// EXTERNAL INCLUDES\r
+#include <dali/devel-api/adaptor-framework/video-sync-mode.h>\r
+\r
// INTERNAL INCLUDES\r
+#include <dali/public-api/animation/animation.h>\r
#include <dali-toolkit/public-api/controls/video-view/video-view.h>\r
#include <dali/public-api/object/any.h>\r
\r
namespace DevelVideoView\r
{\r
\r
-\r
/**\r
* @brief Returns the internal media player.\r
* @param[in] videoView The current VideoView\r
*/\r
DALI_TOOLKIT_API Any GetMediaPlayer( VideoView videoView );\r
\r
+/**\r
+ * @brief Creates an initialized VideoView with synchronization mode.\r
+ *\r
+ * The syncMode is for synchronization between UI(transparent hole) and underlay video.\r
+ *\r
+ * @param[in] syncMode The synchronization mode between the UI (transparent hole) and VideoPlayer\r
+ * @return A handle to a newly allocated Dali VideoView\r
+ */\r
+DALI_TOOLKIT_API VideoView New( VideoSyncMode syncMode );\r
+\r
+/**\r
+ * @brief Play the resize or move animation with synchronization between UI(transparent hole) and video player\r
+ *\r
+ * The resize and move animation's play() function is called.\r
+ * If the animation is played, UI and video player will work synchronization.\r
+ *\r
+ * @param[in] videoView The current VideoView\r
+ * @param[in] animation The animation for video view's resize or move.\r
+ */\r
+DALI_TOOLKIT_API void PlayAnimation( VideoView videoView, Animation animation );\r
\r
} // namespace DevelVideoView\r
\r
#include <dali/public-api/object/type-registry.h>
#include <dali/public-api/object/type-registry-helper.h>
#include <dali/devel-api/scripting/scripting.h>
+#include <dali/devel-api/adaptor-framework/window-devel.h>
#include <dali/public-api/adaptor-framework/native-image-source.h>
#include <dali/integration-api/debug.h>
#include <dali/public-api/animation/constraint.h>
} // anonymous namepsace
-VideoView::VideoView()
+VideoView::VideoView( Dali::VideoSyncMode syncMode )
: Control( ControlBehaviour( ACTOR_BEHAVIOUR_DEFAULT | DISABLE_STYLE_CHANGE_SIGNALS ) ),
mCurrentVideoPlayPosition( 0 ),
+ mFrameID( 0 ),
mIsPlay( false ),
- mIsUnderlay( true )
+ mIsUnderlay( true ),
+ mSyncMode( syncMode )
{
- mVideoPlayer = Dali::VideoPlayer::New();
}
VideoView::~VideoView()
{
}
-Toolkit::VideoView VideoView::New()
+Toolkit::VideoView VideoView::New( VideoSyncMode syncMode )
{
- VideoView* impl = new VideoView();
+ VideoView* impl = new VideoView( syncMode );
Toolkit::VideoView handle = Toolkit::VideoView( *impl );
+ impl->mVideoPlayer = Dali::VideoPlayer::New( impl->Self(), syncMode );
impl->Initialize();
-
return handle;
}
Control::OnStageDisconnection();
}
+void VideoView::OnSizeSet( const Vector3& targetSize )
+{
+ if( mIsUnderlay && mSyncMode == Dali::VideoSyncMode::ENABLED )
+ {
+ SetFrameRenderCallback();
+ mVideoPlayer.StartSynchronization();
+ }
+ Control::OnSizeSet( targetSize );
+}
+
Vector3 VideoView::GetNaturalSize()
{
Vector3 size;
void VideoView::UpdateDisplayArea( Dali::PropertyNotification& source )
{
- if( !mIsUnderlay )
+ // If mSyncMode is enabled, Video player's size and poistion is updated in Video player's constraint.
+ // Because video view and player should be work syncronization.
+ if( !mIsUnderlay || mSyncMode == Dali::VideoSyncMode::ENABLED )
{
return;
}
return mVideoPlayer.GetMediaPlayer();
}
+void VideoView::OnAnimationFinished( Animation& animation )
+{
+ // send desync
+ SetFrameRenderCallback();
+}
+
+void VideoView::PlayAnimation( Dali::Animation animation )
+{
+ if( mIsUnderlay && mSyncMode == Dali::VideoSyncMode::ENABLED )
+ {
+ mVideoPlayer.StartSynchronization();
+ animation.FinishedSignal().Connect( this, &VideoView::OnAnimationFinished );
+ }
+ animation.Play();
+}
+
Dali::Shader VideoView::CreateShader()
{
std::string fragmentShader = "#extension GL_OES_EGL_image_external:require\n";
}
}
+void VideoView::FrameRenderCallback( int frameID )
+{
+ // send desync
+ if( frameID == mFrameID )
+ {
+ mVideoPlayer.FinishSynchronization();
+ mFrameID = 0;
+ }
+}
+
+void VideoView::SetFrameRenderCallback()
+{
+ mFrameID++;
+ DevelWindow::AddFrameRenderedCallback( DevelWindow::Get( Self() ),
+ std::unique_ptr< CallbackBase >( MakeCallback( this, &VideoView::FrameRenderCallback ) ), mFrameID );
+}
+
} // namespace Internal
} // namespace toolkit
#include <dali/public-api/rendering/texture.h>
#include <dali/devel-api/adaptor-framework/video-player.h>
#include <dali/integration-api/adaptor-framework/trigger-event-factory.h>
+#include <dali/devel-api/adaptor-framework/video-sync-mode.h>
// INTERNAL INCLUDES
#include <dali-toolkit/public-api/controls/control-impl.h>
{
protected:
- VideoView();
+ VideoView( Dali::VideoSyncMode syncMode );
virtual ~VideoView();
public:
/**
- * @copydoc Toolkit::VideoView::New()
+ * @copydoc Toolkit::DevelVideoView::New()
*/
- static Toolkit::VideoView New();
+ static Toolkit::VideoView New( VideoSyncMode syncMode );
/**
* @brief Sets a video url to play.
*/
Any GetMediaPlayer();
+ /**
+ * @brief Play the resize or move animation with synchronization between UI(transparent hole) and video player
+ *
+ * The resize and move animation's play() function is called.
+ * If the animation is played, UI and video player will work synchronization.
+ *
+ * @param[in] videoView The current VideoView
+ * @param[in] animation The animation for video view's resize or move.
+ */
+ void PlayAnimation( Dali::Animation animation );
+
private: // From Control
/**
virtual void OnStageDisconnection();
/**
+ * @copydoc Toolkit::Control::OnSizeSet()
+ */
+ virtual void OnSizeSet( const Vector3& targetSize );
+
+ /**
* @copydoc Toolkit::Control::GetNaturalSize
*/
virtual Vector3 GetNaturalSize();
*/
void ApplyBackupProperties();
+ /*
+ * @brief FrameRender's callback function
+ *
+ * This function means the resize/move animation is finished,
+ * so Ui and video player's synchronization can be finished.
+ *
+ */
+ void FrameRenderCallback( int frameID );
+
+ /*
+ * @brief Set frameRender Callback function
+ *
+ * This function is added for listenr the resize/move animation is finished,
+ *
+ */
+ void SetFrameRenderCallback();
+
+
+ /*
+ * @brief resize/move animation finished callback function
+ *
+ * This function is called the resize/move animation is finished,
+ *
+ */
+ void OnAnimationFinished( Dali::Animation& animation );
+
private:
Dali::VideoPlayer mVideoPlayer;
Dali::Property::Map mPropertyBackup;
int mCurrentVideoPlayPosition;
+ int mFrameID;
+
bool mIsPlay;
bool mIsUnderlay;
+
+ Dali::VideoSyncMode mSyncMode;
};
} // namespace Internal
// EXTERNAL INCLUDES
#include <dali/public-api/object/property-map.h>
+#include <dali/devel-api/adaptor-framework/video-sync-mode.h>
// INTERNAL INCLUDES
#include <dali-toolkit/internal/controls/video-view/video-view-impl.h>
VideoView VideoView::New()
{
- return Internal::VideoView::New();
+ return Internal::VideoView::New( Dali::VideoSyncMode::DISABLED );
}
VideoView VideoView::New( const std::string& url )
{
- VideoView videoView = Internal::VideoView::New();
+ VideoView videoView = Internal::VideoView::New( Dali::VideoSyncMode::DISABLED );
Dali::Toolkit::GetImpl( videoView ).SetUrl( url );
return videoView;
}
VideoView VideoView::New( bool swCodec )
{
- VideoView videoView = Internal::VideoView::New();
+ VideoView videoView = Internal::VideoView::New( Dali::VideoSyncMode::DISABLED );
Dali::Toolkit::GetImpl( videoView ).SetSWCodec( swCodec );
return videoView;
}
VideoView VideoView::New( const std::string& url, bool swCodec )
{
- VideoView videoView = Internal::VideoView::New();
+ VideoView videoView = Internal::VideoView::New( Dali::VideoSyncMode::DISABLED );
Dali::Toolkit::GetImpl( videoView ).SetUrl( url );
Dali::Toolkit::GetImpl( videoView ).SetSWCodec( swCodec );
return videoView;