From: taeyoon Date: Wed, 16 Mar 2016 07:45:31 +0000 (+0900) Subject: Video player plugin for video view control X-Git-Tag: dali_1.1.39~3 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=5cfa51b6e93f4464a0949901692695c9569c26be;p=platform%2Fcore%2Fuifw%2Fdali-adaptor.git Video player plugin for video view control Add plugin for video playback in tizen wayland Change-Id: Ifaf9d3cf016bcfe7f2f9f37bbaf86aad73480acd --- diff --git a/adaptors/common/adaptor.cpp b/adaptors/common/adaptor.cpp index e0af921..9c6701c 100644 --- a/adaptors/common/adaptor.cpp +++ b/adaptors/common/adaptor.cpp @@ -104,6 +104,11 @@ RenderSurface& Adaptor::GetSurface() return mImpl->GetSurface(); } +Any Adaptor::GetNativeWindowHandle() +{ + return mImpl->GetNativeWindowHandle(); +} + void Adaptor::ReleaseSurfaceLock() { mImpl->ReleaseSurfaceLock(); diff --git a/adaptors/common/file.list b/adaptors/common/file.list index 35ef1db..c9c39b7 100644 --- a/adaptors/common/file.list +++ b/adaptors/common/file.list @@ -31,19 +31,16 @@ adaptor_common_internal_src_files = \ $(adaptor_common_dir)/watch-application-impl.cpp \ $(adaptor_common_dir)/watch-time.cpp \ $(adaptor_common_dir)/key-impl.cpp \ - \ + $(adaptor_common_dir)/video-player-impl.cpp \ $(adaptor_common_dir)/events/gesture-manager.cpp \ $(adaptor_common_dir)/events/long-press-gesture-detector.cpp \ $(adaptor_common_dir)/events/pan-gesture-detector-base.cpp \ $(adaptor_common_dir)/events/pan-gesture-detector.cpp \ $(adaptor_common_dir)/events/pinch-gesture-detector.cpp \ $(adaptor_common_dir)/events/tap-gesture-detector.cpp \ - \ $(adaptor_common_dir)/networking/socket-impl.cpp \ $(adaptor_common_dir)/networking/socket-factory.cpp \ - \ $(adaptor_common_dir)/feedback/feedback-plugin-proxy.cpp \ - \ $(adaptor_common_dir)/gl/egl-factory.cpp \ $(adaptor_common_dir)/gl/egl-implementation.cpp \ $(adaptor_common_dir)/gl/egl-sync-implementation.cpp \ diff --git a/adaptors/common/video-player-impl.cpp b/adaptors/common/video-player-impl.cpp new file mode 100644 index 0000000..d6c818c --- /dev/null +++ b/adaptors/common/video-player-impl.cpp @@ -0,0 +1,266 @@ +/* + * Copyright (c) 2016 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// CLASS HEADER +#include + +// EXTERNAL INCLUDES +#include +#include +#include +#include + +// INTERNAL INCLUDES +#include + +namespace Dali +{ + +namespace Internal +{ + +namespace Adaptor +{ + +namespace // unnamed namespace +{ +const char* VIDEO_PLUGIN_SO( "libdali-video-player-plugin.so" ); + +Dali::BaseHandle Create() +{ + return Dali::VideoPlayer::New(); +} + +Dali::TypeRegistration type( typeid( Dali::VideoPlayer ), typeid( Dali::BaseHandle ), Create ); + +} // unnamed namespace + +VideoPlayerPtr VideoPlayer::New() +{ + VideoPlayerPtr player = new VideoPlayer(); + return player; +} + +VideoPlayer::VideoPlayer() +: mPlugin( NULL ), + mHandle( NULL ), + mCreateVideoPlayerPtr( NULL ), + mDestroyVideoPlayerPtr( NULL ) +{ +} + +VideoPlayer::~VideoPlayer() +{ + if( mHandle != NULL ) + { + if( mDestroyVideoPlayerPtr != NULL ) + { + mDestroyVideoPlayerPtr( mPlugin ); + } + + dlclose( mHandle ); + } +} + +void VideoPlayer::Initialize() +{ + char* error = NULL; + + mHandle = dlopen( VIDEO_PLUGIN_SO, RTLD_LAZY ); + + error = dlerror(); + if( mHandle == NULL || error != NULL ) + { + DALI_LOG_ERROR( "VideoPlayer::Initialize(), dlopen error: %s\n", error ); + return; + } + + mCreateVideoPlayerPtr = reinterpret_cast< CreateVideoPlayerFunction >( dlsym( mHandle, "CreateVideoPlayerPlugin" ) ); + if( mCreateVideoPlayerPtr == NULL ) + { + DALI_LOG_ERROR( "Can't load symbol CreateVideoPlayerPlugin(), error: %s\n", error ); + return; + } + + mPlugin = mCreateVideoPlayerPtr(); + + if( mPlugin == NULL ) + { + DALI_LOG_ERROR( "Can't create the VideoPlayerPlugin object" ); + return; + } + + mDestroyVideoPlayerPtr = reinterpret_cast< DestroyVideoPlayerFunction >( dlsym( mHandle, "DestroyVideoPlayerPlugin" ) ); + if( mDestroyVideoPlayerPtr == NULL ) + { + DALI_LOG_ERROR( "Can't load symbol DestroyVideoPlayerPlugin(), error: %s\n", error ); + return; + } + +} + +void VideoPlayer::SetUrl( const std::string& url ) +{ + if( mPlugin != NULL ) + { + mPlugin->SetUrl( url ); + } +} + +std::string VideoPlayer::GetUrl() +{ + if( mPlugin != NULL ) + { + return mPlugin->GetUrl(); + } + + return std::string( NULL ); +} + +void VideoPlayer::SetLooping(bool looping) +{ + if( mPlugin != NULL ) + { + mPlugin->SetLooping( looping ); + } +} + +bool VideoPlayer::IsLooping() +{ + if( mPlugin != NULL ) + { + return mPlugin->IsLooping(); + } + + return false; +} + +void VideoPlayer::Play() +{ + if( mPlugin != NULL ) + { + mPlugin->Play(); + } +} + +void VideoPlayer::Pause() +{ + if( mPlugin != NULL ) + { + mPlugin->Pause(); + } +} + +void VideoPlayer::Stop() +{ + if( mPlugin != NULL ) + { + mPlugin->Stop(); + } +} + +void VideoPlayer::SetMute( bool mute ) +{ + if( mPlugin != NULL ) + { + mPlugin->SetMute( mute ); + } +} + +bool VideoPlayer::IsMuted() +{ + if( mPlugin != NULL ) + { + return mPlugin->IsMuted(); + } + + return false; +} + +void VideoPlayer::SetVolume( float left, float right ) +{ + if( mPlugin != NULL ) + { + mPlugin->SetVolume( left, right ); + } +} + +void VideoPlayer::GetVolume( float& left, float& right ) +{ + if( mPlugin != NULL ) + { + mPlugin->GetVolume( left, right ); + } +} + +void VideoPlayer::SetRenderingTarget( Dali::Any target ) +{ + if( mPlugin != NULL ) + { + mPlugin->SetRenderingTarget( target ); + } +} + +void VideoPlayer::SetPlayPosition( int millisecond ) +{ + if( mPlugin != NULL ) + { + mPlugin->SetPlayPosition( millisecond ); + } +} + +int VideoPlayer::GetPlayPosition() +{ + if( mPlugin != NULL ) + { + return mPlugin->GetPlayPosition(); + } + return 0; +} + +void VideoPlayer::SetDisplayRotation( Dali::VideoPlayerPlugin::DisplayRotation rotation ) +{ + if( mPlugin != NULL ) + { + mPlugin->SetDisplayRotation( rotation ); + } +} + +Dali::VideoPlayerPlugin::DisplayRotation VideoPlayer::GetDisplayRotation() +{ + if( mPlugin != NULL ) + { + return mPlugin->GetDisplayRotation(); + } + + return Dali::VideoPlayerPlugin::ROTATION_NONE; +} + +Dali::VideoPlayerPlugin::VideoPlayerSignalType& VideoPlayer::FinishedSignal() +{ + if( mPlugin != NULL ) + { + return mPlugin->FinishedSignal(); + } + + return mFinishedSignal; +} + +} // namespace Adaptor; +} // namespace Internal; +} // namespace Dali; + diff --git a/adaptors/common/video-player-impl.h b/adaptors/common/video-player-impl.h new file mode 100644 index 0000000..4424217 --- /dev/null +++ b/adaptors/common/video-player-impl.h @@ -0,0 +1,205 @@ +#ifndef __DALI_VIDEO_PLAYER_IMPL_H__ +#define __DALI_VIDEO_PLAYER_IMPL_H__ + +/* + * Copyright (c) 2016 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// EXTERNAL INCLUDES +#include + +// INTERNAL INCLUDES +#include +#include + +namespace Dali +{ +class Any; + +namespace Internal +{ + +namespace Adaptor +{ + +class VideoPlayer; + +typedef IntrusivePtr< VideoPlayer > VideoPlayerPtr; + +/** + * @brief VideoPlayer class is used for video playback. + * @SINCE_1_1.24 + */ +class VideoPlayer: public Dali::BaseObject +{ +public: + + /** + * @brief Creates a new VideoPlayer handle + * @SINCE_1_1.24 + * @return VideoPlayer pointer + */ + static VideoPlayerPtr New(); + + /** + * @copydoc Dali::VideoPlayer::SetUrl() + */ + void SetUrl( const std::string& url ); + + /** + * @copydoc Dali::VideoPlayer::GetUrl() + */ + std::string GetUrl(); + + /** + * @copydoc Dali::VideoPlayer::SetLooping() + */ + void SetLooping(bool looping); + + /** + * @copydoc Dali::VideoPlayer::IsLooping() + */ + bool IsLooping(); + + /** + * @copydoc Dali::VideoPlayer::Play() + */ + void Play(); + + /** + * @copydoc Dali::VideoPlayer::Pause() + */ + void Pause(); + + /** + * @copydoc Dali::VideoPlayer::Stop() + */ + void Stop(); + + /** + * @copydoc Dali::VideoPlayer::SetMute() + */ + void SetMute( bool mute ); + + /** + * @copydoc Dali::VideoPlayer::IsMuted() + */ + bool IsMuted(); + + /** + * @copydoc Dali::VideoPlayer::SetVolume() + */ + void SetVolume( float left, float right ); + + /** + * @copydoc Dali::VideoPlayer::GetVolume() + */ + void GetVolume( float& left, float& right ); + + /** + * @copydoc Dali::VideoPlayer::SetRenderingTarget() + */ + void SetRenderingTarget( Dali::Any target ); + + /** + * @copydoc Dali::VideoPlayer::SetPlayPosition() + */ + void SetPlayPosition( int millisecond ); + + /** + * @copydoc Dali::VideoPlayer::GetPlayPosition() + */ + int GetPlayPosition(); + + /** + * @copydoc Dali::VideoPlayer::SetSetDisplayRotation() + */ + void SetDisplayRotation( Dali::VideoPlayerPlugin::DisplayRotation rotation ); + + /** + * @copydoc Dali::VideoPlayer::GetDisplayRotation() + */ + Dali::VideoPlayerPlugin::DisplayRotation GetDisplayRotation(); + + /** + * @copydoc Dali::VideoPlayer::FinishedSignal() + */ + Dali::VideoPlayerPlugin::VideoPlayerSignalType& FinishedSignal(); + + /** + * @brief Initializes member data. + */ + void Initialize(); + +private: + + /** + * @brief Constructor. + * @SINCE_1_1.24 + */ + VideoPlayer(); + + /** + * @brief Destructor. + * @SINCE_1_1.24 + */ + virtual ~VideoPlayer(); + + // Undefined copy constructor + VideoPlayer( const VideoPlayer& player ); + + // Undefined assignment operator + VideoPlayer& operator=( const VideoPlayer& player ); + +private: + + Dali::VideoPlayerPlugin* mPlugin; ///< Videoplayer plugin handle + void* mHandle; ///< Handle for the loaded library + + typedef Dali::VideoPlayerPlugin* (*CreateVideoPlayerFunction)(); + typedef void (*DestroyVideoPlayerFunction)( Dali::VideoPlayerPlugin* plugin ); + + CreateVideoPlayerFunction mCreateVideoPlayerPtr; + DestroyVideoPlayerFunction mDestroyVideoPlayerPtr; + + Dali::VideoPlayerPlugin::VideoPlayerSignalType mFinishedSignal; +}; + +} // namespace Adaptor +} // namespace Internal + +inline static Internal::Adaptor::VideoPlayer& GetImplementation( Dali::VideoPlayer& player ) +{ + DALI_ASSERT_ALWAYS( player && "VideoPlayer handle is empty." ); + + BaseObject& handle = player.GetBaseObject(); + + return static_cast< Internal::Adaptor::VideoPlayer& >( handle ); +} + +inline static const Internal::Adaptor::VideoPlayer& GetImplementation( const Dali::VideoPlayer& player ) +{ + DALI_ASSERT_ALWAYS( player && "VideoPlayer handle is empty." ); + + const BaseObject& handle = player.GetBaseObject(); + + return static_cast< const Internal::Adaptor::VideoPlayer& >( handle ); +} + +} // namespace Dali; + +#endif + diff --git a/adaptors/devel-api/adaptor-framework/video-player-plugin.h b/adaptors/devel-api/adaptor-framework/video-player-plugin.h new file mode 100644 index 0000000..0791db1 --- /dev/null +++ b/adaptors/devel-api/adaptor-framework/video-player-plugin.h @@ -0,0 +1,193 @@ +#ifndef __DALI_VIDEO_PLAYER_PLUGIN_H__ +#define __DALI_VIDEO_PLAYER_PLUGIN_H__ + +/* + * Copyright (c) 2016 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// EXTERNAL INCLUDES +#include + +namespace Dali +{ + +class Any; + +/** + * @brief VideoPlayerPlugin is an abstract interface, used by dali-adaptor to access video player plugin. + * A concrete implementation must be created for each platform and provided as dynamic library. + * @SINCE_1_1.38 + */ +class VideoPlayerPlugin +{ +public: + + typedef Signal< void () > VideoPlayerSignalType; + + /** + * @brief Video display rotation option + * @SINCE_1_1.38 + * @remarks The option is needed only for window surface rendering target + */ + enum DisplayRotation + { + ROTATION_NONE, ///< Display isn't rotated. @SINCE_1_1.38 + ROTATION_90, ///< Display is rotated 90 degree. @SINCE_1_1.38 + ROTATION_180, ///< Display is rotated 180 degree. @SINCE_1_1.38 + ROTATION_270 ///< Display is rotated 270 degree. @SINCE_1_1.38 + }; + + /** + * @brief Constructor. + * @SINCE_1_1.38 + */ + VideoPlayerPlugin(){} + + /** + * @brief Destructor. + * @SINCE_1_1.38 + */ + virtual ~VideoPlayerPlugin(){} + + /** + * @brief Sets a URL of the video file to play. + * + * @SINCE_1_1.38 + * @param [in] url The url of video file + */ + virtual void SetUrl( const std::string& url ) = 0; + + /** + * @brief Returns the URL of the video file. + * @SINCE_1_1.38 + * @return Url of string type + */ + virtual std::string GetUrl() = 0; + + /** + * @brief Sets the player looping status. + * @SINCE_1_1.38 + * + * @param [in] looping The new looping status: true or false + */ + virtual void SetLooping(bool looping) = 0; + + /** + * @brief Returns the player looping status. + * @SINCE_1_1.38 + * + * @return True if player is looping, false otherwise. + */ + virtual bool IsLooping() = 0; + + /** + * @brief Starts the video playback. + * @SINCE_1_1.38 + */ + virtual void Play() = 0; + + /** + * @brief Pauses the video playback. + * @SINCE_1_1.38 + */ + virtual void Pause() = 0; + + /** + * @brief Stops the video playback. + * @SINCE_1_1.38 + */ + virtual void Stop() = 0; + + /** + * @brief Sets the player mute status. + * @SINCE_1_1.38 + * @param[in] mute The new mute status, true is mute. + */ + virtual void SetMute( bool mute ) = 0; + + /** + * @brief Returns the player mute status. + * @SINCE_1_1.38 + * @return True if player is mute. + */ + virtual bool IsMuted() = 0; + + /** + * @brief Sets the player volume. + * @SINCE_1_1.38 + * @param[in] left The left volume scalar + * @param[in] right The right volume scalar + */ + virtual void SetVolume( float left, float right ) = 0; + + /** + * @brief Gets current volume factor. + * @SINCE_1_1.38 + * @param[out] left The current left volume scalar + * @param[out] right The current right volume scalar + */ + virtual void GetVolume( float& left, float& right ) = 0; + + /** + * @brief Sets video rendering target. + * @SINCE_1_1.38 + * @param[in] target The target for video rendering, window surface or native image source + */ + virtual void SetRenderingTarget( Any target ) = 0; + + /** + * @brief Sets the position for playback. + * @SINCE_1_1.38 + * + * @param[in] millisecond The position for playback + */ + virtual void SetPlayPosition( int millisecond ) = 0; + + /** + * @brief Returns the current position in milliseconds. + * @SINCE_1_1.38 + * + * @return The current position of playback + */ + virtual int GetPlayPosition() = 0; + + /** + * @brief Sets video display rotation + * @SINCE_1_1.38 + * @param[in] rotation The rotation of display + */ + virtual void SetDisplayRotation( Dali::VideoPlayerPlugin::DisplayRotation rotation ) = 0; + + /** + * @brief Returns rotation of current video display + * @SINCE_1_1.38 + * @return The rotation of current display + */ + virtual Dali::VideoPlayerPlugin::DisplayRotation GetDisplayRotation() = 0; + + /** + * @brief Connect to this signal to be notified when a video playback have finished. + * + * @SINCE_1_1.38 + * @return A signal object to connect with. + */ + virtual VideoPlayerSignalType& FinishedSignal() = 0; + +}; + +} // namespace Dali; + +#endif diff --git a/adaptors/devel-api/adaptor-framework/video-player.cpp b/adaptors/devel-api/adaptor-framework/video-player.cpp new file mode 100644 index 0000000..8cb5395 --- /dev/null +++ b/adaptors/devel-api/adaptor-framework/video-player.cpp @@ -0,0 +1,160 @@ +/* + * Copyright (c) 2016 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// CLASS HEADER +#include + +// EXTERNAL INCLUDES +#include + +// INTERNAL INCLUDES +#include + +namespace Dali +{ + +VideoPlayer::VideoPlayer() +{ +} + +VideoPlayer::VideoPlayer( Internal::Adaptor::VideoPlayer* internal ) +: BaseHandle( internal ) +{ +} + +VideoPlayer::~VideoPlayer() +{ +} + +VideoPlayer VideoPlayer::New() +{ + Internal::Adaptor::VideoPlayerPtr player = Internal::Adaptor::VideoPlayer::New(); + + if( player ) + { + player->Initialize(); + } + + return VideoPlayer( player.Get() ); +} + +VideoPlayer::VideoPlayer( const VideoPlayer& player ) +: BaseHandle( player ) +{ +} + +VideoPlayer& VideoPlayer::operator=( const VideoPlayer& player ) +{ + if( *this != player ) + { + BaseHandle::operator=( player ); + } + return *this; +} + +VideoPlayer VideoPlayer::DownCast( BaseHandle handle ) +{ + return VideoPlayer( dynamic_cast< Internal::Adaptor::VideoPlayer* >( handle.GetObjectPtr() ) ); +} + +void VideoPlayer::SetUrl( const std::string& url ) +{ + GetImplementation( *this ).SetUrl( url ); +} + +std::string VideoPlayer::GetUrl() +{ + return GetImplementation( *this ).GetUrl(); +} + +void VideoPlayer::SetLooping(bool looping) +{ + GetImplementation( *this ).SetLooping( looping ); +} + +bool VideoPlayer::IsLooping() +{ + return GetImplementation( *this ).IsLooping(); +} + +void VideoPlayer::Play() +{ + GetImplementation( *this ).Play(); +} + +void VideoPlayer::Pause() +{ + GetImplementation( *this ).Pause(); +} + +void VideoPlayer::Stop() +{ + GetImplementation( *this ).Stop(); +} + +void VideoPlayer::SetMute( bool mute ) +{ + GetImplementation( *this ).SetMute( mute ); +} + +bool VideoPlayer::IsMuted() +{ + return GetImplementation( *this ).IsMuted(); +} + +void VideoPlayer::SetVolume( float left, float right ) +{ + GetImplementation( *this ).SetVolume( left, right ); +} + +void VideoPlayer::GetVolume( float& left, float& right ) +{ + GetImplementation( *this ).GetVolume( left, right ); +} + +void VideoPlayer::SetRenderingTarget( Any target ) +{ + GetImplementation( *this ).SetRenderingTarget( target ); +} + +void VideoPlayer::SetPlayPosition( int millisecond ) +{ + GetImplementation( *this ).SetPlayPosition( millisecond ); +} + +int VideoPlayer::GetPlayPosition() +{ + return GetImplementation( *this ).GetPlayPosition(); +} + +void VideoPlayer::SetDisplayRotation( Dali::VideoPlayerPlugin::DisplayRotation rotation ) +{ + GetImplementation( *this ).SetDisplayRotation( rotation ); +} + +Dali::VideoPlayerPlugin::DisplayRotation VideoPlayer::GetDisplayRotation() +{ + return GetImplementation( *this ).GetDisplayRotation(); +} + +Dali::VideoPlayerPlugin::VideoPlayerSignalType& VideoPlayer::FinishedSignal() +{ + return GetImplementation( *this ).FinishedSignal(); +} + +} // namespace Dali; + diff --git a/adaptors/devel-api/adaptor-framework/video-player.h b/adaptors/devel-api/adaptor-framework/video-player.h new file mode 100644 index 0000000..9d37043 --- /dev/null +++ b/adaptors/devel-api/adaptor-framework/video-player.h @@ -0,0 +1,233 @@ +#ifndef __DALI_VIDEO_PLAYER_H__ +#define __DALI_VIDEO_PLAYER_H__ + +/* + * Copyright (c) 2016 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// EXTERNAL INCLUDES +#include + +//INTERNAL INCLUDES +#include "video-player-plugin.h" + +namespace Dali +{ + +class Any; + +namespace Internal +{ + +namespace Adaptor +{ + class VideoPlayer; +} // namespace Adaptor + +} // namespace Internal + +/** + * @brief VideoPlayer class is used for video playback. + * @SINCE_1_1.38 + */ +class DALI_IMPORT_API VideoPlayer: public BaseHandle +{ +public: + + /** + * @brief Constructor. + * @SINCE_1_1.38 + */ + VideoPlayer(); + + /** + * @brief Destructor. + * @SINCE_1_1.38 + */ + ~VideoPlayer(); + + /** + * @brief Creates a new instance of a VideoPlayer. + * @SINCE_1_1.38 + */ + static VideoPlayer New(); + + /** + * @brief Copy constructor. + * + * @SINCE_1_1.38 + * @param[in] player VideoPlayer to copy. The copied player will point at the same implementation + */ + VideoPlayer( const VideoPlayer& player ); + + /** + * @brief Assignment operator. + * + * @SINCE_1_1.38 + * @param[in] player The VideoPlayer to assign from. + * @return The updated VideoPlayer. + */ + VideoPlayer& operator=( const VideoPlayer& player ); + + /** + * @brief Downcast a handle to VideoPlayer handle. + * + * If handle points to a VideoPlayer the downcast produces valid + * handle. If not the returned handle is left uninitialized. + * + * @SINCE_1_1.38 + * @param[in] handle Handle to an object + * @return Handle to a VideoPlayer or an uninitialized handle + */ + static VideoPlayer DownCast( BaseHandle handle ); + + /** + * @brief Sets a URL of the video file to play. + * + * @SINCE_1_1.38 + * @param [in] url The url of video file + */ + void SetUrl( const std::string& url ); + + /** + * @brief Returns the URL of the video file. + * @SINCE_1_1.38 + * @return Url of string type + */ + std::string GetUrl(); + + /** + * @brief Sets the player looping status. + * @SINCE_1_1.38 + * + * @param [in] looping The new looping status: true or false + */ + void SetLooping(bool looping); + + /** + * @brief Returns the player looping status. + * @SINCE_1_1.38 + * + * @return True if player is looping, false otherwise. + */ + bool IsLooping(); + + /** + * @brief Starts the video playback. + * @SINCE_1_1.38 + */ + void Play(); + + /** + * @brief Pauses the video playback. + * @SINCE_1_1.38 + */ + void Pause(); + + /** + * @brief Stops the video playback. + * @SINCE_1_1.38 + */ + void Stop(); + + /** + * @brief Sets the player mute status. + * @SINCE_1_1.38 + * @param[in] mute The new mute status, true is mute. + */ + void SetMute( bool mute ); + + /** + * @brief Returns the player mute status. + * @SINCE_1_1.38 + * @return True if player is mute. + */ + bool IsMuted(); + + /** + * @brief Sets the player volume. + * @SINCE_1_1.38 + * @param[in] left The left volume scalar + * @param[in] right The right volume scalar + */ + void SetVolume( float left, float right ); + + /** + * @brief Returns current volume factor. + * @SINCE_1_1.38 + * @param[out] left The current left volume scalar + * @param[out] right The current right volume scalar + */ + void GetVolume( float& left, float& right ); + + /** + * @brief Sets video rendering target. + * @SINCE_1_1.38 + * @param[in] target The target for video rendering, window surface or native image source + */ + void SetRenderingTarget( Any target ); + + /** + * @brief Sets the position for playback. + * @SINCE_1_1.38 + * + * @param[in] millisecond The position for playback + */ + void SetPlayPosition( int millisecond ); + + /** + * @brief Gets the current position in milliseconds. + * @SINCE_1_1.38 + * + * @return The current position of playback + */ + int GetPlayPosition(); + + /** + * @brief Sets video display rotation + * @SINCE_1_1.38 + * @param[in] rotation The rotation of display + */ + void SetDisplayRotation( Dali::VideoPlayerPlugin::DisplayRotation rotation ); + + /** + * @brief Returns rotation of current video display + * @SINCE_1_1.38 + * @return The rotation of current display + */ + Dali::VideoPlayerPlugin::DisplayRotation GetDisplayRotation(); + + /** + * @brief Connect to this signal to be notified when a video playback have finished. + * + * @SINCE_1_1.38 + * @return A signal object to connect with. + */ + Dali::VideoPlayerPlugin::VideoPlayerSignalType& FinishedSignal(); + +private: // Not intended for application developers + + /** + * @brief Internal constructor + * @SINCE_1_1.38 + */ + explicit DALI_INTERNAL VideoPlayer( Internal::Adaptor::VideoPlayer* internal ); +}; + +} // namespace Dali; + +#endif + diff --git a/adaptors/devel-api/file.list b/adaptors/devel-api/file.list index 4b7b3ba..533fdc6 100644 --- a/adaptors/devel-api/file.list +++ b/adaptors/devel-api/file.list @@ -20,6 +20,7 @@ devel_api_src_files = \ $(adaptor_devel_api_dir)/adaptor-framework/style-monitor.cpp \ $(adaptor_devel_api_dir)/adaptor-framework/tilt-sensor.cpp \ $(adaptor_devel_api_dir)/adaptor-framework/lifecycle-controller.cpp \ + $(adaptor_devel_api_dir)/adaptor-framework/video-player.cpp \ $(adaptor_devel_api_dir)/adaptor-framework/virtual-keyboard.cpp @@ -48,5 +49,7 @@ devel_api_adaptor_framework_header_files = \ $(adaptor_devel_api_dir)/adaptor-framework/sound-player.h \ $(adaptor_devel_api_dir)/adaptor-framework/style-monitor.h \ $(adaptor_devel_api_dir)/adaptor-framework/tilt-sensor.h \ + $(adaptor_devel_api_dir)/adaptor-framework/video-player.h \ + $(adaptor_devel_api_dir)/adaptor-framework/video-player-plugin.h \ $(adaptor_devel_api_dir)/adaptor-framework/virtual-keyboard.h \ $(adaptor_devel_api_dir)/adaptor-framework/physical-keyboard.h diff --git a/adaptors/integration-api/adaptor.h b/adaptors/integration-api/adaptor.h index cc79c35..8eabd4a 100644 --- a/adaptors/integration-api/adaptor.h +++ b/adaptors/integration-api/adaptor.h @@ -213,6 +213,13 @@ public: RenderSurface& GetSurface(); /** + * @brief Gets native window handle + * + * @return Native window handle + */ + Any GetNativeWindowHandle(); + + /** * @brief Release any locks the surface may hold. * * For example, after compositing an offscreen surface, use this method to allow diff --git a/adaptors/public-api/adaptor-framework/native-image-source.cpp b/adaptors/public-api/adaptor-framework/native-image-source.cpp index 6996e73..7897195 100755 --- a/adaptors/public-api/adaptor-framework/native-image-source.cpp +++ b/adaptors/public-api/adaptor-framework/native-image-source.cpp @@ -82,7 +82,7 @@ unsigned int NativeImageSource::TargetTexture() void NativeImageSource::PrepareTexture() { - + mImpl->PrepareTexture(); } unsigned int NativeImageSource::GetWidth() const diff --git a/adaptors/tizen/native-image-source-impl-tizen.cpp b/adaptors/tizen/native-image-source-impl-tizen.cpp index f3952ae..5dac57b 100755 --- a/adaptors/tizen/native-image-source-impl-tizen.cpp +++ b/adaptors/tizen/native-image-source-impl-tizen.cpp @@ -65,12 +65,13 @@ NativeImageSource* NativeImageSource::New(unsigned int width, unsigned int heigh NativeImageSource::NativeImageSource( unsigned int width, unsigned int height, Dali::NativeImageSource::ColorDepth depth, Any nativeImageSource ) : mWidth( width ), mHeight( height ), - mOwnTbmsurface( true ), + mOwnTbmsurface( false ), mTbmsurface( NULL ), mBlendingRequired( false ), mColorDepth( depth ), mEglImageKHR( NULL ), - mEglImageExtensions( NULL ) + mEglImageExtensions( NULL ), + mSetSource( false ) { DALI_ASSERT_ALWAYS( Adaptor::IsAvailable() ); EglFactory& eglFactory = Adaptor::GetImplementation( Adaptor::Get() ).GetEGLFactory(); @@ -88,9 +89,8 @@ NativeImageSource::NativeImageSource( unsigned int width, unsigned int height, D void NativeImageSource::Initialize() { - if( mTbmsurface != NULL ) + if( mTbmsurface != NULL || mWidth == 0 || mHeight == 0 ) { - mOwnTbmsurface = false; return; } @@ -144,6 +144,7 @@ void NativeImageSource::Initialize() mBlendingRequired = ( depth == 32 || depth == 8 ); mTbmsurface = tbm_surface_create( mWidth, mHeight, format ); + mOwnTbmsurface = true; } tbm_surface_h NativeImageSource::GetSurfaceFromAny( Any source ) const @@ -299,16 +300,25 @@ void NativeImageSource::SetSource( Any source ) } mTbmsurface = NULL; + mOwnTbmsurface = false; } mTbmsurface = GetSurfaceFromAny( source ); - mOwnTbmsurface = false; + mSetSource = true; if( mTbmsurface != NULL ) { mWidth = tbm_surface_get_width( mTbmsurface ); mHeight = tbm_surface_get_height( mTbmsurface ); } + + if( mEglImageKHRContainer.Size() > 2 ) + { + mEglImageExtensions->DestroyImageKHR(mEglImageKHRContainer[0]); + mEglImageKHRContainer.Erase( mEglImageKHRContainer.Begin() ); + } + + mEglImageKHRContainer.PushBack( mEglImageKHR ); } bool NativeImageSource::IsColorDepthSupported( Dali::NativeImageSource::ColorDepth colorDepth ) @@ -364,11 +374,6 @@ bool NativeImageSource::IsColorDepthSupported( Dali::NativeImageSource::ColorDep bool NativeImageSource::GlExtensionCreate() { - if( mEglImageKHR != NULL ) - { - GlExtensionDestroy(); - } - // casting from an unsigned int to a void *, which should then be cast back // to an unsigned int in the driver. EGLClientBuffer eglBuffer = reinterpret_cast< EGLClientBuffer > (mTbmsurface); @@ -392,6 +397,15 @@ unsigned int NativeImageSource::TargetTexture() return 0; } +void NativeImageSource::PrepareTexture() +{ + if( mSetSource && GlExtensionCreate() ) + { + TargetTexture(); + mSetSource = false; + } +} + int NativeImageSource::GetPixelDepth(Dali::NativeImageSource::ColorDepth depth) const { switch (depth) diff --git a/adaptors/tizen/native-image-source-impl.h b/adaptors/tizen/native-image-source-impl.h index ceb1c50..3f16926 100755 --- a/adaptors/tizen/native-image-source-impl.h +++ b/adaptors/tizen/native-image-source-impl.h @@ -21,6 +21,7 @@ // EXTERNAL INCLUDES #include #include +#include // INTERNAL INCLUDES #include @@ -35,6 +36,11 @@ namespace Adaptor { class EglImageExtensions; +namespace +{ + typedef Dali::Vector< void* > EglImageContainer; +}; + /** * Dali internal NativeImageSource. */ @@ -102,6 +108,11 @@ public: unsigned int TargetTexture(); /** + * @copydoc Dali::NativeImageSource::PrepareTexture() + */ + void PrepareTexture(); + + /** * @copydoc Dali::NativeImageSource::GetWidth() */ unsigned int GetWidth() const @@ -173,6 +184,8 @@ private: Dali::NativeImageSource::ColorDepth mColorDepth; ///< color depth of image void* mEglImageKHR; ///< From EGL extension EglImageExtensions* mEglImageExtensions; ///< The EGL Image Extensions + bool mSetSource; + EglImageContainer mEglImageKHRContainer; }; } // namespace Adaptor diff --git a/adaptors/x11/native-image-source-impl-x.cpp b/adaptors/x11/native-image-source-impl-x.cpp index 1131d58..c5fd340 100755 --- a/adaptors/x11/native-image-source-impl-x.cpp +++ b/adaptors/x11/native-image-source-impl-x.cpp @@ -323,6 +323,10 @@ unsigned int NativeImageSource::TargetTexture() return 0; } +void NativeImageSource::PrepareTexture() +{ +} + int NativeImageSource::GetPixelDepth(Dali::NativeImageSource::ColorDepth depth) const { switch (depth) diff --git a/adaptors/x11/native-image-source-impl.h b/adaptors/x11/native-image-source-impl.h index b581722..1838c68 100755 --- a/adaptors/x11/native-image-source-impl.h +++ b/adaptors/x11/native-image-source-impl.h @@ -100,6 +100,11 @@ public: unsigned int TargetTexture(); /** + * @copydoc Dali::NativeImageSource::PrepareTexture() + */ + void PrepareTexture(); + + /** * @copydoc Dali::NativeImageSource::GetWidth() */ unsigned int GetWidth() const diff --git a/build/tizen/configure.ac b/build/tizen/configure.ac index a4b137e..053df57 100644 --- a/build/tizen/configure.ac +++ b/build/tizen/configure.ac @@ -31,13 +31,19 @@ AC_ARG_ENABLE([feedback], [enable_feedback=yes], [enable_feedback=no]) +AC_ARG_ENABLE([videoplayer], + [AC_HELP_STRING([ --enable-videoplayer], + [Enable video player plugin])], + [enable_videoplayer=yes], + [enable_videoplayer=no]) + AC_CONFIG_SUBDIRS(adaptor) if test "x$with_libuv" != "xno"; then # build dali-adaptor & dali-adaptor-uv AC_CONFIG_SUBDIRS(adaptor-uv) fi -if test "x$enable_feedback" = "xyes"; then +if test "x$enable_feedback" = "xyes" || test "x$enable_videoplayer" = "xyes"; then # build dali-adaptor & dali-adaptor-uv & plugins AC_CONFIG_SUBDIRS(plugins) fi diff --git a/build/tizen/plugins/Makefile.am b/build/tizen/plugins/Makefile.am index 531bee0..2fb8f35 100644 --- a/build/tizen/plugins/Makefile.am +++ b/build/tizen/plugins/Makefile.am @@ -29,13 +29,19 @@ if USE_FEEDBACK lib_LTLIBRARIES += libdali-feedback-plugin.la endif +if WAYLAND +if USE_VIDEOPLAYER +lib_LTLIBRARIES += libdali-video-player-plugin.la +endif +endif + if USE_FEEDBACK dalisounddir = ${dataReadOnlyDir}/plugins/sounds/ dalisound_DATA = ${dali_plugin_sound_files} # Feedback libdali_feedback_plugin_la_SOURCES = \ - $(plugin_src_files) + $(feedback_plugin_src_files) libdali_feedback_plugin_la_DEPENDENCIES = @@ -87,3 +93,39 @@ libdali_feedback_plugin_la_LIBADD += \ $(FEEDBACK_LIBS) endif + +# VideoPlayer +if WAYLAND +if USE_VIDEOPLAYER + +libdali_video_player_plugin_la_SOURCES = \ + $(video_player_plugin_src_files) + +libdali_video_player_plugin_la_DEPENDENCIES = + +libdali_video_player_plugin_la_CXXFLAGS = -DDALI_COMPILATION \ + -DDALI_ADAPTOR_COMPILATION \ + $(DLOG_CFLAGS) \ + $(DALICORE_CFLAGS) \ + $(ECORE_WAYLAND_CFLAGS) \ + $(CAPI_MEDIA_PLAYER_CFLAGS) \ + $(DALI_PROFILE_CFLAGS) \ + $(DALI_ADAPTOR_CFLAGS) \ + -I../../../adaptors/public-api \ + -I../../../adaptors/devel-api \ + -I../../../adaptors/devel-api/adaptor-framework \ + -I../../../adaptors/integration-api \ + -I../../../adaptors/public-api/adaptor-framework \ + -I../../../plugins/video-player \ + -Werror -Wall + +libdali_video_player_plugin_la_LIBADD = \ + $(DLOG_LIBS) \ + $(ECORE_WAYLAND_LIBS) \ + $(CAPI_MEDIA_PLAYER_LIBS) + +libdali_video_player_plugin_la_LDFLAGS = \ + -rdynamic + +endif # USE_VIDEOPLAYER +endif # WAYLAND diff --git a/build/tizen/plugins/configure.ac b/build/tizen/plugins/configure.ac index 30909a9..b8088b2 100644 --- a/build/tizen/plugins/configure.ac +++ b/build/tizen/plugins/configure.ac @@ -12,13 +12,29 @@ m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])]) LT_INIT +DALI_ADAPTOR_VERSION=dali_version +AC_SUBST(DALI_ADAPTOR_VERSION) + AM_CONDITIONAL([COMMON_PROFILE], [test x$enable_profile = xCOMMON]) AM_CONDITIONAL([MOBILE_PROFILE], [test x$enable_profile = xMOBILE]) AM_CONDITIONAL([WEARABLE_PROFILE], [test x$enable_profile = xWEARABLE]) AM_CONDITIONAL([TV_PROFILE], [test x$enable_profile = xTV]) AM_CONDITIONAL([UBUNTU_PROFILE], [test x$enable_profile = xUBUNTU]) +AM_CONDITIONAL([WAYLAND], [test x$enable_wayland = xyes]) AM_CONDITIONAL([USE_FEEDBACK], [test x$enable_feedback = xyes]) +AM_CONDITIONAL([USE_VIDEOPLAYER], [test x$enable_videoplayer = xyes]) + +if test "x$enable_wayland" = "xyes"; then +if test "x$enable_videoplayer" = "xyes"; then +if test "x$enable_profile" != "xUBUNTU"; then +PKG_CHECK_MODULES(CAPI_MEDIA_PLAYER, capi-media-player) +PKG_CHECK_MODULES(ECORE_WAYLAND, ecore-wayland) +fi +fi # enable_videoplayer +fi # enable_wayland + +if test "x$enable_feedback" = "xyes"; then if test "x$enable_profile" = "xCOMMON" || test "x$enable_profile" = "xTV"; then PKG_CHECK_MODULES(HAPTIC, haptic) @@ -31,6 +47,8 @@ fi PKG_CHECK_MODULES(FEEDBACK, feedback) PKG_CHECK_MODULES(MMFSOUND, mm-sound) +fi # enable_feedback + AC_CONFIG_FILES(Makefile) AC_OUTPUT diff --git a/packaging/dali-adaptor.spec b/packaging/dali-adaptor.spec index 2775c1f..3e334f4 100644 --- a/packaging/dali-adaptor.spec +++ b/packaging/dali-adaptor.spec @@ -34,6 +34,7 @@ Requires: giflib %if "%{profile}" == "mobile" %define dali_profile MOBILE %define dali_feedback_plugin 0 +%define dali_videoplayer_plugin 1 %define shaderbincache_flag DISABLE BuildRequires: pkgconfig(gles20) %define gles_requirement_setup 1 @@ -42,6 +43,7 @@ BuildRequires: pkgconfig(gles20) %if "%{profile}" == "tv" %define dali_profile TV %define dali_feedback_plugin 0 +%define dali_videoplayer_plugin 1 %define shaderbincache_flag ENABLE BuildRequires: pkgconfig(glesv2) %define gles_requirement_setup 1 @@ -50,6 +52,7 @@ BuildRequires: pkgconfig(glesv2) %if "%{profile}" == "wearable" %define dali_profile WEARABLE %define dali_feedback_plugin 0 +%define dali_videoplayer_plugin 1 %define shaderbincache_flag DISABLE BuildRequires: pkgconfig(gles20) BuildRequires: pkgconfig(capi-appfw-watch-application) @@ -60,6 +63,7 @@ BuildRequires: pkgconfig(appcore-watch) %if "%{profile}" == "common" %define dali_profile COMMON %define dali_feedback_plugin 0 +%define dali_videoplayer_plugin 0 %define tizen_2_2_compatibility 1 %define shaderbincache_flag DISABLE BuildRequires: pkgconfig(glesv2) @@ -179,7 +183,7 @@ Group: System/Libraries %if 0%{?dali_feedback_plugin} #Requires: libdeviced BuildRequires: pkgconfig(mm-sound) -BuildRequires: pkgconfig(haptic) +#BuildRequires: pkgconfig(haptic) BuildRequires: libfeedback-devel %endif @@ -187,6 +191,22 @@ BuildRequires: libfeedback-devel Feedback plugin to play haptic and audio feedback for Dali ############################## +# Dali VideoPlayer Plugin +############################## +%if %{with wayland} + +%package dali-video-player-plugin +Summary: Plugin to play a video file for Dali +Group: System/Libraries +%if 0%{?dali_videoplayer_plugin} +BuildRequires: pkgconfig(capi-media-player) +%endif + +%description dali-video-player-plugin +VideoPlayer plugin to play a video file for Dali +%endif + +############################## # Preparation ############################## %prep @@ -248,6 +268,9 @@ FONT_CONFIGURATION_FILE="%{font_configuration_file}" ; export FONT_CONFIGURATION %if 0%{?dali_feedback_plugin} --enable-feedback \ %endif +%if 0%{?dali_videoplayer_plugin} + --enable-videoplayer \ +%endif %if 0%{?tizen_2_2_compatibility} --with-tizen-2-2-compatibility \ %endif @@ -304,6 +327,14 @@ exit 0 exit 0 %endif +%if %{with wayland} +%if 0%{?dali_videoplayer_plugin} +%post dali-video-player-plugin +/sbin/ldconfig +exit 0 +%endif +%endif + ############################## # Pre Uninstall old package ############################## @@ -323,6 +354,14 @@ exit 0 exit 0 %endif +%if %{with wayland} +%if 0%{?dali_videoplayer_plugin} +%postun dali-video-player-plugin +/sbin/ldconfig +exit 0 +%endif +%endif + ############################## # Files in Binary Packages ############################## @@ -357,3 +396,11 @@ exit 0 %{dali_plugin_sound_files}/* %endif +%if %{with wayland} +%if 0%{?dali_videoplayer_plugin} +%files dali-video-player-plugin +%manifest dali-adaptor.manifest +%defattr(-,root,root,-) +%{_libdir}/libdali-video-player-plugin.so* +%endif +%endif diff --git a/plugins/file.list b/plugins/file.list index e467ead..80f8b58 100644 --- a/plugins/file.list +++ b/plugins/file.list @@ -1,5 +1,7 @@ # Add local source files here -plugin_src_files = \ +feedback_plugin_src_files = \ $(plugin_src_dir)/dali-feedback.cpp +video_player_plugin_src_files = \ + $(plugin_src_dir)/video-player/tizen-video-player.cpp diff --git a/plugins/video-player/tizen-video-player.cpp b/plugins/video-player/tizen-video-player.cpp new file mode 100644 index 0000000..812a274 --- /dev/null +++ b/plugins/video-player/tizen-video-player.cpp @@ -0,0 +1,649 @@ +/* + * Copyright (c) 2016 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// CLASS HEADER +#include + +// EXTERNAL INCLUDES +#include +#include +#include + +// INTERNAL INCLUDES + +// The plugin factories +extern "C" DALI_EXPORT_API Dali::VideoPlayerPlugin* CreateVideoPlayerPlugin( void ) +{ + return new Dali::Plugin::TizenVideoPlayer; +} + +extern "C" DALI_EXPORT_API void DestroyVideoPlayerPlugin( Dali::VideoPlayerPlugin* plugin ) +{ + if( plugin != NULL ) + { + delete plugin; + } +} + +namespace Dali +{ + +namespace Plugin +{ + +namespace +{ + +const int TIMER_INTERVAL( 20 ); + +static void MediaPacketVideoDecodedCb( media_packet_h packet, void* user_data ) +{ + TizenVideoPlayer* player = static_cast< TizenVideoPlayer* >( user_data ); + + if( player == NULL ) + { + DALI_LOG_ERROR( "Decoded callback got Null pointer as user_data." ); + return; + } + + player->PushPacket( packet ); +} + + +static void EmitPlaybackFinishedSignal( void* user_data ) +{ + TizenVideoPlayer* player = static_cast< TizenVideoPlayer* >( user_data ); + DALI_LOG_ERROR( "EmitPlaybackFinishedSignal.0" ); + + if( player == NULL ) + { + DALI_LOG_ERROR( "Decoded callback got Null pointer as user_data." ); + return; + } + + DALI_LOG_ERROR( "EmitPlaybackFinishedSignal." ); + + if( !player->mFinishedSignal.Empty() ) + { + DALI_LOG_ERROR( "EmitPlaybackFinishedSignal.3" ); + player->mFinishedSignal.Emit(); + } + + player->Stop(); +} + +void LogPlayerError( int error ) +{ + if( error != PLAYER_ERROR_NONE ) + { + switch( error ) + { + case PLAYER_ERROR_OUT_OF_MEMORY: + { + DALI_LOG_ERROR( "Player error: Out of memory\n" ); + return; + } + case PLAYER_ERROR_INVALID_PARAMETER: + { + DALI_LOG_ERROR( "Player error: Invalid parameter\n" ); + return; + } + case PLAYER_ERROR_NO_SUCH_FILE: + { + DALI_LOG_ERROR( "Player error: No such file\n" ); + return; + } + case PLAYER_ERROR_INVALID_OPERATION: + { + DALI_LOG_ERROR( "Player error: Invalid operation\n" ); + return; + } + case PLAYER_ERROR_FILE_NO_SPACE_ON_DEVICE: + { + DALI_LOG_ERROR( "Player error: No space on device\n" ); + return; + } + case PLAYER_ERROR_FEATURE_NOT_SUPPORTED_ON_DEVICE: + { + DALI_LOG_ERROR( "Player error: Not supported feature on device\n" ); + return; + } + case PLAYER_ERROR_SEEK_FAILED: + { + DALI_LOG_ERROR( "Player error: Seek failed\n" ); + return; + } + case PLAYER_ERROR_INVALID_STATE: + { + DALI_LOG_ERROR( "Player error: Invalid state\n" ); + return; + } + case PLAYER_ERROR_NOT_SUPPORTED_FILE: + { + DALI_LOG_ERROR( "Player error: Not supported file\n" ); + return; + } + case PLAYER_ERROR_INVALID_URI: + { + DALI_LOG_ERROR( "Player error: Invalid uri\n" ); + return; + } + case PLAYER_ERROR_SOUND_POLICY: + { + DALI_LOG_ERROR( "Player error: Sound policy\n" ); + return; + } + case PLAYER_ERROR_CONNECTION_FAILED: + { + DALI_LOG_ERROR( "Player error: Connection failed\n" ); + return; + } + case PLAYER_ERROR_VIDEO_CAPTURE_FAILED: + { + DALI_LOG_ERROR( "Player error: Video capture failed\n" ); + return; + } + case PLAYER_ERROR_DRM_EXPIRED: + { + DALI_LOG_ERROR( "Player error: DRM expired\n" ); + return; + } + case PLAYER_ERROR_DRM_NO_LICENSE: + { + DALI_LOG_ERROR( "Player error: No license\n" ); + return; + } + case PLAYER_ERROR_DRM_FUTURE_USE: + { + DALI_LOG_ERROR( "Player error: License for future use\n" ); + return; + } + case PLAYER_ERROR_DRM_NOT_PERMITTED: + { + DALI_LOG_ERROR( "Player error: Format not permitted\n" ); + return; + } + case PLAYER_ERROR_RESOURCE_LIMIT: + { + DALI_LOG_ERROR( "Player error: Resource limit\n" ); + return; + } + case PLAYER_ERROR_PERMISSION_DENIED: + { + DALI_LOG_ERROR( "Player error: Permission denied\n" ); + return; + } + case PLAYER_ERROR_SERVICE_DISCONNECTED: + { + DALI_LOG_ERROR( "Player error: Service disconnected\n" ); + return; + } + case PLAYER_ERROR_BUFFER_SPACE: + { + DALI_LOG_ERROR( "Player error: Buffer space\n" ); + return; + } + } + } +} + +} // unnamed namespace + +TizenVideoPlayer::TizenVideoPlayer() +: mPlayerState( PLAYER_STATE_NONE ), + mPacket( NULL ), + mBackgroundColor( Dali::Stage::DEFAULT_BACKGROUND_COLOR ), + mTargetType( NativeImage ) +{ +} + +TizenVideoPlayer::~TizenVideoPlayer() +{ +} + +void TizenVideoPlayer::GetPlayerState( player_state_e* state ) +{ + if( player_get_state( mPlayer, state ) != PLAYER_ERROR_NONE ) + { + DALI_LOG_ERROR( "player_get_state error: Invalid parameter\n" ); + *state = PLAYER_STATE_NONE; + } +} + +void TizenVideoPlayer::SetUrl( const std::string& url ) +{ + if( mUrl != url ) + { + mUrl = url; + + GetPlayerState( &mPlayerState ); + + if( mPlayerState != PLAYER_STATE_NONE && mPlayerState != PLAYER_STATE_IDLE ) + { + Stop(); + int error = player_unprepare( mPlayer ); + LogPlayerError( error ); + } + + if( mPlayerState == PLAYER_STATE_IDLE ) + { + int error = player_set_uri( mPlayer, mUrl.c_str() ); + LogPlayerError( error ); + + error = player_prepare( mPlayer ); + LogPlayerError( error ); + } + } +} + +std::string TizenVideoPlayer::GetUrl() +{ + return mUrl; +} + +void TizenVideoPlayer::SetRenderingTarget( Any target ) +{ + int error; + if( mPlayerState != PLAYER_STATE_NONE ) + { + GetPlayerState( &mPlayerState ); + + if( mPlayerState != PLAYER_STATE_IDLE ) + { + Stop(); + error = player_unprepare( mPlayer ); + LogPlayerError( error ); + } + + error = player_destroy( mPlayer ); + LogPlayerError( error ); + mPlayerState = PLAYER_STATE_NONE; + mPlayer = NULL; + mUrl = ""; + } + + mNativeImageSourcePtr = NULL; + + if( target.GetType() == typeid( Dali::NativeImageSourcePtr ) ) + { + if( mTargetType == TizenVideoPlayer::WindowSurface ) + { + Stage::GetCurrent().SetBackgroundColor( mBackgroundColor ); + } + mTargetType = TizenVideoPlayer::NativeImage; + + Dali::NativeImageSourcePtr nativeImageSourcePtr = AnyCast< Dali::NativeImageSourcePtr >( target ); + + InitializeTextureStreamMode( nativeImageSourcePtr ); + } + else if( target.GetType() == typeid( Ecore_Wl_Window* ) ) + { + mTargetType = TizenVideoPlayer::WindowSurface; + mBackgroundColor = Stage::GetCurrent().GetBackgroundColor(); + Stage::GetCurrent().SetBackgroundColor( Color::TRANSPARENT ); + + Ecore_Wl_Window* nativeWindow = Dali::AnyCast< Ecore_Wl_Window* >( target ); + InitializeUnderlayMode( nativeWindow ); + } + else + { + DALI_LOG_ERROR( "Video rendering target is unknown" ); + } +} + +void TizenVideoPlayer::SetLooping( bool looping ) +{ + GetPlayerState( &mPlayerState ); + + if( mPlayerState != PLAYER_STATE_NONE ) + { + int error = player_set_looping( mPlayer, looping ); + LogPlayerError( error ); + } +} + +bool TizenVideoPlayer::IsLooping() +{ + GetPlayerState( &mPlayerState ); + + bool looping = false; + if( mPlayerState != PLAYER_STATE_NONE ) + { + int error = player_is_looping( mPlayer, &looping ); + LogPlayerError( error ); + } + + return looping; +} + +void TizenVideoPlayer::Play() +{ + GetPlayerState( &mPlayerState ); + + if( mPlayerState == PLAYER_STATE_READY || mPlayerState == PLAYER_STATE_PAUSED ) + { + if( mNativeImageSourcePtr != NULL && mTimer ) + { + mTimer.Start(); + } + + int error = player_start( mPlayer ); + LogPlayerError( error ); + } +} + +void TizenVideoPlayer::Pause() +{ + GetPlayerState( &mPlayerState ); + + if( mPlayerState == PLAYER_STATE_PLAYING ) + { + int error = player_pause( mPlayer ); + LogPlayerError( error ); + + if( mNativeImageSourcePtr != NULL && mTimer ) + { + mTimer.Stop(); + DestroyPackets(); + } + } +} + +void TizenVideoPlayer::Stop() +{ + GetPlayerState( &mPlayerState ); + + if( mPlayerState == PLAYER_STATE_PLAYING || mPlayerState == PLAYER_STATE_PAUSED ) + { + int error = player_stop( mPlayer ); + LogPlayerError( error ); + } + + if( mNativeImageSourcePtr != NULL && mTimer ) + { + mTimer.Stop(); + DestroyPackets(); + } +} + +void TizenVideoPlayer::SetMute( bool muted ) +{ + GetPlayerState( &mPlayerState ); + + if( mPlayerState == PLAYER_STATE_IDLE || + mPlayerState == PLAYER_STATE_READY || + mPlayerState == PLAYER_STATE_PLAYING || + mPlayerState == PLAYER_STATE_PAUSED + ) + { + int error = player_set_mute( mPlayer, muted ); + LogPlayerError( error ); + } +} + +bool TizenVideoPlayer::IsMuted() +{ + GetPlayerState( &mPlayerState ); + bool muted = false; + + if( mPlayerState == PLAYER_STATE_IDLE || + mPlayerState == PLAYER_STATE_READY || + mPlayerState == PLAYER_STATE_PLAYING || + mPlayerState == PLAYER_STATE_PAUSED + ) + { + bool muted = false; + int error = player_is_muted( mPlayer, &muted ); + LogPlayerError( error ); + } + + return muted; +} + +void TizenVideoPlayer::SetVolume( float left, float right ) +{ + GetPlayerState( &mPlayerState ); + + int error = player_set_volume( mPlayer, left, right ); + LogPlayerError( error ); +} + +void TizenVideoPlayer::GetVolume( float& left, float& right ) +{ + GetPlayerState( &mPlayerState ); + + int error = player_get_volume( mPlayer, &left, &right ); + LogPlayerError( error ); +} + +void TizenVideoPlayer::SetPlayPosition( int millisecond ) +{ + int error; + + GetPlayerState( &mPlayerState ); + + if( mPlayerState == PLAYER_STATE_READY || + mPlayerState == PLAYER_STATE_PLAYING || + mPlayerState == PLAYER_STATE_PAUSED + ) + { + error = player_set_play_position( mPlayer, millisecond, true, NULL, NULL ); + LogPlayerError( error ); + } +} + +int TizenVideoPlayer::GetPlayPosition() +{ + int error; + int millisecond = 0; + + GetPlayerState( &mPlayerState ); + + if( mPlayerState == PLAYER_STATE_IDLE || + mPlayerState == PLAYER_STATE_READY || + mPlayerState == PLAYER_STATE_PLAYING || + mPlayerState == PLAYER_STATE_PAUSED + ) + { + error = player_get_play_position( mPlayer, &millisecond ); + LogPlayerError( error ); + } + + return millisecond; +} + +void TizenVideoPlayer::SetDisplayRotation( Dali::VideoPlayerPlugin::DisplayRotation rotation ) +{ + if( mNativeImageSourcePtr != NULL ) + { + DALI_LOG_ERROR( "SetDisplayRotation is only for window rendering target.\n" ); + return; + } + + int error; + if( mPlayerState != PLAYER_STATE_NONE ) + { + error = player_set_display_rotation( mPlayer, static_cast< player_display_rotation_e >( rotation ) ); + LogPlayerError( error ); + } +} + +Dali::VideoPlayerPlugin::DisplayRotation TizenVideoPlayer::GetDisplayRotation() +{ + if( mNativeImageSourcePtr != NULL ) + { + DALI_LOG_ERROR( "GetDisplayRotation is only for window rendering target.\n" ); + return Dali::VideoPlayerPlugin::ROTATION_NONE; + } + + int error; + player_display_rotation_e rotation; + if( mPlayerState != PLAYER_STATE_NONE ) + { + error = player_get_display_rotation( mPlayer, &rotation ); + LogPlayerError( error ); + } + return static_cast< Dali::VideoPlayerPlugin::DisplayRotation >( rotation ); +} + +Dali::VideoPlayerPlugin::VideoPlayerSignalType& TizenVideoPlayer::FinishedSignal() +{ + return mFinishedSignal; +} + +void TizenVideoPlayer::InitializeTextureStreamMode( Dali::NativeImageSourcePtr nativeImageSourcePtr ) +{ + int error; + + mNativeImageSourcePtr = nativeImageSourcePtr; + + if( mPlayerState == PLAYER_STATE_NONE ) + { + error = player_create( &mPlayer ); + LogPlayerError( error ); + } + + GetPlayerState( &mPlayerState ); + + if( mPlayerState == PLAYER_STATE_IDLE ) + { + error = player_set_completed_cb( mPlayer, EmitPlaybackFinishedSignal, this ); + LogPlayerError( error ); + + error = player_set_media_packet_video_frame_decoded_cb( mPlayer, MediaPacketVideoDecodedCb, this ); + LogPlayerError( error ); + + error = player_set_sound_type( mPlayer, SOUND_TYPE_MEDIA ); + LogPlayerError( error ); + + error = player_set_display_mode( mPlayer, PLAYER_DISPLAY_MODE_FULL_SCREEN ); + LogPlayerError( error ); + + error = player_set_display( mPlayer, PLAYER_DISPLAY_TYPE_NONE, NULL ); + LogPlayerError( error ); + + error = player_set_display_visible( mPlayer, true ); + LogPlayerError( error ); + + mTimer = Dali::Timer::New( TIMER_INTERVAL ); + mTimer.TickSignal().Connect( this, &TizenVideoPlayer::Update ); + } +} + +void TizenVideoPlayer::InitializeUnderlayMode( Ecore_Wl_Window* ecoreWlWindow ) +{ + int error; + if( mPlayerState == PLAYER_STATE_NONE ) + { + error = player_create( &mPlayer ); + LogPlayerError( error ); + } + + GetPlayerState( &mPlayerState ); + + if( mPlayerState == PLAYER_STATE_IDLE ) + { + error = player_set_completed_cb( mPlayer, EmitPlaybackFinishedSignal, this ); + LogPlayerError( error ); + + error = player_set_sound_type( mPlayer, SOUND_TYPE_MEDIA ); + LogPlayerError( error ); + + error = player_set_display_mode( mPlayer, PLAYER_DISPLAY_MODE_FULL_SCREEN ); + LogPlayerError( error ); + + int width, height; + ecore_wl_screen_size_get( &width, &height ); + error = player_set_ecore_wl_display( mPlayer, PLAYER_DISPLAY_TYPE_OVERLAY, ecoreWlWindow, 0, 0, width, height ); + LogPlayerError( error ); + + error = player_set_display_visible( mPlayer, true ); + LogPlayerError( error ); + } +} + +bool TizenVideoPlayer::Update() +{ + Dali::Mutex::ScopedLock lock( mPacketMutex ); + + int error; + + if( mPacket != NULL ) + { + error = media_packet_destroy( mPacket ); + if( error != MEDIA_PACKET_ERROR_NONE ) + { + DALI_LOG_ERROR( "Media packet destroy error: %d\n", error ); + } + mPacket = NULL; + } + + if( !mPacketVector.Empty() ) + { + mPacket = static_cast< media_packet_h >( mPacketVector[0] ); + mPacketVector.Remove( mPacketVector.Begin() ); + } + + if( mPacket == NULL ) + { + return true; + } + + error = media_packet_get_tbm_surface( mPacket, &mTbmSurface ); + if( error != MEDIA_PACKET_ERROR_NONE ) + { + media_packet_destroy( mPacket ); + mPacket = NULL; + DALI_LOG_ERROR( " error: %d\n", error ); + return true; + } + + Any source( mTbmSurface ); + mNativeImageSourcePtr->SetSource( source ); + Dali::Stage::GetCurrent().KeepRendering( 0.0f ); + + return true; +} + +void TizenVideoPlayer::DestroyPackets() +{ + int error; + if( mPacket != NULL ) + { + error = media_packet_destroy( mPacket ); + DALI_LOG_ERROR( "Media packet destroy error: %d\n", error ); + mPacket = NULL; + } + + for(unsigned int i = 0; i < mPacketVector.Size(); ++i) + { + mPacket = static_cast< media_packet_h >( mPacketVector[i] ); + error = media_packet_destroy( mPacket ); + DALI_LOG_ERROR( "Media packet destroy error: %d\n", error ); + mPacket = NULL; + } + mPacketVector.Clear(); +} + +void TizenVideoPlayer::PushPacket( media_packet_h packet ) +{ + Dali::Mutex::ScopedLock lock( mPacketMutex ); + mPacketVector.PushBack( packet ); +} + +} // namespace Plugin +} // namespace Dali; diff --git a/plugins/video-player/tizen-video-player.h b/plugins/video-player/tizen-video-player.h new file mode 100644 index 0000000..ac82edd --- /dev/null +++ b/plugins/video-player/tizen-video-player.h @@ -0,0 +1,212 @@ +#ifndef __DALI_TIZEN_VIDEO_PLAYER_PLUGIN_H__ +#define __DALI_TIZEN_VIDEO_PLAYER_PLUGIN_H__ + +/* + * Copyright (c) 2016 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// EXTERNAL INCLUDES +#include +#include +#include + +#ifndef HAVE_WAYLAND +#define HAVE_WAYLAND +#endif +#include + +// INTERNAL INCLUDES +#include +#include +#include + +namespace Dali +{ + +namespace Plugin +{ + +/** + * @brief Implementation of the Tizen video player class which has Tizen platform dependency. + * @SINCE_1_1.38 + */ +class TizenVideoPlayer : public Dali::VideoPlayerPlugin, public Dali::ConnectionTracker +{ +public: + + /** + * @brief Video rendering target type + * @SINCE_1_1.38 + */ + enum RenderingTargetType + { + WindowSurface, ///< HW underlay + NativeImage ///< texture stream + }; + + /** + * @brief Constructor. + * @SINCE_1_1.38 + */ + TizenVideoPlayer(); + + /** + * @brief Destructor. + * @SINCE_1_1.38 + */ + virtual ~TizenVideoPlayer(); + + /** + * @copydoc Dali::VideoPlayerPlugin::SetUrl() + */ + virtual void SetUrl( const std::string& url ); + + /** + * @copydoc Dali::VideoPlayerPlugin::GetUrl() + */ + virtual std::string GetUrl(); + + /** + * @copydoc Dali::VideoPlayerPlugin::SetLooping() + */ + virtual void SetLooping(bool looping); + + /** + * @copydoc Dali::VideoPlayerPlugin::IsLooping() + */ + virtual bool IsLooping(); + + /** + * @copydoc Dali::VideoPlayerPlugin::Play() + */ + virtual void Play(); + + /** + * @copydoc Dali::VideoPlayerPlugin::Pause() + */ + virtual void Pause(); + + /** + * @copydoc Dali::VideoPlayerPlugin::Stop() + */ + virtual void Stop(); + + /** + * @copydoc Dali::VideoPlayerPlugin::SetMute() + */ + virtual void SetMute( bool mute ); + + /** + * @copydoc Dali::VideoPlayerPlugin::IsMute() + */ + virtual bool IsMuted(); + + /** + * @copydoc Dali::VideoPlayerPlugin::SetVolume() + */ + virtual void SetVolume( float left, float right ); + + /** + * @copydoc Dali::VideoPlayerPlugin::GetVolume() + */ + virtual void GetVolume( float& left, float& right ); + + /** + * @copydoc Dali::VideoPlayerPlugin::SetRenderingTarget() + */ + void SetRenderingTarget( Any target ); + + /** + * @copydoc Dali::VideoPlayerPlugin::SetPlayPosition() + */ + virtual void SetPlayPosition( int millisecond ); + + /** + * @copydoc Dali::VideoPlayerPlugin::GetPlayPosition() + */ + virtual int GetPlayPosition(); + + /** + * @copydoc Dali::VideoPlayerPlugin::SetDisplayRotation() + */ + virtual void SetDisplayRotation( Dali::VideoPlayerPlugin::DisplayRotation rotation ); + + /** + * @copydoc Dali::VideoPlayerPlugin::GetDisplayRotation() + */ + virtual Dali::VideoPlayerPlugin::DisplayRotation GetDisplayRotation(); + + /** + * @copydoc Dali::VideoPlayerPlugin::FinishedSignal() + */ + virtual Dali::VideoPlayerPlugin::VideoPlayerSignalType& FinishedSignal(); + + /** + * @brief Push media packet with video frame image + */ + void PushPacket( media_packet_h packet ); + +private: + + /** + * @brief Updates video frame image by timer if rendering targe is native image source + */ + bool Update(); + + /** + * @brief Gets current player state + */ + void GetPlayerState( player_state_e* state ); + + /** + * @brief Destroy all packests, which this plugin stores + */ + void DestroyPackets(); + + /** + * @brief Initializes player for video rendering using native image source + */ + void InitializeTextureStreamMode( Dali::NativeImageSourcePtr nativeImageSourcePtr ); + + /** + * @brief Initializes player for video rendering using wayland window surface + */ + void InitializeUnderlayMode( Ecore_Wl_Window* ecoreWlWindow ); + +private: + + std::string mUrl; ///< The video file path + player_h mPlayer; ///< Tizen player handle + player_state_e mPlayerState; ///< Tizen player state + tbm_surface_h mTbmSurface; ///< tbm surface handle + media_packet_h mPacket; ///< Media packet handle with tbm surface of current video frame image + Dali::NativeImageSourcePtr mNativeImageSourcePtr; ///< native image source for video rendering + Dali::Timer mTimer; ///< Timer for texture streaming rendering + Dali::Vector4 mBackgroundColor; ///< Current background color, which texturestream mode needs. + RenderingTargetType mTargetType; ///< Current rendering target type + + Dali::Mutex mPacketMutex; + Dali::Vector< media_packet_h > mPacketVector; ///< Container for media packet handle from Tizen player callback + +public: + + Dali::VideoPlayerPlugin::VideoPlayerSignalType mFinishedSignal; +}; + +} // namespace Plugin +} // namespace Dali; + +#endif