Mobile native Wearable native

Player: Playing Multimedia Content from a File, Network, and Memory

This tutorial demonstrates how you can play audio and video files and play multiple audio files simultaneously.

Warm-up

Become familiar with the Player API basics by learning about:

Follow-up

Once we have learned the basics of the Player API, we can now move on to more advanced tasks, including:

Initializing the Player

To initialize the player:

  1. To use the functions and data types of the Player API (in mobile and wearable applications), include the <player.h>, <Elementary.h>, and <glib.h> header files in your application:

    #include <player.h>
    #include <Elementary.h>
    #include <glib.h>
    

    The <Elementary.h> header file is needed for setting the display.

  2. You must get the default path for this tutorial. For the following example code, you must include the <storage.h> header file.

    #define MP3_SAMPLE "SampleAudio.mp3";
    #define MP4_SAMPLE "SampleVideo.mp4";
    
    int internal_storage_id;
    char *audio_storage_path = NULL;
    char *video_storage_path = NULL;
    char *audio_path = NULL;
    char *video_path = NULL;
    
    static bool storage_cb(int storage_id, storage_type_e type, storage_state_e state, const char *path, void *user_data)
    {
       if (type == STORAGE_TYPE_INTERNAL)
       {
          internal_storage_id = storage_id;
    
          return false;
       }
    
       return true;
    }
    
    void _get_storage_path()
    {
       int error_code = 0;
       char *path = NULL;
    
       error_code = storage_foreach_device_supported(storage_cb, NULL);
       error_code = storage_get_directory(internal_storage_id, STORAGE_DIRECTORY_MUSIC, &path);
       if (error_code != STORAGE_ERROR_NONE)
       {
          audio_storage_path = strdup(path);
          free(path);
       }
    
       error_code = storage_get_directory(internal_storage_id, STORAGE_DIRECTORY_VIDEOS, &path);
       if (error_code != STORAGE_ERROR_NONE)
       {
          video_storage_path = strdup(path);
          free(path);
       }
    }
    
    void _set_test_path()
    {
       int path_len = 0;
    
       path_len = strlen(audio_storage_path) + strlen(MP3_SAMPLE) + 1;
       audio_path = malloc(path_len);
       memset(audio_path, 0x0, path_len);
    
       strncat(audio_path, audio_storage_path, strlen(audio_storage_path));
       strncat(audio_path, MP3_SAMPLE, strlen(MP3_SAMPLE));
    
       path_len = strlen(video_storage_path) + strlen(MP4_SAMPLE) + 1;
       video_path = malloc(path_len);
       memset(video_path, 0x0, path_len);
    
       strncat(video_path, video_storage_path, strlen(video_storage_path));
       strncat(video_path, MP4_SAMPLE, strlen(MP4_SAMPLE));
    }
    
  3. Create a player handle and pass it to the player_create() function. You need the player handle for defining which file to play and with what playback settings.

    typedef struct appdata 
    {
       player_h player;
    } 
    
    static void init_base_player(appdata_s *ad) 
    {
       int error_code = 0;
       error_code = player_create(&ad->player);
       if (error_code != PLAYER_ERROR_NONE)
          dlog_print(DLOG_ERROR, LOG_TAG, "failed to create");
       // Do setting more for playback, like setting callback, setting_uri and prepare
    }
    
    static void create_base_gui(appdata_s *ad)
    {
       // Make window
       // Make button
       // Add callback to button
       evas_object_smart_callback_add(button_init, "clicked", init_base_player, ad);
       evas_object_smart_callback_add(button_end, "clicked", release_base_player, ad);                 
       // Create an Evas image object for the video surface
    }
    
    static void app_create(void *data) 
    {
       appdata_s *ad = data;
       create_base_gui(ad);
    
       return true;
    }
  4. To receive notifications about playback interruptions, register a callback function using the player_set_interrupted_cb() function. The playback is interrupted and the callback triggered when another multimedia application is run. The player state automatically changes to PLAYER_STATE_PAUSED or PLAYER_STATE_IDLE according to the session policy. To get the current state, use the player_get_state() function.

    static void _player_interrupted_cb(player_interrupted_coded_e code, void *data)
    {
       appdata_s *ad = data;
       player_state_e state;
    
       player_get_state(ad->player, &state);
       log_print(DLOG_INFO, LOG_TAG, "current player state = %d", state);
       // If the state is PLAYER_STATE_PAUSED, update UI like button
    }
    
    static void init_base_player(appdata_s *ad)
    {  
       // Set an interruption callback if the application wants to know the point
       error_code = player_set_interrupted_cb(g_player, _player_interrupted_cb, ad);
       if (error_code != PLAYER_ERROR_NONE)
          dlog_print(DLOG_ERROR, LOG_TAG, "failed to create");
    }
  5. To receive a notification when the playback completes, register a callback function using the player_set_completed_cb() function:

    static void _player_completed_cb(void *data)
    {
       dlog_print(DLOG_INFO, "Player", "Playback End");
    }
    
    static void init_base_player(appdata_s *ad)
    {
       // Set a completed callback if the application wants to know the point
       error_code = player_set_completed_cb(g_player, _player_completed_cb, ad);
    
       if (error_code != PLAYER_ERROR_NONE)
          dlog_print(DLOG_ERROR, LOG_TAG, "failed to set completed cb");
    }
  6. To receive notifications about player errors during the playback, register a callback function using the player_set_error_cb() function:

    static void init_base_player(appdata_s *ad)
    {
       error_code = player_set_error_cb(g_player, _player_error_cb, NULL);
       if (error_code != PLAYER_ERROR_NONE)
          dlog_print(DLOG_ERROR, LOG_TAG, "failed to set error cb");
    }

    The following example code implements the _player_error_cb() callback function. The callback is triggered when the player stops working due to an error. The callback tries to change the player state to PLAYER_STATE_READY by calling the player_stop() function. The callback then removes all other callbacks and resets the player by calling the player_unprepare() function. At the end, the player is in the PLAYER_STATE_IDLE state, so you can release the resources allocated to the player.

    static void _player_error_cb(int error_code, void *user_data)
    {
       dlog_print(DLOG_ERROR, LOG_TAG, "playback failed, error = %x", error_code);
    }
    Note
    Do not call the player_destroy() function from the called context, as this can cause the PLAYER_ERROR_INVALID_OPERATION error.

