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