fix svace issue
[platform/core/multimedia/libmm-evas-renderer.git] / src / mm_evas_renderer.c
index 833b366..a62fa61 100644 (file)
 #include <stdlib.h>
 #include <dlog.h>
 #include <mm_error.h>
-
+#include <sys/syscall.h>
 #include "mm_evas_renderer.h"
 
 #ifdef LOG_TAG
 #undef LOG_TAG
 #endif
 #define LOG_TAG "MM_EVAS_RENDER"
+//#define _INTERNAL_DEBUG_ /* debug only */
 
-#define MM_CHECK_NULL( x_var ) \
-if ( ! x_var ) \
-{ \
-       LOGE("[%s] is NULL\n", #x_var ); \
-       return MM_ERROR_INVALID_ARGUMENT; \
-}
+#if 0
+#define MMER_FENTER();                                 LOGD("<ENTER>");
+#define MMER_FLEAVE();                                 LOGD("<LEAVE>");
+#else
+#define MMER_FENTER();
+#define MMER_FLEAVE();
+#endif
+
+#define MM_CHECK_NULL(x_var) \
+       if (!x_var) { \
+               LOGE("[%s] is NULL\n", #x_var); \
+               return MM_ERROR_INVALID_ARGUMENT; \
+       }
 
-#define SET_EVAS_OBJECT_EVENT_CALLBACK( x_evas_image_object, x_usr_data ) \
-       do \
-       { \
+#define SET_EVAS_OBJECT_EVENT_CALLBACK(x_evas_image_object, x_usr_data) \
+       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); \
+                       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)
+       } while (0)
 
-#define UNSET_EVAS_OBJECT_EVENT_CALLBACK( x_evas_image_object ) \
-       do \
-       { \
+#define UNSET_EVAS_OBJECT_EVENT_CALLBACK(x_evas_image_object) \
+       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); \
+                       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)
+       } while (0)
 
-#define SET_EVAS_EVENT_CALLBACK( x_evas, x_usr_data ) \
-       do \
-       { \
+#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); \
+                       evas_event_callback_add(x_evas, EVAS_CALLBACK_RENDER_PRE, _evas_render_pre_cb, x_usr_data); \
                } \
-       } while(0)
+       } while (0)
 
-#define UNSET_EVAS_EVENT_CALLBACK( x_evas ) \
-       do \
-       { \
+#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); \
+                       evas_event_callback_del(x_evas, EVAS_CALLBACK_RENDER_PRE, _evas_render_pre_cb); \
                } \
-       } while(0)
+       } while (0)
 
 enum {
        DISP_GEO_METHOD_LETTER_BOX = 0,
@@ -86,6 +90,7 @@ enum {
        DISP_GEO_METHOD_FULL_SCREEN,
        DISP_GEO_METHOD_CROPPED_FULL_SCREEN,
        DISP_GEO_METHOD_ORIGIN_SIZE_OR_LETTER_BOX,
+       DISP_GEO_METHOD_CUSTOM_ROI,
        DISP_GEO_METHOD_NUM,
 };
 
@@ -105,31 +110,37 @@ enum {
        FLIP_NUM,
 };
 
-/* internal */
-#ifdef _DEBUG_INDEX
-void __print_idx(mm_evas_info *evas_info);
+#ifdef _INTERNAL_DEBUG_
+static int g_cnt = 0;
+static void __print_idx(mm_evas_info *evas_info);
+static int __dump_pkt(media_packet_h pkt);
 #endif
-void _free_previous_packets(mm_evas_info *evas_info);
-int _mm_evas_renderer_create(mm_evas_info **evas_info);
-int _mm_evas_renderer_destroy(mm_evas_info **evas_info);
-int _mm_evas_renderer_set_info(mm_evas_info *evas_info, Evas_Object *eo);
-int _mm_evas_renderer_reset(mm_evas_info *evas_info);
-void _mm_evas_renderer_update_geometry(mm_evas_info *evas_info, rect_info *result);
-int _mm_evas_renderer_apply_geometry(mm_evas_info *evas_info);
+/* internal */
+static void _free_previous_packets(mm_evas_info *evas_info);
+static int _flush_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 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 _evas_resize_cb(void *data, Evas *e, Evas_Object *obj, void *event_info)
 {
+       MMER_FENTER();
+
        int x, y, w, h, ret;
        x = y = w = h = 0;
 
        mm_evas_info *evas_info = data;
-       LOGD("[ENTER]");
 
-       if (!evas_info || !evas_info->eo) {
+       if (!evas_info || !evas_info->eo)
                return;
-       }
 
        evas_object_geometry_get(evas_info->eo, &x, &y, &w, &h);
        if (!w || !h) {
@@ -144,39 +155,53 @@ static void _evas_resize_cb(void *data, Evas *e, Evas_Object *obj, void *event_i
                if (ret != MM_ERROR_NONE)
                        LOGW("fail to apply geometry info");
        }
-       LOGD("[LEAVE]");
+       MMER_FLEAVE();
 }
 
 static void _evas_render_pre_cb(void *data, Evas *e, void *event_info)
 {
+       MMER_FENTER();
+
        mm_evas_info *evas_info = data;
+
        if (!evas_info || !evas_info->eo) {
                LOGW("there is no esink info.... esink : %p, or eo is NULL returning", evas_info);
                return;
        }
-       /* LOGI("- test -"); pre_cb will be used for flush_buffer */
+
+       /* flush will be executed in this callback normally,
+       because native_surface_set must be called in main thread */
+       if (evas_info->retrieve_packet) {
+               g_mutex_lock(&evas_info->idx_lock);
+               if (_flush_packets(evas_info) != MM_ERROR_NONE)
+                       LOGE("flushing packets are failed");
+               g_mutex_unlock(&evas_info->idx_lock);
+       }
+       MMER_FLEAVE();
 }
 
 static void _evas_del_cb(void *data, Evas *e, Evas_Object *obj, void *event_info)
 {
+       MMER_FENTER();
+
        mm_evas_info *evas_info = data;
-       LOGD("[ENTER]");
-       if (!evas_info || !evas_info->eo) {
+
+       if (!evas_info || !evas_info->eo)
                return;
-       }
+
        if (evas_info->eo) {
                _mm_evas_renderer_unset_callback(evas_info);
                evas_object_image_data_set(evas_info->eo, NULL);
                evas_info->eo = NULL;
        }
-       LOGD("[LEAVE]");
+       MMER_FLEAVE();
 }
 
-void _evas_pipe_cb(void *data, void *buffer, update_info info)
+static void _evas_pipe_cb(void *data, void *buffer, update_info info)
 {
-       mm_evas_info *evas_info = data;
+       MMER_FENTER();
 
-       LOGD("[ENTER]");
+       mm_evas_info *evas_info = data;
 
        if (!evas_info) {
                LOGW("evas_info is NULL", evas_info);
@@ -211,11 +236,13 @@ void _evas_pipe_cb(void *data, void *buffer, update_info info)
                return;
        }
 
-       if (evas_info->cur_idx==-1 || !evas_info->pkt_info[evas_info->cur_idx].tbm_surf) {
+       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->mp_lock);
                return;
        }
+       /* perhaps, it is needed to skip setting when state is pause */
+
        g_mutex_lock(&evas_info->idx_lock);
        /* index */
        gint cur_idx = evas_info->cur_idx;
@@ -223,7 +250,7 @@ void _evas_pipe_cb(void *data, void *buffer, update_info info)
 
        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[evas_info->cur_idx].tbm_surf);
+       tbm_format tbm_fmt = tbm_surface_get_format(evas_info->pkt_info[cur_idx].tbm_surf);
        switch (tbm_fmt) {
        case TBM_FORMAT_NV12:
                LOGD("tbm_surface format : TBM_FORMAT_NV12");
@@ -235,17 +262,18 @@ void _evas_pipe_cb(void *data, void *buffer, update_info info)
                LOGW("tbm_surface format : unknown %d", tbm_fmt);
                break;
        }
-       /* it is needed to skip setting when state is pause */
-       Evas_Native_Surface surf;
+
+       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.rot = evas_info->rotate_angle;
+       surf.data.tbm.flip = evas_info->flip;
 
        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);
