[0.0.2] add flip API and support rotation/flip
[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 #define MM_CHECK_NULL( x_var ) \
40 if ( ! x_var ) \
41 { \
42         LOGE("[%s] is NULL\n", #x_var ); \
43         return MM_ERROR_INVALID_ARGUMENT; \
44 }
45
46 #define SET_EVAS_OBJECT_EVENT_CALLBACK( x_evas_image_object, x_usr_data ) \
47         do \
48         { \
49                 if (x_evas_image_object) { \
50                         LOGD("object callback add"); \
51                         evas_object_event_callback_add (x_evas_image_object, EVAS_CALLBACK_DEL, _evas_del_cb, x_usr_data); \
52                         evas_object_event_callback_add (x_evas_image_object, EVAS_CALLBACK_RESIZE, _evas_resize_cb, x_usr_data); \
53                 } \
54         } while(0)
55
56 #define UNSET_EVAS_OBJECT_EVENT_CALLBACK( x_evas_image_object ) \
57         do \
58         { \
59                 if (x_evas_image_object) { \
60                         LOGD("object callback del"); \
61                         evas_object_event_callback_del (x_evas_image_object, EVAS_CALLBACK_DEL, _evas_del_cb); \
62                         evas_object_event_callback_del (x_evas_image_object, EVAS_CALLBACK_RESIZE, _evas_resize_cb); \
63                 } \
64         } while(0)
65
66 #define SET_EVAS_EVENT_CALLBACK( x_evas, x_usr_data ) \
67         do \
68         { \
69                 if (x_evas) { \
70                         LOGD("callback add... evas_callback_render_pre.. evas : %p evas_info : %p", x_evas, x_usr_data); \
71                         evas_event_callback_add (x_evas, EVAS_CALLBACK_RENDER_PRE, _evas_render_pre_cb, x_usr_data); \
72                 } \
73         } while(0)
74
75 #define UNSET_EVAS_EVENT_CALLBACK( x_evas ) \
76         do \
77         { \
78                 if (x_evas) { \
79                         LOGD("callback del... evas_callback_render_pre %p", x_evas); \
80                         evas_event_callback_del (x_evas, EVAS_CALLBACK_RENDER_PRE, _evas_render_pre_cb); \
81                 } \
82         } while(0)
83
84 enum {
85         DISP_GEO_METHOD_LETTER_BOX = 0,
86         DISP_GEO_METHOD_ORIGIN_SIZE,
87         DISP_GEO_METHOD_FULL_SCREEN,
88         DISP_GEO_METHOD_CROPPED_FULL_SCREEN,
89         DISP_GEO_METHOD_ORIGIN_SIZE_OR_LETTER_BOX,
90         DISP_GEO_METHOD_NUM,
91 };
92
93 enum {
94         DEGREE_0 = 0,
95         DEGREE_90,
96         DEGREE_180,
97         DEGREE_270,
98         DEGREE_NUM,
99 };
100
101 enum {
102         FLIP_NONE = 0,
103         FLIP_HORIZONTAL,
104         FLIP_VERTICAL,
105         FLIP_BOTH,
106         FLIP_NUM,
107 };
108
109 #ifdef _INTERNAL_DEBUG_
110 void __print_idx(mm_evas_info *evas_info);
111 #endif
112 /* internal */
113 void _free_previous_packets(mm_evas_info *evas_info);
114 int _flush_packets(mm_evas_info *evas_info);
115 int _mm_evas_renderer_create(mm_evas_info **evas_info);
116 int _mm_evas_renderer_destroy(mm_evas_info **evas_info);
117 int _mm_evas_renderer_set_info(mm_evas_info *evas_info, Evas_Object *eo);
118 int _mm_evas_renderer_reset(mm_evas_info *evas_info);
119 void _mm_evas_renderer_update_geometry(mm_evas_info *evas_info, rect_info *result);
120 int _mm_evas_renderer_apply_geometry(mm_evas_info *evas_info);
121 int _mm_evas_renderer_retrieve_all_packets(mm_evas_info *evas_info, bool keep_screen);
122 int _mm_evas_renderer_make_flush_buffer(mm_evas_info *evas_info);
123 void _mm_evas_renderer_release_flush_buffer(mm_evas_info *evas_info);
124 static void _mm_evas_renderer_set_callback(mm_evas_info *evas_info);
125 static void _mm_evas_renderer_unset_callback(mm_evas_info *evas_info);
126
127 static void _evas_resize_cb(void *data, Evas *e, Evas_Object *obj, void *event_info)
128 {
129         int x, y, w, h, ret;
130         x = y = w = h = 0;
131
132         mm_evas_info *evas_info = data;
133         LOGD("[ENTER]");
134
135         if (!evas_info || !evas_info->eo) {
136                 return;
137         }
138
139         evas_object_geometry_get(evas_info->eo, &x, &y, &w, &h);
140         if (!w || !h) {
141                 LOGW("evas object size (w:%d,h:%d) was not set", w, h);
142         } else {
143                 evas_info->eo_size.x = x;
144                 evas_info->eo_size.y = y;
145                 evas_info->eo_size.w = w;
146                 evas_info->eo_size.h = h;
147                 LOGW("resize (x:%d, y:%d, w:%d, h:%d)", x, y, w, h);
148                 ret = _mm_evas_renderer_apply_geometry(evas_info);
149                 if (ret != MM_ERROR_NONE)
150                         LOGW("fail to apply geometry info");
151         }
152         LOGD("[LEAVE]");
153 }
154
155 static void _evas_render_pre_cb(void *data, Evas *e, void *event_info)
156 {
157         mm_evas_info *evas_info = data;
158
159         if (!evas_info || !evas_info->eo) {
160                 LOGW("there is no esink info.... esink : %p, or eo is NULL returning", evas_info);
161                 return;
162         }
163
164         /* flush will be executed in this callback normally,
165         because native_surface_set must be called in main thread */
166         if (evas_info->retrieve_packet) {
167                 g_mutex_lock(&evas_info->idx_lock);
168                 if (_flush_packets(evas_info) != MM_ERROR_NONE)
169                         LOGE("flushing packets are failed");
170                 g_mutex_unlock(&evas_info->idx_lock);
171         }
172 }
173
174 static void _evas_del_cb(void *data, Evas *e, Evas_Object *obj, void *event_info)
175 {
176         mm_evas_info *evas_info = data;
177         LOGD("[ENTER]");
178         if (!evas_info || !evas_info->eo) {
179                 return;
180         }
181         if (evas_info->eo) {
182                 _mm_evas_renderer_unset_callback(evas_info);
183                 evas_object_image_data_set(evas_info->eo, NULL);
184                 evas_info->eo = NULL;
185         }
186         LOGD("[LEAVE]");
187 }
188
189 void _evas_pipe_cb(void *data, void *buffer, update_info info)
190 {
191         mm_evas_info *evas_info = data;
192
193         LOGD("[ENTER]");
194
195         if (!evas_info) {
196                 LOGW("evas_info is NULL", evas_info);
197                 return;
198         }
199
200         g_mutex_lock(&evas_info->mp_lock);
201
202         if (!evas_info->eo) {
203                 LOGW("evas_info %p", evas_info);
204                 g_mutex_unlock(&evas_info->mp_lock);
205                 return;
206         }
207
208         LOGD("evas_info : %p, evas_info->eo : %p", evas_info, evas_info->eo);
209         if (info == UPDATE_VISIBILITY) {
210                 if (evas_info->visible == VISIBLE_FALSE) {
211                         evas_object_hide(evas_info->eo);
212                         LOGI("object hide..");
213                 } else {
214                         evas_object_show(evas_info->eo);
215                         LOGI("object show.. %d", evas_info->visible);
216                 }
217                 LOGD("[LEAVE]");
218                 g_mutex_unlock(&evas_info->mp_lock);
219                 return;
220         }
221
222         if (info != UPDATE_TBM_SURF) {
223                 LOGW("invalid info type : %d", info);
224                 g_mutex_unlock(&evas_info->mp_lock);
225                 return;
226         }
227
228         if (evas_info->cur_idx==-1 || !evas_info->pkt_info[evas_info->cur_idx].tbm_surf) {
229                 LOGW("cur_idx %d, tbm_surf may be NULL", evas_info->cur_idx);
230                 g_mutex_unlock(&evas_info->mp_lock);
231                 return;
232         }
233         /* perhaps, it is needed to skip setting when state is pause */
234
235         g_mutex_lock(&evas_info->idx_lock);
236         /* index */
237         gint cur_idx = evas_info->cur_idx;
238         gint prev_idx = evas_info->pkt_info[cur_idx].prev;
239
240         LOGD("received (idx %d, packet %p)", cur_idx, evas_info->pkt_info[cur_idx].packet);
241
242         tbm_format tbm_fmt = tbm_surface_get_format(evas_info->pkt_info[cur_idx].tbm_surf);
243         switch (tbm_fmt) {
244         case TBM_FORMAT_NV12:
245                 LOGD("tbm_surface format : TBM_FORMAT_NV12");
246                 break;
247         case TBM_FORMAT_YUV420:
248                 LOGD("tbm_surface format : TBM_FORMAT_YUV420");
249                 break;
250         default:
251                 LOGW("tbm_surface format : unknown %d", tbm_fmt);
252                 break;
253         }
254
255         Evas_Native_Surface surf;
256         surf.type = EVAS_NATIVE_SURFACE_TBM;
257         surf.version = EVAS_NATIVE_SURFACE_VERSION;
258         surf.data.tbm.buffer = evas_info->pkt_info[cur_idx].tbm_surf;
259         surf.data.tbm.rot = evas_info->rotate_angle;
260         surf.data.tbm.flip = evas_info->flip;
261
262         rect_info result = { 0 };
263
264         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);
265         if (!evas_info->eo_size.w || !evas_info->eo_size.h) {
266                 LOGE("there is no information for evas object size");
267                 goto ERROR;
268         }
269         _mm_evas_renderer_update_geometry(evas_info, &result);
270         if (!result.w || !result.h) {
271                 LOGE("no information about geometry (%d, %d)", result.w, result.h);
272                 goto ERROR;
273         }
274
275         if (evas_info->use_ratio) {
276                 surf.data.tbm.ratio = (float) evas_info->w / evas_info->h;
277                 LOGD("set ratio for letter mode");
278         }
279         evas_object_size_hint_align_set(evas_info->eo, EVAS_HINT_FILL, EVAS_HINT_FILL);
280         evas_object_size_hint_weight_set(evas_info->eo, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
281         if (evas_info->w > 0 && evas_info->h > 0)
282                 evas_object_image_size_set(evas_info->eo, evas_info->w, evas_info->h);
283
284         evas_object_image_native_surface_set(evas_info->eo, &surf);
285         LOGD("native surface set finish");
286
287         if (result.x || result.y)
288                 LOGD("coordinate x, y (%d, %d) for locating video to center", result.x, result.y);
289         evas_object_image_fill_set(evas_info->eo, result.x, result.y, result.w, result.h);
290
291         evas_object_image_pixels_dirty_set(evas_info->eo, EINA_TRUE);
292         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);
293
294         /* when _evas_pipe_cb is called sequentially, previous packet and current packet will be the same */
295         if ((prev_idx != -1) && evas_info->pkt_info[prev_idx].packet && (prev_idx != cur_idx))
296                 _free_previous_packets(evas_info);
297
298         LOGD("[LEAVE]");
299         g_mutex_unlock(&evas_info->idx_lock);
300         g_mutex_unlock(&evas_info->mp_lock);
301
302         return;
303
304  ERROR:
305         if ((prev_idx != -1) && evas_info->pkt_info[prev_idx].packet) {
306                 LOGI("cant render");
307                 _free_previous_packets(evas_info);
308         }
309         g_mutex_unlock(&evas_info->idx_lock);
310         g_mutex_unlock(&evas_info->mp_lock);
311 }
312
313 #ifdef _INTERNAL_DEBUG_
314 void __print_idx(mm_evas_info *evas_info)
315 {
316         gint prev_idx = evas_info->pkt_info[evas_info->cur_idx].prev;
317         LOGE("***** start cur_idx : %d -> prev_idx : %d", evas_info->cur_idx, prev_idx);
318         while(prev_idx != -1)
319         {
320                 LOGE("***** cur_idx : %d -> prev_idx : %d", prev_idx, evas_info->pkt_info[prev_idx].prev);
321                 prev_idx = evas_info->pkt_info[prev_idx].prev;
322         }
323         LOGE("***** end");
324         return;
325 }
326 #endif
327
328 void _free_previous_packets(mm_evas_info *evas_info)
329 {
330         gint index = evas_info->cur_idx;
331         gint prev_idx = evas_info->pkt_info[index].prev;
332
333         while(prev_idx != -1)
334         {
335                 LOGD("destroy previous packet [%p] idx %d", evas_info->pkt_info[prev_idx].packet, prev_idx);
336                 if (media_packet_destroy(evas_info->pkt_info[prev_idx].packet) != MEDIA_PACKET_ERROR_NONE)
337                         LOGE("media_packet_destroy failed %p", evas_info->pkt_info[prev_idx].packet);
338                 evas_info->pkt_info[prev_idx].packet = NULL;
339                 evas_info->pkt_info[prev_idx].tbm_surf = NULL;
340                 evas_info->pkt_info[index].prev = -1;
341                 evas_info->sent_buffer_cnt--;
342
343                 /* move index to previous index */
344                 index= prev_idx;
345                 prev_idx = evas_info->pkt_info[prev_idx].prev;
346                 LOGD("sent packet %d", evas_info->sent_buffer_cnt);
347         }
348         return;
349 }
350
351 static int _get_video_size(media_packet_h packet, mm_evas_info *evas_info)
352 {
353         media_format_h fmt;
354         if (media_packet_get_format(packet, &fmt) == MEDIA_PACKET_ERROR_NONE) {
355                 int w, h;
356                 if (media_format_get_video_info(fmt, NULL, &w, &h, NULL, NULL) == MEDIA_PACKET_ERROR_NONE) {
357                         LOGD("video width = %d, height =%d", w, h);
358                         evas_info->w = w;
359                         evas_info->h = h;
360                         return true;
361                 } else
362                         LOGW("media_format_get_video_info is failed");
363                 if (media_format_unref(fmt) != MEDIA_PACKET_ERROR_NONE) /* because of media_packet_get_format */
364                         LOGW("media_format_unref is failed");
365         } else {
366                 LOGW("media_packet_get_format is failed");
367         }
368         return false;
369 }
370
371 int _find_empty_index(mm_evas_info *evas_info)
372 {
373         int i;
374         for (i = 0; i < MAX_PACKET_NUM; i++) {
375                 if (!evas_info->pkt_info[i].packet) {
376                         LOGD("selected idx %d", i);
377                         return i;
378                 }
379         }
380         LOGE("there is no empty idx");
381
382         return -1;
383 }
384
385 int _flush_packets(mm_evas_info *evas_info)
386 {
387         int ret = MM_ERROR_NONE;
388         int ret_mp = MEDIA_PACKET_ERROR_NONE;
389         int i = 0;
390
391         if (!evas_info) {
392                 LOGW("there is no esink info");
393                 return MM_ERROR_INVALID_ARGUMENT;
394         }
395         /* update the screen only if visible is ture */
396         if (evas_info->keep_screen && (evas_info->visible != VISIBLE_FALSE)) {
397                 Evas_Native_Surface surf;
398                 rect_info result = { 0 };
399                 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);
400                 if (!evas_info->eo_size.w || !evas_info->eo_size.h) {
401                         LOGE("there is no information for evas object size");
402                         return MM_ERROR_INVALID_ARGUMENT;
403                 }
404                 _mm_evas_renderer_update_geometry(evas_info, &result);
405                 if (!result.w || !result.h) {
406                         LOGE("no information about geometry (%d, %d)", result.w, result.h);
407                         return MM_ERROR_INVALID_ARGUMENT;
408                 }
409
410                 if (evas_info->use_ratio) {
411                         surf.data.tbm.ratio = (float) evas_info->w / evas_info->h;
412                         LOGD("set ratio for letter mode");
413                 }
414                 evas_object_size_hint_align_set(evas_info->eo, EVAS_HINT_FILL, EVAS_HINT_FILL);
415                 evas_object_size_hint_weight_set(evas_info->eo, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
416                 if (evas_info->w > 0 && evas_info->h > 0)
417                         evas_object_image_size_set(evas_info->eo, evas_info->w, evas_info->h);
418
419                 if (result.x || result.y)
420                         LOGD("coordinate x, y (%d, %d) for locating video to center", result.x, result.y);
421                 evas_object_image_fill_set(evas_info->eo, result.x, result.y, result.w, result.h);
422
423                 /* set flush buffer */
424                 surf.type = EVAS_NATIVE_SURFACE_TBM;
425                 surf.version = EVAS_NATIVE_SURFACE_VERSION;
426                 surf.data.tbm.buffer = evas_info->flush_buffer->tbm_surf;
427                 surf.data.tbm.rot = evas_info->rotate_angle;
428                 surf.data.tbm.flip = evas_info->flip;
429                 evas_object_image_native_surface_set(evas_info->eo, &surf);
430
431                 LOGD("flush_buffer surf(%p), rotate(%d), flip(%d)", evas_info->flush_buffer->tbm_surf, evas_info->rotate_angle, evas_info->flip);
432         } else {
433                 /* unset evas native surface for displaying black screen */
434                 evas_object_image_native_surface_set (evas_info->eo, NULL);
435                 evas_object_image_data_set (evas_info->eo, NULL);
436         }
437         LOGD("sent packet %d", evas_info->sent_buffer_cnt);
438
439         /* destroy all packets */
440         g_mutex_lock(&evas_info->mp_lock);
441         for (i = 0; i < MAX_PACKET_NUM; i++) {
442                 if (evas_info->pkt_info[i].packet) {
443                         LOGD("destroy packet [%p]", evas_info->pkt_info[i].packet);
444                         ret_mp = media_packet_destroy(evas_info->pkt_info[i].packet);
445                         if (ret_mp != MEDIA_PACKET_ERROR_NONE) {
446                                 LOGW("media_packet_destroy failed %p", evas_info->pkt_info[i].packet);
447                                 ret = MM_ERROR_UNKNOWN;
448                         }
449                         else
450                                 evas_info->sent_buffer_cnt--;
451                         evas_info->pkt_info[i].packet = NULL;
452                         evas_info->pkt_info[i].tbm_surf = NULL;
453                         evas_info->pkt_info[i].prev = -1;
454                 }
455         }
456
457         if (evas_info->sent_buffer_cnt != 0)
458                 LOGE("it should be 0 --> [%d]", evas_info->sent_buffer_cnt);
459         evas_info->sent_buffer_cnt = 0;
460         evas_info->cur_idx = -1;
461         g_mutex_unlock(&evas_info->mp_lock);
462
463         evas_object_image_pixels_dirty_set (evas_info->eo, EINA_TRUE);
464         evas_info->retrieve_packet = FALSE;
465
466         return ret;
467 }
468
469 #if 0
470 int _reset_pipe(mm_evas_info *evas_info)
471 {
472         int i = 0;
473         int ret = MM_ERROR_NONE;
474         int ret_mp = MEDIA_PACKET_ERROR_NONE;
475
476         /* delete old pipe */
477         if (evas_info->epipe) {
478                 LOGD("pipe %p will be deleted", evas_info->epipe);
479                 ecore_pipe_del(evas_info->epipe);
480                 evas_info->epipe = NULL;
481         }
482
483         for (i = 0; i < MAX_PACKET_NUM; i++) {
484                 if (evas_info->pkt_info[i].packet) {
485                         /* destroy all packets */
486                         LOGD("destroy packet [%p]", evas_info->pkt_info[i].packet);
487                         ret_mp = media_packet_destroy(evas_info->pkt_info[i].packet);
488                         if (ret_mp != MEDIA_PACKET_ERROR_NONE) {
489                                 LOGW("media_packet_destroy failed %p", evas_info->pkt_info[i].packet);
490                                 ret = MM_ERROR_UNKNOWN;
491                         }
492                         else
493                                 evas_info->sent_buffer_cnt--;
494                         evas_info->pkt_info[i].packet = NULL;
495                         evas_info->pkt_info[i].tbm_surf = NULL;
496                         evas_info->pkt_info[i].prev = -1;
497                 }
498         }
499
500         if (evas_info->sent_buffer_cnt != 0)
501                 LOGE("it should be 0 --> [%d]", evas_info->sent_buffer_cnt);
502         evas_info->sent_buffer_cnt = 0;
503         evas_info->cur_idx = -1;
504
505         /* make new pipe */
506         if (!evas_info->epipe) {
507                 evas_info->epipe = ecore_pipe_add((Ecore_Pipe_Cb) _evas_pipe_cb, evas_info);
508                 if (!evas_info->epipe) {
509                         LOGE("pipe is not created");
510                         ret = MM_ERROR_UNKNOWN;
511                 }
512                 LOGD("created pipe %p", evas_info->epipe);
513         }
514
515         return ret;
516 }
517 #endif
518
519 static void _mm_evas_renderer_set_callback(mm_evas_info *evas_info)
520 {
521         if (evas_info->eo) {
522                 SET_EVAS_OBJECT_EVENT_CALLBACK(evas_info->eo, evas_info);
523                 SET_EVAS_EVENT_CALLBACK(evas_object_evas_get(evas_info->eo), evas_info);
524         }
525 }
526
527 static void _mm_evas_renderer_unset_callback(mm_evas_info *evas_info)
528 {
529         if (evas_info->eo) {
530                 UNSET_EVAS_OBJECT_EVENT_CALLBACK(evas_info->eo);
531                 UNSET_EVAS_EVENT_CALLBACK(evas_object_evas_get(evas_info->eo));
532         }
533 }
534
535 int _mm_evas_renderer_create(mm_evas_info **evas_info)
536 {
537         mm_evas_info *ptr = NULL;
538         ptr = g_malloc0(sizeof(mm_evas_info));
539
540         if (!ptr) {
541                 LOGE("Cannot allocate memory for evas_info\n");
542                 goto ERROR;
543         } else {
544                 *evas_info = ptr;
545                 LOGD("Success create evas_info(%p)", *evas_info);
546         }
547         g_mutex_init(&ptr->mp_lock);
548         g_mutex_init(&ptr->idx_lock);
549
550         return MM_ERROR_NONE;
551
552  ERROR:
553         *evas_info = NULL;
554         return MM_ERROR_OUT_OF_STORAGE;
555 }
556
557 int _mm_evas_renderer_destroy(mm_evas_info **evas_info)
558 {
559         mm_evas_info *ptr = (mm_evas_info *)*evas_info;
560         MM_CHECK_NULL(ptr);
561         int ret = MM_ERROR_NONE;
562
563         LOGD("finalize evas_info %p", ptr);
564
565         ret = _mm_evas_renderer_reset(ptr);
566         g_mutex_clear(&ptr->mp_lock);
567         g_mutex_clear(&ptr->idx_lock);
568
569         g_free(ptr);
570         ptr = NULL;
571
572         return ret;
573 }
574
575 int _mm_evas_renderer_set_info(mm_evas_info *evas_info, Evas_Object *eo)
576 {
577         MM_CHECK_NULL(evas_info);
578         MM_CHECK_NULL(eo);
579         g_mutex_lock(&evas_info->idx_lock);
580
581         LOGD("set evas_info");
582         int i;
583         for (i = 0; i < MAX_PACKET_NUM; i++) {
584                 evas_info->pkt_info[i].packet = NULL;
585                 evas_info->pkt_info[i].tbm_surf = NULL;
586                 evas_info->pkt_info[i].prev = -1;
587         }
588
589         evas_info->cur_idx = -1;
590         evas_info->eo = eo;
591         evas_info->epipe = ecore_pipe_add((Ecore_Pipe_Cb) _evas_pipe_cb, evas_info);
592         if (!evas_info->epipe) {
593                 LOGE("pipe is not created");
594                 g_mutex_unlock(&evas_info->idx_lock);
595                 return MM_ERROR_UNKNOWN;
596         }
597         LOGD("created pipe %p", evas_info->epipe);
598         _mm_evas_renderer_set_callback(evas_info);
599
600         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);
601         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);
602
603         g_mutex_unlock(&evas_info->idx_lock);
604
605         return MM_ERROR_NONE;
606 }
607
608 int _mm_evas_renderer_reset(mm_evas_info *evas_info)
609 {
610         MM_CHECK_NULL(evas_info);
611         g_mutex_lock(&evas_info->idx_lock);
612
613         int i;
614         int ret = MM_ERROR_NONE;
615         int ret_mp = MEDIA_PACKET_ERROR_NONE;
616
617         if (evas_info->eo) {
618                 _mm_evas_renderer_unset_callback(evas_info);
619                 evas_object_image_data_set(evas_info->eo, NULL);
620                 evas_info->eo = NULL;
621         }
622         if (evas_info->epipe) {
623                 LOGD("pipe %p will be deleted", evas_info->epipe);
624                 ecore_pipe_del(evas_info->epipe);
625                 evas_info->epipe = NULL;
626         }
627
628         evas_info->eo_size.x = evas_info->eo_size.y = evas_info->eo_size.w = evas_info->eo_size.h = 0;
629         evas_info->w = evas_info->h = 0;
630
631         if (evas_info->flush_buffer)
632                 _mm_evas_renderer_release_flush_buffer(evas_info);
633
634         g_mutex_lock(&evas_info->mp_lock);
635         for (i = 0; i < MAX_PACKET_NUM; i++) {
636                 if (evas_info->pkt_info[i].packet) {
637                         /* destroy all packets */
638                         LOGD("destroy packet [%p]", evas_info->pkt_info[i].packet);
639                         ret_mp = media_packet_destroy(evas_info->pkt_info[i].packet);
640                         if (ret_mp != MEDIA_PACKET_ERROR_NONE) {
641                                 LOGW("media_packet_destroy failed %p", evas_info->pkt_info[i].packet);
642                                 ret = MM_ERROR_UNKNOWN;
643                         }
644                         else
645                                 evas_info->sent_buffer_cnt--;
646                         evas_info->pkt_info[i].packet = NULL;
647                         evas_info->pkt_info[i].tbm_surf = NULL;
648                         evas_info->pkt_info[i].prev = -1;
649                 }
650         }
651         g_mutex_unlock(&evas_info->mp_lock);
652         if (evas_info->sent_buffer_cnt != 0)
653                 LOGE("it should be 0 --> [%d]", evas_info->sent_buffer_cnt);
654         evas_info->sent_buffer_cnt = 0;
655         evas_info->cur_idx = -1;
656
657         g_mutex_unlock(&evas_info->idx_lock);
658
659         return ret;
660 }
661
662 void _mm_evas_renderer_update_geometry(mm_evas_info *evas_info, rect_info *result)
663 {
664         if (!evas_info || !evas_info->eo) {
665                 LOGW("there is no evas_info or evas object");
666                 return;
667         }
668         if (!result) {
669                 LOGW("there is no rect info");
670                 return;
671         }
672
673         result->x = 0;
674         result->y = 0;
675
676         switch (evas_info->display_geometry_method) {
677         case DISP_GEO_METHOD_LETTER_BOX:
678                 /* set black padding for letter box mode */
679                 LOGD("letter box mode");
680                 evas_info->use_ratio = TRUE;
681                 result->w = evas_info->eo_size.w;
682                 result->h = evas_info->eo_size.h;
683                 break;
684         case DISP_GEO_METHOD_ORIGIN_SIZE:
685                 LOGD("origin size mode");
686                 evas_info->use_ratio = FALSE;
687                 /* set coordinate for each case */
688                 result->x = (evas_info->eo_size.w - evas_info->w) / 2;
689                 result->y = (evas_info->eo_size.h - evas_info->h) / 2;
690                 result->w = evas_info->w;
691                 result->h = evas_info->h;
692                 break;
693         case DISP_GEO_METHOD_FULL_SCREEN:
694                 LOGD("full screen mode");
695                 evas_info->use_ratio = FALSE;
696                 result->w = evas_info->eo_size.w;
697                 result->h = evas_info->eo_size.h;
698                 break;
699         case DISP_GEO_METHOD_CROPPED_FULL_SCREEN:
700                 LOGD("cropped full screen mode");
701                 evas_info->use_ratio = FALSE;
702                 /* compare evas object's ratio with video's */
703                 if ((evas_info->eo_size.w / evas_info->eo_size.h) > (evas_info->w / evas_info->h)) {
704                         result->w = evas_info->eo_size.w;
705                         result->h = evas_info->eo_size.w * evas_info->h / evas_info->w;
706                         result->y = -(result->h - evas_info->eo_size.h) / 2;
707                 } else {
708                         result->w = evas_info->eo_size.h * evas_info->w / evas_info->h;
709                         result->h = evas_info->eo_size.h;
710                         result->x = -(result->w - evas_info->eo_size.w) / 2;
711                 }
712                 break;
713         case DISP_GEO_METHOD_ORIGIN_SIZE_OR_LETTER_BOX:
714                 LOGD("origin size or letter box mode");
715                 /* if video size is smaller than evas object's, it will be set to origin size mode */
716                 if ((evas_info->eo_size.w > evas_info->w) && (evas_info->eo_size.h > evas_info->h)) {
717                         LOGD("origin size mode");
718                         evas_info->use_ratio = FALSE;
719                         /* set coordinate for each case */
720                         result->x = (evas_info->eo_size.w - evas_info->w) / 2;
721                         result->y = (evas_info->eo_size.h - evas_info->h) / 2;
722                         result->w = evas_info->w;
723                         result->h = evas_info->h;
724                 } else {
725                         LOGD("letter box mode");
726                         evas_info->use_ratio = TRUE;
727                         result->w = evas_info->eo_size.w;
728                         result->h = evas_info->eo_size.h;
729                 }
730                 break;
731         default:
732                 LOGW("unsupported mode.");
733                 break;
734         }
735         LOGD("geometry result [%d, %d, %d, %d]", result->x, result->y, result->w, result->h);
736 }
737
738 int _mm_evas_renderer_apply_geometry(mm_evas_info *evas_info)
739 {
740         if (!evas_info || !evas_info->eo) {
741                 LOGW("there is no evas_info or evas object");
742                 return MM_ERROR_NONE;
743         }
744
745         Evas_Native_Surface *surf = evas_object_image_native_surface_get(evas_info->eo);
746         rect_info result = { 0 };
747
748         if (surf) {
749                 LOGD("native surface exists");
750                 surf->data.tbm.rot = evas_info->rotate_angle;
751                 surf->data.tbm.flip = evas_info->flip;
752                 evas_object_image_native_surface_set(evas_info->eo, surf);
753
754                 _mm_evas_renderer_update_geometry(evas_info, &result);
755
756                 if (evas_info->use_ratio) {
757                         surf->data.tbm.ratio = (float) evas_info->w / evas_info->h;
758                         LOGD("set ratio for letter mode");
759                 }
760
761                 if (result.x || result.y)
762                         LOGD("coordinate x, y (%d, %d) for locating video to center", result.x, result.y);
763
764                 evas_object_image_fill_set(evas_info->eo, result.x, result.y, result.w, result.h);
765                 return MM_ERROR_NONE;
766         } else
767                 LOGW("there is no surf");
768         /* FIXME: before pipe_cb is invoked, apply_geometry can be called. */
769         return MM_ERROR_NONE;
770 }
771
772 int _mm_evas_renderer_retrieve_all_packets(mm_evas_info *evas_info, bool keep_screen)
773 {
774         MM_CHECK_NULL(evas_info);
775
776         int ret = MM_ERROR_NONE;
777         pid_t pid = getpid();
778         pid_t tid = syscall(SYS_gettid);
779
780         /* write and this API can be called at the same time.
781         so lock is needed for counting sent_buffer_cnt correctly */
782         g_mutex_lock(&evas_info->idx_lock);
783
784         /* make flush buffer */
785         if (keep_screen)
786                 ret = _mm_evas_renderer_make_flush_buffer(evas_info);
787         evas_info->keep_screen = keep_screen;
788
789         LOGD("pid [%d], tid [%d]", pid, tid);
790         if (pid == tid) {
791                 /* in this case, we deem it is main thread */
792                 if (_flush_packets(evas_info) != MM_ERROR_NONE) {
793                         LOGE("flushing packets are failed");
794                         ret = MM_ERROR_UNKNOWN;
795                 }
796         } else {
797                 /* it will be executed to write flush buffer and destroy media packets in pre_cb */
798                 evas_info->retrieve_packet = TRUE;
799         }
800         g_mutex_unlock(&evas_info->idx_lock);
801
802         return ret;
803 }
804
805 /* make buffer for copying */
806 int _mm_evas_renderer_make_flush_buffer (mm_evas_info *evas_info)
807 {
808         if (evas_info->cur_idx == -1) {
809                 LOGW("there is no remained buffer");
810                 return MM_ERROR_INVALID_ARGUMENT;
811         }
812         media_packet_h packet = evas_info->pkt_info[evas_info->cur_idx].packet;
813         MM_CHECK_NULL(packet);
814
815         flush_info *flush_buffer = NULL;
816         tbm_bo src_bo = NULL;
817         tbm_surface_h src_tbm_surf = NULL;
818         int src_size = 0;
819         int size = 0;
820         tbm_bo bo = NULL;
821         tbm_format tbm_fmt;
822         tbm_bo_handle vaddr_src = {0};
823         tbm_bo_handle vaddr_dst = {0};
824         int ret = MM_ERROR_NONE;
825
826         if (evas_info->flush_buffer)
827                 _mm_evas_renderer_release_flush_buffer(evas_info);
828
829         /* malloc buffer */
830         flush_buffer = (flush_info *)malloc(sizeof(flush_info));
831         if (flush_buffer == NULL) {
832                 LOGE("malloc is failed");
833                 return FALSE;
834         }
835         memset(flush_buffer, 0x0, sizeof(flush_info));
836
837         ret = media_packet_get_tbm_surface(packet, &src_tbm_surf);
838         if (ret != MEDIA_PACKET_ERROR_NONE || !src_tbm_surf) {
839                 LOGW("get_tbm_surface is failed");
840                 goto ERROR;
841         }
842
843         /* get src buffer info */
844         tbm_fmt = tbm_surface_get_format(src_tbm_surf);
845         src_bo = tbm_surface_internal_get_bo(src_tbm_surf, 0);
846         src_size = tbm_bo_size(src_bo);
847         if (!src_bo || !src_size) {
848                 LOGE("bo(%p), size(%d)", src_bo, src_size);
849                 goto ERROR;
850         }
851
852         /* create tbm surface */
853         flush_buffer->tbm_surf = tbm_surface_create(evas_info->w, evas_info->h, tbm_fmt);
854         if (!flush_buffer->tbm_surf)
855         {
856                 LOGE("tbm_surf is NULL!!");
857                 goto ERROR;
858         }
859
860         /* get bo and size */
861         bo = tbm_surface_internal_get_bo(flush_buffer->tbm_surf, 0);
862         size = tbm_bo_size(bo);
863         if (!bo || !size)
864         {
865                 LOGE("bo(%p), size(%d)", bo, size);
866                 goto ERROR;
867         }
868         flush_buffer->bo = bo;
869
870         vaddr_src = tbm_bo_map(src_bo, TBM_DEVICE_CPU, TBM_OPTION_READ|TBM_OPTION_WRITE);
871         vaddr_dst = tbm_bo_map(bo, TBM_DEVICE_CPU, TBM_OPTION_READ|TBM_OPTION_WRITE);
872         if (!vaddr_src.ptr || !vaddr_dst.ptr) {
873                 LOGW("get vaddr failed src %p, dst %p", vaddr_src.ptr, vaddr_dst.ptr);
874                 if (vaddr_src.ptr) {
875                         tbm_bo_unmap(src_bo);
876                 }
877                 if (vaddr_dst.ptr) {
878                         tbm_bo_unmap(bo);
879                 }
880                 goto ERROR;
881         } else {
882                 memset (vaddr_dst.ptr, 0x0, size);
883                 LOGW ("tbm_bo_map(vaddr) is finished, bo(%p), vaddr(%p)", bo, vaddr_dst.ptr);
884         }
885
886         /* copy buffer */
887         memcpy(vaddr_dst.ptr, vaddr_src.ptr, src_size);
888
889         tbm_bo_unmap(src_bo);
890         tbm_bo_unmap(bo);
891         LOGW("copy is done. tbm surface : %p src_size : %d", flush_buffer->tbm_surf, src_size);
892
893         evas_info->flush_buffer = flush_buffer;
894
895         return MM_ERROR_NONE;
896
897 ERROR:
898         if (flush_buffer) {
899                 if(flush_buffer->tbm_surf)
900                 {
901                         tbm_surface_destroy(flush_buffer->tbm_surf);
902                         flush_buffer->tbm_surf = NULL;
903                 }
904
905                 free(flush_buffer);
906                 flush_buffer = NULL;
907         }
908         return MM_ERROR_UNKNOWN;
909 }
910
911 /* release flush buffer */
912 void _mm_evas_renderer_release_flush_buffer (mm_evas_info *evas_info)
913 {
914         LOGW("release FLUSH BUFFER start");
915         if (evas_info->flush_buffer->bo) {
916                 evas_info->flush_buffer->bo = NULL;
917         }
918         if (evas_info->flush_buffer->tbm_surf) {
919                 tbm_surface_destroy(evas_info->flush_buffer->tbm_surf);
920                 evas_info->flush_buffer->tbm_surf = NULL;
921         }
922
923         LOGW("release FLUSH BUFFER done");
924
925         free(evas_info->flush_buffer);
926         evas_info->flush_buffer = NULL;
927
928         return;
929 }
930
931 void mm_evas_renderer_write(media_packet_h packet, void *data)
932 {
933         if (!packet) {
934                 LOGE("packet %p is NULL", packet);
935                 return;
936         }
937         mm_evas_info *handle = (mm_evas_info *)data;
938         int ret = MEDIA_PACKET_ERROR_NONE;
939         bool has;
940         tbm_surface_h tbm_surf;
941         gint index;
942
943         LOGD("packet [%p]", packet);
944
945         if (!data || !handle) {
946                 LOGE("handle %p or evas_info %p is NULL", data, handle);
947                 goto INVALID_PARAM;
948         }
949         g_mutex_lock(&handle->idx_lock);
950
951         ret = media_packet_has_tbm_surface_buffer(packet, &has);
952         if (ret != MEDIA_PACKET_ERROR_NONE) {
953                 LOGW("has_tbm_surface is failed");
954                 goto ERROR;
955         }
956         /* FIXME: when setCaps occurs, _get_video_size should be called */
957         /* currently we are always checking it */
958         if (has && _get_video_size(packet, handle)) {
959                 /* Attention! if this error occurs, we need to consider managing buffer */
960                 if (handle->sent_buffer_cnt > 4) {
961                         LOGE("too many buffers are not released %d", handle->sent_buffer_cnt);
962                         goto ERROR;
963 #if 0
964                         /* FIXME: fix this logic */
965                         /* destroy all media packets and reset pipe at present */
966                         /* Attention! it might free buffer that is being rendered */
967                         g_mutex_lock(&handle->mp_lock);
968                         _reset_pipe(handle);
969                         g_mutex_unlock(&handle->mp_lock);
970 #endif
971                 }
972                 ret = media_packet_get_tbm_surface(packet, &tbm_surf);
973                 if (ret != MEDIA_PACKET_ERROR_NONE || !tbm_surf) {
974                         LOGW("get_tbm_surface is failed");
975                         goto ERROR;
976                 }
977
978                 /* find new index for current packet */
979                 index = _find_empty_index(handle);
980                 if (index == -1) {
981                         goto ERROR;
982                 }
983
984                 /* save previous index */
985                 handle->pkt_info[index].prev = handle->cur_idx;
986                 handle->pkt_info[index].packet = packet;
987                 handle->pkt_info[index].tbm_surf = tbm_surf;
988                 handle->cur_idx = index;
989                 handle->sent_buffer_cnt++;
990                 LOGD("sent packet %d", handle->sent_buffer_cnt);
991
992                 ret = ecore_pipe_write(handle->epipe, handle, UPDATE_TBM_SURF);
993                 if (!ret) {
994                         handle->pkt_info[index].packet = NULL;
995                         handle->pkt_info[index].tbm_surf = NULL;
996                         handle->pkt_info[index].prev = -1;
997                         handle->cur_idx = handle->pkt_info[index].prev;
998                         handle->sent_buffer_cnt--;
999                         LOGW("Failed to ecore_pipe_write() for updating tbm surf\n");
1000                         goto ERROR;
1001                 }
1002         } else {
1003                 LOGW("no tbm_surf");
1004                 goto ERROR;
1005         }
1006         g_mutex_unlock(&handle->idx_lock);
1007
1008         return;
1009 ERROR:
1010         g_mutex_unlock(&handle->idx_lock);
1011 INVALID_PARAM:
1012         /* destroy media_packet immediately */
1013         if (packet) {
1014                 g_mutex_lock(&handle->mp_lock);
1015                 LOGD("cant write. destroy packet [%p]", packet);
1016                 if (media_packet_destroy(packet) != MEDIA_PACKET_ERROR_NONE)
1017                         LOGE("media_packet_destroy failed %p", packet);
1018                 packet = NULL;
1019                 g_mutex_unlock(&handle->mp_lock);
1020         }
1021         return;
1022 }
1023
1024 int mm_evas_renderer_update_param(MMHandleType handle)
1025 {
1026         int ret = MM_ERROR_NONE;
1027         mm_evas_info *evas_info = (mm_evas_info *)handle;
1028
1029         if (!evas_info) {
1030                 LOGW("skip it. it is not evas surface type.");
1031                 return ret;
1032         }
1033
1034         /* when handle is realized, we need to update all properties */
1035         if (evas_info) {
1036                 LOGD("set video param : evas-object %x, method %d", evas_info->eo, evas_info->display_geometry_method);
1037                 LOGD("set video param : visible %d", evas_info->visible);
1038                 LOGD("set video param : rotate %d", evas_info->rotate_angle);
1039
1040                 ret = _mm_evas_renderer_apply_geometry(evas_info);
1041                 if (ret != MM_ERROR_NONE)
1042                         return ret;
1043
1044                 if (evas_info->epipe) {
1045                         ret = ecore_pipe_write(evas_info->epipe, &evas_info->visible, UPDATE_VISIBILITY);
1046                         if (!ret) {
1047                                 LOGW("fail to ecore_pipe_write() for updating visibility\n");
1048                                 return MM_ERROR_UNKNOWN;
1049                         }
1050 #if 0           /* FIXME: pause state only */
1051                         g_mutex_lock(&evas_info->idx_lock);
1052                         ret = ecore_pipe_write(evas_info->epipe, evas_info, UPDATE_TBM_SURF);
1053                         if (!ret) {
1054                                 LOGW("fail to ecore_pipe_write() for updating visibility\n");
1055                                 ret = MM_ERROR_UNKNOWN;
1056                         } else {
1057                                 ret = MM_ERROR_NONE;
1058                         }
1059                         g_mutex_unlock(&evas_info->idx_lock);
1060 #endif
1061                 }
1062         }
1063
1064         return ret;
1065 }
1066
1067 int mm_evas_renderer_create(MMHandleType *handle, Evas_Object *eo)
1068 {
1069         MM_CHECK_NULL(handle);
1070
1071         int ret = MM_ERROR_NONE;
1072         mm_evas_info *evas_info = NULL;
1073
1074         ret = _mm_evas_renderer_create(&evas_info);
1075         if (ret != MM_ERROR_NONE) {
1076                 LOGE("fail to create evas_info");
1077                 return ret;
1078         }
1079         ret = _mm_evas_renderer_set_info(evas_info, eo);
1080         if (ret != MM_ERROR_NONE) {
1081                 LOGE("fail to init evas_info");
1082                 if (_mm_evas_renderer_destroy(&evas_info) != MM_ERROR_NONE)
1083                         LOGE("fail to destroy evas_info");
1084                 return ret;
1085         }
1086
1087         *handle = (MMHandleType)evas_info;
1088
1089         return MM_ERROR_NONE;
1090 }
1091
1092 int mm_evas_renderer_destroy(MMHandleType *handle)
1093 {
1094         MM_CHECK_NULL(handle);
1095
1096         int ret = MM_ERROR_NONE;
1097         mm_evas_info *evas_info = (mm_evas_info *)*handle;
1098
1099         if (!evas_info) {
1100                 LOGD("skip it. it is not evas surface type.");
1101                 return MM_ERROR_RESOURCE_NOT_INITIALIZED;
1102         }
1103
1104         ret = _mm_evas_renderer_destroy(&evas_info);
1105         if (ret != MM_ERROR_NONE) {
1106                 LOGE("fail to destroy evas_info");
1107                 return ret;
1108         }
1109         *handle = NULL;
1110
1111         return MM_ERROR_NONE;
1112 }
1113
1114 int mm_evas_renderer_set_visible(MMHandleType handle, bool visible)
1115 {
1116         int ret = MM_ERROR_NONE;
1117         mm_evas_info *evas_info = (mm_evas_info *)handle;
1118
1119         if (!evas_info) {
1120                 LOGW("skip it. it is not evas surface type or handle is not prepared");
1121                 return MM_ERROR_RESOURCE_NOT_INITIALIZED;
1122         }
1123
1124         if (visible)
1125                 evas_info->visible = VISIBLE_TRUE;
1126         else
1127                 evas_info->visible = VISIBLE_FALSE;
1128
1129         if (evas_info->epipe) {
1130                 ret = ecore_pipe_write(evas_info->epipe, &visible, UPDATE_VISIBILITY);
1131                 if (!ret) {
1132                         LOGW("fail to ecore_pipe_write() for updating visibility\n");
1133                         ret = MM_ERROR_UNKNOWN;
1134                 } else {
1135                         ret = MM_ERROR_NONE;
1136                 }
1137         } else {
1138                 LOGW("there is no epipe. we cant update it");
1139         }
1140
1141         return ret;
1142 }
1143
1144 int mm_evas_renderer_get_visible(MMHandleType handle, bool *visible)
1145 {
1146         mm_evas_info *evas_info = (mm_evas_info *)handle;
1147
1148         if (!evas_info) {
1149                 LOGW("skip it. it is not evas surface type or handle is not prepared");
1150                 return MM_ERROR_RESOURCE_NOT_INITIALIZED;
1151         }
1152
1153         if (evas_info->visible == VISIBLE_FALSE)
1154                 *visible = FALSE;
1155         else
1156                 *visible = TRUE;
1157
1158         return MM_ERROR_NONE;
1159 }
1160
1161 int mm_evas_renderer_set_rotation(MMHandleType handle, int rotate)
1162 {
1163         int ret = MM_ERROR_NONE;
1164         mm_evas_info *evas_info = (mm_evas_info *)handle;
1165
1166         if (!evas_info) {
1167                 LOGW("skip it. it is not evas surface type or handle is not prepared");
1168                 return MM_ERROR_RESOURCE_NOT_INITIALIZED;
1169         }
1170
1171         switch(rotate) {
1172         case DEGREE_0:
1173                 evas_info->rotate_angle = EVAS_IMAGE_ORIENT_0;
1174                 break;
1175         case DEGREE_90:
1176                 evas_info->rotate_angle = EVAS_IMAGE_ORIENT_90;
1177                 break;
1178         case DEGREE_180:
1179                 evas_info->rotate_angle = EVAS_IMAGE_ORIENT_180;
1180                 break;
1181         case DEGREE_270:
1182                 evas_info->rotate_angle = EVAS_IMAGE_ORIENT_270;
1183                 break;
1184         default:
1185                 return MM_ERROR_INVALID_ARGUMENT;
1186         }
1187 #if 0   /* FIXME: pause state only */
1188         if (evas_info->epipe) {
1189                 g_mutex_lock(&evas_info->idx_lock);
1190                 ret = ecore_pipe_write(evas_info->epipe, evas_info, UPDATE_TBM_SURF);
1191                 if (!ret) {
1192                         LOGW("fail to ecore_pipe_write() for updating visibility\n");
1193                         ret = MM_ERROR_UNKNOWN;
1194                 } else {
1195                         ret = MM_ERROR_NONE;
1196                 }
1197                 g_mutex_unlock(&evas_info->idx_lock);
1198         }
1199 #endif
1200         return ret;
1201 }
1202
1203 int mm_evas_renderer_get_rotation(MMHandleType handle, int *rotate)
1204 {
1205         mm_evas_info *evas_info = (mm_evas_info *)handle;
1206
1207         if (!evas_info) {
1208                 LOGW("skip it. it is not evas surface type or handle is not prepared");
1209                 return MM_ERROR_RESOURCE_NOT_INITIALIZED;
1210         }
1211
1212         switch(evas_info->rotate_angle) {
1213         case EVAS_IMAGE_ORIENT_0:
1214                 *rotate = DEGREE_0;
1215                 break;
1216         case EVAS_IMAGE_ORIENT_90:
1217                 *rotate = DEGREE_90;
1218                 break;
1219         case EVAS_IMAGE_ORIENT_180:
1220                 *rotate = DEGREE_180;
1221                 break;
1222         case EVAS_IMAGE_ORIENT_270:
1223                 *rotate = DEGREE_270;
1224                 break;
1225         default:
1226                 return MM_ERROR_INVALID_ARGUMENT;
1227         }
1228
1229         return MM_ERROR_NONE;
1230 }
1231
1232 int mm_evas_renderer_set_geometry(MMHandleType handle, int mode)
1233 {
1234         int ret = MM_ERROR_NONE;
1235         mm_evas_info *evas_info = (mm_evas_info *)handle;
1236
1237         if (!evas_info) {
1238                 LOGW("skip it. it is not evas surface type or handle is not prepared");
1239                 return MM_ERROR_RESOURCE_NOT_INITIALIZED;
1240         }
1241
1242         evas_info->display_geometry_method = mode;
1243         ret = _mm_evas_renderer_apply_geometry(evas_info);
1244
1245         /* ecore_pipe_write is needed, because of setting ratio for letterbox mode */
1246 #if 0   /* FIXME: pause state only */
1247         if (evas_info->epipe) {
1248                 g_mutex_lock(&evas_info->idx_lock);
1249                 ret = ecore_pipe_write(evas_info->epipe, evas_info, UPDATE_TBM_SURF);
1250                 if (!ret) {
1251                         LOGW("fail to ecore_pipe_write() for updating visibility\n");
1252                         ret = MM_ERROR_UNKNOWN;
1253                 } else {
1254                         ret = MM_ERROR_NONE;
1255                 }
1256                 g_mutex_unlock(&evas_info->idx_lock);
1257         }
1258 #endif
1259
1260         return ret;
1261 }
1262
1263 int mm_evas_renderer_get_geometry(MMHandleType handle, int *mode)
1264 {
1265         mm_evas_info *evas_info = (mm_evas_info *)handle;
1266
1267         if (!evas_info) {
1268                 LOGW("skip it. it is not evas surface type or handle is not prepared");
1269                 return MM_ERROR_RESOURCE_NOT_INITIALIZED;
1270         }
1271         *mode = evas_info->display_geometry_method;
1272
1273         return MM_ERROR_NONE;
1274 }
1275
1276 int mm_evas_renderer_set_flip(MMHandleType handle, int flip)
1277 {
1278         int ret = MM_ERROR_NONE;
1279         mm_evas_info *evas_info = (mm_evas_info *)handle;
1280
1281         if (!evas_info) {
1282                 LOGW("skip it. it is not evas surface type or handle is not prepared");
1283                 return MM_ERROR_RESOURCE_NOT_INITIALIZED;
1284         }
1285
1286         switch(flip) {
1287         case FLIP_NONE :
1288                 evas_info->flip = 0;
1289                 break;
1290         case FLIP_HORIZONTAL:
1291                 evas_info->flip = EVAS_IMAGE_FLIP_HORIZONTAL;
1292                 break;
1293         case FLIP_VERTICAL:
1294                 evas_info->flip = EVAS_IMAGE_FLIP_VERTICAL;
1295                 break;
1296         case FLIP_BOTH:
1297                 evas_info->flip = EVAS_IMAGE_ORIENT_180;
1298                 break;
1299         default:
1300                 return MM_ERROR_INVALID_ARGUMENT;
1301         }
1302 #if 0   /* FIXME: pause state only */
1303         if (evas_info->epipe) {
1304                 g_mutex_lock(&evas_info->idx_lock);
1305                 ret = ecore_pipe_write(evas_info->epipe, evas_info, UPDATE_TBM_SURF);
1306                 if (!ret) {
1307                         LOGW("fail to ecore_pipe_write() for updating visibility\n");
1308                         ret = MM_ERROR_UNKNOWN;
1309                 } else {
1310                         ret = MM_ERROR_NONE;
1311                 }
1312                 g_mutex_unlock(&evas_info->idx_lock);
1313         }
1314 #endif
1315         return ret;
1316 }
1317
1318 int mm_evas_renderer_get_flip(MMHandleType handle, int *flip)
1319 {
1320         mm_evas_info *evas_info = (mm_evas_info *)handle;
1321
1322         if (!evas_info) {
1323                 LOGW("skip it. it is not evas surface type or handle is not prepared");
1324                 return MM_ERROR_RESOURCE_NOT_INITIALIZED;
1325         }
1326
1327         switch(evas_info->flip) {
1328         case 0:
1329                 *flip = FLIP_NONE;
1330                 break;
1331         case EVAS_IMAGE_FLIP_HORIZONTAL:
1332                 *flip = FLIP_HORIZONTAL;
1333                 break;
1334         case EVAS_IMAGE_FLIP_VERTICAL:
1335                 *flip = FLIP_VERTICAL;
1336                 break;
1337         case EVAS_IMAGE_ORIENT_180:
1338                 *flip = FLIP_BOTH;
1339                 break;
1340         default:
1341                 return MM_ERROR_INVALID_ARGUMENT;
1342         }
1343
1344         return MM_ERROR_NONE;
1345 }
1346
1347 int mm_evas_renderer_retrieve_all_packets (MMHandleType handle, bool keep_screen)
1348 {
1349         int ret = MM_ERROR_NONE;
1350         mm_evas_info *evas_info = (mm_evas_info*) handle;
1351
1352         if (!evas_info) {
1353                 LOGW("skip it. it is not evas surface type or player is not prepared");
1354                 return MM_ERROR_RESOURCE_NOT_INITIALIZED;
1355         }
1356         ret = _mm_evas_renderer_retrieve_all_packets(evas_info, keep_screen);
1357
1358         return ret;
1359 }