Playing an Audio File

To play an audio file:

  1. Set the audio file path after creating the audio player handler.

    To specify the source file to play, use the player_set_uri() function:

    error_code = player_set_uri(ad->player, audio_path);
  2. Prepare the player for playback.

    Before you can start the playback, the player has to change its state from PLAYER_STATE_IDLE to PLAYER_STATE_READY. To change the state, use the player_prepare() function:

    error_code = player_prepare(ad->player);
  3. Play the audio file.

    To start the playback, use the player_start() function:

    error_code = player_start(ad->player);

Playing a Video File

To play a video file:

  1. Set the video file path.

    To specify the source file to play, use the player_set_uri() function:

    error_code = player_set_uri(ad->player, video_path);
  2. Set the display on which the video is played.

    To get the correct display handle, use the GET_DISPLAY() function. To set the display, use the player_set_display() function with the display handle.

    error_code = player_set_display(g_player, PLAYER_DISPLAY_TYPE_OVERLAY, GET_DISPLAY(evas_obj));
    Note
    In case of an overlay surface, when the device orientation changes, the displayed video does not rotate automatically. If you want to change the video orientation according to the device orientation, use the player_set_display_rotation() function within the app_device_orientation_cb() callback function used by the application. In case of an Evas surface, the Evas object for the video is rotated by the window manager used by the application, not by the player_set_display_rotation() function.
  3. Prepare the player for playback.

    Before you can start the playback, the player has to change its state from PLAYER_STATE_IDLE to PLAYER_STATE_READY. To change the state, use the player_prepare() function:

    error_code = player_prepare(ad->player);

    The player_prepare() function works synchronously, so it can be blocked. To prepare the player asynchronously instead, use the player_prepare_async() function:

    error_code = player_prepare_async(ad->player, _prepared_cb, ad);
  4. Play the video file:

    1. Ensure that the player state has changed to PLAYER_STATE_READY. To check the state, use the player_get_state() function, and to start the playback, use the player_start() function:

      player_state_e state;
      do 
      {
         error_code = player_get_state(ad->player, &state);
         if (error_code != PLAYER_ERROR_NONE)
            break;
         usleep(1000);
      } while (state != PLAYER_STATE_READY);
      
      if (error_code == PLAYER_ERROR_NONE) 
      {
         error_code = player_start(ad->player);
      }
    2. To start the playback, use the player_start() function:

      error_code = player_start(g_player);

      After a successful call of this function, the player state is set to PLAYER_STATE_PLAYING and the playback of the media content stored in the previously specified file starts. The video file plays until you call the player_stop() or player_pause() function.

    3. If you used the player_prepare_async() function to prepare the player, use the following callback functions to handle the playback:

      static void _prepared_cb(void *data)
      {
         appdata_s *ad = data;
         int error_code = 0;
         error_code = player_start(ad->player);
      }

