Fix compile error. Non initialized variable.
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / controls / video-view / video-view-impl.cpp
old mode 100755 (executable)
new mode 100644 (file)
index 1e6da13..463a214
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2020 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.
 #include <cstring>
 #include <dali/public-api/object/type-registry.h>
 #include <dali/public-api/object/type-registry-helper.h>
-#include <dali/public-api/common/stage.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/adaptors/adaptor.h>
 #include <dali/integration-api/debug.h>
 #include <dali/public-api/animation/constraint.h>
 #include <dali/devel-api/actors/actor-devel.h>
 
 // INTERNAL INCLUDES
 #include <dali-toolkit/public-api/controls/video-view/video-view.h>
-#include <dali-toolkit/public-api/visuals/visual-properties.h>
-#include <dali-toolkit/devel-api/visual-factory/visual-factory.h>
-#include <dali-toolkit/internal/visuals/visual-string-constants.h>
-#include <dali-toolkit/internal/visuals/visual-base-impl.h>
-#include <dali-toolkit/internal/visuals/visual-factory-impl.h>
 #include <dali-toolkit/internal/visuals/visual-factory-cache.h>
+#include <dali/integration-api/adaptor-framework/adaptor.h>
 
 namespace Dali
 {
@@ -84,9 +79,15 @@ const char* const RENDERING_TARGET( "renderingTarget" );
 const char* const WINDOW_SURFACE_TARGET( "windowSurfaceTarget" );
 const char* const NATIVE_IMAGE_TARGET( "nativeImageTarget" );
 
+const char* const CUSTOM_SHADER( "shader" );
+const char* const CUSTOM_VERTEX_SHADER( "vertexShader" );
+const char* const CUSTOM_FRAGMENT_SHADER( "fragmentShader" );
+const char* const DEFAULT_SAMPLER_TYPE_NAME( "sampler2D" );
+const char* const CUSTOM_SAMPLER_TYPE_NAME( "samplerExternalOES" );
+
 const char* VERTEX_SHADER = DALI_COMPOSE_SHADER(
   attribute mediump vec2 aPosition;\n
-  uniform mediump mat4 uMvpMatrix;\n
+  uniform highp   mat4 uMvpMatrix;\n
   uniform mediump vec3 uSize;\n
   \n
   void main()\n
@@ -98,59 +99,71 @@ const char* VERTEX_SHADER = DALI_COMPOSE_SHADER(
 );
 
 const char* FRAGMENT_SHADER = DALI_COMPOSE_SHADER(
-  uniform lowp vec4 uColor;\n
-  uniform lowp vec3 mixColor;\n
   \n
   void main()\n
   {\n
-    gl_FragColor = vec4(mixColor, 1.0)*uColor;\n
+    gl_FragColor = vec4(0.0);\n
+  }\n
+);
+
+const char* VERTEX_SHADER_TEXTURE = DALI_COMPOSE_SHADER(
+  attribute mediump vec2 aPosition;\n
+  varying mediump vec2 vTexCoord;\n
+  uniform highp   mat4 uMvpMatrix;\n
+  uniform mediump vec3 uSize;\n
+  varying mediump vec2 sTexCoordRect;\n
+  void main()\n
+  {\n
+    gl_Position = uMvpMatrix * vec4(aPosition * uSize.xy, 0.0, 1.0);\n
+    vTexCoord = aPosition + vec2(0.5);\n
+  }\n
+);
+
+const char* FRAGMENT_SHADER_TEXTURE = DALI_COMPOSE_SHADER(
+  uniform lowp vec4 uColor;\n
+  varying mediump vec2 vTexCoord;\n
+  uniform samplerExternalOES sTexture;\n
+  void main()\n
+  {\n
+    gl_FragColor = texture2D( sTexture, vTexCoord ) * uColor;\n
   }\n
 );
 
 } // 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;
 }
 
 void VideoView::OnInitialize()
 {
   mVideoPlayer.FinishedSignal().Connect( this, &VideoView::EmitSignalFinish );
-  SetWindowSurfaceTarget();
 }
 
 void VideoView::SetUrl( const std::string& url )
 {
-  if( mUrl != url || !mPropertyMap.Empty() )
-  {
     mUrl = url;
     mPropertyMap.Clear();
-  }
-
-  if( !mIsUnderlay )
-  {
-    Actor self( Self() );
-    Internal::InitializeVisual( self, mVisual, mNativeImage );
-  }
 
   mVideoPlayer.SetUrl( mUrl );
 }
