[3.0] Fix Svace warning issue
[platform/core/uifw/dali-adaptor.git] / plugins / video-player / tizen-video-player.cpp
1 /*
2  * Copyright (c) 2016 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */
17
18 // CLASS HEADER
19 #include <tizen-video-player.h>
20
21 // EXTERNAL INCLUDES
22 #include <dali/public-api/common/stage.h>
23 #include <dali/devel-api/threading/mutex.h>
24 #include <dali/integration-api/debug.h>
25
26 // INTERNAL INCLUDES
27
28 // The plugin factories
29 extern "C" DALI_EXPORT_API Dali::VideoPlayerPlugin* CreateVideoPlayerPlugin( void )
30 {
31   return new Dali::Plugin::TizenVideoPlayer;
32 }
33
34 extern "C" DALI_EXPORT_API void DestroyVideoPlayerPlugin( Dali::VideoPlayerPlugin* plugin )
35 {
36   if( plugin != NULL )
37   {
38     delete plugin;
39   }
40 }
41
42 namespace Dali
43 {
44
45 namespace Plugin
46 {
47
48 namespace
49 {
50
51 const int TIMER_INTERVAL( 20 );
52
53 static void MediaPacketVideoDecodedCb( media_packet_h packet, void* user_data )
54 {
55   TizenVideoPlayer* player = static_cast< TizenVideoPlayer* >( user_data );
56
57   if( player == NULL )
58   {
59     DALI_LOG_ERROR( "Decoded callback got Null pointer as user_data." );
60     return;
61   }
62
63   player->PushPacket( packet );
64 }
65
66
67 static void EmitPlaybackFinishedSignal( void* user_data )
68 {
69   TizenVideoPlayer* player = static_cast< TizenVideoPlayer* >( user_data );
70   DALI_LOG_ERROR( "EmitPlaybackFinishedSignal.0" );
71
72   if( player == NULL )
73   {
74     DALI_LOG_ERROR( "Decoded callback got Null pointer as user_data." );
75     return;
76   }
77
78   DALI_LOG_ERROR( "EmitPlaybackFinishedSignal." );
79
80   if( !player->mFinishedSignal.Empty() )
81   {
82     DALI_LOG_ERROR( "EmitPlaybackFinishedSignal.3" );
83     player->mFinishedSignal.Emit();
84   }
85
86   player->Stop();
87 }
88
89 void LogPlayerError( int error )
90 {
91   if( error != PLAYER_ERROR_NONE )
92   {
93     switch( error )
94     {
95       case PLAYER_ERROR_OUT_OF_MEMORY:
96       {
97         DALI_LOG_ERROR( "Player error: Out of memory\n" );
98         return;
99       }
100       case PLAYER_ERROR_INVALID_PARAMETER:
101       {
102         DALI_LOG_ERROR( "Player error: Invalid parameter\n" );
103         return;
104       }
105       case PLAYER_ERROR_NO_SUCH_FILE:
106       {
107         DALI_LOG_ERROR( "Player error: No such file\n" );
108         return;
109       }
110       case PLAYER_ERROR_INVALID_OPERATION:
111       {
112         DALI_LOG_ERROR( "Player error: Invalid operation\n" );
113         return;
114       }
115       case PLAYER_ERROR_FILE_NO_SPACE_ON_DEVICE:
116       {
117         DALI_LOG_ERROR( "Player error: No space on device\n" );
118         return;
119       }
120       case PLAYER_ERROR_FEATURE_NOT_SUPPORTED_ON_DEVICE:
121       {
122         DALI_LOG_ERROR( "Player error: Not supported feature on device\n" );
123         return;
124       }
125       case PLAYER_ERROR_SEEK_FAILED:
126       {
127         DALI_LOG_ERROR( "Player error: Seek failed\n" );
128         return;
129       }
130       case PLAYER_ERROR_INVALID_STATE:
131       {
132         DALI_LOG_ERROR( "Player error: Invalid state\n" );
133         return;
134       }
135       case PLAYER_ERROR_NOT_SUPPORTED_FILE:
136       {
137         DALI_LOG_ERROR( "Player error: Not supported file\n" );
138         return;
139       }
140       case PLAYER_ERROR_INVALID_URI:
141       {
142         DALI_LOG_ERROR( "Player error: Invalid uri\n" );
143         return;
144       }
145       case PLAYER_ERROR_SOUND_POLICY:
146       {
147         DALI_LOG_ERROR( "Player error: Sound policy\n" );
148         return;
149       }
150       case PLAYER_ERROR_CONNECTION_FAILED:
151       {
152         DALI_LOG_ERROR( "Player error: Connection failed\n" );
153         return;
154       }
155       case PLAYER_ERROR_VIDEO_CAPTURE_FAILED:
156       {
157         DALI_LOG_ERROR( "Player error: Video capture failed\n" );
158         return;
159       }
160       case PLAYER_ERROR_DRM_EXPIRED:
161       {
162         DALI_LOG_ERROR( "Player error: DRM expired\n" );
163         return;
164       }
165       case PLAYER_ERROR_DRM_NO_LICENSE:
166       {
167         DALI_LOG_ERROR( "Player error: No license\n" );
168         return;
169       }
170       case PLAYER_ERROR_DRM_FUTURE_USE:
171       {
172         DALI_LOG_ERROR( "Player error: License for future use\n" );
173         return;
174       }
175       case PLAYER_ERROR_DRM_NOT_PERMITTED:
176       {
177         DALI_LOG_ERROR( "Player error: Format not permitted\n" );
178         return;
179       }
180       case PLAYER_ERROR_RESOURCE_LIMIT:
181       {
182         DALI_LOG_ERROR( "Player error: Resource limit\n" );
183         return;
184       }
185       case PLAYER_ERROR_PERMISSION_DENIED:
186       {
187         DALI_LOG_ERROR( "Player error: Permission denied\n" );
188         return;
189       }
190       case PLAYER_ERROR_SERVICE_DISCONNECTED:
191       {
192         DALI_LOG_ERROR( "Player error: Service disconnected\n" );
193         return;
194       }
195       case PLAYER_ERROR_BUFFER_SPACE:
196       {
197         DALI_LOG_ERROR( "Player error: Buffer space\n" );
198         return;
199       }
200     }
201   }
202 }
203
204 } // unnamed namespace
205
206 TizenVideoPlayer::TizenVideoPlayer()
207 : mPlayerState( PLAYER_STATE_NONE ),
208   mPacket( NULL ),
209   mBackgroundColor( Dali::Stage::DEFAULT_BACKGROUND_COLOR ),
210   mTargetType( NativeImage )
211 {
212 }
213
214 TizenVideoPlayer::~TizenVideoPlayer()
215 {
216 }
217
218 void TizenVideoPlayer::GetPlayerState( player_state_e* state )
219 {
220   if( player_get_state( mPlayer, state ) != PLAYER_ERROR_NONE )
221   {
222     DALI_LOG_ERROR( "player_get_state error: Invalid parameter\n" );
223     *state = PLAYER_STATE_NONE;
224   }
225 }
226
227 void TizenVideoPlayer::SetUrl( const std::string& url )
228 {
229   if( mUrl != url )
230   {
231     mUrl = url;
232
233     GetPlayerState( &mPlayerState );
234
235     if( mPlayerState != PLAYER_STATE_NONE && mPlayerState != PLAYER_STATE_IDLE )
236     {
237       Stop();
238       int error = player_unprepare( mPlayer );
239       LogPlayerError( error );
240     }
241
242     if( mPlayerState == PLAYER_STATE_IDLE )
243     {
244       int error = player_set_uri( mPlayer, mUrl.c_str() );
245       LogPlayerError( error );
246
247       error = player_prepare( mPlayer );
248       LogPlayerError( error );
249     }
250   }
251 }
252
253 std::string TizenVideoPlayer::GetUrl()
254 {
255   return mUrl;
256 }
257
258 void TizenVideoPlayer::SetRenderingTarget( Any target )
259 {
260   int error;
261   if( mPlayerState != PLAYER_STATE_NONE )
262   {
263     GetPlayerState( &mPlayerState );
264
265     if( mPlayerState != PLAYER_STATE_IDLE )
266     {
267       Stop();
268       error = player_unprepare( mPlayer );
269       LogPlayerError( error );
270     }
271
272     error = player_destroy( mPlayer );
273     LogPlayerError( error );
274     mPlayerState = PLAYER_STATE_NONE;
275     mPlayer = NULL;
276     mUrl = "";
277   }
278
279   mNativeImageSourcePtr = NULL;
280
281   if( target.GetType() == typeid( Dali::NativeImageSourcePtr ) )
282   {
283     if( mTargetType == TizenVideoPlayer::WindowSurface )
284     {
285       Stage::GetCurrent().SetBackgroundColor( mBackgroundColor );
286     }
287     mTargetType = TizenVideoPlayer::NativeImage;
288
289     Dali::NativeImageSourcePtr nativeImageSourcePtr = AnyCast< Dali::NativeImageSourcePtr >( target );
290
291     InitializeTextureStreamMode( nativeImageSourcePtr );
292   }
293   else if( target.GetType() == typeid( Ecore_Wl_Window* ) )
294   {
295     mTargetType = TizenVideoPlayer::WindowSurface;
296     mBackgroundColor = Stage::GetCurrent().GetBackgroundColor();
297     Stage::GetCurrent().SetBackgroundColor( Color::TRANSPARENT );
298
299     Ecore_Wl_Window* nativeWindow = Dali::AnyCast< Ecore_Wl_Window* >( target );
300     InitializeUnderlayMode( nativeWindow );
301   }
302   else
303   {
304     DALI_LOG_ERROR( "Video rendering target is unknown" );
305   }
306 }
307
308 void TizenVideoPlayer::SetLooping( bool looping )
309 {
310   GetPlayerState( &mPlayerState );
311
312   if( mPlayerState != PLAYER_STATE_NONE )
313   {
314     int error = player_set_looping( mPlayer, looping );
315     LogPlayerError( error );
316   }
317 }
318
319 bool TizenVideoPlayer::IsLooping()
320 {
321   GetPlayerState( &mPlayerState );
322
323   bool looping = false;
324   if( mPlayerState != PLAYER_STATE_NONE )
325   {
326     int error = player_is_looping( mPlayer, &looping );
327     LogPlayerError( error );
328   }
329
330   return looping;
331 }
332
333 void TizenVideoPlayer::Play()
334 {
335   GetPlayerState( &mPlayerState );
336
337   if( mPlayerState == PLAYER_STATE_READY || mPlayerState == PLAYER_STATE_PAUSED )
338   {
339     if( mNativeImageSourcePtr != NULL && mTimer )
340     {
341       mTimer.Start();
342     }
343
344     int error = player_start( mPlayer );
345     LogPlayerError( error );
346   }
347 }
348
349 void TizenVideoPlayer::Pause()
350 {
351   GetPlayerState( &mPlayerState );
352
353   if( mPlayerState == PLAYER_STATE_PLAYING )
354   {
355     int error = player_pause( mPlayer );
356     LogPlayerError( error );
357
358     if( mNativeImageSourcePtr != NULL && mTimer )
359     {
360       mTimer.Stop();
361       DestroyPackets();
362     }
363   }
364 }
365
366 void TizenVideoPlayer::Stop()
367 {
368   GetPlayerState( &mPlayerState );
369
370   if( mPlayerState == PLAYER_STATE_PLAYING || mPlayerState == PLAYER_STATE_PAUSED )
371   {
372     int error = player_stop( mPlayer );
373     LogPlayerError( error );
374   }
375
376   if( mNativeImageSourcePtr != NULL && mTimer )
377   {
378     mTimer.Stop();
379     DestroyPackets();
380   }
381 }
382
383 void TizenVideoPlayer::SetMute( bool muted )
384 {
385   GetPlayerState( &mPlayerState );
386
387   if( mPlayerState == PLAYER_STATE_IDLE ||
388       mPlayerState == PLAYER_STATE_READY ||
389       mPlayerState == PLAYER_STATE_PLAYING ||
390       mPlayerState == PLAYER_STATE_PAUSED
391     )
392   {
393     int error = player_set_mute( mPlayer, muted );
394     LogPlayerError( error );
395   }
396 }
397
398 bool TizenVideoPlayer::IsMuted()
399 {
400   GetPlayerState( &mPlayerState );
401   bool muted = false;
402
403    if( mPlayerState == PLAYER_STATE_IDLE ||
404       mPlayerState == PLAYER_STATE_READY ||
405       mPlayerState == PLAYER_STATE_PLAYING ||
406       mPlayerState == PLAYER_STATE_PAUSED
407     )
408   {
409     bool muted = false;
410     int error = player_is_muted( mPlayer, &muted );
411     LogPlayerError( error );
412   }
413
414   return muted;
415 }
416
417 void TizenVideoPlayer::SetVolume( float left, float right )
418 {
419   GetPlayerState( &mPlayerState );
420
421   int error = player_set_volume( mPlayer, left, right );
422   LogPlayerError( error );
423 }
424
425 void TizenVideoPlayer::GetVolume( float& left, float& right )
426 {
427   GetPlayerState( &mPlayerState );
428
429   int error = player_get_volume( mPlayer, &left, &right );
430   LogPlayerError( error );
431 }
432
433 void TizenVideoPlayer::SetPlayPosition( int millisecond )
434 {
435   int error;
436
437   GetPlayerState( &mPlayerState );
438
439   if( mPlayerState == PLAYER_STATE_READY ||
440       mPlayerState == PLAYER_STATE_PLAYING ||
441       mPlayerState == PLAYER_STATE_PAUSED
442   )
443   {
444     error = player_set_play_position( mPlayer, millisecond, true, NULL, NULL );
445     LogPlayerError( error );
446   }
447 }
448
449 int TizenVideoPlayer::GetPlayPosition()
450 {
451   int error;
452   int millisecond = 0;
453
454   GetPlayerState( &mPlayerState );
455
456   if( mPlayerState == PLAYER_STATE_IDLE ||
457       mPlayerState == PLAYER_STATE_READY ||
458       mPlayerState == PLAYER_STATE_PLAYING ||
459       mPlayerState == PLAYER_STATE_PAUSED
460   )
461   {
462     error = player_get_play_position( mPlayer, &millisecond );
463     LogPlayerError( error );
464   }
465
466   return millisecond;
467 }
468
469 void TizenVideoPlayer::SetDisplayRotation( Dali::VideoPlayerPlugin::DisplayRotation rotation )
470 {
471   if( mNativeImageSourcePtr != NULL )
472   {
473     DALI_LOG_ERROR( "SetDisplayRotation is only for window rendering target.\n" );
474     return;
475   }
476
477   int error;
478   if( mPlayerState != PLAYER_STATE_NONE )
479   {
480     error = player_set_display_rotation( mPlayer, static_cast< player_display_rotation_e >( rotation ) );
481     LogPlayerError( error );
482   }
483 }
484
485 Dali::VideoPlayerPlugin::DisplayRotation TizenVideoPlayer::GetDisplayRotation()
486 {
487   if( mNativeImageSourcePtr != NULL )
488   {
489     DALI_LOG_ERROR( "GetDisplayRotation is only for window rendering target.\n" );
490     return Dali::VideoPlayerPlugin::ROTATION_NONE;
491   }
492
493   int error;
494   player_display_rotation_e rotation = PLAYER_DISPLAY_ROTATION_NONE;
495   if( mPlayerState != PLAYER_STATE_NONE )
496   {
497     error = player_get_display_rotation( mPlayer, &rotation );
498     LogPlayerError( error );
499   }
500   return static_cast< Dali::VideoPlayerPlugin::DisplayRotation >( rotation );
501 }
502
503 Dali::VideoPlayerPlugin::VideoPlayerSignalType& TizenVideoPlayer::FinishedSignal()
504 {
505   return mFinishedSignal;
506 }
507
508 void TizenVideoPlayer::InitializeTextureStreamMode( Dali::NativeImageSourcePtr nativeImageSourcePtr )
509 {
510   int error;
511
512   mNativeImageSourcePtr = nativeImageSourcePtr;
513
514   if( mPlayerState == PLAYER_STATE_NONE )
515   {
516     error = player_create( &mPlayer );
517     LogPlayerError( error );
518   }
519
520   GetPlayerState( &mPlayerState );
521
522   if( mPlayerState == PLAYER_STATE_IDLE )
523   {
524     error = player_set_completed_cb( mPlayer, EmitPlaybackFinishedSignal, this );
525     LogPlayerError( error );
526
527     error = player_set_media_packet_video_frame_decoded_cb( mPlayer, MediaPacketVideoDecodedCb, this );
528     LogPlayerError( error );
529
530     error = player_set_sound_type( mPlayer, SOUND_TYPE_MEDIA );
531     LogPlayerError( error );
532
533     error = player_set_display_mode( mPlayer, PLAYER_DISPLAY_MODE_FULL_SCREEN );
534     LogPlayerError( error );
535
536     error = player_set_display( mPlayer, PLAYER_DISPLAY_TYPE_NONE, NULL );
537     LogPlayerError( error );
538
539     error = player_set_display_visible( mPlayer, true );
540     LogPlayerError( error );
541
542     mTimer = Dali::Timer::New( TIMER_INTERVAL );
543     mTimer.TickSignal().Connect( this, &TizenVideoPlayer::Update );
544   }
545 }
546
547 void TizenVideoPlayer::InitializeUnderlayMode( Ecore_Wl_Window* ecoreWlWindow )
548 {
549   int error;
550   if( mPlayerState == PLAYER_STATE_NONE )
551   {
552     error = player_create( &mPlayer );
553     LogPlayerError( error );
554   }
555
556   GetPlayerState( &mPlayerState );
557
558   if( mPlayerState == PLAYER_STATE_IDLE )
559   {
560     error = player_set_completed_cb( mPlayer, EmitPlaybackFinishedSignal, this );
561     LogPlayerError( error );
562
563     error = player_set_sound_type( mPlayer, SOUND_TYPE_MEDIA );
564     LogPlayerError( error );
565
566     error = player_set_display_mode( mPlayer, PLAYER_DISPLAY_MODE_FULL_SCREEN );
567     LogPlayerError( error );
568
569     int width, height;
570     ecore_wl_screen_size_get( &width, &height );
571     error = player_set_ecore_wl_display( mPlayer, PLAYER_DISPLAY_TYPE_OVERLAY, ecoreWlWindow, 0, 0, width, height );
572     LogPlayerError( error );
573
574     error = player_set_display_visible( mPlayer, true );
575     LogPlayerError( error );
576   }
577 }
578
579 bool TizenVideoPlayer::Update()
580 {
581   Dali::Mutex::ScopedLock lock( mPacketMutex );
582
583   int error;
584
585   if( mPacket != NULL )
586   {
587     error = media_packet_destroy( mPacket );
588     if( error != MEDIA_PACKET_ERROR_NONE )
589     {
590       DALI_LOG_ERROR( "Media packet destroy error: %d\n", error );
591     }
592     mPacket = NULL;
593   }
594
595   if( !mPacketVector.Empty() )
596   {
597     mPacket = static_cast< media_packet_h >( mPacketVector[0] );
598     mPacketVector.Remove( mPacketVector.Begin() );
599   }
600
601   if( mPacket == NULL )
602   {
603     return true;
604   }
605
606   error = media_packet_get_tbm_surface( mPacket, &mTbmSurface );
607   if( error != MEDIA_PACKET_ERROR_NONE )
608   {
609     media_packet_destroy( mPacket );
610     mPacket = NULL;
611     DALI_LOG_ERROR( " error: %d\n", error );
612     return true;
613   }
614
615   Any source( mTbmSurface );
616   mNativeImageSourcePtr->SetSource( source );
617   Dali::Stage::GetCurrent().KeepRendering( 0.0f );
618
619   return true;
620 }
621
622 void TizenVideoPlayer::DestroyPackets()
623 {
624   int error;
625   if( mPacket != NULL )
626   {
627     error = media_packet_destroy( mPacket );
628     DALI_LOG_ERROR( "Media packet destroy error: %d\n", error );
629     mPacket = NULL;
630   }
631
632   for(unsigned int i = 0; i < mPacketVector.Size(); ++i)
633   {
634     mPacket = static_cast< media_packet_h >( mPacketVector[i] );
635     error = media_packet_destroy( mPacket );
636     DALI_LOG_ERROR( "Media packet destroy error: %d\n", error );
637     mPacket = NULL;
638   }
639   mPacketVector.Clear();
640 }
641
642 void TizenVideoPlayer::PushPacket( media_packet_h packet )
643 {
644   Dali::Mutex::ScopedLock lock( mPacketMutex );
645   mPacketVector.PushBack( packet );
646 }
647
648 } // namespace Plugin
649 } // namespace Dali;