From 6b305f18aa42bacab389c252f738e604306c5851 Mon Sep 17 00:00:00 2001 From: "taeyoon0.lee" Date: Thu, 31 Aug 2017 01:00:34 +0900 Subject: [PATCH] Added video-player plugin Change-Id: I8607a015079e08d7a90d9f58fff48be16487c159 --- build/tizen/Makefile.am | 28 + build/tizen/configure.ac | 8 +- dali-extension/file.list | 7 +- dali-extension/{ => key}/key-extension.cpp | 0 dali-extension/{ => key}/key-extension.h | 0 dali-extension/video-player/tizen-video-player.cpp | 736 +++++++++++++++++++++ dali-extension/video-player/tizen-video-player.h | 229 +++++++ packaging/dali-extension.spec | 29 +- 8 files changed, 1032 insertions(+), 5 deletions(-) rename dali-extension/{ => key}/key-extension.cpp (100%) rename dali-extension/{ => key}/key-extension.h (100%) create mode 100644 dali-extension/video-player/tizen-video-player.cpp create mode 100644 dali-extension/video-player/tizen-video-player.h diff --git a/build/tizen/Makefile.am b/build/tizen/Makefile.am index fb2735f..4ad3df7 100644 --- a/build/tizen/Makefile.am +++ b/build/tizen/Makefile.am @@ -29,6 +29,9 @@ if USE_KEY_EXTENSION lib_LTLIBRARIES += libdali-key-extension.la endif +lib_LTLIBRARIES += libdali-video-player-plugin.la + +# key extension libdali_key_extension_la_SOURCES = \ $(key_extension_src_files) libdali_key_extension_la_DEPENDENCIES = @@ -48,3 +51,28 @@ libdali_key_extension_la_LDFLAGS = \ libdali_key_extensiondir = $(devincludepath)/dali-extension/ libdali_key_extension_HEADERS = $(key_extension_header_files) + +# Todo Video player plugin separation +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) \ + $(DALI_CFLAGS) \ + $(ECORE_WAYLAND_CFLAGS) \ + $(CAPI_MEDIA_PLAYER_CFLAGS) \ + -I../../dali-extension/video-player \ + -Werror -Wall + +libdali_video_player_plugin_la_LIBADD = \ + $(DLOG_LIBS) \ + $(DALI_LIBS) \ + $(ECORE_WAYLAND_LIBS) \ + $(CAPI_MEDIA_PLAYER_LIBS) + +libdali_video_player_plugin_la_LDFLAGS = \ + -rdynamic + diff --git a/build/tizen/configure.ac b/build/tizen/configure.ac index 1deaec6..d534bce 100644 --- a/build/tizen/configure.ac +++ b/build/tizen/configure.ac @@ -1,4 +1,4 @@ -m4_define([dali_version],[0.1.0]) +4_define([dali_version],[0.1.0]) AC_INIT([dali], [dali_version]) AM_INIT_AUTOMAKE([-Wall foreign]) @@ -24,6 +24,10 @@ AM_CONDITIONAL([USE_KEY_EXTENSION], [test x$enable_keyextension = xyes]) PKG_CHECK_MODULES([DALI], [dali-core dali-adaptor dali-toolkit]) +# ToDO Videoplayer plugin separation +PKG_CHECK_MODULES(CAPI_MEDIA_PLAYER, capi-media-player) +PKG_CHECK_MODULES(ECORE_WAYLAND, ecore-wayland) + devincludepath=${includedir} AC_SUBST(devincludepath) @@ -32,4 +36,4 @@ Makefile dali-extension.pc ]) -AC_OUTPUT() +AC_OUTPUT diff --git a/dali-extension/file.list b/dali-extension/file.list index a31a692..621a5bc 100644 --- a/dali-extension/file.list +++ b/dali-extension/file.list @@ -1,5 +1,8 @@ key_extension_src_files = \ - $(extension_src_dir)/key-extension.cpp + $(extension_src_dir)/key/key-extension.cpp key_extension_header_files = \ - $(extension_src_dir)/key-extension.h + $(extension_src_dir)/key/key-extension.h + +video_player_plugin_src_files = \ + $(extension_src_dir)/video-player/tizen-video-player.cpp diff --git a/dali-extension/key-extension.cpp b/dali-extension/key/key-extension.cpp similarity index 100% rename from dali-extension/key-extension.cpp rename to dali-extension/key/key-extension.cpp diff --git a/dali-extension/key-extension.h b/dali-extension/key/key-extension.h similarity index 100% rename from dali-extension/key-extension.h rename to dali-extension/key/key-extension.h diff --git a/dali-extension/video-player/tizen-video-player.cpp b/dali-extension/video-player/tizen-video-player.cpp new file mode 100644 index 0000000..f7baa50 --- /dev/null +++ b/dali-extension/video-player/tizen-video-player.cpp @@ -0,0 +1,736 @@ +/* + * 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.\n" ); + return; + } + + player->PushPacket( packet ); +} + +static void EmitPlaybackFinishedSignal( void* user_data ) +{ + TizenVideoPlayer* player = static_cast< TizenVideoPlayer* >( user_data ); + DALI_LOG_ERROR( "EmitPlaybackFinishedSignal.\n" ); + + if( player == NULL ) + { + DALI_LOG_ERROR( "Decoded callback got Null pointer as user_data.\n" ); + return; + } + + DALI_LOG_ERROR( "EmitPlaybackFinishedSignal.\n" ); + + if( !player->mFinishedSignal.Empty() ) + { + DALI_LOG_ERROR( "EmitPlaybackFinishedSignal.3\n" ); + player->mFinishedSignal.Emit(); + } + + player->Stop(); +} + +// ToDo: VD player_set_play_position() doesn't work when callback pointer is NULL. +// We should check whether this callback is needed in platform. +static void PlayerSeekCompletedCb( void* data ) +{ +} + +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() +: mPlayer( NULL ), + mPlayerState( PLAYER_STATE_NONE ), + mTbmSurface( NULL ), + mPacket( NULL ), + mTargetType( NativeImage ), + mAlphaBitChanged( false ) +{ +} + +TizenVideoPlayer::~TizenVideoPlayer() +{ +} + +void TizenVideoPlayer::GetPlayerState( player_state_e* state ) +{ + if( mPlayer != NULL && 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; + mEcoreWlWindow = NULL; + + if( target.GetType() == typeid( Dali::NativeImageSourcePtr ) ) + { + mTargetType = TizenVideoPlayer::NativeImage; + + Dali::NativeImageSourcePtr nativeImageSourcePtr = AnyCast< Dali::NativeImageSourcePtr >( target ); + + InitializeTextureStreamMode( nativeImageSourcePtr ); + } + else if( target.GetType() == typeid( Ecore_Wl_Window* ) ) + { + mTargetType = TizenVideoPlayer::WindowSurface; + + Ecore_Wl_Window* nativeWindow = Dali::AnyCast< Ecore_Wl_Window* >( target ); + InitializeUnderlayMode( nativeWindow ); + } + else + { + DALI_LOG_ERROR( "Video rendering target is unknown\n" ); + } +} + +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 + ) + { + 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, false, PlayerSeekCompletedCb, 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 = PLAYER_DISPLAY_ROTATION_NONE; + 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( mAlphaBitChanged ) + { + ecore_wl_window_alpha_set( mEcoreWlWindow, false ); + mAlphaBitChanged = false; + } + + 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 ); + mEcoreWlWindow = ecoreWlWindow; + + 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_DST_ROI ); + LogPlayerError( error ); + + error = player_set_display_roi_area( mPlayer, 0, 0, 1, 1 ); + + int width, height; + mAlphaBitChanged = ( ecore_wl_window_alpha_get( mEcoreWlWindow ) )? false: true; + ecore_wl_screen_size_get( &width, &height ); + + if( mAlphaBitChanged ) + { + ecore_wl_window_alpha_set( mEcoreWlWindow, true ); + } + error = player_set_ecore_wl_display( mPlayer, PLAYER_DISPLAY_TYPE_OVERLAY, mEcoreWlWindow, 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 ); +} + +void TizenVideoPlayer::SetDisplayArea( DisplayArea area ) +{ + GetPlayerState( &mPlayerState ); + + if( mNativeImageSourcePtr != NULL ) + { + DALI_LOG_ERROR( "SetDisplayArea is only for window surface target.\n" ); + return; + } + + if( mPlayerState == PLAYER_STATE_IDLE || + mPlayerState == PLAYER_STATE_READY || + mPlayerState == PLAYER_STATE_PLAYING || + mPlayerState == PLAYER_STATE_PAUSED + + ) + { + int error = player_set_display_roi_area( mPlayer, area.x, area.y, area.width, area.height ); + LogPlayerError( error ); + } +} + +void TizenVideoPlayer::Forward( int millisecond ) +{ + int error; + + GetPlayerState( &mPlayerState ); + + if( mPlayerState == PLAYER_STATE_READY || + mPlayerState == PLAYER_STATE_PLAYING || + mPlayerState == PLAYER_STATE_PAUSED + ) + { + int currentPosition = 0; + int nextPosition = 0; + + error = player_get_play_position( mPlayer, ¤tPosition ); + LogPlayerError( error ); + + nextPosition = currentPosition + millisecond; + + error = player_set_play_position( mPlayer, nextPosition, false, PlayerSeekCompletedCb, NULL ); + LogPlayerError( error ); + } +} + +void TizenVideoPlayer::Backward( int millisecond ) +{ + int error; + + GetPlayerState( &mPlayerState ); + + if( mPlayerState == PLAYER_STATE_READY || + mPlayerState == PLAYER_STATE_PLAYING || + mPlayerState == PLAYER_STATE_PAUSED + ) + { + int currentPosition = 0; + int nextPosition = 0; + + error = player_get_play_position( mPlayer, ¤tPosition ); + LogPlayerError( error ); + + nextPosition = currentPosition - millisecond; + nextPosition = ( nextPosition < 0 )? 0 : nextPosition; + + error = player_set_play_position( mPlayer, nextPosition, false, PlayerSeekCompletedCb, NULL ); + LogPlayerError( error ); + } +} + +} // namespace Plugin +} // namespace Dali; diff --git a/dali-extension/video-player/tizen-video-player.h b/dali-extension/video-player/tizen-video-player.h new file mode 100644 index 0000000..9a03627 --- /dev/null +++ b/dali-extension/video-player/tizen-video-player.h @@ -0,0 +1,229 @@ +#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 +#include +#include +#include + +#ifndef HAVE_WAYLAND +#define HAVE_WAYLAND +#endif +#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::SetDisplayArea() + */ + virtual void SetDisplayArea( DisplayArea area ); + + /** + * @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 ); + + /** + * @brief Dali::VideoPlayer::Forward() + */ + void Forward( int millisecond ); + + /** + * @brief Dali::VideoPlayer::Backward() + */ + void Backward( int millisecond ); + +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 + + Ecore_Wl_Window* mEcoreWlWindow; + + bool mAlphaBitChanged; ///< True if underlay rendering initialization changes window alpha + +public: + + Dali::VideoPlayerPlugin::VideoPlayerSignalType mFinishedSignal; +}; + +} // namespace Plugin +} // namespace Dali; + +#endif diff --git a/packaging/dali-extension.spec b/packaging/dali-extension.spec index 8e799fa..efef6c3 100644 --- a/packaging/dali-extension.spec +++ b/packaging/dali-extension.spec @@ -37,7 +37,7 @@ Requires: %{name} = %{version}-%{release} %description devel Development components for the DALi Tizen Extensions - public headers and package configs -V############################## +############################## # Dali Key Extension ############################## @@ -49,6 +49,19 @@ Group: System/Libraries Plugin to support extension keys for Dali ############################## +# Dali VideoPlayer Plugin +############################## + +%package video-player-plugin +Summary: Plugin to play a video file for Dali +Group: System/Libraries +BuildRequires: pkgconfig(ecore-wayland) +BuildRequires: pkgconfig(capi-media-player) + +%description video-player-plugin +VideoPlayer plugin to play a video file for Dali + +############################## # Preparation ############################## %prep @@ -99,6 +112,10 @@ exit 0 /sbin/ldconfig exit 0 +%post video-player-plugin +/sbin/ldconfig +exit 0 + ############################## # Pre Uninstall old package ############################## @@ -116,6 +133,10 @@ exit 0 /sbin/ldconfig exit 0 +%postun video-player-plugin +/sbin/ldconfig +exit 0 + ############################## # Files in Binary Packages ############################## @@ -135,3 +156,9 @@ exit 0 %defattr(-,root,root,-) %{_libdir}/libdali-key-extension.so* %license LICENSE + +%files video-player-plugin +%manifest dali-extension.manifest +%defattr(-,root,root,-) +%{_libdir}/libdali-video-player-plugin.so* +%license LICENSE -- 2.7.4