@@ -159,29 +172,6 @@ void VideoView::SetPropertyMap( Property::Map map )
 {
   mPropertyMap = map;
 
-  Actor self( Self() );
-  Internal::InitializeVisual( self, mVisual, mPropertyMap );
-
-  Property::Value* widthValue = mPropertyMap.Find( "width" );
-  if( widthValue )
-  {
-    int width;
-    if( widthValue->Get( width ) )
-    {
-      mVideoSize = ImageDimensions( width, mVideoSize.GetHeight() );
-    }
-  }
-
-  Property::Value* heightValue = mPropertyMap.Find( "height" );
-  if( heightValue )
-  {
-    int height;
-    if( heightValue->Get( height ) )
-    {
-      mVideoSize = ImageDimensions( mVideoSize.GetWidth(), height );
-    }
-  }
-
   Property::Value* target = map.Find( RENDERING_TARGET );
   std::string targetType;
 
@@ -196,6 +186,28 @@ void VideoView::SetPropertyMap( Property::Map map )
     SetNativeImageTarget();
   }
 
+  // Custom shader
+  Property::Value* shaderValue;
+  if( !map.Empty() )
+  {
+    shaderValue = map.Find( CUSTOM_SHADER );
+
+    if( shaderValue )
+    {
+      Property::Map* shaderMap = shaderValue->GetMap();
+      if( shaderMap )
+      {
+        mEffectPropertyMap = *shaderMap;
+      }
+    }
+  }
+
+  if( mTextureRenderer && !mEffectPropertyMap.Empty() )
+  {
+    Dali::Shader shader = CreateShader();
+    mTextureRenderer.SetShader( shader );
+  }
+
   RelayoutRequest();
 }
 
@@ -204,7 +216,7 @@ std::string VideoView::GetUrl()
   return mUrl;
 }
 
-void VideoView::SetLooping(bool looping)
+void VideoView::SetLooping( bool looping )
 {
   mVideoPlayer.SetLooping( looping );
 }
