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