Merge "Previous model height return problem fixed" into 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       mEffectPropertyMap = *( shaderValue->GetMap() );
198     }
199   }
200
201   if( mTextureRenderer && !mEffectPropertyMap.Empty() )
202   {
203     Dali::Shader shader = CreateShader();
204     mTextureRenderer.SetShader( shader );
205   }
206
207   RelayoutRequest();
208 }
209
210 std::string VideoView::GetUrl()
211 {
212   return mUrl;
213 }
214
215 void VideoView::SetLooping( bool looping )
216 {
217   mVideoPlayer.SetLooping( looping );
218 }
219
220 bool VideoView::IsLooping()
221 {
222   return mVideoPlayer.IsLooping();
223 }
224
225 void VideoView::Play()
226 {
227   if( mIsUnderlay )
228   {
229     Self().AddRenderer( mOverlayRenderer );
230   }
231
232   mVideoPlayer.Play();
233   mIsPlay = true;
234 }
235
236 void VideoView::Pause()
237 {
238   mVideoPlayer.Pause();
239   mIsPlay = false;
240 }
241
242 void VideoView::Stop()
243 {
244   mVideoPlayer.Stop();
245   mIsPlay = false;
246 }
247
248 void VideoView::Forward( int millisecond )
249 {
250   int curPos = mVideoPlayer.GetPlayPosition();
251
252   int nextPos = curPos + millisecond;
253
254   mVideoPlayer.SetPlayPosition( nextPos );
255 }
256
257 void VideoView::Backward( int millisecond )
258 {
259   int curPos = mVideoPlayer.GetPlayPosition();
260
261   int nextPos = curPos - millisecond;
262   nextPos = ( nextPos < 0 )? 0: nextPos;
263
264   mVideoPlayer.SetPlayPosition( nextPos );
265 }
266
267 void VideoView::SetMute( bool mute )
268 {
269   mVideoPlayer.SetMute( mute );
270 }
271
272 bool VideoView::IsMuted()
273 {
274   return mVideoPlayer.IsMuted();
275 }
276
277 void VideoView::SetVolume( float left, float right )
278 {
279   mVideoPlayer.SetVolume( left, right );
280 }
281
282 void VideoView::GetVolume( float& left, float& right )
283 {
284   mVideoPlayer.GetVolume( left, right );
285 }
286
287 Dali::Toolkit::VideoView::VideoViewSignalType& VideoView::FinishedSignal()
288 {
289   return mFinishedSignal;
290 }
291
292 void VideoView::EmitSignalFinish()
293 {
294   if( mIsUnderlay )
295   {
296     Self().RemoveRenderer( mOverlayRenderer );
297   }
298
299   if ( !mFinishedSignal.Empty() )
300   {
301     Dali::Toolkit::VideoView handle( GetOwner() );
302     mFinishedSignal.Emit( handle );
303   }
304 }
305
306 bool VideoView::DoAction( BaseObject* object, const std::string& actionName, const Property::Map& attributes )
307 {
308   bool ret = false;
309
310   Dali::BaseHandle handle( object );
311   Toolkit::VideoView videoView = Toolkit::VideoView::DownCast( handle );
312
313   if( !videoView )
314   {
315     return ret;
316   }
317
318   VideoView& impl = GetImpl( videoView );
319
320   if( strcmp( actionName.c_str(), ACTION_VIDEOVIEW_PLAY ) == 0 )
321   {
322     impl.Play();
323     ret = true;
324   }
325   else if( strcmp( actionName.c_str(), ACTION_VIDEOVIEW_PAUSE ) == 0 )
326   {
327     impl.Pause();
328     ret = true;
329   }
330   else if( strcmp( actionName.c_str(), ACTION_VIDEOVIEW_STOP ) == 0 )
331   {
332     impl.Stop();
333     ret = true;
334   }
335   else if( strcmp( actionName.c_str(), ACTION_VIDEOVIEW_FORWARD ) == 0 )
336   {
337     int millisecond = 0;
338     if( attributes["videoForward"].Get( millisecond ) )
339     {
340       impl.Forward( millisecond );
341       ret = true;
342     }
343   }
344   else if( strcmp( actionName.c_str(), ACTION_VIDEOVIEW_BACKWARD ) == 0 )
345   {
346     int millisecond = 0;
347     if( attributes["videoBackward"].Get( millisecond ) )
348     {
349       impl.Backward( millisecond );
350       ret = true;
351     }
352   }
353
354   return ret;
355 }
356
357 bool VideoView::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
358 {
359   Dali::BaseHandle handle( object );
360
361   bool connected( true );
362   Toolkit::VideoView videoView = Toolkit::VideoView::DownCast( handle );
363
364   if( 0 == strcmp( signalName.c_str(), FINISHED_SIGNAL ) )
365   {
366     videoView.FinishedSignal().Connect( tracker, functor );
367   }
368   else
369   {
370     // signalName does not match any signal
371     connected = false;
372   }
373
374   return connected;
375 }
376
377 void VideoView::SetProperty( BaseObject* object, Property::Index index, const Property::Value& value )
378 {
379   Toolkit::VideoView videoView = Toolkit::VideoView::DownCast( Dali::BaseHandle( object ) );
380
381   if( videoView )
382   {
383     VideoView& impl = GetImpl( videoView );
384
385     switch( index )
386     {
387       case Toolkit::VideoView::Property::VIDEO:
388       {
389         std::string videoUrl;
390         Property::Map map;
391
392         if( value.Get( videoUrl ) )
393         {
394           impl.SetUrl( videoUrl );
395         }
396         else if( value.Get( map ) )
397         {
398             impl.SetPropertyMap( map );
399           }
400         break;
401       }
402       case Toolkit::VideoView::Property::LOOPING:
403       {
404         bool looping;
405         if( value.Get( looping ) )
406         {
407           impl.SetLooping( looping );
408         }
409         break;
410       }
411       case Toolkit::VideoView::Property::MUTED:
412       {
413         bool mute;
414         if( value.Get( mute ) )
415         {
416           impl.SetMute( mute );
417         }
418         break;
419       }
420       case Toolkit::VideoView::Property::VOLUME:
421       {
422         Property::Map map;
423         float left, right;
424         if( value.Get( map ) )
425         {
426           Property::Value* volumeLeft = map.Find( VOLUME_LEFT );
427           Property::Value* volumeRight = map.Find( VOLUME_RIGHT );
428           if( volumeLeft && volumeLeft->Get( left ) && volumeRight && volumeRight->Get( right ) )
429           {
430             impl.SetVolume( left, right );
431           }
432         }
433         break;
434       }
435       case Toolkit::VideoView::Property::UNDERLAY:
436       {
437         bool underlay;
438         if( value.Get( underlay ) )
439         {
440           impl.SetUnderlay( underlay );
441         }
442         break;
443       }
444       case Toolkit::VideoView::Property::PLAY_POSITION:
445       {
446         int pos;
447         if( value.Get( pos ) )
448         {
449           impl.SetPlayPosition( pos );
450         }
451         break;
452       }
453       case Toolkit::VideoView::Property::DISPLAY_MODE:
454       {
455         int mode;
456         if( value.Get( mode ) )
457         {
458           impl.SetDisplayMode( mode );
459         }
460         break;
461       }
462     }
463   }
464 }
465
466 Property::Value VideoView::GetProperty( BaseObject* object, Property::Index propertyIndex )
467 {
468   Property::Value value;
469   Toolkit::VideoView videoView = Toolkit::VideoView::DownCast( Dali::BaseHandle( object ) );
470
471   if( videoView )
472   {
473     VideoView& impl = GetImpl( videoView );
474
475     switch( propertyIndex )
476     {
477       case Toolkit::VideoView::Property::VIDEO:
478       {
479         if( !impl.mUrl.empty() )
480         {
481           value = impl.mUrl;
482         }
483         else if( !impl.mPropertyMap.Empty() )
484         {
485           value = impl.mPropertyMap;
486         }
487         break;
488       }
489       case Toolkit::VideoView::Property::LOOPING:
490       {
491         value = impl.IsLooping();
492         break;
493       }
494       case Toolkit::VideoView::Property::MUTED:
495       {
496         value = impl.IsMuted();
497         break;
498       }
499       case Toolkit::VideoView::Property::VOLUME:
500       {
501         Property::Map map;
502         float left, right;
503
504         impl.GetVolume( left, right );
505         map.Insert( VOLUME_LEFT, left );
506         map.Insert( VOLUME_RIGHT, right );
507         value = map;
508         break;
509       }
510       case Toolkit::VideoView::Property::UNDERLAY:
511       {
512         value = impl.IsUnderlay();
513         break;
514       }
515       case Toolkit::VideoView::Property::PLAY_POSITION:
516       {
517         value = impl.GetPlayPosition();
518         break;
519       }
520       case Toolkit::VideoView::Property::DISPLAY_MODE:
521       {
522         value = impl.GetDisplayMode();
523         break;
524       }
525     }
526   }
527
528   return value;
529 }
530
531 void VideoView::SetDepthIndex( int depthIndex )
532 {
533   if( mTextureRenderer )
534   {
535     mTextureRenderer.SetProperty( Renderer::Property::DEPTH_INDEX, depthIndex );
536   }
537 }
538
539 void VideoView::OnStageConnection( int depth )
540 {
541   Control::OnStageConnection( depth );
542 }
543
544 void VideoView::OnStageDisconnection()
545 {
546   Control::OnStageDisconnection();
547 }
548
549 Vector3 VideoView::GetNaturalSize()
550 {
551   Vector3 size;
552   size.x = mVideoSize.GetWidth();
553   size.y = mVideoSize.GetHeight();
554
555   if( size.x > 0 && size.y > 0 )
556   {
557     size.z = std::min( size.x, size.y );
558     return size;
559   }
560   else
561   {
562     return Control::GetNaturalSize();
563   }
564 }
565
566 float VideoView::GetHeightForWidth( float width )
567 {
568   if( mVideoSize.GetWidth() > 0 && mVideoSize.GetHeight() > 0 )
569   {
570     return GetHeightForWidthBase( width );
571   }
572   else
573   {
574     return Control::GetHeightForWidthBase( width );
575   }
576 }
577
578 float VideoView::GetWidthForHeight( float height )
579 {
580   if( mVideoSize.GetWidth() > 0 && mVideoSize.GetHeight() > 0 )
581   {
582     return GetWidthForHeightBase( height );
583   }
584   else
585   {
586     return Control::GetWidthForHeightBase( height );
587   }
588 }
589
590 void VideoView::SetWindowSurfaceTarget()
591 {
592   Actor self = Self();
593   int curPos = mVideoPlayer.GetPlayPosition();
594
595   if( mIsPlay )
596   {
597     mVideoPlayer.Pause();
598   }
599
600   mPositionUpdateNotification = self.AddPropertyNotification( Actor::Property::WORLD_POSITION, StepCondition( 1.0f, 1.0f ) );
601   mSizeUpdateNotification = self.AddPropertyNotification( Actor::Property::SIZE, StepCondition( 1.0f, 1.0f ) );
602   mScaleUpdateNotification = self.AddPropertyNotification( Actor::Property::WORLD_SCALE, StepCondition( 0.1f, 1.0f ) );
603   mPositionUpdateNotification.NotifySignal().Connect( this, &VideoView::UpdateDisplayArea );
604   mSizeUpdateNotification.NotifySignal().Connect( this, &VideoView::UpdateDisplayArea );
605   mScaleUpdateNotification.NotifySignal().Connect( this, &VideoView::UpdateDisplayArea );
606
607   if( mTextureRenderer )
608   {
609     self.RemoveRenderer( mTextureRenderer );
610   }
611
612   mVideoPlayer.SetRenderingTarget( Dali::Adaptor::Get().GetNativeWindowHandle() );
613   mVideoPlayer.SetUrl( mUrl );
614
615   if( !mOverlayRenderer )
616   {
617     // For underlay rendering mode, video display area have to be transparent.
618     Geometry geometry = VisualFactoryCache::CreateQuadGeometry();
619     Shader shader = Shader::New( VERTEX_SHADER, FRAGMENT_SHADER );
620     mOverlayRenderer = Renderer::New( geometry, shader );
621     mOverlayRenderer.SetProperty( Renderer::Property::BLEND_MODE, BlendMode::OFF );
622   }
623
624   if( mIsPlay )
625   {
626     Play();
627   }
628
629   if( curPos > 0 )
630   {
631     mVideoPlayer.SetPlayPosition( curPos );
632   }
633 }
634
635 void VideoView::SetNativeImageTarget()
636 {
637   if( mVideoPlayer.IsVideoTextureSupported() == false )
638   {
639     DALI_LOG_ERROR( "Platform doesn't support decoded video frame images\n" );
640     mIsUnderlay = true;
641     return;
642   }
643
644   if( mIsPlay )
645   {
646     mVideoPlayer.Pause();
647   }
648
649   Actor self( Self() );
650
651   if( mOverlayRenderer )
652   {
653     self.RemoveRenderer( mOverlayRenderer );
654   }
655
656   self.RemovePropertyNotification( mPositionUpdateNotification );
657   self.RemovePropertyNotification( mSizeUpdateNotification );
658   self.RemovePropertyNotification( mScaleUpdateNotification );
659
660   int curPos = mVideoPlayer.GetPlayPosition();
661
662   Any source;
663   Dali::NativeImageSourcePtr nativeImageSourcePtr = Dali::NativeImageSource::New( source );
664   mNativeTexture = Dali::Texture::New( *nativeImageSourcePtr );
665
666   if( !mTextureRenderer )
667   {
668     Dali::Geometry geometry = VisualFactoryCache::CreateQuadGeometry();
669     Dali::Shader shader = CreateShader();
670     Dali::TextureSet textureSet = Dali::TextureSet::New();
671     textureSet.SetTexture( 0u, mNativeTexture );
672
673     mTextureRenderer = Renderer::New( geometry, shader );
674     mTextureRenderer.SetTextures( textureSet );
675   }
676   else
677   {
678     Dali::TextureSet textureSet = mTextureRenderer.GetTextures();
679     textureSet.SetTexture( 0u, mNativeTexture );
680   }
681   Self().AddRenderer( mTextureRenderer );
682
683   mVideoPlayer.SetRenderingTarget( nativeImageSourcePtr );
684   mVideoPlayer.SetUrl( mUrl );
685
686   if( mIsPlay )
687   {
688     Play();
689   }
690
691   if( curPos > 0 )
692   {
693     mVideoPlayer.SetPlayPosition( curPos );
694   }
695 }
696
697 void VideoView::UpdateDisplayArea( Dali::PropertyNotification& source )
698 {
699   if( !mIsUnderlay )
700   {
701     return;
702   }
703
704   Actor self( Self() );
705
706   bool positionUsesAnchorPoint = self.GetProperty( DevelActor::Property::POSITION_USES_ANCHOR_POINT ).Get< bool >();
707   Vector3 actorSize = self.GetCurrentSize() * self.GetCurrentScale();
708   Vector3 anchorPointOffSet = actorSize * ( positionUsesAnchorPoint ? self.GetCurrentAnchorPoint() : AnchorPoint::TOP_LEFT );
709
710   Vector2 screenPosition = self.GetProperty( DevelActor::Property::SCREEN_POSITION ).Get< Vector2 >();
711
712   mDisplayArea.x = screenPosition.x - anchorPointOffSet.x;
713   mDisplayArea.y = screenPosition.y - anchorPointOffSet.y;
714   mDisplayArea.width = actorSize.x;
715   mDisplayArea.height = actorSize.y;
716
717   mVideoPlayer.SetDisplayArea( mDisplayArea );
718 }
719
720 void VideoView::SetUnderlay( bool set )
721 {
722   if( set != mIsUnderlay )
723   {
724     mIsUnderlay = set;
725
726     if( mIsUnderlay )
727     {
728       SetWindowSurfaceTarget();
729     }
730     else
731     {
732       SetNativeImageTarget();
733     }
734
735     RelayoutRequest();
736   }
737 }
738
739 bool VideoView::IsUnderlay()
740 {
741   return mIsUnderlay;
742 }
743
744 void VideoView::SetSWCodec( bool on )
745 {
746   // If setting SW or HW type is failed , video-view shows video by default codec type.
747   // The default codec type is selected by platform.
748   if( on )
749   {
750     mVideoPlayer.SetCodecType( Dali::VideoPlayerPlugin::CodecType::SW );
751   }
752   else
753   {
754     mVideoPlayer.SetCodecType( Dali::VideoPlayerPlugin::CodecType::HW );
755   }
756 }
757
758 int VideoView::GetPlayPosition()
759 {
760   return mVideoPlayer.GetPlayPosition();
761 }
762
763 void VideoView::SetPlayPosition( int pos )
764 {
765   mVideoPlayer.SetPlayPosition( pos );
766 }
767
768 void VideoView::SetDisplayMode( int mode )
769 {
770   mVideoPlayer.SetDisplayMode( static_cast< Dali::VideoPlayerPlugin::DisplayMode::Type >( mode ) );
771 }
772
773 int VideoView::GetDisplayMode() const
774 {
775   return static_cast< int >( mVideoPlayer.GetDisplayMode() );
776 }
777
778 Dali::Shader VideoView::CreateShader()
779 {
780   std::string fragmentShader = "#extension GL_OES_EGL_image_external:require\n";
781   std::string vertexShader;
782   std::string customFragmentShader;
783   bool checkShader = false;
784
785   if( !mEffectPropertyMap.Empty() )
786   {
787     Property::Value* vertexShaderValue = mEffectPropertyMap.Find( CUSTOM_VERTEX_SHADER );
788     if( vertexShaderValue )
789     {
790       checkShader = GetStringFromProperty( *vertexShaderValue, vertexShader );
791     }
792
793     if( !vertexShaderValue || !checkShader )
794     {
795       vertexShader = VERTEX_SHADER_TEXTURE;
796     }
797
798     Property::Value* fragmentShaderValue = mEffectPropertyMap.Find( CUSTOM_FRAGMENT_SHADER );
799     if( fragmentShaderValue )
800     {
801       checkShader = GetStringFromProperty( *fragmentShaderValue, customFragmentShader );
802
803       if( checkShader )
804       {
805         fragmentShader = customFragmentShader;
806       }
807     }
808
809     if( !fragmentShaderValue || !checkShader )
810     {
811       fragmentShader += FRAGMENT_SHADER_TEXTURE;
812     }
813   }
814   else
815   {
816     vertexShader = VERTEX_SHADER_TEXTURE;
817     fragmentShader += FRAGMENT_SHADER_TEXTURE;
818   }
819
820   return Dali::Shader::New( vertexShader, fragmentShader );
821 }
822
823 bool VideoView::GetStringFromProperty( const Dali::Property::Value& value, std::string& output )
824 {
825   bool extracted = false;
826   if( value.Get( output ) )
827   {
828     extracted = true;
829   }
830
831   return extracted;
832 }
833
834 } // namespace Internal
835
836 } // namespace toolkit
837
838 } // namespace Dali