From 6a3c521c93e5f7f3bd4eafb8b16b99090f060913 Mon Sep 17 00:00:00 2001 From: Eunhae Choi Date: Thu, 16 Mar 2017 11:46:03 +0900 Subject: [PATCH] [0.6.36] unrealize player if the external storage is removed - unrealize the player to release external storage resource - ignore the internal error posting when the storage is removed (to avoid duplicated posting) - to check the storage state, storage_info is added. Change-Id: I1494cf8e29fbcc73e53b4dc28252b7a0e96db6ce --- configure.ac | 8 +++++ packaging/libmm-player.spec | 4 ++- src/Makefile.am | 6 +++- src/include/mm_player.h | 5 +++ src/include/mm_player_priv.h | 17 +++++++++- src/include/mm_player_utils.h | 2 ++ src/mm_player.c | 15 +++++++++ src/mm_player_common_priv.c | 32 ++++++++++++++++-- src/mm_player_priv.c | 78 +++++++++++++++++++++++++++++++++++++++++-- src/mm_player_utils.c | 47 +++++++++++++++++++++++++- 10 files changed, 205 insertions(+), 9 deletions(-) diff --git a/configure.ac b/configure.ac index f9a194d..c645915 100644 --- a/configure.ac +++ b/configure.ac @@ -84,6 +84,14 @@ PKG_CHECK_MODULES(GST_APP, gstreamer-app-1.0 >= 1.2.0) AC_SUBST(GST_APP_CFLAGS) AC_SUBST(GST_APP_LIBS) +PKG_CHECK_MODULES(STORAGE, storage) +AC_SUBST(STORAGE_CFLAGS) +AC_SUBST(STORAGE_LIBS) + +PKG_CHECK_MODULES(TZPLATFORM_CONFIG, libtzplatform-config) +AC_SUBST(TZPLATFORM_CONFIG_CFLAGS) +AC_SUBST(TZPLATFORM_CONFIG_LIBS) + PKG_CHECK_MODULES(APPFWK, appcore-efl) AC_SUBST(APPFWK_CFLAGS) AC_SUBST(APPFWK_LIBS) diff --git a/packaging/libmm-player.spec b/packaging/libmm-player.spec index 11aed47..7be12bd 100644 --- a/packaging/libmm-player.spec +++ b/packaging/libmm-player.spec @@ -1,6 +1,6 @@ Name: libmm-player Summary: Multimedia Framework Player Library -Version: 0.6.35 +Version: 0.6.36 Release: 0 Group: Multimedia/Libraries License: Apache-2.0 @@ -26,6 +26,8 @@ BuildRequires: pkgconfig(icu-i18n) BuildRequires: pkgconfig(capi-media-tool) BuildRequires: pkgconfig(murphy-resource) BuildRequires: pkgconfig(murphy-glib) +BuildRequires: pkgconfig(storage) +BuildRequires: pkgconfig(libtzplatform-config) %description Multimedia Framework Player Library files. diff --git a/src/Makefile.am b/src/Makefile.am index 2745741..06e8f47 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -37,6 +37,8 @@ libmmfplayer_la_CFLAGS = -I$(srcdir)/include \ $(MEDIAPACKET_CFLAGS) \ $(DLOG_CFLAGS) \ $(ECORE_CFLAGS) \ + $(STORAGE_CFLAGS) \ + $(TZPLATFORM_CONFIG_CFLAGS) \ -Werror -Wno-deprecated -Wno-deprecated-declarations -Wno-cpp noinst_HEADERS = include/mm_player_utils.h \ @@ -66,7 +68,9 @@ libmmfplayer_la_LIBADD = $(GST_LIBS) \ $(MEDIAPACKET_LIBS) \ $(DLOG_LIBS) \ $(UTILX_LIBS) \ - $(ECORE_LIBS) + $(ECORE_LIBS) \ + $(STORAGE_LIBS) \ + $(TZPLATFORM_CONFIG_LIBS) if IS_SDK diff --git a/src/include/mm_player.h b/src/include/mm_player.h index a35b5ef..787b42d 100644 --- a/src/include/mm_player.h +++ b/src/include/mm_player.h @@ -2338,6 +2338,11 @@ int mm_player_set_file_buffering_path(MMHandleType player, const char *file_path int mm_player_set_sound_stream_info(MMHandleType player, char *stream_type, int stream_index); /** + * This function is to manage the playback according to the external storage state + */ +int mm_player_manage_external_storage_state(MMHandleType player, int state); + +/** @} */ diff --git a/src/include/mm_player_priv.h b/src/include/mm_player_priv.h index 284a151..e4996b9 100644 --- a/src/include/mm_player_priv.h +++ b/src/include/mm_player_priv.h @@ -37,6 +37,7 @@ #include #include #include +#include #include "mm_player.h" #include "mm_player_internal.h" #include "mm_player_audioeffect.h" @@ -327,6 +328,12 @@ enum StreamingSrcError { MMPLAYER_STREAMING_ERROR_OPTION_NOT_SUPPORTED, }; +typedef enum { + MMPLAYER_PATH_VOD = 0, + MMPLAYER_PATH_TEXT, + MMPLAYER_PATH_MAX +} MMPlayerPathType; + /*--------------------------------------------------------------------------- | GLOBAL DATA TYPE DEFINITIONS: | ---------------------------------------------------------------------------*/ @@ -367,6 +374,12 @@ typedef struct { } MMPlayerParseProfile; typedef struct { + storage_type_e type; + storage_state_e state; + int id; +} MMPlayerStorageInfo; + +typedef struct { bool is_pending; MMPlayerPosFormatType format; unsigned long pos; @@ -568,6 +581,7 @@ typedef struct { /* content profile */ MMPlayerParseProfile profile; + MMPlayerStorageInfo storage_info[MMPLAYER_PATH_MAX]; /* streaming service type */ MMStreamingType streaming_type; @@ -845,6 +859,7 @@ void _mm_player_media_packet_video_stream_internal_buffer_unref(void *buffer); int _mmplayer_set_pcm_spec(MMHandleType hplayer, int samplerate, int channel); int _mmplayer_get_timeout(MMHandleType hplayer, int *timeout); int _mmplayer_get_num_of_video_out_buffers(MMHandleType hplayer, int *num, int *extra_num); +int _mmplayer_manage_external_storage_state(MMHandleType hplayer, int state); int __mmplayer_gst_set_state(mm_player_t* player, GstElement * pipeline, GstState state, gboolean async, gint timeout); int __mmplayer_set_state(mm_player_t* player, int state); int __mmplayer_check_state(mm_player_t* player, enum PlayerCommandState command); @@ -867,7 +882,7 @@ gboolean __mmplayer_check_useful_message(mm_player_t *player, GstMessage * messa gboolean __mmplayer_handle_gst_error(mm_player_t* player, GstMessage * message, GError* error); gint __gst_handle_core_error(mm_player_t* player, int code); gint __gst_handle_library_error(mm_player_t* player, int code); -gint __gst_handle_resource_error(mm_player_t* player, int code); +gint __gst_handle_resource_error(mm_player_t* player, int code, GstMessage * message); gint __gst_handle_stream_error(mm_player_t* player, GError* error, GstMessage * message); int _mmplayer_sound_register_with_pid(MMHandleType hplayer, int pid); int _mmplayer_get_client_pid(MMHandleType hplayer, int* pid); diff --git a/src/include/mm_player_utils.h b/src/include/mm_player_utils.h index 099986f..9176954 100644 --- a/src/include/mm_player_utils.h +++ b/src/include/mm_player_utils.h @@ -30,6 +30,7 @@ #include #include #include +#include "mm_player_priv.h" #ifdef __cplusplus extern "C" { @@ -293,6 +294,7 @@ char** util_get_cookie_list(const char *cookies); bool util_check_valid_url(const char *proxy); const char* util_get_charset(const char *file_path); int util_get_pixtype(unsigned int fourcc); +bool util_get_storage_info(const char *path, MMPlayerStorageInfo *storage_info); #ifdef __cplusplus } diff --git a/src/mm_player.c b/src/mm_player.c index 0ef1b83..dcac88c 100644 --- a/src/mm_player.c +++ b/src/mm_player.c @@ -1323,3 +1323,18 @@ int mm_player_set_sound_stream_info(MMHandleType player, char *stream_type, int return result; } + +int mm_player_manage_external_storage_state(MMHandleType player, int state) +{ + int result = MM_ERROR_NONE; + + MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED); + + MMPLAYER_CMD_LOCK( player ); + + result = _mmplayer_manage_external_storage_state(player, state); + + MMPLAYER_CMD_UNLOCK( player ); + + return result; +} diff --git a/src/mm_player_common_priv.c b/src/mm_player_common_priv.c index 0619d85..a871bff 100644 --- a/src/mm_player_common_priv.c +++ b/src/mm_player_common_priv.c @@ -584,7 +584,7 @@ __mmplayer_handle_gst_error(mm_player_t* player, GstMessage * message, GError* e } else if (error->domain == GST_LIBRARY_ERROR) { msg_param.code = __gst_handle_library_error(player, error->code); } else if (error->domain == GST_RESOURCE_ERROR) { - msg_param.code = __gst_handle_resource_error(player, error->code); + msg_param.code = __gst_handle_resource_error(player, error->code, message); } else if (error->domain == GST_STREAM_ERROR) { msg_param.code = __gst_handle_stream_error(player, error, message); } else { @@ -607,6 +607,17 @@ __mmplayer_handle_gst_error(mm_player_t* player, GstMessage * message, GError* e if (msg_param.code == MM_ERROR_NONE) return TRUE; + /* skip error to avoid duplicated posting */ + if ((player->storage_info[MMPLAYER_PATH_VOD].state <= STORAGE_STATE_REMOVED) || + (player->storage_info[MMPLAYER_PATH_TEXT].state <= STORAGE_STATE_REMOVED)) { + + /* The error will be handled by mused. + * @ref _mmplayer_manage_external_storage_state() */ + + LOGW("storage is removed, skip error post"); + return TRUE; + } + /* post error to application */ if (!player->msg_posted) { MMPLAYER_POST_MSG(player, MM_MESSAGE_ERROR, &msg_param); @@ -682,7 +693,7 @@ __gst_handle_library_error(mm_player_t* player, int code) } gint -__gst_handle_resource_error(mm_player_t* player, int code) +__gst_handle_resource_error(mm_player_t* player, int code, GstMessage * message) { gint trans_err = MM_ERROR_NONE; @@ -706,7 +717,22 @@ __gst_handle_resource_error(mm_player_t* player, int code) || MMPLAYER_IS_RTSP_STREAMING(player)) { trans_err = MM_ERROR_PLAYER_STREAMING_FAIL; break; - } + } else if (message != NULL && message->src != NULL) { + storage_state_e storage_state = STORAGE_STATE_UNMOUNTABLE; + MMPlayerPathType path_type = MMPLAYER_PATH_MAX; + + if (message->src == (GstObject *)player->pipeline->mainbin[MMPLAYER_M_SRC].gst) + path_type = MMPLAYER_PATH_VOD; + else if (message->src == (GstObject *)player->pipeline->mainbin[MMPLAYER_M_SUBSRC].gst) + path_type = MMPLAYER_PATH_TEXT; + + if (path_type != MMPLAYER_PATH_MAX && player->storage_info[path_type].type == STORAGE_TYPE_EXTERNAL) { + /* check storage state */ + storage_get_state(player->storage_info[path_type].id, &storage_state); + player->storage_info[path_type].state = storage_state; + LOGW("path %d, storage state %d", path_type, storage_state); + } + } /* fall through */ case GST_RESOURCE_ERROR_WRITE: case GST_RESOURCE_ERROR_FAILED: case GST_RESOURCE_ERROR_SEEK: diff --git a/src/mm_player_priv.c b/src/mm_player_priv.c index bc7bd18..63a78c5 100644 --- a/src/mm_player_priv.c +++ b/src/mm_player_priv.c @@ -273,6 +273,7 @@ static gboolean __gst_seek_subtitle_data(GstElement * appsrc, guint64 position, static void __mmplayer_gst_caps_notify_cb(GstPad * pad, GParamSpec * unused, gpointer data); static void __mmplayer_audio_stream_clear_buffer(mm_player_t* player, gboolean send_all); static void __mmplayer_audio_stream_send_data(mm_player_t* player, mm_player_audio_stream_buff_t *a_buffer); +static void __mmplayer_initialize_storage_info(mm_player_t* player, MMPlayerPathType path_type); /*=========================================================================================== | | @@ -5811,6 +5812,9 @@ __mmplayer_gst_create_subtitle_src(mm_player_t* player) gst_object_unref(pad); pad = NULL; + if (!util_get_storage_info(subtitle_uri, &player->storage_info[MMPLAYER_PATH_TEXT])) + LOGE("failed to get storage info of subtitle path"); + /* create dot. for debugging */ MMPLAYER_GENERATE_DOT_IF_ENABLED(player, "pipeline-with-subtitle"); MMPLAYER_FLEAVE(); @@ -6242,6 +6246,7 @@ __mmplayer_gst_create_pipeline(mm_player_t* player) // @ player->last_multiwin_status = FALSE; _mmplayer_track_initialize(player); + __mmplayer_initialize_storage_info(player, MMPLAYER_PATH_MAX); /* create source element */ switch (player->profile.uri_type) { @@ -6378,6 +6383,8 @@ __mmplayer_gst_create_pipeline(mm_player_t* player) // @ g_object_get(element, "location", &location, NULL); LOGD("PD_LOCATION [%s].\n", location); + if (!util_get_storage_info(location, &player->storage_info[MMPLAYER_PATH_VOD])) + LOGE("failed to get storage info"); if (location) g_free(location); } @@ -6398,7 +6405,8 @@ __mmplayer_gst_create_pipeline(mm_player_t* player) // @ } g_object_set(G_OBJECT(element), "location", (player->profile.uri)+7, NULL); /* uri+7 -> remove "file:// */ - //g_object_set(G_OBJECT(element), "use-mmap", TRUE, NULL); + if (!util_get_storage_info(player->profile.uri, &player->storage_info[MMPLAYER_PATH_VOD])) + LOGE("failed to get storage info"); } break; @@ -7352,7 +7360,7 @@ int __gst_pause(mm_player_t* player, gboolean async) // @ if (error->domain == GST_STREAM_ERROR) ret = __gst_handle_stream_error(player, error, msg); else if (error->domain == GST_RESOURCE_ERROR) - ret = __gst_handle_resource_error(player, error->code); + ret = __gst_handle_resource_error(player, error->code, NULL); else if (error->domain == GST_LIBRARY_ERROR) ret = __gst_handle_library_error(player, error->code); else if (error->domain == GST_CORE_ERROR) @@ -11131,6 +11139,7 @@ __mmplayer_initialize_next_play(mm_player_t *player) player->total_maximum_bitrate = 0; _mmplayer_track_initialize(player); + __mmplayer_initialize_storage_info(player, MMPLAYER_PATH_MAX); for (i = 0; i < MM_PLAYER_STREAM_COUNT_MAX; i++) { player->bitrate[i] = 0; @@ -11231,6 +11240,8 @@ __mmplayer_activate_next_source(mm_player_t *player, GstState target) } g_object_set(G_OBJECT(element), "location", (player->profile.uri)+7, NULL); /* uri+7 -> remove "file:// */ + if (!util_get_storage_info(player->profile.uri, &player->storage_info[MMPLAYER_PATH_VOD])) + LOGE("failed to get storage info"); break; } case MM_PLAYER_URI_TYPE_URL_HTTP: @@ -12303,6 +12314,7 @@ __mmplayer_release_misc_post(mm_player_t* player) /* clear the video stream bo list */ __mmplayer_video_stream_destroy_bo_list(player); + __mmplayer_initialize_storage_info(player, MMPLAYER_PATH_MAX); player->uri_info.uri_idx = 0; MMPLAYER_FLEAVE(); @@ -14233,8 +14245,13 @@ __mmplayer_change_external_subtitle_language(mm_player_t* player, const char* fi goto EXIT; } + __mmplayer_initialize_storage_info(player, MMPLAYER_PATH_TEXT); + g_object_set(G_OBJECT(mainbin[MMPLAYER_M_SUBSRC].gst), "location", filepath, NULL); + if (!util_get_storage_info(filepath, &player->storage_info[MMPLAYER_PATH_TEXT])) + LOGE("failed to get storage info of subtitle path"); + charset = util_get_charset(filepath); if (charset) { LOGD("detected charset is %s\n", charset); @@ -15095,3 +15112,60 @@ int _mmplayer_get_num_of_video_out_buffers(MMHandleType hplayer, int *num, int * return MM_ERROR_NONE; } +static void +__mmplayer_initialize_storage_info(mm_player_t* player, MMPlayerPathType path_type) +{ + int i = 0; + MMPLAYER_FENTER(); + MMPLAYER_RETURN_IF_FAIL(player); + + for (i=0; istorage_info[i].type = STORAGE_TYPE_INTERNAL; + player->storage_info[i].state = STORAGE_STATE_MOUNTED; + player->storage_info[i].id = -1; + + if (path_type != MMPLAYER_PATH_MAX) + break; + } + } + + MMPLAYER_FLEAVE(); +} + +int _mmplayer_manage_external_storage_state(MMHandleType hplayer, int state) +{ + int ret = MM_ERROR_NONE; + mm_player_t* player = (mm_player_t*) hplayer; + MMMessageParamType msg_param = {0, }; + + MMPLAYER_FENTER(); + MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED); + + LOGD("storage state : %d", state); + + if (state != STORAGE_STATE_UNMOUNTABLE && state != STORAGE_STATE_REMOVED) + return MM_ERROR_NONE; + + if ((player->storage_info[MMPLAYER_PATH_VOD].type == STORAGE_TYPE_EXTERNAL) || + (player->storage_info[MMPLAYER_PATH_TEXT].type == STORAGE_TYPE_EXTERNAL)) { + LOGW("external storage is removed."); + + if (player->msg_posted == FALSE) { + memset(&msg_param, 0, sizeof(MMMessageParamType)); + msg_param.code = MM_ERROR_PLAYER_INVALID_URI; + MMPLAYER_POST_MSG(player, MM_MESSAGE_ERROR, &msg_param); + player->msg_posted = TRUE; + } + + /* unrealize the player */ + ret = _mmplayer_unrealize(hplayer); + if (ret != MM_ERROR_NONE) + LOGE("failed to unrealize"); + } + + MMPLAYER_FLEAVE(); + return ret; +} + diff --git a/src/mm_player_utils.c b/src/mm_player_utils.c index 99fdab7..6e72720 100644 --- a/src/mm_player_utils.c +++ b/src/mm_player_utils.c @@ -30,9 +30,12 @@ #include #include #include - +#include +#include #include "mm_player_utils.h" +#define MEDIA_PATH_EXTERNAL tzplatform_getenv(TZ_SYS_STORAGE) /* external storage */ + int util_exist_file_path(const char *file_path) { int fd = 0; @@ -461,3 +464,45 @@ int util_get_pixtype(unsigned int fourcc) return pixtype; } + +static int _util_storage_supported_cb(int storage_id, storage_type_e type, + storage_state_e state, const char *path, void *user_data) +{ + MMPlayerStorageInfo *storage_info = (MMPlayerStorageInfo *)user_data; + + MMPLAYER_RETURN_VAL_IF_FAIL(storage_info, FALSE); + + if (type == storage_info->type && state >= STORAGE_STATE_MOUNTED) { + storage_info->id = storage_id; + storage_info->state = state; + return FALSE; + } + + return TRUE; +} + +bool util_get_storage_info(const char *path, MMPlayerStorageInfo *storage_info) +{ + int ret = 0; + const char *file_path = path; + + MMPLAYER_RETURN_VAL_IF_FAIL(file_path && storage_info, false); + + if (strncmp(file_path, "file://", strlen("file://")) == 0) + file_path = path+7; /* remove file prefix */ + + if (strncmp(file_path, MEDIA_PATH_EXTERNAL, strlen(MEDIA_PATH_EXTERNAL)) == 0) + storage_info->type = STORAGE_TYPE_EXTERNAL; + else + storage_info->type = STORAGE_TYPE_INTERNAL; + + ret = storage_foreach_device_supported((storage_device_supported_cb)_util_storage_supported_cb, storage_info); + if (ret != STORAGE_ERROR_NONE) { + LOGE("storage_foreach_device_supported failed 0x%x", ret); + return false; + } + + LOGD("storage info: type %d, id %d", storage_info->type, storage_info->id); + + return true; +} -- 2.7.4