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