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,
90 DISP_GEO_METHOD_CUSTOM_ROI,
110 #ifdef _INTERNAL_DEBUG_
111 void __print_idx(mm_evas_info *evas_info);
114 void _free_previous_packets(mm_evas_info *evas_info);
115 int _flush_packets(mm_evas_info *evas_info);
116 int _mm_evas_renderer_create(mm_evas_info **evas_info);
117 int _mm_evas_renderer_destroy(mm_evas_info **evas_info);
118 int _mm_evas_renderer_set_info(mm_evas_info *evas_info, Evas_Object *eo);
119 int _mm_evas_renderer_reset(mm_evas_info *evas_info);
120 void _mm_evas_renderer_update_geometry(mm_evas_info *evas_info, rect_info *result);
121 int _mm_evas_renderer_apply_geometry(mm_evas_info *evas_info);
122 int _mm_evas_renderer_retrieve_all_packets(mm_evas_info *evas_info, bool keep_screen);
123 int _mm_evas_renderer_make_flush_buffer(mm_evas_info *evas_info);
124 void _mm_evas_renderer_release_flush_buffer(mm_evas_info *evas_info);
125 static void _mm_evas_renderer_set_callback(mm_evas_info *evas_info);
126 static void _mm_evas_renderer_unset_callback(mm_evas_info *evas_info);
128 static void _evas_resize_cb(void *data, Evas *e, Evas_Object *obj, void *event_info)
133 mm_evas_info *evas_info = data;
136 if (!evas_info || !evas_info->eo) {
140 evas_object_geometry_get(evas_info->eo, &x, &y, &w, &h);
142 LOGW("evas object size (w:%d,h:%d) was not set", w, h);
144 evas_info->eo_size.x = x;
145 evas_info->eo_size.y = y;
146 evas_info->eo_size.w = w;
147 evas_info->eo_size.h = h;
148 LOGW("resize (x:%d, y:%d, w:%d, h:%d)", x, y, w, h);
149 ret = _mm_evas_renderer_apply_geometry(evas_info);
150 if (ret != MM_ERROR_NONE)
151 LOGW("fail to apply geometry info");
156 static void _evas_render_pre_cb(void *data, Evas *e, void *event_info)
158 mm_evas_info *evas_info = data;
160 if (!evas_info || !evas_info->eo) {
161 LOGW("there is no esink info.... esink : %p, or eo is NULL returning", evas_info);
165 /* flush will be executed in this callback normally,
166 because native_surface_set must be called in main thread */
167 if (evas_info->retrieve_packet) {
168 g_mutex_lock(&evas_info->idx_lock);
169 if (_flush_packets(evas_info) != MM_ERROR_NONE)
170 LOGE("flushing packets are failed");
171 g_mutex_unlock(&evas_info->idx_lock);
175 static void _evas_del_cb(void *data, Evas *e, Evas_Object *obj, void *event_info)
177 mm_evas_info *evas_info = data;
179 if (!evas_info || !evas_info->eo) {
183 _mm_evas_renderer_unset_callback(evas_info);
184 evas_object_image_data_set(evas_info->eo, NULL);
185 evas_info->eo = NULL;
190 void _evas_pipe_cb(void *data, void *buffer, update_info info)
192 mm_evas_info *evas_info = data;
197 LOGW("evas_info is NULL", evas_info);
201 g_mutex_lock(&evas_info->mp_lock);
203 if (!evas_info->eo) {
204 LOGW("evas_info %p", evas_info);
205 g_mutex_unlock(&evas_info->mp_lock);
209 LOGD("evas_info : %p, evas_info->eo : %p", evas_info, evas_info->eo);
210 if (info == UPDATE_VISIBILITY) {
211 if (evas_info->visible == VISIBLE_FALSE) {
212 evas_object_hide(evas_info->eo);
213 LOGI("object hide..");
215 evas_object_show(evas_info->eo);
216 LOGI("object show.. %d", evas_info->visible);
219 g_mutex_unlock(&evas_info->mp_lock);
223 if (info != UPDATE_TBM_SURF) {
224 LOGW("invalid info type : %d", info);
225 g_mutex_unlock(&evas_info->mp_lock);
229 if (evas_info->cur_idx==-1 || !evas_info->pkt_info[evas_info->cur_idx].tbm_surf) {
230 LOGW("cur_idx %d, tbm_surf may be NULL", evas_info->cur_idx);
231 g_mutex_unlock(&evas_info->mp_lock);
234 /* perhaps, it is needed to skip setting when state is pause */
236 g_mutex_lock(&evas_info->idx_lock);
238 gint cur_idx = evas_info->cur_idx;
239 gint prev_idx = evas_info->pkt_info[cur_idx].prev;
241 LOGD("received (idx %d, packet %p)", cur_idx, evas_info->pkt_info[cur_idx].packet);
243 tbm_format tbm_fmt = tbm_surface_get_format(evas_info->pkt_info[cur_idx].tbm_surf);
245 case TBM_FORMAT_NV12:
246 LOGD("tbm_surface format : TBM_FORMAT_NV12");
248 case TBM_FORMAT_YUV420:
249 LOGD("tbm_surface format : TBM_FORMAT_YUV420");
252 LOGW("tbm_surface format : unknown %d", tbm_fmt);
256 Evas_Native_Surface surf;
257 surf.type = EVAS_NATIVE_SURFACE_TBM;
258 surf.version = EVAS_NATIVE_SURFACE_VERSION;
259 surf.data.tbm.buffer = evas_info->pkt_info[cur_idx].tbm_surf;
260 surf.data.tbm.rot = evas_info->rotate_angle;
261 surf.data.tbm.flip = evas_info->flip;
263 rect_info result = { 0 };
265 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);
266 if (!evas_info->eo_size.w || !evas_info->eo_size.h) {
267 LOGE("there is no information for evas object size");
270 _mm_evas_renderer_update_geometry(evas_info, &result);
271 if (!result.w || !result.h) {
272 LOGE("no information about geometry (%d, %d)", result.w, result.h);
276 if (evas_info->use_ratio) {
277 surf.data.tbm.ratio = (float) evas_info->w / evas_info->h;
278 LOGD("set ratio for letter mode");
280 evas_object_size_hint_align_set(evas_info->eo, EVAS_HINT_FILL, EVAS_HINT_FILL);
281 evas_object_size_hint_weight_set(evas_info->eo, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
282 if (evas_info->w > 0 && evas_info->h > 0)
283 evas_object_image_size_set(evas_info->eo, evas_info->w, evas_info->h);
285 evas_object_image_native_surface_set(evas_info->eo, &surf);
286 LOGD("native surface set finish");
288 if (result.x || result.y)
289 LOGD("coordinate x, y (%d, %d) for locating video to center", result.x, result.y);
291 if (evas_info->display_geometry_method != DISP_GEO_METHOD_CUSTOM_ROI)
292 evas_object_image_fill_set(evas_info->eo, result.x, result.y, result.w, result.h);
294 evas_object_image_pixels_dirty_set(evas_info->eo, EINA_TRUE);
295 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);
297 /* when _evas_pipe_cb is called sequentially, previous packet and current packet will be the same */
298 if ((prev_idx != -1) && evas_info->pkt_info[prev_idx].packet && (prev_idx != cur_idx))
299 _free_previous_packets(evas_info);
302 g_mutex_unlock(&evas_info->idx_lock);
303 g_mutex_unlock(&evas_info->mp_lock);
308 if ((prev_idx != -1) && evas_info->pkt_info[prev_idx].packet) {
310 _free_previous_packets(evas_info);
312 g_mutex_unlock(&evas_info->idx_lock);
313 g_mutex_unlock(&evas_info->mp_lock);
316 #ifdef _INTERNAL_DEBUG_
317 void __print_idx(mm_evas_info *evas_info)
319 gint prev_idx = evas_info->pkt_info[evas_info->cur_idx].prev;
320 LOGE("***** start cur_idx : %d -> prev_idx : %d", evas_info->cur_idx, prev_idx);
321 while(prev_idx != -1)
323 LOGE("***** cur_idx : %d -> prev_idx : %d", prev_idx, evas_info->pkt_info[prev_idx].prev);
324 prev_idx = evas_info->pkt_info[prev_idx].prev;
331 void _free_previous_packets(mm_evas_info *evas_info)
333 gint index = evas_info->cur_idx;
334 gint prev_idx = evas_info->pkt_info[index].prev;
336 while(prev_idx != -1)
338 LOGD("destroy previous packet [%p] idx %d", evas_info->pkt_info[prev_idx].packet, prev_idx);
339 if (media_packet_destroy(evas_info->pkt_info[prev_idx].packet) != MEDIA_PACKET_ERROR_NONE)
340 LOGE("media_packet_destroy failed %p", evas_info->pkt_info[prev_idx].packet);
341 evas_info->pkt_info[prev_idx].packet = NULL;
342 evas_info->pkt_info[prev_idx].tbm_surf = NULL;
343 evas_info->pkt_info[index].prev = -1;
344 evas_info->sent_buffer_cnt--;
346 /* move index to previous index */
348 prev_idx = evas_info->pkt_info[prev_idx].prev;
349 LOGD("sent packet %d", evas_info->sent_buffer_cnt);
354 static int _get_video_size(media_packet_h packet, mm_evas_info *evas_info)
357 if (media_packet_get_format(packet, &fmt) == MEDIA_PACKET_ERROR_NONE) {
359 if (media_format_get_video_info(fmt, NULL, &w, &h, NULL, NULL) == MEDIA_PACKET_ERROR_NONE) {
360 LOGD("video width = %d, height =%d", w, h);
365 LOGW("media_format_get_video_info is failed");
366 if (media_format_unref(fmt) != MEDIA_PACKET_ERROR_NONE) /* because of media_packet_get_format */
367 LOGW("media_format_unref is failed");
369 LOGW("media_packet_get_format is failed");
374 int _find_empty_index(mm_evas_info *evas_info)
377 for (i = 0; i < MAX_PACKET_NUM; i++) {
378 if (!evas_info->pkt_info[i].packet) {
379 LOGD("selected idx %d", i);
383 LOGE("there is no empty idx");
388 int _flush_packets(mm_evas_info *evas_info)
390 int ret = MM_ERROR_NONE;
391 int ret_mp = MEDIA_PACKET_ERROR_NONE;
395 LOGW("there is no esink info");
396 return MM_ERROR_INVALID_ARGUMENT;
398 /* update the screen only if visible is ture */
399 if (evas_info->keep_screen && (evas_info->visible != VISIBLE_FALSE)) {
400 Evas_Native_Surface surf;
401 rect_info result = { 0 };
402 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);
403 if (!evas_info->eo_size.w || !evas_info->eo_size.h) {
404 LOGE("there is no information for evas object size");
405 return MM_ERROR_INVALID_ARGUMENT;
407 _mm_evas_renderer_update_geometry(evas_info, &result);
408 if (!result.w || !result.h) {
409 LOGE("no information about geometry (%d, %d)", result.w, result.h);
410 return MM_ERROR_INVALID_ARGUMENT;
413 if (evas_info->use_ratio) {
414 surf.data.tbm.ratio = (float) evas_info->w / evas_info->h;
415 LOGD("set ratio for letter mode");
417 evas_object_size_hint_align_set(evas_info->eo, EVAS_HINT_FILL, EVAS_HINT_FILL);
418 evas_object_size_hint_weight_set(evas_info->eo, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
419 if (evas_info->w > 0 && evas_info->h > 0)
420 evas_object_image_size_set(evas_info->eo, evas_info->w, evas_info->h);
422 if (result.x || result.y)
423 LOGD("coordinate x, y (%d, %d) for locating video to center", result.x, result.y);
425 if (evas_info->display_geometry_method != DISP_GEO_METHOD_CUSTOM_ROI)
426 evas_object_image_fill_set(evas_info->eo, result.x, result.y, result.w, result.h);
428 /* set flush buffer */
429 surf.type = EVAS_NATIVE_SURFACE_TBM;
430 surf.version = EVAS_NATIVE_SURFACE_VERSION;
431 surf.data.tbm.buffer = evas_info->flush_buffer->tbm_surf;
432 surf.data.tbm.rot = evas_info->rotate_angle;
433 surf.data.tbm.flip = evas_info->flip;
434 evas_object_image_native_surface_set(evas_info->eo, &surf);
436 LOGD("flush_buffer surf(%p), rotate(%d), flip(%d)", evas_info->flush_buffer->tbm_surf, evas_info->rotate_angle, evas_info->flip);
438 /* unset evas native surface for displaying black screen */
439 evas_object_image_native_surface_set (evas_info->eo, NULL);
440 evas_object_image_data_set (evas_info->eo, NULL);
442 LOGD("sent packet %d", evas_info->sent_buffer_cnt);
444 /* destroy all packets */
445 g_mutex_lock(&evas_info->mp_lock);
446 for (i = 0; i < MAX_PACKET_NUM; i++) {
447 if (evas_info->pkt_info[i].packet) {
448 LOGD("destroy packet [%p]", evas_info->pkt_info[i].packet);
449 ret_mp = media_packet_destroy(evas_info->pkt_info[i].packet);
450 if (ret_mp != MEDIA_PACKET_ERROR_NONE) {
451 LOGW("media_packet_destroy failed %p", evas_info->pkt_info[i].packet);
452 ret = MM_ERROR_UNKNOWN;
455 evas_info->sent_buffer_cnt--;
456 evas_info->pkt_info[i].packet = NULL;
457 evas_info->pkt_info[i].tbm_surf = NULL;
458 evas_info->pkt_info[i].prev = -1;
462 if (evas_info->sent_buffer_cnt != 0)
463 LOGE("it should be 0 --> [%d]", evas_info->sent_buffer_cnt);
464 evas_info->sent_buffer_cnt = 0;
465 evas_info->cur_idx = -1;
466 g_mutex_unlock(&evas_info->mp_lock);
468 evas_object_image_pixels_dirty_set (evas_info->eo, EINA_TRUE);
469 evas_info->retrieve_packet = FALSE;
475 int _reset_pipe(mm_evas_info *evas_info)
478 int ret = MM_ERROR_NONE;
479 int ret_mp = MEDIA_PACKET_ERROR_NONE;
481 /* delete old pipe */
482 if (evas_info->epipe) {
483 LOGD("pipe %p will be deleted", evas_info->epipe);
484 ecore_pipe_del(evas_info->epipe);
485 evas_info->epipe = NULL;
488 for (i = 0; i < MAX_PACKET_NUM; i++) {
489 if (evas_info->pkt_info[i].packet) {
490 /* destroy all packets */
491 LOGD("destroy packet [%p]", evas_info->pkt_info[i].packet);
492 ret_mp = media_packet_destroy(evas_info->pkt_info[i].packet);
493 if (ret_mp != MEDIA_PACKET_ERROR_NONE) {
494 LOGW("media_packet_destroy failed %p", evas_info->pkt_info[i].packet);
495 ret = MM_ERROR_UNKNOWN;
498 evas_info->sent_buffer_cnt--;
499 evas_info->pkt_info[i].packet = NULL;
500 evas_info->pkt_info[i].tbm_surf = NULL;
501 evas_info->pkt_info[i].prev = -1;
505 if (evas_info->sent_buffer_cnt != 0)
506 LOGE("it should be 0 --> [%d]", evas_info->sent_buffer_cnt);
507 evas_info->sent_buffer_cnt = 0;
508 evas_info->cur_idx = -1;
511 if (!evas_info->epipe) {
512 evas_info->epipe = ecore_pipe_add((Ecore_Pipe_Cb) _evas_pipe_cb, evas_info);
513 if (!evas_info->epipe) {
514 LOGE("pipe is not created");
515 ret = MM_ERROR_UNKNOWN;
517 LOGD("created pipe %p", evas_info->epipe);
524 static void _mm_evas_renderer_set_callback(mm_evas_info *evas_info)
527 SET_EVAS_OBJECT_EVENT_CALLBACK(evas_info->eo, evas_info);
528 SET_EVAS_EVENT_CALLBACK(evas_object_evas_get(evas_info->eo), evas_info);
532 static void _mm_evas_renderer_unset_callback(mm_evas_info *evas_info)
535 UNSET_EVAS_OBJECT_EVENT_CALLBACK(evas_info->eo);
536 UNSET_EVAS_EVENT_CALLBACK(evas_object_evas_get(evas_info->eo));
540 int _mm_evas_renderer_create(mm_evas_info **evas_info)
542 mm_evas_info *ptr = NULL;
543 ptr = g_malloc0(sizeof(mm_evas_info));
546 LOGE("Cannot allocate memory for evas_info\n");
550 LOGD("Success create evas_info(%p)", *evas_info);
552 g_mutex_init(&ptr->mp_lock);
553 g_mutex_init(&ptr->idx_lock);
555 return MM_ERROR_NONE;
559 return MM_ERROR_OUT_OF_STORAGE;
562 int _mm_evas_renderer_destroy(mm_evas_info **evas_info)
564 mm_evas_info *ptr = (mm_evas_info *)*evas_info;
566 int ret = MM_ERROR_NONE;
568 LOGD("finalize evas_info %p", ptr);
570 ret = _mm_evas_renderer_reset(ptr);
571 g_mutex_clear(&ptr->mp_lock);
572 g_mutex_clear(&ptr->idx_lock);
580 int _mm_evas_renderer_set_info(mm_evas_info *evas_info, Evas_Object *eo)
582 MM_CHECK_NULL(evas_info);
584 g_mutex_lock(&evas_info->idx_lock);
586 LOGD("set evas_info");
588 for (i = 0; i < MAX_PACKET_NUM; i++) {
589 evas_info->pkt_info[i].packet = NULL;
590 evas_info->pkt_info[i].tbm_surf = NULL;
591 evas_info->pkt_info[i].prev = -1;
593 evas_info->cur_idx = -1;
594 evas_info->dst_roi.x = evas_info->dst_roi.y = evas_info->dst_roi.w = evas_info->dst_roi.h = 0;
596 evas_info->epipe = ecore_pipe_add((Ecore_Pipe_Cb) _evas_pipe_cb, evas_info);
597 if (!evas_info->epipe) {
598 LOGE("pipe is not created");
599 g_mutex_unlock(&evas_info->idx_lock);
600 return MM_ERROR_UNKNOWN;
602 LOGD("created pipe %p", evas_info->epipe);
603 _mm_evas_renderer_set_callback(evas_info);
605 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);
606 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);
608 g_mutex_unlock(&evas_info->idx_lock);
610 return MM_ERROR_NONE;
613 int _mm_evas_renderer_reset(mm_evas_info *evas_info)
615 MM_CHECK_NULL(evas_info);
616 g_mutex_lock(&evas_info->idx_lock);
619 int ret = MM_ERROR_NONE;
620 int ret_mp = MEDIA_PACKET_ERROR_NONE;
623 _mm_evas_renderer_unset_callback(evas_info);
624 evas_object_image_data_set(evas_info->eo, NULL);
625 evas_info->eo = NULL;
627 if (evas_info->epipe) {
628 LOGD("pipe %p will be deleted", evas_info->epipe);
629 ecore_pipe_del(evas_info->epipe);
630 evas_info->epipe = NULL;
633 evas_info->eo_size.x = evas_info->eo_size.y = evas_info->eo_size.w = evas_info->eo_size.h = 0;
634 evas_info->dst_roi.x = evas_info->dst_roi.y = evas_info->dst_roi.w = evas_info->dst_roi.h = 0;
635 evas_info->w = evas_info->h = 0;
637 if (evas_info->flush_buffer)
638 _mm_evas_renderer_release_flush_buffer(evas_info);
640 g_mutex_lock(&evas_info->mp_lock);
641 for (i = 0; i < MAX_PACKET_NUM; i++) {
642 if (evas_info->pkt_info[i].packet) {
643 /* destroy all packets */
644 LOGD("destroy packet [%p]", evas_info->pkt_info[i].packet);
645 ret_mp = media_packet_destroy(evas_info->pkt_info[i].packet);
646 if (ret_mp != MEDIA_PACKET_ERROR_NONE) {
647 LOGW("media_packet_destroy failed %p", evas_info->pkt_info[i].packet);
648 ret = MM_ERROR_UNKNOWN;
651 evas_info->sent_buffer_cnt--;
652 evas_info->pkt_info[i].packet = NULL;
653 evas_info->pkt_info[i].tbm_surf = NULL;
654 evas_info->pkt_info[i].prev = -1;
657 g_mutex_unlock(&evas_info->mp_lock);
658 if (evas_info->sent_buffer_cnt != 0)
659 LOGE("it should be 0 --> [%d]", evas_info->sent_buffer_cnt);
660 evas_info->sent_buffer_cnt = 0;
661 evas_info->cur_idx = -1;
663 g_mutex_unlock(&evas_info->idx_lock);
668 void _mm_evas_renderer_update_geometry(mm_evas_info *evas_info, rect_info *result)
670 if (!evas_info || !evas_info->eo) {
671 LOGW("there is no evas_info or evas object");
675 LOGW("there is no rect info");
682 switch (evas_info->display_geometry_method) {
683 case DISP_GEO_METHOD_LETTER_BOX:
684 /* set black padding for letter box mode */
685 LOGD("letter box mode");
686 evas_info->use_ratio = TRUE;
687 result->w = evas_info->eo_size.w;
688 result->h = evas_info->eo_size.h;
690 case DISP_GEO_METHOD_ORIGIN_SIZE:
691 LOGD("origin size mode");
692 evas_info->use_ratio = FALSE;
693 /* set coordinate for each case */
694 result->x = (evas_info->eo_size.w - evas_info->w) / 2;
695 result->y = (evas_info->eo_size.h - evas_info->h) / 2;
696 result->w = evas_info->w;
697 result->h = evas_info->h;
699 case DISP_GEO_METHOD_FULL_SCREEN:
700 LOGD("full screen mode");
701 evas_info->use_ratio = FALSE;
702 result->w = evas_info->eo_size.w;
703 result->h = evas_info->eo_size.h;
705 case DISP_GEO_METHOD_CROPPED_FULL_SCREEN:
706 LOGD("cropped full screen mode");
707 evas_info->use_ratio = FALSE;
708 /* compare evas object's ratio with video's */
709 if ((evas_info->eo_size.w / evas_info->eo_size.h) > (evas_info->w / evas_info->h)) {
710 result->w = evas_info->eo_size.w;
711 result->h = evas_info->eo_size.w * evas_info->h / evas_info->w;
712 result->y = -(result->h - evas_info->eo_size.h) / 2;
714 result->w = evas_info->eo_size.h * evas_info->w / evas_info->h;
715 result->h = evas_info->eo_size.h;
716 result->x = -(result->w - evas_info->eo_size.w) / 2;
719 case DISP_GEO_METHOD_ORIGIN_SIZE_OR_LETTER_BOX:
720 LOGD("origin size or letter box mode");
721 /* if video size is smaller than evas object's, it will be set to origin size mode */
722 if ((evas_info->eo_size.w > evas_info->w) && (evas_info->eo_size.h > evas_info->h)) {
723 LOGD("origin size mode");
724 evas_info->use_ratio = FALSE;
725 /* set coordinate for each case */
726 result->x = (evas_info->eo_size.w - evas_info->w) / 2;
727 result->y = (evas_info->eo_size.h - evas_info->h) / 2;
728 result->w = evas_info->w;
729 result->h = evas_info->h;
731 LOGD("letter box mode");
732 evas_info->use_ratio = TRUE;
733 result->w = evas_info->eo_size.w;
734 result->h = evas_info->eo_size.h;
737 case DISP_GEO_METHOD_CUSTOM_ROI:
738 LOGD("custom roi mode");
739 evas_info->use_ratio= FALSE;
740 result->x = evas_info->dst_roi.x;
741 result->y = evas_info->dst_roi.y;
742 result->w = evas_info->dst_roi.w;
743 result->h = evas_info->dst_roi.h;
745 /* don't call evas_object_image_fill_set */
746 evas_object_move(evas_info->eo, result->x, result->y);
747 evas_object_resize(evas_info->eo, result->w, result->h);
750 LOGW("unsupported mode.");
753 LOGD("geometry result [%d, %d, %d, %d]", result->x, result->y, result->w, result->h);
756 int _mm_evas_renderer_apply_geometry(mm_evas_info *evas_info)
758 if (!evas_info || !evas_info->eo) {
759 LOGW("there is no evas_info or evas object");
760 return MM_ERROR_NONE;
763 Evas_Native_Surface *surf = evas_object_image_native_surface_get(evas_info->eo);
764 rect_info result = { 0 };
767 LOGD("native surface exists");
768 surf->data.tbm.rot = evas_info->rotate_angle;
769 surf->data.tbm.flip = evas_info->flip;
770 evas_object_image_native_surface_set(evas_info->eo, surf);
772 _mm_evas_renderer_update_geometry(evas_info, &result);
774 if (evas_info->use_ratio) {
775 surf->data.tbm.ratio = (float) evas_info->w / evas_info->h;
776 LOGD("set ratio for letter mode");
779 if (result.x || result.y)
780 LOGD("coordinate x, y (%d, %d) for locating video to center", result.x, result.y);
782 if (evas_info->display_geometry_method != DISP_GEO_METHOD_CUSTOM_ROI)
783 evas_object_image_fill_set(evas_info->eo, result.x, result.y, result.w, result.h);
784 return MM_ERROR_NONE;
786 LOGW("there is no surf");
787 /* FIXME: before pipe_cb is invoked, apply_geometry can be called. */
788 return MM_ERROR_NONE;
791 int _mm_evas_renderer_retrieve_all_packets(mm_evas_info *evas_info, bool keep_screen)
793 MM_CHECK_NULL(evas_info);
795 int ret = MM_ERROR_NONE;
796 pid_t pid = getpid();
797 pid_t tid = syscall(SYS_gettid);
799 /* write and this API can be called at the same time.
800 so lock is needed for counting sent_buffer_cnt correctly */
801 g_mutex_lock(&evas_info->idx_lock);
803 /* make flush buffer */
805 ret = _mm_evas_renderer_make_flush_buffer(evas_info);
806 evas_info->keep_screen = keep_screen;
808 LOGD("pid [%d], tid [%d]", pid, tid);
810 /* in this case, we deem it is main thread */
811 if (_flush_packets(evas_info) != MM_ERROR_NONE) {
812 LOGE("flushing packets are failed");
813 ret = MM_ERROR_UNKNOWN;
816 /* it will be executed to write flush buffer and destroy media packets in pre_cb */
817 evas_info->retrieve_packet = TRUE;
819 g_mutex_unlock(&evas_info->idx_lock);
824 /* make buffer for copying */
825 int _mm_evas_renderer_make_flush_buffer (mm_evas_info *evas_info)
827 if (evas_info->cur_idx == -1) {
828 LOGW("there is no remained buffer");
829 return MM_ERROR_INVALID_ARGUMENT;
831 media_packet_h packet = evas_info->pkt_info[evas_info->cur_idx].packet;
832 MM_CHECK_NULL(packet);
834 flush_info *flush_buffer = NULL;
835 tbm_bo src_bo = NULL;
836 tbm_surface_h src_tbm_surf = NULL;
841 tbm_bo_handle vaddr_src = {0};
842 tbm_bo_handle vaddr_dst = {0};
843 int ret = MM_ERROR_NONE;
845 if (evas_info->flush_buffer)
846 _mm_evas_renderer_release_flush_buffer(evas_info);
849 flush_buffer = (flush_info *)malloc(sizeof(flush_info));
850 if (flush_buffer == NULL) {
851 LOGE("malloc is failed");
854 memset(flush_buffer, 0x0, sizeof(flush_info));
856 ret = media_packet_get_tbm_surface(packet, &src_tbm_surf);
857 if (ret != MEDIA_PACKET_ERROR_NONE || !src_tbm_surf) {
858 LOGW("get_tbm_surface is failed");
862 /* get src buffer info */
863 tbm_fmt = tbm_surface_get_format(src_tbm_surf);
864 src_bo = tbm_surface_internal_get_bo(src_tbm_surf, 0);
865 src_size = tbm_bo_size(src_bo);
866 if (!src_bo || !src_size) {
867 LOGE("bo(%p), size(%d)", src_bo, src_size);
871 /* create tbm surface */
872 flush_buffer->tbm_surf = tbm_surface_create(evas_info->w, evas_info->h, tbm_fmt);
873 if (!flush_buffer->tbm_surf)
875 LOGE("tbm_surf is NULL!!");
879 /* get bo and size */
880 bo = tbm_surface_internal_get_bo(flush_buffer->tbm_surf, 0);
881 size = tbm_bo_size(bo);
884 LOGE("bo(%p), size(%d)", bo, size);
887 flush_buffer->bo = bo;
889 vaddr_src = tbm_bo_map(src_bo, TBM_DEVICE_CPU, TBM_OPTION_READ|TBM_OPTION_WRITE);
890 vaddr_dst = tbm_bo_map(bo, TBM_DEVICE_CPU, TBM_OPTION_READ|TBM_OPTION_WRITE);
891 if (!vaddr_src.ptr || !vaddr_dst.ptr) {
892 LOGW("get vaddr failed src %p, dst %p", vaddr_src.ptr, vaddr_dst.ptr);
894 tbm_bo_unmap(src_bo);
901 memset (vaddr_dst.ptr, 0x0, size);
902 LOGW ("tbm_bo_map(vaddr) is finished, bo(%p), vaddr(%p)", bo, vaddr_dst.ptr);
906 memcpy(vaddr_dst.ptr, vaddr_src.ptr, src_size);
908 tbm_bo_unmap(src_bo);
910 LOGW("copy is done. tbm surface : %p src_size : %d", flush_buffer->tbm_surf, src_size);
912 evas_info->flush_buffer = flush_buffer;
914 return MM_ERROR_NONE;
918 if(flush_buffer->tbm_surf)
920 tbm_surface_destroy(flush_buffer->tbm_surf);
921 flush_buffer->tbm_surf = NULL;
927 return MM_ERROR_UNKNOWN;
930 /* release flush buffer */
931 void _mm_evas_renderer_release_flush_buffer (mm_evas_info *evas_info)
933 LOGW("release FLUSH BUFFER start");
934 if (evas_info->flush_buffer->bo) {
935 evas_info->flush_buffer->bo = NULL;
937 if (evas_info->flush_buffer->tbm_surf) {
938 tbm_surface_destroy(evas_info->flush_buffer->tbm_surf);
939 evas_info->flush_buffer->tbm_surf = NULL;
942 LOGW("release FLUSH BUFFER done");
944 free(evas_info->flush_buffer);
945 evas_info->flush_buffer = NULL;
950 void mm_evas_renderer_write(media_packet_h packet, void *data)
953 LOGE("packet %p is NULL", packet);
956 mm_evas_info *handle = (mm_evas_info *)data;
957 int ret = MEDIA_PACKET_ERROR_NONE;
959 tbm_surface_h tbm_surf;
962 LOGD("packet [%p]", packet);
964 if (!data || !handle) {
965 LOGE("handle %p or evas_info %p is NULL", data, handle);
968 g_mutex_lock(&handle->idx_lock);
970 ret = media_packet_has_tbm_surface_buffer(packet, &has);
971 if (ret != MEDIA_PACKET_ERROR_NONE) {
972 LOGW("has_tbm_surface is failed");
975 /* FIXME: when setCaps occurs, _get_video_size should be called */
976 /* currently we are always checking it */
977 if (has && _get_video_size(packet, handle)) {
978 /* Attention! if this error occurs, we need to consider managing buffer */
979 if (handle->sent_buffer_cnt > 3) {
980 LOGE("too many buffers are not released %d", handle->sent_buffer_cnt);
983 /* FIXME: fix this logic */
984 /* destroy all media packets and reset pipe at present */
985 /* Attention! it might free buffer that is being rendered */
986 g_mutex_lock(&handle->mp_lock);
988 g_mutex_unlock(&handle->mp_lock);
991 ret = media_packet_get_tbm_surface(packet, &tbm_surf);
992 if (ret != MEDIA_PACKET_ERROR_NONE || !tbm_surf) {
993 LOGW("get_tbm_surface is failed");
997 /* find new index for current packet */
998 index = _find_empty_index(handle);
1003 /* save previous index */
1004 handle->pkt_info[index].prev = handle->cur_idx;
1005 handle->pkt_info[index].packet = packet;
1006 handle->pkt_info[index].tbm_surf = tbm_surf;
1007 handle->cur_idx = index;
1008 handle->sent_buffer_cnt++;
1009 LOGD("sent packet %d", handle->sent_buffer_cnt);
1011 ret = ecore_pipe_write(handle->epipe, handle, UPDATE_TBM_SURF);
1013 handle->pkt_info[index].packet = NULL;
1014 handle->pkt_info[index].tbm_surf = NULL;
1015 handle->pkt_info[index].prev = -1;
1016 handle->cur_idx = handle->pkt_info[index].prev;
1017 handle->sent_buffer_cnt--;
1018 LOGW("Failed to ecore_pipe_write() for updating tbm surf\n");
1022 LOGW("no tbm_surf");
1025 g_mutex_unlock(&handle->idx_lock);
1029 g_mutex_unlock(&handle->idx_lock);
1031 /* destroy media_packet immediately */
1033 g_mutex_lock(&handle->mp_lock);
1034 LOGD("cant write. destroy packet [%p]", packet);
1035 if (media_packet_destroy(packet) != MEDIA_PACKET_ERROR_NONE)
1036 LOGE("media_packet_destroy failed %p", packet);
1038 g_mutex_unlock(&handle->mp_lock);
1043 int mm_evas_renderer_update_param(MMHandleType handle)
1045 int ret = MM_ERROR_NONE;
1046 mm_evas_info *evas_info = (mm_evas_info *)handle;
1049 LOGW("skip it. it is not evas surface type.");
1053 /* when handle is realized, we need to update all properties */
1055 LOGD("set video param : evas-object %x, method %d", evas_info->eo, evas_info->display_geometry_method);
1056 LOGD("set video param : visible %d", evas_info->visible);
1057 LOGD("set video param : rotate %d", evas_info->rotate_angle);
1059 ret = _mm_evas_renderer_apply_geometry(evas_info);
1060 if (ret != MM_ERROR_NONE)
1063 if (evas_info->epipe) {
1064 ret = ecore_pipe_write(evas_info->epipe, &evas_info->visible, UPDATE_VISIBILITY);
1066 LOGW("fail to ecore_pipe_write() for updating visibility\n");
1067 return MM_ERROR_UNKNOWN;
1069 ret = MM_ERROR_NONE;
1071 #if 0 /* FIXME: pause state only */
1072 g_mutex_lock(&evas_info->idx_lock);
1073 ret = ecore_pipe_write(evas_info->epipe, evas_info, UPDATE_TBM_SURF);
1075 LOGW("fail to ecore_pipe_write() for updating visibility\n");
1076 ret = MM_ERROR_UNKNOWN;
1078 ret = MM_ERROR_NONE;
1080 g_mutex_unlock(&evas_info->idx_lock);
1088 int mm_evas_renderer_create(MMHandleType *handle, Evas_Object *eo)
1090 MM_CHECK_NULL(handle);
1092 int ret = MM_ERROR_NONE;
1093 mm_evas_info *evas_info = NULL;
1095 ret = _mm_evas_renderer_create(&evas_info);
1096 if (ret != MM_ERROR_NONE) {
1097 LOGE("fail to create evas_info");
1100 ret = _mm_evas_renderer_set_info(evas_info, eo);
1101 if (ret != MM_ERROR_NONE) {
1102 LOGE("fail to init evas_info");
1103 if (_mm_evas_renderer_destroy(&evas_info) != MM_ERROR_NONE)
1104 LOGE("fail to destroy evas_info");
1108 *handle = (MMHandleType)evas_info;
1110 return MM_ERROR_NONE;
1113 int mm_evas_renderer_destroy(MMHandleType *handle)
1115 MM_CHECK_NULL(handle);
1117 int ret = MM_ERROR_NONE;
1118 mm_evas_info *evas_info = (mm_evas_info *)*handle;
1121 LOGD("skip it. it is not evas surface type.");
1122 return MM_ERROR_RESOURCE_NOT_INITIALIZED;
1125 ret = _mm_evas_renderer_destroy(&evas_info);
1126 if (ret != MM_ERROR_NONE) {
1127 LOGE("fail to destroy evas_info");
1132 return MM_ERROR_NONE;
1135 int mm_evas_renderer_set_visible(MMHandleType handle, bool visible)
1137 int ret = MM_ERROR_NONE;
1138 mm_evas_info *evas_info = (mm_evas_info *)handle;
1141 LOGW("skip it. it is not evas surface type or handle is not prepared");
1142 return MM_ERROR_RESOURCE_NOT_INITIALIZED;
1146 evas_info->visible = VISIBLE_TRUE;
1148 evas_info->visible = VISIBLE_FALSE;
1150 if (evas_info->epipe) {
1151 ret = ecore_pipe_write(evas_info->epipe, &visible, UPDATE_VISIBILITY);
1153 LOGW("fail to ecore_pipe_write() for updating visibility\n");
1154 ret = MM_ERROR_UNKNOWN;
1156 ret = MM_ERROR_NONE;
1159 LOGW("there is no epipe. we cant update it");
1165 int mm_evas_renderer_get_visible(MMHandleType handle, bool *visible)
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;
1174 if (evas_info->visible == VISIBLE_FALSE)
1179 return MM_ERROR_NONE;
1182 int mm_evas_renderer_set_rotation(MMHandleType handle, int rotate)
1184 int ret = MM_ERROR_NONE;
1185 mm_evas_info *evas_info = (mm_evas_info *)handle;
1188 LOGW("skip it. it is not evas surface type or handle is not prepared");
1189 return MM_ERROR_RESOURCE_NOT_INITIALIZED;
1194 evas_info->rotate_angle = EVAS_IMAGE_ORIENT_0;
1197 evas_info->rotate_angle = EVAS_IMAGE_ORIENT_90;
1200 evas_info->rotate_angle = EVAS_IMAGE_ORIENT_180;
1203 evas_info->rotate_angle = EVAS_IMAGE_ORIENT_270;
1206 return MM_ERROR_INVALID_ARGUMENT;
1208 #if 0 /* FIXME: pause state only */
1209 if (evas_info->epipe) {
1210 g_mutex_lock(&evas_info->idx_lock);
1211 ret = ecore_pipe_write(evas_info->epipe, evas_info, UPDATE_TBM_SURF);
1213 LOGW("fail to ecore_pipe_write() for updating visibility\n");
1214 ret = MM_ERROR_UNKNOWN;
1216 ret = MM_ERROR_NONE;
1218 g_mutex_unlock(&evas_info->idx_lock);
1224 int mm_evas_renderer_get_rotation(MMHandleType handle, int *rotate)
1226 mm_evas_info *evas_info = (mm_evas_info *)handle;
1229 LOGW("skip it. it is not evas surface type or handle is not prepared");
1230 return MM_ERROR_RESOURCE_NOT_INITIALIZED;
1233 switch(evas_info->rotate_angle) {
1234 case EVAS_IMAGE_ORIENT_0:
1237 case EVAS_IMAGE_ORIENT_90:
1238 *rotate = DEGREE_90;
1240 case EVAS_IMAGE_ORIENT_180:
1241 *rotate = DEGREE_180;
1243 case EVAS_IMAGE_ORIENT_270:
1244 *rotate = DEGREE_270;
1247 return MM_ERROR_INVALID_ARGUMENT;
1250 return MM_ERROR_NONE;
1253 int mm_evas_renderer_set_geometry(MMHandleType handle, int mode)
1255 int ret = MM_ERROR_NONE;
1256 mm_evas_info *evas_info = (mm_evas_info *)handle;
1259 LOGW("skip it. it is not evas surface type or handle is not prepared");
1260 return MM_ERROR_RESOURCE_NOT_INITIALIZED;
1263 evas_info->display_geometry_method = mode;
1264 ret = _mm_evas_renderer_apply_geometry(evas_info);
1266 /* ecore_pipe_write is needed, because of setting ratio for letterbox mode */
1267 #if 0 /* FIXME: pause state only */
1268 if (evas_info->epipe) {
1269 g_mutex_lock(&evas_info->idx_lock);
1270 ret = ecore_pipe_write(evas_info->epipe, evas_info, UPDATE_TBM_SURF);
1272 LOGW("fail to ecore_pipe_write() for updating visibility\n");
1273 ret = MM_ERROR_UNKNOWN;
1275 ret = MM_ERROR_NONE;
1277 g_mutex_unlock(&evas_info->idx_lock);
1284 int mm_evas_renderer_get_geometry(MMHandleType handle, int *mode)
1286 mm_evas_info *evas_info = (mm_evas_info *)handle;
1289 LOGW("skip it. it is not evas surface type or handle is not prepared");
1290 return MM_ERROR_RESOURCE_NOT_INITIALIZED;
1292 *mode = evas_info->display_geometry_method;
1294 return MM_ERROR_NONE;
1297 int mm_evas_renderer_set_roi_area(MMHandleType handle, int x, int y, int w, int h)
1299 int ret = MM_ERROR_NONE;
1300 mm_evas_info *evas_info = (mm_evas_info *)handle;
1303 LOGW("skip it. it is not evas surface type or handle is not prepared");
1304 return MM_ERROR_RESOURCE_NOT_INITIALIZED;
1307 LOGW("invalid resolution");
1308 return MM_ERROR_INVALID_ARGUMENT;
1311 /* display mode is set to DISP_GEO_METHOD_CUSTOM_ROI internally */
1312 evas_info->display_geometry_method = DISP_GEO_METHOD_CUSTOM_ROI;
1313 evas_info->dst_roi.x = x;
1314 evas_info->dst_roi.y = y;
1315 evas_info->dst_roi.w = w;
1316 evas_info->dst_roi.h = h;
1317 ret = _mm_evas_renderer_apply_geometry(evas_info);
1322 int mm_evas_renderer_get_roi_area(MMHandleType handle, int *x, int *y, int *w, int *h)
1324 mm_evas_info *evas_info = (mm_evas_info *)handle;
1327 LOGW("skip it. it is not evas surface type or handle is not prepared");
1328 return MM_ERROR_RESOURCE_NOT_INITIALIZED;
1330 if (evas_info->display_geometry_method != DISP_GEO_METHOD_CUSTOM_ROI) {
1331 LOGW("invalid mode");
1332 return MM_ERROR_INVALID_ARGUMENT;
1335 *x = evas_info->dst_roi.x;
1336 *y = evas_info->dst_roi.y;
1337 *w = evas_info->dst_roi.w;
1338 *h = evas_info->dst_roi.h;
1340 return MM_ERROR_NONE;
1343 int mm_evas_renderer_set_flip(MMHandleType handle, int flip)
1345 int ret = MM_ERROR_NONE;
1346 mm_evas_info *evas_info = (mm_evas_info *)handle;
1349 LOGW("skip it. it is not evas surface type or handle is not prepared");
1350 return MM_ERROR_RESOURCE_NOT_INITIALIZED;
1355 evas_info->flip = EVAS_IMAGE_ORIENT_NONE;
1357 case FLIP_HORIZONTAL:
1358 evas_info->flip = EVAS_IMAGE_FLIP_HORIZONTAL;
1361 evas_info->flip = EVAS_IMAGE_FLIP_VERTICAL;
1364 evas_info->flip = EVAS_IMAGE_ORIENT_180;
1367 return MM_ERROR_INVALID_ARGUMENT;
1369 #if 0 /* FIXME: pause state only */
1370 if (evas_info->epipe) {
1371 g_mutex_lock(&evas_info->idx_lock);
1372 ret = ecore_pipe_write(evas_info->epipe, evas_info, UPDATE_TBM_SURF);
1374 LOGW("fail to ecore_pipe_write() for updating visibility\n");
1375 ret = MM_ERROR_UNKNOWN;
1377 ret = MM_ERROR_NONE;
1379 g_mutex_unlock(&evas_info->idx_lock);
1385 int mm_evas_renderer_get_flip(MMHandleType handle, int *flip)
1387 mm_evas_info *evas_info = (mm_evas_info *)handle;
1390 LOGW("skip it. it is not evas surface type or handle is not prepared");
1391 return MM_ERROR_RESOURCE_NOT_INITIALIZED;
1394 switch(evas_info->flip) {
1395 case EVAS_IMAGE_ORIENT_NONE:
1398 case EVAS_IMAGE_FLIP_HORIZONTAL:
1399 *flip = FLIP_HORIZONTAL;
1401 case EVAS_IMAGE_FLIP_VERTICAL:
1402 *flip = FLIP_VERTICAL;
1404 case EVAS_IMAGE_ORIENT_180:
1408 return MM_ERROR_INVALID_ARGUMENT;
1411 return MM_ERROR_NONE;
1414 int mm_evas_renderer_retrieve_all_packets (MMHandleType handle, bool keep_screen)
1416 int ret = MM_ERROR_NONE;
1417 mm_evas_info *evas_info = (mm_evas_info*) handle;
1420 LOGW("skip it. it is not evas surface type or player is not prepared");
1421 return MM_ERROR_RESOURCE_NOT_INITIALIZED;
1423 ret = _mm_evas_renderer_retrieve_all_packets(evas_info, keep_screen);