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