source code refactoring 57/119557/4
authorHyunil <hyunil46.park@samsung.com>
Fri, 17 Mar 2017 08:37:45 +0000 (17:37 +0900)
committerHyunil <hyunil46.park@samsung.com>
Tue, 21 Mar 2017 06:36:34 +0000 (15:36 +0900)
Change-Id: I3f586b69151b43372179221af5d2cf4d7d87f04e
Signed-off-by: Hyunil <hyunil46.park@samsung.com>
packaging/libmm-evas-renderer.spec
src/include/mm_evas_renderer.h
src/mm_evas_renderer.c

index 988db1ae49d9be93b543da46306a9c0d8865236b..905b396079bcfa8c71e509a2b2b7a54f5a825df8 100644 (file)
@@ -1,6 +1,6 @@
 Name:       libmm-evas-renderer
 Summary:    Multimedia Framework Evas Renderer Library
-Version:    0.0.16
+Version:    0.0.17
 Release:    0
 Group:      Multimedia/Libraries
 License:    Apache-2.0
index dce73225b7ea7eba5122eb5e35c80c916fc8c717..f5ce85aa1a643214616bac0627a540af45258f75 100644 (file)
@@ -61,13 +61,21 @@ extern "C" {
 typedef enum {
        UPDATE_VISIBILITY,
        UPDATE_TBM_SURF,
-       UPDATE_FLUSH_BUFFER
+       UPDATE_FLUSH_BUFFER,
+       UPDATE_DESTROY,
+       UPDATE_INFO_NUM
 } update_info;
 
+enum {
+       COND_RETRIEVE,
+       COND_DESTROY,
+       COND_NUM
+};
+
 typedef struct {
        media_packet_h packet;
        tbm_surface_h tbm_surf;
-       gint prev; /* keep previous index for destroying remained packets */
+       gint prev_idx; /* keep previous index for destroying remained packets */
 } packet_info;
 
 typedef struct {
@@ -94,11 +102,15 @@ typedef struct {
        gint w;
        gint h;
 
+       gboolean rendering_info_changed;
+       gboolean video_size_changed;
+
        /* properties */
        gboolean update_needed; /* to update geometry information on pause state */
        gboolean visible;
        rect_info eo_size;
        rect_info dst_roi;
+       rect_info result;
        float ratio; /* need to set original ratio, not swap */
        guint rotate_angle;
        guint display_geometry_method;
@@ -117,10 +129,13 @@ typedef struct {
        GMutex mp_lock; /* media_packet free lock */
        GMutex idx_lock; /* to keep value of cur_idx */
        GMutex write_lock; /* ecore pipe write lock */
+       GMutex evas_lock;
+       GCond evas_cond[COND_NUM];
 
        /* flush buffer */
        flush_info *flush_buffer;
        gboolean keep_screen;
+       gboolean flush_all_packets;
 
        /* rendered callback */
        mm_evas_renderer_media_packet_rendered_cb packet_rendered_cb;
index 9cd472289111384c795be60be07951faba2ac634..7bffc5a93f1d422a32c3319283741105a3a5d5a6 100755 (executable)
@@ -36,7 +36,8 @@
 #define LOG_TAG "MM_EVAS_RENDER"
 //#define _INTERNAL_DEBUG_ /* debug only */
 #define SWAP(a, b)  ({int t; t = a; a = b; b = t; })
-
+#define INIT_IDX -1
+#define SIGNAL_TIMEOUT 1
 #if 0
 #define MMER_FENTER();                                 LOGD("<ENTER>");
 #define MMER_FLEAVE();                                 LOGD("<LEAVE>");
@@ -65,7 +66,6 @@
        do { \
                if (x_evas_image_object) { \
                        LOGD("object callback add"); \
-                       evas_object_event_callback_add(x_evas_image_object, EVAS_CALLBACK_DEL, _evas_del_cb, x_usr_data); \
                        evas_object_event_callback_add(x_evas_image_object, EVAS_CALLBACK_RESIZE, _evas_resize_cb, x_usr_data); \
                } \
        } while (0)
        do { \
                if (x_evas_image_object) { \
                        LOGD("object callback del"); \
-                       evas_object_event_callback_del(x_evas_image_object, EVAS_CALLBACK_DEL, _evas_del_cb); \
                        evas_object_event_callback_del(x_evas_image_object, EVAS_CALLBACK_RESIZE, _evas_resize_cb); \
                } \
        } while (0)
 
-#define SET_EVAS_EVENT_CALLBACK(x_evas, x_usr_data) \
-       do { \
-               if (x_evas) { \
-                       LOGD("callback add... evas_callback_render_pre.. evas : %p evas_info : %p", x_evas, x_usr_data); \
-                       evas_event_callback_add(x_evas, EVAS_CALLBACK_RENDER_PRE, _evas_render_pre_cb, x_usr_data); \
-               } \
-       } while (0)
-
-#define UNSET_EVAS_EVENT_CALLBACK(x_evas) \
-       do { \
-               if (x_evas) { \
-                       LOGD("callback del... evas_callback_render_pre %p", x_evas); \
-                       evas_event_callback_del(x_evas, EVAS_CALLBACK_RENDER_PRE, _evas_render_pre_cb); \
-               } \
-       } while (0)
-
 enum {
        DISP_GEO_METHOD_LETTER_BOX = 0,
        DISP_GEO_METHOD_ORIGIN_SIZE,
@@ -130,144 +113,104 @@ static int __dump_surf(tbm_surface_h tbm_surf);
 #endif
 /* internal */
 static void _free_previous_packets(mm_evas_info *evas_info);
-static int _flush_packets(mm_evas_info *evas_info);
+static int _flush_all_packets(mm_evas_info *evas_info);
 static int _mm_evas_renderer_create(mm_evas_info **evas_info);
 static int _mm_evas_renderer_destroy(mm_evas_info **evas_info);
 static int _mm_evas_renderer_set_info(mm_evas_info *evas_info, Evas_Object *eo);
 static int _mm_evas_renderer_reset(mm_evas_info *evas_info);
-static void _mm_evas_renderer_update_geometry(mm_evas_info *evas_info, rect_info *result);
-static int _mm_evas_renderer_apply_geometry(mm_evas_info *evas_info);
+static void _mm_evas_renderer_update_geometry(mm_evas_info *evas_info);
 static int _mm_evas_renderer_retrieve_all_packets(mm_evas_info *evas_info, bool keep_screen);
 static int _mm_evas_renderer_make_flush_buffer(mm_evas_info *evas_info);
 static void _mm_evas_renderer_release_flush_buffer(mm_evas_info *evas_info);
 static void _mm_evas_renderer_set_callback(mm_evas_info *evas_info);
 static void _mm_evas_renderer_unset_callback(mm_evas_info *evas_info);
+static void _mm_evas_renderer_set_evas_object_size(mm_evas_info *evas_info);
 
-static void _evas_resize_cb(void *data, Evas *e, Evas_Object *obj, void *event_info)
+/* must be called after the null surface has been set. */
+static int _mm_evas_renderer_update_rendering_info(mm_evas_info *evas_info)
 {
        MMER_FENTER();
 
-       int x, y, w, h, ret;
-       x = y = w = h = 0;
-
-       mm_evas_info *evas_info = data;
+       int ret = MM_ERROR_NONE;
 
-       if (!evas_info || !evas_info->eo)
-               return;
+       MMEVAS_RETURN_VAL_IF_FAIL(evas_info, MM_ERROR_EVASRENDER_NOT_INITIALIZED);
+       MMEVAS_RETURN_VAL_IF_FAIL(evas_info->eo, MM_ERROR_EVASRENDER_NOT_INITIALIZED);
 
-       evas_object_geometry_get(evas_info->eo, &x, &y, &w, &h);
-       if (!w || !h) {
-               LOGW("evas object size (w:%d,h:%d) was not set", w, h);
-       } else {
-               evas_info->eo_size.x = x;
-               evas_info->eo_size.y = y;
-               evas_info->eo_size.w = w;
-               evas_info->eo_size.h = h;
-               LOGW("resize (x:%d, y:%d, w:%d, h:%d)", x, y, w, h);
-               ret = _mm_evas_renderer_apply_geometry(evas_info);
-               if (ret != MM_ERROR_NONE)
-                       LOGW("fail to apply geometry info");
+       evas_object_geometry_get(evas_info->eo, &evas_info->eo_size.x, &evas_info->eo_size.y, &evas_info->eo_size.w, &evas_info->eo_size.h);
+       if (!evas_info->eo_size.w || !evas_info->eo_size.h) {
+               LOGE("there is no information for evas object size");
+               return MM_ERROR_EVASRENDER_INTERNAL;
        }
-       MMER_FLEAVE();
-}
 
-static void _evas_render_pre_cb(void *data, Evas *e, void *event_info)
-{
-       MMER_FENTER();
-
-       mm_evas_info *evas_info = data;
+       _mm_evas_renderer_update_geometry(evas_info);
+       if (!evas_info->result.w || !evas_info->result.h) {
+               LOGE("no information about geometry (%d, %d)", evas_info->result.w, evas_info->result.h);
+               return MM_ERROR_EVASRENDER_INTERNAL;
+       }
 
-       if (!evas_info || !evas_info->eo) {
-               LOGW("there is no evas_info.... evas_info : %p, or eo is NULL", evas_info);
-               return;
+       if (evas_info->video_size_changed) {
+               _mm_evas_renderer_set_evas_object_size(evas_info);
+               evas_info->video_size_changed = FALSE;
        }
 
+       if (evas_info->result.x || evas_info->result.y)
+               LOGD("coordinate x, y (%d, %d) for locating video to center", evas_info->result.x, evas_info->result.y);
+       evas_object_image_fill_set(evas_info->eo, evas_info->result.x, evas_info->result.y, evas_info->result.w, evas_info->result.h);
+
        MMER_FLEAVE();
+       return ret;
 }
 
-static void _evas_del_cb(void *data, Evas *e, Evas_Object *obj, void *event_info)
+static void _evas_resize_cb(void *data, Evas *e, Evas_Object *obj, void *event_info)
 {
        MMER_FENTER();
 
-       mm_evas_info *evas_info = data;
+       /* now evas object size is changed */
 
-       if (!evas_info || !evas_info->eo)
-               return;
+       mm_evas_info *evas_info = data;
 
-       if (evas_info->eo) {
-               _mm_evas_renderer_unset_callback(evas_info);
-               evas_object_image_data_set(evas_info->eo, NULL);
-               evas_info->eo = NULL;
+       MMEVAS_RETURN_IF_FAIL(evas_info);
+       MMEVAS_RETURN_IF_FAIL(evas_info->eo);
+
+       if (_mm_evas_renderer_update_rendering_info(evas_info) == MM_ERROR_NONE) {
+               Evas_Native_Surface *surf;
+               surf = evas_object_image_native_surface_get(evas_info->eo);
+               if (surf) {
+                       LOGD("native surface exists");
+                       surf->data.tbm.rot = evas_info->rotate_angle;
+                       surf->data.tbm.flip = evas_info->flip;
+                       surf->data.tbm.ratio = evas_info->ratio;
+                       /* surface set must be called by main thread */
+                       evas_object_image_native_surface_set(evas_info->eo, surf);
+               } else
+                       LOGW("there is no surf");
        }
+
        MMER_FLEAVE();
 }
 
-static void _evas_pipe_cb(void *data, void *buffer, update_info info)
+static gboolean _check_rendering_packet(mm_evas_info *evas_info)
 {
        MMER_FENTER();
+       gint cur_idx = 0;
+       tbm_format tbm_fmt = 0;
+       gchar *s_fmt = NULL;
 
-       mm_evas_info *evas_info = data;
-
-       if (!evas_info) {
-               LOGW("evas_info is NULL");
-               return;
-       }
-
-       g_mutex_lock(&evas_info->mp_lock);
-
-       if (!evas_info->eo) {
-               LOGW("evas_info %p", evas_info);
-               g_mutex_unlock(&evas_info->mp_lock);
-               return;
-       }
-
-       LOGD("evas_info : %p, info type : %d, evas_info->eo : %p", evas_info, info, evas_info->eo);
-
-       if (info != UPDATE_TBM_SURF && info != UPDATE_VISIBILITY && info != UPDATE_FLUSH_BUFFER) {
-               LOGW("invalid info type : %d", info);
-               g_mutex_unlock(&evas_info->mp_lock);
-               return;
-       }
+       MMEVAS_RETURN_VAL_IF_FAIL(evas_info, FALSE);
 
-       if (info == UPDATE_FLUSH_BUFFER) {
-               if (_flush_packets(evas_info) != MM_ERROR_NONE)
-                       LOGE("flushing packets is failed");
-               g_mutex_unlock(&evas_info->mp_lock);
-               return;
-       }
+       cur_idx = evas_info->cur_idx;
 
-       if (info == UPDATE_VISIBILITY) {
-               if (!evas_info->visible) {
-                       /* surface set must be called by main thread */
-                       evas_object_image_native_surface_set(evas_info->eo, NULL);
-                       evas_object_hide(evas_info->eo);
-                       LOGI("object hide..");
-                       LOGD("[LEAVE]");
-                       g_mutex_unlock(&evas_info->mp_lock);
-                       return;
-               } else {
-                       evas_object_show(evas_info->eo);
-                       LOGI("object show.. %d", evas_info->visible);
-               }
+       if ((cur_idx == -1) || !evas_info->pkt_info[cur_idx].tbm_surf) {
+               LOGW("cur_idx %d, tbm_surf may be NULL", cur_idx);
+               return FALSE;
        }
 
-       g_mutex_lock(&evas_info->idx_lock);
-       if ((evas_info->cur_idx == -1) || !evas_info->pkt_info[evas_info->cur_idx].tbm_surf) {
-               LOGW("cur_idx %d, tbm_surf may be NULL", evas_info->cur_idx);
-               g_mutex_unlock(&evas_info->idx_lock);
-               g_mutex_unlock(&evas_info->mp_lock);
-               return;
+       if (!evas_info->pkt_info[cur_idx].packet) {
+               LOGE(" Packet is NULL");
+               return FALSE;
        }
-       /* perhaps, it is needed to skip setting when state is pause */
-
-       /* index */
-       gint cur_idx = evas_info->cur_idx;
-       gint prev_idx = evas_info->pkt_info[cur_idx].prev;
 
-       LOGD("received (idx %d, packet %p)", cur_idx, evas_info->pkt_info[cur_idx].packet);
-
-       tbm_format tbm_fmt = tbm_surface_get_format(evas_info->pkt_info[cur_idx].tbm_surf);
-       gchar *s_fmt = NULL;
+       tbm_fmt = tbm_surface_get_format(evas_info->pkt_info[cur_idx].tbm_surf);
        switch (tbm_fmt) {
        case TBM_FORMAT_NV12:
                s_fmt = "TBM_FORMAT_NV12";
@@ -279,40 +222,56 @@ static void _evas_pipe_cb(void *data, void *buffer, update_info info)
                s_fmt = "unknown";
                break;
        }
-       LOGD("format(%d) : %s", tbm_fmt, s_fmt);
+       LOGD("received idx(%d), packet(%p), format([%d]: %s)", cur_idx, evas_info->pkt_info[cur_idx].packet, tbm_fmt, s_fmt);
 
-       Evas_Native_Surface surf = { 0 };
-       surf.type = EVAS_NATIVE_SURFACE_TBM;
-       surf.version = EVAS_NATIVE_SURFACE_VERSION;
-       surf.data.tbm.buffer = evas_info->pkt_info[cur_idx].tbm_surf;
-       surf.data.tbm.rot = evas_info->rotate_angle;
-       surf.data.tbm.flip = evas_info->flip;
+       MMER_FLEAVE();
 
-       rect_info result = { 0 };
+       return TRUE;
+}
 
-       evas_object_geometry_get(evas_info->eo, &evas_info->eo_size.x, &evas_info->eo_size.y,
-               &evas_info->eo_size.w, &evas_info->eo_size.h);
-       if (!evas_info->eo_size.w || !evas_info->eo_size.h) {
-               LOGE("there is no information for evas object size");
-               goto ERROR;
+/* must be called after the null surface has been set. */
+static void _mm_evas_renderer_surface_set(mm_evas_info *evas_info)
+{
+       MMER_FENTER();
+
+       gint cur_idx = 0;
+       gint prev_idx = 0;
+
+       MMEVAS_RETURN_IF_FAIL(evas_info);
+       MMEVAS_RETURN_IF_FAIL(evas_info->eo);
+
+       g_mutex_lock(&evas_info->idx_lock);
+
+       if (!_check_rendering_packet(evas_info)) {
+               g_mutex_unlock(&evas_info->idx_lock);
+               return;
        }
-       _mm_evas_renderer_update_geometry(evas_info, &result);
-       if (!result.w || !result.h) {
-               LOGE("no information about geometry (%d, %d)", result.w, result.h);
-               goto ERROR;
+
+       if (evas_info->rendering_info_changed) {
+               LOGD("Rendering info changed");
+               if (_mm_evas_renderer_update_rendering_info(evas_info) != MM_ERROR_NONE)
+                       goto ERROR;
+               evas_info->rendering_info_changed = FALSE;
        }
+       LOGD("GEO_METHOD : src(%dx%d), dst(%dx%d), dst_x(%d), dst_y(%d), rotate(%d), flip(%d)", evas_info->w, evas_info->h, evas_info->eo_size.w, evas_info->eo_size.h, evas_info->eo_size.x, evas_info->eo_size.y, evas_info->rotate_angle, evas_info->flip);
 
        if (evas_info->update_needed) {
-               /* update geometry on pause state */
                evas_object_image_native_surface_set(evas_info->eo, NULL);
                evas_info->update_needed = FALSE;
        }
+
+       cur_idx = evas_info->cur_idx;
+       prev_idx = evas_info->pkt_info[cur_idx].prev_idx;
+
+       /* set surface */
+       Evas_Native_Surface surf = { 0 };
+       surf.type = EVAS_NATIVE_SURFACE_TBM;
+       surf.version = EVAS_NATIVE_SURFACE_VERSION;
+       surf.data.tbm.buffer = evas_info->pkt_info[cur_idx].tbm_surf;
+       surf.data.tbm.rot = evas_info->rotate_angle;
+       surf.data.tbm.flip = evas_info->flip;
        surf.data.tbm.ratio = evas_info->ratio;
 
-       evas_object_size_hint_align_set(evas_info->eo, EVAS_HINT_FILL, EVAS_HINT_FILL);
-       evas_object_size_hint_weight_set(evas_info->eo, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
-       if (evas_info->w > 0 && evas_info->h > 0)
-               evas_object_image_size_set(evas_info->eo, evas_info->w, evas_info->h);
 #ifdef _INTERNAL_DEBUG_
        int ret2 = 0;
        if ((g_cnt_out%5 == 0) && (g_cnt_out < 500))
@@ -325,37 +284,94 @@ static void _evas_pipe_cb(void *data, void *buffer, update_info info)
        if (evas_info->visible) {
                /* surface set must be called by main thread */
                evas_object_image_native_surface_set(evas_info->eo, &surf);
+               evas_object_image_pixels_dirty_set(evas_info->eo, EINA_TRUE);
                LOGD("native surface set finish");
        } else {
                LOGD("skip... surface set");
        }
 
-       if (result.x || result.y)
-               LOGD("coordinate x, y (%d, %d) for locating video to center", result.x, result.y);
-
-       evas_object_image_fill_set(evas_info->eo, result.x, result.y, result.w, result.h);
-
-       evas_object_image_pixels_dirty_set(evas_info->eo, EINA_TRUE);
-       LOGD("GEO_METHOD : src(%dx%d), dst(%dx%d), dst_x(%d), dst_y(%d), rotate(%d), flip(%d)", evas_info->w, evas_info->h, evas_info->eo_size.w, evas_info->eo_size.h, evas_info->eo_size.x, evas_info->eo_size.y, evas_info->rotate_angle, evas_info->flip);
-
        /* when _evas_pipe_cb is called sequentially, previous packet and current packet will be the same */
        if ((prev_idx != -1) && evas_info->pkt_info[prev_idx].packet && (prev_idx != cur_idx))
                _free_previous_packets(evas_info);
 
        g_mutex_unlock(&evas_info->idx_lock);
-       g_mutex_unlock(&evas_info->mp_lock);
 
        MMER_FLEAVE();
-
        return;
 
- ERROR:
+ERROR:
        if ((prev_idx != -1) && evas_info->pkt_info[prev_idx].packet) {
                LOGI("cant render");
                _free_previous_packets(evas_info);
        }
        g_mutex_unlock(&evas_info->idx_lock);
-       g_mutex_unlock(&evas_info->mp_lock);
+
+       return;
+}
+
+/* must be called after the null surface has been set. */
+static void _mm_evas_renderer_select_task(mm_evas_info *evas_info, update_info info)
+{
+       MMER_FENTER();
+
+       MMEVAS_RETURN_IF_FAIL(evas_info);
+       MMEVAS_RETURN_IF_FAIL(evas_info->eo);
+
+       LOGD("evas_info : %p, info type : %d, evas_info->eo : %p", evas_info, info, evas_info->eo);
+
+       switch (info) {
+       case UPDATE_VISIBILITY:
+               if (!evas_info->visible) {
+                       /* surface set must be called by main thread */
+                       evas_object_image_native_surface_set(evas_info->eo, NULL);
+                       evas_object_hide(evas_info->eo);
+                       LOGI("object hide..");
+                       LOGD("[LEAVE]");
+               } else {
+                       evas_object_show(evas_info->eo);
+                       LOGI("object show.. %d", evas_info->visible);
+                       /* video rendering */
+                       _mm_evas_renderer_surface_set(evas_info);
+               }
+               break;
+       case UPDATE_TBM_SURF:
+               /* video rendering */
+               _mm_evas_renderer_surface_set(evas_info);
+               break;
+       case UPDATE_FLUSH_BUFFER:
+               if (_flush_all_packets(evas_info) != MM_ERROR_NONE)
+                       LOGE("flushing packets is failed");
+               break;
+       case UPDATE_DESTROY:
+               g_mutex_unlock(&evas_info->mp_lock);
+               if (_mm_evas_renderer_reset(evas_info) != MM_ERROR_NONE)
+                       LOGE("_mm_evas_renderer_reset is failed");
+               break;
+       default:
+               LOGW("invalid info type : %d", info);
+               break;
+       }
+
+       MMER_FLEAVE();
+       return;
+}
+
+static void _evas_pipe_cb(void *data, void *buffer, update_info info)
+{
+       MMER_FENTER();
+       mm_evas_info *evas_info = data;
+
+       MMEVAS_RETURN_IF_FAIL(evas_info);
+       MMEVAS_RETURN_IF_FAIL(evas_info->eo);
+
+       LOGD("ecore_pipe is called");
+       g_mutex_lock(&evas_info->mp_lock);
+       _mm_evas_renderer_select_task(evas_info, info);
+       if (info != UPDATE_DESTROY)
+               g_mutex_unlock(&evas_info->mp_lock);
+
+       MMER_FLEAVE();
+       return;
 }
 
 #ifdef _INTERNAL_DEBUG_
@@ -461,7 +477,7 @@ static void _free_previous_packets(mm_evas_info *evas_info)
        MMER_FENTER();
 
        gint index = evas_info->cur_idx;
-       gint prev_idx = evas_info->pkt_info[index].prev;
+       gint prev_idx = evas_info->pkt_info[index].prev_idx;
 
        while (prev_idx != -1) {
                LOGD("destroy previous packet [%p] idx %d", evas_info->pkt_info[prev_idx].packet, prev_idx);
@@ -474,11 +490,11 @@ static void _free_previous_packets(mm_evas_info *evas_info)
                evas_info->sent_buffer_cnt--;
                evas_info->pkt_info[prev_idx].packet = NULL;
                evas_info->pkt_info[prev_idx].tbm_surf = NULL;
-               evas_info->pkt_info[index].prev = -1;
+               evas_info->pkt_info[index].prev_idx = -1;
 
                /* move index to previous index */
                index = prev_idx;
-               prev_idx = evas_info->pkt_info[prev_idx].prev;
+               prev_idx = evas_info->pkt_info[prev_idx].prev_idx;
                LOGD("sent packet %d", evas_info->sent_buffer_cnt);
        }
 
@@ -496,8 +512,12 @@ static int _get_video_size(media_packet_h packet, mm_evas_info *evas_info)
                int w, h;
                if (media_format_get_video_info(fmt, NULL, &w, &h, NULL, NULL) == MEDIA_PACKET_ERROR_NONE) {
                        LOGD("video width = %d, height =%d", w, h);
-                       evas_info->w = w;
-                       evas_info->h = h;
+                       if (w != evas_info->w || h != evas_info->h) {
+                               evas_info->w = w;
+                               evas_info->h = h;
+                               evas_info->rendering_info_changed = TRUE;
+                               evas_info->video_size_changed = TRUE;
+                       }
                        return true;
                } else
                        LOGW("media_format_get_video_info is failed");
@@ -517,6 +537,7 @@ static int _find_empty_index(mm_evas_info *evas_info)
        MMER_FENTER();
 
        int i;
+
        for (i = 0; i < MAX_PACKET_NUM; i++) {
                if (!evas_info->pkt_info[i].packet) {
                        LOGD("selected idx %d", i);
@@ -530,7 +551,8 @@ static int _find_empty_index(mm_evas_info *evas_info)
        return -1;
 }
 
-static int _flush_packets(mm_evas_info *evas_info)
+/* must be called after the null surface has been set. */
+static int _destory_all_packets(mm_evas_info *evas_info)
 {
        MMER_FENTER();
 
@@ -538,59 +560,12 @@ static int _flush_packets(mm_evas_info *evas_info)
        int ret_mp = MEDIA_PACKET_ERROR_NONE;
        int i = 0;
 
-       if (!evas_info) {
-               LOGW("there is no evas_info");
-               return MM_ERROR_EVASRENDER_INVALID_ARGUMENT;
-       }
-
-       /* update the screen only if visible is true */
-       /* if flush buffer is null, we cant keep screen */
-       if (evas_info->keep_screen && evas_info->visible && evas_info->flush_buffer) {
-               Evas_Native_Surface surf = { 0 };
-               rect_info result = { 0 };
-               evas_object_geometry_get(evas_info->eo, &evas_info->eo_size.x, &evas_info->eo_size.y, &evas_info->eo_size.w, &evas_info->eo_size.h);
-               if (!evas_info->eo_size.w || !evas_info->eo_size.h) {
-                       LOGE("there is no information for evas object size");
-                       return MM_ERROR_EVASRENDER_INVALID_ARGUMENT;
-               }
-               _mm_evas_renderer_update_geometry(evas_info, &result);
-               if (!result.w || !result.h) {
-                       LOGE("no information about geometry (%d, %d)", result.w, result.h);
-                       return MM_ERROR_EVASRENDER_INVALID_ARGUMENT;
-               }
-               surf.data.tbm.ratio = evas_info->ratio;
-
-               evas_object_size_hint_align_set(evas_info->eo, EVAS_HINT_FILL, EVAS_HINT_FILL);
-               evas_object_size_hint_weight_set(evas_info->eo, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
-               if (evas_info->w > 0 && evas_info->h > 0)
-                       evas_object_image_size_set(evas_info->eo, evas_info->w, evas_info->h);
-
-               if (result.x || result.y)
-                       LOGD("coordinate x, y (%d, %d) for locating video to center", result.x, result.y);
-
-               evas_object_image_fill_set(evas_info->eo, result.x, result.y, result.w, result.h);
-
-               /* set flush buffer */
-               surf.type = EVAS_NATIVE_SURFACE_TBM;
-               surf.version = EVAS_NATIVE_SURFACE_VERSION;
-               surf.data.tbm.buffer = evas_info->flush_buffer->tbm_surf;
-               surf.data.tbm.rot = evas_info->rotate_angle;
-               surf.data.tbm.flip = evas_info->flip;
-               /* surface set must be called by main thread */
-               evas_object_image_native_surface_set(evas_info->eo, &surf);
-
-               LOGD("flush_buffer surf(%p), rotate(%d), flip(%d)", evas_info->flush_buffer->tbm_surf, evas_info->rotate_angle, evas_info->flip);
-       } else {
-               /* unset evas native surface for displaying black screen */
-               evas_object_image_native_surface_set(evas_info->eo, NULL);
-               evas_object_image_data_set(evas_info->eo, NULL);
-       }
-       LOGD("sent packet %d", evas_info->sent_buffer_cnt);
+       MMEVAS_RETURN_VAL_IF_FAIL(evas_info, MM_ERROR_EVASRENDER_NOT_INITIALIZED);
 
-       /* destroy all packets */
        g_mutex_lock(&evas_info->idx_lock);
        for (i = 0; i < MAX_PACKET_NUM; i++) {
                if (evas_info->pkt_info[i].packet) {
+                       /* destroy all packets */
                        LOGD("destroy packet [%p]", evas_info->pkt_info[i].packet);
                        if (evas_info->packet_rendered_cb) {
                                evas_info->packet_rendered_cb(evas_info->pkt_info[i].packet, evas_info->packet_rendered_cb_user);
@@ -604,94 +579,135 @@ static int _flush_packets(mm_evas_info *evas_info)
                        evas_info->sent_buffer_cnt--;
                        evas_info->pkt_info[i].packet = NULL;
                        evas_info->pkt_info[i].tbm_surf = NULL;
-                       evas_info->pkt_info[i].prev = -1;
+                       evas_info->pkt_info[i].prev_idx = INIT_IDX;
                }
        }
 
        if (evas_info->sent_buffer_cnt != 0)
                LOGE("it should be 0 --> [%d]", evas_info->sent_buffer_cnt);
        evas_info->sent_buffer_cnt = 0;
-       evas_info->cur_idx = -1;
-       g_mutex_unlock(&evas_info->idx_lock);
+       evas_info->cur_idx = INIT_IDX;
+       evas_info->flush_all_packets = TRUE;
 
-       evas_object_image_pixels_dirty_set(evas_info->eo, EINA_TRUE);
+       g_mutex_unlock(&evas_info->idx_lock);
 
        MMER_FLEAVE();
 
        return ret;
+
 }
 
-#if 0
-int _reset_pipe(mm_evas_info *evas_info)
+static int _set_flush_buffer(mm_evas_info *evas_info)
 {
-       int i = 0;
+       MMER_FENTER();
+
        int ret = MM_ERROR_NONE;
-       int ret_mp = MEDIA_PACKET_ERROR_NONE;
+       Evas_Native_Surface surf = { 0 };
 
-       /* delete old pipe */
-       if (evas_info->epipe) {
-               LOGD("pipe %p will be deleted", evas_info->epipe);
-               ecore_pipe_del(evas_info->epipe);
-               evas_info->epipe = NULL;
-       }
+       MMEVAS_RETURN_VAL_IF_FAIL(evas_info, MM_ERROR_EVASRENDER_NOT_INITIALIZED);
 
-       for (i = 0; i < MAX_PACKET_NUM; i++) {
-               if (evas_info->pkt_info[i].packet) {
-                       /* destroy all packets */
-                       LOGD("destroy packet [%p]", evas_info->pkt_info[i].packet);
-                       if (evas_info->packet_rendered_cb) {
-                               evas_info->packet_rendered_cb(evas_info->pkt_info[i].packet, evas_info->packet_rendered_cb_user);
-                       } else {
-                               ret_mp = media_packet_destroy(evas_info->pkt_info[i].packet);
-                               if (ret_mp != MEDIA_PACKET_ERROR_NONE) {
-                                       LOGW("media_packet_destroy failed %p", evas_info->pkt_info[i].packet);
-                                       ret = MM_ERROR_EVASRENDER_INTERNAL;
-                               }
-                       }
-                       evas_info->sent_buffer_cnt--;
-                       evas_info->pkt_info[i].packet = NULL;
-                       evas_info->pkt_info[i].tbm_surf = NULL;
-                       evas_info->pkt_info[i].prev = -1;
-               }
+       /* set flush buffer surface*/
+       surf.type = EVAS_NATIVE_SURFACE_TBM;
+       surf.version = EVAS_NATIVE_SURFACE_VERSION;
+       surf.data.tbm.buffer = evas_info->flush_buffer->tbm_surf;
+       surf.data.tbm.rot = evas_info->rotate_angle;
+       surf.data.tbm.flip = evas_info->flip;
+       surf.data.tbm.ratio = evas_info->ratio;
+
+       /* surface set must be called by main thread */
+       evas_object_image_native_surface_set(evas_info->eo, &surf);
+       evas_object_image_pixels_dirty_set(evas_info->eo, EINA_TRUE);
+
+       LOGD("flush_buffer surf(%p), rotate(%d), flip(%d)", evas_info->flush_buffer->tbm_surf, evas_info->rotate_angle, evas_info->flip);
+
+       return ret;
+}
+
+/* EVAS API must be called by main thread */
+static int _flush_all_packets(mm_evas_info *evas_info)
+{
+       MMER_FENTER();
+
+       int ret = MM_ERROR_NONE;
+       MMEVAS_RETURN_VAL_IF_FAIL(evas_info, MM_ERROR_EVASRENDER_NOT_INITIALIZED);
+
+       /* update the screen only if visible is true */
+       /* if flush buffer is null, we cant keep screen */
+       if (evas_info->keep_screen && evas_info->visible && evas_info->flush_buffer) {
+               /* _set_flush_buffer */
+               ret = _set_flush_buffer(evas_info);
+               if (ret != MM_ERROR_NONE) return ret;
+       } else {
+               /* unset evas native surface for displaying black screen */
+               evas_object_image_native_surface_set(evas_info->eo, NULL);
+               evas_object_image_pixels_dirty_set(evas_info->eo, EINA_TRUE);
        }
 
-       if (evas_info->sent_buffer_cnt != 0)
-               LOGE("it should be 0 --> [%d]", evas_info->sent_buffer_cnt);
-       evas_info->sent_buffer_cnt = 0;
-       evas_info->cur_idx = -1;
+       LOGD("sent packet %d", evas_info->sent_buffer_cnt);
+       ret = _destory_all_packets(evas_info);
 
-       /* make new pipe */
-       if (!evas_info->epipe) {
-               evas_info->epipe = ecore_pipe_add((Ecore_Pipe_Cb) _evas_pipe_cb, evas_info);
-               if (!evas_info->epipe) {
-                       LOGE("pipe is not created");
-                       ret = MM_ERROR_EVASRENDER_INTERNAL;
-               }
-               LOGD("created pipe %p", evas_info->epipe);
+       if (ret == MM_ERROR_NONE) {
+               g_mutex_lock(&evas_info->evas_lock);
+               LOGD("send signal[COND_RETRIEVE]");
+               g_cond_signal(&evas_info->evas_cond[COND_RETRIEVE]);
+               g_mutex_unlock(&evas_info->evas_lock);
        }
 
+       MMER_FLEAVE();
+
        return ret;
 }
-#endif
 
 static void _mm_evas_renderer_set_callback(mm_evas_info *evas_info)
 {
        MMER_FENTER();
-       if (evas_info->eo) {
+       if (evas_info->eo)
                SET_EVAS_OBJECT_EVENT_CALLBACK(evas_info->eo, evas_info);
-               SET_EVAS_EVENT_CALLBACK(evas_object_evas_get(evas_info->eo), evas_info);
-       }
+
        MMER_FLEAVE();
 }
 
 static void _mm_evas_renderer_unset_callback(mm_evas_info *evas_info)
 {
        MMER_FENTER();
-       if (evas_info->eo) {
+       if (evas_info->eo)
                UNSET_EVAS_OBJECT_EVENT_CALLBACK(evas_info->eo);
-               UNSET_EVAS_EVENT_CALLBACK(evas_object_evas_get(evas_info->eo));
+
+       MMER_FLEAVE();
+}
+
+static void _mm_evas_renderer_set_evas_object_size(mm_evas_info *evas_info)
+{
+       MMER_FENTER();
+       MMEVAS_RETURN_IF_FAIL(evas_info);
+       MMEVAS_RETURN_IF_FAIL(evas_info->eo);
+
+       if (evas_info->w > 0 && evas_info->h > 0)
+               evas_object_image_size_set(evas_info->eo, evas_info->w, evas_info->h);
+       evas_object_size_hint_align_set(evas_info->eo, EVAS_HINT_FILL, EVAS_HINT_FILL);
+       evas_object_size_hint_weight_set(evas_info->eo, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+
+       return;
+}
+
+static int _mm_evas_pipe_write(mm_evas_info *evas_info, update_info info)
+{
+       MMER_FENTER();
+
+       int ret = MM_ERROR_NONE;
+
+       MMEVAS_RETURN_VAL_IF_FAIL(evas_info, MM_ERROR_EVASRENDER_NOT_INITIALIZED);
+       MMEVAS_RETURN_VAL_IF_FAIL(evas_info->epipe, MM_ERROR_EVASRENDER_NOT_INITIALIZED);
+
+       g_mutex_lock(&evas_info->write_lock);
+       if (!ecore_pipe_write(evas_info->epipe, evas_info, info)) {
+               LOGW("fail to ecore_pipe_write() for update info type(%d)", info);
+               ret = MM_ERROR_EVASRENDER_INTERNAL;
        }
+       g_mutex_unlock(&evas_info->write_lock);
+
        MMER_FLEAVE();
+       return ret;
 }
 
 static int _mm_evas_renderer_create(mm_evas_info **evas_info)
@@ -711,7 +727,9 @@ static int _mm_evas_renderer_create(mm_evas_info **evas_info)
        g_mutex_init(&ptr->mp_lock);
        g_mutex_init(&ptr->idx_lock);
        g_mutex_init(&ptr->write_lock);
-
+       g_mutex_init(&ptr->evas_lock);
+       g_cond_init(&ptr->evas_cond[COND_RETRIEVE]);
+       g_cond_init(&ptr->evas_cond[COND_DESTROY]);
 
        MMER_FLEAVE();
 
@@ -726,20 +744,31 @@ static int _mm_evas_renderer_destroy(mm_evas_info **evas_info)
 {
        MMER_FENTER();
 
+       int ret = MM_ERROR_NONE;
+       pid_t pid = getpid();
+       pid_t tid = syscall(SYS_gettid);
+       gint64 end_time = g_get_monotonic_time() + SIGNAL_TIMEOUT * G_TIME_SPAN_SECOND;
        mm_evas_info *ptr = (mm_evas_info *)*evas_info;
+
        MMEVAS_RETURN_VAL_IF_FAIL(ptr, MM_ERROR_EVASRENDER_NOT_INITIALIZED);
-       int ret = MM_ERROR_NONE;
 
        LOGD("finalize evas_info %p", ptr);
 
-       ret = _mm_evas_renderer_reset(ptr);
-       g_mutex_clear(&ptr->mp_lock);
-       g_mutex_clear(&ptr->idx_lock);
-       g_mutex_clear(&ptr->write_lock);
-
-
-       g_free(ptr);
-       ptr = NULL;
+       /* this API can be call by sub thread */
+       LOGD("pid [%d], tid [%d]", pid, tid);
+       if (pid == tid) { /* API call by main thread */
+               ret = _mm_evas_renderer_reset(ptr);
+               if (ret != MM_ERROR_NONE)
+                       LOGE("_mm_evas_renderer_reset is failed");
+       } else {
+               ret = _mm_evas_pipe_write(ptr, UPDATE_DESTROY);
+               g_mutex_lock(&ptr->evas_lock);
+               if (!g_cond_wait_until(&ptr->evas_cond[COND_DESTROY], &ptr->evas_lock, end_time)) {
+                       //timeout
+                       LOGW("timeout: main thread is busy, App need to handle main thread well.");
+               }
+               g_mutex_unlock(&ptr->evas_lock);
+       }
 
        MMER_FLEAVE();
 
@@ -759,9 +788,13 @@ static int _mm_evas_renderer_set_info(mm_evas_info *evas_info, Evas_Object *eo)
        for (i = 0; i < MAX_PACKET_NUM; i++) {
                evas_info->pkt_info[i].packet = NULL;
                evas_info->pkt_info[i].tbm_surf = NULL;
-               evas_info->pkt_info[i].prev = -1;
+               evas_info->pkt_info[i].prev_idx = -1;
        }
 
+       evas_info->flush_all_packets = FALSE;
+       evas_info->rendering_info_changed = FALSE;
+       evas_info->video_size_changed = FALSE;
+       evas_info->w = evas_info->h = 0;
        evas_info->cur_idx = -1;
        evas_info->dst_roi.x = evas_info->dst_roi.y = evas_info->dst_roi.w = evas_info->dst_roi.h = 0;
        evas_info->eo = eo;
@@ -787,77 +820,80 @@ static int _mm_evas_renderer_set_info(mm_evas_info *evas_info, Evas_Object *eo)
 static int _mm_evas_renderer_reset(mm_evas_info *evas_info)
 {
        MMER_FENTER();
+
+       int ret = MM_ERROR_NONE;
        MMEVAS_RETURN_VAL_IF_FAIL(evas_info, MM_ERROR_EVASRENDER_NOT_INITIALIZED);
+       MMEVAS_RETURN_VAL_IF_FAIL(evas_info->eo, MM_ERROR_EVASRENDER_NOT_INITIALIZED);
+
        g_mutex_lock(&evas_info->mp_lock);
 
-       int i;
-       int ret = MM_ERROR_NONE;
-       int ret_mp = MEDIA_PACKET_ERROR_NONE;
+       evas_object_image_native_surface_set(evas_info->eo, NULL);
+       evas_object_image_pixels_dirty_set(evas_info->eo, EINA_TRUE);
+
+       evas_info->eo_size.x = evas_info->eo_size.y = evas_info->eo_size.w = evas_info->eo_size.h = 0;
+       evas_info->dst_roi.x = evas_info->dst_roi.y = evas_info->dst_roi.w = evas_info->dst_roi.h = 0;
+       evas_info->w = evas_info->h = 0;
+       evas_info->flush_all_packets = FALSE;
+
+       if (evas_info->flush_buffer)
+               _mm_evas_renderer_release_flush_buffer(evas_info);
+
+       if (!evas_info->flush_all_packets) {
+               ret = _destory_all_packets(evas_info);
+               if (ret != MM_ERROR_NONE) {
+                       g_mutex_unlock(&evas_info->mp_lock);
+                       return MM_ERROR_EVASRENDER_INTERNAL;
+               }
+       }
 
        if (evas_info->eo) {
                _mm_evas_renderer_unset_callback(evas_info);
-               evas_object_image_data_set(evas_info->eo, NULL);
                evas_info->eo = NULL;
        }
+
        if (evas_info->epipe) {
                LOGD("pipe %p will be deleted", evas_info->epipe);
                ecore_pipe_del(evas_info->epipe);
                evas_info->epipe = NULL;
        }
 
-       evas_info->eo_size.x = evas_info->eo_size.y = evas_info->eo_size.w = evas_info->eo_size.h = 0;
-       evas_info->dst_roi.x = evas_info->dst_roi.y = evas_info->dst_roi.w = evas_info->dst_roi.h = 0;
-       evas_info->w = evas_info->h = 0;
-
-       if (evas_info->flush_buffer)
-               _mm_evas_renderer_release_flush_buffer(evas_info);
-
-       g_mutex_lock(&evas_info->idx_lock);
-       for (i = 0; i < MAX_PACKET_NUM; i++) {
-               if (evas_info->pkt_info[i].packet) {
-                       /* destroy all packets */
-                       LOGD("destroy packet [%p]", evas_info->pkt_info[i].packet);
-                       if (evas_info->packet_rendered_cb) {
-                               evas_info->packet_rendered_cb(evas_info->pkt_info[i].packet, evas_info->packet_rendered_cb_user);
-                       } else {
-                               ret_mp = media_packet_destroy(evas_info->pkt_info[i].packet);
-                               if (ret_mp != MEDIA_PACKET_ERROR_NONE) {
-                                       LOGW("media_packet_destroy failed %p", evas_info->pkt_info[i].packet);
-                                       ret = MM_ERROR_EVASRENDER_INTERNAL;
-                               }
-                       }
-                       evas_info->sent_buffer_cnt--;
-                       evas_info->pkt_info[i].packet = NULL;
-                       evas_info->pkt_info[i].tbm_surf = NULL;
-                       evas_info->pkt_info[i].prev = -1;
-               }
+       if (ret == MM_ERROR_NONE) {
+               g_mutex_lock(&evas_info->evas_lock);
+               LOGD("send signal[COND_DESTROY]");
+               g_cond_signal(&evas_info->evas_cond[COND_DESTROY]);
+               g_mutex_unlock(&evas_info->evas_lock);
        }
-       g_mutex_unlock(&evas_info->idx_lock);
-       if (evas_info->sent_buffer_cnt != 0)
-               LOGE("it should be 0 --> [%d]", evas_info->sent_buffer_cnt);
-       evas_info->sent_buffer_cnt = 0;
-       evas_info->cur_idx = -1;
 
        g_mutex_unlock(&evas_info->mp_lock);
 
+       g_mutex_clear(&evas_info->mp_lock);
+       g_mutex_clear(&evas_info->idx_lock);
+       g_mutex_clear(&evas_info->write_lock);
+       g_mutex_clear(&evas_info->evas_lock);
+       g_cond_clear(&evas_info->evas_cond[COND_RETRIEVE]);
+       g_cond_clear(&evas_info->evas_cond[COND_DESTROY]);
+
+       g_free(evas_info);
+       evas_info = NULL;
+
        MMER_FLEAVE();
 
        return ret;
 }
 
-static void _mm_evas_renderer_update_geometry(mm_evas_info *evas_info, rect_info *result)
+static void _mm_evas_renderer_update_geometry(mm_evas_info *evas_info)
 {
        MMER_FENTER();
 
        gint video_width = 0;
        gint video_height = 0;
+       rect_info result = { 0 };
 
        MMEVAS_RETURN_IF_FAIL(evas_info);
        MMEVAS_RETURN_IF_FAIL(evas_info->eo); //need to check evas object
-       MMEVAS_RETURN_IF_FAIL(result);
 
-       result->x = 0;
-       result->y = 0;
+       result.x = 0;
+       result.y = 0;
        video_width = evas_info->w;
        video_height = evas_info->h;
 
@@ -874,23 +910,23 @@ static void _mm_evas_renderer_update_geometry(mm_evas_info *evas_info, rect_info
                /* set black padding for letter box mode */
                LOGD("letter box mode");
                evas_info->ratio = (float) evas_info->w / evas_info->h; /* need to set original video ratio */
-               result->w = evas_info->eo_size.w;
-               result->h = evas_info->eo_size.h;
+               result.w = evas_info->eo_size.w;
+               result.h = evas_info->eo_size.h;
                break;
        case DISP_GEO_METHOD_ORIGIN_SIZE:
                LOGD("origin size mode");
                evas_info->ratio = 0;
                /* set coordinate for each case */
-               result->x = (evas_info->eo_size.w - video_width) / 2;
-               result->y = (evas_info->eo_size.h - video_height) / 2;
-               result->w = video_width;
-               result->h = video_height;
+               result.x = (evas_info->eo_size.w - video_width) / 2;
+               result.y = (evas_info->eo_size.h - video_height) / 2;
+               result.w = video_width;
+               result.h = video_height;
                break;
        case DISP_GEO_METHOD_FULL_SCREEN:
                LOGD("full screen mode");
                evas_info->ratio = 0;
-               result->w = evas_info->eo_size.w;
-               result->h = evas_info->eo_size.h;
+               result.w = evas_info->eo_size.w;
+               result.h = evas_info->eo_size.h;
                break;
        case DISP_GEO_METHOD_CROPPED_FULL_SCREEN:
                LOGD("cropped full screen mode");
@@ -899,13 +935,13 @@ static void _mm_evas_renderer_update_geometry(mm_evas_info *evas_info, rect_info
                float video_ratio = (float)video_width / video_height;
                /* compare evas object's ratio with video's */
                if (eo_ratio > video_ratio) {
-                       result->w = evas_info->eo_size.w;
-                       result->h = evas_info->eo_size.w * video_height / video_width;
-                       result->y = -(result->h - evas_info->eo_size.h) / 2;
+                       result.w = evas_info->eo_size.w;
+                       result.h = evas_info->eo_size.w * video_height / video_width;
+                       result.y = -(result.h - evas_info->eo_size.h) / 2;
                } else {
-                       result->w = evas_info->eo_size.h * video_width / video_height;
-                       result->h = evas_info->eo_size.h;
-                       result->x = -(result->w - evas_info->eo_size.w) / 2;
+                       result.w = evas_info->eo_size.h * video_width / video_height;
+                       result.h = evas_info->eo_size.h;
+                       result.x = -(result.w - evas_info->eo_size.w) / 2;
                }
                break;
        case DISP_GEO_METHOD_ORIGIN_SIZE_OR_LETTER_BOX:
@@ -915,102 +951,53 @@ static void _mm_evas_renderer_update_geometry(mm_evas_info *evas_info, rect_info
                        LOGD("origin size mode");
                        evas_info->ratio = 0;
                        /* set coordinate for each case */
-                       result->x = (evas_info->eo_size.w - video_width) / 2;
-                       result->y = (evas_info->eo_size.h - video_height) / 2;
-                       result->w = video_width;
-                       result->h = video_height;
+                       result.x = (evas_info->eo_size.w - video_width) / 2;
+                       result.y = (evas_info->eo_size.h - video_height) / 2;
+                       result.w = video_width;
+                       result.h = video_height;
                } else {
                        LOGD("letter box mode");
                        evas_info->ratio = (float) evas_info->w / evas_info->h; /* need to set original video ratio */
-                       result->w = evas_info->eo_size.w;
-                       result->h = evas_info->eo_size.h;
+                       result.w = evas_info->eo_size.w;
+                       result.h = evas_info->eo_size.h;
                }
                break;
        case DISP_GEO_METHOD_CUSTOM_ROI:
                LOGD("custom roi mode");
                /* roi need to set -1 */
                evas_info->ratio = -1;
-               result->x = evas_info->dst_roi.x;
-               result->y = evas_info->dst_roi.y;
-               result->w = evas_info->dst_roi.w;
-               result->h = evas_info->dst_roi.h;
+               result.x = evas_info->dst_roi.x;
+               result.y = evas_info->dst_roi.y;
+               result.w = evas_info->dst_roi.w;
+               result.h = evas_info->dst_roi.h;
                if (evas_info->rotate_angle == DEGREE_90 || evas_info->rotate_angle == DEGREE_270)
-                       SWAP(result->w, result->h);
+                       SWAP(result.w, result.h);
                break;
        default:
                LOGW("unsupported mode.");
                break;
        }
 
-       LOGD("geometry result [%d, %d, %d, %d]", result->x, result->y, result->w, result->h);
-
-       MMER_FLEAVE();
-}
+       evas_info->result.x = result.x;
+       evas_info->result.y = result.y;
+       evas_info->result.w = result.w;
+       evas_info->result.h = result.h;
 
-static int _mm_evas_renderer_apply_geometry(mm_evas_info *evas_info)
-{
-       MMER_FENTER();
-
-       MMEVAS_RETURN_VAL_IF_FAIL(evas_info, MM_ERROR_EVASRENDER_NOT_INITIALIZED);
-       MMEVAS_RETURN_VAL_IF_FAIL(evas_info->eo, MM_ERROR_EVASRENDER_NOT_INITIALIZED); //need to check evas object
-
-       Evas_Native_Surface *surf = evas_object_image_native_surface_get(evas_info->eo);
-       rect_info result = { 0 };
-
-       if (surf) {
-               LOGD("native surface exists");
-               surf->data.tbm.rot = evas_info->rotate_angle;
-               surf->data.tbm.flip = evas_info->flip;
-               /* surface set must be called by main thread */
-               evas_object_image_native_surface_set(evas_info->eo, surf);
-
-               _mm_evas_renderer_update_geometry(evas_info, &result);
-
-               surf->data.tbm.ratio = evas_info->ratio;
-
-               if (result.x || result.y)
-                       LOGD("coordinate x, y (%d, %d) for locating video to center", result.x, result.y);
-
-               evas_object_image_fill_set(evas_info->eo, result.x, result.y, result.w, result.h);
-
-               return MM_ERROR_NONE;
-       } else
-               LOGW("there is no surf");
-       /* FIXME: before pipe_cb is invoked, apply_geometry can be called. */
-
-       MMER_FLEAVE();
-
-       return MM_ERROR_NONE;
-}
-
-
-static int _mm_evas_pipe_write(mm_evas_info *evas_info, update_info info)
-{
-       MMER_FENTER();
-       MMEVAS_RETURN_VAL_IF_FAIL(evas_info, MM_ERROR_EVASRENDER_NOT_INITIALIZED);
-       MMEVAS_RETURN_VAL_IF_FAIL(evas_info->epipe, MM_ERROR_EVASRENDER_NOT_INITIALIZED);
-
-       int ret = MM_ERROR_NONE;
-
-       g_mutex_lock(&evas_info->write_lock);
-       if (!ecore_pipe_write(evas_info->epipe, evas_info, info)) {
-               LOGW("fail to ecore_pipe_write() for update info type(%d)", info);
-               ret = MM_ERROR_EVASRENDER_INTERNAL;
-       }
-       g_mutex_unlock(&evas_info->write_lock);
+       LOGD("geometry result [%d, %d, %d, %d]", evas_info->result.x, evas_info->result.y, evas_info->result.w, evas_info->result.h);
 
        MMER_FLEAVE();
-       return ret;
 }
 
 static int _mm_evas_renderer_retrieve_all_packets(mm_evas_info *evas_info, bool keep_screen)
 {
        MMER_FENTER();
-       MMEVAS_RETURN_VAL_IF_FAIL(evas_info, MM_ERROR_EVASRENDER_NOT_INITIALIZED);
 
        int ret = MM_ERROR_NONE;
        pid_t pid = getpid();
        pid_t tid = syscall(SYS_gettid);
+       gint64 end_time = g_get_monotonic_time() + SIGNAL_TIMEOUT * G_TIME_SPAN_SECOND;
+
+       MMEVAS_RETURN_VAL_IF_FAIL(evas_info, MM_ERROR_EVASRENDER_NOT_INITIALIZED);
 
        /* this API can be call by sub thread */
        LOGD("pid [%d], tid [%d]", pid, tid);
@@ -1020,7 +1007,23 @@ static int _mm_evas_renderer_retrieve_all_packets(mm_evas_info *evas_info, bool
                ret = _mm_evas_renderer_make_flush_buffer(evas_info);
        evas_info->keep_screen = keep_screen;
 
-       ret = _mm_evas_pipe_write(evas_info, UPDATE_FLUSH_BUFFER);
+       if (pid == tid) { /* API call by main thread */
+               /* flush all packet */
+               g_mutex_lock(&evas_info->mp_lock);
+               ret = _flush_all_packets(evas_info);
+               if (ret != MM_ERROR_NONE)
+                       LOGE("flushing packets is failed");
+               g_mutex_unlock(&evas_info->mp_lock);
+       } else {
+               /* flush all packet */
+               ret = _mm_evas_pipe_write(evas_info, UPDATE_FLUSH_BUFFER);
+               g_mutex_lock(&evas_info->evas_lock);
+               if (!g_cond_wait_until(&evas_info->evas_cond[COND_RETRIEVE], &evas_info->evas_lock, end_time)) {
+                       //timeout
+                       LOGW("timeout: main thread is busy, App need to handle main thread well.");
+               }
+               g_mutex_unlock(&evas_info->evas_lock);
+       }
 
        MMER_FLEAVE();
 
@@ -1180,7 +1183,7 @@ void mm_evas_renderer_write(media_packet_h packet, void *data)
        int ret = MEDIA_PACKET_ERROR_NONE;
        bool has;
        tbm_surface_h tbm_surf;
-       gint index;
+       gint new_idx;
 
        LOGD("packet [%p]", packet);
 
@@ -1202,14 +1205,6 @@ void mm_evas_renderer_write(media_packet_h packet, void *data)
                if (handle->sent_buffer_cnt > 3) {
                        LOGE("too many buffers are not released %d", handle->sent_buffer_cnt);
                        goto ERROR;
-#if 0
-                       /* FIXME: fix this logic */
-                       /* destroy all media packets and reset pipe at present */
-                       /* Attention! it might free buffer that is being rendered */
-                       g_mutex_lock(&handle->mp_lock);
-                       _reset_pipe(handle);
-                       g_mutex_unlock(&handle->mp_lock);
-#endif
                }
                ret = media_packet_get_tbm_surface(packet, &tbm_surf);
                if (ret != MEDIA_PACKET_ERROR_NONE || !tbm_surf) {
@@ -1218,8 +1213,8 @@ void mm_evas_renderer_write(media_packet_h packet, void *data)
                }
 
                /* find new index for current packet */
-               index = _find_empty_index(handle);
-               if (index == -1)
+               new_idx = _find_empty_index(handle);
+               if (new_idx == -1)
                        goto ERROR;
 
 #ifdef _INTERNAL_DEBUG_
@@ -1233,19 +1228,19 @@ void mm_evas_renderer_write(media_packet_h packet, void *data)
                        g_cnt_in++;
 #endif
                /* save previous index */
-               handle->pkt_info[index].prev = handle->cur_idx;
-               handle->pkt_info[index].packet = packet;
-               handle->pkt_info[index].tbm_surf = tbm_surf;
-               handle->cur_idx = index;
+               handle->pkt_info[new_idx].prev_idx = handle->cur_idx;
+               handle->pkt_info[new_idx].packet = packet;
+               handle->pkt_info[new_idx].tbm_surf = tbm_surf;
+               handle->cur_idx = new_idx;
                handle->sent_buffer_cnt++;
                LOGD("sent packet %d", handle->sent_buffer_cnt);
 
                ret = _mm_evas_pipe_write(handle, UPDATE_TBM_SURF);
                if (ret != MM_ERROR_NONE) {
-                       handle->pkt_info[index].packet = NULL;
-                       handle->pkt_info[index].tbm_surf = NULL;
-                       handle->pkt_info[index].prev = -1;
-                       handle->cur_idx = handle->pkt_info[index].prev;
+                       handle->pkt_info[new_idx].packet = NULL;
+                       handle->pkt_info[new_idx].tbm_surf = NULL;
+                       handle->pkt_info[new_idx].prev_idx = -1;
+                       handle->cur_idx = handle->pkt_info[new_idx].prev_idx;
                        handle->sent_buffer_cnt--;
                        LOGW("Failed to ecore_pipe_write() for updating tbm surf\n");
                        goto ERROR;
@@ -1281,13 +1276,13 @@ INVALID_PARAM:
 int mm_evas_renderer_create(MMHandleType *handle, Evas_Object *eo)
 {
        MMER_FENTER();
-       MMEVAS_RETURN_VAL_IF_FAIL(handle, MM_ERROR_EVASRENDER_INVALID_ARGUMENT);
-       MMEVAS_RETURN_VAL_IF_FAIL(eo, MM_ERROR_EVASRENDER_INVALID_ARGUMENT);
-
 
        int ret = MM_ERROR_NONE;
        mm_evas_info *evas_info = NULL;
 
+       MMEVAS_RETURN_VAL_IF_FAIL(handle, MM_ERROR_EVASRENDER_INVALID_ARGUMENT);
+       MMEVAS_RETURN_VAL_IF_FAIL(eo, MM_ERROR_EVASRENDER_INVALID_ARGUMENT);
+
        ret = _mm_evas_renderer_create(&evas_info);
        if (ret != MM_ERROR_NONE) {
                LOGE("fail to create evas_info");
@@ -1386,6 +1381,7 @@ int mm_evas_renderer_set_rotation(MMHandleType handle, int rotate)
                evas_info->update_needed = TRUE;
                evas_info->rotate_angle = value;
        }
+       evas_info->rendering_info_changed = TRUE;
 
        ret = _mm_evas_pipe_write(evas_info, UPDATE_TBM_SURF);
 
@@ -1436,6 +1432,8 @@ int mm_evas_renderer_set_geometry(MMHandleType handle, int mode)
                evas_info->display_geometry_method = mode;
        }
 
+       evas_info->rendering_info_changed = TRUE;
+
        /* ecore_pipe_write is needed, because of setting ratio for letterbox mode */
        ret = _mm_evas_pipe_write(evas_info, UPDATE_TBM_SURF);
 
@@ -1484,6 +1482,8 @@ int mm_evas_renderer_set_roi_area(MMHandleType handle, int x, int y, int w, int
                evas_info->dst_roi.h = h;
        }
 
+       evas_info->rendering_info_changed = TRUE;
+
        /* pipe_write could be needed because ratio can be changed on pause state */
        ret = _mm_evas_pipe_write(evas_info, UPDATE_TBM_SURF);
 
@@ -1544,6 +1544,7 @@ int mm_evas_renderer_set_flip(MMHandleType handle, int flip)
                evas_info->update_needed = TRUE;
                evas_info->flip = value;
        }
+
        ret = _mm_evas_pipe_write(evas_info, UPDATE_TBM_SURF);
 
        MMER_FLEAVE();