2 * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
22 #include <sys/types.h>
30 #include <sys/syscall.h>
31 #include "mm_evas_renderer.h"
36 #define LOG_TAG "MM_EVAS_RENDER"
37 //#define _INTERNAL_DEBUG_ /* debug only */
40 #define MMER_FENTER(); LOGD("<ENTER>");
41 #define MMER_FLEAVE(); LOGD("<LEAVE>");
43 #define MMER_FENTER();
44 #define MMER_FLEAVE();
47 #define MM_CHECK_NULL(x_var) \
49 LOGE("[%s] is NULL\n", #x_var); \
50 return MM_ERROR_EVASRENDER_INVALID_ARGUMENT; \
53 #define SET_EVAS_OBJECT_EVENT_CALLBACK(x_evas_image_object, x_usr_data) \
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); \
62 #define UNSET_EVAS_OBJECT_EVENT_CALLBACK(x_evas_image_object) \
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); \
71 #define SET_EVAS_EVENT_CALLBACK(x_evas, x_usr_data) \
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); \
79 #define UNSET_EVAS_EVENT_CALLBACK(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); \
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,
113 #ifdef _INTERNAL_DEBUG_
114 static int g_cnt_in = 0;
115 static int g_cnt_out = 0;
116 //static void __print_idx(mm_evas_info *evas_info);
117 static int __dump_pkt(media_packet_h pkt, int width, int height);
118 static int __dump_surf(tbm_surface_h tbm_surf);
121 static void _free_previous_packets(mm_evas_info *evas_info);
122 static int _flush_packets(mm_evas_info *evas_info);
123 static int _mm_evas_renderer_create(mm_evas_info **evas_info);
124 static int _mm_evas_renderer_destroy(mm_evas_info **evas_info);
125 static int _mm_evas_renderer_set_info(mm_evas_info *evas_info, Evas_Object *eo);
126 static int _mm_evas_renderer_reset(mm_evas_info *evas_info);
127 static void _mm_evas_renderer_update_geometry(mm_evas_info *evas_info, rect_info *result);
128 static int _mm_evas_renderer_apply_geometry(mm_evas_info *evas_info);
129 static int _mm_evas_renderer_retrieve_all_packets(mm_evas_info *evas_info, bool keep_screen);
130 static int _mm_evas_renderer_make_flush_buffer(mm_evas_info *evas_info);
131 static void _mm_evas_renderer_release_flush_buffer(mm_evas_info *evas_info);
132 static void _mm_evas_renderer_set_callback(mm_evas_info *evas_info);
133 static void _mm_evas_renderer_unset_callback(mm_evas_info *evas_info);
135 static void _evas_resize_cb(void *data, Evas *e, Evas_Object *obj, void *event_info)
142 mm_evas_info *evas_info = data;
144 if (!evas_info || !evas_info->eo)
147 evas_object_geometry_get(evas_info->eo, &x, &y, &w, &h);
149 LOGW("evas object size (w:%d,h:%d) was not set", w, h);
151 evas_info->eo_size.x = x;
152 evas_info->eo_size.y = y;
153 evas_info->eo_size.w = w;
154 evas_info->eo_size.h = h;
155 LOGW("resize (x:%d, y:%d, w:%d, h:%d)", x, y, w, h);
156 ret = _mm_evas_renderer_apply_geometry(evas_info);
157 if (ret != MM_ERROR_NONE)
158 LOGW("fail to apply geometry info");
163 static void _evas_render_pre_cb(void *data, Evas *e, void *event_info)
167 mm_evas_info *evas_info = data;
169 if (!evas_info || !evas_info->eo) {
170 LOGW("there is no esink info.... esink : %p, or eo is NULL returning", evas_info);
174 /* flush will be executed in this callback normally,
175 because native_surface_set must be called in main thread */
176 if (evas_info->retrieve_packet) {
177 g_mutex_lock(&evas_info->idx_lock);
178 if (_flush_packets(evas_info) != MM_ERROR_NONE)
179 LOGE("flushing packets are failed");
180 g_mutex_unlock(&evas_info->idx_lock);
185 static void _evas_del_cb(void *data, Evas *e, Evas_Object *obj, void *event_info)
189 mm_evas_info *evas_info = data;
191 if (!evas_info || !evas_info->eo)
195 _mm_evas_renderer_unset_callback(evas_info);
196 evas_object_image_data_set(evas_info->eo, NULL);
197 evas_info->eo = NULL;
202 static void _evas_pipe_cb(void *data, void *buffer, update_info info)
206 mm_evas_info *evas_info = data;
209 LOGW("evas_info is NULL", evas_info);
213 g_mutex_lock(&evas_info->mp_lock);
215 if (!evas_info->eo) {
216 LOGW("evas_info %p", evas_info);
217 g_mutex_unlock(&evas_info->mp_lock);
221 LOGD("evas_info : %p, evas_info->eo : %p", evas_info, evas_info->eo);
222 if (info == UPDATE_VISIBILITY) {
223 if (evas_info->visible == VISIBLE_FALSE) {
224 evas_object_hide(evas_info->eo);
225 LOGI("object hide..");
227 evas_object_show(evas_info->eo);
228 LOGI("object show.. %d", evas_info->visible);
231 g_mutex_unlock(&evas_info->mp_lock);
235 if (info != UPDATE_TBM_SURF) {
236 LOGW("invalid info type : %d", info);
237 g_mutex_unlock(&evas_info->mp_lock);
241 if ((evas_info->cur_idx == -1) || !evas_info->pkt_info[evas_info->cur_idx].tbm_surf) {
242 LOGW("cur_idx %d, tbm_surf may be NULL", evas_info->cur_idx);
243 g_mutex_unlock(&evas_info->mp_lock);
246 /* perhaps, it is needed to skip setting when state is pause */
248 g_mutex_lock(&evas_info->idx_lock);
250 gint cur_idx = evas_info->cur_idx;
251 gint prev_idx = evas_info->pkt_info[cur_idx].prev;
253 LOGD("received (idx %d, packet %p)", cur_idx, evas_info->pkt_info[cur_idx].packet);
255 tbm_format tbm_fmt = tbm_surface_get_format(evas_info->pkt_info[cur_idx].tbm_surf);
257 case TBM_FORMAT_NV12:
258 LOGD("tbm_surface format : TBM_FORMAT_NV12");
260 case TBM_FORMAT_YUV420:
261 LOGD("tbm_surface format : TBM_FORMAT_YUV420");
264 LOGW("tbm_surface format : unknown %d", tbm_fmt);
268 Evas_Native_Surface surf = { 0 };
269 surf.type = EVAS_NATIVE_SURFACE_TBM;
270 surf.version = EVAS_NATIVE_SURFACE_VERSION;
271 surf.data.tbm.buffer = evas_info->pkt_info[cur_idx].tbm_surf;
272 surf.data.tbm.rot = evas_info->rotate_angle;
273 surf.data.tbm.flip = evas_info->flip;
275 rect_info result = { 0 };
277 evas_object_geometry_get(evas_info->eo, &evas_info->eo_size.x, &evas_info->eo_size.y,
278 &evas_info->eo_size.w, &evas_info->eo_size.h);
279 if (!evas_info->eo_size.w || !evas_info->eo_size.h) {
280 LOGE("there is no information for evas object size");
283 _mm_evas_renderer_update_geometry(evas_info, &result);
284 if (!result.w || !result.h) {
285 LOGE("no information about geometry (%d, %d)", result.w, result.h);
289 if (evas_info->update_needed) {
290 /* update geometry on pause state */
291 evas_object_image_native_surface_set(evas_info->eo, NULL);
292 evas_info->update_needed = FALSE;
295 if (evas_info->use_ratio) {
296 surf.data.tbm.ratio = (float) evas_info->w / evas_info->h;
299 evas_object_size_hint_align_set(evas_info->eo, EVAS_HINT_FILL, EVAS_HINT_FILL);
300 evas_object_size_hint_weight_set(evas_info->eo, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
301 if (evas_info->w > 0 && evas_info->h > 0)
302 evas_object_image_size_set(evas_info->eo, evas_info->w, evas_info->h);
303 #ifdef _INTERNAL_DEBUG_
305 if ((g_cnt_out%5 == 0) && (g_cnt_out < 500))
306 ret2 = __dump_surf(evas_info->pkt_info[cur_idx].tbm_surf);
308 LOGW("__dump_surf() is failed");
312 evas_object_image_native_surface_set(evas_info->eo, &surf);
313 LOGD("native surface set finish");
315 if (result.x || result.y)
316 LOGD("coordinate x, y (%d, %d) for locating video to center", result.x, result.y);
318 evas_object_image_fill_set(evas_info->eo, result.x, result.y, result.w, result.h);
320 evas_object_image_pixels_dirty_set(evas_info->eo, EINA_TRUE);
321 LOGD("GEO_METHOD : src(%dx%d), dst(%dx%d), dst_x(%d), dst_y(%d), rotate(%d), flip(%d)", evas_info->w, evas_info->h, evas_info->eo_size.w, evas_info->eo_size.h, evas_info->eo_size.x, evas_info->eo_size.y, evas_info->rotate_angle, evas_info->flip);
323 /* when _evas_pipe_cb is called sequentially, previous packet and current packet will be the same */
324 if ((prev_idx != -1) && evas_info->pkt_info[prev_idx].packet && (prev_idx != cur_idx))
325 _free_previous_packets(evas_info);
327 g_mutex_unlock(&evas_info->idx_lock);
328 g_mutex_unlock(&evas_info->mp_lock);
335 if ((prev_idx != -1) && evas_info->pkt_info[prev_idx].packet) {
337 _free_previous_packets(evas_info);
339 g_mutex_unlock(&evas_info->idx_lock);
340 g_mutex_unlock(&evas_info->mp_lock);
343 #ifdef _INTERNAL_DEBUG_
345 static void __print_idx(mm_evas_info *evas_info)
347 gint prev_idx = evas_info->pkt_info[evas_info->cur_idx].prev;
348 LOGE("***** start cur_idx : %d -> prev_idx : %d", evas_info->cur_idx, prev_idx);
349 while (prev_idx != -1) {
350 LOGE("***** cur_idx : %d -> prev_idx : %d", prev_idx, evas_info->pkt_info[prev_idx].prev);
351 prev_idx = evas_info->pkt_info[prev_idx].prev;
357 static int __dump_pkt(media_packet_h pkt, int width, int height)
361 char filename[128] = {0};
364 int stride_width, stride_height;
366 sprintf(filename, "/tmp/DUMP_IN_IMG_%2.2d.dump", g_cnt_in);
367 fp = fopen(filename, "wb");
371 media_packet_get_video_plane_data_ptr(pkt, 0, &data);
372 media_packet_get_video_stride_width(pkt, 0, &stride_width);
373 media_packet_get_video_stride_height(pkt, 0, &stride_height);
374 media_packet_get_buffer_size(pkt, &size);
375 LOGI("[0]stride : %d, %d", stride_width, stride_height);
377 for (i = 0; i < height; i++) {
378 fwrite(data, width, 1, fp);
379 data += stride_width;
381 #if 0 //hw format(NV12)
382 media_packet_get_video_plane_data_ptr(pkt, 1, &data);
383 media_packet_get_video_stride_width(pkt, 1, &stride_width);
384 for (i = 0; i < height/2; i++) {
385 fwrite(data, width, 1, fp);
386 data += stride_width;
389 media_packet_get_video_plane_data_ptr(pkt, 1, &data);
390 media_packet_get_video_stride_width(pkt, 1, &stride_width);
391 for (i = 0; i < height/2; i++) {
392 fwrite(data, width/2, 1, fp);
393 data += stride_width;
395 LOGI("[1]stride : %d, %d", stride_width, stride_height);
396 media_packet_get_video_plane_data_ptr(pkt, 2, &data);
397 media_packet_get_video_stride_width(pkt, 2, &stride_width);
398 for (i = 0; i < height/2; i++) {
399 fwrite(data, width/2, 1, fp);
400 data += stride_width;
402 LOGI("[2]stride : %d, %d", stride_width, stride_height);
404 LOGI("DUMP_IN_IMG_%2.2d : buffer size(%d) data(%p)", g_cnt_in, (int)size, data);
410 static int __dump_surf(tbm_surface_h tbm_surf)
412 char filename[128] = {0};
413 tbm_surface_info_s info = {0};
415 sprintf(filename, "DUMP_OUT_IMG_%2.2d", g_cnt_out);
416 if (tbm_surface_get_info(tbm_surf, &info)) {
417 LOGE("get_info is failed");
421 tbm_surface_internal_dump_start("/tmp", info.width, info.height, 1);
422 tbm_surface_internal_dump_buffer(tbm_surf, filename);
423 tbm_surface_internal_dump_end();
425 LOGI("[0]stride : %d, offset : %d", (int)info.planes[0].stride, (int)info.planes[0].offset);
426 LOGI("[1]stride : %d, offset : %d", (int)info.planes[1].stride, (int)info.planes[1].offset);
427 LOGI("[2]stride : %d, offset : %d", (int)info.planes[2].stride, (int)info.planes[2].offset);
428 LOGI("DUMP_OUT_IMG_%2.2d : buffer size(%d) surf(%p) %d*%d", g_cnt_out, (int)info.size, tbm_surf, info.width, info.height);
434 static void _free_previous_packets(mm_evas_info *evas_info)
438 gint index = evas_info->cur_idx;
439 gint prev_idx = evas_info->pkt_info[index].prev;
441 while (prev_idx != -1) {
442 LOGD("destroy previous packet [%p] idx %d", evas_info->pkt_info[prev_idx].packet, prev_idx);
443 if (evas_info->packet_rendered_cb) {
444 evas_info->packet_rendered_cb(evas_info->pkt_info[prev_idx].packet, evas_info->packet_rendered_cb_user);
446 if (media_packet_destroy(evas_info->pkt_info[prev_idx].packet) != MEDIA_PACKET_ERROR_NONE)
447 LOGE("media_packet_destroy failed %p", evas_info->pkt_info[prev_idx].packet);
449 evas_info->sent_buffer_cnt--;
450 evas_info->pkt_info[prev_idx].packet = NULL;
451 evas_info->pkt_info[prev_idx].tbm_surf = NULL;
452 evas_info->pkt_info[index].prev = -1;
454 /* move index to previous index */
456 prev_idx = evas_info->pkt_info[prev_idx].prev;
457 LOGD("sent packet %d", evas_info->sent_buffer_cnt);
465 static int _get_video_size(media_packet_h packet, mm_evas_info *evas_info)
470 if (media_packet_get_format(packet, &fmt) == MEDIA_PACKET_ERROR_NONE) {
472 if (media_format_get_video_info(fmt, NULL, &w, &h, NULL, NULL) == MEDIA_PACKET_ERROR_NONE) {
473 LOGD("video width = %d, height =%d", w, h);
478 LOGW("media_format_get_video_info is failed");
479 if (media_format_unref(fmt) != MEDIA_PACKET_ERROR_NONE) /* because of media_packet_get_format */
480 LOGW("media_format_unref is failed");
482 LOGW("media_packet_get_format is failed");
490 static int _find_empty_index(mm_evas_info *evas_info)
495 for (i = 0; i < MAX_PACKET_NUM; i++) {
496 if (!evas_info->pkt_info[i].packet) {
497 LOGD("selected idx %d", i);
501 LOGE("there is no empty idx");
508 static int _flush_packets(mm_evas_info *evas_info)
512 int ret = MM_ERROR_NONE;
513 int ret_mp = MEDIA_PACKET_ERROR_NONE;
517 LOGW("there is no esink info");
518 return MM_ERROR_EVASRENDER_INVALID_ARGUMENT;
521 /* update the screen only if visible is true */
522 /* if flush buffer is null, we cant keep screen */
523 if (evas_info->keep_screen && (evas_info->visible != VISIBLE_FALSE) && evas_info->flush_buffer) {
524 Evas_Native_Surface surf = { 0 };
525 rect_info result = { 0 };
526 evas_object_geometry_get(evas_info->eo, &evas_info->eo_size.x, &evas_info->eo_size.y, &evas_info->eo_size.w, &evas_info->eo_size.h);
527 if (!evas_info->eo_size.w || !evas_info->eo_size.h) {
528 LOGE("there is no information for evas object size");
529 return MM_ERROR_EVASRENDER_INVALID_ARGUMENT;
531 _mm_evas_renderer_update_geometry(evas_info, &result);
532 if (!result.w || !result.h) {
533 LOGE("no information about geometry (%d, %d)", result.w, result.h);
534 return MM_ERROR_EVASRENDER_INVALID_ARGUMENT;
537 if (evas_info->use_ratio) {
538 surf.data.tbm.ratio = (float) evas_info->w / evas_info->h;
541 evas_object_size_hint_align_set(evas_info->eo, EVAS_HINT_FILL, EVAS_HINT_FILL);
542 evas_object_size_hint_weight_set(evas_info->eo, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
543 if (evas_info->w > 0 && evas_info->h > 0)
544 evas_object_image_size_set(evas_info->eo, evas_info->w, evas_info->h);
546 if (result.x || result.y)
547 LOGD("coordinate x, y (%d, %d) for locating video to center", result.x, result.y);
549 evas_object_image_fill_set(evas_info->eo, result.x, result.y, result.w, result.h);
551 /* set flush buffer */
552 surf.type = EVAS_NATIVE_SURFACE_TBM;
553 surf.version = EVAS_NATIVE_SURFACE_VERSION;
554 surf.data.tbm.buffer = evas_info->flush_buffer->tbm_surf;
555 surf.data.tbm.rot = evas_info->rotate_angle;
556 surf.data.tbm.flip = evas_info->flip;
557 evas_object_image_native_surface_set(evas_info->eo, &surf);
559 LOGD("flush_buffer surf(%p), rotate(%d), flip(%d)", evas_info->flush_buffer->tbm_surf, evas_info->rotate_angle, evas_info->flip);
561 /* unset evas native surface for displaying black screen */
562 evas_object_image_native_surface_set(evas_info->eo, NULL);
563 evas_object_image_data_set(evas_info->eo, NULL);
565 LOGD("sent packet %d", evas_info->sent_buffer_cnt);
567 /* destroy all packets */
568 g_mutex_lock(&evas_info->mp_lock);
569 for (i = 0; i < MAX_PACKET_NUM; i++) {
570 if (evas_info->pkt_info[i].packet) {
571 LOGD("destroy packet [%p]", evas_info->pkt_info[i].packet);
572 if (evas_info->packet_rendered_cb) {
573 evas_info->packet_rendered_cb(evas_info->pkt_info[i].packet, evas_info->packet_rendered_cb_user);
575 ret_mp = media_packet_destroy(evas_info->pkt_info[i].packet);
576 if (ret_mp != MEDIA_PACKET_ERROR_NONE) {
577 LOGW("media_packet_destroy failed %p", evas_info->pkt_info[i].packet);
578 ret = MM_ERROR_EVASRENDER_INTERNAL;
581 evas_info->sent_buffer_cnt--;
582 evas_info->pkt_info[i].packet = NULL;
583 evas_info->pkt_info[i].tbm_surf = NULL;
584 evas_info->pkt_info[i].prev = -1;
588 if (evas_info->sent_buffer_cnt != 0)
589 LOGE("it should be 0 --> [%d]", evas_info->sent_buffer_cnt);
590 evas_info->sent_buffer_cnt = 0;
591 evas_info->cur_idx = -1;
592 g_mutex_unlock(&evas_info->mp_lock);
594 evas_object_image_pixels_dirty_set(evas_info->eo, EINA_TRUE);
595 evas_info->retrieve_packet = FALSE;
603 int _reset_pipe(mm_evas_info *evas_info)
606 int ret = MM_ERROR_NONE;
607 int ret_mp = MEDIA_PACKET_ERROR_NONE;
609 /* delete old pipe */
610 if (evas_info->epipe) {
611 LOGD("pipe %p will be deleted", evas_info->epipe);
612 ecore_pipe_del(evas_info->epipe);
613 evas_info->epipe = NULL;
616 for (i = 0; i < MAX_PACKET_NUM; i++) {
617 if (evas_info->pkt_info[i].packet) {
618 /* destroy all packets */
619 LOGD("destroy packet [%p]", evas_info->pkt_info[i].packet);
620 if (evas_info->packet_rendered_cb) {
621 evas_info->packet_rendered_cb(evas_info->pkt_info[i].packet, evas_info->packet_rendered_cb_user);
623 ret_mp = media_packet_destroy(evas_info->pkt_info[i].packet);
624 if (ret_mp != MEDIA_PACKET_ERROR_NONE) {
625 LOGW("media_packet_destroy failed %p", evas_info->pkt_info[i].packet);
626 ret = MM_ERROR_EVASRENDER_INTERNAL;
629 evas_info->sent_buffer_cnt--;
630 evas_info->pkt_info[i].packet = NULL;
631 evas_info->pkt_info[i].tbm_surf = NULL;
632 evas_info->pkt_info[i].prev = -1;
636 if (evas_info->sent_buffer_cnt != 0)
637 LOGE("it should be 0 --> [%d]", evas_info->sent_buffer_cnt);
638 evas_info->sent_buffer_cnt = 0;
639 evas_info->cur_idx = -1;
642 if (!evas_info->epipe) {
643 evas_info->epipe = ecore_pipe_add((Ecore_Pipe_Cb) _evas_pipe_cb, evas_info);
644 if (!evas_info->epipe) {
645 LOGE("pipe is not created");
646 ret = MM_ERROR_EVASRENDER_INTERNAL;
648 LOGD("created pipe %p", evas_info->epipe);
655 static void _mm_evas_renderer_set_callback(mm_evas_info *evas_info)
659 SET_EVAS_OBJECT_EVENT_CALLBACK(evas_info->eo, evas_info);
660 SET_EVAS_EVENT_CALLBACK(evas_object_evas_get(evas_info->eo), evas_info);
665 static void _mm_evas_renderer_unset_callback(mm_evas_info *evas_info)
669 UNSET_EVAS_OBJECT_EVENT_CALLBACK(evas_info->eo);
670 UNSET_EVAS_EVENT_CALLBACK(evas_object_evas_get(evas_info->eo));
675 static int _mm_evas_renderer_create(mm_evas_info **evas_info)
679 mm_evas_info *ptr = NULL;
680 ptr = g_malloc0(sizeof(mm_evas_info));
683 LOGE("Cannot allocate memory for evas_info\n");
687 LOGD("Success create evas_info(%p)", *evas_info);
689 g_mutex_init(&ptr->mp_lock);
690 g_mutex_init(&ptr->idx_lock);
694 return MM_ERROR_NONE;
698 return MM_ERROR_EVASRENDER_NO_FREE_SPACE;
701 static int _mm_evas_renderer_destroy(mm_evas_info **evas_info)
705 mm_evas_info *ptr = (mm_evas_info *)*evas_info;
707 int ret = MM_ERROR_NONE;
709 LOGD("finalize evas_info %p", ptr);
711 ret = _mm_evas_renderer_reset(ptr);
712 g_mutex_clear(&ptr->mp_lock);
713 g_mutex_clear(&ptr->idx_lock);
723 static int _mm_evas_renderer_set_info(mm_evas_info *evas_info, Evas_Object *eo)
726 MM_CHECK_NULL(evas_info);
728 g_mutex_lock(&evas_info->idx_lock);
730 LOGD("set evas_info");
732 for (i = 0; i < MAX_PACKET_NUM; i++) {
733 evas_info->pkt_info[i].packet = NULL;
734 evas_info->pkt_info[i].tbm_surf = NULL;
735 evas_info->pkt_info[i].prev = -1;
737 evas_info->cur_idx = -1;
738 evas_info->dst_roi.x = evas_info->dst_roi.y = evas_info->dst_roi.w = evas_info->dst_roi.h = 0;
740 evas_info->epipe = ecore_pipe_add((Ecore_Pipe_Cb) _evas_pipe_cb, evas_info);
741 if (!evas_info->epipe) {
742 LOGE("pipe is not created");
743 g_mutex_unlock(&evas_info->idx_lock);
744 return MM_ERROR_EVASRENDER_INTERNAL;
746 LOGD("created pipe %p", evas_info->epipe);
747 _mm_evas_renderer_set_callback(evas_info);
749 evas_object_geometry_get(evas_info->eo, &evas_info->eo_size.x, &evas_info->eo_size.y, &evas_info->eo_size.w, &evas_info->eo_size.h);
750 LOGI("evas object %p (%d, %d, %d, %d)", evas_info->eo, evas_info->eo_size.x, evas_info->eo_size.y, evas_info->eo_size.w, evas_info->eo_size.h);
752 g_mutex_unlock(&evas_info->idx_lock);
756 return MM_ERROR_NONE;
759 static int _mm_evas_renderer_reset(mm_evas_info *evas_info)
762 MM_CHECK_NULL(evas_info);
763 g_mutex_lock(&evas_info->idx_lock);
766 int ret = MM_ERROR_NONE;
767 int ret_mp = MEDIA_PACKET_ERROR_NONE;
770 _mm_evas_renderer_unset_callback(evas_info);
771 evas_object_image_data_set(evas_info->eo, NULL);
772 evas_info->eo = NULL;
774 if (evas_info->epipe) {
775 LOGD("pipe %p will be deleted", evas_info->epipe);
776 ecore_pipe_del(evas_info->epipe);
777 evas_info->epipe = NULL;
780 evas_info->eo_size.x = evas_info->eo_size.y = evas_info->eo_size.w = evas_info->eo_size.h = 0;
781 evas_info->dst_roi.x = evas_info->dst_roi.y = evas_info->dst_roi.w = evas_info->dst_roi.h = 0;
782 evas_info->w = evas_info->h = 0;
784 if (evas_info->flush_buffer)
785 _mm_evas_renderer_release_flush_buffer(evas_info);
787 g_mutex_lock(&evas_info->mp_lock);
788 for (i = 0; i < MAX_PACKET_NUM; i++) {
789 if (evas_info->pkt_info[i].packet) {
790 /* destroy all packets */
791 LOGD("destroy packet [%p]", evas_info->pkt_info[i].packet);
792 if (evas_info->packet_rendered_cb) {
793 evas_info->packet_rendered_cb(evas_info->pkt_info[i].packet, evas_info->packet_rendered_cb_user);
795 ret_mp = media_packet_destroy(evas_info->pkt_info[i].packet);
796 if (ret_mp != MEDIA_PACKET_ERROR_NONE) {
797 LOGW("media_packet_destroy failed %p", evas_info->pkt_info[i].packet);
798 ret = MM_ERROR_EVASRENDER_INTERNAL;
801 evas_info->sent_buffer_cnt--;
802 evas_info->pkt_info[i].packet = NULL;
803 evas_info->pkt_info[i].tbm_surf = NULL;
804 evas_info->pkt_info[i].prev = -1;
807 g_mutex_unlock(&evas_info->mp_lock);
808 if (evas_info->sent_buffer_cnt != 0)
809 LOGE("it should be 0 --> [%d]", evas_info->sent_buffer_cnt);
810 evas_info->sent_buffer_cnt = 0;
811 evas_info->cur_idx = -1;
813 g_mutex_unlock(&evas_info->idx_lock);
820 static void _mm_evas_renderer_update_geometry(mm_evas_info *evas_info, rect_info *result)
824 if (!evas_info || !evas_info->eo) {
825 LOGW("there is no evas_info or evas object");
829 LOGW("there is no rect info");
836 switch (evas_info->display_geometry_method) {
837 case DISP_GEO_METHOD_LETTER_BOX:
838 /* set black padding for letter box mode */
839 LOGD("letter box mode");
840 evas_info->use_ratio = TRUE;
841 result->w = evas_info->eo_size.w;
842 result->h = evas_info->eo_size.h;
844 case DISP_GEO_METHOD_ORIGIN_SIZE:
845 LOGD("origin size mode");
846 evas_info->use_ratio = FALSE;
847 /* set coordinate for each case */
848 result->x = (evas_info->eo_size.w - evas_info->w) / 2;
849 result->y = (evas_info->eo_size.h - evas_info->h) / 2;
850 result->w = evas_info->w;
851 result->h = evas_info->h;
853 case DISP_GEO_METHOD_FULL_SCREEN:
854 LOGD("full screen mode");
855 evas_info->use_ratio = FALSE;
856 result->w = evas_info->eo_size.w;
857 result->h = evas_info->eo_size.h;
859 case DISP_GEO_METHOD_CROPPED_FULL_SCREEN:
860 LOGD("cropped full screen mode");
861 evas_info->use_ratio = FALSE;
862 /* compare evas object's ratio with video's */
863 if ((evas_info->eo_size.w / evas_info->eo_size.h) > (evas_info->w / evas_info->h)) {
864 result->w = evas_info->eo_size.w;
865 result->h = evas_info->eo_size.w * evas_info->h / evas_info->w;
866 result->y = -(result->h - evas_info->eo_size.h) / 2;
868 result->w = evas_info->eo_size.h * evas_info->w / evas_info->h;
869 result->h = evas_info->eo_size.h;
870 result->x = -(result->w - evas_info->eo_size.w) / 2;
873 case DISP_GEO_METHOD_ORIGIN_SIZE_OR_LETTER_BOX:
874 LOGD("origin size or letter box mode");
875 /* if video size is smaller than evas object's, it will be set to origin size mode */
876 if ((evas_info->eo_size.w > evas_info->w) && (evas_info->eo_size.h > evas_info->h)) {
877 LOGD("origin size mode");
878 evas_info->use_ratio = FALSE;
879 /* set coordinate for each case */
880 result->x = (evas_info->eo_size.w - evas_info->w) / 2;
881 result->y = (evas_info->eo_size.h - evas_info->h) / 2;
882 result->w = evas_info->w;
883 result->h = evas_info->h;
885 LOGD("letter box mode");
886 evas_info->use_ratio = TRUE;
887 result->w = evas_info->eo_size.w;
888 result->h = evas_info->eo_size.h;
891 case DISP_GEO_METHOD_CUSTOM_ROI:
892 LOGD("custom roi mode");
893 evas_info->use_ratio = TRUE;
894 result->x = evas_info->dst_roi.x;
895 result->y = evas_info->dst_roi.y;
896 result->w = evas_info->dst_roi.w;
897 result->h = evas_info->dst_roi.h;
900 LOGW("unsupported mode.");
903 LOGD("geometry result [%d, %d, %d, %d]", result->x, result->y, result->w, result->h);
908 static int _mm_evas_renderer_apply_geometry(mm_evas_info *evas_info)
912 if (!evas_info || !evas_info->eo) {
913 LOGW("there is no evas_info or evas object");
914 return MM_ERROR_NONE;
917 Evas_Native_Surface *surf = evas_object_image_native_surface_get(evas_info->eo);
918 rect_info result = { 0 };
921 LOGD("native surface exists");
922 surf->data.tbm.rot = evas_info->rotate_angle;
923 surf->data.tbm.flip = evas_info->flip;
924 evas_object_image_native_surface_set(evas_info->eo, surf);
926 _mm_evas_renderer_update_geometry(evas_info, &result);
928 if (evas_info->use_ratio) {
929 surf->data.tbm.ratio = (float) evas_info->w / evas_info->h;
932 if (result.x || result.y)
933 LOGD("coordinate x, y (%d, %d) for locating video to center", result.x, result.y);
935 evas_object_image_fill_set(evas_info->eo, result.x, result.y, result.w, result.h);
937 return MM_ERROR_NONE;
939 LOGW("there is no surf");
940 /* FIXME: before pipe_cb is invoked, apply_geometry can be called. */
944 return MM_ERROR_NONE;
947 static int _mm_evas_renderer_retrieve_all_packets(mm_evas_info *evas_info, bool keep_screen)
950 MM_CHECK_NULL(evas_info);
952 int ret = MM_ERROR_NONE;
953 pid_t pid = getpid();
954 pid_t tid = syscall(SYS_gettid);
956 /* write and this API can be called at the same time.
957 so lock is needed for counting sent_buffer_cnt correctly */
958 g_mutex_lock(&evas_info->idx_lock);
960 /* make flush buffer */
962 ret = _mm_evas_renderer_make_flush_buffer(evas_info);
963 evas_info->keep_screen = keep_screen;
965 LOGD("pid [%d], tid [%d]", pid, tid);
967 /* in this case, we deem it is main thread */
968 if (_flush_packets(evas_info) != MM_ERROR_NONE) {
969 LOGE("flushing packets are failed");
970 ret = MM_ERROR_EVASRENDER_INTERNAL;
973 /* it will be executed to write flush buffer and destroy media packets in pre_cb */
974 evas_info->retrieve_packet = TRUE;
976 g_mutex_unlock(&evas_info->idx_lock);
983 /* make buffer for copying */
984 static int _mm_evas_renderer_make_flush_buffer(mm_evas_info *evas_info)
988 if (evas_info->cur_idx == -1) {
989 LOGW("there is no remained buffer");
990 return MM_ERROR_EVASRENDER_INVALID_ARGUMENT;
992 media_packet_h packet = evas_info->pkt_info[evas_info->cur_idx].packet;
993 MM_CHECK_NULL(packet);
995 flush_info *flush_buffer = NULL;
996 tbm_surface_h src_tbm_surf = NULL;
997 tbm_surface_info_s src_info = {0};
998 tbm_surface_info_s dst_info = {0};
999 int ret = MM_ERROR_NONE;
1001 if (evas_info->flush_buffer)
1002 _mm_evas_renderer_release_flush_buffer(evas_info);
1005 flush_buffer = (flush_info *)malloc(sizeof(flush_info));
1006 if (flush_buffer == NULL) {
1007 LOGE("malloc is failed");
1010 memset(flush_buffer, 0x0, sizeof(flush_info));
1012 ret = media_packet_get_tbm_surface(packet, &src_tbm_surf);
1013 if (ret != MEDIA_PACKET_ERROR_NONE || !src_tbm_surf) {
1014 LOGW("get_tbm_surface is failed");
1018 /* get src buffer info */
1019 if (tbm_surface_map(src_tbm_surf, TBM_OPTION_READ|TBM_OPTION_WRITE, &src_info)) {
1020 LOGW("[src] map is failed");
1024 /* create tbm surface */
1025 flush_buffer->tbm_surf = tbm_surface_create(evas_info->w, evas_info->h, src_info.format);
1026 if (!flush_buffer->tbm_surf) {
1027 LOGE("tbm_surf is NULL!!");
1028 if (tbm_surface_unmap(src_tbm_surf))
1029 LOGW("[src] unmap is failed");
1033 /* get dst buffer info */
1034 if (tbm_surface_map(flush_buffer->tbm_surf, TBM_OPTION_READ|TBM_OPTION_WRITE, &dst_info)) {
1035 LOGW("[dst] map is failed");
1036 if (tbm_surface_unmap(src_tbm_surf))
1037 LOGW("[src] unmap is failed");
1041 if (src_info.size > dst_info.size) {
1042 LOGE("src size(%d), dst size(%d)!!!", src_info.size, dst_info.size);
1043 if (tbm_surface_unmap(src_tbm_surf))
1044 LOGW("[src] unmap is failed");
1045 if (tbm_surface_unmap(flush_buffer->tbm_surf))
1046 LOGW("[dst] unmap is failed");
1051 switch (src_info.format) {
1052 case TBM_FORMAT_YUV420:
1053 memcpy(dst_info.planes[0].ptr, src_info.planes[0].ptr, src_info.planes[0].size);
1054 memcpy(dst_info.planes[1].ptr, src_info.planes[1].ptr, src_info.planes[1].size);
1055 memcpy(dst_info.planes[2].ptr, src_info.planes[2].ptr, src_info.planes[2].size);
1057 case TBM_FORMAT_NV12:
1058 memcpy(dst_info.planes[0].ptr, src_info.planes[0].ptr, src_info.planes[0].size);
1059 memcpy(dst_info.planes[1].ptr, src_info.planes[1].ptr, src_info.planes[1].size);
1062 LOGW("unsupported format");
1066 #ifdef _INTERNAL_DEBUG_
1067 __dump_surf(flush_buffer->tbm_surf);
1069 LOGD("flush_buffer dump is done");
1072 if (tbm_surface_unmap(src_tbm_surf))
1073 LOGW("[src] unmap is failed");
1074 if (tbm_surface_unmap(flush_buffer->tbm_surf))
1075 LOGW("[dst] unmap is failed");
1077 LOGW("copy is done. tbm surface : %p", flush_buffer->tbm_surf);
1078 evas_info->flush_buffer = flush_buffer;
1082 return MM_ERROR_NONE;
1086 if (flush_buffer->tbm_surf) {
1087 tbm_surface_destroy(flush_buffer->tbm_surf);
1088 flush_buffer->tbm_surf = NULL;
1092 flush_buffer = NULL;
1094 return MM_ERROR_EVASRENDER_INTERNAL;
1097 /* release flush buffer */
1098 static void _mm_evas_renderer_release_flush_buffer(mm_evas_info *evas_info)
1102 LOGW("release FLUSH BUFFER start");
1103 if (evas_info->flush_buffer->bo)
1104 evas_info->flush_buffer->bo = NULL;
1106 if (evas_info->flush_buffer->tbm_surf) {
1107 tbm_surface_destroy(evas_info->flush_buffer->tbm_surf);
1108 evas_info->flush_buffer->tbm_surf = NULL;
1111 LOGW("release FLUSH BUFFER done");
1113 free(evas_info->flush_buffer);
1114 evas_info->flush_buffer = NULL;
1121 void mm_evas_renderer_write(media_packet_h packet, void *data)
1126 LOGE("packet %p is NULL", packet);
1129 mm_evas_info *handle = (mm_evas_info *)data;
1130 int ret = MEDIA_PACKET_ERROR_NONE;
1132 tbm_surface_h tbm_surf;
1135 LOGD("packet [%p]", packet);
1137 if (!data || !handle) {
1138 LOGE("handle %p or evas_info %p is NULL", data, handle);
1141 g_mutex_lock(&handle->idx_lock);
1143 ret = media_packet_has_tbm_surface_buffer(packet, &has);
1144 if (ret != MEDIA_PACKET_ERROR_NONE) {
1145 LOGW("has_tbm_surface is failed");
1148 /* FIXME: when setCaps occurs, _get_video_size should be called */
1149 /* currently we are always checking it */
1150 if (has && _get_video_size(packet, handle)) {
1151 /* Attention! if this error occurs, we need to consider managing buffer */
1152 if (handle->sent_buffer_cnt > 3) {
1153 LOGE("too many buffers are not released %d", handle->sent_buffer_cnt);
1156 /* FIXME: fix this logic */
1157 /* destroy all media packets and reset pipe at present */
1158 /* Attention! it might free buffer that is being rendered */
1159 g_mutex_lock(&handle->mp_lock);
1160 _reset_pipe(handle);
1161 g_mutex_unlock(&handle->mp_lock);
1164 ret = media_packet_get_tbm_surface(packet, &tbm_surf);
1165 if (ret != MEDIA_PACKET_ERROR_NONE || !tbm_surf) {
1166 LOGW("get_tbm_surface is failed");
1170 /* find new index for current packet */
1171 index = _find_empty_index(handle);
1175 #ifdef _INTERNAL_DEBUG_
1177 if ((g_cnt_in%10 == 0) && (g_cnt_in < 500))
1178 ret2 = __dump_pkt(packet, handle->w, handle->h);
1181 LOGW("__dump_pkt() is failed");
1185 /* save previous index */
1186 handle->pkt_info[index].prev = handle->cur_idx;
1187 handle->pkt_info[index].packet = packet;
1188 handle->pkt_info[index].tbm_surf = tbm_surf;
1189 handle->cur_idx = index;
1190 handle->sent_buffer_cnt++;
1191 LOGD("sent packet %d", handle->sent_buffer_cnt);
1193 ret = ecore_pipe_write(handle->epipe, handle, UPDATE_TBM_SURF);
1195 handle->pkt_info[index].packet = NULL;
1196 handle->pkt_info[index].tbm_surf = NULL;
1197 handle->pkt_info[index].prev = -1;
1198 handle->cur_idx = handle->pkt_info[index].prev;
1199 handle->sent_buffer_cnt--;
1200 LOGW("Failed to ecore_pipe_write() for updating tbm surf\n");
1204 LOGW("no tbm_surf");
1207 g_mutex_unlock(&handle->idx_lock);
1213 g_mutex_unlock(&handle->idx_lock);
1215 /* destroy media_packet immediately */
1217 g_mutex_lock(&handle->mp_lock);
1218 LOGD("cant write. destroy packet [%p]", packet);
1219 if (handle && handle->packet_rendered_cb) {
1220 handle->packet_rendered_cb(packet, handle->packet_rendered_cb_user);
1222 if (media_packet_destroy(packet) != MEDIA_PACKET_ERROR_NONE)
1223 LOGE("media_packet_destroy failed %p", packet);
1226 g_mutex_unlock(&handle->mp_lock);
1231 int mm_evas_renderer_update_param(MMHandleType handle)
1235 int ret = MM_ERROR_NONE;
1236 mm_evas_info *evas_info = (mm_evas_info *)handle;
1239 LOGW("skip it. it is not evas surface type.");
1243 /* when handle is realized, we need to update all properties */
1245 LOGD("set video param : evas-object %x, method %d", evas_info->eo, evas_info->display_geometry_method);
1246 LOGD("set video param : visible %d", evas_info->visible);
1247 LOGD("set video param : rotate %d", evas_info->rotate_angle);
1249 ret = _mm_evas_renderer_apply_geometry(evas_info);
1250 if (ret != MM_ERROR_NONE)
1253 if (evas_info->epipe) {
1254 ret = ecore_pipe_write(evas_info->epipe, &evas_info->visible, UPDATE_VISIBILITY);
1256 LOGW("fail to ecore_pipe_write() for updating visibility\n");
1257 return MM_ERROR_EVASRENDER_INTERNAL;
1259 evas_info->update_needed = TRUE;
1260 /* FIXME: pause state only */
1261 g_mutex_lock(&evas_info->idx_lock);
1262 ret = ecore_pipe_write(evas_info->epipe, evas_info, UPDATE_TBM_SURF);
1264 LOGW("fail to ecore_pipe_write() for updating visibility\n");
1265 ret = MM_ERROR_EVASRENDER_INTERNAL;
1267 ret = MM_ERROR_NONE;
1269 g_mutex_unlock(&evas_info->idx_lock);
1278 int mm_evas_renderer_create(MMHandleType *handle, Evas_Object *eo)
1281 MM_CHECK_NULL(handle);
1283 int ret = MM_ERROR_NONE;
1284 mm_evas_info *evas_info = NULL;
1286 ret = _mm_evas_renderer_create(&evas_info);
1287 if (ret != MM_ERROR_NONE) {
1288 LOGE("fail to create evas_info");
1291 ret = _mm_evas_renderer_set_info(evas_info, eo);
1292 if (ret != MM_ERROR_NONE) {
1293 LOGE("fail to init evas_info");
1294 if (_mm_evas_renderer_destroy(&evas_info) != MM_ERROR_NONE)
1295 LOGE("fail to destroy evas_info");
1299 *handle = (MMHandleType)evas_info;
1301 return MM_ERROR_NONE;
1304 int mm_evas_renderer_destroy(MMHandleType *handle)
1307 MM_CHECK_NULL(handle);
1309 int ret = MM_ERROR_NONE;
1310 mm_evas_info *evas_info = (mm_evas_info *)*handle;
1313 LOGD("skip it. it is not evas surface type.");
1314 return MM_ERROR_EVASRENDER_NOT_INITIALIZED;
1317 ret = _mm_evas_renderer_destroy(&evas_info);
1318 if (ret != MM_ERROR_NONE) {
1319 LOGE("fail to destroy evas_info");
1326 return MM_ERROR_NONE;
1329 int mm_evas_renderer_set_visible(MMHandleType handle, bool visible)
1333 int ret = MM_ERROR_NONE;
1334 mm_evas_info *evas_info = (mm_evas_info *)handle;
1337 LOGW("skip it. it is not evas surface type or handle is not prepared");
1338 return MM_ERROR_EVASRENDER_NOT_INITIALIZED;
1342 evas_info->visible = VISIBLE_TRUE;
1344 evas_info->visible = VISIBLE_FALSE;
1346 if (evas_info->epipe) {
1347 ret = ecore_pipe_write(evas_info->epipe, &visible, UPDATE_VISIBILITY);
1349 LOGW("fail to ecore_pipe_write() for updating visibility\n");
1350 ret = MM_ERROR_EVASRENDER_INTERNAL;
1352 ret = MM_ERROR_NONE;
1355 LOGW("there is no epipe. we cant update it");
1363 int mm_evas_renderer_get_visible(MMHandleType handle, bool *visible)
1367 mm_evas_info *evas_info = (mm_evas_info *)handle;
1370 LOGW("skip it. it is not evas surface type or handle is not prepared");
1371 return MM_ERROR_EVASRENDER_NOT_INITIALIZED;
1374 if (evas_info->visible == VISIBLE_FALSE)
1381 return MM_ERROR_NONE;
1384 int mm_evas_renderer_set_rotation(MMHandleType handle, int rotate)
1388 int ret = MM_ERROR_NONE;
1389 mm_evas_info *evas_info = (mm_evas_info *)handle;
1393 LOGW("skip it. it is not evas surface type or handle is not prepared");
1394 return MM_ERROR_EVASRENDER_NOT_INITIALIZED;
1399 value = EVAS_IMAGE_ORIENT_0;
1402 value = EVAS_IMAGE_ORIENT_90;
1405 value = EVAS_IMAGE_ORIENT_180;
1408 value = EVAS_IMAGE_ORIENT_270;
1411 return MM_ERROR_EVASRENDER_INVALID_ARGUMENT;
1413 if (evas_info->rotate_angle != value) {
1414 evas_info->update_needed = TRUE;
1415 evas_info->rotate_angle = value;
1418 /* FIXME: pause state only */
1419 if (evas_info->epipe) {
1420 g_mutex_lock(&evas_info->idx_lock);
1421 ret = ecore_pipe_write(evas_info->epipe, evas_info, UPDATE_TBM_SURF);
1423 LOGW("fail to ecore_pipe_write() for updating visibility\n");
1424 ret = MM_ERROR_EVASRENDER_INTERNAL;
1426 ret = MM_ERROR_NONE;
1428 g_mutex_unlock(&evas_info->idx_lock);
1435 int mm_evas_renderer_get_rotation(MMHandleType handle, int *rotate)
1439 mm_evas_info *evas_info = (mm_evas_info *)handle;
1442 LOGW("skip it. it is not evas surface type or handle is not prepared");
1443 return MM_ERROR_EVASRENDER_NOT_INITIALIZED;
1446 switch (evas_info->rotate_angle) {
1447 case EVAS_IMAGE_ORIENT_0:
1450 case EVAS_IMAGE_ORIENT_90:
1451 *rotate = DEGREE_90;
1453 case EVAS_IMAGE_ORIENT_180:
1454 *rotate = DEGREE_180;
1456 case EVAS_IMAGE_ORIENT_270:
1457 *rotate = DEGREE_270;
1460 return MM_ERROR_EVASRENDER_INVALID_ARGUMENT;
1465 return MM_ERROR_NONE;
1468 int mm_evas_renderer_set_geometry(MMHandleType handle, int mode)
1472 int ret = MM_ERROR_NONE;
1473 mm_evas_info *evas_info = (mm_evas_info *)handle;
1476 LOGW("skip it. it is not evas surface type or handle is not prepared");
1477 return MM_ERROR_EVASRENDER_NOT_INITIALIZED;
1479 if (evas_info->display_geometry_method != mode) {
1480 evas_info->update_needed = TRUE;
1481 evas_info->display_geometry_method = mode;
1484 /* ecore_pipe_write is needed, because of setting ratio for letterbox mode */
1485 /* FIXME: pause state only */
1486 if (evas_info->epipe) {
1487 g_mutex_lock(&evas_info->idx_lock);
1488 ret = ecore_pipe_write(evas_info->epipe, evas_info, UPDATE_TBM_SURF);
1490 LOGW("fail to ecore_pipe_write() for updating visibility\n");
1491 ret = MM_ERROR_EVASRENDER_INTERNAL;
1493 ret = MM_ERROR_NONE;
1495 g_mutex_unlock(&evas_info->idx_lock);
1502 int mm_evas_renderer_get_geometry(MMHandleType handle, int *mode)
1506 mm_evas_info *evas_info = (mm_evas_info *)handle;
1509 LOGW("skip it. it is not evas surface type or handle is not prepared");
1510 return MM_ERROR_EVASRENDER_NOT_INITIALIZED;
1512 *mode = evas_info->display_geometry_method;
1516 return MM_ERROR_NONE;
1519 int mm_evas_renderer_set_roi_area(MMHandleType handle, int x, int y, int w, int h)
1523 int ret = MM_ERROR_NONE;
1524 mm_evas_info *evas_info = (mm_evas_info *)handle;
1527 LOGW("skip it. it is not evas surface type or handle is not prepared");
1528 return MM_ERROR_EVASRENDER_NOT_INITIALIZED;
1531 LOGE("invalid resolution");
1532 return MM_ERROR_EVASRENDER_INVALID_ARGUMENT;
1534 if (evas_info->display_geometry_method != DISP_GEO_METHOD_CUSTOM_ROI) {
1535 LOGE("invalid mode");
1536 return MM_ERROR_EVASRENDER_INVALID_OPERATION;
1539 if (evas_info->dst_roi.x != x || evas_info->dst_roi.y != y
1540 || evas_info->dst_roi.w != w || evas_info->dst_roi.h != h) {
1541 evas_info->update_needed = TRUE;
1542 evas_info->dst_roi.x = x;
1543 evas_info->dst_roi.y = y;
1544 evas_info->dst_roi.w = w;
1545 evas_info->dst_roi.h = h;
1548 /* pipe_write could be needed because ratio can be changed on pause state */
1549 if (evas_info->epipe) {
1550 g_mutex_lock(&evas_info->idx_lock);
1551 ret = ecore_pipe_write(evas_info->epipe, evas_info, UPDATE_TBM_SURF);
1553 LOGW("fail to ecore_pipe_write() for updating visibility\n");
1554 ret = MM_ERROR_EVASRENDER_INTERNAL;
1556 ret = MM_ERROR_NONE;
1558 g_mutex_unlock(&evas_info->idx_lock);
1566 int mm_evas_renderer_get_roi_area(MMHandleType handle, int *x, int *y, int *w, int *h)
1570 mm_evas_info *evas_info = (mm_evas_info *)handle;
1573 LOGW("skip it. it is not evas surface type or handle is not prepared");
1574 return MM_ERROR_EVASRENDER_NOT_INITIALIZED;
1576 if (evas_info->display_geometry_method != DISP_GEO_METHOD_CUSTOM_ROI) {
1577 LOGE("invalid mode");
1578 return MM_ERROR_EVASRENDER_INVALID_OPERATION;
1581 *x = evas_info->dst_roi.x;
1582 *y = evas_info->dst_roi.y;
1583 *w = evas_info->dst_roi.w;
1584 *h = evas_info->dst_roi.h;
1588 return MM_ERROR_NONE;
1591 int mm_evas_renderer_set_flip(MMHandleType handle, int flip)
1595 int ret = MM_ERROR_NONE;
1596 mm_evas_info *evas_info = (mm_evas_info *)handle;
1600 LOGW("skip it. it is not evas surface type or handle is not prepared");
1601 return MM_ERROR_EVASRENDER_NOT_INITIALIZED;
1606 value = EVAS_IMAGE_ORIENT_NONE;
1608 case FLIP_HORIZONTAL:
1609 value = EVAS_IMAGE_FLIP_HORIZONTAL;
1612 value = EVAS_IMAGE_FLIP_VERTICAL;
1615 value = EVAS_IMAGE_ORIENT_180;
1618 return MM_ERROR_EVASRENDER_INVALID_ARGUMENT;
1620 if (evas_info->flip != value) {
1621 evas_info->update_needed = TRUE;
1622 evas_info->flip = value;
1625 /* FIXME: pause state only */
1626 if (evas_info->epipe) {
1627 g_mutex_lock(&evas_info->idx_lock);
1628 ret = ecore_pipe_write(evas_info->epipe, evas_info, UPDATE_TBM_SURF);
1630 LOGW("fail to ecore_pipe_write() for updating visibility\n");
1631 ret = MM_ERROR_EVASRENDER_INTERNAL;
1633 ret = MM_ERROR_NONE;
1635 g_mutex_unlock(&evas_info->idx_lock);
1643 int mm_evas_renderer_get_flip(MMHandleType handle, int *flip)
1647 mm_evas_info *evas_info = (mm_evas_info *)handle;
1650 LOGW("skip it. it is not evas surface type or handle is not prepared");
1651 return MM_ERROR_EVASRENDER_NOT_INITIALIZED;
1654 switch (evas_info->flip) {
1655 case EVAS_IMAGE_ORIENT_NONE:
1658 case EVAS_IMAGE_FLIP_HORIZONTAL:
1659 *flip = FLIP_HORIZONTAL;
1661 case EVAS_IMAGE_FLIP_VERTICAL:
1662 *flip = FLIP_VERTICAL;
1664 case EVAS_IMAGE_ORIENT_180:
1668 return MM_ERROR_EVASRENDER_INVALID_ARGUMENT;
1673 return MM_ERROR_NONE;
1676 int mm_evas_renderer_retrieve_all_packets(MMHandleType handle, bool keep_screen)
1680 int ret = MM_ERROR_NONE;
1681 mm_evas_info *evas_info = (mm_evas_info*) handle;
1684 LOGW("skip it. it is not evas surface type or player is not prepared");
1685 return MM_ERROR_EVASRENDER_NOT_INITIALIZED;
1687 ret = _mm_evas_renderer_retrieve_all_packets(evas_info, keep_screen);
1694 int mm_evas_renderer_set_packet_rendered_callback(MMHandleType handle, mm_evas_renderer_media_packet_rendered_cb callback, void *user_data)
1698 mm_evas_info *evas_info = (mm_evas_info*) handle;
1701 LOGW("skip it. it is not evas surface type or player is not prepared");
1702 return MM_ERROR_EVASRENDER_NOT_INITIALIZED;
1704 evas_info->packet_rendered_cb = callback;
1705 evas_info->packet_rendered_cb_user = user_data;
1707 LOGW("set rendered callback %p, user_data %p", evas_info->packet_rendered_cb, evas_info->packet_rendered_cb_user);
1711 return MM_ERROR_NONE;