3b47de93f5392bc4b0b4226acd9f5fe84f864fa8
[platform/core/multimedia/libmm-evas-renderer.git] / src / mm_evas_renderer.c
1 /*
2 * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16 #ifdef HAVE_CONFIG_H
17 #include <config.h>
18 #endif
19
20 #include <glib.h>
21
22 #include <sys/types.h>
23 #include <unistd.h>
24 #include <sys/stat.h>
25 #include <string.h>
26 #include <sys/time.h>
27 #include <stdlib.h>
28 #include <dlog.h>
29 #include <mm_error.h>
30 #include <sys/syscall.h>
31 #include "mm_evas_renderer.h"
32
33 #ifdef LOG_TAG
34 #undef LOG_TAG
35 #endif
36 #define LOG_TAG "MM_EVAS_RENDER"
37 //#define _INTERNAL_DEBUG_ /* debug only */
38
39 #if 0
40 #define MMER_FENTER();                                  LOGD("<ENTER>");
41 #define MMER_FLEAVE();                                  LOGD("<LEAVE>");
42 #else
43 #define MMER_FENTER();
44 #define MMER_FLEAVE();
45 #endif
46
47 #define MM_CHECK_NULL(x_var) \
48         if (!x_var) { \
49                 LOGE("[%s] is NULL\n", #x_var); \
50                 return MM_ERROR_INVALID_ARGUMENT; \
51         }
52
53 #define SET_EVAS_OBJECT_EVENT_CALLBACK(x_evas_image_object, x_usr_data) \
54         do { \
55                 if (x_evas_image_object) { \
56                         LOGD("object callback add"); \
57                         evas_object_event_callback_add(x_evas_image_object, EVAS_CALLBACK_DEL, _evas_del_cb, x_usr_data); \
58                         evas_object_event_callback_add(x_evas_image_object, EVAS_CALLBACK_RESIZE, _evas_resize_cb, x_usr_data); \
59                 } \
60         } while (0)
61
62 #define UNSET_EVAS_OBJECT_EVENT_CALLBACK(x_evas_image_object) \
63         do { \
64                 if (x_evas_image_object) { \
65                         LOGD("object callback del"); \
66                         evas_object_event_callback_del(x_evas_image_object, EVAS_CALLBACK_DEL, _evas_del_cb); \
67                         evas_object_event_callback_del(x_evas_image_object, EVAS_CALLBACK_RESIZE, _evas_resize_cb); \
68                 } \
69         } while (0)
70
71 #define SET_EVAS_EVENT_CALLBACK(x_evas, x_usr_data) \
72         do { \
73                 if (x_evas) { \
74                         LOGD("callback add... evas_callback_render_pre.. evas : %p evas_info : %p", x_evas, x_usr_data); \
75                         evas_event_callback_add(x_evas, EVAS_CALLBACK_RENDER_PRE, _evas_render_pre_cb, x_usr_data); \
76                 } \
77         } while (0)
78
79 #define UNSET_EVAS_EVENT_CALLBACK(x_evas) \
80         do { \
81                 if (x_evas) { \
82                         LOGD("callback del... evas_callback_render_pre %p", x_evas); \
83                         evas_event_callback_del(x_evas, EVAS_CALLBACK_RENDER_PRE, _evas_render_pre_cb); \
84                 } \
85         } while (0)
86
87 enum {
88         DISP_GEO_METHOD_LETTER_BOX = 0,
89         DISP_GEO_METHOD_ORIGIN_SIZE,
90         DISP_GEO_METHOD_FULL_SCREEN,
91         DISP_GEO_METHOD_CROPPED_FULL_SCREEN,
92         DISP_GEO_METHOD_ORIGIN_SIZE_OR_LETTER_BOX,
93         DISP_GEO_METHOD_CUSTOM_ROI,
94         DISP_GEO_METHOD_NUM,
95 };
96
97 enum {
98         DEGREE_0 = 0,
99         DEGREE_90,
100         DEGREE_180,
101         DEGREE_270,
102         DEGREE_NUM,
103 };
104
105 enum {
106         FLIP_NONE = 0,
107         FLIP_HORIZONTAL,
108         FLIP_VERTICAL,
109         FLIP_BOTH,
110         FLIP_NUM,
111 };
112
113 #ifdef _INTERNAL_DEBUG_
114 static int g_cnt = 0;
115 static void __print_idx(mm_evas_info *evas_info);
116 static int __dump_pkt(media_packet_h pkt);
117 #endif
118 /* internal */
119 static void _free_previous_packets(mm_evas_info *evas_info);
120 static int _flush_packets(mm_evas_info *evas_info);
121 static int _mm_evas_renderer_create(mm_evas_info **evas_info);
122 static int _mm_evas_renderer_destroy(mm_evas_info **evas_info);
123 static int _mm_evas_renderer_set_info(mm_evas_info *evas_info, Evas_Object *eo);
124 static int _mm_evas_renderer_reset(mm_evas_info *evas_info);
125 static void _mm_evas_renderer_update_geometry(mm_evas_info *evas_info, rect_info *result);
126 static int _mm_evas_renderer_apply_geometry(mm_evas_info *evas_info);
127 static int _mm_evas_renderer_retrieve_all_packets(mm_evas_info *evas_info, bool keep_screen);
128 static int _mm_evas_renderer_make_flush_buffer(mm_evas_info *evas_info);
129 static void _mm_evas_renderer_release_flush_buffer(mm_evas_info *evas_info);
130 static void _mm_evas_renderer_set_callback(mm_evas_info *evas_info);
131 static void _mm_evas_renderer_unset_callback(mm_evas_info *evas_info);
132
133 static void _evas_resize_cb(void *data, Evas *e, Evas_Object *obj, void *event_info)
134 {
135         MMER_FENTER();
136
137         int x, y, w, h, ret;
138         x = y = w = h = 0;
139
140         mm_evas_info *evas_info = data;
141
142         if (!evas_info || !evas_info->eo)
143                 return;
144
145         evas_object_geometry_get(evas_info->eo, &x, &y, &w, &h);
146         if (!w || !h) {
147                 LOGW("evas object size (w:%d,h:%d) was not set", w, h);
148         } else {
149                 evas_info->eo_size.x = x;
150                 evas_info->eo_size.y = y;
151                 evas_info->eo_size.w = w;
152                 evas_info->eo_size.h = h;
153                 LOGW("resize (x:%d, y:%d, w:%d, h:%d)", x, y, w, h);
154                 ret = _mm_evas_renderer_apply_geometry(evas_info);
155                 if (ret != MM_ERROR_NONE)
156                         LOGW("fail to apply geometry info");
157         }
158         MMER_FLEAVE();
159 }
160
161 static void _evas_render_pre_cb(void *data, Evas *e, void *event_info)
162 {
163         MMER_FENTER();
164
165         mm_evas_info *evas_info = data;
166
167         if (!evas_info || !evas_info->eo) {
168                 LOGW("there is no esink info.... esink : %p, or eo is NULL returning", evas_info);
169                 return;
170         }
171
172         /* flush will be executed in this callback normally,
173         because native_surface_set must be called in main thread */
174         if (evas_info->retrieve_packet) {
175                 g_mutex_lock(&evas_info->idx_lock);
176                 if (_flush_packets(evas_info) != MM_ERROR_NONE)
177                         LOGE("flushing packets are failed");
178                 g_mutex_unlock(&evas_info->idx_lock);
179         }
180         MMER_FLEAVE();
181 }
182
183 static void _evas_del_cb(void *data, Evas *e, Evas_Object *obj, void *event_info)
184 {
185         MMER_FENTER();
186
187         mm_evas_info *evas_info = data;
188
189         if (!evas_info || !evas_info->eo)
190                 return;
191
192         if (evas_info->eo) {
193                 _mm_evas_renderer_unset_callback(evas_info);
194                 evas_object_image_data_set(evas_info->eo, NULL);
195                 evas_info->eo = NULL;
196         }
197         MMER_FLEAVE();
198 }
199
200 static void _evas_pipe_cb(void *data, void *buffer, update_info info)
201 {
202         MMER_FENTER();
203
204         mm_evas_info *evas_info = data;
205
206         if (!evas_info) {
207                 LOGW("evas_info is NULL", evas_info);
208                 return;
209         }
210
211         g_mutex_lock(&evas_info->mp_lock);
212
213         if (!evas_info->eo) {
214                 LOGW("evas_info %p", evas_info);
215                 g_mutex_unlock(&evas_info->mp_lock);
216                 return;
217         }
218
219         LOGD("evas_info : %p, evas_info->eo : %p", evas_info, evas_info->eo);
220         if (info == UPDATE_VISIBILITY) {
221                 if (evas_info->visible == VISIBLE_FALSE) {
222                         evas_object_hide(evas_info->eo);
223                         LOGI("object hide..");
224                 } else {
225                         evas_object_show(evas_info->eo);
226                         LOGI("object show.. %d", evas_info->visible);
227                 }
228                 LOGD("[LEAVE]");
229                 g_mutex_unlock(&evas_info->mp_lock);
230                 return;
231         }
232
233         if (info != UPDATE_TBM_SURF) {
234                 LOGW("invalid info type : %d", info);
235                 g_mutex_unlock(&evas_info->mp_lock);
236                 return;
237         }
238
239         if ((evas_info->cur_idx == -1) || !evas_info->pkt_info[evas_info->cur_idx].tbm_surf) {
240                 LOGW("cur_idx %d, tbm_surf may be NULL", evas_info->cur_idx);
241                 g_mutex_unlock(&evas_info->mp_lock);
242                 return;
243         }
244         /* perhaps, it is needed to skip setting when state is pause */
245
246         g_mutex_lock(&evas_info->idx_lock);
247         /* index */
248         gint cur_idx = evas_info->cur_idx;
249         gint prev_idx = evas_info->pkt_info[cur_idx].prev;
250
251         LOGD("received (idx %d, packet %p)", cur_idx, evas_info->pkt_info[cur_idx].packet);
252
253         tbm_format tbm_fmt = tbm_surface_get_format(evas_info->pkt_info[cur_idx].tbm_surf);
254         switch (tbm_fmt) {
255         case TBM_FORMAT_NV12:
256                 LOGD("tbm_surface format : TBM_FORMAT_NV12");
257                 break;
258         case TBM_FORMAT_YUV420:
259                 LOGD("tbm_surface format : TBM_FORMAT_YUV420");
260                 break;
261         default:
262                 LOGW("tbm_surface format : unknown %d", tbm_fmt);
263                 break;
264         }
265
266         Evas_Native_Surface surf = { 0 };
267         surf.type = EVAS_NATIVE_SURFACE_TBM;
268         surf.version = EVAS_NATIVE_SURFACE_VERSION;
269         surf.data.tbm.buffer = evas_info->pkt_info[cur_idx].tbm_surf;
270         surf.data.tbm.rot = evas_info->rotate_angle;
271         surf.data.tbm.flip = evas_info->flip;
272
273         rect_info result = { 0 };
274
275         evas_object_geometry_get(evas_info->eo, &evas_info->eo_size.x, &evas_info->eo_size.y,
276                 &evas_info->eo_size.w, &evas_info->eo_size.h);
277         if (!evas_info->eo_size.w || !evas_info->eo_size.h) {
278                 LOGE("there is no information for evas object size");
279                 goto ERROR;
280         }
281         _mm_evas_renderer_update_geometry(evas_info, &result);
282         if (!result.w || !result.h) {
283                 LOGE("no information about geometry (%d, %d)", result.w, result.h);
284                 goto ERROR;
285         }
286
287         if (evas_info->update_needed) {
288                 /* update geometry on pause state */
289                 evas_object_image_native_surface_set(evas_info->eo, NULL);
290                 evas_info->update_needed = FALSE;
291         }
292
293         if (evas_info->use_ratio) {
294                 surf.data.tbm.ratio = (float) evas_info->w / evas_info->h;
295                 LOGD("set ratio");
296         }
297         evas_object_size_hint_align_set(evas_info->eo, EVAS_HINT_FILL, EVAS_HINT_FILL);
298         evas_object_size_hint_weight_set(evas_info->eo, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
299         if (evas_info->w > 0 && evas_info->h > 0)
300                 evas_object_image_size_set(evas_info->eo, evas_info->w, evas_info->h);
301
302         evas_object_image_native_surface_set(evas_info->eo, &surf);
303         LOGD("native surface set finish");
304
305         if (result.x || result.y)
306                 LOGD("coordinate x, y (%d, %d) for locating video to center", result.x, result.y);
307
308         evas_object_image_fill_set(evas_info->eo, result.x, result.y, result.w, result.h);
309
310         evas_object_image_pixels_dirty_set(evas_info->eo, EINA_TRUE);
311         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);
312
313         /* when _evas_pipe_cb is called sequentially, previous packet and current packet will be the same */
314         if ((prev_idx != -1) && evas_info->pkt_info[prev_idx].packet && (prev_idx != cur_idx))
315                 _free_previous_packets(evas_info);
316
317         g_mutex_unlock(&evas_info->idx_lock);
318         g_mutex_unlock(&evas_info->mp_lock);
319
320         MMER_FLEAVE();
321
322         return;
323
324  ERROR:
325         if ((prev_idx != -1) && evas_info->pkt_info[prev_idx].packet) {
326                 LOGI("cant render");
327                 _free_previous_packets(evas_info);
328         }
329         g_mutex_unlock(&evas_info->idx_lock);
330         g_mutex_unlock(&evas_info->mp_lock);
331 }
332
333 #ifdef _INTERNAL_DEBUG_
334 static void __print_idx(mm_evas_info *evas_info)
335 {
336         gint prev_idx = evas_info->pkt_info[evas_info->cur_idx].prev;
337         LOGE("***** start cur_idx : %d -> prev_idx : %d", evas_info->cur_idx, prev_idx);
338         while (prev_idx != -1) {
339                 LOGE("***** cur_idx : %d -> prev_idx : %d", prev_idx, evas_info->pkt_info[prev_idx].prev);
340                 prev_idx = evas_info->pkt_info[prev_idx].prev;
341         }
342         LOGE("***** end");
343         return;
344 }
345
346 static int __dump_pkt(media_packet_h pkt)
347 {
348         void *data;
349         uint64_t buf_size;
350         char filename[100] = {0};
351         FILE *fp = NULL;
352
353         sprintf(filename, "/tmp/DUMP_IMG_%2.2d.dump", g_cnt);
354         fp = fopen(filename, "wb");
355         if (fp == NULL)
356                 return 1;
357
358         LOGW("DUMP IMG_%2.2d", g_cnt);
359         media_packet_get_buffer_data_ptr(pkt, &data);
360         media_packet_get_buffer_size(pkt, &buf_size);
361         LOGW("input data : %p, size %d\n", data, (int)buf_size);
362         fwrite(data, (int)buf_size, 1, fp);
363         fclose(fp);
364
365         return 0;
366 }
367 #endif
368
369 static void _free_previous_packets(mm_evas_info *evas_info)
370 {
371         MMER_FENTER();
372
373         gint index = evas_info->cur_idx;
374         gint prev_idx = evas_info->pkt_info[index].prev;
375
376         while (prev_idx != -1) {
377                 LOGD("destroy previous packet [%p] idx %d", evas_info->pkt_info[prev_idx].packet, prev_idx);
378                 if (evas_info->packet_rendered_cb) {
379                         evas_info->packet_rendered_cb(evas_info->pkt_info[prev_idx].packet, evas_info->packet_rendered_cb_user);
380                 } else {
381                         if (media_packet_destroy(evas_info->pkt_info[prev_idx].packet) != MEDIA_PACKET_ERROR_NONE)
382                                 LOGE("media_packet_destroy failed %p", evas_info->pkt_info[prev_idx].packet);
383                 }
384                 evas_info->sent_buffer_cnt--;
385                 evas_info->pkt_info[prev_idx].packet = NULL;
386                 evas_info->pkt_info[prev_idx].tbm_surf = NULL;
387                 evas_info->pkt_info[index].prev = -1;
388
389                 /* move index to previous index */
390                 index = prev_idx;
391                 prev_idx = evas_info->pkt_info[prev_idx].prev;
392                 LOGD("sent packet %d", evas_info->sent_buffer_cnt);
393         }
394
395         MMER_FLEAVE();
396
397         return;
398 }
399
400 static int _get_video_size(media_packet_h packet, mm_evas_info *evas_info)
401 {
402         MMER_FENTER();
403
404         media_format_h fmt;
405         if (media_packet_get_format(packet, &fmt) == MEDIA_PACKET_ERROR_NONE) {
406                 int w, h;
407                 if (media_format_get_video_info(fmt, NULL, &w, &h, NULL, NULL) == MEDIA_PACKET_ERROR_NONE) {
408                         LOGD("video width = %d, height =%d", w, h);
409                         evas_info->w = w;
410                         evas_info->h = h;
411                         return true;
412                 } else
413                         LOGW("media_format_get_video_info is failed");
414                 if (media_format_unref(fmt) != MEDIA_PACKET_ERROR_NONE) /* because of media_packet_get_format */
415                         LOGW("media_format_unref is failed");
416         } else {
417                 LOGW("media_packet_get_format is failed");
418         }
419
420         MMER_FLEAVE();
421
422         return false;
423 }
424
425 static int _find_empty_index(mm_evas_info *evas_info)
426 {
427         MMER_FENTER();
428
429         int i;
430         for (i = 0; i < MAX_PACKET_NUM; i++) {
431                 if (!evas_info->pkt_info[i].packet) {
432                         LOGD("selected idx %d", i);
433                         return i;
434                 }
435         }
436         LOGE("there is no empty idx");
437
438         MMER_FLEAVE();
439
440         return -1;
441 }
442
443 static int _flush_packets(mm_evas_info *evas_info)
444 {
445         MMER_FENTER();
446
447         int ret = MM_ERROR_NONE;
448         int ret_mp = MEDIA_PACKET_ERROR_NONE;
449         int i = 0;
450
451         if (!evas_info) {
452                 LOGW("there is no esink info");
453                 return MM_ERROR_INVALID_ARGUMENT;
454         }
455
456         /* update the screen only if visible is true */
457         /* if flush buffer is null, we cant keep screen */
458         if (evas_info->keep_screen && (evas_info->visible != VISIBLE_FALSE) && evas_info->flush_buffer) {
459                 Evas_Native_Surface surf = { 0 };
460                 rect_info result = { 0 };
461                 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);
462                 if (!evas_info->eo_size.w || !evas_info->eo_size.h) {
463                         LOGE("there is no information for evas object size");
464                         return MM_ERROR_INVALID_ARGUMENT;
465                 }
466                 _mm_evas_renderer_update_geometry(evas_info, &result);
467                 if (!result.w || !result.h) {
468                         LOGE("no information about geometry (%d, %d)", result.w, result.h);
469                         return MM_ERROR_INVALID_ARGUMENT;
470                 }
471
472                 if (evas_info->use_ratio) {
473                         surf.data.tbm.ratio = (float) evas_info->w / evas_info->h;
474                         LOGD("set ratio");
475                 }
476                 evas_object_size_hint_align_set(evas_info->eo, EVAS_HINT_FILL, EVAS_HINT_FILL);
477                 evas_object_size_hint_weight_set(evas_info->eo, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
478                 if (evas_info->w > 0 && evas_info->h > 0)
479                         evas_object_image_size_set(evas_info->eo, evas_info->w, evas_info->h);
480
481                 if (result.x || result.y)
482                         LOGD("coordinate x, y (%d, %d) for locating video to center", result.x, result.y);
483
484                 evas_object_image_fill_set(evas_info->eo, result.x, result.y, result.w, result.h);
485
486                 /* set flush buffer */
487                 surf.type = EVAS_NATIVE_SURFACE_TBM;
488                 surf.version = EVAS_NATIVE_SURFACE_VERSION;
489                 surf.data.tbm.buffer = evas_info->flush_buffer->tbm_surf;
490                 surf.data.tbm.rot = evas_info->rotate_angle;
491                 surf.data.tbm.flip = evas_info->flip;
492                 evas_object_image_native_surface_set(evas_info->eo, &surf);
493
494                 LOGD("flush_buffer surf(%p), rotate(%d), flip(%d)", evas_info->flush_buffer->tbm_surf, evas_info->rotate_angle, evas_info->flip);
495         } else {
496                 /* unset evas native surface for displaying black screen */
497                 evas_object_image_native_surface_set(evas_info->eo, NULL);
498                 evas_object_image_data_set(evas_info->eo, NULL);
499         }
500         LOGD("sent packet %d", evas_info->sent_buffer_cnt);
501
502         /* destroy all packets */
503         g_mutex_lock(&evas_info->mp_lock);
504         for (i = 0; i < MAX_PACKET_NUM; i++) {
505                 if (evas_info->pkt_info[i].packet) {
506                         LOGD("destroy packet [%p]", evas_info->pkt_info[i].packet);
507                         if (evas_info->packet_rendered_cb) {
508                                 evas_info->packet_rendered_cb(evas_info->pkt_info[i].packet, evas_info->packet_rendered_cb_user);
509                         } else {
510                                 ret_mp = media_packet_destroy(evas_info->pkt_info[i].packet);
511                                 if (ret_mp != MEDIA_PACKET_ERROR_NONE) {
512                                         LOGW("media_packet_destroy failed %p", evas_info->pkt_info[i].packet);
513                                         ret = MM_ERROR_UNKNOWN;
514                                 }
515                         }
516                         evas_info->sent_buffer_cnt--;
517                         evas_info->pkt_info[i].packet = NULL;
518                         evas_info->pkt_info[i].tbm_surf = NULL;
519                         evas_info->pkt_info[i].prev = -1;
520                 }
521         }
522
523         if (evas_info->sent_buffer_cnt != 0)
524                 LOGE("it should be 0 --> [%d]", evas_info->sent_buffer_cnt);
525         evas_info->sent_buffer_cnt = 0;
526         evas_info->cur_idx = -1;
527         g_mutex_unlock(&evas_info->mp_lock);
528
529         evas_object_image_pixels_dirty_set(evas_info->eo, EINA_TRUE);
530         evas_info->retrieve_packet = FALSE;
531
532         MMER_FLEAVE();
533
534         return ret;
535 }
536
537 #if 0
538 int _reset_pipe(mm_evas_info *evas_info)
539 {
540         int i = 0;
541         int ret = MM_ERROR_NONE;
542         int ret_mp = MEDIA_PACKET_ERROR_NONE;
543
544         /* delete old pipe */
545         if (evas_info->epipe) {
546                 LOGD("pipe %p will be deleted", evas_info->epipe);
547                 ecore_pipe_del(evas_info->epipe);
548                 evas_info->epipe = NULL;
549         }
550
551         for (i = 0; i < MAX_PACKET_NUM; i++) {
552                 if (evas_info->pkt_info[i].packet) {
553                         /* destroy all packets */
554                         LOGD("destroy packet [%p]", evas_info->pkt_info[i].packet);
555                         if (evas_info->packet_rendered_cb) {
556                                 evas_info->packet_rendered_cb(evas_info->pkt_info[i].packet, evas_info->packet_rendered_cb_user);
557                         } else {
558                                 ret_mp = media_packet_destroy(evas_info->pkt_info[i].packet);
559                                 if (ret_mp != MEDIA_PACKET_ERROR_NONE) {
560                                         LOGW("media_packet_destroy failed %p", evas_info->pkt_info[i].packet);
561                                         ret = MM_ERROR_UNKNOWN;
562                                 }
563                         }
564                         evas_info->sent_buffer_cnt--;
565                         evas_info->pkt_info[i].packet = NULL;
566                         evas_info->pkt_info[i].tbm_surf = NULL;
567                         evas_info->pkt_info[i].prev = -1;
568                 }
569         }
570
571         if (evas_info->sent_buffer_cnt != 0)
572                 LOGE("it should be 0 --> [%d]", evas_info->sent_buffer_cnt);
573         evas_info->sent_buffer_cnt = 0;
574         evas_info->cur_idx = -1;
575
576         /* make new pipe */
577         if (!evas_info->epipe) {
578                 evas_info->epipe = ecore_pipe_add((Ecore_Pipe_Cb) _evas_pipe_cb, evas_info);
579                 if (!evas_info->epipe) {
580                         LOGE("pipe is not created");
581                         ret = MM_ERROR_UNKNOWN;
582                 }
583                 LOGD("created pipe %p", evas_info->epipe);
584         }
585
586         return ret;
587 }
588 #endif
589
590 static void _mm_evas_renderer_set_callback(mm_evas_info *evas_info)
591 {
592         MMER_FENTER();
593         if (evas_info->eo) {
594                 SET_EVAS_OBJECT_EVENT_CALLBACK(evas_info->eo, evas_info);
595                 SET_EVAS_EVENT_CALLBACK(evas_object_evas_get(evas_info->eo), evas_info);
596         }
597         MMER_FLEAVE();
598 }
599
600 static void _mm_evas_renderer_unset_callback(mm_evas_info *evas_info)
601 {
602         MMER_FENTER();
603         if (evas_info->eo) {
604                 UNSET_EVAS_OBJECT_EVENT_CALLBACK(evas_info->eo);
605                 UNSET_EVAS_EVENT_CALLBACK(evas_object_evas_get(evas_info->eo));
606         }
607         MMER_FLEAVE();
608 }
609
610 static int _mm_evas_renderer_create(mm_evas_info **evas_info)
611 {
612         MMER_FENTER();
613
614         mm_evas_info *ptr = NULL;
615         ptr = g_malloc0(sizeof(mm_evas_info));
616
617         if (!ptr) {
618                 LOGE("Cannot allocate memory for evas_info\n");
619                 goto ERROR;
620         } else {
621                 *evas_info = ptr;
622                 LOGD("Success create evas_info(%p)", *evas_info);
623         }
624         g_mutex_init(&ptr->mp_lock);
625         g_mutex_init(&ptr->idx_lock);
626
627         MMER_FLEAVE();
628
629         return MM_ERROR_NONE;
630
631  ERROR:
632         *evas_info = NULL;
633         return MM_ERROR_OUT_OF_STORAGE;
634 }
635
636 static int _mm_evas_renderer_destroy(mm_evas_info **evas_info)
637 {
638         MMER_FENTER();
639
640         mm_evas_info *ptr = (mm_evas_info *)*evas_info;
641         MM_CHECK_NULL(ptr);
642         int ret = MM_ERROR_NONE;
643
644         LOGD("finalize evas_info %p", ptr);
645
646         ret = _mm_evas_renderer_reset(ptr);
647         g_mutex_clear(&ptr->mp_lock);
648         g_mutex_clear(&ptr->idx_lock);
649
650         g_free(ptr);
651         ptr = NULL;
652
653         MMER_FLEAVE();
654
655         return ret;
656 }
657
658 static int _mm_evas_renderer_set_info(mm_evas_info *evas_info, Evas_Object *eo)
659 {
660         MMER_FENTER();
661         MM_CHECK_NULL(evas_info);
662         MM_CHECK_NULL(eo);
663         g_mutex_lock(&evas_info->idx_lock);
664
665         LOGD("set evas_info");
666         int i;
667         for (i = 0; i < MAX_PACKET_NUM; i++) {
668                 evas_info->pkt_info[i].packet = NULL;
669                 evas_info->pkt_info[i].tbm_surf = NULL;
670                 evas_info->pkt_info[i].prev = -1;
671         }
672         evas_info->cur_idx = -1;
673         evas_info->dst_roi.x = evas_info->dst_roi.y = evas_info->dst_roi.w = evas_info->dst_roi.h = 0;
674         evas_info->eo = eo;
675         evas_info->epipe = ecore_pipe_add((Ecore_Pipe_Cb) _evas_pipe_cb, evas_info);
676         if (!evas_info->epipe) {
677                 LOGE("pipe is not created");
678                 g_mutex_unlock(&evas_info->idx_lock);
679                 return MM_ERROR_UNKNOWN;
680         }
681         LOGD("created pipe %p", evas_info->epipe);
682         _mm_evas_renderer_set_callback(evas_info);
683
684         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);
685         LOGI("evas object %p (%d, %d, %d, %d)", evas_info->eo, evas_info->eo_size.x, evas_info->eo_size.y, evas_info->eo_size.w, evas_info->eo_size.h);
686
687         g_mutex_unlock(&evas_info->idx_lock);
688
689         MMER_FLEAVE();
690
691         return MM_ERROR_NONE;
692 }
693
694 static int _mm_evas_renderer_reset(mm_evas_info *evas_info)
695 {
696         MMER_FENTER();
697         MM_CHECK_NULL(evas_info);
698         g_mutex_lock(&evas_info->idx_lock);
699
700         int i;
701         int ret = MM_ERROR_NONE;
702         int ret_mp = MEDIA_PACKET_ERROR_NONE;
703
704         if (evas_info->eo) {
705                 _mm_evas_renderer_unset_callback(evas_info);
706                 evas_object_image_data_set(evas_info->eo, NULL);
707                 evas_info->eo = NULL;
708         }
709         if (evas_info->epipe) {
710                 LOGD("pipe %p will be deleted", evas_info->epipe);
711                 ecore_pipe_del(evas_info->epipe);
712                 evas_info->epipe = NULL;
713         }
714
715         evas_info->eo_size.x = evas_info->eo_size.y = evas_info->eo_size.w = evas_info->eo_size.h = 0;
716         evas_info->dst_roi.x = evas_info->dst_roi.y = evas_info->dst_roi.w = evas_info->dst_roi.h = 0;
717         evas_info->w = evas_info->h = 0;
718
719         if (evas_info->flush_buffer)
720                 _mm_evas_renderer_release_flush_buffer(evas_info);
721
722         g_mutex_lock(&evas_info->mp_lock);
723         for (i = 0; i < MAX_PACKET_NUM; i++) {
724                 if (evas_info->pkt_info[i].packet) {
725                         /* destroy all packets */
726                         LOGD("destroy packet [%p]", evas_info->pkt_info[i].packet);
727                         if (evas_info->packet_rendered_cb) {
728                                 evas_info->packet_rendered_cb(evas_info->pkt_info[i].packet, evas_info->packet_rendered_cb_user);
729                         } else {
730                                 ret_mp = media_packet_destroy(evas_info->pkt_info[i].packet);
731                                 if (ret_mp != MEDIA_PACKET_ERROR_NONE) {
732                                         LOGW("media_packet_destroy failed %p", evas_info->pkt_info[i].packet);
733                                         ret = MM_ERROR_UNKNOWN;
734                                 }
735                         }
736                         evas_info->sent_buffer_cnt--;
737                         evas_info->pkt_info[i].packet = NULL;
738                         evas_info->pkt_info[i].tbm_surf = NULL;
739                         evas_info->pkt_info[i].prev = -1;
740                 }
741         }
742         g_mutex_unlock(&evas_info->mp_lock);
743         if (evas_info->sent_buffer_cnt != 0)
744                 LOGE("it should be 0 --> [%d]", evas_info->sent_buffer_cnt);
745         evas_info->sent_buffer_cnt = 0;
746         evas_info->cur_idx = -1;
747
748         g_mutex_unlock(&evas_info->idx_lock);
749
750         MMER_FLEAVE();
751
752         return ret;
753 }
754
755 static void _mm_evas_renderer_update_geometry(mm_evas_info *evas_info, rect_info *result)
756 {
757         MMER_FENTER();
758
759         if (!evas_info || !evas_info->eo) {
760                 LOGW("there is no evas_info or evas object");
761                 return;
762         }
763         if (!result) {
764                 LOGW("there is no rect info");
765                 return;
766         }
767
768         result->x = 0;
769         result->y = 0;
770
771         switch (evas_info->display_geometry_method) {
772         case DISP_GEO_METHOD_LETTER_BOX:
773                 /* set black padding for letter box mode */
774                 LOGD("letter box mode");
775                 evas_info->use_ratio = TRUE;
776                 result->w = evas_info->eo_size.w;
777                 result->h = evas_info->eo_size.h;
778                 break;
779         case DISP_GEO_METHOD_ORIGIN_SIZE:
780                 LOGD("origin size mode");
781                 evas_info->use_ratio = FALSE;
782                 /* set coordinate for each case */
783                 result->x = (evas_info->eo_size.w - evas_info->w) / 2;
784                 result->y = (evas_info->eo_size.h - evas_info->h) / 2;
785                 result->w = evas_info->w;
786                 result->h = evas_info->h;
787                 break;
788         case DISP_GEO_METHOD_FULL_SCREEN:
789                 LOGD("full screen mode");
790                 evas_info->use_ratio = FALSE;
791                 result->w = evas_info->eo_size.w;
792                 result->h = evas_info->eo_size.h;
793                 break;
794         case DISP_GEO_METHOD_CROPPED_FULL_SCREEN:
795                 LOGD("cropped full screen mode");
796                 evas_info->use_ratio = FALSE;
797                 /* compare evas object's ratio with video's */
798                 if ((evas_info->eo_size.w / evas_info->eo_size.h) > (evas_info->w / evas_info->h)) {
799                         result->w = evas_info->eo_size.w;
800                         result->h = evas_info->eo_size.w * evas_info->h / evas_info->w;
801                         result->y = -(result->h - evas_info->eo_size.h) / 2;
802                 } else {
803                         result->w = evas_info->eo_size.h * evas_info->w / evas_info->h;
804                         result->h = evas_info->eo_size.h;
805                         result->x = -(result->w - evas_info->eo_size.w) / 2;
806                 }
807                 break;
808         case DISP_GEO_METHOD_ORIGIN_SIZE_OR_LETTER_BOX:
809                 LOGD("origin size or letter box mode");
810                 /* if video size is smaller than evas object's, it will be set to origin size mode */
811                 if ((evas_info->eo_size.w > evas_info->w) && (evas_info->eo_size.h > evas_info->h)) {
812                         LOGD("origin size mode");
813                         evas_info->use_ratio = FALSE;
814                         /* set coordinate for each case */
815                         result->x = (evas_info->eo_size.w - evas_info->w) / 2;
816                         result->y = (evas_info->eo_size.h - evas_info->h) / 2;
817                         result->w = evas_info->w;
818                         result->h = evas_info->h;
819                 } else {
820                         LOGD("letter box mode");
821                         evas_info->use_ratio = TRUE;
822                         result->w = evas_info->eo_size.w;
823                         result->h = evas_info->eo_size.h;
824                 }
825                 break;
826         case DISP_GEO_METHOD_CUSTOM_ROI:
827                 LOGD("custom roi mode");
828                 evas_info->use_ratio = TRUE;
829                 result->x = evas_info->dst_roi.x;
830                 result->y = evas_info->dst_roi.y;
831                 result->w = evas_info->dst_roi.w;
832                 result->h = evas_info->dst_roi.h;
833                 break;
834         default:
835                 LOGW("unsupported mode.");
836                 break;
837         }
838         LOGD("geometry result [%d, %d, %d, %d]", result->x, result->y, result->w, result->h);
839
840         MMER_FLEAVE();
841 }
842
843 static int _mm_evas_renderer_apply_geometry(mm_evas_info *evas_info)
844 {
845         MMER_FENTER();
846
847         if (!evas_info || !evas_info->eo) {
848                 LOGW("there is no evas_info or evas object");
849                 return MM_ERROR_NONE;
850         }
851
852         Evas_Native_Surface *surf = evas_object_image_native_surface_get(evas_info->eo);
853         rect_info result = { 0 };
854
855         if (surf) {
856                 LOGD("native surface exists");
857                 surf->data.tbm.rot = evas_info->rotate_angle;
858                 surf->data.tbm.flip = evas_info->flip;
859                 evas_object_image_native_surface_set(evas_info->eo, surf);
860
861                 _mm_evas_renderer_update_geometry(evas_info, &result);
862
863                 if (evas_info->use_ratio) {
864                         surf->data.tbm.ratio = (float) evas_info->w / evas_info->h;
865                         LOGD("set ratio");
866                 }
867                 if (result.x || result.y)
868                         LOGD("coordinate x, y (%d, %d) for locating video to center", result.x, result.y);
869
870                 evas_object_image_fill_set(evas_info->eo, result.x, result.y, result.w, result.h);
871
872                 return MM_ERROR_NONE;
873         } else
874                 LOGW("there is no surf");
875         /* FIXME: before pipe_cb is invoked, apply_geometry can be called. */
876
877         MMER_FLEAVE();
878
879         return MM_ERROR_NONE;
880 }
881
882 static int _mm_evas_renderer_retrieve_all_packets(mm_evas_info *evas_info, bool keep_screen)
883 {
884         MMER_FENTER();
885         MM_CHECK_NULL(evas_info);
886
887         int ret = MM_ERROR_NONE;
888         pid_t pid = getpid();
889         pid_t tid = syscall(SYS_gettid);
890
891         /* write and this API can be called at the same time.
892         so lock is needed for counting sent_buffer_cnt correctly */
893         g_mutex_lock(&evas_info->idx_lock);
894
895         /* make flush buffer */
896         if (keep_screen)
897                 ret = _mm_evas_renderer_make_flush_buffer(evas_info);
898         evas_info->keep_screen = keep_screen;
899
900         LOGD("pid [%d], tid [%d]", pid, tid);
901         if (pid == tid) {
902                 /* in this case, we deem it is main thread */
903                 if (_flush_packets(evas_info) != MM_ERROR_NONE) {
904                         LOGE("flushing packets are failed");
905                         ret = MM_ERROR_UNKNOWN;
906                 }
907         } else {
908                 /* it will be executed to write flush buffer and destroy media packets in pre_cb */
909                 evas_info->retrieve_packet = TRUE;
910         }
911         g_mutex_unlock(&evas_info->idx_lock);
912
913         MMER_FLEAVE();
914
915         return ret;
916 }
917
918 /* make buffer for copying */
919 static int _mm_evas_renderer_make_flush_buffer(mm_evas_info *evas_info)
920 {
921         MMER_FENTER();
922
923         if (evas_info->cur_idx == -1) {
924                 LOGW("there is no remained buffer");
925                 return MM_ERROR_INVALID_ARGUMENT;
926         }
927         media_packet_h packet = evas_info->pkt_info[evas_info->cur_idx].packet;
928         MM_CHECK_NULL(packet);
929
930         flush_info *flush_buffer = NULL;
931         tbm_bo src_bo = NULL;
932         tbm_surface_h src_tbm_surf = NULL;
933         int src_size = 0;
934         tbm_bo bo = NULL;
935         tbm_surface_info_s info = {0};
936         tbm_bo_handle vaddr_src = {0};
937         tbm_bo_handle vaddr_dst = {0};
938         int ret = MM_ERROR_NONE;
939
940         if (evas_info->flush_buffer)
941                 _mm_evas_renderer_release_flush_buffer(evas_info);
942
943         /* malloc buffer */
944         flush_buffer = (flush_info *)malloc(sizeof(flush_info));
945         if (flush_buffer == NULL) {
946                 LOGE("malloc is failed");
947                 return FALSE;
948         }
949         memset(flush_buffer, 0x0, sizeof(flush_info));
950         LOGD("flush_buffer %p is allocated", flush_buffer);
951
952         ret = media_packet_get_tbm_surface(packet, &src_tbm_surf);
953         if (ret != MEDIA_PACKET_ERROR_NONE || !src_tbm_surf) {
954                 LOGW("get_tbm_surface is failed");
955                 goto ERROR;
956         }
957
958         /* get src buffer info */
959         src_bo = tbm_surface_internal_get_bo(src_tbm_surf, 0);
960         src_size = tbm_surface_internal_get_size(src_tbm_surf);
961         if (!src_bo || !src_size) {
962                 LOGE("src bo(%p), size(%d)", src_bo, src_size);
963                 goto ERROR;
964         }
965         LOGD("src bo(%p), size(%d)", src_bo, src_size);
966
967         /* create tbm surface */
968         info.format = tbm_surface_get_format(src_tbm_surf);
969         flush_buffer->tbm_surf = tbm_surface_create(evas_info->w, evas_info->h, info.format);
970         if (!flush_buffer->tbm_surf) {
971                 LOGE("tbm_surf is NULL!!");
972                 goto ERROR;
973         }
974
975         /* get bo and size */
976         bo = tbm_surface_internal_get_bo(flush_buffer->tbm_surf, 0);
977         info.size = tbm_surface_internal_get_size(flush_buffer->tbm_surf);
978         if (!bo || !info.size) {
979                 LOGE("dst bo(%p), size(%d)", bo, info.size);
980                 goto ERROR;
981         }
982         LOGD("dst bo(%p), size(%d)", bo, info.size);
983
984         /* FIXME: each plane should be copied */
985         info.num_planes = tbm_surface_internal_get_num_planes(info.format);
986
987         flush_buffer->bo = bo;
988
989         vaddr_src = tbm_bo_map(src_bo, TBM_DEVICE_CPU, TBM_OPTION_READ|TBM_OPTION_WRITE);
990         vaddr_dst = tbm_bo_map(bo, TBM_DEVICE_CPU, TBM_OPTION_READ|TBM_OPTION_WRITE);
991         if (!vaddr_src.ptr || !vaddr_dst.ptr) {
992                 LOGW("get vaddr failed src %p, dst %p", vaddr_src.ptr, vaddr_dst.ptr);
993                 if (vaddr_src.ptr)
994                         tbm_bo_unmap(src_bo);
995                 if (vaddr_dst.ptr)
996                         tbm_bo_unmap(bo);
997                 goto ERROR;
998         } else {
999                 memset(vaddr_dst.ptr, 0x0, info.size);
1000                 LOGW("tbm_bo_map(vaddr) is finished, bo(%p), vaddr(%p)", bo, vaddr_dst.ptr);
1001         }
1002
1003         /* copy buffer */
1004         memcpy(vaddr_dst.ptr, vaddr_src.ptr, src_size);
1005
1006         tbm_bo_unmap(src_bo);
1007         tbm_bo_unmap(bo);
1008         LOGW("copy is done. tbm surface : %p", flush_buffer->tbm_surf);
1009
1010         evas_info->flush_buffer = flush_buffer;
1011
1012         MMER_FLEAVE();
1013
1014         return MM_ERROR_NONE;
1015
1016 ERROR:
1017         if (flush_buffer) {
1018                 if (flush_buffer->tbm_surf) {
1019                         tbm_surface_destroy(flush_buffer->tbm_surf);
1020                         flush_buffer->tbm_surf = NULL;
1021                 }
1022
1023                 free(flush_buffer);
1024                 flush_buffer = NULL;
1025         }
1026         return MM_ERROR_UNKNOWN;
1027 }
1028
1029 /* release flush buffer */
1030 static void _mm_evas_renderer_release_flush_buffer(mm_evas_info *evas_info)
1031 {
1032         MMER_FENTER();
1033
1034         LOGW("release FLUSH BUFFER start");
1035         if (evas_info->flush_buffer->bo)
1036                 evas_info->flush_buffer->bo = NULL;
1037
1038         if (evas_info->flush_buffer->tbm_surf) {
1039                 tbm_surface_destroy(evas_info->flush_buffer->tbm_surf);
1040                 evas_info->flush_buffer->tbm_surf = NULL;
1041         }
1042
1043         LOGW("release FLUSH BUFFER done");
1044
1045         free(evas_info->flush_buffer);
1046         evas_info->flush_buffer = NULL;
1047
1048         MMER_FLEAVE();
1049
1050         return;
1051 }
1052
1053 void mm_evas_renderer_write(media_packet_h packet, void *data)
1054 {
1055         MMER_FENTER();
1056
1057         if (!packet) {
1058                 LOGE("packet %p is NULL", packet);
1059                 return;
1060         }
1061         mm_evas_info *handle = (mm_evas_info *)data;
1062         int ret = MEDIA_PACKET_ERROR_NONE;
1063         bool has;
1064         tbm_surface_h tbm_surf;
1065         gint index;
1066
1067         LOGD("packet [%p]", packet);
1068
1069         if (!data || !handle) {
1070                 LOGE("handle %p or evas_info %p is NULL", data, handle);
1071                 goto INVALID_PARAM;
1072         }
1073         g_mutex_lock(&handle->idx_lock);
1074
1075         ret = media_packet_has_tbm_surface_buffer(packet, &has);
1076         if (ret != MEDIA_PACKET_ERROR_NONE) {
1077                 LOGW("has_tbm_surface is failed");
1078                 goto ERROR;
1079         }
1080         /* FIXME: when setCaps occurs, _get_video_size should be called */
1081         /* currently we are always checking it */
1082         if (has && _get_video_size(packet, handle)) {
1083                 /* Attention! if this error occurs, we need to consider managing buffer */
1084                 if (handle->sent_buffer_cnt > 3) {
1085                         LOGE("too many buffers are not released %d", handle->sent_buffer_cnt);
1086                         goto ERROR;
1087 #if 0
1088                         /* FIXME: fix this logic */
1089                         /* destroy all media packets and reset pipe at present */
1090                         /* Attention! it might free buffer that is being rendered */
1091                         g_mutex_lock(&handle->mp_lock);
1092                         _reset_pipe(handle);
1093                         g_mutex_unlock(&handle->mp_lock);
1094 #endif
1095                 }
1096                 ret = media_packet_get_tbm_surface(packet, &tbm_surf);
1097                 if (ret != MEDIA_PACKET_ERROR_NONE || !tbm_surf) {
1098                         LOGW("get_tbm_surface is failed");
1099                         goto ERROR;
1100                 }
1101
1102                 /* find new index for current packet */
1103                 index = _find_empty_index(handle);
1104                 if (index == -1)
1105                         goto ERROR;
1106
1107 #ifdef _INTERNAL_DEBUG_
1108                 int ret2 = 0;
1109                 if ((g_cnt%10 == 0) && (g_cnt < 500))
1110                         ret2 = __dump_pkt(packet);
1111
1112                 if (ret2)
1113                         LOGW("__dump_pkt() is failed");
1114                 else
1115                         g_cnt++;
1116 #endif
1117                 /* save previous index */
1118                 handle->pkt_info[index].prev = handle->cur_idx;
1119                 handle->pkt_info[index].packet = packet;
1120                 handle->pkt_info[index].tbm_surf = tbm_surf;
1121                 handle->cur_idx = index;
1122                 handle->sent_buffer_cnt++;
1123                 LOGD("sent packet %d", handle->sent_buffer_cnt);
1124
1125                 ret = ecore_pipe_write(handle->epipe, handle, UPDATE_TBM_SURF);
1126                 if (!ret) {
1127                         handle->pkt_info[index].packet = NULL;
1128                         handle->pkt_info[index].tbm_surf = NULL;
1129                         handle->pkt_info[index].prev = -1;
1130                         handle->cur_idx = handle->pkt_info[index].prev;
1131                         handle->sent_buffer_cnt--;
1132                         LOGW("Failed to ecore_pipe_write() for updating tbm surf\n");
1133                         goto ERROR;
1134                 }
1135         } else {
1136                 LOGW("no tbm_surf");
1137                 goto ERROR;
1138         }
1139         g_mutex_unlock(&handle->idx_lock);
1140
1141         MMER_FLEAVE();
1142
1143         return;
1144 ERROR:
1145         g_mutex_unlock(&handle->idx_lock);
1146 INVALID_PARAM:
1147         /* destroy media_packet immediately */
1148         if (packet) {
1149                 g_mutex_lock(&handle->mp_lock);
1150                 LOGD("cant write. destroy packet [%p]", packet);
1151                 if (handle->packet_rendered_cb) {
1152                         handle->packet_rendered_cb(packet, handle->packet_rendered_cb_user);
1153                 } else {
1154                         if (media_packet_destroy(packet) != MEDIA_PACKET_ERROR_NONE)
1155                                 LOGE("media_packet_destroy failed %p", packet);
1156                         packet = NULL;
1157                 }
1158                 g_mutex_unlock(&handle->mp_lock);
1159         }
1160         return;
1161 }
1162
1163 int mm_evas_renderer_update_param(MMHandleType handle)
1164 {
1165         MMER_FENTER();
1166
1167         int ret = MM_ERROR_NONE;
1168         mm_evas_info *evas_info = (mm_evas_info *)handle;
1169
1170         if (!evas_info) {
1171                 LOGW("skip it. it is not evas surface type.");
1172                 return ret;
1173         }
1174
1175         /* when handle is realized, we need to update all properties */
1176         if (evas_info) {
1177                 LOGD("set video param : evas-object %x, method %d", evas_info->eo, evas_info->display_geometry_method);
1178                 LOGD("set video param : visible %d", evas_info->visible);
1179                 LOGD("set video param : rotate %d", evas_info->rotate_angle);
1180
1181                 ret = _mm_evas_renderer_apply_geometry(evas_info);
1182                 if (ret != MM_ERROR_NONE)
1183                         return ret;
1184
1185                 if (evas_info->epipe) {
1186                         ret = ecore_pipe_write(evas_info->epipe, &evas_info->visible, UPDATE_VISIBILITY);
1187                         if (!ret) {
1188                                 LOGW("fail to ecore_pipe_write() for updating visibility\n");
1189                                 return MM_ERROR_UNKNOWN;
1190                         }
1191                         evas_info->update_needed = TRUE;
1192                         /* FIXME: pause state only */
1193                         g_mutex_lock(&evas_info->idx_lock);
1194                         ret = ecore_pipe_write(evas_info->epipe, evas_info, UPDATE_TBM_SURF);
1195                         if (!ret) {
1196                                 LOGW("fail to ecore_pipe_write() for updating visibility\n");
1197                                 ret = MM_ERROR_UNKNOWN;
1198                         } else {
1199                                 ret = MM_ERROR_NONE;
1200                         }
1201                         g_mutex_unlock(&evas_info->idx_lock);
1202                 }
1203         }
1204
1205         MMER_FLEAVE();
1206
1207         return ret;
1208 }
1209
1210 int mm_evas_renderer_create(MMHandleType *handle, Evas_Object *eo)
1211 {
1212         MMER_FENTER();
1213         MM_CHECK_NULL(handle);
1214
1215         int ret = MM_ERROR_NONE;
1216         mm_evas_info *evas_info = NULL;
1217
1218         ret = _mm_evas_renderer_create(&evas_info);
1219         if (ret != MM_ERROR_NONE) {
1220                 LOGE("fail to create evas_info");
1221                 return ret;
1222         }
1223         ret = _mm_evas_renderer_set_info(evas_info, eo);
1224         if (ret != MM_ERROR_NONE) {
1225                 LOGE("fail to init evas_info");
1226                 if (_mm_evas_renderer_destroy(&evas_info) != MM_ERROR_NONE)
1227                         LOGE("fail to destroy evas_info");
1228                 return ret;
1229         }
1230
1231         *handle = (MMHandleType)evas_info;
1232
1233         return MM_ERROR_NONE;
1234 }
1235
1236 int mm_evas_renderer_destroy(MMHandleType *handle)
1237 {
1238         MMER_FENTER();
1239         MM_CHECK_NULL(handle);
1240
1241         int ret = MM_ERROR_NONE;
1242         mm_evas_info *evas_info = (mm_evas_info *)*handle;
1243
1244         if (!evas_info) {
1245                 LOGD("skip it. it is not evas surface type.");
1246                 return MM_ERROR_RESOURCE_NOT_INITIALIZED;
1247         }
1248
1249         ret = _mm_evas_renderer_destroy(&evas_info);
1250         if (ret != MM_ERROR_NONE) {
1251                 LOGE("fail to destroy evas_info");
1252                 return ret;
1253         }
1254         *handle = NULL;
1255
1256         MMER_FLEAVE();
1257
1258         return MM_ERROR_NONE;
1259 }
1260
1261 int mm_evas_renderer_set_visible(MMHandleType handle, bool visible)
1262 {
1263         MMER_FENTER();
1264
1265         int ret = MM_ERROR_NONE;
1266         mm_evas_info *evas_info = (mm_evas_info *)handle;
1267
1268         if (!evas_info) {
1269                 LOGW("skip it. it is not evas surface type or handle is not prepared");
1270                 return MM_ERROR_RESOURCE_NOT_INITIALIZED;
1271         }
1272
1273         if (visible)
1274                 evas_info->visible = VISIBLE_TRUE;
1275         else
1276                 evas_info->visible = VISIBLE_FALSE;
1277
1278         if (evas_info->epipe) {
1279                 ret = ecore_pipe_write(evas_info->epipe, &visible, UPDATE_VISIBILITY);
1280                 if (!ret) {
1281                         LOGW("fail to ecore_pipe_write() for updating visibility\n");
1282                         ret = MM_ERROR_UNKNOWN;
1283                 } else {
1284                         ret = MM_ERROR_NONE;
1285                 }
1286         } else {
1287                 LOGW("there is no epipe. we cant update it");
1288         }
1289
1290         MMER_FLEAVE();
1291
1292         return ret;
1293 }
1294
1295 int mm_evas_renderer_get_visible(MMHandleType handle, bool *visible)
1296 {
1297         MMER_FENTER();
1298
1299         mm_evas_info *evas_info = (mm_evas_info *)handle;
1300
1301         if (!evas_info) {
1302                 LOGW("skip it. it is not evas surface type or handle is not prepared");
1303                 return MM_ERROR_RESOURCE_NOT_INITIALIZED;
1304         }
1305
1306         if (evas_info->visible == VISIBLE_FALSE)
1307                 *visible = FALSE;
1308         else
1309                 *visible = TRUE;
1310
1311         MMER_FLEAVE();
1312
1313         return MM_ERROR_NONE;
1314 }
1315
1316 int mm_evas_renderer_set_rotation(MMHandleType handle, int rotate)
1317 {
1318         MMER_FENTER();
1319
1320         int ret = MM_ERROR_NONE;
1321         mm_evas_info *evas_info = (mm_evas_info *)handle;
1322         guint value;
1323
1324         if (!evas_info) {
1325                 LOGW("skip it. it is not evas surface type or handle is not prepared");
1326                 return MM_ERROR_RESOURCE_NOT_INITIALIZED;
1327         }
1328
1329         switch (rotate) {
1330         case DEGREE_0:
1331                 value = EVAS_IMAGE_ORIENT_0;
1332                 break;
1333         case DEGREE_90:
1334                 value = EVAS_IMAGE_ORIENT_90;
1335                 break;
1336         case DEGREE_180:
1337                 value = EVAS_IMAGE_ORIENT_180;
1338                 break;
1339         case DEGREE_270:
1340                 value = EVAS_IMAGE_ORIENT_270;
1341                 break;
1342         default:
1343                 return MM_ERROR_INVALID_ARGUMENT;
1344         }
1345         if (evas_info->rotate_angle != value) {
1346                 evas_info->update_needed = TRUE;
1347                 evas_info->rotate_angle = value;
1348         }
1349
1350         /* FIXME: pause state only */
1351         if (evas_info->epipe) {
1352                 g_mutex_lock(&evas_info->idx_lock);
1353                 ret = ecore_pipe_write(evas_info->epipe, evas_info, UPDATE_TBM_SURF);
1354                 if (!ret) {
1355                         LOGW("fail to ecore_pipe_write() for updating visibility\n");
1356                         ret = MM_ERROR_UNKNOWN;
1357                 } else {
1358                         ret = MM_ERROR_NONE;
1359                 }
1360                 g_mutex_unlock(&evas_info->idx_lock);
1361         }
1362         MMER_FLEAVE();
1363
1364         return ret;
1365 }
1366
1367 int mm_evas_renderer_get_rotation(MMHandleType handle, int *rotate)
1368 {
1369         MMER_FENTER();
1370
1371         mm_evas_info *evas_info = (mm_evas_info *)handle;
1372
1373         if (!evas_info) {
1374                 LOGW("skip it. it is not evas surface type or handle is not prepared");
1375                 return MM_ERROR_RESOURCE_NOT_INITIALIZED;
1376         }
1377
1378         switch (evas_info->rotate_angle) {
1379         case EVAS_IMAGE_ORIENT_0:
1380                 *rotate = DEGREE_0;
1381                 break;
1382         case EVAS_IMAGE_ORIENT_90:
1383                 *rotate = DEGREE_90;
1384                 break;
1385         case EVAS_IMAGE_ORIENT_180:
1386                 *rotate = DEGREE_180;
1387                 break;
1388         case EVAS_IMAGE_ORIENT_270:
1389                 *rotate = DEGREE_270;
1390                 break;
1391         default:
1392                 return MM_ERROR_INVALID_ARGUMENT;
1393         }
1394
1395         MMER_FLEAVE();
1396
1397         return MM_ERROR_NONE;
1398 }
1399
1400 int mm_evas_renderer_set_geometry(MMHandleType handle, int mode)
1401 {
1402         MMER_FENTER();
1403
1404         int ret = MM_ERROR_NONE;
1405         mm_evas_info *evas_info = (mm_evas_info *)handle;
1406
1407         if (!evas_info) {
1408                 LOGW("skip it. it is not evas surface type or handle is not prepared");
1409                 return MM_ERROR_RESOURCE_NOT_INITIALIZED;
1410         }
1411         if (evas_info->display_geometry_method != mode) {
1412                 evas_info->update_needed = TRUE;
1413                 evas_info->display_geometry_method = mode;
1414         }
1415
1416         /* ecore_pipe_write is needed, because of setting ratio for letterbox mode */
1417         /* FIXME: pause state only */
1418         if (evas_info->epipe) {
1419                 g_mutex_lock(&evas_info->idx_lock);
1420                 ret = ecore_pipe_write(evas_info->epipe, evas_info, UPDATE_TBM_SURF);
1421                 if (!ret) {
1422                         LOGW("fail to ecore_pipe_write() for updating visibility\n");
1423                         ret = MM_ERROR_UNKNOWN;
1424                 } else {
1425                         ret = MM_ERROR_NONE;
1426                 }
1427                 g_mutex_unlock(&evas_info->idx_lock);
1428         }
1429         MMER_FLEAVE();
1430
1431         return ret;
1432 }
1433
1434 int mm_evas_renderer_get_geometry(MMHandleType handle, int *mode)
1435 {
1436         MMER_FENTER();
1437
1438         mm_evas_info *evas_info = (mm_evas_info *)handle;
1439
1440         if (!evas_info) {
1441                 LOGW("skip it. it is not evas surface type or handle is not prepared");
1442                 return MM_ERROR_RESOURCE_NOT_INITIALIZED;
1443         }
1444         *mode = evas_info->display_geometry_method;
1445
1446         MMER_FLEAVE();
1447
1448         return MM_ERROR_NONE;
1449 }
1450
1451 int mm_evas_renderer_set_roi_area(MMHandleType handle, int x, int y, int w, int h)
1452 {
1453         MMER_FENTER();
1454
1455         int ret = MM_ERROR_NONE;
1456         mm_evas_info *evas_info = (mm_evas_info *)handle;
1457
1458         if (!evas_info) {
1459                 LOGW("skip it. it is not evas surface type or handle is not prepared");
1460                 return MM_ERROR_RESOURCE_NOT_INITIALIZED;
1461         }
1462         if (!w || !h) {
1463                 LOGW("invalid resolution");
1464                 return MM_ERROR_INVALID_ARGUMENT;
1465         }
1466
1467         /* display mode is set to DISP_GEO_METHOD_CUSTOM_ROI internally */
1468         if (evas_info->display_geometry_method != DISP_GEO_METHOD_CUSTOM_ROI)
1469                 evas_info->update_needed = TRUE;
1470         evas_info->display_geometry_method = DISP_GEO_METHOD_CUSTOM_ROI;
1471         evas_info->dst_roi.x = x;
1472         evas_info->dst_roi.y = y;
1473         evas_info->dst_roi.w = w;
1474         evas_info->dst_roi.h = h;
1475
1476         /* pipe_write could be needed because ratio can be changed on pause state */
1477         if (evas_info->epipe) {
1478                 g_mutex_lock(&evas_info->idx_lock);
1479                 ret = ecore_pipe_write(evas_info->epipe, evas_info, UPDATE_TBM_SURF);
1480                 if (!ret) {
1481                         LOGW("fail to ecore_pipe_write() for updating visibility\n");
1482                         ret = MM_ERROR_UNKNOWN;
1483                 } else {
1484                         ret = MM_ERROR_NONE;
1485                 }
1486                 g_mutex_unlock(&evas_info->idx_lock);
1487         }
1488
1489         MMER_FLEAVE();
1490
1491         return ret;
1492 }
1493
1494 int mm_evas_renderer_get_roi_area(MMHandleType handle, int *x, int *y, int *w, int *h)
1495 {
1496         MMER_FENTER();
1497
1498         mm_evas_info *evas_info = (mm_evas_info *)handle;
1499
1500         if (!evas_info) {
1501                 LOGW("skip it. it is not evas surface type or handle is not prepared");
1502                 return MM_ERROR_RESOURCE_NOT_INITIALIZED;
1503         }
1504         if (evas_info->display_geometry_method != DISP_GEO_METHOD_CUSTOM_ROI) {
1505                 LOGW("invalid mode");
1506                 return MM_ERROR_INVALID_ARGUMENT;
1507         }
1508
1509         *x = evas_info->dst_roi.x;
1510         *y = evas_info->dst_roi.y;
1511         *w = evas_info->dst_roi.w;
1512         *h = evas_info->dst_roi.h;
1513
1514         MMER_FLEAVE();
1515
1516         return MM_ERROR_NONE;
1517 }
1518
1519 int mm_evas_renderer_set_flip(MMHandleType handle, int flip)
1520 {
1521         MMER_FENTER();
1522
1523         int ret = MM_ERROR_NONE;
1524         mm_evas_info *evas_info = (mm_evas_info *)handle;
1525         guint value;
1526
1527         if (!evas_info) {
1528                 LOGW("skip it. it is not evas surface type or handle is not prepared");
1529                 return MM_ERROR_RESOURCE_NOT_INITIALIZED;
1530         }
1531
1532         switch (flip) {
1533         case FLIP_NONE:
1534                 value = EVAS_IMAGE_ORIENT_NONE;
1535                 break;
1536         case FLIP_HORIZONTAL:
1537                 value = EVAS_IMAGE_FLIP_HORIZONTAL;
1538                 break;
1539         case FLIP_VERTICAL:
1540                 value = EVAS_IMAGE_FLIP_VERTICAL;
1541                 break;
1542         case FLIP_BOTH:
1543                 value = EVAS_IMAGE_ORIENT_180;
1544                 break;
1545         default:
1546                 return MM_ERROR_INVALID_ARGUMENT;
1547         }
1548         if (evas_info->flip != value) {
1549                 evas_info->update_needed = TRUE;
1550                 evas_info->flip = value;
1551         }
1552
1553         /* FIXME: pause state only */
1554         if (evas_info->epipe) {
1555                 g_mutex_lock(&evas_info->idx_lock);
1556                 ret = ecore_pipe_write(evas_info->epipe, evas_info, UPDATE_TBM_SURF);
1557                 if (!ret) {
1558                         LOGW("fail to ecore_pipe_write() for updating visibility\n");
1559                         ret = MM_ERROR_UNKNOWN;
1560                 } else {
1561                         ret = MM_ERROR_NONE;
1562                 }
1563                 g_mutex_unlock(&evas_info->idx_lock);
1564         }
1565
1566         MMER_FLEAVE();
1567
1568         return ret;
1569 }
1570
1571 int mm_evas_renderer_get_flip(MMHandleType handle, int *flip)
1572 {
1573         MMER_FENTER();
1574
1575         mm_evas_info *evas_info = (mm_evas_info *)handle;
1576
1577         if (!evas_info) {
1578                 LOGW("skip it. it is not evas surface type or handle is not prepared");
1579                 return MM_ERROR_RESOURCE_NOT_INITIALIZED;
1580         }
1581
1582         switch (evas_info->flip) {
1583         case EVAS_IMAGE_ORIENT_NONE:
1584                 *flip = FLIP_NONE;
1585                 break;
1586         case EVAS_IMAGE_FLIP_HORIZONTAL:
1587                 *flip = FLIP_HORIZONTAL;
1588                 break;
1589         case EVAS_IMAGE_FLIP_VERTICAL:
1590                 *flip = FLIP_VERTICAL;
1591                 break;
1592         case EVAS_IMAGE_ORIENT_180:
1593                 *flip = FLIP_BOTH;
1594                 break;
1595         default:
1596                 return MM_ERROR_INVALID_ARGUMENT;
1597         }
1598
1599         MMER_FLEAVE();
1600
1601         return MM_ERROR_NONE;
1602 }
1603
1604 int mm_evas_renderer_retrieve_all_packets(MMHandleType handle, bool keep_screen)
1605 {
1606         MMER_FENTER();
1607
1608         int ret = MM_ERROR_NONE;
1609         mm_evas_info *evas_info = (mm_evas_info*) handle;
1610
1611         if (!evas_info) {
1612                 LOGW("skip it. it is not evas surface type or player is not prepared");
1613                 return MM_ERROR_RESOURCE_NOT_INITIALIZED;
1614         }
1615         ret = _mm_evas_renderer_retrieve_all_packets(evas_info, keep_screen);
1616
1617         MMER_FLEAVE();
1618
1619         return ret;
1620 }
1621
1622 int mm_evas_renderer_set_packet_rendered_callback(MMHandleType handle, mm_evas_renderer_media_packet_rendered_cb callback, void *user_data)
1623 {
1624         MMER_FENTER();
1625
1626         mm_evas_info *evas_info = (mm_evas_info*) handle;
1627
1628         if (!evas_info) {
1629                 LOGW("skip it. it is not evas surface type or player is not prepared");
1630                 return MM_ERROR_RESOURCE_NOT_INITIALIZED;
1631         }
1632         evas_info->packet_rendered_cb = callback;
1633         evas_info->packet_rendered_cb_user = user_data;
1634
1635         LOGW("set rendered callback %p, user_data %p", evas_info->packet_rendered_cb, evas_info->packet_rendered_cb_user);
1636
1637         MMER_FLEAVE();
1638
1639         return MM_ERROR_NONE;
1640 }