Merge "Fix doc and comment for Native API Reference page" into devel/master
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / controls / video-view / video-view-impl.cpp
index 0dd7e1c..5834950 100644 (file)
@@ -26,6 +26,9 @@
 #include <dali/devel-api/scripting/scripting.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>
@@ -33,6 +36,8 @@
 #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>
 
 namespace Dali
 {
@@ -57,6 +62,7 @@ DALI_PROPERTY_REGISTRATION( Toolkit, VideoView, "video", MAP, VIDEO )
 DALI_PROPERTY_REGISTRATION( Toolkit, VideoView, "looping", BOOLEAN, LOOPING )
 DALI_PROPERTY_REGISTRATION( Toolkit, VideoView, "muted", BOOLEAN, MUTED )
 DALI_PROPERTY_REGISTRATION( Toolkit, VideoView, "volume", MAP, VOLUME )
+DALI_PROPERTY_REGISTRATION( Toolkit, VideoView, "underlay", BOOLEAN, UNDERLAY )
 
 DALI_SIGNAL_REGISTRATION( Toolkit, VideoView, "finished", FINISHED_SIGNAL )
 
@@ -70,24 +76,78 @@ DALI_TYPE_REGISTRATION_END()
 
 const char* const VOLUME_LEFT( "volumeLeft" );
 const char* const VOLUME_RIGHT( "volumeRight" );
+
+// 3.0 TC uses RENDERING_TARGET. It should be removed in next release
 const char* const RENDERING_TARGET( "renderingTarget" );
 const char* const WINDOW_SURFACE_TARGET( "windowSurfaceTarget" );
 const char* const NATIVE_IMAGE_TARGET( "nativeImageTarget" );
 
+const char* VERTEX_SHADER = DALI_COMPOSE_SHADER(
+  attribute mediump vec2 aPosition;\n
+  uniform mediump mat4 uMvpMatrix;\n
+  uniform mediump vec3 uSize;\n
+  \n
+  void main()\n
+  {\n
+    mediump vec4 vertexPosition = vec4(aPosition, 0.0, 1.0);\n
+    vertexPosition.xyz *= uSize;\n
+    gl_Position = uMvpMatrix * vertexPosition;\n
+  }\n
+);
+
+const char* FRAGMENT_SHADER = DALI_COMPOSE_SHADER(
+  uniform lowp vec4 uColor;\n
+  uniform lowp vec3 mixColor;\n
+  uniform lowp float opacity;\n
+  \n
+  void main()\n
+  {\n
+    gl_FragColor = vec4(mixColor, opacity)*uColor;\n
+  }\n
+);
+
+struct TriggerFunctor
+{
+  TriggerFunctor( TriggerEventInterface* notification )
+  : mNotification( notification )
+  {
+  }
+
+  void operator()( bool& current, const PropertyInputContainer& inputs )
+  {
+    if( mNotification != NULL )
+    {
+      mNotification->Trigger();
+    }
+  }
+
+  TriggerEventInterface* mNotification;
+};
+
 } // anonymous namepsace
 
 VideoView::VideoView()
 : Control( ControlBehaviour( ACTOR_BEHAVIOUR_DEFAULT | DISABLE_STYLE_CHANGE_SIGNALS ) ),
+  mUpdateTriggerPropertyIndex( Property::INVALID_INDEX),
+  mNotification( NULL ),
   mCurrentVideoPlayPosition( 0 ),
-  mIsNativeImageTarget( true ),
   mIsPlay( false ),
-  mIsPause( false )
+  mIsPause( false ),
+  mIsUnderlay( true )
 {
   mVideoPlayer = Dali::VideoPlayer::New();
+
+  TriggerEventFactory triggerEventFactory;
+  mNotification = triggerEventFactory.CreateTriggerEvent( MakeCallback(this, &VideoView::UpdateDisplayArea ),
+                                                               TriggerEventInterface::KEEP_ALIVE_AFTER_TRIGGER);
 }
 
 VideoView::~VideoView()
 {
+  if( mNotification != NULL )
+  {
+    delete mNotification;
+  }
 }
 
 Toolkit::VideoView VideoView::New()
@@ -102,12 +162,9 @@ Toolkit::VideoView VideoView::New()
 
 void VideoView::OnInitialize()
 {
-  Any source;
-  Dali::NativeImageSourcePtr nativeImageSourcePtr = Dali::NativeImageSource::New( source );
-  mNativeImage = Dali::NativeImage::New( *nativeImageSourcePtr );
-
-  mVideoPlayer.SetRenderingTarget( nativeImageSourcePtr );
+  mUpdateTriggerPropertyIndex = Self().RegisterProperty( "updateTrigger", true );
   mVideoPlayer.FinishedSignal().Connect( this, &VideoView::EmitSignalFinish );
+  SetWindowSurfaceTarget();
 }
 
 void VideoView::SetUrl( const std::string& url )
@@ -118,7 +175,7 @@ void VideoView::SetUrl( const std::string& url )
     mPropertyMap.Clear();
   }
 
