[dali_1.3.24] Merge branch 'devel/master'
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / controls / video-view / video-view-impl.cpp
1 /*
2  * Copyright (c) 2018 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/public-api/common/stage.h>
26 #include <dali/devel-api/scripting/scripting.h>
27 #include <dali/public-api/adaptor-framework/native-image-source.h>
28 #include <dali/integration-api/adaptors/adaptor.h>
29 #include <dali/integration-api/debug.h>
30 #include <dali/public-api/animation/constraint.h>
31 #include <dali/devel-api/actors/actor-devel.h>
32
33 // INTERNAL INCLUDES
34 #include <dali-toolkit/public-api/controls/video-view/video-view.h>
35 #include <dali-toolkit/internal/visuals/visual-factory-cache.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 mediump mat4 uMvpMatrix;\n
91   uniform mediump 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 mediump mat4 uMvpMatrix;\n
113   uniform mediump 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()
135 : Control( ControlBehaviour( ACTOR_BEHAVIOUR_DEFAULT | DISABLE_STYLE_CHANGE_SIGNALS ) ),
136   mCurrentVideoPlayPosition( 0 ),
137   mIsPlay( false ),
138   mIsUnderlay( true )
139 {
140   mVideoPlayer = Dali::VideoPlayer::New();
141 }
142
143 VideoView::~VideoView()
144 {
145 }
146
147 Toolkit::VideoView VideoView::New()
148 {
149   VideoView* impl = new VideoView();
150   Toolkit::VideoView handle = Toolkit::VideoView( *impl );
151
152   impl->Initialize();
153
154   return handle;
155 }
156
157 void VideoView::OnInitialize()
158 {
159   mVideoPlayer.FinishedSignal().Connect( this, &VideoView::EmitSignalFinish );
160   SetWindowSurfaceTarget();
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( mIsUnderlay )
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( mIsUnderlay )
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::SetProperty( BaseObject* object, Property::Index index, const Property::Value& value )
382 {
383   Toolkit::VideoView videoView = Toolkit::VideoView::DownCast( Dali::BaseHandle( object ) );
384
385   if( videoView )
386   {
387     VideoView& impl = GetImpl( videoView );
388
389     switch( index )
390     {
391       case Toolkit::VideoView::Property::VIDEO:
392       {
393         std::string videoUrl;
394         Property::Map map;
395
396         if( value.Get( videoUrl ) )
397         {
398           impl.SetUrl( videoUrl );
399         }
400         else if( value.Get( map ) )
401         {
402             impl.SetPropertyMap( map );
403           }
404         break;
405       }
406       case Toolkit::VideoView::Property::LOOPING:
407       {
408         bool looping;
409         if( value.Get( looping ) )
410         {
411           impl.SetLooping( looping );
412         }
413         break;
414       }
415       case Toolkit::VideoView::Property::MUTED:
416       {
417         bool mute;
418         if( value.Get( mute ) )
419         {
420           impl.SetMute( mute );
421         }
422         break;
423       }
424       case Toolkit::VideoView::Property::VOLUME:
425       {
426         Property::Map map;
427         float left, right;
428         if( value.Get( map ) )
429         {
430           Property::Value* volumeLeft = map.Find( VOLUME_LEFT );
431           Property::Value* volumeRight = map.Find( VOLUME_RIGHT );
432           if( volumeLeft && volumeLeft->Get( left ) && volumeRight && volumeRight->Get( right ) )
433           {
434             impl.SetVolume( left, right );
435           }
436         }
437         break;
438       }
439       case Toolkit::VideoView::Property::UNDERLAY:
440       {
441         bool underlay;
442         if( value.Get( underlay ) )
443         {
444           impl.SetUnderlay( underlay );
445         }
446         break;
447       }
448       case Toolkit::VideoView::Property::PLAY_POSITION:
449       {
450         int pos;
451         if( value.Get( pos ) )
452         {
453           impl.SetPlayPosition( pos );
454         }
455         break;
456       }
457       case Toolkit::VideoView::Property::DISPLAY_MODE:
458       {
459         int mode;
460         if( value.Get( mode ) )
461         {
462           impl.SetDisplayMode( mode );
463         }
464         break;
465       }
466     }
467   }
468 }
469
470 Property::Value VideoView::GetProperty( BaseObject* object, Property::Index propertyIndex )
471 {
472   Property::Value value;
473   Toolkit::VideoView videoView = Toolkit::VideoView::DownCast( Dali::BaseHandle( object ) );
474
475   if( videoView )
476   {
477     VideoView& impl = GetImpl( videoView );
478
479     switch( propertyIndex )
480     {
481       case Toolkit::VideoView::Property::VIDEO:
482       {
483         if( !impl.mUrl.empty() )
484         {
485           value = impl.mUrl;
486         }
487         else if( !impl.mPropertyMap.Empty() )
488         {
489           value = impl.mPropertyMap;
490         }
491         break;
492       }
493       case Toolkit::VideoView::Property::LOOPING:
494       {
495         value = impl.IsLooping();
496         break;
497       }
498       case Toolkit::VideoView::Property::MUTED:
499       {
500         value = impl.IsMuted();
501         break;
502       }
503       case Toolkit::VideoView::Property::VOLUME:
504       {
505         Property::Map map;
506         float left, right;
507
508         impl.GetVolume( left, right );
509         map.Insert( VOLUME_LEFT, left );
510         map.Insert( VOLUME_RIGHT, right );
511         value = map;
512         break;
513       }
514       case Toolkit::VideoView::Property::UNDERLAY:
515       {
516         value = impl.IsUnderlay();
517         break;
518       }
519       case Toolkit::VideoView::Property::PLAY_POSITION:
520       {
521         value = impl.GetPlayPosition();
522         break;
523       }
524       case Toolkit::VideoView::Property::DISPLAY_MODE:
525       {
526         value = impl.GetDisplayMode();
527         break;
528       }
529     }
530   }
531
532   return value;
533 }
534
535 void VideoView::SetDepthIndex( int depthIndex )
536 {
537   if( mTextureRenderer )
538   {
539     mTextureRenderer.SetProperty( Renderer::Property::DEPTH_INDEX, depthIndex );
540   }
541 }
542
543 void VideoView::OnStageConnection( int depth )
544 {
545   Control::OnStageConnection( depth );
546 }
547
548 void VideoView::OnStageDisconnection()
549 {
550   Control::OnStageDisconnection();
551 }
552
553 Vector3 VideoView::GetNaturalSize()
554 {
555   Vector3 size;
556   size.x = mVideoSize.GetWidth();
557   size.y = mVideoSize.GetHeight();
558
559   if( size.x > 0 && size.y > 0 )
560   {
561     size.z = std::min( size.x, size.y );
562     return size;
563   }
564   else
565   {
566     return Control::GetNaturalSize();
567   }
568 }
569
570 float VideoView::GetHeightForWidth( float width )
571 {
572   if( mVideoSize.GetWidth() > 0 && mVideoSize.GetHeight() > 0 )
573   {
574     return GetHeightForWidthBase( width );
575   }
576   else
577   {
578     return Control::GetHeightForWidthBase( width );
579   }
580 }
581
582 float VideoView::GetWidthForHeight( float height )
583 {
584   if( mVideoSize.GetWidth() > 0 && mVideoSize.GetHeight() > 0 )
585   {
586     return GetWidthForHeightBase( height );
587   }
588   else
589   {
590     return Control::GetWidthForHeightBase( height );
591   }
592 }
593
594 void VideoView::SetWindowSurfaceTarget()
595 {
596   Actor self = Self();
597   int curPos = mVideoPlayer.GetPlayPosition();
598
599   if( mIsPlay )
600   {
601     mVideoPlayer.Pause();
602   }
603
604   mPositionUpdateNotification = self.AddPropertyNotification( Actor::Property::WORLD_POSITION, StepCondition( 1.0f, 1.0f ) );
605   mSizeUpdateNotification = self.AddPropertyNotification( Actor::Property::SIZE, StepCondition( 1.0f, 1.0f ) );
606   mScaleUpdateNotification = self.AddPropertyNotification( Actor::Property::WORLD_SCALE, StepCondition( 0.1f, 1.0f ) );
607   mPositionUpdateNotification.NotifySignal().Connect( this, &VideoView::UpdateDisplayArea );
608   mSizeUpdateNotification.NotifySignal().Connect( this, &VideoView::UpdateDisplayArea );
609   mScaleUpdateNotification.NotifySignal().Connect( this, &VideoView::UpdateDisplayArea );
610
611   if( mTextureRenderer )
612   {
613     self.RemoveRenderer( mTextureRenderer );
614   }
615
616   mVideoPlayer.SetRenderingTarget( Dali::Adaptor::Get().GetNativeWindowHandle() );
617   mVideoPlayer.SetUrl( mUrl );
618
619   if( !mOverlayRenderer )
620   {
621     // For underlay rendering mode, video display area have to be transparent.
622     Geometry geometry = VisualFactoryCache::CreateQuadGeometry();
623     Shader shader = Shader::New( VERTEX_SHADER, FRAGMENT_SHADER );
624     mOverlayRenderer = Renderer::New( geometry, shader );
625     mOverlayRenderer.SetProperty( Renderer::Property::BLEND_MODE, BlendMode::OFF );
626   }
627
628   if( mIsPlay )
629   {
630     Play();
631   }
632
633   if( curPos > 0 )
634   {
635     mVideoPlayer.SetPlayPosition( curPos );
636   }
637 }
638
639 void VideoView::SetNativeImageTarget()
640 {
641   if( mVideoPlayer.IsVideoTextureSupported() == false )
642   {
643     DALI_LOG_ERROR( "Platform doesn't support decoded video frame images\n" );
644     mIsUnderlay = true;
645     return;
646   }
647
648   if( mIsPlay )
649   {
650     mVideoPlayer.Pause();
651   }
652
653   Actor self( Self() );
654
655   if( mOverlayRenderer )
656   {
657     self.RemoveRenderer( mOverlayRenderer );
658   }
659
660   self.RemovePropertyNotification( mPositionUpdateNotification );
661   self.RemovePropertyNotification( mSizeUpdateNotification );
662   self.RemovePropertyNotification( mScaleUpdateNotification );
663
664   int curPos = mVideoPlayer.GetPlayPosition();
665
666   Any source;
667   Dali::NativeImageSourcePtr nativeImageSourcePtr = Dali::NativeImageSource::New( source );
668   mNativeTexture = Dali::Texture::New( *nativeImageSourcePtr );
669
670   if( !mTextureRenderer )
671   {
672     Dali::Geometry geometry = VisualFactoryCache::CreateQuadGeometry();
673     Dali::Shader shader = CreateShader();
674     Dali::TextureSet textureSet = Dali::TextureSet::New();
675     textureSet.SetTexture( 0u, mNativeTexture );
676
677     mTextureRenderer = Renderer::New( geometry, shader );
678     mTextureRenderer.SetTextures( textureSet );
679   }
680   else
681   {
682     Dali::TextureSet textureSet = mTextureRenderer.GetTextures();
683     textureSet.SetTexture( 0u, mNativeTexture );
684   }
685   Self().AddRenderer( mTextureRenderer );
686
687   mVideoPlayer.SetRenderingTarget( nativeImageSourcePtr );
688   mVideoPlayer.SetUrl( mUrl );
689
690   if( mIsPlay )
691   {
692     Play();
693   }
694
695   if( curPos > 0 )
696   {
697     mVideoPlayer.SetPlayPosition( curPos );
698   }
699 }
700
701 void VideoView::UpdateDisplayArea( Dali::PropertyNotification& source )
702 {
703   if( !mIsUnderlay )
704   {
705     return;
706   }
707
708   Actor self( Self() );
709
710   bool positionUsesAnchorPoint = self.GetProperty( DevelActor::Property::POSITION_USES_ANCHOR_POINT ).Get< bool >();
711   Vector3 actorSize = self.GetCurrentSize() * self.GetCurrentScale();
712   Vector3 anchorPointOffSet = actorSize * ( positionUsesAnchorPoint ? self.GetCurrentAnchorPoint() : AnchorPoint::TOP_LEFT );
713
714   Vector2 screenPosition = self.GetProperty( DevelActor::Property::SCREEN_POSITION ).Get< Vector2 >();
715
716   mDisplayArea.x = screenPosition.x - anchorPointOffSet.x;
717   mDisplayArea.y = screenPosition.y - anchorPointOffSet.y;
718   mDisplayArea.width = actorSize.x;
719   mDisplayArea.height = actorSize.y;
720
721   mVideoPlayer.SetDisplayArea( mDisplayArea );
722 }
723
724 void VideoView::SetUnderlay( bool set )
725 {
726   if( set != mIsUnderlay )
727   {
728     mIsUnderlay = set;
729
730     if( mIsUnderlay )
731     {
732       SetWindowSurfaceTarget();
733     }
734     else
735     {
736       SetNativeImageTarget();
737     }
738
739     RelayoutRequest();
740   }
741 }
742
743 bool VideoView::IsUnderlay()
744 {
745   return mIsUnderlay;
746 }
747
748 void VideoView::SetSWCodec( bool on )
749 {
750   // If setting SW or HW type is failed , video-view shows video by default codec type.
751   // The default codec type is selected by platform.
752   if( on )
753   {
754     mVideoPlayer.SetCodecType( Dali::VideoPlayerPlugin::CodecType::SW );
755   }
756   else
757   {
758     mVideoPlayer.SetCodecType( Dali::VideoPlayerPlugin::CodecType::HW );
759   }
760 }
761
762 int VideoView::GetPlayPosition()
763 {
764   return mVideoPlayer.GetPlayPosition();
765 }
766
767 void VideoView::SetPlayPosition( int pos )
768 {
769   mVideoPlayer.SetPlayPosition( pos );
770 }
771
772 void VideoView::SetDisplayMode( int mode )
773 {
774   mVideoPlayer.SetDisplayMode( static_cast< Dali::VideoPlayerPlugin::DisplayMode::Type >( mode ) );
775 }
776
777 int VideoView::GetDisplayMode() const
778 {
779   return static_cast< int >( mVideoPlayer.GetDisplayMode() );
780 }
781
782 Dali::Shader VideoView::CreateShader()
783 {
784   std::string fragmentShader = "#extension GL_OES_EGL_image_external:require\n";
785   std::string vertexShader;
786   std::string customFragmentShader;
787   bool checkShader = false;
788
789   if( !mEffectPropertyMap.Empty() )
790   {
791     Property::Value* vertexShaderValue = mEffectPropertyMap.Find( CUSTOM_VERTEX_SHADER );
792     if( vertexShaderValue )
793     {
794       checkShader = GetStringFromProperty( *vertexShaderValue, vertexShader );
795     }
796
797     if( !vertexShaderValue || !checkShader )
798     {
799       vertexShader = VERTEX_SHADER_TEXTURE;
800     }
801
802     Property::Value* fragmentShaderValue = mEffectPropertyMap.Find( CUSTOM_FRAGMENT_SHADER );
803     if( fragmentShaderValue )
804     {
805       checkShader = GetStringFromProperty( *fragmentShaderValue, customFragmentShader );
806
807       if( checkShader )
808       {
809         fragmentShader = customFragmentShader;
810       }
811     }
812
813     if( !fragmentShaderValue || !checkShader )
814     {
815       fragmentShader += FRAGMENT_SHADER_TEXTURE;
816     }
817   }
818   else
819   {
820     vertexShader = VERTEX_SHADER_TEXTURE;
821     fragmentShader += FRAGMENT_SHADER_TEXTURE;
822   }
823
824   return Dali::Shader::New( vertexShader, fragmentShader );
825 }
826
827 bool VideoView::GetStringFromProperty( const Dali::Property::Value& value, std::string& output )
828 {
829   bool extracted = false;
830   if( value.Get( output ) )
831   {
832     extracted = true;
833   }
834
835   return extracted;
836 }
837
838 } // namespace Internal
839
840 } // namespace toolkit
841
842 } // namespace Dali