+       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;
@@ -256,9 +284,15 @@ void _evas_pipe_cb(void *data, void *buffer, update_info info)
                goto ERROR;
        }
 
+       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;
+       }
+
        if (evas_info->use_ratio) {
-//      surf.data.tbm.ratio = (float) evas_info->w / evas_info->h;
-               LOGD("set ratio for letter mode");
+               surf.data.tbm.ratio = (float) evas_info->w / evas_info->h;
+               LOGD("set 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);
@@ -270,6 +304,7 @@ void _evas_pipe_cb(void *data, void *buffer, update_info info)
 
        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);
@@ -279,10 +314,11 @@ void _evas_pipe_cb(void *data, void *buffer, update_info info)
        if ((prev_idx != -1) && evas_info->pkt_info[prev_idx].packet && (prev_idx != cur_idx))
                _free_previous_packets(evas_info);
 
-       LOGD("[LEAVE]");
        g_mutex_unlock(&evas_info->idx_lock);
        g_mutex_unlock(&evas_info->mp_lock);
 
+       MMER_FLEAVE();
+
        return;
 
  ERROR:
@@ -294,46 +330,77 @@ void _evas_pipe_cb(void *data, void *buffer, update_info info)
        g_mutex_unlock(&evas_info->mp_lock);
 }
 
-#ifdef _DEBUG_INDEX
-void __print_idx(mm_evas_info *evas_info)
+#ifdef _INTERNAL_DEBUG_
+static void __print_idx(mm_evas_info *evas_info)
 {
        gint prev_idx = evas_info->pkt_info[evas_info->cur_idx].prev;
        LOGE("***** start cur_idx : %d -> prev_idx : %d", evas_info->cur_idx, prev_idx);
-       while(prev_idx != -1)
-       {
+       while (prev_idx != -1) {
                LOGE("***** cur_idx : %d -> prev_idx : %d", prev_idx, evas_info->pkt_info[prev_idx].prev);
                prev_idx = evas_info->pkt_info[prev_idx].prev;
        }
        LOGE("***** end");
        return;
 }
+
+static int __dump_pkt(media_packet_h pkt)
+{
+       void *data;
+       uint64_t buf_size;
+       char filename[100] = {0};
+       FILE *fp = NULL;
+
+       sprintf(filename, "/tmp/DUMP_IMG_%2.2d.dump", g_cnt);
+       fp = fopen(filename, "wb");
+       if (fp == NULL)
+               return 1;
+
+       LOGW("DUMP IMG_%2.2d", g_cnt);
+       media_packet_get_buffer_data_ptr(pkt, &data);
+       media_packet_get_buffer_size(pkt, &buf_size);
+       LOGW("input data : %p, size %d\n", data, (int)buf_size);
+       fwrite(data, (int)buf_size, 1, fp);
+       fclose(fp);
+
+       return 0;
+}
 #endif
 
-void _free_previous_packets(mm_evas_info *evas_info)
+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;
 
-       while(prev_idx != -1)
-       {
+       while (prev_idx != -1) {
                LOGD("destroy previous packet [%p] idx %d", evas_info->pkt_info[prev_idx].packet, prev_idx);
-               if (media_packet_destroy(evas_info->pkt_info[prev_idx].packet) != MEDIA_PACKET_ERROR_NONE)
-                       LOGE("media_packet_destroy failed %p", evas_info->pkt_info[prev_idx].packet);
+               if (evas_info->packet_rendered_cb) {
+                       evas_info->packet_rendered_cb(evas_info->pkt_info[prev_idx].packet, evas_info->packet_rendered_cb_user);
+               } else {
+                       if (media_packet_destroy(evas_info->pkt_info[prev_idx].packet) != MEDIA_PACKET_ERROR_NONE)
+                               LOGE("media_packet_destroy failed %p", evas_info->pkt_info[prev_idx].packet);
+               }
+               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->sent_buffer_cnt--;
 
                /* move index to previous index */
-               index= prev_idx;
+               index = prev_idx;
                prev_idx = evas_info->pkt_info[prev_idx].prev;
                LOGD("sent packet %d", evas_info->sent_buffer_cnt);
        }
+
+       MMER_FLEAVE();
+
        return;
 }
 
 static int _get_video_size(media_packet_h packet, mm_evas_info *evas_info)
 {
+       MMER_FENTER();
+
        media_format_h fmt;
        if (media_packet_get_format(packet, &fmt) == MEDIA_PACKET_ERROR_NONE) {
                int w, h;
@@ -349,11 +416,16 @@ static int _get_video_size(media_packet_h packet, mm_evas_info *evas_info)
        } else {
                LOGW("media_packet_get_format is failed");
        }
+
+       MMER_FLEAVE();
+
        return false;
 }
 
-int _find_empty_index(mm_evas_info *evas_info)
+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) {
@@ -363,14 +435,111 @@ int _find_empty_index(mm_evas_info *evas_info)
        }
        LOGE("there is no empty idx");
 
