Merge "Change the precision of size and uSize from mediumP to highP" into devel/master
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / controls / video-view / video-view-impl.cpp
1 /*
2  * Copyright (c) 2020 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */
17
18 // CLASS HEADER
19 #include "video-view-impl.h"
20
21 // EXTERNAL INCLUDES
22 #include <cstring>
23 #include <dali/public-api/object/type-registry.h>
24 #include <dali/public-api/object/type-registry-helper.h>
25 #include <dali/devel-api/scripting/scripting.h>
26 #include <dali/devel-api/adaptor-framework/window-devel.h>
27 #include <dali/public-api/adaptor-framework/native-image-source.h>
28 #include <dali/integration-api/debug.h>
29 #include <dali/public-api/animation/constraint.h>
30 #include <dali/devel-api/actors/actor-devel.h>
31
32 // INTERNAL INCLUDES
33 #include <dali-toolkit/public-api/controls/video-view/video-view.h>
34 #include <dali-toolkit/internal/visuals/visual-factory-cache.h>
35 #include <dali/integration-api/adaptor-framework/adaptor.h>
36
37 namespace Dali
38 {
39
40 namespace Toolkit
41 {
42
43 namespace Internal
44 {
45
46 namespace
47 {
48
49 BaseHandle Create()
50 {
51   return Toolkit::VideoView::New();
52 }
53
54 DALI_TYPE_REGISTRATION_BEGIN( Toolkit::VideoView, Toolkit::Control, Create );
55
56 DALI_PROPERTY_REGISTRATION( Toolkit, VideoView, "video", MAP, VIDEO )
57 DALI_PROPERTY_REGISTRATION( Toolkit, VideoView, "looping", BOOLEAN, LOOPING )
58 DALI_PROPERTY_REGISTRATION( Toolkit, VideoView, "muted", BOOLEAN, MUTED )
59 DALI_PROPERTY_REGISTRATION( Toolkit, VideoView, "volume", MAP, VOLUME )
60 DALI_PROPERTY_REGISTRATION( Toolkit, VideoView, "underlay", BOOLEAN, UNDERLAY )
61 DALI_PROPERTY_REGISTRATION( Toolkit, VideoView, "playPosition", INTEGER, PLAY_POSITION )
62 DALI_PROPERTY_REGISTRATION( Toolkit, VideoView, "displayMode", INTEGER, DISPLAY_MODE )
63
64 DALI_SIGNAL_REGISTRATION( Toolkit, VideoView, "finished", FINISHED_SIGNAL )
65
66 DALI_ACTION_REGISTRATION( Toolkit, VideoView, "play", ACTION_VIDEOVIEW_PLAY )
67 DALI_ACTION_REGISTRATION( Toolkit, VideoView, "pause", ACTION_VIDEOVIEW_PAUSE )
68 DALI_ACTION_REGISTRATION( Toolkit, VideoView, "stop", ACTION_VIDEOVIEW_STOP )
69 DALI_ACTION_REGISTRATION( Toolkit, VideoView, "forward", ACTION_VIDEOVIEW_FORWARD )
70 DALI_ACTION_REGISTRATION( Toolkit, VideoView, "backward", ACTION_VIDEOVIEW_BACKWARD )
71
72 DALI_TYPE_REGISTRATION_END()
73
74 const char* const VOLUME_LEFT( "volumeLeft" );
75 const char* const VOLUME_RIGHT( "volumeRight" );
76
77 // 3.0 TC uses RENDERING_TARGET. It should be removed in next release
78 const char* const RENDERING_TARGET( "renderingTarget" );
79 const char* const WINDOW_SURFACE_TARGET( "windowSurfaceTarget" );
80 const char* const NATIVE_IMAGE_TARGET( "nativeImageTarget" );
81
82 const char* const CUSTOM_SHADER( "shader" );
83 const char* const CUSTOM_VERTEX_SHADER( "vertexShader" );
84 const char* const CUSTOM_FRAGMENT_SHADER( "fragmentShader" );
85 const char* const DEFAULT_SAMPLER_TYPE_NAME( "sampler2D" );
86 const char* const CUSTOM_SAMPLER_TYPE_NAME( "samplerExternalOES" );
87
88 const char* VERTEX_SHADER = DALI_COMPOSE_SHADER(
89   attribute mediump vec2 aPosition;\n
90   uniform highp   mat4 uMvpMatrix;\n
91   uniform highp   vec3 uSize;\n
92   \n
93   void main()\n
94   {\n
95     mediump vec4 vertexPosition = vec4(aPosition, 0.0, 1.0);\n
96     vertexPosition.xyz *= uSize;\n
97     gl_Position = uMvpMatrix * vertexPosition;\n
98   }\n
99 );
100
101 const char* FRAGMENT_SHADER = DALI_COMPOSE_SHADER(
102   \n
103   void main()\n
104   {\n
105     gl_FragColor = vec4(0.0);\n
106   }\n
107 );
108
109 const char* VERTEX_SHADER_TEXTURE = DALI_COMPOSE_SHADER(
110   attribute mediump vec2 aPosition;\n
111   varying mediump vec2 vTexCoord;\n
112   uniform highp   mat4 uMvpMatrix;\n
113   uniform highp   vec3 uSize;\n
114   varying mediump vec2 sTexCoordRect;\n
115   void main()\n
116   {\n
117     gl_Position = uMvpMatrix * vec4(aPosition * uSize.xy, 0.0, 1.0);\n
118     vTexCoord = aPosition + vec2(0.5);\n
119   }\n
120 );
121
122 const char* FRAGMENT_SHADER_TEXTURE = DALI_COMPOSE_SHADER(
123   uniform lowp vec4 uColor;\n
124   varying mediump vec2 vTexCoord;\n
125   uniform samplerExternalOES sTexture;\n
126   void main()\n
127   {\n
128     gl_FragColor = texture2D( sTexture, vTexCoord ) * uColor;\n
129   }\n
130 );
131
132 } // anonymous namepsace
133
134 VideoView::VideoView( Dali::VideoSyncMode syncMode )
135 : Control( ControlBehaviour( ACTOR_BEHAVIOUR_DEFAULT | DISABLE_STYLE_CHANGE_SIGNALS ) ),
136   mCurrentVideoPlayPosition( 0 ),
137   mFrameID( 0 ),
138   mIsPlay( false ),
139   mIsUnderlay( true ),
140   mSyncMode( syncMode )
141 {
142 }
143
144 VideoView::~VideoView()
145 {
146 }
147
148 Toolkit::VideoView VideoView::New( VideoSyncMode syncMode )
149 {
150   VideoView* impl = new VideoView( syncMode );
151   Toolkit::VideoView handle = Toolkit::VideoView( *impl );
152
153   impl->mVideoPlayer = Dali::VideoPlayer::New( impl->Self(), syncMode );
154   impl->Initialize();
155   return handle;
156 }
157
158 void VideoView::OnInitialize()
159 {
160   mVideoPlayer.FinishedSignal().Connect( this, &VideoView::EmitSignalFinish );
161 }
162
163 void VideoView::SetUrl( const std::string& url )
164 {
165     mUrl = url;
166     mPropertyMap.Clear();
167
168   mVideoPlayer.SetUrl( mUrl );
169 }
170
171 void VideoView::SetPropertyMap( Property::Map map )
172 {
173   mPropertyMap = map;
174
175   Property::Value* target = map.Find( RENDERING_TARGET );
176   std::string targetType;
177
178   if( target && target->Get( targetType ) && targetType == WINDOW_SURFACE_TARGET )
179   {
180     mIsUnderlay = true;
181     SetWindowSurfaceTarget();
182   }
183   else if( target && target->Get( targetType ) && targetType == NATIVE_IMAGE_TARGET )
184   {
185     mIsUnderlay = false;
186     SetNativeImageTarget();
187   }
188
189   // Custom shader
190   Property::Value* shaderValue;
191   if( !map.Empty() )
192   {
193     shaderValue = map.Find( CUSTOM_SHADER );
194
195     if( shaderValue )
196     {
197       Property::Map* shaderMap = shaderValue->GetMap();
198       if( shaderMap )
199       {
200         mEffectPropertyMap = *shaderMap;
201       }
202     }
203   }
204
205   if( mTextureRenderer && !mEffectPropertyMap.Empty() )
206   {
207     Dali::Shader shader = CreateShader();
208     mTextureRenderer.SetShader( shader );
209   }
210
211   RelayoutRequest();
212 }
213
214 std::string VideoView::GetUrl()
215 {
216   return mUrl;
217 }
218
219 void VideoView::SetLooping( bool looping )
220 {
221   mVideoPlayer.SetLooping( looping );
222 }
223
224 bool VideoView::IsLooping()
225 {
226   return mVideoPlayer.IsLooping();
227 }
228
229 void VideoView::Play()
230 {
231   if( mOverlayRenderer )
232   {
233     Self().AddRenderer( mOverlayRenderer );
234   }
235
236   mVideoPlayer.Play();
237   mIsPlay = true;
238 }
239
240 void VideoView::Pause()
241 {
242   mVideoPlayer.Pause();
243   mIsPlay = false;
244 }
245
246 void VideoView::Stop()
247 {
248   mVideoPlayer.Stop();
249   mIsPlay = false;
250 }
251
252 void VideoView::Forward( int millisecond )
253 {
254   int curPos = mVideoPlayer.GetPlayPosition();
255
256   int nextPos = curPos + millisecond;
257
258   mVideoPlayer.SetPlayPosition( nextPos );
259 }
260
261 void VideoView::Backward( int millisecond )
262 {
263   int curPos = mVideoPlayer.GetPlayPosition();
264
265   int nextPos = curPos - millisecond;
266   nextPos = ( nextPos < 0 )? 0: nextPos;
267
268   mVideoPlayer.SetPlayPosition( nextPos );
269 }
270
271 void VideoView::SetMute( bool mute )
272 {
273   mVideoPlayer.SetMute( mute );
274 }
275
276 bool VideoView::IsMuted()
277 {
278   return mVideoPlayer.IsMuted();
279 }
280
281 void VideoView::SetVolume( float left, float right )
282 {
283   mVideoPlayer.SetVolume( left, right );
284 }
285
286 void VideoView::GetVolume( float& left, float& right )
287 {
288   mVideoPlayer.GetVolume( left, right );
289 }
290
291 Dali::Toolkit::VideoView::VideoViewSignalType& VideoView::FinishedSignal()
292 {
293   return mFinishedSignal;
294 }
295
296 void VideoView::EmitSignalFinish()
297 {
298   if( mOverlayRenderer )
299   {
300     Self().RemoveRenderer( mOverlayRenderer );
301   }
302
303   if ( !mFinishedSignal.Empty() )
304   {
305     Dali::Toolkit::VideoView handle( GetOwner() );
306     mFinishedSignal.Emit( handle );
307   }
308 }
309
310 bool VideoView::DoAction( BaseObject* object, const std::string& actionName, const Property::Map& attributes )
311 {
312   bool ret = false;
313
314   Dali::BaseHandle handle( object );
315   Toolkit::VideoView videoView = Toolkit::VideoView::DownCast( handle );
316
317   if( !videoView )
318   {
319     return ret;
320   }
321
322   VideoView& impl = GetImpl( videoView );
323
324   if( strcmp( actionName.c_str(), ACTION_VIDEOVIEW_PLAY ) == 0 )
325   {
326     impl.Play();
327     ret = true;
328   }
329   else if( strcmp( actionName.c_str(), ACTION_VIDEOVIEW_PAUSE ) == 0 )
330   {
331     impl.Pause();
332     ret = true;
333   }
334   else if( strcmp( actionName.c_str(), ACTION_VIDEOVIEW_STOP ) == 0 )
335   {
336     impl.Stop();
337     ret = true;
338   }
339   else if( strcmp( actionName.c_str(), ACTION_VIDEOVIEW_FORWARD ) == 0 )
340   {
341     int millisecond = 0;
342     if( attributes["videoForward"].Get( millisecond ) )
343     {
344       impl.Forward( millisecond );
345       ret = true;
346     }
347   }
348   else if( strcmp( actionName.c_str(), ACTION_VIDEOVIEW_BACKWARD ) == 0 )
349   {
350     int millisecond = 0;
351     if( attributes["videoBackward"].Get( millisecond ) )
352     {
353       impl.Backward( millisecond );
354       ret = true;
355     }
356   }
357
358   return ret;
359 }
360
361 bool VideoView::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
362 {
363   Dali::BaseHandle handle( object );
364
365   bool connected( true );
366   Toolkit::VideoView videoView = Toolkit::VideoView::DownCast( handle );
367
368   if( 0 == strcmp( signalName.c_str(), FINISHED_SIGNAL ) )
369   {
370     videoView.FinishedSignal().Connect( tracker, functor );
371   }
372   else
373   {
374     // signalName does not match any signal
375     connected = false;
376   }
377
378   return connected;
379 }
380
381 void VideoView::SetPropertyInternal( Property::Index index, const Property::Value& value )
382 {
383   switch( index )
384   {
385     case Toolkit::VideoView::Property::VIDEO:
386     {
387       std::string videoUrl;
388       Property::Map map;
389
390       if( value.Get( videoUrl ) )
391       {
392         SetUrl( videoUrl );
393       }
394       else if( value.Get( map ) )
395       {
396         SetPropertyMap( map );
397       }
398       break;
399     }
400     case Toolkit::VideoView::Property::LOOPING:
401     {
402       bool looping;
403       if( value.Get( looping ) )
404       {
405         SetLooping( looping );
406       }
407       break;
408     }
409     case Toolkit::VideoView::Property::MUTED:
410     {
411       bool mute;
412       if( value.Get( mute ) )
413       {
414         SetMute( mute );
415       }
416       break;
417     }
418     case Toolkit::VideoView::Property::VOLUME:
419     {
420       Property::Map map;
421       float left, right;
422       if( value.Get( map ) )
423       {
424         Property::Value* volumeLeft = map.Find( VOLUME_LEFT );
425         Property::Value* volumeRight = map.Find( VOLUME_RIGHT );
426         if( volumeLeft && volumeLeft->Get( left ) && volumeRight && volumeRight->Get( right ) )
427         {
428           SetVolume( left, right );
429         }
430       }
431       break;
432     }
433     case Toolkit::VideoView::Property::UNDERLAY:
434     {
435       bool underlay;
436       if( value.Get( underlay ) )
437       {
438         SetUnderlay( underlay );
439       }
440       break;
441     }
442     case Toolkit::VideoView::Property::PLAY_POSITION:
443     {
444       int pos;
445       if( value.Get( pos ) )
446       {
447         SetPlayPosition( pos );
448       }
449       break;
450     }
451     case Toolkit::VideoView::Property::DISPLAY_MODE:
452     {
453       int mode;
454       if( value.Get( mode ) )
455       {
456         SetDisplayMode( mode );
457       }
458       break;
459     }
460   }
461 }
462
463 void VideoView::SetProperty( BaseObject* object, Property::Index index, const Property::Value& value )
464 {
465   Toolkit::VideoView videoView = Toolkit::VideoView::DownCast( Dali::BaseHandle( object ) );
466
467   if( videoView )
468   {
469     VideoView& impl = GetImpl( videoView );
470
471     impl.SetPropertyInternal( index, value );
472
473     if( index != Toolkit::VideoView::Property::UNDERLAY )
474     {
475       // Backup values.
476       // These values will be used when underlay mode is changed.
477       impl.mPropertyBackup[index] = value;
478     }
479   }
480 }
481
482 Property::Value VideoView::GetProperty( BaseObject* object, Property::Index propertyIndex )
483 {
484   Property::Value value;
485   Toolkit::VideoView videoView = Toolkit::VideoView::DownCast( Dali::BaseHandle( object ) );
486
487   if( videoView )
488   {
489     VideoView& impl = GetImpl( videoView );
490
491     switch( propertyIndex )
492     {
493       case Toolkit::VideoView::Property::VIDEO:
494       {
495         if( !impl.mUrl.empty() )
496         {
497           value = impl.mUrl;
498         }
499         else if( !impl.mPropertyMap.Empty() )
500         {
501           value = impl.mPropertyMap;
502         }
503         break;
504       }
505       case Toolkit::VideoView::Property::LOOPING:
506       {
507         value = impl.IsLooping();
508         break;
509       }
510       case Toolkit::VideoView::Property::MUTED:
511       {
512         value = impl.IsMuted();
513         break;
514       }
515       case Toolkit::VideoView::Property::VOLUME:
516       {
517         Property::Map map;
518         float left, right;
519
520         impl.GetVolume( left, right );
521         map.Insert( VOLUME_LEFT, left );
522         map.Insert( VOLUME_RIGHT, right );
523         value = map;
524         break;
525       }
526       case Toolkit::VideoView::Property::UNDERLAY:
527       {
528         value = impl.IsUnderlay();
529         break;
530       }
531       case Toolkit::VideoView::Property::PLAY_POSITION:
532       {
533         value = impl.GetPlayPosition();
534         break;
535       }
536       case Toolkit::VideoView::Property::DISPLAY_MODE:
537       {
538         value = impl.GetDisplayMode();
539         break;
540       }
541     }
542   }
543
544   return value;
545 }
546
547 void VideoView::SetDepthIndex( int depthIndex )
548 {
549   if( mTextureRenderer )
550   {
551     mTextureRenderer.SetProperty( Renderer::Property::DEPTH_INDEX, depthIndex );
552   }
553 }
554
555 void VideoView::OnSceneConnection( int depth )
556 {
557   Control::OnSceneConnection( depth );
558
559   if( mIsUnderlay )
560   {
561     SetWindowSurfaceTarget();
562   }
563 }
564
565 void VideoView::OnSceneDisconnection()
566 {
567   Control::OnSceneDisconnection();
568 }
569
570 void VideoView::OnSizeSet( const Vector3& targetSize )
571 {
572   if( mIsUnderlay && mSyncMode == Dali::VideoSyncMode::ENABLED )
573   {
574     SetFrameRenderCallback();
575     mVideoPlayer.StartSynchronization();
576   }
577   Control::OnSizeSet( targetSize );
578 }
579
580 Vector3 VideoView::GetNaturalSize()
581 {
582   Vector3 size;
583   size.x = mVideoSize.GetWidth();
584   size.y = mVideoSize.GetHeight();
585
586   if( size.x > 0 && size.y > 0 )
587   {
588     size.z = std::min( size.x, size.y );
589     return size;
590   }
591   else
592   {
593     return Control::GetNaturalSize();
594   }
595 }
596
597 float VideoView::GetHeightForWidth( float width )
598 {
599   if( mVideoSize.GetWidth() > 0 && mVideoSize.GetHeight() > 0 )
600   {
601     return GetHeightForWidthBase( width );
602   }
603   else
604   {
605     return Control::GetHeightForWidthBase( width );
606   }
607 }
608
609 float VideoView::GetWidthForHeight( float height )
610 {
611   if( mVideoSize.GetWidth() > 0 && mVideoSize.GetHeight() > 0 )
612   {
613     return GetWidthForHeightBase( height );
614   }
615   else
616   {
617     return Control::GetWidthForHeightBase( height );
618   }
619 }
620
621 void VideoView::SetWindowSurfaceTarget()
622 {
623   Actor self = Self();
624
625   if( !self.GetProperty< bool >( Actor::Property::CONNECTED_TO_SCENE ) )
626   {
627     // When the control is off the stage, it does not have Window.
628     return;
629   }
630
631   int curPos = mVideoPlayer.GetPlayPosition();
632
633   if( mIsPlay )
634   {
635     mVideoPlayer.Pause();
636   }
637
638   mPositionUpdateNotification = self.AddPropertyNotification( Actor::Property::WORLD_POSITION, StepCondition( 1.0f, 1.0f ) );
639   mSizeUpdateNotification = self.AddPropertyNotification( Actor::Property::SIZE, StepCondition( 1.0f, 1.0f ) );
640   mScaleUpdateNotification = self.AddPropertyNotification( Actor::Property::WORLD_SCALE, StepCondition( 0.1f, 1.0f ) );
641   mPositionUpdateNotification.NotifySignal().Connect( this, &VideoView::UpdateDisplayArea );
642   mSizeUpdateNotification.NotifySignal().Connect( this, &VideoView::UpdateDisplayArea );
643   mScaleUpdateNotification.NotifySignal().Connect( this, &VideoView::UpdateDisplayArea );
644
645   if( mTextureRenderer )
646   {
647     self.RemoveRenderer( mTextureRenderer );
648   }
649
650   // Note VideoPlayer::SetRenderingTarget resets all the options. (e.g. url, mute, looping)
651   mVideoPlayer.SetRenderingTarget( Dali::Adaptor::Get().GetNativeWindowHandle( self ) );
652
653   ApplyBackupProperties();
654
655   if( !mOverlayRenderer )
656   {
657     // For underlay rendering mode, video display area have to be transparent.
658     Geometry geometry = VisualFactoryCache::CreateQuadGeometry();
659     Shader shader = Shader::New( VERTEX_SHADER, FRAGMENT_SHADER );
660     mOverlayRenderer = Renderer::New( geometry, shader );
661     mOverlayRenderer.SetProperty( Renderer::Property::BLEND_MODE, BlendMode::OFF );
662   }
663
664   if( mIsPlay )
665   {
666     Play();
667   }
668
669   if( curPos > 0 )
670   {
671     mVideoPlayer.SetPlayPosition( curPos );
672   }
673 }
674
675 void VideoView::SetNativeImageTarget()
676 {
677   if( mVideoPlayer.IsVideoTextureSupported() == false )
678   {
679     DALI_LOG_ERROR( "Platform doesn't support decoded video frame images\n" );
680     mIsUnderlay = true;
681     return;
682   }
683
684   if( mIsPlay )
685   {
686     mVideoPlayer.Pause();
687   }
688
689   Actor self( Self() );
690
691   if( mOverlayRenderer )
692   {
693     self.RemoveRenderer( mOverlayRenderer );
694
695     mOverlayRenderer.Reset();
696   }
697
698   self.RemovePropertyNotification( mPositionUpdateNotification );
699   self.RemovePropertyNotification( mSizeUpdateNotification );
700   self.RemovePropertyNotification( mScaleUpdateNotification );
701
702   int curPos = mVideoPlayer.GetPlayPosition();
703
704   Any source;
705   Dali::NativeImageSourcePtr nativeImageSourcePtr = Dali::NativeImageSource::New( source );
706   mNativeTexture = Dali::Texture::New( *nativeImageSourcePtr );
707
708   if( !mTextureRenderer )
709   {
710     Dali::Geometry geometry = VisualFactoryCache::CreateQuadGeometry();
711     Dali::Shader shader = CreateShader();
712     Dali::TextureSet textureSet = Dali::TextureSet::New();
713     textureSet.SetTexture( 0u, mNativeTexture );
714
715     mTextureRenderer = Renderer::New( geometry, shader );
716     mTextureRenderer.SetTextures( textureSet );
717   }
718   else
719   {
720     Dali::TextureSet textureSet = mTextureRenderer.GetTextures();
721     textureSet.SetTexture( 0u, mNativeTexture );
722   }
723   Self().AddRenderer( mTextureRenderer );
724
725   // Note VideoPlayer::SetRenderingTarget resets all the options. (e.g. url, mute, looping)
726   mVideoPlayer.SetRenderingTarget( nativeImageSourcePtr );
727
728   ApplyBackupProperties();
729
730   if( mIsPlay )
731   {
732     Play();
733   }
734
735   if( curPos > 0 )
736   {
737     mVideoPlayer.SetPlayPosition( curPos );
738   }
739 }
740
741 void VideoView::UpdateDisplayArea( Dali::PropertyNotification& source )
742 {
743   // If mSyncMode is enabled, Video player's size and poistion is updated in Video player's constraint.
744   // Because video view and player should be work syncronization.
745   if( !mIsUnderlay || mSyncMode == Dali::VideoSyncMode::ENABLED )
746   {
747     return;
748   }
749
750   Actor self( Self() );
751
752   bool positionUsesAnchorPoint = self.GetProperty( Actor::Property::POSITION_USES_ANCHOR_POINT ).Get< bool >();
753   Vector3 actorSize = self.GetCurrentProperty< Vector3 >( Actor::Property::SIZE ) * self.GetCurrentProperty< Vector3 >( Actor::Property::SCALE );
754   Vector3 anchorPointOffSet = actorSize * ( positionUsesAnchorPoint ? self.GetCurrentProperty< Vector3 >( Actor::Property::ANCHOR_POINT ) : AnchorPoint::TOP_LEFT );
755
756   Vector2 screenPosition = self.GetProperty( Actor::Property::SCREEN_POSITION ).Get< Vector2 >();
757
758   mDisplayArea.x = screenPosition.x - anchorPointOffSet.x;
759   mDisplayArea.y = screenPosition.y - anchorPointOffSet.y;
760   mDisplayArea.width = actorSize.x;
761   mDisplayArea.height = actorSize.y;
762
763   mVideoPlayer.SetDisplayArea( mDisplayArea );
764 }
765
766 void VideoView::SetUnderlay( bool set )
767 {
768   if( set != mIsUnderlay )
769   {
770     mIsUnderlay = set;
771
772     if( mIsUnderlay )
773     {
774       SetWindowSurfaceTarget();
775     }
776     else
777     {
778       SetNativeImageTarget();
779     }
780
781     RelayoutRequest();
782   }
783 }
784
785 bool VideoView::IsUnderlay()
786 {
787   return mIsUnderlay;
788 }
789
790 void VideoView::SetSWCodec( bool on )
791 {
792   // If setting SW or HW type is failed , video-view shows video by default codec type.
793   // The default codec type is selected by platform.
794   if( on )
795   {
796     mVideoPlayer.SetCodecType( Dali::VideoPlayerPlugin::CodecType::SW );
797   }
798   else
799   {
800     mVideoPlayer.SetCodecType( Dali::VideoPlayerPlugin::CodecType::HW );
801   }
802 }
803
804 int VideoView::GetPlayPosition()
805 {
806   return mVideoPlayer.GetPlayPosition();
807 }
808
809 void VideoView::SetPlayPosition( int pos )
810 {
811   mVideoPlayer.SetPlayPosition( pos );
812 }
813
814 void VideoView::SetDisplayMode( int mode )
815 {
816   mVideoPlayer.SetDisplayMode( static_cast< Dali::VideoPlayerPlugin::DisplayMode::Type >( mode ) );
817 }
818
819 int VideoView::GetDisplayMode() const
820 {
821   return static_cast< int >( mVideoPlayer.GetDisplayMode() );
822 }
823
824 Any VideoView::GetMediaPlayer()
825 {
826   return mVideoPlayer.GetMediaPlayer();
827 }
828
829 void VideoView::OnAnimationFinished( Animation& animation )
830 {
831   // send desync
832   SetFrameRenderCallback();
833 }
834
835 void VideoView::PlayAnimation( Dali::Animation animation )
836 {
837   if( mIsUnderlay && mSyncMode == Dali::VideoSyncMode::ENABLED )
838   {
839     mVideoPlayer.StartSynchronization();
840     animation.FinishedSignal().Connect( this, &VideoView::OnAnimationFinished );
841   }
842   animation.Play();
843 }
844
845 Dali::Shader VideoView::CreateShader()
846 {
847   std::string fragmentShader = "#extension GL_OES_EGL_image_external:require\n";
848   std::string vertexShader;
849   std::string customFragmentShader;
850   bool checkShader = false;
851
852   if( !mEffectPropertyMap.Empty() )
853   {
854     Property::Value* vertexShaderValue = mEffectPropertyMap.Find( CUSTOM_VERTEX_SHADER );
855     if( vertexShaderValue )
856     {
857       checkShader = GetStringFromProperty( *vertexShaderValue, vertexShader );
858     }
859
860     if( !vertexShaderValue || !checkShader )
861     {
862       vertexShader = VERTEX_SHADER_TEXTURE;
863     }
864
865     Property::Value* fragmentShaderValue = mEffectPropertyMap.Find( CUSTOM_FRAGMENT_SHADER );
866     if( fragmentShaderValue )
867     {
868       checkShader = GetStringFromProperty( *fragmentShaderValue, customFragmentShader );
869
870       if( checkShader )
871       {
872         fragmentShader = customFragmentShader;
873       }
874     }
875
876     if( !fragmentShaderValue || !checkShader )
877     {
878       fragmentShader += FRAGMENT_SHADER_TEXTURE;
879     }
880   }
881   else
882   {
883     vertexShader = VERTEX_SHADER_TEXTURE;
884     fragmentShader += FRAGMENT_SHADER_TEXTURE;
885   }
886
887   return Dali::Shader::New( vertexShader, fragmentShader );
888 }
889
890 bool VideoView::GetStringFromProperty( const Dali::Property::Value& value, std::string& output )
891 {
892   bool extracted = false;
893   if( value.Get( output ) )
894   {
895     extracted = true;
896   }
897
898   return extracted;
899 }
900
901 void VideoView::ApplyBackupProperties()
902 {
903   Property::Map::SizeType pos = 0;
904   Property::Map::SizeType count = mPropertyBackup.Count();
905
906   for( ; pos < count; pos++ )
907   {
908     KeyValuePair property = mPropertyBackup.GetKeyValue( pos );
909
910     SetPropertyInternal( property.first.indexKey, property.second );
911   }
912 }
913
914 void VideoView::FrameRenderCallback( int frameID )
915 {
916   // send desync
917   if( frameID == mFrameID )
918   {
919     mVideoPlayer.FinishSynchronization();
920     mFrameID = 0;
921   }
922 }
923
924 void VideoView::SetFrameRenderCallback()
925 {
926   mFrameID++;
927   DevelWindow::AddFrameRenderedCallback( DevelWindow::Get( Self() ),
928                                          std::unique_ptr< CallbackBase >( MakeCallback( this, &VideoView::FrameRenderCallback ) ), mFrameID );
929 }
930
931 } // namespace Internal
932
933 } // namespace toolkit
934
935 } // namespace Dali