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 */
39 #define MM_CHECK_NULL( x_var ) \
42 LOGE("[%s] is NULL\n", #x_var ); \
43 return MM_ERROR_INVALID_ARGUMENT; \
46 #define SET_EVAS_OBJECT_EVENT_CALLBACK( x_evas_image_object, x_usr_data ) \
49 if (x_evas_image_object) { \
50 LOGD("object callback add"); \
51 evas_object_event_callback_add (x_evas_image_object, EVAS_CALLBACK_DEL, _evas_del_cb, x_usr_data); \
52 evas_object_event_callback_add (x_evas_image_object, EVAS_CALLBACK_RESIZE, _evas_resize_cb, x_usr_data); \
56 #define UNSET_EVAS_OBJECT_EVENT_CALLBACK( x_evas_image_object ) \
59 if (x_evas_image_object) { \
60 LOGD("object callback del"); \
61 evas_object_event_callback_del (x_evas_image_object, EVAS_CALLBACK_DEL, _evas_del_cb); \
62 evas_object_event_callback_del (x_evas_image_object, EVAS_CALLBACK_RESIZE, _evas_resize_cb); \
66 #define SET_EVAS_EVENT_CALLBACK( x_evas, x_usr_data ) \
70 LOGD("callback add... evas_callback_render_pre.. evas : %p evas_info : %p", x_evas, x_usr_data); \
71 evas_event_callback_add (x_evas, EVAS_CALLBACK_RENDER_PRE, _evas_render_pre_cb, x_usr_data); \
75 #define UNSET_EVAS_EVENT_CALLBACK( x_evas ) \
79 LOGD("callback del... evas_callback_render_pre %p", x_evas); \
80 evas_event_callback_del (x_evas, EVAS_CALLBACK_RENDER_PRE, _evas_render_pre_cb); \
85 DISP_GEO_METHOD_LETTER_BOX = 0,
86 DISP_GEO_METHOD_ORIGIN_SIZE,
87 DISP_GEO_METHOD_FULL_SCREEN,
88 DISP_GEO_METHOD_CROPPED_FULL_SCREEN,
89 DISP_GEO_METHOD_ORIGIN_SIZE_OR_LETTER_BOX,
109 #ifdef _INTERNAL_DEBUG_
110 void __print_idx(mm_evas_info *evas_info);
113 void _free_previous_packets(mm_evas_info *evas_info);
114 int _flush_packets(mm_evas_info *evas_info);
115 int _mm_evas_renderer_create(mm_evas_info **evas_info);
116 int _mm_evas_renderer_destroy(mm_evas_info **evas_info);
117 int _mm_evas_renderer_set_info(mm_evas_info *evas_info, Evas_Object *eo);
118 int _mm_evas_renderer_reset(mm_evas_info *evas_info);
119 void _mm_evas_renderer_update_geometry(mm_evas_info *evas_info, rect_info *result);
120 int _mm_evas_renderer_apply_geometry(mm_evas_info *evas_info);
121 int _mm_evas_renderer_retrieve_all_packets(mm_evas_info *evas_info, bool keep_screen);
122 int _mm_evas_renderer_make_flush_buffer(mm_evas_info *evas_info);
123 void _mm_evas_renderer_release_flush_buffer(mm_evas_info *evas_info);
124 static void _mm_evas_renderer_set_callback(mm_evas_info *evas_info);
125 static void _mm_evas_renderer_unset_callback(mm_evas_info *evas_info);
127 static void _evas_resize_cb(void *data, Evas *e, Evas_Object *obj, void *event_info)
132 mm_evas_info *evas_info = data;
135 if (!evas_info || !evas_info->eo) {
139 evas_object_geometry_get(evas_info->eo, &x, &y, &w, &h);
141 LOGW("evas object size (w:%d,h:%d) was not set", w, h);
143 evas_info->eo_size.x = x;
144 evas_info->eo_size.y = y;
145 evas_info->eo_size.w = w;
146 evas_info->eo_size.h = h;
147 LOGW("resize (x:%d, y:%d, w:%d, h:%d)", x, y, w, h);
148 ret = _mm_evas_renderer_apply_geometry(evas_info);
149 if (ret != MM_ERROR_NONE)
150 LOGW("fail to apply geometry info");
155 static void _evas_render_pre_cb(void *data, Evas *e, void *event_info)
157 mm_evas_info *evas_info = data;
159 if (!evas_info || !evas_info->eo) {
160 LOGW("there is no esink info.... esink : %p, or eo is NULL returning", evas_info);
164 /* flush will be executed in this callback normally,
165 because native_surface_set must be called in main thread */
166 if (evas_info->retrieve_packet) {
167 g_mutex_lock(&evas_info->idx_lock);
168 if (_flush_packets(evas_info) != MM_ERROR_NONE)
169 LOGE("flushing packets are failed");
170 g_mutex_unlock(&evas_info->idx_lock);
174 static void _evas_del_cb(void *data, Evas *e, Evas_Object *obj, void *event_info)
176 mm_evas_info *evas_info = data;
178 if (!evas_info || !evas_info->eo) {
182 _mm_evas_renderer_unset_callback(evas_info);
183 evas_object_image_data_set(evas_info->eo, NULL);
184 evas_info->eo = NULL;
189 void _evas_pipe_cb(void *data, void *buffer, update_info info)
191 mm_evas_info *evas_info = data;
196 LOGW("evas_info is NULL", evas_info);
200 g_mutex_lock(&evas_info->mp_lock);
202 if (!evas_info->eo) {
203 LOGW("evas_info %p", evas_info);
204 g_mutex_unlock(&evas_info->mp_lock);
208 LOGD("evas_info : %p, evas_info->eo : %p", evas_info, evas_info->eo);
209 if (info == UPDATE_VISIBILITY) {
210 if (evas_info->visible == VISIBLE_FALSE) {
211 evas_object_hide(evas_info->eo);
212 LOGI("object hide..");
214 evas_object_show(evas_info->eo);
215 LOGI("object show.. %d", evas_info->visible);
218 g_mutex_unlock(&evas_info->mp_lock);
222 if (info != UPDATE_TBM_SURF) {
223 LOGW("invalid info type : %d", info);
224 g_mutex_unlock(&evas_info->mp_lock);
228 if (evas_info->cur_idx==-1 || !evas_info->pkt_info[evas_info->cur_idx].tbm_surf) {
229 LOGW("cur_idx %d, tbm_surf may be NULL", evas_info->cur_idx);
230 g_mutex_unlock(&evas_info->mp_lock);
233 /* perhaps, it is needed to skip setting when state is pause */
235 g_mutex_lock(&evas_info->idx_lock);
237 gint cur_idx = evas_info->cur_idx;
238 gint prev_idx = evas_info->pkt_info[cur_idx].prev;
240 LOGD("received (idx %d, packet %p)", cur_idx, evas_info->pkt_info[cur_idx].packet);
242 tbm_format tbm_fmt = tbm_surface_get_format(evas_info->pkt_info[cur_idx].tbm_surf);
244 case TBM_FORMAT_NV12:
245 LOGD("tbm_surface format : TBM_FORMAT_NV12");
247 case TBM_FORMAT_YUV420:
248 LOGD("tbm_surface format : TBM_FORMAT_YUV420");
251 LOGW("tbm_surface format : unknown %d", tbm_fmt);
255 Evas_Native_Surface surf;
256 surf.type = EVAS_NATIVE_SURFACE_TBM;
257 surf.version = EVAS_NATIVE_SURFACE_VERSION;
258 surf.data.tbm.buffer = evas_info->pkt_info[cur_idx].tbm_surf;
259 surf.data.tbm.rot = evas_info->rotate_angle;
260 surf.data.tbm.flip = evas_info->flip;
262 rect_info result = { 0 };
264 evas_object_geometry_get(evas_info->eo, &evas_info->eo_size.x, &evas_info->eo_size.y, &evas_info->eo_size.w, &evas_info->eo_size.h);
265 if (!evas_info->eo_size.w || !evas_info->eo_size.h) {
266 LOGE("there is no information for evas object size");
269 _mm_evas_renderer_update_geometry(evas_info, &result);
270 if (!result.w || !result.h) {
271 LOGE("no information about geometry (%d, %d)", result.w, result.h);
275 if (evas_info->use_ratio) {
276 surf.data.tbm.ratio = (float) evas_info->w / evas_info->h;
277 LOGD("set ratio for letter mode");
279 evas_object_size_hint_align_set(evas_info->eo, EVAS_HINT_FILL, EVAS_HINT_FILL);
280 evas_object_size_hint_weight_set(evas_info->eo, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
281 if (evas_info->w > 0 && evas_info->h > 0)
282 evas_object_image_size_set(evas_info->eo, evas_info->w, evas_info->h);
284 evas_object_image_native_surface_set(evas_info->eo, &surf);
285 LOGD("native surface set finish");
287 if (result.x || result.y)
288 LOGD("coordinate x, y (%d, %d) for locating video to center", result.x, result.y);
289 evas_object_image_fill_set(evas_info->eo, result.x, result.y, result.w, result.h);
291 evas_object_image_pixels_dirty_set(evas_info->eo, EINA_TRUE);
292 LOGD("GEO_METHOD : src(%dx%d), dst(%dx%d), dst_x(%d), dst_y(%d), rotate(%d), flip(%d)", evas_info->w, evas_info->h, evas_info->eo_size.w, evas_info->eo_size.h, evas_info->eo_size.x, evas_info->eo_size.y, evas_info->rotate_angle, evas_info->flip);
294 /* when _evas_pipe_cb is called sequentially, previous packet and current packet will be the same */
295 if ((prev_idx != -1) && evas_info->pkt_info[prev_idx].packet && (prev_idx != cur_idx))
296 _free_previous_packets(evas_info);
299 g_mutex_unlock(&evas_info->idx_lock);
300 g_mutex_unlock(&evas_info->mp_lock);
305 if ((prev_idx != -1) && evas_info->pkt_info[prev_idx].packet) {
307 _free_previous_packets(evas_info);
309 g_mutex_unlock(&evas_info->idx_lock);
310 g_mutex_unlock(&evas_info->mp_lock);
313 #ifdef _INTERNAL_DEBUG_
314 void __print_idx(mm_evas_info *evas_info)
316 gint prev_idx = evas_info->pkt_info[evas_info->cur_idx].prev;
317 LOGE("***** start cur_idx : %d -> prev_idx : %d", evas_info->cur_idx, prev_idx);
318 while(prev_idx != -1)
320 LOGE("***** cur_idx : %d -> prev_idx : %d", prev_idx, evas_info->pkt_info[prev_idx].prev);
321 prev_idx = evas_info->pkt_info[prev_idx].prev;
328 void _free_previous_packets(mm_evas_info *evas_info)
330 gint index = evas_info->cur_idx;
331 gint prev_idx = evas_info->pkt_info[index].prev;
333 while(prev_idx != -1)
335 LOGD("destroy previous packet [%p] idx %d", evas_info->pkt_info[prev_idx].packet, prev_idx);
336 if (media_packet_destroy(evas_info->pkt_info[prev_idx].packet) != MEDIA_PACKET_ERROR_NONE)
337 LOGE("media_packet_destroy failed %p", evas_info->pkt_info[prev_idx].packet);
338 evas_info->pkt_info[prev_idx].packet = NULL;
339 evas_info->pkt_info[prev_idx].tbm_surf = NULL;
340 evas_info->pkt_info[index].prev = -1;
341 evas_info->sent_buffer_cnt--;
343 /* move index to previous index */
345 prev_idx = evas_info->pkt_info[prev_idx].prev;
346 LOGD("sent packet %d", evas_info->sent_buffer_cnt);
351 static int _get_video_size(media_packet_h packet, mm_evas_info *evas_info)
354 if (media_packet_get_format(packet, &fmt) == MEDIA_PACKET_ERROR_NONE) {
356 if (media_format_get_video_info(fmt, NULL, &w, &h, NULL, NULL) == MEDIA_PACKET_ERROR_NONE) {
357 LOGD("video width = %d, height =%d", w, h);
362 LOGW("media_format_get_video_info is failed");
363 if (media_format_unref(fmt) != MEDIA_PACKET_ERROR_NONE) /* because of media_packet_get_format */
364 LOGW("media_format_unref is failed");
366 LOGW("media_packet_get_format is failed");
371 int _find_empty_index(mm_evas_info *evas_info)
374 for (i = 0; i < MAX_PACKET_NUM; i++) {
375 if (!evas_info->pkt_info[i].packet) {
376 LOGD("selected idx %d", i);
380 LOGE("there is no empty idx");
385 int _flush_packets(mm_evas_info *evas_info)
387 int ret = MM_ERROR_NONE;
388 int ret_mp = MEDIA_PACKET_ERROR_NONE;
392 LOGW("there is no esink info");
393 return MM_ERROR_INVALID_ARGUMENT;
395 /* update the screen only if visible is ture */
396 if (evas_info->keep_screen && (evas_info->visible != VISIBLE_FALSE)) {
397 Evas_Native_Surface surf;
398 rect_info result = { 0 };
399 evas_object_geometry_get(evas_info->eo, &evas_info->eo_size.x, &evas_info->eo_size.y, &evas_info->eo_size.w, &evas_info->eo_size.h);
400 if (!evas_info->eo_size.w || !evas_info->eo_size.h) {
401 LOGE("there is no information for evas object size");
402 return MM_ERROR_INVALID_ARGUMENT;
404 _mm_evas_renderer_update_geometry(evas_info, &result);
405 if (!result.w || !result.h) {
406 LOGE("no information about geometry (%d, %d)", result.w, result.h);
407 return MM_ERROR_INVALID_ARGUMENT;
410 if (evas_info->use_ratio) {
411 surf.data.tbm.ratio = (float) evas_info->w / evas_info->h;
412 LOGD("set ratio for letter mode");
414 evas_object_size_hint_align_set(evas_info->eo, EVAS_HINT_FILL, EVAS_HINT_FILL);
415 evas_object_size_hint_weight_set(evas_info->eo, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
416 if (evas_info->w > 0 && evas_info->h > 0)
417 evas_object_image_size_set(evas_info->eo, evas_info->w, evas_info->h);
419 if (result.x || result.y)
420 LOGD("coordinate x, y (%d, %d) for locating video to center", result.x, result.y);
421 evas_object_image_fill_set(evas_info->eo, result.x, result.y, result.w, result.h);
423 /* set flush buffer */
424 surf.type = EVAS_NATIVE_SURFACE_TBM;
425 surf.version = EVAS_NATIVE_SURFACE_VERSION;
426 surf.data.tbm.buffer = evas_info->flush_buffer->tbm_surf;
427 surf.data.tbm.rot = evas_info->rotate_angle;
428 surf.data.tbm.flip = evas_info->flip;
429 evas_object_image_native_surface_set(evas_info->eo, &surf);
431 LOGD("flush_buffer surf(%p), rotate(%d), flip(%d)", evas_info->flush_buffer->tbm_surf, evas_info->rotate_angle, evas_info->flip);
433 /* unset evas native surface for displaying black screen */
434 evas_object_image_native_surface_set (evas_info->eo, NULL);
435 evas_object_image_data_set (evas_info->eo, NULL);
437 LOGD("sent packet %d", evas_info->sent_buffer_cnt);
439 /* destroy all packets */
440 g_mutex_lock(&evas_info->mp_lock);
441 for (i = 0; i < MAX_PACKET_NUM; i++) {
442 if (evas_info->pkt_info[i].packet) {
443 LOGD("destroy packet [%p]", evas_info->pkt_info[i].packet);
444 ret_mp = media_packet_destroy(evas_info->pkt_info[i].packet);
445 if (ret_mp != MEDIA_PACKET_ERROR_NONE) {
446 LOGW("media_packet_destroy failed %p", evas_info->pkt_info[i].packet);
447 ret = MM_ERROR_UNKNOWN;
450 evas_info->sent_buffer_cnt--;
451 evas_info->pkt_info[i].packet = NULL;
452 evas_info->pkt_info[i].tbm_surf = NULL;
453 evas_info->pkt_info[i].prev = -1;
457 if (evas_info->sent_buffer_cnt != 0)
458 LOGE("it should be 0 --> [%d]", evas_info->sent_buffer_cnt);
459 evas_info->sent_buffer_cnt = 0;
460 evas_info->cur_idx = -1;
461 g_mutex_unlock(&evas_info->mp_lock);
463 evas_object_image_pixels_dirty_set (evas_info->eo, EINA_TRUE);
464 evas_info->retrieve_packet = FALSE;
470 int _reset_pipe(mm_evas_info *evas_info)
473 int ret = MM_ERROR_NONE;
474 int ret_mp = MEDIA_PACKET_ERROR_NONE;
476 /* delete old pipe */
477 if (evas_info->epipe) {
478 LOGD("pipe %p will be deleted", evas_info->epipe);
479 ecore_pipe_del(evas_info->epipe);
480 evas_info->epipe = NULL;
483 for (i = 0; i < MAX_PACKET_NUM; i++) {
484 if (evas_info->pkt_info[i].packet) {
485 /* destroy all packets */
486 LOGD("destroy packet [%p]", evas_info->pkt_info[i].packet);
487 ret_mp = media_packet_destroy(evas_info->pkt_info[i].packet);
488 if (ret_mp != MEDIA_PACKET_ERROR_NONE) {
489 LOGW("media_packet_destroy failed %p", evas_info->pkt_info[i].packet);
490 ret = MM_ERROR_UNKNOWN;
493 evas_info->sent_buffer_cnt--;
494 evas_info->pkt_info[i].packet = NULL;
495 evas_info->pkt_info[i].tbm_surf = NULL;
496 evas_info->pkt_info[i].prev = -1;
500 if (evas_info->sent_buffer_cnt != 0)
501 LOGE("it should be 0 --> [%d]", evas_info->sent_buffer_cnt);
502 evas_info->sent_buffer_cnt = 0;
503 evas_info->cur_idx = -1;
506 if (!evas_info->epipe) {
507 evas_info->epipe = ecore_pipe_add((Ecore_Pipe_Cb) _evas_pipe_cb, evas_info);
508 if (!evas_info->epipe) {
509 LOGE("pipe is not created");
510 ret = MM_ERROR_UNKNOWN;
512 LOGD("created pipe %p", evas_info->epipe);
519 static void _mm_evas_renderer_set_callback(mm_evas_info *evas_info)
522 SET_EVAS_OBJECT_EVENT_CALLBACK(evas_info->eo, evas_info);
523 SET_EVAS_EVENT_CALLBACK(evas_object_evas_get(evas_info->eo), evas_info);
527 static void _mm_evas_renderer_unset_callback(mm_evas_info *evas_info)
530 UNSET_EVAS_OBJECT_EVENT_CALLBACK(evas_info->eo);
531 UNSET_EVAS_EVENT_CALLBACK(evas_object_evas_get(evas_info->eo));
535 int _mm_evas_renderer_create(mm_evas_info **evas_info)
537 mm_evas_info *ptr = NULL;
538 ptr = g_malloc0(sizeof(mm_evas_info));
541 LOGE("Cannot allocate memory for evas_info\n");
545 LOGD("Success create evas_info(%p)", *evas_info);
547 g_mutex_init(&ptr->mp_lock);
548 g_mutex_init(&ptr->idx_lock);
550 return MM_ERROR_NONE;
554 return MM_ERROR_OUT_OF_STORAGE;
557 int _mm_evas_renderer_destroy(mm_evas_info **evas_info)
559 mm_evas_info *ptr = (mm_evas_info *)*evas_info;
561 int ret = MM_ERROR_NONE;
563 LOGD("finalize evas_info %p", ptr);
565 ret = _mm_evas_renderer_reset(ptr);
566 g_mutex_clear(&ptr->mp_lock);
567 g_mutex_clear(&ptr->idx_lock);
575 int _mm_evas_renderer_set_info(mm_evas_info *evas_info, Evas_Object *eo)
577 MM_CHECK_NULL(evas_info);
579 g_mutex_lock(&evas_info->idx_lock);
581 LOGD("set evas_info");
583 for (i = 0; i < MAX_PACKET_NUM; i++) {
584 evas_info->pkt_info[i].packet = NULL;
585 evas_info->pkt_info[i].tbm_surf = NULL;
586 evas_info->pkt_info[i].prev = -1;
589 evas_info->cur_idx = -1;
591 evas_info->epipe = ecore_pipe_add((Ecore_Pipe_Cb) _evas_pipe_cb, evas_info);
592 if (!evas_info->epipe) {
593 LOGE("pipe is not created");
594 g_mutex_unlock(&evas_info->idx_lock);
595 return MM_ERROR_UNKNOWN;
597 LOGD("created pipe %p", evas_info->epipe);
598 _mm_evas_renderer_set_callback(evas_info);
600 evas_object_geometry_get(evas_info->eo, &evas_info->eo_size.x, &evas_info->eo_size.y, &evas_info->eo_size.w, &evas_info->eo_size.h);
601 LOGI("evas object %p (%d, %d, %d, %d)", evas_info->eo, evas_info->eo_size.x, evas_info->eo_size.y, evas_info->eo_size.w, evas_info->eo_size.h);
603 g_mutex_unlock(&evas_info->idx_lock);
605 return MM_ERROR_NONE;
608 int _mm_evas_renderer_reset(mm_evas_info *evas_info)
610 MM_CHECK_NULL(evas_info);
611 g_mutex_lock(&evas_info->idx_lock);
614 int ret = MM_ERROR_NONE;
615 int ret_mp = MEDIA_PACKET_ERROR_NONE;
618 _mm_evas_renderer_unset_callback(evas_info);
619 evas_object_image_data_set(evas_info->eo, NULL);
620 evas_info->eo = NULL;
622 if (evas_info->epipe) {
623 LOGD("pipe %p will be deleted", evas_info->epipe);
624 ecore_pipe_del(evas_info->epipe);
625 evas_info->epipe = NULL;
628 evas_info->eo_size.x = evas_info->eo_size.y = evas_info->eo_size.w = evas_info->eo_size.h = 0;
629 evas_info->w = evas_info->h = 0;
631 if (evas_info->flush_buffer)
632 _mm_evas_renderer_release_flush_buffer(evas_info);
634 g_mutex_lock(&evas_info->mp_lock);
635 for (i = 0; i < MAX_PACKET_NUM; i++) {
636 if (evas_info->pkt_info[i].packet) {
637 /* destroy all packets */
638 LOGD("destroy packet [%p]", evas_info->pkt_info[i].packet);
639 ret_mp = media_packet_destroy(evas_info->pkt_info[i].packet);
640 if (ret_mp != MEDIA_PACKET_ERROR_NONE) {
641 LOGW("media_packet_destroy failed %p", evas_info->pkt_info[i].packet);
642 ret = MM_ERROR_UNKNOWN;
645 evas_info->sent_buffer_cnt--;
646 evas_info->pkt_info[i].packet = NULL;
647 evas_info->pkt_info[i].tbm_surf = NULL;
648 evas_info->pkt_info[i].prev = -1;
651 g_mutex_unlock(&evas_info->mp_lock);
652 if (evas_info->sent_buffer_cnt != 0)
653 LOGE("it should be 0 --> [%d]", evas_info->sent_buffer_cnt);
654 evas_info->sent_buffer_cnt = 0;
655 evas_info->cur_idx = -1;
657 g_mutex_unlock(&evas_info->idx_lock);
662 void _mm_evas_renderer_update_geometry(mm_evas_info *evas_info, rect_info *result)
664 if (!evas_info || !evas_info->eo) {
665 LOGW("there is no evas_info or evas object");
669 LOGW("there is no rect info");
676 switch (evas_info->display_geometry_method) {
677 case DISP_GEO_METHOD_LETTER_BOX:
678 /* set black padding for letter box mode */
679 LOGD("letter box mode");
680 evas_info->use_ratio = TRUE;
681 result->w = evas_info->eo_size.w;
682 result->h = evas_info->eo_size.h;
684 case DISP_GEO_METHOD_ORIGIN_SIZE:
685 LOGD("origin size mode");
686 evas_info->use_ratio = FALSE;
687 /* set coordinate for each case */
688 result->x = (evas_info->eo_size.w - evas_info->w) / 2;
689 result->y = (evas_info->eo_size.h - evas_info->h) / 2;
690 result->w = evas_info->w;
691 result->h = evas_info->h;
693 case DISP_GEO_METHOD_FULL_SCREEN:
694 LOGD("full screen mode");
695 evas_info->use_ratio = FALSE;
696 result->w = evas_info->eo_size.w;
697 result->h = evas_info->eo_size.h;
699 case DISP_GEO_METHOD_CROPPED_FULL_SCREEN:
700 LOGD("cropped full screen mode");
701 evas_info->use_ratio = FALSE;
702 /* compare evas object's ratio with video's */
703 if ((evas_info->eo_size.w / evas_info->eo_size.h) > (evas_info->w / evas_info->h)) {
704 result->w = evas_info->eo_size.w;
705 result->h = evas_info->eo_size.w * evas_info->h / evas_info->w;
706 result->y = -(result->h - evas_info->eo_size.h) / 2;
708 result->w = evas_info->eo_size.h * evas_info->w / evas_info->h;
709 result->h = evas_info->eo_size.h;
710 result->x = -(result->w - evas_info->eo_size.w) / 2;
713 case DISP_GEO_METHOD_ORIGIN_SIZE_OR_LETTER_BOX:
714 LOGD("origin size or letter box mode");
715 /* if video size is smaller than evas object's, it will be set to origin size mode */
716 if ((evas_info->eo_size.w > evas_info->w) && (evas_info->eo_size.h > evas_info->h)) {
717 LOGD("origin size mode");
718 evas_info->use_ratio = FALSE;
719 /* set coordinate for each case */
720 result->x = (evas_info->eo_size.w - evas_info->w) / 2;
721 result->y = (evas_info->eo_size.h - evas_info->h) / 2;
722 result->w = evas_info->w;
723 result->h = evas_info->h;
725 LOGD("letter box mode");
726 evas_info->use_ratio = TRUE;
727 result->w = evas_info->eo_size.w;
728 result->h = evas_info->eo_size.h;
732 LOGW("unsupported mode.");
735 LOGD("geometry result [%d, %d, %d, %d]", result->x, result->y, result->w, result->h);
738 int _mm_evas_renderer_apply_geometry(mm_evas_info *evas_info)
740 if (!evas_info || !evas_info->eo) {
741 LOGW("there is no evas_info or evas object");
742 return MM_ERROR_NONE;
745 Evas_Native_Surface *surf = evas_object_image_native_surface_get(evas_info->eo);
746 rect_info result = { 0 };
749 LOGD("native surface exists");
750 surf->data.tbm.rot = evas_info->rotate_angle;
751 surf->data.tbm.flip = evas_info->flip;
752 evas_object_image_native_surface_set(evas_info->eo, surf);
754 _mm_evas_renderer_update_geometry(evas_info, &result);
756 if (evas_info->use_ratio) {
757 surf->data.tbm.ratio = (float) evas_info->w / evas_info->h;
758 LOGD("set ratio for letter mode");
761 if (result.x || result.y)
762 LOGD("coordinate x, y (%d, %d) for locating video to center", result.x, result.y);
764 evas_object_image_fill_set(evas_info->eo, result.x, result.y, result.w, result.h);
765 return MM_ERROR_NONE;
767 LOGW("there is no surf");
768 /* FIXME: before pipe_cb is invoked, apply_geometry can be called. */
769 return MM_ERROR_NONE;
772 int _mm_evas_renderer_retrieve_all_packets(mm_evas_info *evas_info, bool keep_screen)
774 MM_CHECK_NULL(evas_info);
776 int ret = MM_ERROR_NONE;
777 pid_t pid = getpid();
778 pid_t tid = syscall(SYS_gettid);
780 /* write and this API can be called at the same time.
781 so lock is needed for counting sent_buffer_cnt correctly */
782 g_mutex_lock(&evas_info->idx_lock);
784 /* make flush buffer */
786 ret = _mm_evas_renderer_make_flush_buffer(evas_info);
787 evas_info->keep_screen = keep_screen;
789 LOGD("pid [%d], tid [%d]", pid, tid);
791 /* in this case, we deem it is main thread */
792 if (_flush_packets(evas_info) != MM_ERROR_NONE) {
793 LOGE("flushing packets are failed");
794 ret = MM_ERROR_UNKNOWN;
797 /* it will be executed to write flush buffer and destroy media packets in pre_cb */
798 evas_info->retrieve_packet = TRUE;
800 g_mutex_unlock(&evas_info->idx_lock);
805 /* make buffer for copying */
806 int _mm_evas_renderer_make_flush_buffer (mm_evas_info *evas_info)
808 if (evas_info->cur_idx == -1) {
809 LOGW("there is no remained buffer");
810 return MM_ERROR_INVALID_ARGUMENT;
812 media_packet_h packet = evas_info->pkt_info[evas_info->cur_idx].packet;
813 MM_CHECK_NULL(packet);
815 flush_info *flush_buffer = NULL;
816 tbm_bo src_bo = NULL;
817 tbm_surface_h src_tbm_surf = NULL;
822 tbm_bo_handle vaddr_src = {0};
823 tbm_bo_handle vaddr_dst = {0};
824 int ret = MM_ERROR_NONE;
826 if (evas_info->flush_buffer)
827 _mm_evas_renderer_release_flush_buffer(evas_info);
830 flush_buffer = (flush_info *)malloc(sizeof(flush_info));
831 if (flush_buffer == NULL) {
832 LOGE("malloc is failed");
835 memset(flush_buffer, 0x0, sizeof(flush_info));
837 ret = media_packet_get_tbm_surface(packet, &src_tbm_surf);
838 if (ret != MEDIA_PACKET_ERROR_NONE || !src_tbm_surf) {
839 LOGW("get_tbm_surface is failed");
843 /* get src buffer info */
844 tbm_fmt = tbm_surface_get_format(src_tbm_surf);
845 src_bo = tbm_surface_internal_get_bo(src_tbm_surf, 0);
846 src_size = tbm_bo_size(src_bo);
847 if (!src_bo || !src_size) {
848 LOGE("bo(%p), size(%d)", src_bo, src_size);
852 /* create tbm surface */
853 flush_buffer->tbm_surf = tbm_surface_create(evas_info->w, evas_info->h, tbm_fmt);
854 if (!flush_buffer->tbm_surf)
856 LOGE("tbm_surf is NULL!!");
860 /* get bo and size */
861 bo = tbm_surface_internal_get_bo(flush_buffer->tbm_surf, 0);
862 size = tbm_bo_size(bo);
865 LOGE("bo(%p), size(%d)", bo, size);
868 flush_buffer->bo = bo;
870 vaddr_src = tbm_bo_map(src_bo, TBM_DEVICE_CPU, TBM_OPTION_READ|TBM_OPTION_WRITE);
871 vaddr_dst = tbm_bo_map(bo, TBM_DEVICE_CPU, TBM_OPTION_READ|TBM_OPTION_WRITE);
872 if (!vaddr_src.ptr || !vaddr_dst.ptr) {
873 LOGW("get vaddr failed src %p, dst %p", vaddr_src.ptr, vaddr_dst.ptr);
875 tbm_bo_unmap(src_bo);
882 memset (vaddr_dst.ptr, 0x0, size);
883 LOGW ("tbm_bo_map(vaddr) is finished, bo(%p), vaddr(%p)", bo, vaddr_dst.ptr);
887 memcpy(vaddr_dst.ptr, vaddr_src.ptr, src_size);
889 tbm_bo_unmap(src_bo);
891 LOGW("copy is done. tbm surface : %p src_size : %d", flush_buffer->tbm_surf, src_size);
893 evas_info->flush_buffer = flush_buffer;
895 return MM_ERROR_NONE;
899 if(flush_buffer->tbm_surf)
901 tbm_surface_destroy(flush_buffer->tbm_surf);
902 flush_buffer->tbm_surf = NULL;
908 return MM_ERROR_UNKNOWN;
911 /* release flush buffer */
912 void _mm_evas_renderer_release_flush_buffer (mm_evas_info *evas_info)
914 LOGW("release FLUSH BUFFER start");
915 if (evas_info->flush_buffer->bo) {
916 evas_info->flush_buffer->bo = NULL;
918 if (evas_info->flush_buffer->tbm_surf) {
919 tbm_surface_destroy(evas_info->flush_buffer->tbm_surf);
920 evas_info->flush_buffer->tbm_surf = NULL;
923 LOGW("release FLUSH BUFFER done");
925 free(evas_info->flush_buffer);
926 evas_info->flush_buffer = NULL;
931 void mm_evas_renderer_write(media_packet_h packet, void *data)
934 LOGE("packet %p is NULL", packet);
937 mm_evas_info *handle = (mm_evas_info *)data;
938 int ret = MEDIA_PACKET_ERROR_NONE;
940 tbm_surface_h tbm_surf;
943 LOGD("packet [%p]", packet);
945 if (!data || !handle) {
946 LOGE("handle %p or evas_info %p is NULL", data, handle);
949 g_mutex_lock(&handle->idx_lock);
951 ret = media_packet_has_tbm_surface_buffer(packet, &has);
952 if (ret != MEDIA_PACKET_ERROR_NONE) {
953 LOGW("has_tbm_surface is failed");
956 /* FIXME: when setCaps occurs, _get_video_size should be called */
957 /* currently we are always checking it */
958 if (has && _get_video_size(packet, handle)) {
959 /* Attention! if this error occurs, we need to consider managing buffer */
960 if (handle->sent_buffer_cnt > 4) {
961 LOGE("too many buffers are not released %d", handle->sent_buffer_cnt);
964 /* FIXME: fix this logic */
965 /* destroy all media packets and reset pipe at present */
966 /* Attention! it might free buffer that is being rendered */
967 g_mutex_lock(&handle->mp_lock);
969 g_mutex_unlock(&handle->mp_lock);
972 ret = media_packet_get_tbm_surface(packet, &tbm_surf);
973 if (ret != MEDIA_PACKET_ERROR_NONE || !tbm_surf) {
974 LOGW("get_tbm_surface is failed");
978 /* find new index for current packet */
979 index = _find_empty_index(handle);
984 /* save previous index */
985 handle->pkt_info[index].prev = handle->cur_idx;
986 handle->pkt_info[index].packet = packet;
987 handle->pkt_info[index].tbm_surf = tbm_surf;
988 handle->cur_idx = index;
989 handle->sent_buffer_cnt++;
990 LOGD("sent packet %d", handle->sent_buffer_cnt);
992 ret = ecore_pipe_write(handle->epipe, handle, UPDATE_TBM_SURF);
994 handle->pkt_info[index].packet = NULL;
995 handle->pkt_info[index].tbm_surf = NULL;
996 handle->pkt_info[index].prev = -1;
997 handle->cur_idx = handle->pkt_info[index].prev;
998 handle->sent_buffer_cnt--;
999 LOGW("Failed to ecore_pipe_write() for updating tbm surf\n");
1003 LOGW("no tbm_surf");
1006 g_mutex_unlock(&handle->idx_lock);
1010 g_mutex_unlock(&handle->idx_lock);
1012 /* destroy media_packet immediately */
1014 g_mutex_lock(&handle->mp_lock);
1015 LOGD("cant write. destroy packet [%p]", packet);
1016 if (media_packet_destroy(packet) != MEDIA_PACKET_ERROR_NONE)
1017 LOGE("media_packet_destroy failed %p", packet);
1019 g_mutex_unlock(&handle->mp_lock);
1024 int mm_evas_renderer_update_param(MMHandleType handle)
1026 int ret = MM_ERROR_NONE;
1027 mm_evas_info *evas_info = (mm_evas_info *)handle;
1030 LOGW("skip it. it is not evas surface type.");
1034 /* when handle is realized, we need to update all properties */
1036 LOGD("set video param : evas-object %x, method %d", evas_info->eo, evas_info->display_geometry_method);
1037 LOGD("set video param : visible %d", evas_info->visible);
1038 LOGD("set video param : rotate %d", evas_info->rotate_angle);
1040 ret = _mm_evas_renderer_apply_geometry(evas_info);
1041 if (ret != MM_ERROR_NONE)
1044 if (evas_info->epipe) {
1045 ret = ecore_pipe_write(evas_info->epipe, &evas_info->visible, UPDATE_VISIBILITY);
1047 LOGW("fail to ecore_pipe_write() for updating visibility\n");
1048 return MM_ERROR_UNKNOWN;
1050 #if 0 /* FIXME: pause state only */
1051 g_mutex_lock(&evas_info->idx_lock);
1052 ret = ecore_pipe_write(evas_info->epipe, evas_info, UPDATE_TBM_SURF);
1054 LOGW("fail to ecore_pipe_write() for updating visibility\n");
1055 ret = MM_ERROR_UNKNOWN;
1057 ret = MM_ERROR_NONE;
1059 g_mutex_unlock(&evas_info->idx_lock);
1067 int mm_evas_renderer_create(MMHandleType *handle, Evas_Object *eo)
1069 MM_CHECK_NULL(handle);
1071 int ret = MM_ERROR_NONE;
1072 mm_evas_info *evas_info = NULL;
1074 ret = _mm_evas_renderer_create(&evas_info);
1075 if (ret != MM_ERROR_NONE) {
1076 LOGE("fail to create evas_info");
1079 ret = _mm_evas_renderer_set_info(evas_info, eo);
1080 if (ret != MM_ERROR_NONE) {
1081 LOGE("fail to init evas_info");
1082 if (_mm_evas_renderer_destroy(&evas_info) != MM_ERROR_NONE)
1083 LOGE("fail to destroy evas_info");
1087 *handle = (MMHandleType)evas_info;
1089 return MM_ERROR_NONE;
1092 int mm_evas_renderer_destroy(MMHandleType *handle)
1094 MM_CHECK_NULL(handle);
1096 int ret = MM_ERROR_NONE;
1097 mm_evas_info *evas_info = (mm_evas_info *)*handle;
1100 LOGD("skip it. it is not evas surface type.");
1101 return MM_ERROR_RESOURCE_NOT_INITIALIZED;
1104 ret = _mm_evas_renderer_destroy(&evas_info);
1105 if (ret != MM_ERROR_NONE) {
1106 LOGE("fail to destroy evas_info");
1111 return MM_ERROR_NONE;
1114 int mm_evas_renderer_set_visible(MMHandleType handle, bool visible)
1116 int ret = MM_ERROR_NONE;
1117 mm_evas_info *evas_info = (mm_evas_info *)handle;
1120 LOGW("skip it. it is not evas surface type or handle is not prepared");
1121 return MM_ERROR_RESOURCE_NOT_INITIALIZED;
1125 evas_info->visible = VISIBLE_TRUE;
1127 evas_info->visible = VISIBLE_FALSE;
1129 if (evas_info->epipe) {
1130 ret = ecore_pipe_write(evas_info->epipe, &visible, UPDATE_VISIBILITY);
1132 LOGW("fail to ecore_pipe_write() for updating visibility\n");
1133 ret = MM_ERROR_UNKNOWN;
1135 ret = MM_ERROR_NONE;
1138 LOGW("there is no epipe. we cant update it");
1144 int mm_evas_renderer_get_visible(MMHandleType handle, bool *visible)
1146 mm_evas_info *evas_info = (mm_evas_info *)handle;
1149 LOGW("skip it. it is not evas surface type or handle is not prepared");
1150 return MM_ERROR_RESOURCE_NOT_INITIALIZED;
1153 if (evas_info->visible == VISIBLE_FALSE)
1158 return MM_ERROR_NONE;
1161 int mm_evas_renderer_set_rotation(MMHandleType handle, int rotate)
1163 int ret = MM_ERROR_NONE;
1164 mm_evas_info *evas_info = (mm_evas_info *)handle;
1167 LOGW("skip it. it is not evas surface type or handle is not prepared");
1168 return MM_ERROR_RESOURCE_NOT_INITIALIZED;
1173 evas_info->rotate_angle = EVAS_IMAGE_ORIENT_0;
1176 evas_info->rotate_angle = EVAS_IMAGE_ORIENT_90;
1179 evas_info->rotate_angle = EVAS_IMAGE_ORIENT_180;
1182 evas_info->rotate_angle = EVAS_IMAGE_ORIENT_270;
1185 return MM_ERROR_INVALID_ARGUMENT;
1187 #if 0 /* FIXME: pause state only */
1188 if (evas_info->epipe) {
1189 g_mutex_lock(&evas_info->idx_lock);
1190 ret = ecore_pipe_write(evas_info->epipe, evas_info, UPDATE_TBM_SURF);
1192 LOGW("fail to ecore_pipe_write() for updating visibility\n");
1193 ret = MM_ERROR_UNKNOWN;
1195 ret = MM_ERROR_NONE;
1197 g_mutex_unlock(&evas_info->idx_lock);
1203 int mm_evas_renderer_get_rotation(MMHandleType handle, int *rotate)
1205 mm_evas_info *evas_info = (mm_evas_info *)handle;
1208 LOGW("skip it. it is not evas surface type or handle is not prepared");
1209 return MM_ERROR_RESOURCE_NOT_INITIALIZED;
1212 switch(evas_info->rotate_angle) {
1213 case EVAS_IMAGE_ORIENT_0:
1216 case EVAS_IMAGE_ORIENT_90:
1217 *rotate = DEGREE_90;
1219 case EVAS_IMAGE_ORIENT_180:
1220 *rotate = DEGREE_180;
1222 case EVAS_IMAGE_ORIENT_270:
1223 *rotate = DEGREE_270;
1226 return MM_ERROR_INVALID_ARGUMENT;
1229 return MM_ERROR_NONE;
1232 int mm_evas_renderer_set_geometry(MMHandleType handle, int mode)
1234 int ret = MM_ERROR_NONE;
1235 mm_evas_info *evas_info = (mm_evas_info *)handle;
1238 LOGW("skip it. it is not evas surface type or handle is not prepared");
1239 return MM_ERROR_RESOURCE_NOT_INITIALIZED;
1242 evas_info->display_geometry_method = mode;
1243 ret = _mm_evas_renderer_apply_geometry(evas_info);
1245 /* ecore_pipe_write is needed, because of setting ratio for letterbox mode */
1246 #if 0 /* FIXME: pause state only */
1247 if (evas_info->epipe) {
1248 g_mutex_lock(&evas_info->idx_lock);
1249 ret = ecore_pipe_write(evas_info->epipe, evas_info, UPDATE_TBM_SURF);
1251 LOGW("fail to ecore_pipe_write() for updating visibility\n");
1252 ret = MM_ERROR_UNKNOWN;
1254 ret = MM_ERROR_NONE;
1256 g_mutex_unlock(&evas_info->idx_lock);
1263 int mm_evas_renderer_get_geometry(MMHandleType handle, int *mode)
1265 mm_evas_info *evas_info = (mm_evas_info *)handle;
1268 LOGW("skip it. it is not evas surface type or handle is not prepared");
1269 return MM_ERROR_RESOURCE_NOT_INITIALIZED;
1271 *mode = evas_info->display_geometry_method;
1273 return MM_ERROR_NONE;
1276 int mm_evas_renderer_set_flip(MMHandleType handle, int flip)
1278 int ret = MM_ERROR_NONE;
1279 mm_evas_info *evas_info = (mm_evas_info *)handle;
1282 LOGW("skip it. it is not evas surface type or handle is not prepared");
1283 return MM_ERROR_RESOURCE_NOT_INITIALIZED;
1288 evas_info->flip = 0;
1290 case FLIP_HORIZONTAL:
1291 evas_info->flip = EVAS_IMAGE_FLIP_HORIZONTAL;
1294 evas_info->flip = EVAS_IMAGE_FLIP_VERTICAL;
1297 evas_info->flip = EVAS_IMAGE_ORIENT_180;
1300 return MM_ERROR_INVALID_ARGUMENT;
1302 #if 0 /* FIXME: pause state only */
1303 if (evas_info->epipe) {
1304 g_mutex_lock(&evas_info->idx_lock);
1305 ret = ecore_pipe_write(evas_info->epipe, evas_info, UPDATE_TBM_SURF);
1307 LOGW("fail to ecore_pipe_write() for updating visibility\n");
1308 ret = MM_ERROR_UNKNOWN;
1310 ret = MM_ERROR_NONE;
1312 g_mutex_unlock(&evas_info->idx_lock);
1318 int mm_evas_renderer_get_flip(MMHandleType handle, int *flip)
1320 mm_evas_info *evas_info = (mm_evas_info *)handle;
1323 LOGW("skip it. it is not evas surface type or handle is not prepared");
1324 return MM_ERROR_RESOURCE_NOT_INITIALIZED;
1327 switch(evas_info->flip) {
1331 case EVAS_IMAGE_FLIP_HORIZONTAL:
1332 *flip = FLIP_HORIZONTAL;
1334 case EVAS_IMAGE_FLIP_VERTICAL:
1335 *flip = FLIP_VERTICAL;
1337 case EVAS_IMAGE_ORIENT_180:
1341 return MM_ERROR_INVALID_ARGUMENT;
1344 return MM_ERROR_NONE;
1347 int mm_evas_renderer_retrieve_all_packets (MMHandleType handle, bool keep_screen)
1349 int ret = MM_ERROR_NONE;
1350 mm_evas_info *evas_info = (mm_evas_info*) handle;
1353 LOGW("skip it. it is not evas surface type or player is not prepared");
1354 return MM_ERROR_RESOURCE_NOT_INITIALIZED;
1356 ret = _mm_evas_renderer_retrieve_all_packets(evas_info, keep_screen);