Stopping the Player and Releasing Resources

To stop the player when it is no longer needed:

  1. Reset the player using the player_unprepare() function with the player handle as a parameter. Before using this function, make sure that the player is stopped using the player_stop() function.

    error_code = player_stop(player);
    dlog_print(DLOG_ERROR, LOG_TAG, "player_stop() = %d", error_code);
    
    error_code = player_unprepare(player);
    dlog_print(DLOG_ERROR, LOG_TAG, "player_unprepare() = %d", error_code);
    
  2. When the player is unprepared, it is in the PLAYER_STATE_IDLE state. Destroy the player handle using the player_destroy() function.

    error_code = player_destroy(player);
    dlog_print(DLOG_ERROR, LOG_TAG, "player_destroy = %d", error_code);
    

Initializing the Players

To initialize the players:

  1. To use the functions and data types of the Player API (in mobile and wearable applications), include the <player.h>, <stdio.h>, and <unistd.h> header files in your application:

    #include <player.h>
    #include <stdio.h>
    #include <unistd.h>
    
  2. Declare the variables for player handlers, player states, file paths, playback time, and return value:
    static player_h player_1, player_2, player_3;
    static player_state_e state_1, state_2, state_3;
    static int ret =0;
    static char *path_1 = NULL;
    static char *path_2 = NULL;
    static char *path_3 = NULL;
    char *resource_path = NULL;
    
    resource_path = app_get_resource_path();
    snprintf(path_1, sizeof(path_1)-1, "%s/sample.3gp", resource_path);
    snprintf(path_2, sizeof(path_2)-1, "%s/test.wav", resource_path);
    snprintf(path_3, sizeof(path_3)-1, "%s/test2.wav", resource_path);
    free(resource_path);
    
    static const int PLAYBACK_TIME=6;

    To ensure that a function has been properly executed, always check its return value. If the return value differs from PLAYER_ERROR_NONE, an error has occurred.

Playing Multiple Files Simultaneously

To play multiple files simultaneously:

  1. To play multiple files at the same time, create a player handle for each file using the player_create() function:

    ret = player_create(&player_1);
    
    ret = player_create(&player_2);
    
    ret = player_create(&player_3);
    
  2. To specify the source files to play, use the player_set_uri() function:

    ret = player_set_uri(player_1, path_1);
    
    ret = player_set_uri(player_2, path_2);
    
    ret = player_set_uri(player_3, path_3);
    
  3. Before you can start the playback, the players have to change their states from PLAYER_STATE_IDLE to PLAYER_STATE_READY. To change the states, use the player_prepare() function:

    ret = player_prepare (player_1);
    
    ret = player_prepare (player_2);
    
    ret = player_prepare (player_3);
    
  4. Play the files:

    1. Ensure that the player states have changed to PLAYER_STATE_READY. To check the states, use the player_get_state() function. It is recommended to implement a waiting loop for each player:

      // Wait to prepare player_1
      ret = player_get_state(player_1, &state_1);
      
      while(state_1 != PLAYER_STATE_READY)
      {
         ret = player_get_state(player_1, &state_1);
      
         usleep(1000);
      }
      
      // Wait to prepare player_2
      ret = player_get_state(player_2, &state_2);
      
      while(state_2 != PLAYER_STATE_READY)
      {
         ret = player_get_state(player_2, &state_2);
      
         usleep(1000);
      }
      
      // Wait to prepare player_3
      ret = player_get_state(player_3, &state_3);
      
      while(state_3 != PLAYER_STATE_READY)
      {
         ret = player_get_state(player_3, &state_3);
      
         usleep(1000);
      }
    2. To start the playback, use the player_start() function:

      ret = player_start(player_1);
      
      ret = player_start(player_2);
      
      ret = player_start(player_3);
      
  5. To reset the players and destroy the player handles, use the player_unprepare() and player_destroy() functions, respectively:

    ret = player_unprepare(player_1);
    ret = player_destroy(player_1);
    
    ret = player_unprepare(player_2);
    ret = player_destroy(player_2);
    
    ret = player_unprepare(player_3);
    ret = player_destroy(player_3);
    

