Metadata Extractor: Extracting Metadata from an Input Media File
This tutorial demonstrates how you can extract metadata from media files.
Warm-up
Become familiar with the Metadata Extractor API basics by learning about:
-
Initializing the Metadata Extractor
Initialize the metadata extractor for use.
-
Getting Metadata, Artwork, and Frame
Create a metadata extractor handle, bind the handle with the file, and get metadata, artwork, lyrics, and frames.
Initializing the Metadata Extractor
Note |
---|
The metadata extractor can only be used with video and audio files. It is not supported in the image files. |
To initialize the metadata extractor:
-
To use the functions and data types of the Metadata Extractor API (in mobile and wearable applications), include the <metadata_extractor.h> header file in your application:
#include <metadata_extractor.h>
-
To work with the Metadata Extractor API, create a handle to the metadata extractor. A global variable is used in this tutorial:
static metadata_extractor_h g_metadata_h = NULL;
-
Files must contain metadata in order for the Metadata Extractor API functions to work. This tutorial uses 2 files - an audio file in the mp3 format and a video file in the mp4 format.
You must get the default path for this tutorial. For the following example code, you must include the <storage.h> header file.
int internal_storage_id; char *internal_music_storage_path; char *internal_video_storage_path; char *music_file_name = "test_music.mp3"; char *video_file_name = "test_video.mp4"; char *music_test_path; char *video_test_path; 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_internal_storage_path() { int error; char *path = NULL; error = storage_foreach_device_supported(storage_cb, NULL); error = storage_get_directory(internal_storage_id, STORAGE_DIRECTORY_MUSIC, &path); if (error != STORAGE_ERROR_NONE) { internal_music_storage_path = strdup(path); free(path); } error = storage_get_directory(internal_storage_id, STORAGE_DIRECTORY_VIDEOS, &path); if (error != STORAGE_ERROR_NONE) { internal_video_storage_path = strdup(path); free(path); } } void _make_test_path() { int path_len = 0; path_len = strlen(internal_music_storage_path) + strlen(music_file_name) + 1; music_test_path = malloc(path_len); memset(music_test_path, 0x0, path_len); strncat(music_test_path, internal_music_storage_path, strlen(internal_music_storage_path)); strncat(music_test_path, music_file_name, strlen(music_file_name)); path_len = strlen(internal_video_storage_path) + strlen(video_file_name) + 1; video_test_path = malloc(path_len); memset(video_test_path, 0x0, path_len); strncat(video_test_path, internal_video_storage_path, strlen(internal_video_storage_path)); strncat(video_test_path, video_file_name, strlen(video_file_name)); }
The metadata extractor APIs can use not only common content in the storage (internal or external), but also the private content in your application data.
Getting Metadata, Artwork, and Frame
To get metadata from the file:
- Create the metadata extractor handle.
Use the metadata_extractor_create() function. This is necessary to prepare the metadata extractor handle for work.
ret = metadata_extractor_create(&g_metadata_h);
- Set the path to the file whose data you want to obtain.
Use the metadata_extractor_set_path() function. It binds the handle with the media file specified in the video_test_path, passed as a second argument to this function.
ret = metadata_extractor_set_path(g_metadata_h, video_test_path); // Or ret = metadata_extractor_set_path(g_metadata_h, music_test_path);
- Get metadata from the file.
Use the metadata_extractor_get_metadata() function, which takes 3 parameters. The first one is the handle to the metadata extractor. The second parameter is the wanted data type. The possible values for this parameter are those defined in the metadata_extractor_attr_e enumeration (in mobile and wearable applications). In this tutorial all the possible data from the file is extracted, so a function with all possible attribute types is needed. The value read from the file is stored in the final parameter, which is a pointer to the char variable and is fulfilled by the function.
char *value = NULL; ret = metadata_extractor_get_metadata(g_metadata_h, METADATA_DURATION, &value); dlog_print(DLOG_DEBUG, LOG_TAG, "METADATA_DURATION: %s\n", value); if (value != NULL) { free(value); value = NULL; }
After calling the function, check whether the value returned by the function is equal to METADATA_EXTRACTOR_ERROR_NONE. If it is not, an error occurred. Otherwise, the function got the requested data successfully and its value is stored in the value variable. The obtained value is printed to the screen. When the work with the obtained value is finished, release it using the free() function.
The other types of metadata attributes can be obtained in the exactly same way. Just change the second parameter during calling the function to get different attributes of the metadata.
- Get the artwork of the file (in case of music content).
Use the metadata_extractor_get_artwork() function.
This function takes 4 parameters. The first one is the handle to the metadata extractor. Other parameters are [out] – type parameters, so their values are fulfilled by the function. The first of them, the artwork variable, is fulfilled with the encoded artwork image, the artwork_size variable stores the size of the encoded artwork, and the artwork_mime variable contains the mime type of the artwork. The obtained values are merely printed. Afterwards, release the memory allocated for the artwork and artwork_mime variables to avoid memory leaks.
int artwork_size = 0; void *artwork = NULL; char *artwork_mime = NULL; ret = metadata_extractor_get_artwork(g_metadata_h, &artwork, &artwork_size, &artwork_mime); dlog_print(DLOG_DEBUG, LOG_TAG, "Artwork: size: %d, mime type: %s\n", artwork_size, artwork_mime); if (artwork != NULL) { free(artwork); artwork = NULL; } if (artwork_mime != NULL) { free(artwork_mime); artwork_mime = NULL; }
- Get synchronized lyrics from the file (in case of music content).
Use the metadata_extractor_get_synclyrics() function. It takes the following parameters:
- Handle to the metadata extractor
- Index of the time/lyrics set
- Time information of the index
- Lyrics of the index
The last 2 parameters are of the type [out].
unsigned long time_info = 0; char *lyrics = NULL; ret = metadata_extractor_get_synclyrics(g_metadata_h, 1, &time_info, &lyrics); if (lyrics != NULL) { dlog_print(DLOG_DEBUG, LOG_TAG, "Synclyrics: time_info: %d, lyrics: %s\n", time_info, lyrics); free(lyrics); lyrics = NULL; }
If the function returns METADATA_EXTRACTOR_ERROR_NONE, no errors occurred and the time information and lyrics were correctly fulfilled by the function. Only their values are printed. Free the memory allocated for the lyrics to avoid memory leaks.
- Get frames from video files.
Use the following functions. The metadata_extractor_get_frame() function gets the frame of a video media file without specifying the time when the frame appears. The metadata_extractor_get_frame_at_time() function takes a timestamp as one of the parameters. This parameter defines when a specific frame appears in the video file.
// Use metadata_extractor_get_frame() int frame_size = 0; void *frame = NULL; ret = metadata_extractor_get_frame(g_metadata_h, &frame, &frame_size); dlog_print(DLOG_DEBUG, LOG_TAG, "Frame: size: %d\n", frame_size); if (frame != NULL) { free(frame); frame = NULL; } // Use metadata_extractor_get_frame_at_time() unsigned long timestamp = 500; ret = metadata_extractor_get_frame_at_time(g_metadata_h, timestamp, true, &frame, &frame_size); dlog_print(DLOG_DEBUG, LOG_TAG, "Frame at %d: size: %d\n", timestamp, frame_size); if (frame != NULL) { free(frame); frame = NULL; }
Both functions take the handle to the metadata extractor as their first parameter. They also take the frame and frame_size variables to fulfill them. The difference is that the second function takes 2 more parameters. The first one was described above. It defines the timestamp from the beginning of the movie to the wanted frame. The second additional parameter is a Boolean value defining whether the user can get an accurate frame (if the value is true) or only the nearest i-frame.
To check whether the functions are executed successfully, check the value returned by them. If it is METADATA_EXTRACTOR_ERROR_NONE, no errors occurred and the frame has been successfully stored in the frame variable.
Release the memory allocated for the frame by calling the free() function.
- Clean up on the application end.
metadata_extractor_destroy(g_metadata_h);