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