Setting Display Parameters

To set the display parameters:

  1. Create the player handle and prepare the player.
  2. Set the parameters:
    • Set the display.
      1. To play a video, set the display on which the video is rendered. Get the display handle from the window with the GET_DISPLAY() function, and set the display type.

        The display is created from the player_set_display() function called with the player handle, a player_display_type_e display type, and a player_display_h display handle.

        After successfully calling this function, the player is connected to the display handle.

        player_display_h display;
        			
        error_code = player_set_display(player, PLAYER_DISPLAY_TYPE_OVERLAY, GET_DISPLAY(evas_obj));
        dlog_print(DLOG_ERROR, LOG_TAG, "player_set_display = %d", error_code);
      2. When the source data and the display are set and the player status is PLAYER_STATE_READY, invoke the player_start() function:

        error_code = player_start(player);
        dlog_print(DLOG_ERROR, LOG_TAG, "player_start = %d", error_code);

        After a successful call of this function, the player state is set to PLAYER_STATE_PLAYING. The playback of the media contents stored in the previously specified file starts. The video file plays until the player_stop() or player_pause() function is called.

    • Set the display visibility.
      1. Before setting the visibility of the x surface video display, check that it has not already been done by using the player_is_display_visible() function:

        bool is_visible;
        
        error_code = player_is_display_visible(player, &is_visible);
        dlog_print(DLOG_ERROR, LOG_TAG, "player_is_display_visible = %d", error_code);
      2. If the is_visible variable is set to false, the visibility of the display can be set using the player_set_display_visible() function:

        if (!is_visible) 
        {
           error_code = player_set_display_visible(player, true);
           dlog_print(DLOG_ERROR, LOG_TAG, "player_set_display_visible = %d", error_code);
        }
        
    • Set the display mode.
      1. Check the possibility of using the video display mode using the player_is_display_mode_changeable() function:

        bool is_changeable;
        
        error_code = player_is_display_mode_changeable(player, &is_changeable);
        dlog_print(DLOG_ERROR, LOG_TAG, "player_is_display_mode_changeable = %d", error_code);
        
      2. If the is_changeable variable is set to true, set the display mode using the player_set_display_mode() function. The player_display_mode_e enumerator (in mobile and wearable applications) defines the available display modes.

        if (is_changeable)
        {
           error_code = player_set_display_mode(player, PLAYER_DISPLAY_MODE_FULL_SCREEN);
           dlog_print(DLOG_ERROR, LOG_TAG, "player_set_display_mode = %d", error_code);
        }
    • Set the display rotation.

      Set the display rotation using the player_set_display_rotation() function. The player_display_rotation_e enumerator (in mobile and wearable applications) defines the available display rotations.

      error_code = player_set_display_rotation(player, PLAYER_DISPLAY_ROTATION_90);
      dlog_print(DLOG_ERROR, LOG_TAG, "player_set_display_mode = %d", error_code);

Getting Stream Information

