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