[0.6.36] unrealize player if the external storage is removed 90/119190/5 accepted/tizen/3.0/common/20170320.130524 accepted/tizen/3.0/ivi/20170320.080546 accepted/tizen/3.0/mobile/20170320.075300 accepted/tizen/3.0/tv/20170320.080030 accepted/tizen/3.0/wearable/20170320.080212 submit/tizen_3.0/20170317.034449
authorEunhae Choi <eunhae1.choi@samsung.com>
Thu, 16 Mar 2017 02:46:03 +0000 (11:46 +0900)
committerEunhae Choi <eunhae1.choi@samsung.com>
Thu, 16 Mar 2017 06:51:53 +0000 (15:51 +0900)
- 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
packaging/libmm-player.spec
src/Makefile.am
src/include/mm_player.h
src/include/mm_player_priv.h
src/include/mm_player_utils.h
src/mm_player.c
src/mm_player_common_priv.c
src/mm_player_priv.c
src/mm_player_utils.c

index f9a194d..c645915 100644 (file)
@@ -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)
index 11aed47..7be12bd 100644 (file)
@@ -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.
index 2745741..06e8f47 100644 (file)
@@ -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
index a35b5ef..787b42d 100644 (file)
@@ -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);
+
+/**
        @}
  */
 
index 284a151..e4996b9 100644 (file)
@@ -37,6 +37,7 @@
 #include <stdlib.h>
 #include <stdio.h>
 #include <tbm_bufmgr.h>
+#include <storage.h>
 #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);
index 099986f..9176954 100644 (file)
@@ -30,6 +30,7 @@
 #include <mm_types.h>
 #include <mm_error.h>
 #include <mm_message.h>
+#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
        }
index 0ef1b83..dcac88c 100644 (file)
@@ -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;
+}
index 0619d85..a871bff 100644 (file)
@@ -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:
index bc7bd18..63a78c5 100644 (file)
@@ -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; i<MMPLAYER_PATH_MAX; i++) {
+
+               if (path_type == MMPLAYER_PATH_MAX || path_type == i) {
+                       player->storage_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;
+}
+
index 99fdab7..6e72720 100644 (file)
 #include <arpa/inet.h>
 #include <unicode/ucsdet.h>
 #include <dlog.h>
-
+#include <storage.h>
+#include <tzplatform_config.h>
 #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;
+}