+       MMER_FLEAVE();
+
        return -1;
 }
 
+static int _flush_packets(mm_evas_info *evas_info)
+{
+       MMER_FENTER();
+
+       int ret = MM_ERROR_NONE;
+       int ret_mp = MEDIA_PACKET_ERROR_NONE;
+       int i = 0;
+
+       if (!evas_info) {
+               LOGW("there is no esink info");
+               return MM_ERROR_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 != VISIBLE_FALSE) && 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_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_INVALID_ARGUMENT;
+               }
+
+               if (evas_info->use_ratio) {
+                       surf.data.tbm.ratio = (float) evas_info->w / evas_info->h;
+                       LOGD("set 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;
+               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);
+
+       /* destroy all packets */
+       g_mutex_lock(&evas_info->mp_lock);
+       for (i = 0; i < MAX_PACKET_NUM; i++) {
+               if (evas_info->pkt_info[i].packet) {
+                       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_UNKNOWN;
+                               }
+                       }
+                       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 (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);
+
+       evas_object_image_pixels_dirty_set(evas_info->eo, EINA_TRUE);
+       evas_info->retrieve_packet = FALSE;
+
+       MMER_FLEAVE();
+
+       return ret;
+}
+
 #if 0
-void _reset_pipe(mm_evas_info *evas_info)
+int _reset_pipe(mm_evas_info *evas_info)
 {
        int i = 0;
-       int ret = MEDIA_PACKET_ERROR_NONE;
+       int ret = MM_ERROR_NONE;
+       int ret_mp = MEDIA_PACKET_ERROR_NONE;
 
        /* delete old pipe */
        if (evas_info->epipe) {
@@ -379,49 +548,69 @@ void _reset_pipe(mm_evas_info *evas_info)
                evas_info->epipe = NULL;
        }
 
-       /* destroy all packets */
        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);