To get stream information:

  1. Create the player handle, prepare the player, and set the display.
    Note
    To get the stream information, the player state must be either PLAYER_STATE_PLAYING or PLAYER_STATE_PAUSED.
  2. Get the stream information
    • Get the video size.

      Get the width and height of the video display using the player_get_video_size() function:

      int width, height;
      
      error_code = player_get_video_size(player, &width, &height);
      dlog_print(DLOG_ERROR, LOG_TAG, "player_is_display_visible = %d", error_code);
    • Get the duration.

      Get the total media running time using the player_get_duration() function. The duration is returned in milliseconds.

      int duration;
      
      error_code = player_get_duration(player, &duration);
      dlog_print(DLOG_INFO, LOG_TAG, "player_get_duration = %d", error_code);
    • Get the video stream info.

      Get the video stream information using the player_get_video_stream_info() function. The function returns the number of frames per second and the video bit rate (in Hz).

      int fps, bit_rate;
      
      error_code = player_get_video_stream_info(player, &fps, &bit_rate);
      dlog_print(DLOG_INFO, LOG_TAG, "player_ get_video_stream_info = %d", error_code);
      
    • Get the codec info.

      Get information about the video codec using the player_get_codec_info() function:

      char *video_codec;
      
      error_code = player_get_codec_info(player, NULL, &video_codec);
      dlog_print(DLOG_INFO, LOG_TAG, "player_get_codec_info = %d", error_code);
      
    • Get the content info.

      Get information about the author, album, artist, genre, title, and year using the get_info_content() function. The values are specified by the player_content_info_e enumeration.

      char *album, *artist, *author, *genre, *title, *year;
      
      error_code = player_get_content_info(player, PLAYER_CONTENT_INFO_ALBUM, &album);
      dlog_print(DLOG_INFO, LOG_TAG, "player_get_content_info album = %d", album);
      error_code = player_get_content_info(player, PLAYER_CONTENT_INFO_ARTIST, &artist);
      dlog_print(DLOG_INFO, LOG_TAG, "player_get_content_info artist = %d", artist);
      error_code = player_get_content_info(player, PLAYER_CONTENT_INFO_AUTHOR, &author);
      dlog_print(DLOG_INFO, LOG_TAG, "player_get_content_info author = %d", author);
      error_code = player_get_content_info(player, PLAYER_CONTENT_INFO_GENRE, &genre);
      dlog_print(DLOG_INFO, LOG_TAG, "player_get_content_info genre = %d", genre);
      error_code = player_get_content_info(player, PLAYER_CONTENT_INFO_TITLE, &title);
      dlog_print(DLOG_INFO, LOG_TAG, "player_get_content_info title = %d", title);
      error_code = player_get_content_info(player, PLAYER_CONTENT_INFO_YEAR, &year);
      dlog_print(DLOG_INFO, LOG_TAG, "player_get_content_info year = %d", year);
      
      Note
      The values must be released by the free() function.
    • Get the album art.

      Get the album art using the player_get_album_art() function. It returns the encoded artwork image and size.

      void *album_art;
      int size;
      
      error_code = player_get_album_art(player, &album_art, &size);
      dlog_print(DLOG_INFO, LOG_TAG, "player_set_display_mode = %d", error_code);
      

Inserting Subtitles

To insert subtitles to a video file:

  1. Create the player handle.
  2. To set the subtitle path, use the player_set_subtitle_path() function:

    #define SUBTITLE "subtitles_test_file.srt"
    
    char *data_path = app_get_data_path();
    int path_len = strlen(data_path) + 10;
    char *path = malloc(path_len);
    strncat(path, data_path, path_len);
    strncat(path, SUBTITLE, path_len);
    
    error_code = player_set_subtitle_path(player, path);
    dlog_print(DLOG_ERROR, LOG_TAG, "player_set_subtitle_path() = %d", error_code);
    free(path);
    
    Note
    The subtitle path can be set when the player state is PLAYER_STATE_IDLE, PLAYER_STATE_READY, PLAYER_STATE_PLAYING, or PLAYER_STATE_PAUSED.

    After setting the subtitle path, set video display and prepare the player. You can play the video file as usual, by starting the player.

Go to top