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 for use:

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

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

    In this tutorial, you also need the <Elementary.h> and <glib.h> header files to set the display and use the Glib library functions.

  2. Retrieve the default internal storage paths for audio and video files, and define the specific paths for the audio and video files to play. To access and use internal storage, include the storage.h header file in your application.

    #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. Define a variable for the player handle, and create the handle by passing the variable to the player_create() function. You need the handle for defining which file to play and with what playback settings. The following example code also creates buttons for the UI to control the playback.

    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");
       }
       // Perform more playback configuration, such as setting callbacks,
       // setting the source file URI, and preparing the player
    }
    
    static void
    create_base_gui(appdata_s *ad)
    {
       // Create a window
       // Create a button
       // Add a callback to the 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, register the appropriate callbacks:

    • To receive notifications about playback interruptions, register a callback function using the player_set_interrupted_cb() 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 (for example, button)
      }
      
      static void
      init_base_player(appdata_s *ad)
      {
         // Set an interruption callback if the application wants to know the reason
         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");
      }
      

      The playback is interrupted and the callback triggered when, for example, 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.

    • To receive a notification when the playback ends, 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 when the playback ends
         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");
      }
      
    • To receive notifications about player errors during playback, register a callback function using the player_set_error_cb() function:

      static void
      _player_error_cb(int error_code, void *user_data)
      {
         dlog_print(DLOG_ERROR, LOG_TAG, "playback failed, error = %x", error_code);
      }
      
      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 player error callback is triggered when the player stops working due to an error. You can use the callback to try to recover from the error. For example, try to change the player state to PLAYER_STATE_READY by calling the player_stop() function. Then remove all other callbacks and reset 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.

      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. After creating the player handle, specify the audio file to play using the player_set_uri() function:

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

    error_code = player_prepare(ad->player);
    

    The function changes the player state from PLAYER_STATE_IDLE to PLAYER_STATE_READY, which is required to start playback.

  3. Start playing the audio file using the player_start() function:

    error_code = player_start(ad->player);
    

    The function changes the player state from PLAYER_STATE_READY to PLAYER_STATE_PLAYING. The audio file plays until you call the player_stop() or player_pause() function.

Playing a Video File

To play a video file:

  1. After creating the player handle, specify the video file to play using 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 retrieve the correct display handle, use the GET_DISPLAY() function. To set the display, use the player_set_display() function with the player handle, display type (a player_display_type_e enumerator in mobile and wearable applications), and display handle:

    error_code = player_set_display(g_player, PLAYER_DISPLAY_TYPE_OVERLAY, GET_DISPLAY(evas_obj));
    

    After the player_set_display() function has been successfully executed, the player is connected to the display.

    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 using the player_prepare() function:

    error_code = player_prepare(ad->player);
    

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

    error_code = player_prepare_async(ad->player, _prepared_cb, ad);
    

    Both functions change the player state from PLAYER_STATE_IDLE to PLAYER_STATE_READY, which is required to start playback.

  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 in a waiting loop:

      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);
      
    2. Start playing the video file using the player_start() function:

      if (error_code == PLAYER_ERROR_NONE)
      {
         error_code = player_start(g_player);
      }
      

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

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

      The player_start() function changes the player state from PLAYER_STATE_READY to PLAYER_STATE_PLAYING. The video file plays until you call the player_stop() or player_pause() function.

Stopping the Player and Releasing Resources

To stop the player and release the resources allocated to the player:

  1. Stop the player using the player_stop() function:

    error_code = player_stop(player);
    dlog_print(DLOG_ERROR, LOG_TAG, "player_stop() = %d", error_code);
    
  2. Reset the player using the player_unprepare() function:

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

    After the player is reset, it is in the PLAYER_STATE_IDLE state.

  3. 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 Multiple Players

To initialize multiple players for use:

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

    #include <player.h>
    #include <stdio.h>
    #include <unistd.h>
    

    In this tutorial, you also need the <stdio.h> and <unistd.h> header files to use standard file input and output functions and system calls.

    To ensure that a Player function has been executed properly, make sure that the return value is equal to PLAYER_ERROR_NONE.

  2. Define 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;
    

Playing Multiple Files Simultaneously

To play multiple files simultaneously:

  1. 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. Specify the files to play using 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. Prepare the players for playback using the player_prepare() function:

    ret = player_prepare(player_1);
    
    ret = player_prepare(player_2);
    
    ret = player_prepare(player_3);
    

    The function changes the player states from PLAYER_STATE_IDLE to PLAYER_STATE_READY, which is required to start playback.

  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 in a waiting loop:

      // 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. Start playing the files using the player_start() function:

      ret = player_start(player_1);
      
      ret = player_start(player_2);
      
      ret = player_start(player_3);
      
  5. After the playback has ended or been stopped, reset the players and destroy the player handles using the player_unprepare() and player_destroy() functions:

    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);
    

Configuring the Video Playback Display

To set the display parameters for playing a video file:

  1. Make sure that the player handle has been created, the display set, and the player prepared and started.

  2. During playback, you can manage the display settings as needed:

    • Make the display visible:

      1. Check whether the display is already visible 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 display is not visible, make it visible using the player_set_display_visible() function with the second parameter set to true:

        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 using the player_set_display_mode() function:

      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);
      

      The available display modes are defined in the player_display_mode_e enumeration (in mobile and wearable applications).

    • Set the display rotation using the player_set_display_rotation() function:

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

      The available display rotations are defined in the player_display_rotation_e enumeration (in mobile and wearable applications).

Retrieving Stream Information

To retrieve information about the audio and video streams:

  1. Create the player handle, prepare and start the player, and set the display parameters.

    Note
    To retrieve the stream information, the player state must be either PLAYER_STATE_PLAYING or PLAYER_STATE_PAUSED.
  2. Retrieve the stream information:

    • Video display size

      Retrieve 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);
      
    • Duration

      Retrieve the total media running time (in milliseconds) using the player_get_duration() function:

      int duration;
      
      error_code = player_get_duration(player, &duration);
      dlog_print(DLOG_INFO, LOG_TAG, "player_get_duration = %d", error_code);
      
    • Audio stream details

      Retrieve the audio stream details using the player_get_audio_stream_info() function. The function returns the audio sample rate (in Hz), number of audio channels (1 for mono or 2 for stereo), and audio bit rate (in Hz).

      int sample_rate, channels, bit_rate;
      
      error_code = player_get_audio_stream_info(player, &sample_rate, &channels, &bit_rate);
      dlog_print(DLOG_INFO, LOG_TAG, "player_get_audio_stream_info = %d", error_code);
      
    • Video stream details

      Retrieve the video stream details 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);
      
    • Audio and video codec names

      Retrieve the audio and video codec names using the player_get_codec_info() function:

      char *audio_codec;
      char *video_codec;
      
      error_code = player_get_codec_info(player, &audio_codec, &video_codec);
      dlog_print(DLOG_INFO, LOG_TAG, "player_get_codec_info = %d", error_code);
      
    • Content metadata

      Retrieve information about the album, artist, author, genre, title, and year using the player_get_content_info() function. The available metadata attributes are defined in the player_content_info_e enumeration (in mobile and wearable applications).

      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 using the free() function.
    • Album artwork

      Retrieve the album artwork using the player_get_album_art() function. The function 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. Set the subtitle path using 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
    You can set the subtitle path when the player state is PLAYER_STATE_IDLE, PLAYER_STATE_READY, PLAYER_STATE_PLAYING, or PLAYER_STATE_PAUSED.
Go to top