-                       ret = media_packet_destroy(evas_info->pkt_info[i].packet);
-                       if (ret != MEDIA_PACKET_ERROR_NONE)
-                               LOGW("media_packet_destroy failed %p", evas_info->pkt_info[i].packet);
-                       else
-                               evas_info->sent_buffer_cnt--;
+                       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_UNKNOWN;
+                               }
+                       }
+                       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 (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;
+
        /* 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_UNKNOWN;
                }
                LOGD("created pipe %p", evas_info->epipe);
        }
 
-       return;
+       return ret;
 }
 #endif
+
 static void _mm_evas_renderer_set_callback(mm_evas_info *evas_info)
 {
+       MMER_FENTER();
        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) {
                UNSET_EVAS_OBJECT_EVENT_CALLBACK(evas_info->eo);
                UNSET_EVAS_EVENT_CALLBACK(evas_object_evas_get(evas_info->eo));
        }
+       MMER_FLEAVE();
 }
 
-int _mm_evas_renderer_create(mm_evas_info **evas_info)
+static int _mm_evas_renderer_create(mm_evas_info **evas_info)
 {
+       MMER_FENTER();
+
        mm_evas_info *ptr = NULL;
        ptr = g_malloc0(sizeof(mm_evas_info));
 
@@ -435,6 +624,8 @@ int _mm_evas_renderer_create(mm_evas_info **evas_info)
        g_mutex_init(&ptr->mp_lock);
        g_mutex_init(&ptr->idx_lock);
 
+       MMER_FLEAVE();
+
        return MM_ERROR_NONE;
 
  ERROR:
@@ -442,8 +633,10 @@ int _mm_evas_renderer_create(mm_evas_info **evas_info)
        return MM_ERROR_OUT_OF_STORAGE;
 }
 
-int _mm_evas_renderer_destroy(mm_evas_info **evas_info)
+static int _mm_evas_renderer_destroy(mm_evas_info **evas_info)
 {
+       MMER_FENTER();
+
        mm_evas_info *ptr = (mm_evas_info *)*evas_info;
        MM_CHECK_NULL(ptr);
        int ret = MM_ERROR_NONE;
@@ -457,11 +650,14 @@ int _mm_evas_renderer_destroy(mm_evas_info **evas_info)
        g_free(ptr);
        ptr = NULL;
 
+       MMER_FLEAVE();
+
        return ret;
 }
 
-int _mm_evas_renderer_set_info(mm_evas_info *evas_info, Evas_Object *eo)
+static int _mm_evas_renderer_set_info(mm_evas_info *evas_info, Evas_Object *eo)
 {
+       MMER_FENTER();
        MM_CHECK_NULL(evas_info);
        MM_CHECK_NULL(eo);
        g_mutex_lock(&evas_info->idx_lock);
@@ -473,8 +669,8 @@ int _mm_evas_renderer_set_info(mm_evas_info *evas_info, Evas_Object *eo)
                evas_info->pkt_info[i].tbm_surf = NULL;
                evas_info->pkt_info[i].prev = -1;
        }
-
        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;
        evas_info->epipe = ecore_pipe_add((Ecore_Pipe_Cb) _evas_pipe_cb, evas_info);
        if (!evas_info->epipe) {
@@ -490,11 +686,14 @@ int _mm_evas_renderer_set_info(mm_evas_info *evas_info, Evas_Object *eo)
 
        g_mutex_unlock(&evas_info->idx_lock);
 
+       MMER_FLEAVE();
+
        return MM_ERROR_NONE;
 }
 
-int _mm_evas_renderer_reset(mm_evas_info *evas_info)
+static int _mm_evas_renderer_reset(mm_evas_info *evas_info)
 {
+       MMER_FENTER();
        MM_CHECK_NULL(evas_info);
        g_mutex_lock(&evas_info->idx_lock);
 
@@ -514,20 +713,27 @@ int _mm_evas_renderer_reset(mm_evas_info *evas_info)
        }
 
        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->mp_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);
-                       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_UNKNOWN;
+                       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_UNKNOWN;
+                               }
                        }
-                       else
-                               evas_info->sent_buffer_cnt--;
+                       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;
@@ -541,11 +747,15 @@ int _mm_evas_renderer_reset(mm_evas_info *evas_info)
 
        g_mutex_unlock(&evas_info->idx_lock);
 
+       MMER_FLEAVE();
+
        return ret;
 }
 
-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, rect_info *result)
 {
+       MMER_FENTER();
+
        if (!evas_info || !evas_info->eo) {
                LOGW("there is no evas_info or evas object");
                return;
@@ -613,15 +823,27 @@ void _mm_evas_renderer_update_geometry(mm_evas_info *evas_info, rect_info *resul
                        result->h = evas_info->eo_size.h;
                }
                break;
+       case DISP_GEO_METHOD_CUSTOM_ROI:
+               LOGD("custom roi mode");
+               evas_info->use_ratio = TRUE;
+               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;
+               break;
        default:
                LOGW("unsupported mode.");
                break;
        }
        LOGD("geometry result [%d, %d, %d, %d]", result->x, result->y, result->w, result->h);
+
+       MMER_FLEAVE();
 }
 
-int _mm_evas_renderer_apply_geometry(mm_evas_info *evas_info)
+static int _mm_evas_renderer_apply_geometry(mm_evas_info *evas_info)
 {
+       MMER_FENTER();
+
        if (!evas_info || !evas_info->eo) {
                LOGW("there is no evas_info or evas object");
                return MM_ERROR_NONE;
@@ -632,30 +854,205 @@ int _mm_evas_renderer_apply_geometry(mm_evas_info *evas_info)
 
        if (surf) {
                LOGD("native surface exists");
-//      surf->data.tbm.rot = evas_info->rotate_angle;
-//      surf->data.tbm.flip = evas_info->flip;
+               surf->data.tbm.rot = evas_info->rotate_angle;
+               surf->data.tbm.flip = evas_info->flip;
                evas_object_image_native_surface_set(evas_info->eo, surf);
 
                _mm_evas_renderer_update_geometry(evas_info, &result);
 
                if (evas_info->use_ratio) {
-//          surf->data.tbm.ratio = (float) evas_info->w / evas_info->h;
-                       LOGD("set ratio for letter mode");
+                       surf->data.tbm.ratio = (float) evas_info->w / evas_info->h;
+                       LOGD("set 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_renderer_retrieve_all_packets(mm_evas_info *evas_info, bool keep_screen)
+{
+       MMER_FENTER();
+       MM_CHECK_NULL(evas_info);
+
+       int ret = MM_ERROR_NONE;
+       pid_t pid = getpid();
+       pid_t tid = syscall(SYS_gettid);
+
+       /* write and this API can be called at the same time.
+       so lock is needed for counting sent_buffer_cnt correctly */
+       g_mutex_lock(&evas_info->idx_lock);
+
+       /* make flush buffer */
+       if (keep_screen)
+               ret = _mm_evas_renderer_make_flush_buffer(evas_info);
+       evas_info->keep_screen = keep_screen;
+
+       LOGD("pid [%d], tid [%d]", pid, tid);
+       if (pid == tid) {
+               /* in this case, we deem it is main thread */
+               if (_flush_packets(evas_info) != MM_ERROR_NONE) {
+                       LOGE("flushing packets are failed");
+                       ret = MM_ERROR_UNKNOWN;
+               }
+       } else {
+               /* it will be executed to write flush buffer and destroy media packets in pre_cb */
+               evas_info->retrieve_packet = TRUE;
+       }
+       g_mutex_unlock(&evas_info->idx_lock);
+
+       MMER_FLEAVE();
+
+       return ret;
+}
+
+/* make buffer for copying */
+static int _mm_evas_renderer_make_flush_buffer(mm_evas_info *evas_info)
+{
+       MMER_FENTER();
+
+       if (evas_info->cur_idx == -1) {
+               LOGW("there is no remained buffer");
+               return MM_ERROR_INVALID_ARGUMENT;
+       }
+       media_packet_h packet = evas_info->pkt_info[evas_info->cur_idx].packet;
+       MM_CHECK_NULL(packet);
+
+       flush_info *flush_buffer = NULL;
+       tbm_bo src_bo = NULL;
+       tbm_surface_h src_tbm_surf = NULL;
+       int src_size = 0;
+       tbm_bo bo = NULL;
+       tbm_surface_info_s info = {0};
+       tbm_bo_handle vaddr_src = {0};
+       tbm_bo_handle vaddr_dst = {0};
+       int ret = MM_ERROR_NONE;
+
+       if (evas_info->flush_buffer)
+               _mm_evas_renderer_release_flush_buffer(evas_info);
+
+       /* malloc buffer */
+       flush_buffer = (flush_info *)malloc(sizeof(flush_info));
+       if (flush_buffer == NULL) {
+               LOGE("malloc is failed");
+               return FALSE;
+       }
+       memset(flush_buffer, 0x0, sizeof(flush_info));
+
+       ret = media_packet_get_tbm_surface(packet, &src_tbm_surf);
+       if (ret != MEDIA_PACKET_ERROR_NONE || !src_tbm_surf) {
+               LOGW("get_tbm_surface is failed");
+               goto ERROR;
+       }
+
+       /* get src buffer info */
+       src_bo = tbm_surface_internal_get_bo(src_tbm_surf, 0);
+       src_size = tbm_surface_internal_get_size(src_tbm_surf);
+       if (!src_bo || !src_size) {
+               LOGE("src bo(%p), size(%d)", src_bo, src_size);
+               goto ERROR;
+       }
+       LOGD("src bo(%p), size(%d)", src_bo, src_size);
+
+       /* create tbm surface */
+       info.format = tbm_surface_get_format(src_tbm_surf);
+       flush_buffer->tbm_surf = tbm_surface_create(evas_info->w, evas_info->h, info.format);
+       if (!flush_buffer->tbm_surf) {
+               LOGE("tbm_surf is NULL!!");
+               goto ERROR;
+       }
+
+       /* get bo and size */
+       bo = tbm_surface_internal_get_bo(flush_buffer->tbm_surf, 0);
+       info.size = tbm_surface_internal_get_size(flush_buffer->tbm_surf);
+       if (!bo || !info.size) {
+               LOGE("dst bo(%p), size(%d)", bo, info.size);
+               goto ERROR;
+       }
+       LOGD("dst bo(%p), size(%d)", bo, info.size);
+
+       /* FIXME: each plane should be copied */
+       info.num_planes = tbm_surface_internal_get_num_planes(info.format);
+
+       flush_buffer->bo = bo;
+
+       vaddr_src = tbm_bo_map(src_bo, TBM_DEVICE_CPU, TBM_OPTION_READ|TBM_OPTION_WRITE);
+       vaddr_dst = tbm_bo_map(bo, TBM_DEVICE_CPU, TBM_OPTION_READ|TBM_OPTION_WRITE);
+       if (!vaddr_src.ptr || !vaddr_dst.ptr) {
+               LOGW("get vaddr failed src %p, dst %p", vaddr_src.ptr, vaddr_dst.ptr);
+               if (vaddr_src.ptr)
+                       tbm_bo_unmap(src_bo);
+               if (vaddr_dst.ptr)
+                       tbm_bo_unmap(bo);
+               goto ERROR;
+       } else {
+               memset(vaddr_dst.ptr, 0x0, info.size);
+               LOGW("tbm_bo_map(vaddr) is finished, bo(%p), vaddr(%p)", bo, vaddr_dst.ptr);
+       }
+
+       /* copy buffer */
+       memcpy(vaddr_dst.ptr, vaddr_src.ptr, src_size);
+
+       tbm_bo_unmap(src_bo);
+       tbm_bo_unmap(bo);
+       LOGW("copy is done. tbm surface : %p", flush_buffer->tbm_surf);
+
+       evas_info->flush_buffer = flush_buffer;
+
+       MMER_FLEAVE();
+
+       return MM_ERROR_NONE;
+
+ERROR:
+       if (flush_buffer) {
+               if (flush_buffer->tbm_surf) {
+                       tbm_surface_destroy(flush_buffer->tbm_surf);
+                       flush_buffer->tbm_surf = NULL;
+               }
+
+               free(flush_buffer);
+               flush_buffer = NULL;
+       }
+       return MM_ERROR_UNKNOWN;
+}
+
+/* release flush buffer */
+static void _mm_evas_renderer_release_flush_buffer(mm_evas_info *evas_info)
+{
+       MMER_FENTER();
+
+       LOGW("release FLUSH BUFFER start");
+       if (evas_info->flush_buffer->bo)
+               evas_info->flush_buffer->bo = NULL;
+
+       if (evas_info->flush_buffer->tbm_surf) {
+               tbm_surface_destroy(evas_info->flush_buffer->tbm_surf);
+               evas_info->flush_buffer->tbm_surf = NULL;
+       }
+
+       LOGW("release FLUSH BUFFER done");
+
+       free(evas_info->flush_buffer);
+       evas_info->flush_buffer = NULL;
+
+       MMER_FLEAVE();
+
+       return;
+}
+
 void mm_evas_renderer_write(media_packet_h packet, void *data)
 {
+       MMER_FENTER();
+
        if (!packet) {
                LOGE("packet %p is NULL", packet);
                return;
@@ -683,7 +1080,7 @@ void mm_evas_renderer_write(media_packet_h packet, void *data)
        /* currently we are always checking it */
        if (has && _get_video_size(packet, handle)) {
                /* Attention! if this error occurs, we need to consider managing buffer */
-               if (handle->sent_buffer_cnt > 10) {
+               if (handle->sent_buffer_cnt > 3) {
                        LOGE("too many buffers are not released %d", handle->sent_buffer_cnt);
                        goto ERROR;
 #if 0
@@ -703,10 +1100,19 @@ 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) {
+               if (index == -1)
                        goto ERROR;
-               }
 
+#ifdef _INTERNAL_DEBUG_
+               int ret2 = 0;
+               if ((g_cnt%10 == 0) && (g_cnt < 500))
+                       ret2 = __dump_pkt(packet);
+
+               if (ret2)
+                       LOGW("__dump_pkt() is failed");
+               else
+                       g_cnt++;
+#endif
                /* save previous index */
                handle->pkt_info[index].prev = handle->cur_idx;
                handle->pkt_info[index].packet = packet;
@@ -731,6 +1137,8 @@ void mm_evas_renderer_write(media_packet_h packet, void *data)
        }
        g_mutex_unlock(&handle->idx_lock);
 
+       MMER_FLEAVE();
+
        return;
 ERROR:
        g_mutex_unlock(&handle->idx_lock);
@@ -739,9 +1147,13 @@ INVALID_PARAM:
        if (packet) {
                g_mutex_lock(&handle->mp_lock);
                LOGD("cant write. destroy packet [%p]", packet);
-               if (media_packet_destroy(packet) != MEDIA_PACKET_ERROR_NONE)
-                       LOGE("media_packet_destroy failed %p", packet);
-               packet = NULL;
+               if (handle && handle->packet_rendered_cb) {
+                       handle->packet_rendered_cb(packet, handle->packet_rendered_cb_user);
+               } else {
+                       if (media_packet_destroy(packet) != MEDIA_PACKET_ERROR_NONE)
+                               LOGE("media_packet_destroy failed %p", packet);
+                       packet = NULL;
+               }
                g_mutex_unlock(&handle->mp_lock);
        }
        return;
@@ -749,6 +1161,8 @@ INVALID_PARAM:
 
 int mm_evas_renderer_update_param(MMHandleType handle)
 {
+       MMER_FENTER();
+
        int ret = MM_ERROR_NONE;
        mm_evas_info *evas_info = (mm_evas_info *)handle;
 
@@ -771,18 +1185,30 @@ int mm_evas_renderer_update_param(MMHandleType handle)
                        ret = ecore_pipe_write(evas_info->epipe, &evas_info->visible, UPDATE_VISIBILITY);
                        if (!ret) {
                                LOGW("fail to ecore_pipe_write() for updating visibility\n");
+                               return MM_ERROR_UNKNOWN;
+                       }
+                       evas_info->update_needed = TRUE;
+                       /* FIXME: pause state only */
+                       g_mutex_lock(&evas_info->idx_lock);
+                       ret = ecore_pipe_write(evas_info->epipe, evas_info, UPDATE_TBM_SURF);
+                       if (!ret) {
+                               LOGW("fail to ecore_pipe_write() for updating visibility\n");
                                ret = MM_ERROR_UNKNOWN;
                        } else {
                                ret = MM_ERROR_NONE;
                        }
+                       g_mutex_unlock(&evas_info->idx_lock);
                }
        }
 
+       MMER_FLEAVE();
+
        return ret;
 }
 
 int mm_evas_renderer_create(MMHandleType *handle, Evas_Object *eo)
 {
+       MMER_FENTER();
        MM_CHECK_NULL(handle);
 
        int ret = MM_ERROR_NONE;
@@ -808,6 +1234,7 @@ int mm_evas_renderer_create(MMHandleType *handle, Evas_Object *eo)
 
 int mm_evas_renderer_destroy(MMHandleType *handle)
 {
+       MMER_FENTER();
        MM_CHECK_NULL(handle);
 
        int ret = MM_ERROR_NONE;
@@ -825,11 +1252,15 @@ int mm_evas_renderer_destroy(MMHandleType *handle)
        }
        *handle = NULL;
 
+       MMER_FLEAVE();
+
        return MM_ERROR_NONE;
 }
 
 int mm_evas_renderer_set_visible(MMHandleType handle, bool visible)
 {
+       MMER_FENTER();
+
        int ret = MM_ERROR_NONE;
        mm_evas_info *evas_info = (mm_evas_info *)handle;
 
@@ -855,11 +1286,15 @@ int mm_evas_renderer_set_visible(MMHandleType handle, bool visible)
                LOGW("there is no epipe. we cant update it");
        }
 
+       MMER_FLEAVE();
+
        return ret;
 }
 
 int mm_evas_renderer_get_visible(MMHandleType handle, bool *visible)
 {
+       MMER_FENTER();
+
        mm_evas_info *evas_info = (mm_evas_info *)handle;
 
        if (!evas_info) {
@@ -872,40 +1307,99 @@ int mm_evas_renderer_get_visible(MMHandleType handle, bool *visible)
        else
                *visible = TRUE;
 
+       MMER_FLEAVE();
+
        return MM_ERROR_NONE;
 }
 
 int mm_evas_renderer_set_rotation(MMHandleType handle, int rotate)
 {
+       MMER_FENTER();
+
        int ret = MM_ERROR_NONE;
        mm_evas_info *evas_info = (mm_evas_info *)handle;
+       guint value;
 
        if (!evas_info) {
                LOGW("skip it. it is not evas surface type or handle is not prepared");
                return MM_ERROR_RESOURCE_NOT_INITIALIZED;
        }
 
-       evas_info->rotate_angle = rotate;
-       ret = _mm_evas_renderer_apply_geometry(evas_info);
+       switch (rotate) {
+       case DEGREE_0:
+               value = EVAS_IMAGE_ORIENT_0;
+               break;
+       case DEGREE_90:
+               value = EVAS_IMAGE_ORIENT_90;
+               break;
+       case DEGREE_180:
+               value = EVAS_IMAGE_ORIENT_180;
+               break;
+       case DEGREE_270:
+               value = EVAS_IMAGE_ORIENT_270;
+               break;
+       default:
+               return MM_ERROR_INVALID_ARGUMENT;
+       }
+       if (evas_info->rotate_angle != value) {
+               evas_info->update_needed = TRUE;
+               evas_info->rotate_angle = value;
+       }
+
+       /* FIXME: pause state only */
+       if (evas_info->epipe) {
+               g_mutex_lock(&evas_info->idx_lock);
+               ret = ecore_pipe_write(evas_info->epipe, evas_info, UPDATE_TBM_SURF);
+               if (!ret) {
+                       LOGW("fail to ecore_pipe_write() for updating visibility\n");
+                       ret = MM_ERROR_UNKNOWN;
+               } else {
+                       ret = MM_ERROR_NONE;
+               }
+               g_mutex_unlock(&evas_info->idx_lock);
+       }
+       MMER_FLEAVE();
 
        return ret;
 }
 
 int mm_evas_renderer_get_rotation(MMHandleType handle, int *rotate)
 {
+       MMER_FENTER();
+
        mm_evas_info *evas_info = (mm_evas_info *)handle;
 
        if (!evas_info) {
                LOGW("skip it. it is not evas surface type or handle is not prepared");
                return MM_ERROR_RESOURCE_NOT_INITIALIZED;
        }
-       *rotate = evas_info->rotate_angle;
+
+       switch (evas_info->rotate_angle) {
+       case EVAS_IMAGE_ORIENT_0:
+               *rotate = DEGREE_0;
+               break;
+       case EVAS_IMAGE_ORIENT_90:
+               *rotate = DEGREE_90;
+               break;
+       case EVAS_IMAGE_ORIENT_180:
+               *rotate = DEGREE_180;
+               break;
+       case EVAS_IMAGE_ORIENT_270:
+               *rotate = DEGREE_270;
+               break;
+       default:
+               return MM_ERROR_INVALID_ARGUMENT;
+       }
+
+       MMER_FLEAVE();
 
        return MM_ERROR_NONE;
 }
 
 int mm_evas_renderer_set_geometry(MMHandleType handle, int mode)
 {
+       MMER_FENTER();
+
        int ret = MM_ERROR_NONE;
        mm_evas_info *evas_info = (mm_evas_info *)handle;
 
@@ -913,15 +1407,33 @@ int mm_evas_renderer_set_geometry(MMHandleType handle, int mode)
                LOGW("skip it. it is not evas surface type or handle is not prepared");
                return MM_ERROR_RESOURCE_NOT_INITIALIZED;
        }
+       if (evas_info->display_geometry_method != mode) {
+               evas_info->update_needed = TRUE;
+               evas_info->display_geometry_method = mode;
+       }
 
-       evas_info->display_geometry_method = mode;
-       ret = _mm_evas_renderer_apply_geometry(evas_info);
+       /* ecore_pipe_write is needed, because of setting ratio for letterbox mode */
+       /* FIXME: pause state only */
+       if (evas_info->epipe) {
+               g_mutex_lock(&evas_info->idx_lock);
+               ret = ecore_pipe_write(evas_info->epipe, evas_info, UPDATE_TBM_SURF);
+               if (!ret) {
+                       LOGW("fail to ecore_pipe_write() for updating visibility\n");
+                       ret = MM_ERROR_UNKNOWN;
+               } else {
+                       ret = MM_ERROR_NONE;
+               }
+               g_mutex_unlock(&evas_info->idx_lock);
+       }
+       MMER_FLEAVE();
 
        return ret;
 }
 
 int mm_evas_renderer_get_geometry(MMHandleType handle, int *mode)
 {
+       MMER_FENTER();
+
        mm_evas_info *evas_info = (mm_evas_info *)handle;
 
        if (!evas_info) {
@@ -930,5 +1442,198 @@ int mm_evas_renderer_get_geometry(MMHandleType handle, int *mode)
        }
        *mode = evas_info->display_geometry_method;
 
+       MMER_FLEAVE();
+
+       return MM_ERROR_NONE;
+}
+
+int mm_evas_renderer_set_roi_area(MMHandleType handle, int x, int y, int w, int h)
+{
+       MMER_FENTER();
+
+       int ret = MM_ERROR_NONE;
+       mm_evas_info *evas_info = (mm_evas_info *)handle;
+
+       if (!evas_info) {
+               LOGW("skip it. it is not evas surface type or handle is not prepared");
+               return MM_ERROR_RESOURCE_NOT_INITIALIZED;
+       }
+       if (!w || !h) {
+               LOGW("invalid resolution");
+               return MM_ERROR_INVALID_ARGUMENT;
+       }
+
+       /* display mode is set to DISP_GEO_METHOD_CUSTOM_ROI internally */
+       if (evas_info->display_geometry_method != DISP_GEO_METHOD_CUSTOM_ROI)
+               evas_info->update_needed = TRUE;
+       evas_info->display_geometry_method = DISP_GEO_METHOD_CUSTOM_ROI;
+       evas_info->dst_roi.x = x;
+       evas_info->dst_roi.y = y;
+       evas_info->dst_roi.w = w;
+       evas_info->dst_roi.h = h;
+
+       /* pipe_write could be needed because ratio can be changed on pause state */
+       if (evas_info->epipe) {
+               g_mutex_lock(&evas_info->idx_lock);
+               ret = ecore_pipe_write(evas_info->epipe, evas_info, UPDATE_TBM_SURF);
+               if (!ret) {
+                       LOGW("fail to ecore_pipe_write() for updating visibility\n");
+                       ret = MM_ERROR_UNKNOWN;
+               } else {
+                       ret = MM_ERROR_NONE;
+               }
+               g_mutex_unlock(&evas_info->idx_lock);
+       }
+
+       MMER_FLEAVE();
+
+       return ret;
+}
+
+int mm_evas_renderer_get_roi_area(MMHandleType handle, int *x, int *y, int *w, int *h)
+{
+       MMER_FENTER();
+
+       mm_evas_info *evas_info = (mm_evas_info *)handle;
+
+       if (!evas_info) {
+               LOGW("skip it. it is not evas surface type or handle is not prepared");
+               return MM_ERROR_RESOURCE_NOT_INITIALIZED;
+       }
+       if (evas_info->display_geometry_method != DISP_GEO_METHOD_CUSTOM_ROI) {
+               LOGW("invalid mode");
+               return MM_ERROR_INVALID_ARGUMENT;
+       }
+
+       *x = evas_info->dst_roi.x;
+       *y = evas_info->dst_roi.y;
+       *w = evas_info->dst_roi.w;
+       *h = evas_info->dst_roi.h;
+
+       MMER_FLEAVE();
+
+       return MM_ERROR_NONE;
+}
+
+int mm_evas_renderer_set_flip(MMHandleType handle, int flip)
+{
+       MMER_FENTER();
+
+       int ret = MM_ERROR_NONE;
+       mm_evas_info *evas_info = (mm_evas_info *)handle;
+       guint value;
+
+       if (!evas_info) {
+               LOGW("skip it. it is not evas surface type or handle is not prepared");
+               return MM_ERROR_RESOURCE_NOT_INITIALIZED;
+       }
+
+       switch (flip) {
+       case FLIP_NONE:
+               value = EVAS_IMAGE_ORIENT_NONE;
+               break;
+       case FLIP_HORIZONTAL:
+               value = EVAS_IMAGE_FLIP_HORIZONTAL;
+               break;
+       case FLIP_VERTICAL:
+               value = EVAS_IMAGE_FLIP_VERTICAL;
+               break;
+       case FLIP_BOTH:
+               value = EVAS_IMAGE_ORIENT_180;
+               break;
+       default:
+               return MM_ERROR_INVALID_ARGUMENT;
+       }
+       if (evas_info->flip != value) {
+               evas_info->update_needed = TRUE;
+               evas_info->flip = value;
+       }
+
+       /* FIXME: pause state only */
+       if (evas_info->epipe) {
+               g_mutex_lock(&evas_info->idx_lock);
+               ret = ecore_pipe_write(evas_info->epipe, evas_info, UPDATE_TBM_SURF);
+               if (!ret) {
+                       LOGW("fail to ecore_pipe_write() for updating visibility\n");
+                       ret = MM_ERROR_UNKNOWN;
+               } else {
+                       ret = MM_ERROR_NONE;
+               }
+               g_mutex_unlock(&evas_info->idx_lock);
+       }
+
+       MMER_FLEAVE();
+
+       return ret;
+}
+
+int mm_evas_renderer_get_flip(MMHandleType handle, int *flip)
+{
+       MMER_FENTER();
+
+       mm_evas_info *evas_info = (mm_evas_info *)handle;
+
+       if (!evas_info) {
+               LOGW("skip it. it is not evas surface type or handle is not prepared");
+               return MM_ERROR_RESOURCE_NOT_INITIALIZED;
+       }
+
+       switch (evas_info->flip) {
+       case EVAS_IMAGE_ORIENT_NONE:
+               *flip = FLIP_NONE;
+               break;
+       case EVAS_IMAGE_FLIP_HORIZONTAL:
+               *flip = FLIP_HORIZONTAL;
+               break;
+       case EVAS_IMAGE_FLIP_VERTICAL:
+               *flip = FLIP_VERTICAL;
+               break;
+       case EVAS_IMAGE_ORIENT_180:
+               *flip = FLIP_BOTH;
+               break;
+       default:
+               return MM_ERROR_INVALID_ARGUMENT;
+       }
+
+       MMER_FLEAVE();
+
+       return MM_ERROR_NONE;
+}
+
+int mm_evas_renderer_retrieve_all_packets(MMHandleType handle, bool keep_screen)
+{
+       MMER_FENTER();
+
+       int ret = MM_ERROR_NONE;
+       mm_evas_info *evas_info = (mm_evas_info*) handle;
+
+       if (!evas_info) {
+               LOGW("skip it. it is not evas surface type or player is not prepared");
+               return MM_ERROR_RESOURCE_NOT_INITIALIZED;
+       }
+       ret = _mm_evas_renderer_retrieve_all_packets(evas_info, keep_screen);
+
+       MMER_FLEAVE();
+
+       return ret;
+}
+
+int mm_evas_renderer_set_packet_rendered_callback(MMHandleType handle, mm_evas_renderer_media_packet_rendered_cb callback, void *user_data)
+{
+       MMER_FENTER();
+
+       mm_evas_info *evas_info = (mm_evas_info*) handle;
+
+       if (!evas_info) {
+               LOGW("skip it. it is not evas surface type or player is not prepared");
+               return MM_ERROR_RESOURCE_NOT_INITIALIZED;
+       }
+       evas_info->packet_rendered_cb = callback;
+       evas_info->packet_rendered_cb_user = user_data;
+
+       LOGW("set rendered callback %p, user_data %p", evas_info->packet_rendered_cb, evas_info->packet_rendered_cb_user);
+
+       MMER_FLEAVE();
+
        return MM_ERROR_NONE;
 }