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