add callback so that user who created media_packet can destroy it
[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                 }
385                 evas_info->sent_buffer_cnt--;
386                 evas_info->pkt_info[prev_idx].packet = NULL;
387                 evas_info->pkt_info[prev_idx].tbm_surf = NULL;
388                 evas_info->pkt_info[index].prev = -1;
389
390                 /* move index to previous index */
391                 index = prev_idx;
392                 prev_idx = evas_info->pkt_info[prev_idx].prev;
393                 LOGD("sent packet %d", evas_info->sent_buffer_cnt);
394         }
395
396         MMER_FLEAVE();
397
398         return;
399 }
400
401 static int _get_video_size(media_packet_h packet, mm_evas_info *evas_info)
402 {
403         MMER_FENTER();
404
405         media_format_h fmt;
406         if (media_packet_get_format(packet, &fmt) == MEDIA_PACKET_ERROR_NONE) {
407                 int w, h;
408                 if (media_format_get_video_info(fmt, NULL, &w, &h, NULL, NULL) == MEDIA_PACKET_ERROR_NONE) {
409                         LOGD("video width = %d, height =%d", w, h);
410                         evas_info->w = w;
411                         evas_info->h = h;
412                         return true;
413                 } else
414                         LOGW("media_format_get_video_info is failed");
415                 if (media_format_unref(fmt) != MEDIA_PACKET_ERROR_NONE) /* because of media_packet_get_format */
416                         LOGW("media_format_unref is failed");
417         } else {
418                 LOGW("media_packet_get_format is failed");
419         }
420
421         MMER_FLEAVE();
422
423         return false;
424 }
425
426 static int _find_empty_index(mm_evas_info *evas_info)
427 {
428         MMER_FENTER();
429
430         int i;
431         for (i = 0; i < MAX_PACKET_NUM; i++) {
432                 if (!evas_info->pkt_info[i].packet) {
433                         LOGD("selected idx %d", i);
434                         return i;
435                 }
436         }
437         LOGE("there is no empty idx");
438
439         MMER_FLEAVE();
440
441         return -1;
442 }
443
444 static int _flush_packets(mm_evas_info *evas_info)
445 {
446         MMER_FENTER();
447
448         int ret = MM_ERROR_NONE;
449         int ret_mp = MEDIA_PACKET_ERROR_NONE;
450         int i = 0;
451
452         if (!evas_info) {
453                 LOGW("there is no esink info");
454                 return MM_ERROR_INVALID_ARGUMENT;
455         }
456
457         /* update the screen only if visible is true */
458         /* if flush buffer is null, we cant keep screen */
459         if (evas_info->keep_screen && (evas_info->visible != VISIBLE_FALSE) && evas_info->flush_buffer) {
460                 Evas_Native_Surface surf = { 0 };
461                 rect_info result = { 0 };
462                 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);
463                 if (!evas_info->eo_size.w || !evas_info->eo_size.h) {
464                         LOGE("there is no information for evas object size");
465                         return MM_ERROR_INVALID_ARGUMENT;
466                 }
467                 _mm_evas_renderer_update_geometry(evas_info, &result);
468                 if (!result.w || !result.h) {
469                         LOGE("no information about geometry (%d, %d)", result.w, result.h);
470                         return MM_ERROR_INVALID_ARGUMENT;
471                 }
472
473                 if (evas_info->use_ratio) {
474                         surf.data.tbm.ratio = (float) evas_info->w / evas_info->h;
475                         LOGD("set ratio");
476                 }
477                 evas_object_size_hint_align_set(evas_info->eo, EVAS_HINT_FILL, EVAS_HINT_FILL);
478                 evas_object_size_hint_weight_set(evas_info->eo, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
479                 if (evas_info->w > 0 && evas_info->h > 0)
480                         evas_object_image_size_set(evas_info->eo, evas_info->w, evas_info->h);
481
482                 if (result.x || result.y)
483                         LOGD("coordinate x, y (%d, %d) for locating video to center", result.x, result.y);
484
485                 evas_object_image_fill_set(evas_info->eo, result.x, result.y, result.w, result.h);
486
487                 /* set flush buffer */
488                 surf.type = EVAS_NATIVE_SURFACE_TBM;
489                 surf.version = EVAS_NATIVE_SURFACE_VERSION;
490                 surf.data.tbm.buffer = evas_info->flush_buffer->tbm_surf;
491                 surf.data.tbm.rot = evas_info->rotate_angle;
492                 surf.data.tbm.flip = evas_info->flip;
493                 evas_object_image_native_surface_set(evas_info->eo, &surf);
494
495                 LOGD("flush_buffer surf(%p), rotate(%d), flip(%d)", evas_info->flush_buffer->tbm_surf, evas_info->rotate_angle, evas_info->flip);
496         } else {
497                 /* unset evas native surface for displaying black screen */
498                 evas_object_image_native_surface_set(evas_info->eo, NULL);
499                 evas_object_image_data_set(evas_info->eo, NULL);
500         }
501         LOGD("sent packet %d", evas_info->sent_buffer_cnt);
502
503         /* destroy all packets */
504         g_mutex_lock(&evas_info->mp_lock);
505         for (i = 0; i < MAX_PACKET_NUM; i++) {
506                 if (evas_info->pkt_info[i].packet) {
507                         LOGD("destroy packet [%p]", evas_info->pkt_info[i].packet);
508                         if (evas_info->packet_rendered_cb) {
509                                 evas_info->packet_rendered_cb(evas_info->pkt_info[i].packet, evas_info->packet_rendered_cb_user);
510                         } else {
511                                 ret_mp = media_packet_destroy(evas_info->pkt_info[i].packet);
512                                 if (ret_mp != MEDIA_PACKET_ERROR_NONE) {
513                                         LOGW("media_packet_destroy failed %p", evas_info->pkt_info[i].packet);
514                                         ret = MM_ERROR_UNKNOWN;
515                                 }
516                         }
517                         evas_info->sent_buffer_cnt--;
518                         evas_info->pkt_info[i].packet = NULL;
519                         evas_info->pkt_info[i].tbm_surf = NULL;
520                         evas_info->pkt_info[i].prev = -1;
521                 }
522         }
523
524         if (evas_info->sent_buffer_cnt != 0)
525                 LOGE("it should be 0 --> [%d]", evas_info->sent_buffer_cnt);
526         evas_info->sent_buffer_cnt = 0;
527         evas_info->cur_idx = -1;
528         g_mutex_unlock(&evas_info->mp_lock);
529
530         evas_object_image_pixels_dirty_set(evas_info->eo, EINA_TRUE);
531         evas_info->retrieve_packet = FALSE;
532
533         MMER_FLEAVE();
534
535         return ret;
536 }
537
538 #if 0
539 int _reset_pipe(mm_evas_info *evas_info)
540 {
541         int i = 0;
542         int ret = MM_ERROR_NONE;
543         int ret_mp = MEDIA_PACKET_ERROR_NONE;
544
545         /* delete old pipe */
546         if (evas_info->epipe) {
547                 LOGD("pipe %p will be deleted", evas_info->epipe);
548                 ecore_pipe_del(evas_info->epipe);
549                 evas_info->epipe = NULL;
550         }
551
552         for (i = 0; i < MAX_PACKET_NUM; i++) {
553                 if (evas_info->pkt_info[i].packet) {
554                         /* destroy all packets */
555                         LOGD("destroy packet [%p]", evas_info->pkt_info[i].packet);
556                         if (evas_info->packet_rendered_cb) {
557                                 evas_info->packet_rendered_cb(evas_info->pkt_info[i].packet, evas_info->packet_rendered_cb_user);
558                         } else {
559                                 ret_mp = media_packet_destroy(evas_info->pkt_info[i].packet);
560                                 if (ret_mp != MEDIA_PACKET_ERROR_NONE) {
561                                         LOGW("media_packet_destroy failed %p", evas_info->pkt_info[i].packet);
562                                         ret = MM_ERROR_UNKNOWN;
563                                 }
564                         }
565                         evas_info->sent_buffer_cnt--;
566                         evas_info->pkt_info[i].packet = NULL;
567                         evas_info->pkt_info[i].tbm_surf = NULL;
568                         evas_info->pkt_info[i].prev = -1;
569                 }
570         }
571
572         if (evas_info->sent_buffer_cnt != 0)
573                 LOGE("it should be 0 --> [%d]", evas_info->sent_buffer_cnt);
574         evas_info->sent_buffer_cnt = 0;
575         evas_info->cur_idx = -1;
576
577         /* make new pipe */
578         if (!evas_info->epipe) {
579                 evas_info->epipe = ecore_pipe_add((Ecore_Pipe_Cb) _evas_pipe_cb, evas_info);
580                 if (!evas_info->epipe) {
581                         LOGE("pipe is not created");
582                         ret = MM_ERROR_UNKNOWN;
583                 }
584                 LOGD("created pipe %p", evas_info->epipe);
585         }
586
587         return ret;
588 }
589 #endif
590
591 static void _mm_evas_renderer_set_callback(mm_evas_info *evas_info)
592 {
593         MMER_FENTER();
594         if (evas_info->eo) {
595                 SET_EVAS_OBJECT_EVENT_CALLBACK(evas_info->eo, evas_info);
596                 SET_EVAS_EVENT_CALLBACK(evas_object_evas_get(evas_info->eo), evas_info);
597         }
598         MMER_FLEAVE();
599 }
600
601 static void _mm_evas_renderer_unset_callback(mm_evas_info *evas_info)
602 {
603         MMER_FENTER();
604         if (evas_info->eo) {
605                 UNSET_EVAS_OBJECT_EVENT_CALLBACK(evas_info->eo);
606                 UNSET_EVAS_EVENT_CALLBACK(evas_object_evas_get(evas_info->eo));
607         }
608         MMER_FLEAVE();
609 }
610
611 static int _mm_evas_renderer_create(mm_evas_info **evas_info)
612 {
613         MMER_FENTER();
614
615         mm_evas_info *ptr = NULL;
616         ptr = g_malloc0(sizeof(mm_evas_info));
617
618         if (!ptr) {
619                 LOGE("Cannot allocate memory for evas_info\n");
620                 goto ERROR;
621         } else {
622                 *evas_info = ptr;
623                 LOGD("Success create evas_info(%p)", *evas_info);
624         }
625         g_mutex_init(&ptr->mp_lock);
626         g_mutex_init(&ptr->idx_lock);
627
628         MMER_FLEAVE();
629
630         return MM_ERROR_NONE;
631
632  ERROR:
633         *evas_info = NULL;
634         return MM_ERROR_OUT_OF_STORAGE;
635 }
636
637 static int _mm_evas_renderer_destroy(mm_evas_info **evas_info)
638 {
639         MMER_FENTER();
640
641         mm_evas_info *ptr = (mm_evas_info *)*evas_info;
642         MM_CHECK_NULL(ptr);
643         int ret = MM_ERROR_NONE;
644
645         LOGD("finalize evas_info %p", ptr);
646
647         ret = _mm_evas_renderer_reset(ptr);
648         g_mutex_clear(&ptr->mp_lock);
649         g_mutex_clear(&ptr->idx_lock);
650
651         g_free(ptr);
652         ptr = NULL;
653
654         MMER_FLEAVE();
655
656         return ret;
657 }
658
659 static int _mm_evas_renderer_set_info(mm_evas_info *evas_info, Evas_Object *eo)
660 {
661         MMER_FENTER();
662         MM_CHECK_NULL(evas_info);
663         MM_CHECK_NULL(eo);
664         g_mutex_lock(&evas_info->idx_lock);
665
666         LOGD("set evas_info");
667         int i;
668         for (i = 0; i < MAX_PACKET_NUM; i++) {
669                 evas_info->pkt_info[i].packet = NULL;
670                 evas_info->pkt_info[i].tbm_surf = NULL;
671                 evas_info->pkt_info[i].prev = -1;
672         }
673         evas_info->cur_idx = -1;
674         evas_info->dst_roi.x = evas_info->dst_roi.y = evas_info->dst_roi.w = evas_info->dst_roi.h = 0;
675         evas_info->eo = eo;
676         evas_info->epipe = ecore_pipe_add((Ecore_Pipe_Cb) _evas_pipe_cb, evas_info);
677         if (!evas_info->epipe) {
678                 LOGE("pipe is not created");
679                 g_mutex_unlock(&evas_info->idx_lock);
680                 return MM_ERROR_UNKNOWN;
681         }
682         LOGD("created pipe %p", evas_info->epipe);
683         _mm_evas_renderer_set_callback(evas_info);
684
685         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);
686         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);
687
688         g_mutex_unlock(&evas_info->idx_lock);
689
690         MMER_FLEAVE();
691
692         return MM_ERROR_NONE;
693 }
694
695 static int _mm_evas_renderer_reset(mm_evas_info *evas_info)
696 {
697         MMER_FENTER();
698         MM_CHECK_NULL(evas_info);
699         g_mutex_lock(&evas_info->idx_lock);
700
701         int i;
702         int ret = MM_ERROR_NONE;
703         int ret_mp = MEDIA_PACKET_ERROR_NONE;
704
705         if (evas_info->eo) {
706                 _mm_evas_renderer_unset_callback(evas_info);
707                 evas_object_image_data_set(evas_info->eo, NULL);
708                 evas_info->eo = NULL;
709         }
710         if (evas_info->epipe) {
711                 LOGD("pipe %p will be deleted", evas_info->epipe);
712                 ecore_pipe_del(evas_info->epipe);
713                 evas_info->epipe = NULL;
714         }
715
716         evas_info->eo_size.x = evas_info->eo_size.y = evas_info->eo_size.w = evas_info->eo_size.h = 0;
717         evas_info->dst_roi.x = evas_info->dst_roi.y = evas_info->dst_roi.w = evas_info->dst_roi.h = 0;
718         evas_info->w = evas_info->h = 0;
719
720         if (evas_info->flush_buffer)
721                 _mm_evas_renderer_release_flush_buffer(evas_info);
722
723         g_mutex_lock(&evas_info->mp_lock);
724         for (i = 0; i < MAX_PACKET_NUM; i++) {
725                 if (evas_info->pkt_info[i].packet) {
726                         /* destroy all packets */
727                         LOGD("destroy packet [%p]", evas_info->pkt_info[i].packet);
728                         if (evas_info->packet_rendered_cb) {
729                                 evas_info->packet_rendered_cb(evas_info->pkt_info[i].packet, evas_info->packet_rendered_cb_user);
730                         } else {
731                                 ret_mp = media_packet_destroy(evas_info->pkt_info[i].packet);
732                                 if (ret_mp != MEDIA_PACKET_ERROR_NONE) {
733                                         LOGW("media_packet_destroy failed %p", evas_info->pkt_info[i].packet);
734                                         ret = MM_ERROR_UNKNOWN;
735                                 }
736                         }
737                         evas_info->sent_buffer_cnt--;
738                         evas_info->pkt_info[i].packet = NULL;
739                         evas_info->pkt_info[i].tbm_surf = NULL;
740                         evas_info->pkt_info[i].prev = -1;
741                 }
742         }
743         g_mutex_unlock(&evas_info->mp_lock);
744         if (evas_info->sent_buffer_cnt != 0)
745                 LOGE("it should be 0 --> [%d]", evas_info->sent_buffer_cnt);
746         evas_info->sent_buffer_cnt = 0;
747         evas_info->cur_idx = -1;
748
749         g_mutex_unlock(&evas_info->idx_lock);
750
751         MMER_FLEAVE();
752
753         return ret;
754 }
755
756 static void _mm_evas_renderer_update_geometry(mm_evas_info *evas_info, rect_info *result)
757 {
758         MMER_FENTER();
759
760         if (!evas_info || !evas_info->eo) {
761                 LOGW("there is no evas_info or evas object");
762                 return;
763         }
764         if (!result) {
765                 LOGW("there is no rect info");
766                 return;
767         }
768
769         result->x = 0;
770         result->y = 0;
771
772         switch (evas_info->display_geometry_method) {
773         case DISP_GEO_METHOD_LETTER_BOX:
774                 /* set black padding for letter box mode */
775                 LOGD("letter box mode");
776                 evas_info->use_ratio = TRUE;
777                 result->w = evas_info->eo_size.w;
778                 result->h = evas_info->eo_size.h;
779                 break;
780         case DISP_GEO_METHOD_ORIGIN_SIZE:
781                 LOGD("origin size mode");
782                 evas_info->use_ratio = FALSE;
783                 /* set coordinate for each case */
784                 result->x = (evas_info->eo_size.w - evas_info->w) / 2;
785                 result->y = (evas_info->eo_size.h - evas_info->h) / 2;
786                 result->w = evas_info->w;
787                 result->h = evas_info->h;
788                 break;
789         case DISP_GEO_METHOD_FULL_SCREEN:
790                 LOGD("full screen mode");
791                 evas_info->use_ratio = FALSE;
792                 result->w = evas_info->eo_size.w;
793                 result->h = evas_info->eo_size.h;
794                 break;
795         case DISP_GEO_METHOD_CROPPED_FULL_SCREEN:
796                 LOGD("cropped full screen mode");
797                 evas_info->use_ratio = FALSE;
798                 /* compare evas object's ratio with video's */
799                 if ((evas_info->eo_size.w / evas_info->eo_size.h) > (evas_info->w / evas_info->h)) {
800                         result->w = evas_info->eo_size.w;
801                         result->h = evas_info->eo_size.w * evas_info->h / evas_info->w;
802                         result->y = -(result->h - evas_info->eo_size.h) / 2;
803                 } else {
804                         result->w = evas_info->eo_size.h * evas_info->w / evas_info->h;
805                         result->h = evas_info->eo_size.h;
806                         result->x = -(result->w - evas_info->eo_size.w) / 2;
807                 }
808                 break;
809         case DISP_GEO_METHOD_ORIGIN_SIZE_OR_LETTER_BOX:
810                 LOGD("origin size or letter box mode");
811                 /* if video size is smaller than evas object's, it will be set to origin size mode */
812                 if ((evas_info->eo_size.w > evas_info->w) && (evas_info->eo_size.h > evas_info->h)) {
813                         LOGD("origin size mode");
814                         evas_info->use_ratio = FALSE;
815                         /* set coordinate for each case */
816                         result->x = (evas_info->eo_size.w - evas_info->w) / 2;
817                         result->y = (evas_info->eo_size.h - evas_info->h) / 2;
818                         result->w = evas_info->w;
819                         result->h = evas_info->h;
820                 } else {
821                         LOGD("letter box mode");
822                         evas_info->use_ratio = TRUE;
823                         result->w = evas_info->eo_size.w;
824                         result->h = evas_info->eo_size.h;
825                 }
826                 break;
827         case DISP_GEO_METHOD_CUSTOM_ROI:
828                 LOGD("custom roi mode");
829                 evas_info->use_ratio = TRUE;
830                 result->x = evas_info->dst_roi.x;
831                 result->y = evas_info->dst_roi.y;
832                 result->w = evas_info->dst_roi.w;
833                 result->h = evas_info->dst_roi.h;
834                 break;
835         default:
836                 LOGW("unsupported mode.");
837                 break;
838         }
839         LOGD("geometry result [%d, %d, %d, %d]", result->x, result->y, result->w, result->h);
840
841         MMER_FLEAVE();
842 }
843
844 static int _mm_evas_renderer_apply_geometry(mm_evas_info *evas_info)
845 {
846         MMER_FENTER();
847
848         if (!evas_info || !evas_info->eo) {
849                 LOGW("there is no evas_info or evas object");
850                 return MM_ERROR_NONE;
851         }
852
853         Evas_Native_Surface *surf = evas_object_image_native_surface_get(evas_info->eo);
854         rect_info result = { 0 };
855
856         if (surf) {
857                 LOGD("native surface exists");
858                 surf->data.tbm.rot = evas_info->rotate_angle;
859                 surf->data.tbm.flip = evas_info->flip;
860                 evas_object_image_native_surface_set(evas_info->eo, surf);
861
862                 _mm_evas_renderer_update_geometry(evas_info, &result);
863
864                 if (evas_info->use_ratio) {
865                         surf->data.tbm.ratio = (float) evas_info->w / evas_info->h;
866                         LOGD("set ratio");
867                 }
868                 if (result.x || result.y)
869                         LOGD("coordinate x, y (%d, %d) for locating video to center", result.x, result.y);
870
871                 evas_object_image_fill_set(evas_info->eo, result.x, result.y, result.w, result.h);
872
873                 return MM_ERROR_NONE;
874         } else
875                 LOGW("there is no surf");
876         /* FIXME: before pipe_cb is invoked, apply_geometry can be called. */
877
878         MMER_FLEAVE();
879
880         return MM_ERROR_NONE;
881 }
882
883 static int _mm_evas_renderer_retrieve_all_packets(mm_evas_info *evas_info, bool keep_screen)
884 {
885         MMER_FENTER();
886         MM_CHECK_NULL(evas_info);
887
888         int ret = MM_ERROR_NONE;
889         pid_t pid = getpid();
890         pid_t tid = syscall(SYS_gettid);
891
892         /* write and this API can be called at the same time.
893         so lock is needed for counting sent_buffer_cnt correctly */
894         g_mutex_lock(&evas_info->idx_lock);
895
896         /* make flush buffer */
897         if (keep_screen)
898                 ret = _mm_evas_renderer_make_flush_buffer(evas_info);
899         evas_info->keep_screen = keep_screen;
900
901         LOGD("pid [%d], tid [%d]", pid, tid);
902         if (pid == tid) {
903                 /* in this case, we deem it is main thread */
904                 if (_flush_packets(evas_info) != MM_ERROR_NONE) {
905                         LOGE("flushing packets are failed");
906                         ret = MM_ERROR_UNKNOWN;
907                 }
908         } else {
909                 /* it will be executed to write flush buffer and destroy media packets in pre_cb */
910                 evas_info->retrieve_packet = TRUE;
911         }
912         g_mutex_unlock(&evas_info->idx_lock);
913
914         MMER_FLEAVE();
915
916         return ret;
917 }
918
919 /* make buffer for copying */
920 static int _mm_evas_renderer_make_flush_buffer(mm_evas_info *evas_info)
921 {
922         MMER_FENTER();
923
924         if (evas_info->cur_idx == -1) {
925                 LOGW("there is no remained buffer");
926                 return MM_ERROR_INVALID_ARGUMENT;
927         }
928         media_packet_h packet = evas_info->pkt_info[evas_info->cur_idx].packet;
929         MM_CHECK_NULL(packet);
930
931         flush_info *flush_buffer = NULL;
932         tbm_bo src_bo = NULL;
933         tbm_surface_h src_tbm_surf = NULL;
934         int src_size = 0;
935         int size = 0;
936         tbm_bo bo = NULL;
937         tbm_format tbm_fmt;
938         tbm_bo_handle vaddr_src = {0};
939         tbm_bo_handle vaddr_dst = {0};
940         int ret = MM_ERROR_NONE;
941
942         if (evas_info->flush_buffer)
943                 _mm_evas_renderer_release_flush_buffer(evas_info);
944
945         /* malloc buffer */
946         flush_buffer = (flush_info *)malloc(sizeof(flush_info));
947         if (flush_buffer == NULL) {
948                 LOGE("malloc is failed");
949                 return FALSE;
950         }
951         memset(flush_buffer, 0x0, sizeof(flush_info));
952
953         ret = media_packet_get_tbm_surface(packet, &src_tbm_surf);
954         if (ret != MEDIA_PACKET_ERROR_NONE || !src_tbm_surf) {
955                 LOGW("get_tbm_surface is failed");
956                 goto ERROR;
957         }
958
959         /* get src buffer info */
960         tbm_fmt = tbm_surface_get_format(src_tbm_surf);
961         src_bo = tbm_surface_internal_get_bo(src_tbm_surf, 0);
962         src_size = tbm_bo_size(src_bo);
963         if (!src_bo || !src_size) {
964                 LOGE("bo(%p), size(%d)", src_bo, src_size);
965                 goto ERROR;
966         }
967
968         /* create tbm surface */
969         flush_buffer->tbm_surf = tbm_surface_create(evas_info->w, evas_info->h, tbm_fmt);
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         size = tbm_bo_size(bo);
978         if (!bo || !size) {
979                 LOGE("bo(%p), size(%d)", bo, size);
980                 goto ERROR;
981         }
982         flush_buffer->bo = bo;
983
984         vaddr_src = tbm_bo_map(src_bo, TBM_DEVICE_CPU, TBM_OPTION_READ|TBM_OPTION_WRITE);
985         vaddr_dst = tbm_bo_map(bo, TBM_DEVICE_CPU, TBM_OPTION_READ|TBM_OPTION_WRITE);
986         if (!vaddr_src.ptr || !vaddr_dst.ptr) {
987                 LOGW("get vaddr failed src %p, dst %p", vaddr_src.ptr, vaddr_dst.ptr);
988                 if (vaddr_src.ptr)
989                         tbm_bo_unmap(src_bo);
990                 if (vaddr_dst.ptr)
991                         tbm_bo_unmap(bo);
992                 goto ERROR;
993         } else {
994                 memset(vaddr_dst.ptr, 0x0, size);
995                 LOGW("tbm_bo_map(vaddr) is finished, bo(%p), vaddr(%p)", bo, vaddr_dst.ptr);
996         }
997
998         /* copy buffer */
999         memcpy(vaddr_dst.ptr, vaddr_src.ptr, src_size);
1000
1001         tbm_bo_unmap(src_bo);
1002         tbm_bo_unmap(bo);
1003         LOGW("copy is done. tbm surface : %p src_size : %d", flush_buffer->tbm_surf, src_size);
1004
1005         evas_info->flush_buffer = flush_buffer;
1006
1007         MMER_FLEAVE();
1008
1009         return MM_ERROR_NONE;
1010
1011 ERROR:
1012         if (flush_buffer) {
1013                 if (flush_buffer->tbm_surf) {
1014                         tbm_surface_destroy(flush_buffer->tbm_surf);
1015                         flush_buffer->tbm_surf = NULL;
1016                 }
1017
1018                 free(flush_buffer);
1019                 flush_buffer = NULL;
1020         }
1021         return MM_ERROR_UNKNOWN;
1022 }
1023
1024 /* release flush buffer */
1025 static void _mm_evas_renderer_release_flush_buffer(mm_evas_info *evas_info)
1026 {
1027         MMER_FENTER();
1028
1029         LOGW("release FLUSH BUFFER start");
1030         if (evas_info->flush_buffer->bo)
1031                 evas_info->flush_buffer->bo = NULL;
1032
1033         if (evas_info->flush_buffer->tbm_surf) {
1034                 tbm_surface_destroy(evas_info->flush_buffer->tbm_surf);
1035                 evas_info->flush_buffer->tbm_surf = NULL;
1036         }
1037
1038         LOGW("release FLUSH BUFFER done");
1039
1040         free(evas_info->flush_buffer);
1041         evas_info->flush_buffer = NULL;
1042
1043         MMER_FLEAVE();
1044
1045         return;
1046 }
1047
1048 void mm_evas_renderer_write(media_packet_h packet, void *data)
1049 {
1050         MMER_FENTER();
1051
1052         if (!packet) {
1053                 LOGE("packet %p is NULL", packet);
1054                 return;
1055         }
1056         mm_evas_info *handle = (mm_evas_info *)data;
1057         int ret = MEDIA_PACKET_ERROR_NONE;
1058         bool has;
1059         tbm_surface_h tbm_surf;
1060         gint index;
1061
1062         LOGD("packet [%p]", packet);
1063
1064         if (!data || !handle) {
1065                 LOGE("handle %p or evas_info %p is NULL", data, handle);
1066                 goto INVALID_PARAM;
1067         }
1068         g_mutex_lock(&handle->idx_lock);
1069
1070         ret = media_packet_has_tbm_surface_buffer(packet, &has);
1071         if (ret != MEDIA_PACKET_ERROR_NONE) {
1072                 LOGW("has_tbm_surface is failed");
1073                 goto ERROR;
1074         }
1075         /* FIXME: when setCaps occurs, _get_video_size should be called */
1076         /* currently we are always checking it */
1077         if (has && _get_video_size(packet, handle)) {
1078                 /* Attention! if this error occurs, we need to consider managing buffer */
1079                 if (handle->sent_buffer_cnt > 3) {
1080                         LOGE("too many buffers are not released %d", handle->sent_buffer_cnt);
1081                         goto ERROR;
1082 #if 0
1083                         /* FIXME: fix this logic */
1084                         /* destroy all media packets and reset pipe at present */
1085                         /* Attention! it might free buffer that is being rendered */
1086                         g_mutex_lock(&handle->mp_lock);
1087                         _reset_pipe(handle);
1088                         g_mutex_unlock(&handle->mp_lock);
1089 #endif
1090                 }
1091                 ret = media_packet_get_tbm_surface(packet, &tbm_surf);
1092                 if (ret != MEDIA_PACKET_ERROR_NONE || !tbm_surf) {
1093                         LOGW("get_tbm_surface is failed");
1094                         goto ERROR;
1095                 }
1096
1097                 /* find new index for current packet */
1098                 index = _find_empty_index(handle);
1099                 if (index == -1)
1100                         goto ERROR;
1101
1102 #ifdef _INTERNAL_DEBUG_
1103                 int ret2 = 0;
1104                 if ((g_cnt%10 == 0) && (g_cnt < 500))
1105                         ret2 = __dump_pkt(packet);
1106
1107                 if (ret2)
1108                         LOGW("__dump_pkt() is failed");
1109                 else
1110                         g_cnt++;
1111 #endif
1112                 /* save previous index */
1113                 handle->pkt_info[index].prev = handle->cur_idx;
1114                 handle->pkt_info[index].packet = packet;
1115                 handle->pkt_info[index].tbm_surf = tbm_surf;
1116                 handle->cur_idx = index;
1117                 handle->sent_buffer_cnt++;
1118                 LOGD("sent packet %d", handle->sent_buffer_cnt);
1119
1120                 ret = ecore_pipe_write(handle->epipe, handle, UPDATE_TBM_SURF);
1121                 if (!ret) {
1122                         handle->pkt_info[index].packet = NULL;
1123                         handle->pkt_info[index].tbm_surf = NULL;
1124                         handle->pkt_info[index].prev = -1;
1125                         handle->cur_idx = handle->pkt_info[index].prev;
1126                         handle->sent_buffer_cnt--;
1127                         LOGW("Failed to ecore_pipe_write() for updating tbm surf\n");
1128                         goto ERROR;
1129                 }
1130         } else {
1131                 LOGW("no tbm_surf");
1132                 goto ERROR;
1133         }
1134         g_mutex_unlock(&handle->idx_lock);
1135
1136         MMER_FLEAVE();
1137
1138         return;
1139 ERROR:
1140         g_mutex_unlock(&handle->idx_lock);
1141 INVALID_PARAM:
1142         /* destroy media_packet immediately */
1143         if (packet) {
1144                 g_mutex_lock(&handle->mp_lock);
1145                 LOGD("cant write. destroy packet [%p]", packet);
1146                 if (handle->packet_rendered_cb) {
1147                         handle->packet_rendered_cb(packet, handle->packet_rendered_cb_user);
1148                 } else {
1149                         if (media_packet_destroy(packet) != MEDIA_PACKET_ERROR_NONE)
1150                                 LOGE("media_packet_destroy failed %p", packet);
1151                         packet = NULL;
1152                 }
1153                 g_mutex_unlock(&handle->mp_lock);
1154         }
1155         return;
1156 }
1157
1158 int mm_evas_renderer_update_param(MMHandleType handle)
1159 {
1160         MMER_FENTER();
1161
1162         int ret = MM_ERROR_NONE;
1163         mm_evas_info *evas_info = (mm_evas_info *)handle;
1164
1165         if (!evas_info) {
1166                 LOGW("skip it. it is not evas surface type.");
1167                 return ret;
1168         }
1169
1170         /* when handle is realized, we need to update all properties */
1171         if (evas_info) {
1172                 LOGD("set video param : evas-object %x, method %d", evas_info->eo, evas_info->display_geometry_method);
1173                 LOGD("set video param : visible %d", evas_info->visible);
1174                 LOGD("set video param : rotate %d", evas_info->rotate_angle);
1175
1176                 ret = _mm_evas_renderer_apply_geometry(evas_info);
1177                 if (ret != MM_ERROR_NONE)
1178                         return ret;
1179
1180                 if (evas_info->epipe) {
1181                         ret = ecore_pipe_write(evas_info->epipe, &evas_info->visible, UPDATE_VISIBILITY);
1182                         if (!ret) {
1183                                 LOGW("fail to ecore_pipe_write() for updating visibility\n");
1184                                 return MM_ERROR_UNKNOWN;
1185                         }
1186                         evas_info->update_needed = TRUE;
1187                         /* FIXME: pause state only */
1188                         g_mutex_lock(&evas_info->idx_lock);
1189                         ret = ecore_pipe_write(evas_info->epipe, evas_info, UPDATE_TBM_SURF);
1190                         if (!ret) {
1191                                 LOGW("fail to ecore_pipe_write() for updating visibility\n");
1192                                 ret = MM_ERROR_UNKNOWN;
1193                         } else {
1194                                 ret = MM_ERROR_NONE;
1195                         }
1196                         g_mutex_unlock(&evas_info->idx_lock);
1197                 }
1198         }
1199
1200         MMER_FLEAVE();
1201
1202         return ret;
1203 }
1204
1205 int mm_evas_renderer_create(MMHandleType *handle, Evas_Object *eo)
1206 {
1207         MMER_FENTER();
1208         MM_CHECK_NULL(handle);
1209
1210         int ret = MM_ERROR_NONE;
1211         mm_evas_info *evas_info = NULL;
1212
1213         ret = _mm_evas_renderer_create(&evas_info);
1214         if (ret != MM_ERROR_NONE) {
1215                 LOGE("fail to create evas_info");
1216                 return ret;
1217         }
1218         ret = _mm_evas_renderer_set_info(evas_info, eo);
1219         if (ret != MM_ERROR_NONE) {
1220                 LOGE("fail to init evas_info");
1221                 if (_mm_evas_renderer_destroy(&evas_info) != MM_ERROR_NONE)
1222                         LOGE("fail to destroy evas_info");
1223                 return ret;
1224         }
1225
1226         *handle = (MMHandleType)evas_info;
1227
1228         return MM_ERROR_NONE;
1229 }
1230
1231 int mm_evas_renderer_destroy(MMHandleType *handle)
1232 {
1233         MMER_FENTER();
1234         MM_CHECK_NULL(handle);
1235
1236         int ret = MM_ERROR_NONE;
1237         mm_evas_info *evas_info = (mm_evas_info *)*handle;
1238
1239         if (!evas_info) {
1240                 LOGD("skip it. it is not evas surface type.");
1241                 return MM_ERROR_RESOURCE_NOT_INITIALIZED;
1242         }
1243
1244         ret = _mm_evas_renderer_destroy(&evas_info);
1245         if (ret != MM_ERROR_NONE) {
1246                 LOGE("fail to destroy evas_info");
1247                 return ret;
1248         }
1249         *handle = NULL;
1250
1251         MMER_FLEAVE();
1252
1253         return MM_ERROR_NONE;
1254 }
1255
1256 int mm_evas_renderer_set_visible(MMHandleType handle, bool visible)
1257 {
1258         MMER_FENTER();
1259
1260         int ret = MM_ERROR_NONE;
1261         mm_evas_info *evas_info = (mm_evas_info *)handle;
1262
1263         if (!evas_info) {
1264                 LOGW("skip it. it is not evas surface type or handle is not prepared");
1265                 return MM_ERROR_RESOURCE_NOT_INITIALIZED;
1266         }
1267
1268         if (visible)
1269                 evas_info->visible = VISIBLE_TRUE;
1270         else
1271                 evas_info->visible = VISIBLE_FALSE;
1272
1273         if (evas_info->epipe) {
1274                 ret = ecore_pipe_write(evas_info->epipe, &visible, UPDATE_VISIBILITY);
1275                 if (!ret) {
1276                         LOGW("fail to ecore_pipe_write() for updating visibility\n");
1277                         ret = MM_ERROR_UNKNOWN;
1278                 } else {
1279                         ret = MM_ERROR_NONE;
1280                 }
1281         } else {
1282                 LOGW("there is no epipe. we cant update it");
1283         }
1284
1285         MMER_FLEAVE();
1286
1287         return ret;
1288 }
1289
1290 int mm_evas_renderer_get_visible(MMHandleType handle, bool *visible)
1291 {
1292         MMER_FENTER();
1293
1294         mm_evas_info *evas_info = (mm_evas_info *)handle;
1295
1296         if (!evas_info) {
1297                 LOGW("skip it. it is not evas surface type or handle is not prepared");
1298                 return MM_ERROR_RESOURCE_NOT_INITIALIZED;
1299         }
1300
1301         if (evas_info->visible == VISIBLE_FALSE)
1302                 *visible = FALSE;
1303         else
1304                 *visible = TRUE;
1305
1306         MMER_FLEAVE();
1307
1308         return MM_ERROR_NONE;
1309 }
1310
1311 int mm_evas_renderer_set_rotation(MMHandleType handle, int rotate)
1312 {
1313         MMER_FENTER();
1314
1315         int ret = MM_ERROR_NONE;
1316         mm_evas_info *evas_info = (mm_evas_info *)handle;
1317         guint value;
1318
1319         if (!evas_info) {
1320                 LOGW("skip it. it is not evas surface type or handle is not prepared");
1321                 return MM_ERROR_RESOURCE_NOT_INITIALIZED;
1322         }
1323
1324         switch (rotate) {
1325         case DEGREE_0:
1326                 value = EVAS_IMAGE_ORIENT_0;
1327                 break;
1328         case DEGREE_90:
1329                 value = EVAS_IMAGE_ORIENT_90;
1330                 break;
1331         case DEGREE_180:
1332                 value = EVAS_IMAGE_ORIENT_180;
1333                 break;
1334         case DEGREE_270:
1335                 value = EVAS_IMAGE_ORIENT_270;
1336                 break;
1337         default:
1338                 return MM_ERROR_INVALID_ARGUMENT;
1339         }
1340         if (evas_info->rotate_angle != value) {
1341                 evas_info->update_needed = TRUE;
1342                 evas_info->rotate_angle = value;
1343         }
1344
1345         /* FIXME: pause state only */
1346         if (evas_info->epipe) {
1347                 g_mutex_lock(&evas_info->idx_lock);
1348                 ret = ecore_pipe_write(evas_info->epipe, evas_info, UPDATE_TBM_SURF);
1349                 if (!ret) {
1350                         LOGW("fail to ecore_pipe_write() for updating visibility\n");
1351                         ret = MM_ERROR_UNKNOWN;
1352                 } else {
1353                         ret = MM_ERROR_NONE;
1354                 }
1355                 g_mutex_unlock(&evas_info->idx_lock);
1356         }
1357         MMER_FLEAVE();
1358
1359         return ret;
1360 }
1361
1362 int mm_evas_renderer_get_rotation(MMHandleType handle, int *rotate)
1363 {
1364         MMER_FENTER();
1365
1366         mm_evas_info *evas_info = (mm_evas_info *)handle;
1367
1368         if (!evas_info) {
1369                 LOGW("skip it. it is not evas surface type or handle is not prepared");
1370                 return MM_ERROR_RESOURCE_NOT_INITIALIZED;
1371         }
1372
1373         switch (evas_info->rotate_angle) {
1374         case EVAS_IMAGE_ORIENT_0:
1375                 *rotate = DEGREE_0;
1376                 break;
1377         case EVAS_IMAGE_ORIENT_90:
1378                 *rotate = DEGREE_90;
1379                 break;
1380         case EVAS_IMAGE_ORIENT_180:
1381                 *rotate = DEGREE_180;
1382                 break;
1383         case EVAS_IMAGE_ORIENT_270:
1384                 *rotate = DEGREE_270;
1385                 break;
1386         default:
1387                 return MM_ERROR_INVALID_ARGUMENT;
1388         }
1389
1390         MMER_FLEAVE();
1391
1392         return MM_ERROR_NONE;
1393 }
1394
1395 int mm_evas_renderer_set_geometry(MMHandleType handle, int mode)
1396 {
1397         MMER_FENTER();
1398
1399         int ret = MM_ERROR_NONE;
1400         mm_evas_info *evas_info = (mm_evas_info *)handle;
1401
1402         if (!evas_info) {
1403                 LOGW("skip it. it is not evas surface type or handle is not prepared");
1404                 return MM_ERROR_RESOURCE_NOT_INITIALIZED;
1405         }
1406         if (evas_info->display_geometry_method != mode) {
1407                 evas_info->update_needed = TRUE;
1408                 evas_info->display_geometry_method = mode;
1409         }
1410
1411         /* ecore_pipe_write is needed, because of setting ratio for letterbox mode */
1412         /* FIXME: pause state only */
1413         if (evas_info->epipe) {
1414                 g_mutex_lock(&evas_info->idx_lock);
1415                 ret = ecore_pipe_write(evas_info->epipe, evas_info, UPDATE_TBM_SURF);
1416                 if (!ret) {
1417                         LOGW("fail to ecore_pipe_write() for updating visibility\n");
1418                         ret = MM_ERROR_UNKNOWN;
1419                 } else {
1420                         ret = MM_ERROR_NONE;
1421                 }
1422                 g_mutex_unlock(&evas_info->idx_lock);
1423         }
1424         MMER_FLEAVE();
1425
1426         return ret;
1427 }
1428
1429 int mm_evas_renderer_get_geometry(MMHandleType handle, int *mode)
1430 {
1431         MMER_FENTER();
1432
1433         mm_evas_info *evas_info = (mm_evas_info *)handle;
1434
1435         if (!evas_info) {
1436                 LOGW("skip it. it is not evas surface type or handle is not prepared");
1437                 return MM_ERROR_RESOURCE_NOT_INITIALIZED;
1438         }
1439         *mode = evas_info->display_geometry_method;
1440
1441         MMER_FLEAVE();
1442
1443         return MM_ERROR_NONE;
1444 }
1445
1446 int mm_evas_renderer_set_roi_area(MMHandleType handle, int x, int y, int w, int h)
1447 {
1448         MMER_FENTER();
1449
1450         int ret = MM_ERROR_NONE;
1451         mm_evas_info *evas_info = (mm_evas_info *)handle;
1452
1453         if (!evas_info) {
1454                 LOGW("skip it. it is not evas surface type or handle is not prepared");
1455                 return MM_ERROR_RESOURCE_NOT_INITIALIZED;
1456         }
1457         if (!w || !h) {
1458                 LOGW("invalid resolution");
1459                 return MM_ERROR_INVALID_ARGUMENT;
1460         }
1461
1462         /* display mode is set to DISP_GEO_METHOD_CUSTOM_ROI internally */
1463         if (evas_info->display_geometry_method != DISP_GEO_METHOD_CUSTOM_ROI)
1464                 evas_info->update_needed = TRUE;
1465         evas_info->display_geometry_method = DISP_GEO_METHOD_CUSTOM_ROI;
1466         evas_info->dst_roi.x = x;
1467         evas_info->dst_roi.y = y;
1468         evas_info->dst_roi.w = w;
1469         evas_info->dst_roi.h = h;
1470
1471         /* pipe_write could be needed because ratio can be changed on pause state */
1472         if (evas_info->epipe) {
1473                 g_mutex_lock(&evas_info->idx_lock);
1474                 ret = ecore_pipe_write(evas_info->epipe, evas_info, UPDATE_TBM_SURF);
1475                 if (!ret) {
1476                         LOGW("fail to ecore_pipe_write() for updating visibility\n");
1477                         ret = MM_ERROR_UNKNOWN;
1478                 } else {
1479                         ret = MM_ERROR_NONE;
1480                 }
1481                 g_mutex_unlock(&evas_info->idx_lock);
1482         }
1483
1484         MMER_FLEAVE();
1485
1486         return ret;
1487 }
1488
1489 int mm_evas_renderer_get_roi_area(MMHandleType handle, int *x, int *y, int *w, int *h)
1490 {
1491         MMER_FENTER();
1492
1493         mm_evas_info *evas_info = (mm_evas_info *)handle;
1494
1495         if (!evas_info) {
1496                 LOGW("skip it. it is not evas surface type or handle is not prepared");
1497                 return MM_ERROR_RESOURCE_NOT_INITIALIZED;
1498         }
1499         if (evas_info->display_geometry_method != DISP_GEO_METHOD_CUSTOM_ROI) {
1500                 LOGW("invalid mode");
1501                 return MM_ERROR_INVALID_ARGUMENT;
1502         }
1503
1504         *x = evas_info->dst_roi.x;
1505         *y = evas_info->dst_roi.y;
1506         *w = evas_info->dst_roi.w;
1507         *h = evas_info->dst_roi.h;
1508
1509         MMER_FLEAVE();
1510
1511         return MM_ERROR_NONE;
1512 }
1513
1514 int mm_evas_renderer_set_flip(MMHandleType handle, int flip)
1515 {
1516         MMER_FENTER();
1517
1518         int ret = MM_ERROR_NONE;
1519         mm_evas_info *evas_info = (mm_evas_info *)handle;
1520         guint value;
1521
1522         if (!evas_info) {
1523                 LOGW("skip it. it is not evas surface type or handle is not prepared");
1524                 return MM_ERROR_RESOURCE_NOT_INITIALIZED;
1525         }
1526
1527         switch (flip) {
1528         case FLIP_NONE:
1529                 value = EVAS_IMAGE_ORIENT_NONE;
1530                 break;
1531         case FLIP_HORIZONTAL:
1532                 value = EVAS_IMAGE_FLIP_HORIZONTAL;
1533                 break;
1534         case FLIP_VERTICAL:
1535                 value = EVAS_IMAGE_FLIP_VERTICAL;
1536                 break;
1537         case FLIP_BOTH:
1538                 value = EVAS_IMAGE_ORIENT_180;
1539                 break;
1540         default:
1541                 return MM_ERROR_INVALID_ARGUMENT;
1542         }
1543         if (evas_info->flip != value) {
1544                 evas_info->update_needed = TRUE;
1545                 evas_info->flip = value;
1546         }
1547
1548         /* FIXME: pause state only */
1549         if (evas_info->epipe) {
1550                 g_mutex_lock(&evas_info->idx_lock);
1551                 ret = ecore_pipe_write(evas_info->epipe, evas_info, UPDATE_TBM_SURF);
1552                 if (!ret) {
1553                         LOGW("fail to ecore_pipe_write() for updating visibility\n");
1554                         ret = MM_ERROR_UNKNOWN;
1555                 } else {
1556                         ret = MM_ERROR_NONE;
1557                 }
1558                 g_mutex_unlock(&evas_info->idx_lock);
1559         }
1560
1561         MMER_FLEAVE();
1562
1563         return ret;
1564 }
1565
1566 int mm_evas_renderer_get_flip(MMHandleType handle, int *flip)
1567 {
1568         MMER_FENTER();
1569
1570         mm_evas_info *evas_info = (mm_evas_info *)handle;
1571
1572         if (!evas_info) {
1573                 LOGW("skip it. it is not evas surface type or handle is not prepared");
1574                 return MM_ERROR_RESOURCE_NOT_INITIALIZED;
1575         }
1576
1577         switch (evas_info->flip) {
1578         case EVAS_IMAGE_ORIENT_NONE:
1579                 *flip = FLIP_NONE;
1580                 break;
1581         case EVAS_IMAGE_FLIP_HORIZONTAL:
1582                 *flip = FLIP_HORIZONTAL;
1583                 break;
1584         case EVAS_IMAGE_FLIP_VERTICAL:
1585                 *flip = FLIP_VERTICAL;
1586                 break;
1587         case EVAS_IMAGE_ORIENT_180:
1588                 *flip = FLIP_BOTH;
1589                 break;
1590         default:
1591                 return MM_ERROR_INVALID_ARGUMENT;
1592         }
1593
1594         MMER_FLEAVE();
1595
1596         return MM_ERROR_NONE;
1597 }
1598
1599 int mm_evas_renderer_retrieve_all_packets(MMHandleType handle, bool keep_screen)
1600 {
1601         MMER_FENTER();
1602
1603         int ret = MM_ERROR_NONE;
1604         mm_evas_info *evas_info = (mm_evas_info*) handle;
1605
1606         if (!evas_info) {
1607                 LOGW("skip it. it is not evas surface type or player is not prepared");
1608                 return MM_ERROR_RESOURCE_NOT_INITIALIZED;
1609         }
1610         ret = _mm_evas_renderer_retrieve_all_packets(evas_info, keep_screen);
1611
1612         MMER_FLEAVE();
1613
1614         return ret;
1615 }
1616
1617 int mm_evas_renderer_set_packet_rendered_callback(MMHandleType handle, mm_evas_renderer_media_packet_rendered_cb callback, void *user_data)
1618 {
1619         MMER_FENTER();
1620
1621         mm_evas_info *evas_info = (mm_evas_info*) handle;
1622
1623         if (!evas_info) {
1624                 LOGW("skip it. it is not evas surface type or player is not prepared");
1625                 return MM_ERROR_RESOURCE_NOT_INITIALIZED;
1626         }
1627         evas_info->packet_rendered_cb = callback;
1628         evas_info->packet_rendered_cb_user = user_data;
1629
1630         LOGW("set rendered callback %p, user_data %p", evas_info->packet_rendered_cb, evas_info->packet_rendered_cb_user);
1631
1632         MMER_FLEAVE();
1633
1634         return MM_ERROR_NONE;
1635 }