@@ -216,9 +228,9 @@ bool VideoView::IsLooping()
 
 void VideoView::Play()
 {
-  if( mIsUnderlay )
+  if( mOverlayRenderer )
   {
-    Self().AddRenderer( mRenderer );
+    Self().AddRenderer( mOverlayRenderer );
   }
 
   mVideoPlayer.Play();
@@ -283,9 +295,9 @@ Dali::Toolkit::VideoView::VideoViewSignalType& VideoView::FinishedSignal()
 
 void VideoView::EmitSignalFinish()
 {
-  if( mIsUnderlay )
+  if( mOverlayRenderer )
   {
-    Self().RemoveRenderer( mRenderer );
+    Self().RemoveRenderer( mOverlayRenderer );
   }
 
   if ( !mFinishedSignal.Empty() )
@@ -366,110 +378,103 @@ bool VideoView::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface*
   return connected;
 }
 
-void VideoView::SetProperty( BaseObject* object, Property::Index index, const Property::Value& value )
+void VideoView::SetPropertyInternal( Property::Index index, const Property::Value& value )
 {
-  Toolkit::VideoView videoView = Toolkit::VideoView::DownCast( Dali::BaseHandle( object ) );
-
-  if( videoView )
+  switch( index )
   {
-    VideoView& impl = GetImpl( videoView );
-
-    switch( index )
+    case Toolkit::VideoView::Property::VIDEO:
     {
-      case Toolkit::VideoView::Property::VIDEO:
-      {
-        std::string videoUrl;
-        Property::Map map;
+      std::string videoUrl;
+      Property::Map map;
 
-        if( value.Get( videoUrl ) )
-        {
-          impl.SetUrl( videoUrl );
-        }
-        else if( value.Get( map ) )
-        {
-          Property::Value* shaderValue = map.Find( Toolkit::Visual::Property::SHADER, CUSTOM_SHADER );
-
-          if( map.Count() > 1u || !shaderValue )
-          {
-            impl.SetPropertyMap( map );
-          }
-          else if( impl.mVisual && map.Count() == 1u && shaderValue )
-          {
-            Property::Map shaderMap;
-            if( shaderValue->Get( shaderMap ) )
-            {
-              Internal::Visual::Base& visual = Toolkit::GetImplementation( impl.mVisual );
-              visual.SetCustomShader( shaderMap );
-              if( videoView.OnStage() )
-              {
-                visual.SetOffStage( videoView );
-                visual.SetOnStage( videoView );
-              }
-            }
-          }
-        }
-        break;
+      if( value.Get( videoUrl ) )
+      {
+        SetUrl( videoUrl );
       }
-      case Toolkit::VideoView::Property::LOOPING:
+      else if( value.Get( map ) )
       {
-        bool looping;
-        if( value.Get( looping ) )
-        {
-          impl.SetLooping( looping );
-        }
-        break;
+        SetPropertyMap( map );
       }
-      case Toolkit::VideoView::Property::MUTED:
+      break;
+    }
+    case Toolkit::VideoView::Property::LOOPING:
+    {
+      bool looping;
+      if( value.Get( looping ) )
       {
-        bool mute;
-        if( value.Get( mute ) )
-        {
-          impl.SetMute( mute );
-        }
-        break;
+        SetLooping( looping );
       }
-      case Toolkit::VideoView::Property::VOLUME:
+      break;
+    }
+    case Toolkit::VideoView::Property::MUTED:
+    {
+      bool mute;
+      if( value.Get( mute ) )
       {
-        Property::Map map;
-        float left, right;
-        if( value.Get( map ) )
-        {
-          Property::Value* volumeLeft = map.Find( VOLUME_LEFT );
-          Property::Value* volumeRight = map.Find( VOLUME_RIGHT );
-          if( volumeLeft && volumeLeft->Get( left ) && volumeRight && volumeRight->Get( right ) )
-          {
-            impl.SetVolume( left, right );
-          }
-        }
-        break;
+        SetMute( mute );
       }
-      case Toolkit::VideoView::Property::UNDERLAY:
+      break;
+    }
+    case Toolkit::VideoView::Property::VOLUME:
+    {
+      Property::Map map;
+      float left, right;
+      if( value.Get( map ) )
       {
-        bool underlay;
-        if( value.Get( underlay ) )
+        Property::Value* volumeLeft = map.Find( VOLUME_LEFT );
+        Property::Value* volumeRight = map.Find( VOLUME_RIGHT );
+        if( volumeLeft && volumeLeft->Get( left ) && volumeRight && volumeRight->Get( right ) )
         {
-          impl.SetUnderlay( underlay );
+          SetVolume( left, right );
         }
-        break;
       }
-      case Toolkit::VideoView::Property::PLAY_POSITION:
+      break;
+    }
+    case Toolkit::VideoView::Property::UNDERLAY:
+    {
+      bool underlay;
+      if( value.Get( underlay ) )
       {
-        int pos;
-        if( value.Get( pos ) )
-        {
-          impl.SetPlayPosition( pos );
-        }
-        break;
+        SetUnderlay( underlay );
       }
-      case Toolkit::VideoView::Property::DISPLAY_MODE:
+      break;
+    }
+    case Toolkit::VideoView::Property::PLAY_POSITION:
+    {
+      int pos;
+      if( value.Get( pos ) )
       {
-        int mode;
-        if( value.Get( mode ) )
-        {
-          impl.SetDisplayMode( mode );
-        }
-        break;
+        SetPlayPosition( pos );
+      }
+      break;
+    }
+    case Toolkit::VideoView::Property::DISPLAY_MODE:
+    {
+      int mode;
+      if( value.Get( mode ) )
+      {
+        SetDisplayMode( mode );
       }
+      break;
+    }
+  }
+}
+
+void VideoView::SetProperty( BaseObject* object, Property::Index index, const Property::Value& value )
+{
+  Toolkit::VideoView videoView = Toolkit::VideoView::DownCast( Dali::BaseHandle( object ) );
+
+  if( videoView )
+  {
+    VideoView& impl = GetImpl( videoView );
+
+    impl.SetPropertyInternal( index, value );
+
+    if( index != Toolkit::VideoView::Property::UNDERLAY )
+    {
+      // Backup values.
+      // These values will be used when underlay mode is changed.
+      impl.mPropertyBackup[index] = value;
     }
   }
 }
@@ -541,32 +546,35 @@ Property::Value VideoView::GetProperty( BaseObject* object, Property::Index prop
 
 void VideoView::SetDepthIndex( int depthIndex )
 {
-  if( mVisual )
+  if( mTextureRenderer )
   {
-    mVisual.SetDepthIndex( depthIndex );
+    mTextureRenderer.SetProperty( Renderer::Property::DEPTH_INDEX, depthIndex );
   }
 }
 
-void VideoView::OnStageConnection( int depth )
+void VideoView::OnSceneConnection( int depth )
 {
-  if( mVisual )
+  Control::OnSceneConnection( depth );
+
+  if( mIsUnderlay )
   {
-    CustomActor self = Self();
-    Toolkit::GetImplementation(mVisual).SetOnStage( self );
+    SetWindowSurfaceTarget();
   }
+}
 
-  Control::OnStageConnection( depth );
+void VideoView::OnSceneDisconnection()
+{
+  Control::OnSceneDisconnection();
 }
 
-void VideoView::OnStageDisconnection()
+void VideoView::OnSizeSet( const Vector3& targetSize )
 {
-  if( mVisual )
+  if( mIsUnderlay && mSyncMode == Dali::VideoSyncMode::ENABLED )
   {
-    CustomActor self = Self();
-    Toolkit::GetImplementation(mVisual).SetOffStage( self );
+    SetFrameRenderCallback();
+    mVideoPlayer.StartSynchronization();
   }
-
-  Control::OnStageDisconnection();
+  Control::OnSizeSet( targetSize );
 }
 
 Vector3 VideoView::GetNaturalSize()
@@ -613,14 +621,15 @@ float VideoView::GetWidthForHeight( float height )
 void VideoView::SetWindowSurfaceTarget()
 {
   Actor self = Self();
-  int curPos = mVideoPlayer.GetPlayPosition();
 
-  if( mVisual )
+  if( !self.GetProperty< bool >( Actor::Property::CONNECTED_TO_SCENE ) )
   {
-    Toolkit::GetImplementation(mVisual).SetOffStage(self);
-    mVisual.Reset();
+    // When the control is off the stage, it does not have Window.
+    return;
   }
 
+  int curPos = mVideoPlayer.GetPlayPosition();
+
   if( mIsPlay )
   {
     mVideoPlayer.Pause();
@@ -633,21 +642,23 @@ void VideoView::SetWindowSurfaceTarget()
   mSizeUpdateNotification.NotifySignal().Connect( this, &VideoView::UpdateDisplayArea );
   mScaleUpdateNotification.NotifySignal().Connect( this, &VideoView::UpdateDisplayArea );
 
-  mVideoPlayer.SetRenderingTarget( Dali::Adaptor::Get().GetNativeWindowHandle() );
-  mVideoPlayer.SetUrl( mUrl );
+  if( mTextureRenderer )
+  {
+    self.RemoveRenderer( mTextureRenderer );
+  }
+
+  // Note VideoPlayer::SetRenderingTarget resets all the options. (e.g. url, mute, looping)
+  mVideoPlayer.SetRenderingTarget( Dali::Adaptor::Get().GetNativeWindowHandle( self ) );
 
-  if( !mRenderer )
+  ApplyBackupProperties();
+
+  if( !mOverlayRenderer )
   {
     // For underlay rendering mode, video display area have to be transparent.
     Geometry geometry = VisualFactoryCache::CreateQuadGeometry();
     Shader shader = Shader::New( VERTEX_SHADER, FRAGMENT_SHADER );
-    mRenderer = Renderer::New( geometry, shader );
-
-    mRenderer.SetProperty( Renderer::Property::BLEND_MODE, BlendMode::ON );
-    mRenderer.SetProperty( Renderer::Property::BLEND_FACTOR_SRC_RGB, BlendFactor::ONE );
-    mRenderer.SetProperty( Renderer::Property::BLEND_FACTOR_DEST_RGB, BlendFactor::ZERO );
-    mRenderer.SetProperty( Renderer::Property::BLEND_FACTOR_SRC_ALPHA, BlendFactor::ONE );
-    mRenderer.SetProperty( Renderer::Property::BLEND_FACTOR_DEST_ALPHA, BlendFactor::ZERO );
+    mOverlayRenderer = Renderer::New( geometry, shader );
+    mOverlayRenderer.SetProperty( Renderer::Property::BLEND_MODE, BlendMode::OFF );
   }
 
   if( mIsPlay )
@@ -676,8 +687,13 @@ void VideoView::SetNativeImageTarget()
   }
 
   Actor self( Self() );
-  self.RemoveRenderer( mRenderer );
-  Dali::Stage::GetCurrent().KeepRendering( 0.0f );
+
+  if( mOverlayRenderer )
+  {
+    self.RemoveRenderer( mOverlayRenderer );
+
+    mOverlayRenderer.Reset();
+  }
 
   self.RemovePropertyNotification( mPositionUpdateNotification );
   self.RemovePropertyNotification( mSizeUpdateNotification );
@@ -687,13 +703,29 @@ void VideoView::SetNativeImageTarget()
 
   Any source;
   Dali::NativeImageSourcePtr nativeImageSourcePtr = Dali::NativeImageSource::New( source );
-  mNativeImage = Dali::NativeImage::New( *nativeImageSourcePtr );
+  mNativeTexture = Dali::Texture::New( *nativeImageSourcePtr );
+
+  if( !mTextureRenderer )
+  {
+    Dali::Geometry geometry = VisualFactoryCache::CreateQuadGeometry();
+    Dali::Shader shader = CreateShader();
+    Dali::TextureSet textureSet = Dali::TextureSet::New();
+    textureSet.SetTexture( 0u, mNativeTexture );
+
+    mTextureRenderer = Renderer::New( geometry, shader );
+    mTextureRenderer.SetTextures( textureSet );
+  }
+  else
+  {
+    Dali::TextureSet textureSet = mTextureRenderer.GetTextures();
+    textureSet.SetTexture( 0u, mNativeTexture );
+  }
+  Self().AddRenderer( mTextureRenderer );
 
+  // Note VideoPlayer::SetRenderingTarget resets all the options. (e.g. url, mute, looping)
   mVideoPlayer.SetRenderingTarget( nativeImageSourcePtr );
-  mVideoPlayer.SetUrl( mUrl );
 
-  Internal::InitializeVisual( self, mVisual, mNativeImage );
-  Self().RemoveRenderer( mRenderer );
+  ApplyBackupProperties();
 
   if( mIsPlay )
   {
@@ -708,18 +740,20 @@ void VideoView::SetNativeImageTarget()
 
 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;
   }
 
   Actor self( Self() );
 
-  bool positionUsesAnchorPoint = self.GetProperty( DevelActor::Property::POSITION_USES_ANCHOR_POINT ).Get< bool >();
-  Vector3 actorSize = self.GetCurrentSize() * self.GetCurrentScale();
-  Vector3 anchorPointOffSet = actorSize * ( positionUsesAnchorPoint ? self.GetCurrentAnchorPoint() : AnchorPoint::TOP_LEFT );
+  bool positionUsesAnchorPoint = self.GetProperty( Actor::Property::POSITION_USES_ANCHOR_POINT ).Get< bool >();
+  Vector3 actorSize = self.GetCurrentProperty< Vector3 >( Actor::Property::SIZE ) * self.GetCurrentProperty< Vector3 >( Actor::Property::SCALE );
+  Vector3 anchorPointOffSet = actorSize * ( positionUsesAnchorPoint ? self.GetCurrentProperty< Vector3 >( Actor::Property::ANCHOR_POINT ) : AnchorPoint::TOP_LEFT );
 
-  Vector2 screenPosition = self.GetProperty( DevelActor::Property::SCREEN_POSITION ).Get< Vector2 >();
+  Vector2 screenPosition = self.GetProperty( Actor::Property::SCREEN_POSITION ).Get< Vector2 >();
 
   mDisplayArea.x = screenPosition.x - anchorPointOffSet.x;
   mDisplayArea.y = screenPosition.y - anchorPointOffSet.y;
@@ -787,6 +821,113 @@ int VideoView::GetDisplayMode() const
   return static_cast< int >( mVideoPlayer.GetDisplayMode() );
 }
 
+Any VideoView::GetMediaPlayer()
+{
+  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";
+  std::string vertexShader;
+  std::string customFragmentShader;
+  bool checkShader = false;
+
+  if( !mEffectPropertyMap.Empty() )
+  {
+    Property::Value* vertexShaderValue = mEffectPropertyMap.Find( CUSTOM_VERTEX_SHADER );
+    if( vertexShaderValue )
+    {
+      checkShader = GetStringFromProperty( *vertexShaderValue, vertexShader );
+    }
+
+    if( !vertexShaderValue || !checkShader )
+    {
+      vertexShader = VERTEX_SHADER_TEXTURE;
+    }
+
+    Property::Value* fragmentShaderValue = mEffectPropertyMap.Find( CUSTOM_FRAGMENT_SHADER );
+    if( fragmentShaderValue )
+    {
+      checkShader = GetStringFromProperty( *fragmentShaderValue, customFragmentShader );
+
+      if( checkShader )
+      {
+        fragmentShader = customFragmentShader;
+      }
+    }
+
+    if( !fragmentShaderValue || !checkShader )
+    {
+      fragmentShader += FRAGMENT_SHADER_TEXTURE;
+    }
+  }
+  else
+  {
+    vertexShader = VERTEX_SHADER_TEXTURE;
+    fragmentShader += FRAGMENT_SHADER_TEXTURE;
+  }
+
+  return Dali::Shader::New( vertexShader, fragmentShader );
+}
+
+bool VideoView::GetStringFromProperty( const Dali::Property::Value& value, std::string& output )
+{
+  bool extracted = false;
+  if( value.Get( output ) )
+  {
+    extracted = true;
+  }
+
+  return extracted;
+}
+
+void VideoView::ApplyBackupProperties()
+{
+  Property::Map::SizeType pos = 0;
+  Property::Map::SizeType count = mPropertyBackup.Count();
+
+  for( ; pos < count; pos++ )
+  {
+    KeyValuePair property = mPropertyBackup.GetKeyValue( pos );
+
+    SetPropertyInternal( property.first.indexKey, property.second );
+  }
+}
+
+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