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