X-Git-Url: http://review.tizen.org/git/?p=platform%2Fcore%2Fuifw%2Fdali-toolkit.git;a=blobdiff_plain;f=dali-toolkit%2Finternal%2Fcontrols%2Fvideo-view%2Fvideo-view-impl.cpp;h=85b219e5a2408b34d2946cb8d5095fb5e6f01627;hp=25dff0111ada502c8519d19aa408af7f067ac60c;hb=2f48746387a5d6b993f19fad3756796c8bd95c1c;hpb=3297062b74ec6c1e48177974e3d8d7de9b86ff57 diff --git a/dali-toolkit/internal/controls/video-view/video-view-impl.cpp b/dali-toolkit/internal/controls/video-view/video-view-impl.cpp index 25dff01..85b219e 100644 --- a/dali-toolkit/internal/controls/video-view/video-view-impl.cpp +++ b/dali-toolkit/internal/controls/video-view/video-view-impl.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017 Samsung Electronics Co., Ltd. + * Copyright (c) 2021 Samsung Electronics Co., Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,180 +19,159 @@ #include "video-view-impl.h" // EXTERNAL INCLUDES -#include -#include -#include -#include +#include +#include #include -#include -#include #include +#include #include -#include +#include +#include +#include // INTERNAL INCLUDES -#include -#include -#include -#include -#include -#include +#include +#include #include +#include +#include namespace Dali { - namespace Toolkit { - namespace Internal { - namespace { - BaseHandle Create() { return Toolkit::VideoView::New(); } -DALI_TYPE_REGISTRATION_BEGIN( Toolkit::VideoView, Toolkit::Control, Create ); +DALI_TYPE_REGISTRATION_BEGIN(Toolkit::VideoView, Toolkit::Control, Create); -DALI_PROPERTY_REGISTRATION( Toolkit, VideoView, "video", MAP, VIDEO ) -DALI_PROPERTY_REGISTRATION( Toolkit, VideoView, "looping", BOOLEAN, LOOPING ) -DALI_PROPERTY_REGISTRATION( Toolkit, VideoView, "muted", BOOLEAN, MUTED ) -DALI_PROPERTY_REGISTRATION( Toolkit, VideoView, "volume", MAP, VOLUME ) -DALI_PROPERTY_REGISTRATION( Toolkit, VideoView, "underlay", BOOLEAN, UNDERLAY ) +DALI_PROPERTY_REGISTRATION(Toolkit, VideoView, "video", MAP, VIDEO) +DALI_PROPERTY_REGISTRATION(Toolkit, VideoView, "looping", BOOLEAN, LOOPING) +DALI_PROPERTY_REGISTRATION(Toolkit, VideoView, "muted", BOOLEAN, MUTED) +DALI_PROPERTY_REGISTRATION(Toolkit, VideoView, "volume", MAP, VOLUME) +DALI_PROPERTY_REGISTRATION(Toolkit, VideoView, "underlay", BOOLEAN, UNDERLAY) +DALI_PROPERTY_REGISTRATION(Toolkit, VideoView, "playPosition", INTEGER, PLAY_POSITION) +DALI_PROPERTY_REGISTRATION(Toolkit, VideoView, "displayMode", INTEGER, DISPLAY_MODE) -DALI_SIGNAL_REGISTRATION( Toolkit, VideoView, "finished", FINISHED_SIGNAL ) +DALI_SIGNAL_REGISTRATION(Toolkit, VideoView, "finished", FINISHED_SIGNAL) -DALI_ACTION_REGISTRATION( Toolkit, VideoView, "play", ACTION_VIDEOVIEW_PLAY ) -DALI_ACTION_REGISTRATION( Toolkit, VideoView, "pause", ACTION_VIDEOVIEW_PAUSE ) -DALI_ACTION_REGISTRATION( Toolkit, VideoView, "stop", ACTION_VIDEOVIEW_STOP ) -DALI_ACTION_REGISTRATION( Toolkit, VideoView, "forward", ACTION_VIDEOVIEW_FORWARD ) -DALI_ACTION_REGISTRATION( Toolkit, VideoView, "backward", ACTION_VIDEOVIEW_BACKWARD ) +DALI_ACTION_REGISTRATION(Toolkit, VideoView, "play", ACTION_VIDEOVIEW_PLAY) +DALI_ACTION_REGISTRATION(Toolkit, VideoView, "pause", ACTION_VIDEOVIEW_PAUSE) +DALI_ACTION_REGISTRATION(Toolkit, VideoView, "stop", ACTION_VIDEOVIEW_STOP) +DALI_ACTION_REGISTRATION(Toolkit, VideoView, "forward", ACTION_VIDEOVIEW_FORWARD) +DALI_ACTION_REGISTRATION(Toolkit, VideoView, "backward", ACTION_VIDEOVIEW_BACKWARD) DALI_TYPE_REGISTRATION_END() -const char* const VOLUME_LEFT( "volumeLeft" ); -const char* const VOLUME_RIGHT( "volumeRight" ); +const char* const VOLUME_LEFT("volumeLeft"); +const char* const VOLUME_RIGHT("volumeRight"); // 3.0 TC uses RENDERING_TARGET. It should be removed in next release -const char* const RENDERING_TARGET( "renderingTarget" ); -const char* const WINDOW_SURFACE_TARGET( "windowSurfaceTarget" ); -const char* const NATIVE_IMAGE_TARGET( "nativeImageTarget" ); - -const char* VERTEX_SHADER = DALI_COMPOSE_SHADER( - attribute mediump vec2 aPosition;\n - uniform mediump mat4 uMvpMatrix;\n - uniform mediump vec3 uSize;\n - \n - void main()\n - {\n - mediump vec4 vertexPosition = vec4(aPosition, 0.0, 1.0);\n - vertexPosition.xyz *= uSize;\n - gl_Position = uMvpMatrix * vertexPosition;\n - }\n -); - -const char* FRAGMENT_SHADER = DALI_COMPOSE_SHADER( - uniform lowp vec4 uColor;\n - uniform lowp vec3 mixColor;\n - uniform lowp float opacity;\n - \n - void main()\n - {\n - gl_FragColor = vec4(mixColor, opacity)*uColor;\n - }\n -); - -} // anonymous namepsace - -VideoView::VideoView() -: Control( ControlBehaviour( ACTOR_BEHAVIOUR_DEFAULT | DISABLE_STYLE_CHANGE_SIGNALS ) ), - mCurrentVideoPlayPosition( 0 ), - mIsPlay( false ), - mIsUnderlay( true ) -{ - mVideoPlayer = Dali::VideoPlayer::New(); +const char* const RENDERING_TARGET("renderingTarget"); +const char* const WINDOW_SURFACE_TARGET("windowSurfaceTarget"); +const char* const NATIVE_IMAGE_TARGET("nativeImageTarget"); + +const char* const CUSTOM_SHADER("shader"); +const char* const CUSTOM_VERTEX_SHADER("vertexShader"); +const char* const CUSTOM_FRAGMENT_SHADER("fragmentShader"); +const char* const DEFAULT_SAMPLER_TYPE_NAME("sampler2D"); +const char* const CUSTOM_SAMPLER_TYPE_NAME("samplerExternalOES"); + +const char* const IS_VIDEO_VIEW_PROPERTY_NAME = "isVideoView"; + +} // namespace + +VideoView::VideoView(Dali::VideoSyncMode syncMode) +: Control(ControlBehaviour(ACTOR_BEHAVIOUR_DEFAULT | DISABLE_STYLE_CHANGE_SIGNALS)), + mCurrentVideoPlayPosition(0), + mFrameID(0), + mIsPlay(false), + mIsUnderlay(true), + mSyncMode(syncMode), + mSiblingOrder(0) +{ } VideoView::~VideoView() { } -Toolkit::VideoView VideoView::New() +Toolkit::VideoView VideoView::New(VideoSyncMode syncMode) { - VideoView* impl = new VideoView(); - Toolkit::VideoView handle = Toolkit::VideoView( *impl ); + VideoView* impl = new VideoView(syncMode); + Toolkit::VideoView handle = Toolkit::VideoView(*impl); + impl->mVideoPlayer = Dali::VideoPlayer::New(impl->Self(), syncMode); impl->Initialize(); - return handle; } void VideoView::OnInitialize() { - mVideoPlayer.FinishedSignal().Connect( this, &VideoView::EmitSignalFinish ); - SetWindowSurfaceTarget(); + Actor self = Self(); + mVideoPlayer.FinishedSignal().Connect(this, &VideoView::EmitSignalFinish); + + DevelControl::SetAccessibilityConstructor(self, [](Dali::Actor actor) { + return std::unique_ptr( + new DevelControl::AccessibleImpl(actor, Dali::Accessibility::Role::VIDEO)); + }); + + //update self property + self.RegisterProperty(IS_VIDEO_VIEW_PROPERTY_NAME, true, Property::READ_WRITE); } -void VideoView::SetUrl( const std::string& url ) +void VideoView::SetUrl(const std::string& url) { - if( mUrl != url || !mPropertyMap.Empty() ) - { - mUrl = url; - mPropertyMap.Clear(); - } - - if( !mIsUnderlay ) - { - Actor self( Self() ); - Internal::InitializeVisual( self, mVisual, mNativeImage ); - } + mUrl = url; + mPropertyMap.Clear(); - mVideoPlayer.SetUrl( mUrl ); + mVideoPlayer.SetUrl(mUrl); } -void VideoView::SetPropertyMap( Property::Map map ) +void VideoView::SetPropertyMap(Property::Map map) { mPropertyMap = map; - Actor self( Self() ); - Internal::InitializeVisual( self, mVisual, mPropertyMap ); + Property::Value* target = map.Find(RENDERING_TARGET); + std::string targetType; - Property::Value* widthValue = mPropertyMap.Find( "width" ); - if( widthValue ) + if(target && target->Get(targetType) && targetType == WINDOW_SURFACE_TARGET) { - int width; - if( widthValue->Get( width ) ) - { - mVideoSize = ImageDimensions( width, mVideoSize.GetHeight() ); - } + mIsUnderlay = true; + SetWindowSurfaceTarget(); + } + else if(target && target->Get(targetType) && targetType == NATIVE_IMAGE_TARGET) + { + mIsUnderlay = false; + SetNativeImageTarget(); } - Property::Value* heightValue = mPropertyMap.Find( "height" ); - if( heightValue ) + // Custom shader + Property::Value* shaderValue; + if(!map.Empty()) { - int height; - if( heightValue->Get( height ) ) + shaderValue = map.Find(CUSTOM_SHADER); + + if(shaderValue) { - mVideoSize = ImageDimensions( mVideoSize.GetWidth(), height ); + Property::Map* shaderMap = shaderValue->GetMap(); + if(shaderMap) + { + mEffectPropertyMap = *shaderMap; + } } } - Property::Value* target = map.Find( RENDERING_TARGET ); - std::string targetType; - - if( target && target->Get( targetType ) && targetType == WINDOW_SURFACE_TARGET ) - { - mIsUnderlay = true; - SetWindowSurfaceTarget(); - } - else if( target && target->Get( targetType ) && targetType == NATIVE_IMAGE_TARGET ) + if(mTextureRenderer && !mEffectPropertyMap.Empty()) { - mIsUnderlay = false; - SetNativeImageTarget(); + Dali::Shader shader = CreateShader(); + mTextureRenderer.SetShader(shader); } RelayoutRequest(); @@ -205,7 +184,7 @@ std::string VideoView::GetUrl() void VideoView::SetLooping(bool looping) { - mVideoPlayer.SetLooping( looping ); + mVideoPlayer.SetLooping(looping); } bool VideoView::IsLooping() @@ -215,11 +194,6 @@ bool VideoView::IsLooping() void VideoView::Play() { - if( mIsUnderlay ) - { - Self().AddRenderer( mRenderer ); - } - mVideoPlayer.Play(); mIsPlay = true; } @@ -236,28 +210,28 @@ void VideoView::Stop() mIsPlay = false; } -void VideoView::Forward( int millisecond ) +void VideoView::Forward(int millisecond) { int curPos = mVideoPlayer.GetPlayPosition(); int nextPos = curPos + millisecond; - mVideoPlayer.SetPlayPosition( nextPos ); + mVideoPlayer.SetPlayPosition(nextPos); } -void VideoView::Backward( int millisecond ) +void VideoView::Backward(int millisecond) { int curPos = mVideoPlayer.GetPlayPosition(); int nextPos = curPos - millisecond; - nextPos = ( nextPos < 0 )? 0: nextPos; + nextPos = (nextPos < 0) ? 0 : nextPos; - mVideoPlayer.SetPlayPosition( nextPos ); + mVideoPlayer.SetPlayPosition(nextPos); } -void VideoView::SetMute( bool mute ) +void VideoView::SetMute(bool mute) { - mVideoPlayer.SetMute( mute ); + mVideoPlayer.SetMute(mute); } bool VideoView::IsMuted() @@ -265,14 +239,14 @@ bool VideoView::IsMuted() return mVideoPlayer.IsMuted(); } -void VideoView::SetVolume( float left, float right ) +void VideoView::SetVolume(float left, float right) { - mVideoPlayer.SetVolume( left, right ); + mVideoPlayer.SetVolume(left, right); } -void VideoView::GetVolume( float& left, float& right ) +void VideoView::GetVolume(float& left, float& right) { - mVideoPlayer.GetVolume( left, right ); + mVideoPlayer.GetVolume(left, right); } Dali::Toolkit::VideoView::VideoViewSignalType& VideoView::FinishedSignal() @@ -282,62 +256,57 @@ Dali::Toolkit::VideoView::VideoViewSignalType& VideoView::FinishedSignal() void VideoView::EmitSignalFinish() { - if( mIsUnderlay ) - { - Self().RemoveRenderer( mRenderer ); - } - - if ( !mFinishedSignal.Empty() ) + if(!mFinishedSignal.Empty()) { - Dali::Toolkit::VideoView handle( GetOwner() ); - mFinishedSignal.Emit( handle ); + Dali::Toolkit::VideoView handle(GetOwner()); + mFinishedSignal.Emit(handle); } } -bool VideoView::DoAction( BaseObject* object, const std::string& actionName, const Property::Map& attributes ) +bool VideoView::DoAction(BaseObject* object, const std::string& actionName, const Property::Map& attributes) { bool ret = false; - Dali::BaseHandle handle( object ); - Toolkit::VideoView videoView = Toolkit::VideoView::DownCast( handle ); + Dali::BaseHandle handle(object); + Toolkit::VideoView videoView = Toolkit::VideoView::DownCast(handle); - if( !videoView ) + if(!videoView) { return ret; } - VideoView& impl = GetImpl( videoView ); + VideoView& impl = GetImpl(videoView); - if( strcmp( actionName.c_str(), ACTION_VIDEOVIEW_PLAY ) == 0 ) + if(strcmp(actionName.c_str(), ACTION_VIDEOVIEW_PLAY) == 0) { impl.Play(); ret = true; } - else if( strcmp( actionName.c_str(), ACTION_VIDEOVIEW_PAUSE ) == 0 ) + else if(strcmp(actionName.c_str(), ACTION_VIDEOVIEW_PAUSE) == 0) { impl.Pause(); ret = true; } - else if( strcmp( actionName.c_str(), ACTION_VIDEOVIEW_STOP ) == 0 ) + else if(strcmp(actionName.c_str(), ACTION_VIDEOVIEW_STOP) == 0) { impl.Stop(); ret = true; } - else if( strcmp( actionName.c_str(), ACTION_VIDEOVIEW_FORWARD ) == 0 ) + else if(strcmp(actionName.c_str(), ACTION_VIDEOVIEW_FORWARD) == 0) { int millisecond = 0; - if( attributes["videoForward"].Get( millisecond ) ) + if(attributes["videoForward"].Get(millisecond)) { - impl.Forward( millisecond ); + impl.Forward(millisecond); ret = true; } } - else if( strcmp( actionName.c_str(), ACTION_VIDEOVIEW_BACKWARD ) == 0 ) + else if(strcmp(actionName.c_str(), ACTION_VIDEOVIEW_BACKWARD) == 0) { int millisecond = 0; - if( attributes["videoBackward"].Get( millisecond ) ) + if(attributes["videoBackward"].Get(millisecond)) { - impl.Backward( millisecond ); + impl.Backward(millisecond); ret = true; } } @@ -345,16 +314,16 @@ bool VideoView::DoAction( BaseObject* object, const std::string& actionName, con return ret; } -bool VideoView::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor ) +bool VideoView::DoConnectSignal(BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor) { - Dali::BaseHandle handle( object ); + Dali::BaseHandle handle(object); - bool connected( true ); - Toolkit::VideoView videoView = Toolkit::VideoView::DownCast( handle ); + bool connected(true); + Toolkit::VideoView videoView = Toolkit::VideoView::DownCast(handle); - if( 0 == strcmp( signalName.c_str(), FINISHED_SIGNAL ) ) + if(0 == strcmp(signalName.c_str(), FINISHED_SIGNAL)) { - videoView.FinishedSignal().Connect( tracker, functor ); + videoView.FinishedSignal().Connect(tracker, functor); } else { @@ -365,114 +334,125 @@ bool VideoView::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* return connected; } -void VideoView::SetProperty( BaseObject* object, Property::Index index, const Property::Value& value ) +void VideoView::SetPropertyInternal(Property::Index index, const Property::Value& value) { - Toolkit::VideoView videoView = Toolkit::VideoView::DownCast( Dali::BaseHandle( object ) ); - - if( videoView ) + switch(index) { - VideoView& impl = GetImpl( videoView ); + case Toolkit::VideoView::Property::VIDEO: + { + std::string videoUrl; + Property::Map map; - switch( index ) + if(value.Get(videoUrl)) + { + SetUrl(videoUrl); + } + else if(value.Get(map)) + { + SetPropertyMap(map); + } + break; + } + case Toolkit::VideoView::Property::LOOPING: { - case Toolkit::VideoView::Property::VIDEO: + bool looping; + if(value.Get(looping)) { - std::string videoUrl; - Property::Map map; - - if( value.Get( videoUrl ) ) - { - impl.SetUrl( videoUrl ); - } - else if( value.Get( map ) ) - { - Property::Value* shaderValue = map.Find( Toolkit::Visual::Property::SHADER, CUSTOM_SHADER ); - - if( map.Count() > 1u || !shaderValue ) - { - impl.SetPropertyMap( map ); - } - else if( impl.mVisual && map.Count() == 1u && shaderValue ) - { - Property::Map shaderMap; - if( shaderValue->Get( shaderMap ) ) - { - Internal::Visual::Base& visual = Toolkit::GetImplementation( impl.mVisual ); - visual.SetCustomShader( shaderMap ); - if( videoView.OnStage() ) - { - visual.SetOffStage( videoView ); - visual.SetOnStage( videoView ); - } - } - } - } - break; + SetLooping(looping); } - case Toolkit::VideoView::Property::LOOPING: + break; + } + case Toolkit::VideoView::Property::MUTED: + { + bool mute; + if(value.Get(mute)) { - bool looping; - if( value.Get( looping ) ) - { - impl.SetLooping( looping ); - } - break; + SetMute(mute); } - case Toolkit::VideoView::Property::MUTED: + break; + } + case Toolkit::VideoView::Property::VOLUME: + { + Property::Map map; + float left, right; + if(value.Get(map)) { - bool mute; - if( value.Get( mute ) ) + Property::Value* volumeLeft = map.Find(VOLUME_LEFT); + Property::Value* volumeRight = map.Find(VOLUME_RIGHT); + if(volumeLeft && volumeLeft->Get(left) && volumeRight && volumeRight->Get(right)) { - impl.SetMute( mute ); + SetVolume(left, right); } - break; } - case Toolkit::VideoView::Property::VOLUME: + break; + } + case Toolkit::VideoView::Property::UNDERLAY: + { + bool underlay; + if(value.Get(underlay)) { - Property::Map map; - float left, right; - if( value.Get( map ) ) - { - Property::Value* volumeLeft = map.Find( VOLUME_LEFT ); - Property::Value* volumeRight = map.Find( VOLUME_RIGHT ); - if( volumeLeft && volumeLeft->Get( left ) && volumeRight && volumeRight->Get( right ) ) - { - impl.SetVolume( left, right ); - } - } - break; + SetUnderlay(underlay); } - case Toolkit::VideoView::Property::UNDERLAY: + break; + } + case Toolkit::VideoView::Property::PLAY_POSITION: + { + int pos; + if(value.Get(pos)) { - bool underlay; - if( value.Get( underlay ) ) - { - impl.SetUnderlay( underlay ); - } - break; + SetPlayPosition(pos); + } + break; + } + case Toolkit::VideoView::Property::DISPLAY_MODE: + { + int mode; + if(value.Get(mode)) + { + SetDisplayMode(mode); } + break; } } } -Property::Value VideoView::GetProperty( BaseObject* object, Property::Index propertyIndex ) +void VideoView::SetProperty(BaseObject* object, Property::Index index, const Property::Value& value) { - Property::Value value; - Toolkit::VideoView videoView = Toolkit::VideoView::DownCast( Dali::BaseHandle( object ) ); + Toolkit::VideoView videoView = Toolkit::VideoView::DownCast(Dali::BaseHandle(object)); - if( videoView ) + if(videoView) { - VideoView& impl = GetImpl( videoView ); + VideoView& impl = GetImpl(videoView); - switch( propertyIndex ) + impl.SetPropertyInternal(index, value); + + if(index != Toolkit::VideoView::Property::UNDERLAY) + { + // Backup values. + // These values will be used when underlay mode is changed. + impl.mPropertyBackup[index] = value; + } + } +} + +Property::Value VideoView::GetProperty(BaseObject* object, Property::Index propertyIndex) +{ + Property::Value value; + Toolkit::VideoView videoView = Toolkit::VideoView::DownCast(Dali::BaseHandle(object)); + + if(videoView) + { + VideoView& impl = GetImpl(videoView); + + switch(propertyIndex) { case Toolkit::VideoView::Property::VIDEO: { - if( !impl.mUrl.empty() ) + if(!impl.mUrl.empty()) { value = impl.mUrl; } - else if( !impl.mPropertyMap.Empty() ) + else if(!impl.mPropertyMap.Empty()) { value = impl.mPropertyMap; } @@ -491,11 +471,11 @@ Property::Value VideoView::GetProperty( BaseObject* object, Property::Index prop case Toolkit::VideoView::Property::VOLUME: { Property::Map map; - float left, right; + float left, right; - impl.GetVolume( left, right ); - map.Insert( VOLUME_LEFT, left ); - map.Insert( VOLUME_RIGHT, right ); + impl.GetVolume(left, right); + map.Insert(VOLUME_LEFT, left); + map.Insert(VOLUME_RIGHT, right); value = map; break; } @@ -504,40 +484,107 @@ Property::Value VideoView::GetProperty( BaseObject* object, Property::Index prop value = impl.IsUnderlay(); break; } + case Toolkit::VideoView::Property::PLAY_POSITION: + { + value = impl.GetPlayPosition(); + break; + } + case Toolkit::VideoView::Property::DISPLAY_MODE: + { + value = impl.GetDisplayMode(); + break; + } } } return value; } -void VideoView::SetDepthIndex( int depthIndex ) +void VideoView::SetDepthIndex(int depthIndex) { - if( mVisual ) + if(mTextureRenderer) { - mVisual.SetDepthIndex( depthIndex ); + mTextureRenderer.SetProperty(Renderer::Property::DEPTH_INDEX, depthIndex); } } -void VideoView::OnStageConnection( int depth ) +void VideoView::OnSceneConnection(int depth) { - if( mVisual ) + Actor self = Self(); + if(mIsUnderlay) { - CustomActor self = Self(); - Toolkit::GetImplementation(mVisual).SetOnStage( self ); + mSiblingOrder = self.GetProperty(Dali::DevelActor::Property::SIBLING_ORDER); + DevelActor::ChildOrderChangedSignal(self.GetParent()).Connect(this, &VideoView::OnChildOrderChanged); + SetWindowSurfaceTarget(); } - Control::OnStageConnection( depth ); + Control::OnSceneConnection(depth); +} + +void VideoView::OnSceneDisconnection() +{ + Control::OnSceneDisconnection(); } -void VideoView::OnStageDisconnection() +void VideoView::OnSizeSet(const Vector3& targetSize) { - if( mVisual ) + if(mIsUnderlay && mSyncMode == Dali::VideoSyncMode::ENABLED) { - CustomActor self = Self(); - Toolkit::GetImplementation(mVisual).SetOffStage( self ); + SetFrameRenderCallback(); + mVideoPlayer.StartSynchronization(); } + Control::OnSizeSet(targetSize); +} + +void VideoView::OnChildOrderChanged(Actor actor) +{ + Actor self = Self(); + int currentSiblingOrder = self.GetProperty(Dali::DevelActor::Property::SIBLING_ORDER); + if(currentSiblingOrder != mSiblingOrder) + { + Actor parent = self.GetParent(); + Actor child; + Actor upper; + Actor lower; + + int numChildren = static_cast(parent.GetChildCount()); + for(int i = 0; i < numChildren; i++) + { + child = parent.GetChildAt(i); + if(!IsVideoView(child)) + { + continue; + } + + if(child == self) + { + continue; + } - Control::OnStageDisconnection(); + if(i < currentSiblingOrder) + { + lower = child; + } + else if(i > currentSiblingOrder) + { + upper = child; + break; + } + } + + if(lower) + { + Toolkit::VideoView lowerView = Toolkit::VideoView::DownCast(lower); + mVideoPlayer.RaiseAbove(GetImpl(lowerView).GetVideoPlayer()); + } + + if(upper) + { + Toolkit::VideoView upperView = Toolkit::VideoView::DownCast(upper); + mVideoPlayer.LowerBelow(GetImpl(upperView).GetVideoPlayer()); + } + mSiblingOrder = currentSiblingOrder; + } } Vector3 VideoView::GetNaturalSize() @@ -546,9 +593,9 @@ Vector3 VideoView::GetNaturalSize() size.x = mVideoSize.GetWidth(); size.y = mVideoSize.GetHeight(); - if( size.x > 0 && size.y > 0 ) + if(size.x > 0 && size.y > 0) { - size.z = std::min( size.x, size.y ); + size.z = std::min(size.x, size.y); return size; } else @@ -557,156 +604,186 @@ Vector3 VideoView::GetNaturalSize() } } -float VideoView::GetHeightForWidth( float width ) +float VideoView::GetHeightForWidth(float width) { - if( mVideoSize.GetWidth() > 0 && mVideoSize.GetHeight() > 0 ) + if(mVideoSize.GetWidth() > 0 && mVideoSize.GetHeight() > 0) { - return GetHeightForWidthBase( width ); + return GetHeightForWidthBase(width); } else { - return Control::GetHeightForWidthBase( width ); + return Control::GetHeightForWidthBase(width); } } -float VideoView::GetWidthForHeight( float height ) +float VideoView::GetWidthForHeight(float height) { - if( mVideoSize.GetWidth() > 0 && mVideoSize.GetHeight() > 0 ) + if(mVideoSize.GetWidth() > 0 && mVideoSize.GetHeight() > 0) { - return GetWidthForHeightBase( height ); + return GetWidthForHeightBase(height); } else { - return Control::GetWidthForHeightBase( height ); + return Control::GetWidthForHeightBase(height); } } void VideoView::SetWindowSurfaceTarget() { Actor self = Self(); - int curPos = mVideoPlayer.GetPlayPosition(); - if( mVisual ) + if(!self.GetProperty(Actor::Property::CONNECTED_TO_SCENE)) { - Toolkit::GetImplementation(mVisual).SetOffStage(self); - mVisual.Reset(); + // When the control is off the stage, it does not have Window. + return; } - if( mIsPlay ) + Dali::Window window = DevelWindow::Get(self); + window.ResizeSignal().Connect(this, &VideoView::OnWindowResized); + + int curPos = mVideoPlayer.GetPlayPosition(); + + if(mIsPlay) { mVideoPlayer.Pause(); } - mPositionUpdateNotification = self.AddPropertyNotification( Actor::Property::WORLD_POSITION, StepCondition( 1.0f, 1.0f ) ); - mSizeUpdateNotification = self.AddPropertyNotification( Actor::Property::SIZE, StepCondition( 1.0f, 1.0f ) ); - mScaleUpdateNotification = self.AddPropertyNotification( Actor::Property::WORLD_SCALE, StepCondition( 0.1f, 1.0f ) ); - mPositionUpdateNotification.NotifySignal().Connect( this, &VideoView::UpdateDisplayArea ); - mSizeUpdateNotification.NotifySignal().Connect( this, &VideoView::UpdateDisplayArea ); - mScaleUpdateNotification.NotifySignal().Connect( this, &VideoView::UpdateDisplayArea ); + mPositionUpdateNotification = self.AddPropertyNotification(Actor::Property::WORLD_POSITION, StepCondition(1.0f, 1.0f)); + mSizeUpdateNotification = self.AddPropertyNotification(Actor::Property::SIZE, StepCondition(1.0f, 1.0f)); + mScaleUpdateNotification = self.AddPropertyNotification(Actor::Property::WORLD_SCALE, StepCondition(0.1f, 1.0f)); + mPositionUpdateNotification.NotifySignal().Connect(this, &VideoView::UpdateDisplayArea); + mSizeUpdateNotification.NotifySignal().Connect(this, &VideoView::UpdateDisplayArea); + mScaleUpdateNotification.NotifySignal().Connect(this, &VideoView::UpdateDisplayArea); + + if(mTextureRenderer) + { + self.RemoveRenderer(mTextureRenderer); + } + + // Note VideoPlayer::SetRenderingTarget resets all the options. (e.g. url, mute, looping) + mVideoPlayer.SetRenderingTarget(Dali::Adaptor::Get().GetNativeWindowHandle(self)); - mVideoPlayer.SetRenderingTarget( Dali::Adaptor::Get().GetNativeWindowHandle() ); - mVideoPlayer.SetUrl( mUrl ); + ApplyBackupProperties(); - if( !mRenderer ) + if(!mOverlayRenderer) { // For underlay rendering mode, video display area have to be transparent. Geometry geometry = VisualFactoryCache::CreateQuadGeometry(); - Shader shader = Shader::New( VERTEX_SHADER, FRAGMENT_SHADER ); - mRenderer = Renderer::New( geometry, shader ); - - mRenderer.SetProperty( Renderer::Property::BLEND_MODE, BlendMode::ON ); - mRenderer.SetProperty( Renderer::Property::BLEND_FACTOR_SRC_RGB, BlendFactor::ONE ); - mRenderer.SetProperty( Renderer::Property::BLEND_FACTOR_DEST_RGB, BlendFactor::ZERO ); - mRenderer.SetProperty( Renderer::Property::BLEND_FACTOR_SRC_ALPHA, BlendFactor::ONE ); - mRenderer.SetProperty( Renderer::Property::BLEND_FACTOR_DEST_ALPHA, BlendFactor::ZERO ); + Shader shader = Shader::New(SHADER_VIDEO_VIEW_VERT, SHADER_VIDEO_VIEW_FRAG); + mOverlayRenderer = Renderer::New(geometry, shader); + mOverlayRenderer.SetProperty(Renderer::Property::BLEND_MODE, BlendMode::OFF); } + Self().AddRenderer(mOverlayRenderer); - if( mIsPlay ) + if(mIsPlay) { Play(); } - if( curPos > 0 ) + if(curPos > 0) { - mVideoPlayer.SetPlayPosition( curPos ); + mVideoPlayer.SetPlayPosition(curPos); } } void VideoView::SetNativeImageTarget() { - if( mVideoPlayer.IsVideoTextureSupported() == false ) + if(mVideoPlayer.IsVideoTextureSupported() == false) { - DALI_LOG_ERROR( "Platform doesn't support decoded video frame images\n" ); + DALI_LOG_ERROR("Platform doesn't support decoded video frame images\n"); mIsUnderlay = true; return; } - if( mIsPlay ) + if(mIsPlay) { mVideoPlayer.Pause(); } - Actor self( Self() ); - self.RemoveRenderer( mRenderer ); - Dali::Stage::GetCurrent().KeepRendering( 0.0f ); + Actor self(Self()); + + if(mOverlayRenderer) + { + self.RemoveRenderer(mOverlayRenderer); + + mOverlayRenderer.Reset(); + } - self.RemovePropertyNotification( mPositionUpdateNotification ); - self.RemovePropertyNotification( mSizeUpdateNotification ); - self.RemovePropertyNotification( mScaleUpdateNotification ); + self.RemovePropertyNotification(mPositionUpdateNotification); + self.RemovePropertyNotification(mSizeUpdateNotification); + self.RemovePropertyNotification(mScaleUpdateNotification); int curPos = mVideoPlayer.GetPlayPosition(); - Any source; - Dali::NativeImageSourcePtr nativeImageSourcePtr = Dali::NativeImageSource::New( source ); - mNativeImage = Dali::NativeImage::New( *nativeImageSourcePtr ); + Any source; + Dali::NativeImageSourcePtr nativeImageSourcePtr = Dali::NativeImageSource::New(source); + mNativeTexture = Dali::Texture::New(*nativeImageSourcePtr); + + if(!mTextureRenderer) + { + Dali::Geometry geometry = VisualFactoryCache::CreateQuadGeometry(); + Dali::Shader shader = CreateShader(); + Dali::TextureSet textureSet = Dali::TextureSet::New(); + textureSet.SetTexture(0u, mNativeTexture); + + mTextureRenderer = Renderer::New(geometry, shader); + mTextureRenderer.SetTextures(textureSet); + } + else + { + Dali::TextureSet textureSet = mTextureRenderer.GetTextures(); + textureSet.SetTexture(0u, mNativeTexture); + } + Self().AddRenderer(mTextureRenderer); - mVideoPlayer.SetRenderingTarget( nativeImageSourcePtr ); - mVideoPlayer.SetUrl( mUrl ); + // Note VideoPlayer::SetRenderingTarget resets all the options. (e.g. url, mute, looping) + mVideoPlayer.SetRenderingTarget(nativeImageSourcePtr); - Internal::InitializeVisual( self, mVisual, mNativeImage ); - Self().RemoveRenderer( mRenderer ); + ApplyBackupProperties(); - if( mIsPlay ) + if(mIsPlay) { Play(); } - if( curPos > 0 ) + if(curPos > 0) { - mVideoPlayer.SetPlayPosition( curPos ); + mVideoPlayer.SetPlayPosition(curPos); } } -void VideoView::UpdateDisplayArea( Dali::PropertyNotification& source ) +void VideoView::UpdateDisplayArea(Dali::PropertyNotification& source) { - if( !mIsUnderlay ) + // If mSyncMode is enabled, Video player's size and poistion is updated in Video player's constraint. + // Because video view and player should be work syncronization. + if(!mIsUnderlay || mSyncMode == Dali::VideoSyncMode::ENABLED) { return; } - Actor self( Self() ); + Actor self(Self()); - bool positionUsesAnchorPoint = self.GetProperty( DevelActor::Property::POSITION_USES_ANCHOR_POINT ).Get< bool >(); - Vector3 actorSize = self.GetCurrentSize() * self.GetCurrentScale(); - Vector3 anchorPointOffSet = actorSize * ( positionUsesAnchorPoint ? self.GetCurrentAnchorPoint() : AnchorPoint::TOP_LEFT ); + bool positionUsesAnchorPoint = self.GetProperty(Actor::Property::POSITION_USES_ANCHOR_POINT).Get(); + Vector3 actorSize = self.GetCurrentProperty(Actor::Property::SIZE) * self.GetCurrentProperty(Actor::Property::SCALE); + Vector3 anchorPointOffSet = actorSize * (positionUsesAnchorPoint ? self.GetCurrentProperty(Actor::Property::ANCHOR_POINT) : AnchorPoint::TOP_LEFT); - Vector2 screenPosition = self.GetProperty( DevelActor::Property::SCREEN_POSITION ).Get< Vector2 >(); + Vector2 screenPosition = self.GetProperty(Actor::Property::SCREEN_POSITION).Get(); - mDisplayArea.x = screenPosition.x - anchorPointOffSet.x; - mDisplayArea.y = screenPosition.y - anchorPointOffSet.y; - mDisplayArea.width = actorSize.x; + mDisplayArea.x = screenPosition.x - anchorPointOffSet.x; + mDisplayArea.y = screenPosition.y - anchorPointOffSet.y; + mDisplayArea.width = actorSize.x; mDisplayArea.height = actorSize.y; - mVideoPlayer.SetDisplayArea( mDisplayArea ); + mVideoPlayer.SetDisplayArea(mDisplayArea); } -void VideoView::SetUnderlay( bool set ) +void VideoView::SetUnderlay(bool set) { - if( set != mIsUnderlay ) + if(set != mIsUnderlay) { mIsUnderlay = set; - if( mIsUnderlay ) + if(mIsUnderlay) { SetWindowSurfaceTarget(); } @@ -724,8 +801,183 @@ bool VideoView::IsUnderlay() return mIsUnderlay; } +void VideoView::SetSWCodec(bool on) +{ + // If setting SW or HW type is failed , video-view shows video by default codec type. + // The default codec type is selected by platform. + if(on) + { + mVideoPlayer.SetCodecType(Dali::VideoPlayerPlugin::CodecType::SW); + } + else + { + mVideoPlayer.SetCodecType(Dali::VideoPlayerPlugin::CodecType::HW); + } +} + +int VideoView::GetPlayPosition() +{ + return mVideoPlayer.GetPlayPosition(); +} + +void VideoView::SetPlayPosition(int pos) +{ + mVideoPlayer.SetPlayPosition(pos); +} + +void VideoView::SetDisplayMode(int mode) +{ + mVideoPlayer.SetDisplayMode(static_cast(mode)); +} + +int VideoView::GetDisplayMode() const +{ + return static_cast(mVideoPlayer.GetDisplayMode()); +} + +Any VideoView::GetMediaPlayer() +{ + return mVideoPlayer.GetMediaPlayer(); +} + +void VideoView::OnAnimationFinished(Animation& animation) +{ + // send desync + SetFrameRenderCallback(); +} + +void VideoView::OnWindowResized(Dali::Window winHandle, Dali::Window::WindowSize size) +{ + Dali::VideoPlayerPlugin::DisplayRotation videoAngle = mVideoPlayer.GetDisplayRotation(); + int windowAngle = (DevelWindow::GetPhysicalOrientation(winHandle) / 90); + + if(windowAngle != videoAngle) + { + mVideoPlayer.SetDisplayRotation(static_cast(windowAngle)); + } +} + +void VideoView::PlayAnimation(Dali::Animation animation) +{ + if(mIsUnderlay && mSyncMode == Dali::VideoSyncMode::ENABLED) + { + mVideoPlayer.StartSynchronization(); + animation.FinishedSignal().Connect(this, &VideoView::OnAnimationFinished); + } + animation.Play(); +} + +Dali::Shader VideoView::CreateShader() +{ + std::string fragmentShader = "#extension GL_OES_EGL_image_external:require\n"; + std::string vertexShader; + std::string customFragmentShader; + bool checkShader = false; + + if(!mEffectPropertyMap.Empty()) + { + Property::Value* vertexShaderValue = mEffectPropertyMap.Find(CUSTOM_VERTEX_SHADER); + if(vertexShaderValue) + { + checkShader = GetStringFromProperty(*vertexShaderValue, vertexShader); + } + + if(!vertexShaderValue || !checkShader) + { + vertexShader = SHADER_VIDEO_VIEW_TEXTURE_VERT.data(); + } + + Property::Value* fragmentShaderValue = mEffectPropertyMap.Find(CUSTOM_FRAGMENT_SHADER); + if(fragmentShaderValue) + { + checkShader = GetStringFromProperty(*fragmentShaderValue, customFragmentShader); + + if(checkShader) + { + fragmentShader = customFragmentShader; + } + } + + if(!fragmentShaderValue || !checkShader) + { + fragmentShader += SHADER_VIDEO_VIEW_TEXTURE_FRAG.data(); + } + } + else + { + vertexShader = SHADER_VIDEO_VIEW_TEXTURE_VERT.data(); + fragmentShader += SHADER_VIDEO_VIEW_TEXTURE_FRAG.data(); + } + + return Dali::Shader::New(vertexShader, fragmentShader); +} + +bool VideoView::GetStringFromProperty(const Dali::Property::Value& value, std::string& output) +{ + bool extracted = false; + if(value.Get(output)) + { + extracted = true; + } + + return extracted; +} + +void VideoView::ApplyBackupProperties() +{ + Property::Map::SizeType pos = 0; + Property::Map::SizeType count = mPropertyBackup.Count(); + + for(; pos < count; pos++) + { + KeyValuePair property = mPropertyBackup.GetKeyValue(pos); + + SetPropertyInternal(property.first.indexKey, property.second); + } +} + +void VideoView::FrameRenderCallback(int frameID) +{ + // send desync + if(frameID == mFrameID) + { + mVideoPlayer.FinishSynchronization(); + mFrameID = 0; + } +} + +void VideoView::SetFrameRenderCallback() +{ + mFrameID++; + DevelWindow::AddFrameRenderedCallback(DevelWindow::Get(Self()), + std::unique_ptr(MakeCallback(this, &VideoView::FrameRenderCallback)), + mFrameID); +} + +bool VideoView::IsVideoView(Actor actor) const +{ + // Check whether the actor is a VideoView + bool isVideoView = false; + + if(actor) + { + Property::Index propertyIsVideoView = actor.GetPropertyIndex(IS_VIDEO_VIEW_PROPERTY_NAME); + if(propertyIsVideoView != Property::INVALID_INDEX) + { + isVideoView = actor.GetProperty(propertyIsVideoView); + } + } + + return isVideoView; +} + +VideoPlayer VideoView::GetVideoPlayer() +{ + return mVideoPlayer; +} + } // namespace Internal -} // namespace toolkit +} // namespace Toolkit } // namespace Dali