2 * Copyright (c) 2016 Samsung Electronics Co., Ltd.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
19 #include <tizen-video-player.h>
22 #include <dali/public-api/common/stage.h>
23 #include <dali/devel-api/threading/mutex.h>
24 #include <dali/integration-api/debug.h>
25 #include <system_info.h>
29 // The plugin factories
30 extern "C" DALI_EXPORT_API Dali::VideoPlayerPlugin* CreateVideoPlayerPlugin( void )
32 return new Dali::Plugin::TizenVideoPlayer;
35 extern "C" DALI_EXPORT_API void DestroyVideoPlayerPlugin( Dali::VideoPlayerPlugin* plugin )
52 const int TIMER_INTERVAL( 20 );
54 static void MediaPacketVideoDecodedCb( media_packet_h packet, void* user_data )
56 TizenVideoPlayer* player = static_cast< TizenVideoPlayer* >( user_data );
60 DALI_LOG_ERROR( "Decoded callback got Null pointer as user_data.\n" );
64 player->PushPacket( packet );
67 static void EmitPlaybackFinishedSignal( void* user_data )
69 TizenVideoPlayer* player = static_cast< TizenVideoPlayer* >( user_data );
73 DALI_LOG_ERROR( "Decoded callback got Null pointer as user_data.\n" );
77 if( !player->mFinishedSignal.Empty() )
79 DALI_LOG_ERROR( "EmitPlaybackFinishedSignal.3\n" );
80 player->mFinishedSignal.Emit();
86 // ToDo: VD player_set_play_position() doesn't work when callback pointer is NULL.
87 // We should check whether this callback is needed in platform.
88 static void PlayerSeekCompletedCb( void* data )
92 void LogPlayerError( int error )
94 if( error != PLAYER_ERROR_NONE )
98 case PLAYER_ERROR_OUT_OF_MEMORY:
100 DALI_LOG_ERROR( "Player error: Out of memory\n" );
103 case PLAYER_ERROR_INVALID_PARAMETER:
105 DALI_LOG_ERROR( "Player error: Invalid parameter\n" );
108 case PLAYER_ERROR_NO_SUCH_FILE:
110 DALI_LOG_ERROR( "Player error: No such file\n" );
113 case PLAYER_ERROR_INVALID_OPERATION:
115 DALI_LOG_ERROR( "Player error: Invalid operation\n" );
118 case PLAYER_ERROR_FILE_NO_SPACE_ON_DEVICE:
120 DALI_LOG_ERROR( "Player error: No space on device\n" );
123 case PLAYER_ERROR_FEATURE_NOT_SUPPORTED_ON_DEVICE:
125 DALI_LOG_ERROR( "Player error: Not supported feature on device\n" );
128 case PLAYER_ERROR_SEEK_FAILED:
130 DALI_LOG_ERROR( "Player error: Seek failed\n" );
133 case PLAYER_ERROR_INVALID_STATE:
135 DALI_LOG_ERROR( "Player error: Invalid state\n" );
138 case PLAYER_ERROR_NOT_SUPPORTED_FILE:
140 DALI_LOG_ERROR( "Player error: Not supported file\n" );
143 case PLAYER_ERROR_INVALID_URI:
145 DALI_LOG_ERROR( "Player error: Invalid uri\n" );
148 case PLAYER_ERROR_SOUND_POLICY:
150 DALI_LOG_ERROR( "Player error: Sound policy\n" );
153 case PLAYER_ERROR_CONNECTION_FAILED:
155 DALI_LOG_ERROR( "Player error: Connection failed\n" );
158 case PLAYER_ERROR_VIDEO_CAPTURE_FAILED:
160 DALI_LOG_ERROR( "Player error: Video capture failed\n" );
163 case PLAYER_ERROR_DRM_EXPIRED:
165 DALI_LOG_ERROR( "Player error: DRM expired\n" );
168 case PLAYER_ERROR_DRM_NO_LICENSE:
170 DALI_LOG_ERROR( "Player error: No license\n" );
173 case PLAYER_ERROR_DRM_FUTURE_USE:
175 DALI_LOG_ERROR( "Player error: License for future use\n" );
178 case PLAYER_ERROR_DRM_NOT_PERMITTED:
180 DALI_LOG_ERROR( "Player error: Format not permitted\n" );
183 case PLAYER_ERROR_RESOURCE_LIMIT:
185 DALI_LOG_ERROR( "Player error: Resource limit\n" );
188 case PLAYER_ERROR_PERMISSION_DENIED:
190 DALI_LOG_ERROR( "Player error: Permission denied\n" );
193 case PLAYER_ERROR_SERVICE_DISCONNECTED:
195 DALI_LOG_ERROR( "Player error: Service disconnected\n" );
198 case PLAYER_ERROR_BUFFER_SPACE:
200 DALI_LOG_ERROR( "Player error: Buffer space\n" );
207 } // unnamed namespace
209 TizenVideoPlayer::TizenVideoPlayer()
212 mPlayerState( PLAYER_STATE_NONE ),
215 mNativeImageSourcePtr( NULL ),
217 mBackgroundColor( Dali::Vector4( 1.0f, 1.0f, 1.0f, 0.0f ) ),
218 mTargetType( NativeImage ),
221 mEcoreWlWindow( NULL ),
222 mAlphaBitChanged( false )
226 TizenVideoPlayer::~TizenVideoPlayer()
230 void TizenVideoPlayer::GetPlayerState( player_state_e* state )
232 if( mPlayer != NULL && player_get_state( mPlayer, state ) != PLAYER_ERROR_NONE )
234 DALI_LOG_ERROR( "player_get_state error: Invalid parameter\n" );
235 *state = PLAYER_STATE_NONE;
239 void TizenVideoPlayer::SetUrl( const std::string& url )
245 GetPlayerState( &mPlayerState );
247 if( mPlayerState != PLAYER_STATE_NONE && mPlayerState != PLAYER_STATE_IDLE )
250 int error = player_unprepare( mPlayer );
251 LogPlayerError( error );
254 if( mPlayerState == PLAYER_STATE_IDLE )
256 int error = player_set_uri( mPlayer, mUrl.c_str() );
257 LogPlayerError( error );
259 error = player_prepare( mPlayer );
260 LogPlayerError( error );
265 std::string TizenVideoPlayer::GetUrl()
270 void TizenVideoPlayer::SetRenderingTarget( Any target )
273 if( mPlayerState != PLAYER_STATE_NONE )
275 GetPlayerState( &mPlayerState );
277 if( mPlayerState != PLAYER_STATE_IDLE )
280 error = player_unprepare( mPlayer );
281 LogPlayerError( error );
284 error = player_destroy( mPlayer );
285 LogPlayerError( error );
286 mPlayerState = PLAYER_STATE_NONE;
291 mNativeImageSourcePtr = NULL;
292 mEcoreWlWindow = NULL;
294 if( target.GetType() == typeid( Dali::NativeImageSourcePtr ) )
296 mTargetType = TizenVideoPlayer::NativeImage;
298 Dali::NativeImageSourcePtr nativeImageSourcePtr = AnyCast< Dali::NativeImageSourcePtr >( target );
300 InitializeTextureStreamMode( nativeImageSourcePtr );
302 else if( target.GetType() == typeid( Ecore_Wl_Window* ) )
304 mTargetType = TizenVideoPlayer::WindowSurface;
306 Ecore_Wl_Window* nativeWindow = Dali::AnyCast< Ecore_Wl_Window* >( target );
307 InitializeUnderlayMode( nativeWindow );
311 DALI_LOG_ERROR( "Video rendering target is unknown\n" );
315 void TizenVideoPlayer::SetLooping( bool looping )
317 GetPlayerState( &mPlayerState );
319 if( mPlayerState != PLAYER_STATE_NONE )
321 int error = player_set_looping( mPlayer, looping );
322 LogPlayerError( error );
326 bool TizenVideoPlayer::IsLooping()
328 GetPlayerState( &mPlayerState );
330 bool looping = false;
331 if( mPlayerState != PLAYER_STATE_NONE )
333 int error = player_is_looping( mPlayer, &looping );
334 LogPlayerError( error );
340 void TizenVideoPlayer::Play()
342 GetPlayerState( &mPlayerState );
344 if( mPlayerState == PLAYER_STATE_READY || mPlayerState == PLAYER_STATE_PAUSED )
346 if( mNativeImageSourcePtr != NULL && mTimer )
351 int error = player_start( mPlayer );
352 LogPlayerError( error );
356 void TizenVideoPlayer::Pause()
358 GetPlayerState( &mPlayerState );
360 if( mPlayerState == PLAYER_STATE_PLAYING )
362 int error = player_pause( mPlayer );
363 LogPlayerError( error );
365 if( mNativeImageSourcePtr != NULL && mTimer )
373 void TizenVideoPlayer::Stop()
375 GetPlayerState( &mPlayerState );
377 if( mPlayerState == PLAYER_STATE_PLAYING || mPlayerState == PLAYER_STATE_PAUSED )
379 int error = player_stop( mPlayer );
380 LogPlayerError( error );
383 if( mNativeImageSourcePtr != NULL && mTimer )
390 void TizenVideoPlayer::SetMute( bool muted )
392 GetPlayerState( &mPlayerState );
394 if( mPlayerState == PLAYER_STATE_IDLE ||
395 mPlayerState == PLAYER_STATE_READY ||
396 mPlayerState == PLAYER_STATE_PLAYING ||
397 mPlayerState == PLAYER_STATE_PAUSED
400 int error = player_set_mute( mPlayer, muted );
401 LogPlayerError( error );
405 bool TizenVideoPlayer::IsMuted()
407 GetPlayerState( &mPlayerState );
410 if( mPlayerState == PLAYER_STATE_IDLE ||
411 mPlayerState == PLAYER_STATE_READY ||
412 mPlayerState == PLAYER_STATE_PLAYING ||
413 mPlayerState == PLAYER_STATE_PAUSED
416 int error = player_is_muted( mPlayer, &muted );
417 LogPlayerError( error );
423 void TizenVideoPlayer::SetVolume( float left, float right )
425 GetPlayerState( &mPlayerState );
427 int error = player_set_volume( mPlayer, left, right );
428 LogPlayerError( error );
431 void TizenVideoPlayer::GetVolume( float& left, float& right )
433 GetPlayerState( &mPlayerState );
435 int error = player_get_volume( mPlayer, &left, &right );
436 LogPlayerError( error );
439 void TizenVideoPlayer::SetPlayPosition( int millisecond )
443 GetPlayerState( &mPlayerState );
445 if( mPlayerState == PLAYER_STATE_READY ||
446 mPlayerState == PLAYER_STATE_PLAYING ||
447 mPlayerState == PLAYER_STATE_PAUSED
450 error = player_set_play_position( mPlayer, millisecond, false, PlayerSeekCompletedCb, NULL );
451 LogPlayerError( error );
455 int TizenVideoPlayer::GetPlayPosition()
460 GetPlayerState( &mPlayerState );
462 if( mPlayerState == PLAYER_STATE_IDLE ||
463 mPlayerState == PLAYER_STATE_READY ||
464 mPlayerState == PLAYER_STATE_PLAYING ||
465 mPlayerState == PLAYER_STATE_PAUSED
468 error = player_get_play_position( mPlayer, &millisecond );
469 LogPlayerError( error );
475 void TizenVideoPlayer::SetDisplayRotation( Dali::VideoPlayerPlugin::DisplayRotation rotation )
477 if( mNativeImageSourcePtr != NULL )
479 DALI_LOG_ERROR( "SetDisplayRotation is only for window rendering target.\n" );
484 if( mPlayerState != PLAYER_STATE_NONE )
486 error = player_set_display_rotation( mPlayer, static_cast< player_display_rotation_e >( rotation ) );
487 LogPlayerError( error );
491 Dali::VideoPlayerPlugin::DisplayRotation TizenVideoPlayer::GetDisplayRotation()
493 if( mNativeImageSourcePtr != NULL )
495 DALI_LOG_ERROR( "GetDisplayRotation is only for window rendering target.\n" );
496 return Dali::VideoPlayerPlugin::ROTATION_NONE;
500 player_display_rotation_e rotation = PLAYER_DISPLAY_ROTATION_NONE;
501 if( mPlayerState != PLAYER_STATE_NONE )
503 error = player_get_display_rotation( mPlayer, &rotation );
504 LogPlayerError( error );
506 return static_cast< Dali::VideoPlayerPlugin::DisplayRotation >( rotation );
509 Dali::VideoPlayerPlugin::VideoPlayerSignalType& TizenVideoPlayer::FinishedSignal()
511 return mFinishedSignal;
514 void TizenVideoPlayer::InitializeTextureStreamMode( Dali::NativeImageSourcePtr nativeImageSourcePtr )
518 mNativeImageSourcePtr = nativeImageSourcePtr;
520 if( mAlphaBitChanged )
522 ecore_wl_window_alpha_set( mEcoreWlWindow, false );
523 mAlphaBitChanged = false;
526 if( mPlayerState == PLAYER_STATE_NONE )
528 error = player_create( &mPlayer );
529 LogPlayerError( error );
532 GetPlayerState( &mPlayerState );
534 if( mPlayerState == PLAYER_STATE_IDLE )
536 error = player_set_completed_cb( mPlayer, EmitPlaybackFinishedSignal, this );
537 LogPlayerError( error );
539 error = player_set_media_packet_video_frame_decoded_cb( mPlayer, MediaPacketVideoDecodedCb, this );
540 LogPlayerError( error );
542 error = player_set_sound_type( mPlayer, SOUND_TYPE_MEDIA );
543 LogPlayerError( error );
545 error = player_set_display_mode( mPlayer, PLAYER_DISPLAY_MODE_FULL_SCREEN );
546 LogPlayerError( error );
548 error = player_set_display( mPlayer, PLAYER_DISPLAY_TYPE_NONE, NULL );
549 LogPlayerError( error );
551 error = player_set_display_visible( mPlayer, true );
552 LogPlayerError( error );
554 mTimer = Dali::Timer::New( TIMER_INTERVAL );
555 mTimer.TickSignal().Connect( this, &TizenVideoPlayer::Update );
559 void TizenVideoPlayer::InitializeUnderlayMode( Ecore_Wl_Window* ecoreWlWindow )
562 if( mPlayerState == PLAYER_STATE_NONE )
564 error = player_create( &mPlayer );
565 LogPlayerError( error );
568 GetPlayerState( &mPlayerState );
569 mEcoreWlWindow = ecoreWlWindow;
571 if( mPlayerState == PLAYER_STATE_IDLE )
573 error = player_set_completed_cb( mPlayer, EmitPlaybackFinishedSignal, this );
574 LogPlayerError( error );
576 error = player_set_sound_type( mPlayer, SOUND_TYPE_MEDIA );
577 LogPlayerError( error );
579 error = player_set_display_mode( mPlayer, PLAYER_DISPLAY_MODE_DST_ROI );
580 LogPlayerError( error );
582 error = player_set_display_roi_area( mPlayer, 0, 0, 1, 1 );
585 mAlphaBitChanged = ( ecore_wl_window_alpha_get( mEcoreWlWindow ) )? false: true;
586 ecore_wl_screen_size_get( &width, &height );
588 if( mAlphaBitChanged )
590 ecore_wl_window_alpha_set( mEcoreWlWindow, true );
592 error = player_set_ecore_wl_display( mPlayer, PLAYER_DISPLAY_TYPE_OVERLAY, mEcoreWlWindow, 0, 0, width, height );
593 LogPlayerError( error );
595 error = player_set_display_visible( mPlayer, true );
596 LogPlayerError( error );
600 bool TizenVideoPlayer::Update()
602 Dali::Mutex::ScopedLock lock( mPacketMutex );
606 if( mPacket != NULL )
608 error = media_packet_destroy( mPacket );
609 if( error != MEDIA_PACKET_ERROR_NONE )
611 DALI_LOG_ERROR( "Media packet destroy error: %d\n", error );
616 if( !mPacketVector.Empty() )
618 mPacket = static_cast< media_packet_h >( mPacketVector[0] );
619 mPacketVector.Remove( mPacketVector.Begin() );
622 if( mPacket == NULL )
627 error = media_packet_get_tbm_surface( mPacket, &mTbmSurface );
628 if( error != MEDIA_PACKET_ERROR_NONE )
630 media_packet_destroy( mPacket );
632 DALI_LOG_ERROR( " error: %d\n", error );
636 Any source( mTbmSurface );
637 mNativeImageSourcePtr->SetSource( source );
638 Dali::Stage::GetCurrent().KeepRendering( 0.0f );
643 void TizenVideoPlayer::DestroyPackets()
646 if( mPacket != NULL )
648 error = media_packet_destroy( mPacket );
649 DALI_LOG_ERROR( "Media packet destroy error: %d\n", error );
653 for(unsigned int i = 0; i < mPacketVector.Size(); ++i)
655 mPacket = static_cast< media_packet_h >( mPacketVector[i] );
656 error = media_packet_destroy( mPacket );
657 DALI_LOG_ERROR( "Media packet destroy error: %d\n", error );
660 mPacketVector.Clear();
663 void TizenVideoPlayer::PushPacket( media_packet_h packet )
665 Dali::Mutex::ScopedLock lock( mPacketMutex );
666 mPacketVector.PushBack( packet );
669 void TizenVideoPlayer::SetDisplayArea( DisplayArea area )
671 GetPlayerState( &mPlayerState );
673 if( mNativeImageSourcePtr != NULL )
675 DALI_LOG_ERROR( "SetDisplayArea is only for window surface target.\n" );
679 if( mPlayerState == PLAYER_STATE_IDLE ||
680 mPlayerState == PLAYER_STATE_READY ||
681 mPlayerState == PLAYER_STATE_PLAYING ||
682 mPlayerState == PLAYER_STATE_PAUSED
686 area.x = ( area.x < 0 ) ? 0: area.x;
687 area.y = ( area.y < 0 ) ? 0: area.y;
688 int error = player_set_display_roi_area( mPlayer, area.x, area.y, area.width, area.height );
689 LogPlayerError( error );
693 void TizenVideoPlayer::Forward( int millisecond )
697 GetPlayerState( &mPlayerState );
699 if( mPlayerState == PLAYER_STATE_READY ||
700 mPlayerState == PLAYER_STATE_PLAYING ||
701 mPlayerState == PLAYER_STATE_PAUSED
704 int currentPosition = 0;
705 int nextPosition = 0;
707 error = player_get_play_position( mPlayer, ¤tPosition );
708 LogPlayerError( error );
710 nextPosition = currentPosition + millisecond;
712 error = player_set_play_position( mPlayer, nextPosition, false, PlayerSeekCompletedCb, NULL );
713 LogPlayerError( error );
717 void TizenVideoPlayer::Backward( int millisecond )
721 GetPlayerState( &mPlayerState );
723 if( mPlayerState == PLAYER_STATE_READY ||
724 mPlayerState == PLAYER_STATE_PLAYING ||
725 mPlayerState == PLAYER_STATE_PAUSED
728 int currentPosition = 0;
729 int nextPosition = 0;
731 error = player_get_play_position( mPlayer, ¤tPosition );
732 LogPlayerError( error );
734 nextPosition = currentPosition - millisecond;
735 nextPosition = ( nextPosition < 0 )? 0 : nextPosition;
737 error = player_set_play_position( mPlayer, nextPosition, false, PlayerSeekCompletedCb, NULL );
738 LogPlayerError( error );
742 bool TizenVideoPlayer::IsVideoTextureSupported()
744 bool featureFlag = true;
745 int error = SYSTEM_INFO_ERROR_NONE;
747 error = system_info_get_platform_bool( "tizen.org/feature/multimedia.raw_video", &featureFlag );
749 if( error != SYSTEM_INFO_ERROR_NONE )
751 DALI_LOG_ERROR( "Plugin can't check platform feature\n" );
758 } // namespace Plugin