-  if( mIsNativeImageTarget )
+  if( !mIsUnderlay )
   {
     Actor self( Self() );
     Internal::InitializeVisual( self, mVisual, mNativeImage );
@@ -159,11 +216,13 @@ void VideoView::SetPropertyMap( Property::Map map )
 
   if( target && target->Get( targetType ) && targetType == WINDOW_SURFACE_TARGET )
   {
-    this->SetWindowSurfaceTarget();
+    mIsUnderlay = true;
+    SetWindowSurfaceTarget();
   }
   else if( target && target->Get( targetType ) && targetType == NATIVE_IMAGE_TARGET )
   {
-    this->SetNativeImageTarget();
+    mIsUnderlay = false;
+    SetNativeImageTarget();
   }
 
   RelayoutRequest();
@@ -406,6 +465,15 @@ void VideoView::SetProperty( BaseObject* object, Property::Index index, const Pr
         }
         break;
       }
+      case Toolkit::VideoView::Property::UNDERLAY:
+      {
+        bool underlay;
+        if( value.Get( underlay ) )
+        {
+          impl.SetUnderlay( underlay );
+        }
+        break;
+      }
     }
   }
 }
@@ -454,6 +522,11 @@ Property::Value VideoView::GetProperty( BaseObject* object, Property::Index prop
         value = map;
         break;
       }
+      case Toolkit::VideoView::Property::UNDERLAY:
+      {
+        value = impl.IsUnderlay();
+        break;
+      }
     }
   }
 
@@ -542,10 +615,30 @@ void VideoView::SetWindowSurfaceTarget()
     mVisual.Reset();
   }
 
+  Constraint constraint = Constraint::New<bool>( self, mUpdateTriggerPropertyIndex, TriggerFunctor( mNotification ) );
+  constraint.AddSource( Source( self, Actor::Property::POSITION ) );
+  constraint.AddSource( Source( self, Actor::Property::SIZE ) );
+  constraint.Apply();
+
   mVideoPlayer.SetRenderingTarget( Dali::Adaptor::Get().GetNativeWindowHandle() );
   mVideoPlayer.SetUrl( mUrl );
 
-  mIsNativeImageTarget = false;
+  if( !mRenderer )
+  {
+    // 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 );
+  }
+  self.AddRenderer( mRenderer );
+
+  UpdateDisplayArea();
 
   if( mIsPlay )
   {
@@ -556,11 +649,22 @@ void VideoView::SetWindowSurfaceTarget()
     mVideoPlayer.Play();
     mVideoPlayer.Pause();
   }
-  mVideoPlayer.SetPlayPosition( curPos );
+
+  if( curPos > 0 )
+  {
+    mVideoPlayer.SetPlayPosition( curPos );
+  }
 }
 
 void VideoView::SetNativeImageTarget()
 {
+  if( mVideoPlayer.IsVideoTextureSupported() == false )
+  {
+    DALI_LOG_ERROR( "Platform doesn't support decoded video frame images\n" );
+    mIsUnderlay = true;
+    return;
+  }
+
   Actor self( Self() );
   int curPos = mVideoPlayer.GetPlayPosition();
 
@@ -572,7 +676,7 @@ void VideoView::SetNativeImageTarget()
   mVideoPlayer.SetUrl( mUrl );
 
   Internal::InitializeVisual( self, mVisual, mNativeImage );
-  mIsNativeImageTarget = true;
+  Self().RemoveRenderer( mRenderer );
 
   if( mIsPlay )
   {
@@ -584,11 +688,59 @@ void VideoView::SetNativeImageTarget()
     mVideoPlayer.Play();
     mVideoPlayer.Pause();
   }
-  mVideoPlayer.SetPlayPosition( curPos );
+  if( curPos > 0 )
+  {
+    mVideoPlayer.SetPlayPosition( curPos );
+  }
+}
+
+void VideoView::UpdateDisplayArea()
+{
+  if( !mIsUnderlay )
+  {
+    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 );
+
+  Vector2 screenPosition = self.GetProperty( DevelActor::Property::SCREEN_POSITION ).Get< Vector2 >();
+
+  mDisplayArea.x = screenPosition.x - anchorPointOffSet.x;
+  mDisplayArea.y = screenPosition.y - anchorPointOffSet.y;
+  mDisplayArea.width = actorSize.x;
+  mDisplayArea.height = actorSize.y;
+
+  mVideoPlayer.SetDisplayArea( mDisplayArea );
+}
+
+void VideoView::SetUnderlay( bool set )
+{
+  if( set != mIsUnderlay )
+  {
+    mIsUnderlay = set;
+
+    if( mIsUnderlay )
+    {
+      SetWindowSurfaceTarget();
+    }
+    else
+    {
+      SetNativeImageTarget();
+    }
+  }
+}
+
+bool VideoView::IsUnderlay()
+{
+  return mIsUnderlay;
 }
 
 } // namespace Internal
 
-} // namespace Toolkit
+} // namespace toolkit
 
 } // namespace Dali