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"
38 #define MM_CHECK_NULL( x_var ) \
41 LOGE("[%s] is NULL\n", #x_var ); \
42 return MM_ERROR_INVALID_ARGUMENT; \
45 #define SET_EVAS_OBJECT_EVENT_CALLBACK( x_evas_image_object, x_usr_data ) \
48 if (x_evas_image_object) { \
49 LOGD("object callback add"); \
50 evas_object_event_callback_add (x_evas_image_object, EVAS_CALLBACK_DEL, _evas_del_cb, x_usr_data); \
51 evas_object_event_callback_add (x_evas_image_object, EVAS_CALLBACK_RESIZE, _evas_resize_cb, x_usr_data); \
55 #define UNSET_EVAS_OBJECT_EVENT_CALLBACK( x_evas_image_object ) \
58 if (x_evas_image_object) { \
59 LOGD("object callback del"); \
60 evas_object_event_callback_del (x_evas_image_object, EVAS_CALLBACK_DEL, _evas_del_cb); \
61 evas_object_event_callback_del (x_evas_image_object, EVAS_CALLBACK_RESIZE, _evas_resize_cb); \
65 #define SET_EVAS_EVENT_CALLBACK( x_evas, x_usr_data ) \
69 LOGD("callback add... evas_callback_render_pre.. evas : %p evas_info : %p", x_evas, x_usr_data); \
70 evas_event_callback_add (x_evas, EVAS_CALLBACK_RENDER_PRE, _evas_render_pre_cb, x_usr_data); \
74 #define UNSET_EVAS_EVENT_CALLBACK( x_evas ) \
78 LOGD("callback del... evas_callback_render_pre %p", x_evas); \
79 evas_event_callback_del (x_evas, EVAS_CALLBACK_RENDER_PRE, _evas_render_pre_cb); \
84 DISP_GEO_METHOD_LETTER_BOX = 0,
85 DISP_GEO_METHOD_ORIGIN_SIZE,
86 DISP_GEO_METHOD_FULL_SCREEN,
87 DISP_GEO_METHOD_CROPPED_FULL_SCREEN,
88 DISP_GEO_METHOD_ORIGIN_SIZE_OR_LETTER_BOX,
110 void __print_idx(mm_evas_info *evas_info);
112 void _free_previous_packets(mm_evas_info *evas_info);
113 int _flush_packets(mm_evas_info *evas_info);
114 int _mm_evas_renderer_create(mm_evas_info **evas_info);
115 int _mm_evas_renderer_destroy(mm_evas_info **evas_info);
116 int _mm_evas_renderer_set_info(mm_evas_info *evas_info, Evas_Object *eo);
117 int _mm_evas_renderer_reset(mm_evas_info *evas_info);
118 void _mm_evas_renderer_update_geometry(mm_evas_info *evas_info, rect_info *result);
119 int _mm_evas_renderer_apply_geometry(mm_evas_info *evas_info);
120 int _mm_evas_renderer_retrieve_all_packets(mm_evas_info *evas_info, bool keep_screen);
121 int _mm_evas_renderer_make_flush_buffer(mm_evas_info *evas_info);
122 void _mm_evas_renderer_release_flush_buffer(mm_evas_info *evas_info);
123 static void _mm_evas_renderer_set_callback(mm_evas_info *evas_info);
124 static void _mm_evas_renderer_unset_callback(mm_evas_info *evas_info);
126 static void _evas_resize_cb(void *data, Evas *e, Evas_Object *obj, void *event_info)
131 mm_evas_info *evas_info = data;
134 if (!evas_info || !evas_info->eo) {
138 evas_object_geometry_get(evas_info->eo, &x, &y, &w, &h);
140 LOGW("evas object size (w:%d,h:%d) was not set", w, h);
142 evas_info->eo_size.x = x;
143 evas_info->eo_size.y = y;
144 evas_info->eo_size.w = w;
145 evas_info->eo_size.h = h;
146 LOGW("resize (x:%d, y:%d, w:%d, h:%d)", x, y, w, h);
147 ret = _mm_evas_renderer_apply_geometry(evas_info);
148 if (ret != MM_ERROR_NONE)
149 LOGW("fail to apply geometry info");
154 static void _evas_render_pre_cb(void *data, Evas *e, void *event_info)
156 mm_evas_info *evas_info = data;
158 if (!evas_info || !evas_info->eo) {
159 LOGW("there is no esink info.... esink : %p, or eo is NULL returning", evas_info);
163 /* flush will be executed in this callback normally,
164 because native_surface_set must be called in main thread */
165 if (evas_info->retrieve_packet) {
166 g_mutex_lock(&evas_info->idx_lock);
167 if (_flush_packets(evas_info) != MM_ERROR_NONE)
168 LOGE("flushing packets are failed");
169 g_mutex_unlock(&evas_info->idx_lock);
173 static void _evas_del_cb(void *data, Evas *e, Evas_Object *obj, void *event_info)
175 mm_evas_info *evas_info = data;
177 if (!evas_info || !evas_info->eo) {
181 _mm_evas_renderer_unset_callback(evas_info);
182 evas_object_image_data_set(evas_info->eo, NULL);
183 evas_info->eo = NULL;
188 void _evas_pipe_cb(void *data, void *buffer, update_info info)
190 mm_evas_info *evas_info = data;
195 LOGW("evas_info is NULL", evas_info);
199 g_mutex_lock(&evas_info->mp_lock);
201 if (!evas_info->eo) {
202 LOGW("evas_info %p", evas_info);
203 g_mutex_unlock(&evas_info->mp_lock);
207 LOGD("evas_info : %p, evas_info->eo : %p", evas_info, evas_info->eo);
208 if (info == UPDATE_VISIBILITY) {
209 if (evas_info->visible == VISIBLE_FALSE) {
210 evas_object_hide(evas_info->eo);
211 LOGI("object hide..");
213 evas_object_show(evas_info->eo);
214 LOGI("object show.. %d", evas_info->visible);
217 g_mutex_unlock(&evas_info->mp_lock);
221 if (info != UPDATE_TBM_SURF) {
222 LOGW("invalid info type : %d", info);
223 g_mutex_unlock(&evas_info->mp_lock);
227 if (evas_info->cur_idx==-1 || !evas_info->pkt_info[evas_info->cur_idx].tbm_surf) {
228 LOGW("cur_idx %d, tbm_surf may be NULL", evas_info->cur_idx);
229 g_mutex_unlock(&evas_info->mp_lock);
232 g_mutex_lock(&evas_info->idx_lock);
234 gint cur_idx = evas_info->cur_idx;
235 gint prev_idx = evas_info->pkt_info[cur_idx].prev;
237 LOGD("received (idx %d, packet %p)", cur_idx, evas_info->pkt_info[cur_idx].packet);
239 tbm_format tbm_fmt = tbm_surface_get_format(evas_info->pkt_info[cur_idx].tbm_surf);
241 case TBM_FORMAT_NV12:
242 LOGD("tbm_surface format : TBM_FORMAT_NV12");
244 case TBM_FORMAT_YUV420:
245 LOGD("tbm_surface format : TBM_FORMAT_YUV420");
248 LOGW("tbm_surface format : unknown %d", tbm_fmt);
251 /* it is needed to skip setting when state is pause */
252 Evas_Native_Surface surf;
253 surf.type = EVAS_NATIVE_SURFACE_TBM;
254 surf.version = EVAS_NATIVE_SURFACE_VERSION;
255 surf.data.tbm.buffer = evas_info->pkt_info[cur_idx].tbm_surf;
256 // surf.data.tbm.rot = evas_info->rotate_angle;
257 // surf.data.tbm.flip = evas_info->flip;
259 rect_info result = { 0 };
261 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);
262 if (!evas_info->eo_size.w || !evas_info->eo_size.h) {
263 LOGE("there is no information for evas object size");
266 _mm_evas_renderer_update_geometry(evas_info, &result);
267 if (!result.w || !result.h) {
268 LOGE("no information about geometry (%d, %d)", result.w, result.h);
272 if (evas_info->use_ratio) {
273 // surf.data.tbm.ratio = (float) evas_info->w / evas_info->h;
274 LOGD("set ratio for letter mode");
276 evas_object_size_hint_align_set(evas_info->eo, EVAS_HINT_FILL, EVAS_HINT_FILL);
277 evas_object_size_hint_weight_set(evas_info->eo, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
278 if (evas_info->w > 0 && evas_info->h > 0)
279 evas_object_image_size_set(evas_info->eo, evas_info->w, evas_info->h);
281 evas_object_image_native_surface_set(evas_info->eo, &surf);
282 LOGD("native surface set finish");
284 if (result.x || result.y)
285 LOGD("coordinate x, y (%d, %d) for locating video to center", result.x, result.y);
286 evas_object_image_fill_set(evas_info->eo, result.x, result.y, result.w, result.h);
288 evas_object_image_pixels_dirty_set(evas_info->eo, EINA_TRUE);
289 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);
291 /* when _evas_pipe_cb is called sequentially, previous packet and current packet will be the same */
292 if ((prev_idx != -1) && evas_info->pkt_info[prev_idx].packet && (prev_idx != cur_idx))
293 _free_previous_packets(evas_info);
296 g_mutex_unlock(&evas_info->idx_lock);
297 g_mutex_unlock(&evas_info->mp_lock);
302 if ((prev_idx != -1) && evas_info->pkt_info[prev_idx].packet) {
304 _free_previous_packets(evas_info);
306 g_mutex_unlock(&evas_info->idx_lock);
307 g_mutex_unlock(&evas_info->mp_lock);
311 void __print_idx(mm_evas_info *evas_info)
313 gint prev_idx = evas_info->pkt_info[evas_info->cur_idx].prev;
314 LOGE("***** start cur_idx : %d -> prev_idx : %d", evas_info->cur_idx, prev_idx);
315 while(prev_idx != -1)
317 LOGE("***** cur_idx : %d -> prev_idx : %d", prev_idx, evas_info->pkt_info[prev_idx].prev);
318 prev_idx = evas_info->pkt_info[prev_idx].prev;
325 void _free_previous_packets(mm_evas_info *evas_info)
327 gint index = evas_info->cur_idx;
328 gint prev_idx = evas_info->pkt_info[index].prev;
330 while(prev_idx != -1)
332 LOGD("destroy previous packet [%p] idx %d", evas_info->pkt_info[prev_idx].packet, prev_idx);
333 if (media_packet_destroy(evas_info->pkt_info[prev_idx].packet) != MEDIA_PACKET_ERROR_NONE)
334 LOGE("media_packet_destroy failed %p", evas_info->pkt_info[prev_idx].packet);
335 evas_info->pkt_info[prev_idx].packet = NULL;
336 evas_info->pkt_info[prev_idx].tbm_surf = NULL;
337 evas_info->pkt_info[index].prev = -1;
338 evas_info->sent_buffer_cnt--;
340 /* move index to previous index */
342 prev_idx = evas_info->pkt_info[prev_idx].prev;
343 LOGD("sent packet %d", evas_info->sent_buffer_cnt);
348 static int _get_video_size(media_packet_h packet, mm_evas_info *evas_info)
351 if (media_packet_get_format(packet, &fmt) == MEDIA_PACKET_ERROR_NONE) {
353 if (media_format_get_video_info(fmt, NULL, &w, &h, NULL, NULL) == MEDIA_PACKET_ERROR_NONE) {
354 LOGD("video width = %d, height =%d", w, h);
359 LOGW("media_format_get_video_info is failed");
360 if (media_format_unref(fmt) != MEDIA_PACKET_ERROR_NONE) /* because of media_packet_get_format */
361 LOGW("media_format_unref is failed");
363 LOGW("media_packet_get_format is failed");
368 int _find_empty_index(mm_evas_info *evas_info)
371 for (i = 0; i < MAX_PACKET_NUM; i++) {
372 if (!evas_info->pkt_info[i].packet) {
373 LOGD("selected idx %d", i);
377 LOGE("there is no empty idx");
382 int _flush_packets(mm_evas_info *evas_info)
384 int ret = MM_ERROR_NONE;
385 int ret_mp = MEDIA_PACKET_ERROR_NONE;
389 LOGW("there is no esink info");
390 return MM_ERROR_INVALID_ARGUMENT;
392 /* update the screen only if visible is ture */
393 if (evas_info->keep_screen && (evas_info->visible != VISIBLE_FALSE)) {
394 Evas_Native_Surface surf;
395 rect_info result = { 0 };
396 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);
397 if (!evas_info->eo_size.w || !evas_info->eo_size.h) {
398 LOGE("there is no information for evas object size");
399 return MM_ERROR_INVALID_ARGUMENT;
401 _mm_evas_renderer_update_geometry(evas_info, &result);
402 if (!result.w || !result.h) {
403 LOGE("no information about geometry (%d, %d)", result.w, result.h);
404 return MM_ERROR_INVALID_ARGUMENT;
407 if (evas_info->use_ratio) {
408 // surf.data.tbm.ratio = (float) evas_info->w / evas_info->h;
409 LOGD("set ratio for letter mode");
411 evas_object_size_hint_align_set(evas_info->eo, EVAS_HINT_FILL, EVAS_HINT_FILL);
412 evas_object_size_hint_weight_set(evas_info->eo, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
413 if (evas_info->w > 0 && evas_info->h > 0)
414 evas_object_image_size_set(evas_info->eo, evas_info->w, evas_info->h);
416 if (result.x || result.y)
417 LOGD("coordinate x, y (%d, %d) for locating video to center", result.x, result.y);
418 evas_object_image_fill_set(evas_info->eo, result.x, result.y, result.w, result.h);
420 /* set flush buffer */
421 surf.type = EVAS_NATIVE_SURFACE_TBM;
422 surf.version = EVAS_NATIVE_SURFACE_VERSION;
423 surf.data.tbm.buffer = evas_info->flush_buffer->tbm_surf;
424 // surf.data.tbm.rot = evas_info->rotate_angle;
425 // surf.data.tbm.flip = evas_info->flip;
426 evas_object_image_native_surface_set(evas_info->eo, &surf);
428 LOGD("flush_buffer surf(%p), rotate(%d), flip(%d)", evas_info->flush_buffer->tbm_surf, evas_info->rotate_angle, evas_info->flip);
430 /* unset evas native surface for displaying black screen */
431 evas_object_image_native_surface_set (evas_info->eo, NULL);
432 evas_object_image_data_set (evas_info->eo, NULL);
434 LOGD("sent packet %d", evas_info->sent_buffer_cnt);
436 /* destroy all packets */
437 g_mutex_lock(&evas_info->mp_lock);
438 for (i = 0; i < MAX_PACKET_NUM; i++) {
439 if (evas_info->pkt_info[i].packet) {
440 LOGD("destroy packet [%p]", evas_info->pkt_info[i].packet);
441 ret_mp = media_packet_destroy(evas_info->pkt_info[i].packet);
442 if (ret_mp != MEDIA_PACKET_ERROR_NONE) {
443 LOGW("media_packet_destroy failed %p", evas_info->pkt_info[i].packet);
444 ret = MM_ERROR_UNKNOWN;
447 evas_info->sent_buffer_cnt--;
448 evas_info->pkt_info[i].packet = NULL;
449 evas_info->pkt_info[i].tbm_surf = NULL;
450 evas_info->pkt_info[i].prev = -1;
454 if (evas_info->sent_buffer_cnt != 0)
455 LOGE("it should be 0 --> [%d]", evas_info->sent_buffer_cnt);
456 evas_info->sent_buffer_cnt = 0;
457 evas_info->cur_idx = -1;
458 g_mutex_unlock(&evas_info->mp_lock);
460 evas_object_image_pixels_dirty_set (evas_info->eo, EINA_TRUE);
461 evas_info->retrieve_packet = FALSE;
467 int _reset_pipe(mm_evas_info *evas_info)
470 int ret = MM_ERROR_NONE;
471 int ret_mp = MEDIA_PACKET_ERROR_NONE;
473 /* delete old pipe */
474 if (evas_info->epipe) {
475 LOGD("pipe %p will be deleted", evas_info->epipe);
476 ecore_pipe_del(evas_info->epipe);
477 evas_info->epipe = NULL;
480 for (i = 0; i < MAX_PACKET_NUM; i++) {
481 if (evas_info->pkt_info[i].packet) {
482 /* destroy all packets */
483 LOGD("destroy packet [%p]", evas_info->pkt_info[i].packet);
484 ret_mp = media_packet_destroy(evas_info->pkt_info[i].packet);
485 if (ret_mp != MEDIA_PACKET_ERROR_NONE) {
486 LOGW("media_packet_destroy failed %p", evas_info->pkt_info[i].packet);
487 ret = MM_ERROR_UNKNOWN;
490 evas_info->sent_buffer_cnt--;
491 evas_info->pkt_info[i].packet = NULL;
492 evas_info->pkt_info[i].tbm_surf = NULL;
493 evas_info->pkt_info[i].prev = -1;
497 if (evas_info->sent_buffer_cnt != 0)
498 LOGE("it should be 0 --> [%d]", evas_info->sent_buffer_cnt);
499 evas_info->sent_buffer_cnt = 0;
500 evas_info->cur_idx = -1;
503 if (!evas_info->epipe) {
504 evas_info->epipe = ecore_pipe_add((Ecore_Pipe_Cb) _evas_pipe_cb, evas_info);
505 if (!evas_info->epipe) {
506 LOGE("pipe is not created");
507 ret = MM_ERROR_UNKNOWN;
509 LOGD("created pipe %p", evas_info->epipe);
516 static void _mm_evas_renderer_set_callback(mm_evas_info *evas_info)
519 SET_EVAS_OBJECT_EVENT_CALLBACK(evas_info->eo, evas_info);
520 SET_EVAS_EVENT_CALLBACK(evas_object_evas_get(evas_info->eo), evas_info);
524 static void _mm_evas_renderer_unset_callback(mm_evas_info *evas_info)
527 UNSET_EVAS_OBJECT_EVENT_CALLBACK(evas_info->eo);
528 UNSET_EVAS_EVENT_CALLBACK(evas_object_evas_get(evas_info->eo));
532 int _mm_evas_renderer_create(mm_evas_info **evas_info)
534 mm_evas_info *ptr = NULL;
535 ptr = g_malloc0(sizeof(mm_evas_info));
538 LOGE("Cannot allocate memory for evas_info\n");
542 LOGD("Success create evas_info(%p)", *evas_info);
544 g_mutex_init(&ptr->mp_lock);
545 g_mutex_init(&ptr->idx_lock);
547 return MM_ERROR_NONE;
551 return MM_ERROR_OUT_OF_STORAGE;
554 int _mm_evas_renderer_destroy(mm_evas_info **evas_info)
556 mm_evas_info *ptr = (mm_evas_info *)*evas_info;
558 int ret = MM_ERROR_NONE;
560 LOGD("finalize evas_info %p", ptr);
562 ret = _mm_evas_renderer_reset(ptr);
563 g_mutex_clear(&ptr->mp_lock);
564 g_mutex_clear(&ptr->idx_lock);
572 int _mm_evas_renderer_set_info(mm_evas_info *evas_info, Evas_Object *eo)
574 MM_CHECK_NULL(evas_info);
576 g_mutex_lock(&evas_info->idx_lock);
578 LOGD("set evas_info");
580 for (i = 0; i < MAX_PACKET_NUM; i++) {
581 evas_info->pkt_info[i].packet = NULL;
582 evas_info->pkt_info[i].tbm_surf = NULL;
583 evas_info->pkt_info[i].prev = -1;
586 evas_info->cur_idx = -1;
588 evas_info->epipe = ecore_pipe_add((Ecore_Pipe_Cb) _evas_pipe_cb, evas_info);
589 if (!evas_info->epipe) {
590 LOGE("pipe is not created");
591 g_mutex_unlock(&evas_info->idx_lock);
592 return MM_ERROR_UNKNOWN;
594 LOGD("created pipe %p", evas_info->epipe);
595 _mm_evas_renderer_set_callback(evas_info);
597 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);
598 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);
600 g_mutex_unlock(&evas_info->idx_lock);
602 return MM_ERROR_NONE;
605 int _mm_evas_renderer_reset(mm_evas_info *evas_info)
607 MM_CHECK_NULL(evas_info);
608 g_mutex_lock(&evas_info->idx_lock);
611 int ret = MM_ERROR_NONE;
612 int ret_mp = MEDIA_PACKET_ERROR_NONE;
615 _mm_evas_renderer_unset_callback(evas_info);
616 evas_object_image_data_set(evas_info->eo, NULL);
617 evas_info->eo = NULL;
619 if (evas_info->epipe) {
620 LOGD("pipe %p will be deleted", evas_info->epipe);
621 ecore_pipe_del(evas_info->epipe);
622 evas_info->epipe = NULL;
625 evas_info->eo_size.x = evas_info->eo_size.y = evas_info->eo_size.w = evas_info->eo_size.h = 0;
626 evas_info->w = evas_info->h = 0;
628 if (evas_info->flush_buffer)
629 _mm_evas_renderer_release_flush_buffer(evas_info);
631 g_mutex_lock(&evas_info->mp_lock);
632 for (i = 0; i < MAX_PACKET_NUM; i++) {
633 if (evas_info->pkt_info[i].packet) {
634 /* destroy all packets */
635 LOGD("destroy packet [%p]", evas_info->pkt_info[i].packet);
636 ret_mp = media_packet_destroy(evas_info->pkt_info[i].packet);
637 if (ret_mp != MEDIA_PACKET_ERROR_NONE) {
638 LOGW("media_packet_destroy failed %p", evas_info->pkt_info[i].packet);
639 ret = MM_ERROR_UNKNOWN;
642 evas_info->sent_buffer_cnt--;
643 evas_info->pkt_info[i].packet = NULL;
644 evas_info->pkt_info[i].tbm_surf = NULL;
645 evas_info->pkt_info[i].prev = -1;
648 g_mutex_unlock(&evas_info->mp_lock);
649 if (evas_info->sent_buffer_cnt != 0)
650 LOGE("it should be 0 --> [%d]", evas_info->sent_buffer_cnt);
651 evas_info->sent_buffer_cnt = 0;
652 evas_info->cur_idx = -1;
654 g_mutex_unlock(&evas_info->idx_lock);
659 void _mm_evas_renderer_update_geometry(mm_evas_info *evas_info, rect_info *result)
661 if (!evas_info || !evas_info->eo) {
662 LOGW("there is no evas_info or evas object");
666 LOGW("there is no rect info");
673 switch (evas_info->display_geometry_method) {
674 case DISP_GEO_METHOD_LETTER_BOX:
675 /* set black padding for letter box mode */
676 LOGD("letter box mode");
677 evas_info->use_ratio = TRUE;
678 result->w = evas_info->eo_size.w;
679 result->h = evas_info->eo_size.h;
681 case DISP_GEO_METHOD_ORIGIN_SIZE:
682 LOGD("origin size mode");
683 evas_info->use_ratio = FALSE;
684 /* set coordinate for each case */
685 result->x = (evas_info->eo_size.w - evas_info->w) / 2;
686 result->y = (evas_info->eo_size.h - evas_info->h) / 2;
687 result->w = evas_info->w;
688 result->h = evas_info->h;
690 case DISP_GEO_METHOD_FULL_SCREEN:
691 LOGD("full screen mode");
692 evas_info->use_ratio = FALSE;
693 result->w = evas_info->eo_size.w;
694 result->h = evas_info->eo_size.h;
696 case DISP_GEO_METHOD_CROPPED_FULL_SCREEN:
697 LOGD("cropped full screen mode");
698 evas_info->use_ratio = FALSE;
699 /* compare evas object's ratio with video's */
700 if ((evas_info->eo_size.w / evas_info->eo_size.h) > (evas_info->w / evas_info->h)) {
701 result->w = evas_info->eo_size.w;
702 result->h = evas_info->eo_size.w * evas_info->h / evas_info->w;
703 result->y = -(result->h - evas_info->eo_size.h) / 2;
705 result->w = evas_info->eo_size.h * evas_info->w / evas_info->h;
706 result->h = evas_info->eo_size.h;
707 result->x = -(result->w - evas_info->eo_size.w) / 2;
710 case DISP_GEO_METHOD_ORIGIN_SIZE_OR_LETTER_BOX:
711 LOGD("origin size or letter box mode");
712 /* if video size is smaller than evas object's, it will be set to origin size mode */
713 if ((evas_info->eo_size.w > evas_info->w) && (evas_info->eo_size.h > evas_info->h)) {
714 LOGD("origin size mode");
715 evas_info->use_ratio = FALSE;
716 /* set coordinate for each case */
717 result->x = (evas_info->eo_size.w - evas_info->w) / 2;
718 result->y = (evas_info->eo_size.h - evas_info->h) / 2;
719 result->w = evas_info->w;
720 result->h = evas_info->h;
722 LOGD("letter box mode");
723 evas_info->use_ratio = TRUE;
724 result->w = evas_info->eo_size.w;
725 result->h = evas_info->eo_size.h;
729 LOGW("unsupported mode.");
732 LOGD("geometry result [%d, %d, %d, %d]", result->x, result->y, result->w, result->h);
735 int _mm_evas_renderer_apply_geometry(mm_evas_info *evas_info)
737 if (!evas_info || !evas_info->eo) {
738 LOGW("there is no evas_info or evas object");
739 return MM_ERROR_NONE;
742 Evas_Native_Surface *surf = evas_object_image_native_surface_get(evas_info->eo);
743 rect_info result = { 0 };
746 LOGD("native surface exists");
747 // surf->data.tbm.rot = evas_info->rotate_angle;
748 // surf->data.tbm.flip = evas_info->flip;
749 evas_object_image_native_surface_set(evas_info->eo, surf);
751 _mm_evas_renderer_update_geometry(evas_info, &result);
753 if (evas_info->use_ratio) {
754 // surf->data.tbm.ratio = (float) evas_info->w / evas_info->h;
755 LOGD("set ratio for letter mode");
758 if (result.x || result.y)
759 LOGD("coordinate x, y (%d, %d) for locating video to center", result.x, result.y);
761 evas_object_image_fill_set(evas_info->eo, result.x, result.y, result.w, result.h);
762 return MM_ERROR_NONE;
764 LOGW("there is no surf");
765 /* FIXME: before pipe_cb is invoked, apply_geometry can be called. */
766 return MM_ERROR_NONE;
769 int _mm_evas_renderer_retrieve_all_packets(mm_evas_info *evas_info, bool keep_screen)
771 MM_CHECK_NULL(evas_info);
773 int ret = MM_ERROR_NONE;
774 pid_t pid = getpid();
775 pid_t tid = syscall(SYS_gettid);
777 /* write and this API can be called at the same time.
778 so lock is needed for counting sent_buffer_cnt correctly */
779 g_mutex_lock(&evas_info->idx_lock);
781 /* make flush buffer */
783 ret = _mm_evas_renderer_make_flush_buffer(evas_info);
784 evas_info->keep_screen = keep_screen;
786 LOGD("pid [%d], tid [%d]", pid, tid);
788 /* in this case, we deem it is main thread */
789 if (_flush_packets(evas_info) != MM_ERROR_NONE) {
790 LOGE("flushing packets are failed");
791 ret = MM_ERROR_UNKNOWN;
794 /* it will be executed to write flush buffer and destroy media packets in pre_cb */
795 evas_info->retrieve_packet = TRUE;
797 g_mutex_unlock(&evas_info->idx_lock);
802 /* make buffer for copying */
803 int _mm_evas_renderer_make_flush_buffer (mm_evas_info *evas_info)
805 if (evas_info->cur_idx == -1) {
806 LOGW("there is no remained buffer");
807 return MM_ERROR_INVALID_ARGUMENT;
809 media_packet_h packet = evas_info->pkt_info[evas_info->cur_idx].packet;
810 MM_CHECK_NULL(packet);
812 flush_info *flush_buffer = NULL;
813 tbm_bo src_bo = NULL;
814 tbm_surface_h src_tbm_surf = NULL;
819 tbm_bo_handle vaddr_src = {0};
820 tbm_bo_handle vaddr_dst = {0};
821 int ret = MM_ERROR_NONE;
823 if (evas_info->flush_buffer)
824 _mm_evas_renderer_release_flush_buffer(evas_info);
827 flush_buffer = (flush_info *)malloc(sizeof(flush_info));
828 if (flush_buffer == NULL) {
829 LOGE("malloc is failed");
832 memset(flush_buffer, 0x0, sizeof(flush_info));
834 ret = media_packet_get_tbm_surface(packet, &src_tbm_surf);
835 if (ret != MEDIA_PACKET_ERROR_NONE || !src_tbm_surf) {
836 LOGW("get_tbm_surface is failed");
840 /* get src buffer info */
841 tbm_fmt = tbm_surface_get_format(src_tbm_surf);
842 src_bo = tbm_surface_internal_get_bo(src_tbm_surf, 0);
843 src_size = tbm_bo_size(src_bo);
844 if (!src_bo || !src_size) {
845 LOGE("bo(%p), size(%d)", src_bo, src_size);
849 /* create tbm surface */
850 flush_buffer->tbm_surf = tbm_surface_create(evas_info->w, evas_info->h, tbm_fmt);
851 if (!flush_buffer->tbm_surf)
853 LOGE("tbm_surf is NULL!!");
857 /* get bo and size */
858 bo = tbm_surface_internal_get_bo(flush_buffer->tbm_surf, 0);
859 size = tbm_bo_size(bo);
862 LOGE("bo(%p), size(%d)", bo, size);
865 flush_buffer->bo = bo;
867 vaddr_src = tbm_bo_map(src_bo, TBM_DEVICE_CPU, TBM_OPTION_READ|TBM_OPTION_WRITE);
868 vaddr_dst = tbm_bo_map(bo, TBM_DEVICE_CPU, TBM_OPTION_READ|TBM_OPTION_WRITE);
869 if (!vaddr_src.ptr || !vaddr_dst.ptr) {
870 LOGW("get vaddr failed src %p, dst %p", vaddr_src.ptr, vaddr_dst.ptr);
872 tbm_bo_unmap(src_bo);
879 memset (vaddr_dst.ptr, 0x0, size);
880 LOGW ("tbm_bo_map(vaddr) is finished, bo(%p), vaddr(%p)", bo, vaddr_dst.ptr);
884 memcpy(vaddr_dst.ptr, vaddr_src.ptr, src_size);
886 tbm_bo_unmap(src_bo);
888 LOGW("copy is done. tbm surface : %p src_size : %d", flush_buffer->tbm_surf, src_size);
890 evas_info->flush_buffer = flush_buffer;
892 return MM_ERROR_NONE;
896 if(flush_buffer->tbm_surf)
898 tbm_surface_destroy(flush_buffer->tbm_surf);
899 flush_buffer->tbm_surf = NULL;
905 return MM_ERROR_UNKNOWN;
908 /* release flush buffer */
909 void _mm_evas_renderer_release_flush_buffer (mm_evas_info *evas_info)
911 LOGW("release FLUSH BUFFER start");
912 if (evas_info->flush_buffer->bo) {
913 evas_info->flush_buffer->bo = NULL;
915 if (evas_info->flush_buffer->tbm_surf) {
916 tbm_surface_destroy(evas_info->flush_buffer->tbm_surf);
917 evas_info->flush_buffer->tbm_surf = NULL;
920 LOGW("release FLUSH BUFFER done");
922 free(evas_info->flush_buffer);
923 evas_info->flush_buffer = NULL;
928 void mm_evas_renderer_write(media_packet_h packet, void *data)
931 LOGE("packet %p is NULL", packet);
934 mm_evas_info *handle = (mm_evas_info *)data;
935 int ret = MEDIA_PACKET_ERROR_NONE;
937 tbm_surface_h tbm_surf;
940 LOGD("packet [%p]", packet);
942 if (!data || !handle) {
943 LOGE("handle %p or evas_info %p is NULL", data, handle);
946 g_mutex_lock(&handle->idx_lock);
948 ret = media_packet_has_tbm_surface_buffer(packet, &has);
949 if (ret != MEDIA_PACKET_ERROR_NONE) {
950 LOGW("has_tbm_surface is failed");
953 /* FIXME: when setCaps occurs, _get_video_size should be called */
954 /* currently we are always checking it */
955 if (has && _get_video_size(packet, handle)) {
956 /* Attention! if this error occurs, we need to consider managing buffer */
957 if (handle->sent_buffer_cnt > 4) {
958 LOGE("too many buffers are not released %d", handle->sent_buffer_cnt);
961 /* FIXME: fix this logic */
962 /* destroy all media packets and reset pipe at present */
963 /* Attention! it might free buffer that is being rendered */
964 g_mutex_lock(&handle->mp_lock);
966 g_mutex_unlock(&handle->mp_lock);
969 ret = media_packet_get_tbm_surface(packet, &tbm_surf);
970 if (ret != MEDIA_PACKET_ERROR_NONE || !tbm_surf) {
971 LOGW("get_tbm_surface is failed");
975 /* find new index for current packet */
976 index = _find_empty_index(handle);
981 /* save previous index */
982 handle->pkt_info[index].prev = handle->cur_idx;
983 handle->pkt_info[index].packet = packet;
984 handle->pkt_info[index].tbm_surf = tbm_surf;
985 handle->cur_idx = index;
986 handle->sent_buffer_cnt++;
987 LOGD("sent packet %d", handle->sent_buffer_cnt);
989 ret = ecore_pipe_write(handle->epipe, handle, UPDATE_TBM_SURF);
991 handle->pkt_info[index].packet = NULL;
992 handle->pkt_info[index].tbm_surf = NULL;
993 handle->pkt_info[index].prev = -1;
994 handle->cur_idx = handle->pkt_info[index].prev;
995 handle->sent_buffer_cnt--;
996 LOGW("Failed to ecore_pipe_write() for updating tbm surf\n");
1000 LOGW("no tbm_surf");
1003 g_mutex_unlock(&handle->idx_lock);
1007 g_mutex_unlock(&handle->idx_lock);
1009 /* destroy media_packet immediately */
1011 g_mutex_lock(&handle->mp_lock);
1012 LOGD("cant write. destroy packet [%p]", packet);
1013 if (media_packet_destroy(packet) != MEDIA_PACKET_ERROR_NONE)
1014 LOGE("media_packet_destroy failed %p", packet);
1016 g_mutex_unlock(&handle->mp_lock);
1021 int mm_evas_renderer_update_param(MMHandleType handle)
1023 int ret = MM_ERROR_NONE;
1024 mm_evas_info *evas_info = (mm_evas_info *)handle;
1027 LOGW("skip it. it is not evas surface type.");
1031 /* when handle is realized, we need to update all properties */
1033 LOGD("set video param : evas-object %x, method %d", evas_info->eo, evas_info->display_geometry_method);
1034 LOGD("set video param : visible %d", evas_info->visible);
1035 LOGD("set video param : rotate %d", evas_info->rotate_angle);
1037 ret = _mm_evas_renderer_apply_geometry(evas_info);
1038 if (ret != MM_ERROR_NONE)
1041 if (evas_info->epipe) {
1042 ret = ecore_pipe_write(evas_info->epipe, &evas_info->visible, UPDATE_VISIBILITY);
1044 LOGW("fail to ecore_pipe_write() for updating visibility\n");
1045 ret = MM_ERROR_UNKNOWN;
1047 ret = MM_ERROR_NONE;
1055 int mm_evas_renderer_create(MMHandleType *handle, Evas_Object *eo)
1057 MM_CHECK_NULL(handle);
1059 int ret = MM_ERROR_NONE;
1060 mm_evas_info *evas_info = NULL;
1062 ret = _mm_evas_renderer_create(&evas_info);
1063 if (ret != MM_ERROR_NONE) {
1064 LOGE("fail to create evas_info");
1067 ret = _mm_evas_renderer_set_info(evas_info, eo);
1068 if (ret != MM_ERROR_NONE) {
1069 LOGE("fail to init evas_info");
1070 if (_mm_evas_renderer_destroy(&evas_info) != MM_ERROR_NONE)
1071 LOGE("fail to destroy evas_info");
1075 *handle = (MMHandleType)evas_info;
1077 return MM_ERROR_NONE;
1080 int mm_evas_renderer_destroy(MMHandleType *handle)
1082 MM_CHECK_NULL(handle);
1084 int ret = MM_ERROR_NONE;
1085 mm_evas_info *evas_info = (mm_evas_info *)*handle;
1088 LOGD("skip it. it is not evas surface type.");
1089 return MM_ERROR_RESOURCE_NOT_INITIALIZED;
1092 ret = _mm_evas_renderer_destroy(&evas_info);
1093 if (ret != MM_ERROR_NONE) {
1094 LOGE("fail to destroy evas_info");
1099 return MM_ERROR_NONE;
1102 int mm_evas_renderer_set_visible(MMHandleType handle, bool visible)
1104 int ret = MM_ERROR_NONE;
1105 mm_evas_info *evas_info = (mm_evas_info *)handle;
1108 LOGW("skip it. it is not evas surface type or handle is not prepared");
1109 return MM_ERROR_RESOURCE_NOT_INITIALIZED;
1113 evas_info->visible = VISIBLE_TRUE;
1115 evas_info->visible = VISIBLE_FALSE;
1117 if (evas_info->epipe) {
1118 ret = ecore_pipe_write(evas_info->epipe, &visible, UPDATE_VISIBILITY);
1120 LOGW("fail to ecore_pipe_write() for updating visibility\n");
1121 ret = MM_ERROR_UNKNOWN;
1123 ret = MM_ERROR_NONE;
1126 LOGW("there is no epipe. we cant update it");
1132 int mm_evas_renderer_get_visible(MMHandleType handle, bool *visible)
1134 mm_evas_info *evas_info = (mm_evas_info *)handle;
1137 LOGW("skip it. it is not evas surface type or handle is not prepared");
1138 return MM_ERROR_RESOURCE_NOT_INITIALIZED;
1141 if (evas_info->visible == VISIBLE_FALSE)
1146 return MM_ERROR_NONE;
1149 int mm_evas_renderer_set_rotation(MMHandleType handle, int rotate)
1151 int ret = MM_ERROR_NONE;
1152 mm_evas_info *evas_info = (mm_evas_info *)handle;
1155 LOGW("skip it. it is not evas surface type or handle is not prepared");
1156 return MM_ERROR_RESOURCE_NOT_INITIALIZED;
1159 evas_info->rotate_angle = rotate;
1160 ret = _mm_evas_renderer_apply_geometry(evas_info);
1165 int mm_evas_renderer_get_rotation(MMHandleType handle, int *rotate)
1167 mm_evas_info *evas_info = (mm_evas_info *)handle;
1170 LOGW("skip it. it is not evas surface type or handle is not prepared");
1171 return MM_ERROR_RESOURCE_NOT_INITIALIZED;
1173 *rotate = evas_info->rotate_angle;
1175 return MM_ERROR_NONE;
1178 int mm_evas_renderer_set_geometry(MMHandleType handle, int mode)
1180 int ret = MM_ERROR_NONE;
1181 mm_evas_info *evas_info = (mm_evas_info *)handle;
1184 LOGW("skip it. it is not evas surface type or handle is not prepared");
1185 return MM_ERROR_RESOURCE_NOT_INITIALIZED;
1188 evas_info->display_geometry_method = mode;
1189 ret = _mm_evas_renderer_apply_geometry(evas_info);
1194 int mm_evas_renderer_get_geometry(MMHandleType handle, int *mode)
1196 mm_evas_info *evas_info = (mm_evas_info *)handle;
1199 LOGW("skip it. it is not evas surface type or handle is not prepared");
1200 return MM_ERROR_RESOURCE_NOT_INITIALIZED;
1202 *mode = evas_info->display_geometry_method;
1204 return MM_ERROR_NONE;
1207 int mm_evas_renderer_retrieve_all_packets (MMHandleType handle, bool keep_screen)
1209 int ret = MM_ERROR_NONE;
1210 mm_evas_info *evas_info = (mm_evas_info*) handle;
1213 LOGW("skip it. it is not evas surface type or player is not prepared");
1214 return MM_ERROR_RESOURCE_NOT_INITIALIZED;
1216 ret = _mm_evas_renderer_retrieve_all_packets(evas_info, keep_screen);