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.
23 #include <sys/types.h>
26 #include <sys/syscall.h>
29 #include <tbm_surface.h>
30 #include <tbm_surface_internal.h>
32 #include "mm_evas_renderer_private.h"
37 #define LOG_TAG "MM_EVAS_RENDER"
39 //#define _INTERNAL_DEBUG_ /* debug only */
40 #define SWAP(a, b) ({int t; t = a; a = b; b = t; })
42 #define SIGNAL_TIMEOUT 1
44 #define MMER_FENTER(); LOGD("<ENTER>");
45 #define MMER_FLEAVE(); LOGD("<LEAVE>");
47 #define MMEVAS_RETURN_IF_FAIL(expr) \
50 LOGW("faild [%s]", #expr); \
55 #define MMEVAS_RETURN_VAL_IF_FAIL(expr, var) \
58 LOGW("faild [%s]", #expr); \
64 DISP_GEO_METHOD_LETTER_BOX = 0,
65 DISP_GEO_METHOD_ORIGIN_SIZE,
66 DISP_GEO_METHOD_FULL_SCREEN,
67 DISP_GEO_METHOD_CROPPED_FULL_SCREEN,
68 DISP_GEO_METHOD_ORIGIN_SIZE_OR_LETTER_BOX,
69 DISP_GEO_METHOD_CUSTOM_ROI,
89 #ifdef _INTERNAL_DEBUG_
90 static int g_cnt_in = 0;
91 static int g_cnt_out = 0;
92 static int __dump_pkt(media_packet_h pkt, int width, int height);
93 static int __dump_surf(tbm_surface_h tbm_surf);
96 static void _free_previous_packets(mm_evas_info *evas_info);
97 static int _flush_all_packets(mm_evas_info *evas_info);
98 static int _mm_evas_renderer_create(mm_evas_info **evas_info);
99 static int _mm_evas_renderer_destroy(mm_evas_info **evas_info);
100 static int _mm_evas_renderer_set_info(mm_evas_info *evas_info, Evas_Object *eo);
101 static int _mm_evas_renderer_reset(mm_evas_info *evas_info, gboolean is_sub_thread);
102 static void _mm_evas_renderer_update_geometry(mm_evas_info *evas_info);
103 static int _mm_evas_renderer_retrieve_all_packets(mm_evas_info *evas_info, bool keep_screen);
104 static int _mm_evas_renderer_make_flush_buffer(mm_evas_info *evas_info);
105 static void _mm_evas_renderer_release_flush_buffer(mm_evas_info *evas_info);
106 static void _mm_evas_renderer_get_video_angle(mm_evas_info *evas_info, int *rotate_angle, int *orientation);
107 static void _mm_evas_renderer_update_rotate_angle(mm_evas_info *evas_info);
108 static void _mm_evas_renderer_set_callback(mm_evas_info *evas_info);
109 static void _mm_evas_renderer_unset_callback(mm_evas_info *evas_info);
110 static void _mm_evas_renderer_set_evas_object_size(mm_evas_info *evas_info);
111 static gboolean _check_rendering_packet(mm_evas_info *evas_info);
113 /* must be called after the null surface has been set. */
114 static int _mm_evas_renderer_update_rendering_info(mm_evas_info *evas_info)
118 MMEVAS_RETURN_VAL_IF_FAIL(evas_info, MM_ERROR_EVASRENDER_NOT_INITIALIZED);
119 MMEVAS_RETURN_VAL_IF_FAIL(evas_info->eo, MM_ERROR_EVASRENDER_NOT_INITIALIZED);
121 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);
122 if (!evas_info->eo_size.w || !evas_info->eo_size.h) {
123 LOGE("there is no information for evas object size");
124 return MM_ERROR_EVASRENDER_INTERNAL;
126 if (!evas_info->w || !evas_info->h) {
127 LOGE("there is no video size from mm_evas_renderer_write() which is callback_func of player or camera");
128 return MM_ERROR_EVASRENDER_INTERNAL;
131 _mm_evas_renderer_update_geometry(evas_info);
132 if (!evas_info->result.w || !evas_info->result.h) {
133 LOGE("no information about geometry (%d, %d)", evas_info->result.w, evas_info->result.h);
134 return MM_ERROR_EVASRENDER_INTERNAL;
137 if (evas_info->video_size_changed) {
138 _mm_evas_renderer_set_evas_object_size(evas_info);
139 evas_info->video_size_changed = FALSE;
142 if (evas_info->result.x || evas_info->result.y)
143 LOGD("coordinate x, y (%d, %d) for locating video to center", evas_info->result.x, evas_info->result.y);
144 evas_object_image_fill_set(evas_info->eo, evas_info->result.x, evas_info->result.y, evas_info->result.w, evas_info->result.h);
147 return MM_ERROR_NONE;
150 static void _evas_resize_cb(void *data, Evas *e, Evas_Object *obj, void *event_info)
152 /* now evas object size is changed */
153 mm_evas_info *evas_info = data;
157 MMEVAS_RETURN_IF_FAIL(evas_info);
158 MMEVAS_RETURN_IF_FAIL(evas_info->eo);
160 g_mutex_lock(&evas_info->idx_lock);
162 if (!_check_rendering_packet(evas_info)) {
163 g_mutex_unlock(&evas_info->idx_lock);
167 g_mutex_unlock(&evas_info->idx_lock);
169 if (_mm_evas_renderer_update_rendering_info(evas_info) == MM_ERROR_NONE) {
170 Evas_Native_Surface *surf;
171 surf = evas_object_image_native_surface_get(evas_info->eo);
173 LOGD("native surface exists");
174 surf->data.tbm.rot = evas_info->rotate_angle;
175 surf->data.tbm.flip = evas_info->flip;
176 surf->data.tbm.ratio = evas_info->ratio;
177 /* surface set must be called by main thread */
178 evas_object_image_native_surface_set(evas_info->eo, surf);
180 LOGW("there is no surf");
186 static gboolean _check_rendering_packet(mm_evas_info *evas_info)
189 tbm_format tbm_fmt = 0;
194 MMEVAS_RETURN_VAL_IF_FAIL(evas_info, FALSE);
196 cur_idx = evas_info->cur_idx;
198 if ((cur_idx == -1) || !evas_info->pkt_info[cur_idx].tbm_surf) {
199 LOGW("cur_idx %d, tbm_surf may be NULL", cur_idx);
203 if (!evas_info->pkt_info[cur_idx].packet) {
204 LOGE(" Packet is NULL");
208 tbm_fmt = tbm_surface_get_format(evas_info->pkt_info[cur_idx].tbm_surf);
210 case TBM_FORMAT_NV12:
211 s_fmt = "TBM_FORMAT_NV12";
213 case TBM_FORMAT_YUV420:
214 s_fmt = "TBM_FORMAT_YUV420";
216 case TBM_FORMAT_YUYV:
217 s_fmt = "TBM_FORMAT_YUYV";
223 LOGD("received idx(%d), packet(%p), format([%d]: %s)", cur_idx, evas_info->pkt_info[cur_idx].packet, tbm_fmt, s_fmt);
230 /* must be called after the null surface has been set. */
231 static void _mm_evas_renderer_surface_set(mm_evas_info *evas_info)
238 MMEVAS_RETURN_IF_FAIL(evas_info);
239 MMEVAS_RETURN_IF_FAIL(evas_info->eo);
241 g_mutex_lock(&evas_info->idx_lock);
243 if (!_check_rendering_packet(evas_info)) {
244 g_mutex_unlock(&evas_info->idx_lock);
248 if (evas_info->rendering_info_changed) {
249 LOGD("Rendering info changed");
250 if (_mm_evas_renderer_update_rendering_info(evas_info) != MM_ERROR_NONE)
252 evas_info->rendering_info_changed = FALSE;
254 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);
256 if (evas_info->update_needed) {
257 evas_object_image_native_surface_set(evas_info->eo, NULL);
258 evas_info->update_needed = FALSE;
261 cur_idx = evas_info->cur_idx;
262 prev_idx = evas_info->pkt_info[cur_idx].prev_idx;
265 Evas_Native_Surface surf = { 0 };
266 surf.type = EVAS_NATIVE_SURFACE_TBM;
267 surf.version = EVAS_NATIVE_SURFACE_VERSION;
268 surf.data.tbm.buffer = evas_info->pkt_info[cur_idx].tbm_surf;
269 surf.data.tbm.rot = evas_info->rotate_angle;
270 surf.data.tbm.flip = evas_info->flip;
271 surf.data.tbm.ratio = evas_info->ratio;
273 #ifdef _INTERNAL_DEBUG_
275 if ((g_cnt_out%5 == 0) && (g_cnt_out < 500))
276 ret2 = __dump_surf(evas_info->pkt_info[cur_idx].tbm_surf);
278 LOGW("__dump_surf() is failed");
282 if (evas_info->visible) {
283 /* surface set must be called by main thread */
284 evas_object_image_native_surface_set(evas_info->eo, &surf);
285 evas_object_image_pixels_dirty_set(evas_info->eo, EINA_TRUE);
286 LOGD("native surface set finish");
288 LOGD("skip... surface set");
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);
295 g_mutex_unlock(&evas_info->idx_lock);
301 if ((prev_idx != -1) && evas_info->pkt_info[prev_idx].packet) {
303 _free_previous_packets(evas_info);
305 g_mutex_unlock(&evas_info->idx_lock);
310 /* must be called after the null surface has been set. */
311 static void _mm_evas_renderer_select_task(mm_evas_info *evas_info, update_info info)
315 MMEVAS_RETURN_IF_FAIL(evas_info);
316 MMEVAS_RETURN_IF_FAIL(evas_info->eo);
318 LOGD("evas_info : %p, info type : %d, evas_info->eo : %p", evas_info, info, evas_info->eo);
321 case UPDATE_VISIBILITY:
322 if (!evas_info->visible) {
323 /* surface set must be called by main thread */
324 evas_object_image_native_surface_set(evas_info->eo, NULL);
325 evas_object_hide(evas_info->eo);
326 LOGI("object hide..");
329 evas_object_show(evas_info->eo);
330 LOGI("object show.. %d", evas_info->visible);
331 /* video rendering */
332 _mm_evas_renderer_surface_set(evas_info);
335 case UPDATE_TBM_SURF:
336 /* video rendering */
337 _mm_evas_renderer_surface_set(evas_info);
339 case UPDATE_FLUSH_BUFFER:
340 if (_flush_all_packets(evas_info) != MM_ERROR_NONE)
341 LOGE("flushing packets is failed");
344 LOGW("invalid info type : %d", info);
352 static void _evas_pipe_cb(void *data, void *buffer, update_info info)
354 mm_evas_info *evas_info = data;
358 MMEVAS_RETURN_IF_FAIL(evas_info);
359 MMEVAS_RETURN_IF_FAIL(evas_info->eo);
361 LOGD("ecore_pipe is called");
363 if (!evas_info->is_set_resize_cb)
364 _mm_evas_renderer_set_callback(evas_info);
366 g_mutex_lock(&evas_info->mp_lock);
367 _mm_evas_renderer_select_task(evas_info, info);
368 g_mutex_unlock(&evas_info->mp_lock);
374 #ifdef _INTERNAL_DEBUG_
375 static int __dump_pkt(media_packet_h pkt, int width, int height)
379 char filename[128] = {0};
382 int stride_width, stride_height;
383 uint32_t plane_num = 0;
385 sprintf(filename, "/tmp/DUMP_IN_IMG_%2.2d.dump", g_cnt_in);
386 fp = fopen(filename, "wb");
390 media_packet_get_number_of_video_planes(pkt, &plane_num); /* temporary expedient to decide format */
391 media_packet_get_video_plane_data_ptr(pkt, 0, (void **)&data);
392 media_packet_get_video_stride_width(pkt, 0, &stride_width);
393 media_packet_get_video_stride_height(pkt, 0, &stride_height);
394 media_packet_get_buffer_size(pkt, &size);
395 LOGI("[0]stride : %d, %d", stride_width, stride_height);
397 for (i = 0; i < height; i++) {
398 fwrite(data, width, 1, fp);
399 data += stride_width;
401 if (plane_num == 2) { /* hw codec(NV12) */
402 media_packet_get_video_plane_data_ptr(pkt, 1, (void **)&data);
403 media_packet_get_video_stride_width(pkt, 1, &stride_width);
404 for (i = 0; i < height/2; i++) {
405 fwrite(data, width, 1, fp);
406 data += stride_width;
408 } else if (plane_num == 3) { /* sw codec(YUV420) */
409 media_packet_get_video_plane_data_ptr(pkt, 1, (void **)&data);
410 media_packet_get_video_stride_width(pkt, 1, &stride_width);
411 for (i = 0; i < height/2; i++) {
412 fwrite(data, width/2, 1, fp);
413 data += stride_width;
415 LOGI("[1]stride : %d, %d", stride_width, stride_height);
416 media_packet_get_video_plane_data_ptr(pkt, 2, (void **)&data);
417 media_packet_get_video_stride_width(pkt, 2, &stride_width);
418 for (i = 0; i < height/2; i++) {
419 fwrite(data, width/2, 1, fp);
420 data += stride_width;
422 LOGI("[2]stride : %d, %d", stride_width, stride_height);
424 LOGW("plane_num %d", plane_num);
429 LOGI("DUMP_IN_IMG_%2.2d : buffer size(%d) data(%p)", g_cnt_in, (int)size, data);
435 static int __dump_surf(tbm_surface_h tbm_surf)
437 char filename[128] = {0};
438 tbm_surface_info_s info = {0};
440 sprintf(filename, "DUMP_OUT_IMG_%2.2d", g_cnt_out);
441 if (tbm_surface_get_info(tbm_surf, &info)) {
442 LOGE("get_info is failed");
446 tbm_surface_internal_dump_start("/tmp", info.width, info.height, 1);
447 tbm_surface_internal_dump_buffer(tbm_surf, filename);
448 tbm_surface_internal_dump_end();
450 LOGI("[0]stride : %d, offset : %d", (int)info.planes[0].stride, (int)info.planes[0].offset);
451 LOGI("[1]stride : %d, offset : %d", (int)info.planes[1].stride, (int)info.planes[1].offset);
452 LOGI("[2]stride : %d, offset : %d", (int)info.planes[2].stride, (int)info.planes[2].offset);
453 LOGI("DUMP_OUT_IMG_%2.2d : buffer size(%d) surf(%p) %d*%d", g_cnt_out, (int)info.size, tbm_surf, info.width, info.height);
459 static void _free_previous_packets(mm_evas_info *evas_info)
461 gint index = evas_info->cur_idx;
462 gint prev_idx = evas_info->pkt_info[index].prev_idx;
466 while (prev_idx != -1) {
467 LOGD("destroy previous packet [%p] idx %d", evas_info->pkt_info[prev_idx].packet, prev_idx);
468 if (evas_info->packet_rendered_cb) {
469 evas_info->packet_rendered_cb(evas_info->pkt_info[prev_idx].packet, evas_info->packet_rendered_cb_user);
471 if (media_packet_destroy(evas_info->pkt_info[prev_idx].packet) != MEDIA_PACKET_ERROR_NONE)
472 LOGE("media_packet_destroy failed %p", evas_info->pkt_info[prev_idx].packet);
474 evas_info->sent_buffer_cnt--;
475 evas_info->pkt_info[prev_idx].packet = NULL;
476 evas_info->pkt_info[prev_idx].tbm_surf = NULL;
477 evas_info->pkt_info[index].prev_idx = -1;
479 /* move index to previous index */
481 prev_idx = evas_info->pkt_info[prev_idx].prev_idx;
482 LOGD("sent packet %d", evas_info->sent_buffer_cnt);
490 static bool _get_video_size(media_packet_h packet, mm_evas_info *evas_info)
496 MMEVAS_RETURN_VAL_IF_FAIL(packet, false);
497 MMEVAS_RETURN_VAL_IF_FAIL(evas_info, false);
499 if (media_packet_get_format(packet, &fmt) != MEDIA_PACKET_ERROR_NONE) {
500 LOGE("media_packet_get_format is failed");
504 if (media_format_get_video_info(fmt, NULL, &w, &h, NULL, NULL) != MEDIA_FORMAT_ERROR_NONE) {
505 LOGE("media_format_get_video_info is failed");
510 if (w != evas_info->w || h != evas_info->h) {
511 LOGD("previous: (%dx%d)", evas_info->w, evas_info->w);
514 evas_info->rendering_info_changed = TRUE;
515 evas_info->video_size_changed = TRUE;
517 LOGD("(%dx%d)", evas_info->w, evas_info->w);
520 if (media_format_unref(fmt) != MEDIA_FORMAT_ERROR_NONE)
521 LOGW("media_format_unref is failed");
526 static int _find_empty_index(mm_evas_info *evas_info)
532 for (i = 0; i < MAX_PACKET_NUM; i++) {
533 if (!evas_info->pkt_info[i].packet) {
534 LOGD("selected idx %d", i);
538 LOGE("there is no empty idx");
545 /* must be called after the null surface has been set. */
546 static int _destroy_all_packets(mm_evas_info *evas_info)
548 int ret = MM_ERROR_NONE;
549 int ret_mp = MEDIA_PACKET_ERROR_NONE;
554 MMEVAS_RETURN_VAL_IF_FAIL(evas_info, MM_ERROR_EVASRENDER_NOT_INITIALIZED);
556 g_mutex_lock(&evas_info->idx_lock);
557 for (i = 0; i < MAX_PACKET_NUM; i++) {
558 if (evas_info->pkt_info[i].packet) {
559 /* destroy all packets */
560 LOGD("destroy packet [%p]", evas_info->pkt_info[i].packet);
561 if (evas_info->packet_rendered_cb) {
562 evas_info->packet_rendered_cb(evas_info->pkt_info[i].packet, evas_info->packet_rendered_cb_user);
564 ret_mp = media_packet_destroy(evas_info->pkt_info[i].packet);
565 if (ret_mp != MEDIA_PACKET_ERROR_NONE) {
566 LOGW("media_packet_destroy failed %p", evas_info->pkt_info[i].packet);
567 ret = MM_ERROR_EVASRENDER_INTERNAL;
570 evas_info->sent_buffer_cnt--;
571 evas_info->pkt_info[i].packet = NULL;
572 evas_info->pkt_info[i].tbm_surf = NULL;
573 evas_info->pkt_info[i].prev_idx = INIT_IDX;
577 if (evas_info->sent_buffer_cnt != 0)
578 LOGE("it should be 0 --> [%d]", evas_info->sent_buffer_cnt);
579 evas_info->sent_buffer_cnt = 0;
580 evas_info->cur_idx = INIT_IDX;
581 evas_info->flush_all_packets = TRUE;
583 g_mutex_unlock(&evas_info->idx_lock);
591 static int _set_flush_buffer(mm_evas_info *evas_info)
593 int ret = MM_ERROR_NONE;
594 Evas_Native_Surface surf = { 0 };
598 MMEVAS_RETURN_VAL_IF_FAIL(evas_info, MM_ERROR_EVASRENDER_NOT_INITIALIZED);
600 /* set flush buffer surface*/
601 surf.type = EVAS_NATIVE_SURFACE_TBM;
602 surf.version = EVAS_NATIVE_SURFACE_VERSION;
603 surf.data.tbm.buffer = evas_info->flush_buffer->tbm_surf;
604 surf.data.tbm.rot = evas_info->rotate_angle;
605 surf.data.tbm.flip = evas_info->flip;
606 surf.data.tbm.ratio = evas_info->ratio;
608 /* surface set must be called by main thread */
609 evas_object_image_native_surface_set(evas_info->eo, &surf);
610 evas_object_image_pixels_dirty_set(evas_info->eo, EINA_TRUE);
612 LOGD("flush_buffer surf(%p), rotate(%d), flip(%d)", evas_info->flush_buffer->tbm_surf, evas_info->rotate_angle, evas_info->flip);
617 /* EVAS API must be called by main thread */
618 static int _flush_all_packets(mm_evas_info *evas_info)
620 int ret = MM_ERROR_NONE;
624 MMEVAS_RETURN_VAL_IF_FAIL(evas_info, MM_ERROR_EVASRENDER_NOT_INITIALIZED);
625 MMEVAS_RETURN_VAL_IF_FAIL(evas_info->eo, MM_ERROR_EVASRENDER_NOT_INITIALIZED);
627 /* update the screen only if visible is true */
628 /* if flush buffer is null, we cant keep screen */
629 if (evas_info->keep_screen && evas_info->visible && evas_info->flush_buffer) {
630 /* _set_flush_buffer */
631 ret = _set_flush_buffer(evas_info);
632 if (ret != MM_ERROR_NONE) return ret;
634 /* unset evas native surface for removing rendered video frame */
635 evas_object_image_native_surface_set(evas_info->eo, NULL);
636 evas_object_image_pixels_dirty_set(evas_info->eo, EINA_TRUE);
637 _mm_evas_renderer_unset_callback(evas_info);
640 LOGD("sent packet %d", evas_info->sent_buffer_cnt);
641 ret = _destroy_all_packets(evas_info);
643 if (ret == MM_ERROR_NONE) {
644 g_mutex_lock(&evas_info->evas_lock);
645 LOGD("send signal[COND_RETRIEVE]");
646 g_cond_signal(&evas_info->evas_cond[COND_RETRIEVE]);
647 g_mutex_unlock(&evas_info->evas_lock);
655 static void _mm_evas_renderer_set_callback(mm_evas_info *evas_info)
660 LOGD("resize callback add");
661 evas_object_event_callback_add(evas_info->eo, EVAS_CALLBACK_RESIZE, _evas_resize_cb, evas_info);
662 evas_info->is_set_resize_cb = TRUE;
668 static void _mm_evas_renderer_unset_callback(mm_evas_info *evas_info)
673 LOGD("resize callback del");
674 evas_object_event_callback_del(evas_info->eo, EVAS_CALLBACK_RESIZE, _evas_resize_cb);
675 evas_info->is_set_resize_cb = FALSE;
681 static void _mm_evas_renderer_set_evas_object_size(mm_evas_info *evas_info)
685 MMEVAS_RETURN_IF_FAIL(evas_info);
686 MMEVAS_RETURN_IF_FAIL(evas_info->eo);
688 if (evas_info->w > 0 && evas_info->h > 0)
689 evas_object_image_size_set(evas_info->eo, evas_info->w, evas_info->h);
690 evas_object_size_hint_align_set(evas_info->eo, EVAS_HINT_FILL, EVAS_HINT_FILL);
691 evas_object_size_hint_weight_set(evas_info->eo, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
698 static int _mm_evas_pipe_write(mm_evas_info *evas_info, update_info info)
700 int ret = MM_ERROR_NONE;
704 MMEVAS_RETURN_VAL_IF_FAIL(evas_info, MM_ERROR_EVASRENDER_NOT_INITIALIZED);
705 MMEVAS_RETURN_VAL_IF_FAIL(evas_info->epipe, MM_ERROR_EVASRENDER_NOT_INITIALIZED);
707 g_mutex_lock(&evas_info->write_lock);
708 if (!ecore_pipe_write(evas_info->epipe, evas_info, info)) {
709 LOGW("fail to ecore_pipe_write() for update info type(%d)", info);
710 ret = MM_ERROR_EVASRENDER_INTERNAL;
712 g_mutex_unlock(&evas_info->write_lock);
719 static int _mm_evas_renderer_create(mm_evas_info **evas_info)
721 mm_evas_info *ptr = NULL;
725 ptr = g_malloc0(sizeof(mm_evas_info));
728 LOGE("Cannot allocate memory for evas_info\n");
732 LOGD("Success create evas_info(%p)", *evas_info);
734 g_mutex_init(&ptr->mp_lock);
735 g_mutex_init(&ptr->idx_lock);
736 g_mutex_init(&ptr->write_lock);
737 g_mutex_init(&ptr->evas_lock);
738 g_cond_init(&ptr->evas_cond[COND_RETRIEVE]);
739 g_cond_init(&ptr->evas_cond[COND_DESTROY]);
743 return MM_ERROR_NONE;
747 return MM_ERROR_EVASRENDER_NO_FREE_SPACE;
750 static int _mm_evas_renderer_destroy(mm_evas_info **evas_info)
752 int ret = MM_ERROR_NONE;
753 mm_evas_info *ptr = (mm_evas_info *)*evas_info;
757 MMEVAS_RETURN_VAL_IF_FAIL(ptr, MM_ERROR_EVASRENDER_NOT_INITIALIZED);
759 LOGD("finalize evas_info %p", ptr);
761 ret = _mm_evas_renderer_reset(ptr, FALSE);
762 if (ret != MM_ERROR_NONE)
763 LOGE("_mm_evas_renderer_reset is failed");
765 g_mutex_clear(&ptr->mp_lock);
766 g_mutex_clear(&ptr->idx_lock);
767 g_mutex_clear(&ptr->write_lock);
768 g_mutex_clear(&ptr->evas_lock);
769 g_cond_clear(&ptr->evas_cond[COND_RETRIEVE]);
770 g_cond_clear(&ptr->evas_cond[COND_DESTROY]);
780 static int _mm_evas_renderer_set_info(mm_evas_info *evas_info, Evas_Object *eo)
786 MMEVAS_RETURN_VAL_IF_FAIL(evas_info, MM_ERROR_EVASRENDER_NOT_INITIALIZED);
787 MMEVAS_RETURN_VAL_IF_FAIL(eo, MM_ERROR_EVASRENDER_INVALID_ARGUMENT);
789 g_mutex_lock(&evas_info->idx_lock);
791 LOGD("set evas_info");
793 for (i = 0; i < MAX_PACKET_NUM; i++) {
794 evas_info->pkt_info[i].packet = NULL;
795 evas_info->pkt_info[i].tbm_surf = NULL;
796 evas_info->pkt_info[i].prev_idx = -1;
799 evas_info->flush_all_packets = FALSE;
800 evas_info->rendering_info_changed = FALSE;
801 evas_info->video_size_changed = FALSE;
802 evas_info->w = evas_info->h = 0;
803 evas_info->cur_idx = -1;
804 evas_info->dst_roi.x = evas_info->dst_roi.y = evas_info->dst_roi.w = evas_info->dst_roi.h = 0;
805 evas_info->is_set_roi_area = FALSE;
806 evas_info->is_set_resize_cb = FALSE;
807 evas_info->display_geometry_method = evas_info->pre_display_geometry_method = DISP_GEO_METHOD_LETTER_BOX;
809 evas_info->epipe = ecore_pipe_add((Ecore_Pipe_Cb) _evas_pipe_cb, evas_info);
810 if (!evas_info->epipe) {
811 LOGE("pipe is not created");
812 g_mutex_unlock(&evas_info->idx_lock);
813 return MM_ERROR_EVASRENDER_INTERNAL;
815 LOGD("created pipe %p", evas_info->epipe);
817 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);
818 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);
820 g_mutex_unlock(&evas_info->idx_lock);
824 return MM_ERROR_NONE;
827 static int _mm_evas_renderer_reset(mm_evas_info *evas_info, gboolean is_sub_thread)
829 int ret = MM_ERROR_NONE;
833 MMEVAS_RETURN_VAL_IF_FAIL(evas_info, MM_ERROR_EVASRENDER_NOT_INITIALIZED);
834 MMEVAS_RETURN_VAL_IF_FAIL(evas_info->eo, MM_ERROR_EVASRENDER_NOT_INITIALIZED);
836 g_mutex_lock(&evas_info->mp_lock);
838 evas_info->eo_size.x = evas_info->eo_size.y = evas_info->eo_size.w = evas_info->eo_size.h = 0;
839 evas_info->dst_roi.x = evas_info->dst_roi.y = evas_info->dst_roi.w = evas_info->dst_roi.h = 0;
840 evas_info->w = evas_info->h = 0;
842 if (evas_info->flush_buffer)
843 _mm_evas_renderer_release_flush_buffer(evas_info);
846 evas_info->eo = NULL;
848 if (evas_info->epipe) {
849 LOGD("pipe %p will be deleted", evas_info->epipe);
850 ecore_pipe_del(evas_info->epipe);
851 evas_info->epipe = NULL;
855 g_mutex_lock(&evas_info->evas_lock);
856 LOGD("send signal[COND_DESTROY]");
857 g_cond_signal(&evas_info->evas_cond[COND_DESTROY]);
858 g_mutex_unlock(&evas_info->evas_lock);
861 g_mutex_unlock(&evas_info->mp_lock);
868 static void _mm_evas_renderer_update_geometry(mm_evas_info *evas_info)
870 gint video_width = 0;
871 gint video_height = 0;
872 rect_info result = { 0 };
877 MMEVAS_RETURN_IF_FAIL(evas_info);
878 MMEVAS_RETURN_IF_FAIL(evas_info->eo); //need to check evas object
880 /* get rotate angle with content orientaion */
881 _mm_evas_renderer_update_rotate_angle(evas_info);
885 video_width = evas_info->w;
886 video_height = evas_info->h;
888 /* Only SWAP is needed for result coordination calculation */
889 if (evas_info->rotate_angle == DEGREE_90 || evas_info->rotate_angle == DEGREE_270) {
890 SWAP(video_width, video_height);
891 #ifdef _INTERNAL_DEBUG_
892 LOGD("swapped width %d, height %d", video_width, video_height);
895 LOGD("eo size (x:%d,y:%d,w:%d,h:%d)", evas_info->eo_size.x, evas_info->eo_size.y, evas_info->eo_size.w, evas_info->eo_size.h);
896 LOGD("video size (w:%d,h:%d)", video_width, video_height);
898 if (evas_info->display_geometry_method == DISP_GEO_METHOD_CUSTOM_ROI && evas_info->is_set_roi_area == FALSE) {
899 disp_mode = evas_info->pre_display_geometry_method;
900 LOGD("ROI area isn't set. and use previous display geometry method(%d)", disp_mode);
902 disp_mode = evas_info->display_geometry_method;
905 case DISP_GEO_METHOD_LETTER_BOX:
906 /* set black padding for letter box mode */
907 LOGD("letter box mode");
908 evas_info->ratio = (float) evas_info->w / evas_info->h; /* need to set original video ratio */
909 result.w = evas_info->eo_size.w;
910 result.h = evas_info->eo_size.h;
912 case DISP_GEO_METHOD_ORIGIN_SIZE:
913 LOGD("origin size mode");
914 evas_info->ratio = 0;
915 /* set coordinate for each case */
916 result.x = (evas_info->eo_size.w - video_width) / 2;
917 result.y = (evas_info->eo_size.h - video_height) / 2;
918 result.w = video_width;
919 result.h = video_height;
921 case DISP_GEO_METHOD_FULL_SCREEN:
922 LOGD("full screen mode");
923 evas_info->ratio = 0;
924 result.w = evas_info->eo_size.w;
925 result.h = evas_info->eo_size.h;
927 case DISP_GEO_METHOD_CROPPED_FULL_SCREEN:
928 LOGD("cropped full screen mode");
929 evas_info->ratio = 0;
930 float eo_ratio = (float)evas_info->eo_size.w / evas_info->eo_size.h;
931 float video_ratio = (float)video_width / video_height;
932 /* compare evas object's ratio with video's */
933 if (eo_ratio > video_ratio) {
934 result.w = evas_info->eo_size.w;
935 result.h = evas_info->eo_size.w * video_height / video_width;
936 result.y = -(result.h - evas_info->eo_size.h) / 2;
938 result.w = evas_info->eo_size.h * video_width / video_height;
939 result.h = evas_info->eo_size.h;
940 result.x = -(result.w - evas_info->eo_size.w) / 2;
943 case DISP_GEO_METHOD_ORIGIN_SIZE_OR_LETTER_BOX:
944 /* if video size is smaller than evas object's, it will be set to origin size mode */
945 if ((evas_info->eo_size.w > video_width) && (evas_info->eo_size.h > video_height)) {
946 LOGD("origin size or letter box mode : set origin size mode");
947 evas_info->ratio = 0;
948 result.x = (evas_info->eo_size.w - video_width) / 2;
949 result.y = (evas_info->eo_size.h - video_height) / 2;
950 result.w = video_width;
951 result.h = video_height;
953 LOGD("origin size or letter box mode : set letter box mode");
954 evas_info->ratio = (float) evas_info->w / evas_info->h; /* need to set original video ratio */
955 result.w = evas_info->eo_size.w;
956 result.h = evas_info->eo_size.h;
959 case DISP_GEO_METHOD_CUSTOM_ROI:
960 LOGD("custom roi mode");
961 if (evas_info->is_set_roi_area == FALSE) {
962 LOGW("ROI Area isn't set");
965 /* roi need to set -1 */
966 evas_info->ratio = -1;
967 result.x = evas_info->dst_roi.x;
968 result.y = evas_info->dst_roi.y;
969 result.w = evas_info->dst_roi.w;
970 result.h = evas_info->dst_roi.h;
971 if (evas_info->rotate_angle == DEGREE_90 || evas_info->rotate_angle == DEGREE_270)
972 SWAP(result.w, result.h);
975 LOGW("unsupported mode.");
979 evas_info->result.x = result.x;
980 evas_info->result.y = result.y;
981 evas_info->result.w = result.w;
982 evas_info->result.h = result.h;
984 LOGD("geometry result [%d, %d, %d, %d]", evas_info->result.x, evas_info->result.y, evas_info->result.w, evas_info->result.h);
989 static int _mm_evas_renderer_retrieve_all_packets(mm_evas_info *evas_info, bool keep_screen)
991 int ret = MM_ERROR_NONE;
992 pid_t pid = getpid();
993 pid_t tid = syscall(SYS_gettid);
994 gint64 end_time = g_get_monotonic_time() + SIGNAL_TIMEOUT * G_TIME_SPAN_SECOND;
998 MMEVAS_RETURN_VAL_IF_FAIL(evas_info, MM_ERROR_EVASRENDER_NOT_INITIALIZED);
1000 /* this API can be call by sub thread */
1001 LOGD("pid [%d], tid [%d]", pid, tid);
1003 /* make flush buffer */
1005 ret = _mm_evas_renderer_make_flush_buffer(evas_info);
1006 evas_info->keep_screen = keep_screen;
1008 if (pid == tid) { /* API call by main thread */
1009 /* flush all packet */
1010 g_mutex_lock(&evas_info->mp_lock);
1011 ret = _flush_all_packets(evas_info);
1012 if (ret != MM_ERROR_NONE)
1013 LOGE("flushing packets is failed");
1014 g_mutex_unlock(&evas_info->mp_lock);
1016 /* flush all packet */
1017 g_mutex_lock(&evas_info->evas_lock);
1018 ret = _mm_evas_pipe_write(evas_info, UPDATE_FLUSH_BUFFER);
1019 if (ret == MM_ERROR_NONE) {
1020 if (!g_cond_wait_until(&evas_info->evas_cond[COND_RETRIEVE], &evas_info->evas_lock, end_time)) {
1022 LOGW("timeout: main thread is busy, App need to handle main thread well.");
1025 g_mutex_unlock(&evas_info->evas_lock);
1033 /* make buffer for copying */
1034 static int _mm_evas_renderer_make_flush_buffer(mm_evas_info *evas_info)
1038 MMEVAS_RETURN_VAL_IF_FAIL(evas_info, MM_ERROR_EVASRENDER_NOT_INITIALIZED);
1040 if (evas_info->cur_idx == -1) {
1041 /* it is deemed ERROR_NONE, because this API is used only for retrieving buffers */
1042 LOGW("there is no remaining buffer");
1043 return MM_ERROR_NONE;
1045 media_packet_h packet = evas_info->pkt_info[evas_info->cur_idx].packet;
1046 MMEVAS_RETURN_VAL_IF_FAIL(packet, MM_ERROR_EVASRENDER_INTERNAL);
1048 flush_info *flush_buffer = NULL;
1049 tbm_surface_h src_tbm_surf = NULL;
1050 tbm_surface_info_s src_info = {0};
1051 tbm_surface_info_s dst_info = {0};
1052 int ret = MM_ERROR_NONE;
1054 if (evas_info->flush_buffer)
1055 _mm_evas_renderer_release_flush_buffer(evas_info);
1058 flush_buffer = (flush_info *)malloc(sizeof(flush_info));
1059 if (flush_buffer == NULL) {
1060 LOGE("malloc is failed");
1063 memset(flush_buffer, 0x0, sizeof(flush_info));
1065 ret = media_packet_get_tbm_surface(packet, &src_tbm_surf);
1066 if (ret != MEDIA_PACKET_ERROR_NONE || !src_tbm_surf) {
1067 LOGW("get_tbm_surface is failed");
1071 /* get src buffer info */
1072 if (tbm_surface_map(src_tbm_surf, TBM_OPTION_READ|TBM_OPTION_WRITE, &src_info)) {
1073 LOGW("[src] map is failed");
1077 /* create tbm surface */
1078 flush_buffer->tbm_surf = tbm_surface_create(evas_info->w, evas_info->h, src_info.format);
1080 if (!flush_buffer->tbm_surf) {
1081 LOGE("tbm_surf is NULL!!");
1082 if (tbm_surface_unmap(src_tbm_surf))
1083 LOGW("[src] unmap is failed");
1087 /* get dst buffer info */
1088 if (tbm_surface_map(flush_buffer->tbm_surf, TBM_OPTION_READ|TBM_OPTION_WRITE, &dst_info)) {
1089 LOGW("[dst] map is failed");
1090 if (tbm_surface_unmap(src_tbm_surf))
1091 LOGW("[src] unmap is failed");
1095 if (src_info.size > dst_info.size) {
1096 LOGE("src size(%d), dst size(%d)!!!", src_info.size, dst_info.size);
1097 if (tbm_surface_unmap(src_tbm_surf))
1098 LOGW("[src] unmap is failed");
1099 if (tbm_surface_unmap(flush_buffer->tbm_surf))
1100 LOGW("[dst] unmap is failed");
1105 switch (src_info.format) {
1106 case TBM_FORMAT_YUV420:
1107 memcpy(dst_info.planes[0].ptr, src_info.planes[0].ptr, src_info.planes[0].size);
1108 memcpy(dst_info.planes[1].ptr, src_info.planes[1].ptr, src_info.planes[1].size);
1109 memcpy(dst_info.planes[2].ptr, src_info.planes[2].ptr, src_info.planes[2].size);
1111 case TBM_FORMAT_NV12:
1112 memcpy(dst_info.planes[0].ptr, src_info.planes[0].ptr, src_info.planes[0].stride * src_info.height);
1113 memcpy(dst_info.planes[1].ptr, src_info.planes[1].ptr, src_info.planes[0].stride * src_info.height / 2);
1115 case TBM_FORMAT_YUYV:
1116 memcpy(dst_info.planes[0].ptr, src_info.planes[0].ptr, src_info.planes[0].size);
1119 LOGW("unsupported format");
1123 #ifdef _INTERNAL_DEBUG_
1124 __dump_surf(flush_buffer->tbm_surf);
1126 LOGD("flush_buffer dump is done");
1129 if (tbm_surface_unmap(src_tbm_surf))
1130 LOGW("[src] unmap is failed");
1131 if (tbm_surface_unmap(flush_buffer->tbm_surf))
1132 LOGW("[dst] unmap is failed");
1134 LOGW("copy is done. tbm surface : %p", flush_buffer->tbm_surf);
1135 evas_info->flush_buffer = flush_buffer;
1139 return MM_ERROR_NONE;
1143 if (flush_buffer->tbm_surf) {
1144 tbm_surface_destroy(flush_buffer->tbm_surf);
1145 flush_buffer->tbm_surf = NULL;
1149 flush_buffer = NULL;
1151 return MM_ERROR_EVASRENDER_INTERNAL;
1154 /* release flush buffer */
1155 static void _mm_evas_renderer_release_flush_buffer(mm_evas_info *evas_info)
1159 MMEVAS_RETURN_IF_FAIL(evas_info);
1161 LOGW("release FLUSH BUFFER start");
1162 if (evas_info->flush_buffer->bo)
1163 evas_info->flush_buffer->bo = NULL;
1165 if (evas_info->flush_buffer->tbm_surf) {
1166 tbm_surface_destroy(evas_info->flush_buffer->tbm_surf);
1167 evas_info->flush_buffer->tbm_surf = NULL;
1170 LOGW("release FLUSH BUFFER done");
1172 free(evas_info->flush_buffer);
1173 evas_info->flush_buffer = NULL;
1180 static void _mm_evas_renderer_get_video_angle(mm_evas_info *evas_info, int *rotate_angle, int *orientation)
1183 media_packet_h packet = NULL;
1184 media_packet_rotate_method_e org_orient = 0;
1188 MMEVAS_RETURN_IF_FAIL(evas_info);
1189 MMEVAS_RETURN_IF_FAIL(rotate_angle);
1190 MMEVAS_RETURN_IF_FAIL(orientation);
1192 rotate = evas_info->rotate;
1193 LOGD("current rotate value: %d", rotate);
1195 /* Counter clockwise */
1197 case EVAS_IMAGE_ORIENT_0: //0
1200 case EVAS_IMAGE_ORIENT_90: //1
1203 case EVAS_IMAGE_ORIENT_180: //2
1204 *rotate_angle = 180;
1206 case EVAS_IMAGE_ORIENT_270: //3
1207 *rotate_angle = 270;
1210 LOGW("wrong angle type : %d", rotate);
1213 LOGD("check display angle: %d", *rotate_angle);
1215 /* get content orientation */
1216 packet = evas_info->pkt_info[evas_info->cur_idx].packet;
1217 MMEVAS_RETURN_IF_FAIL(packet);
1219 media_packet_get_rotate_method(packet, &org_orient);
1220 LOGE("get content orientation : %d", org_orient);
1222 /* Counter clockwise */
1223 switch (org_orient) {
1224 case MEDIA_PACKET_ROTATE_IDENTITY: //0
1227 case MEDIA_PACKET_ROTATE_90: //1
1230 case MEDIA_PACKET_ROTATE_180: //2
1233 case MEDIA_PACKET_ROTATE_270: //3
1237 LOGW("wrong angle type : %d", org_orient);
1240 LOGD("check orientation: %d", *orientation);
1245 static void _mm_evas_renderer_update_rotate_angle(mm_evas_info *evas_info)
1248 int required_angle = 0; /* Angle required for straight view */
1249 int rotate_angle = 0;
1250 int orientation = 0;
1254 MMEVAS_RETURN_IF_FAIL(evas_info);
1256 _mm_evas_renderer_get_video_angle(evas_info, &rotate_angle, &orientation);
1258 required_angle = 360 - orientation;
1259 rotate_angle = (rotate_angle + required_angle) % 360;
1261 /* chech if supported or not */
1262 if (rotate_angle % 90) {
1263 LOGD("not supported rotation angle = %d", rotate_angle);
1267 switch (rotate_angle) {
1269 evas_info->rotate_angle = EVAS_IMAGE_ORIENT_0;
1272 evas_info->rotate_angle = EVAS_IMAGE_ORIENT_90;
1275 evas_info->rotate_angle = EVAS_IMAGE_ORIENT_180;
1278 evas_info->rotate_angle = EVAS_IMAGE_ORIENT_270;
1282 LOGD("setting rotation angle : %d", evas_info->rotate_angle);
1287 void mm_evas_renderer_write(media_packet_h packet, void *data)
1291 mm_evas_info *handle = (mm_evas_info *)data;
1292 int ret = MEDIA_PACKET_ERROR_NONE;
1294 tbm_surface_h tbm_surf;
1297 MMEVAS_RETURN_IF_FAIL(packet);
1298 LOGD("packet [%p]", packet);
1301 LOGE("handle %p is NULL", handle);
1302 goto INVALID_HANDLE;
1304 g_mutex_lock(&handle->idx_lock);
1306 ret = media_packet_has_tbm_surface_buffer(packet, &has);
1307 if (ret != MEDIA_PACKET_ERROR_NONE) {
1308 LOGW("has_tbm_surface is failed");
1311 /* FIXME: when setCaps occurs, _get_video_size should be called */
1312 /* currently we are always checking it */
1313 if (has && _get_video_size(packet, handle)) {
1314 /* Attention! if this error occurs, we need to consider managing buffer */
1315 if (handle->sent_buffer_cnt > 3) {
1316 LOGE("too many buffers are not released %d", handle->sent_buffer_cnt);
1319 ret = media_packet_get_tbm_surface(packet, &tbm_surf);
1320 if (ret != MEDIA_PACKET_ERROR_NONE || !tbm_surf) {
1321 LOGW("get_tbm_surface is failed");
1325 /* find new index for current packet */
1326 new_idx = _find_empty_index(handle);
1330 #ifdef _INTERNAL_DEBUG_
1332 if ((g_cnt_in%10 == 0) && (g_cnt_in < 500))
1333 ret2 = __dump_pkt(packet, handle->w, handle->h);
1336 LOGW("__dump_pkt() is failed");
1340 /* save previous index */
1341 handle->pkt_info[new_idx].prev_idx = handle->cur_idx;
1342 handle->pkt_info[new_idx].packet = packet;
1343 handle->pkt_info[new_idx].tbm_surf = tbm_surf;
1344 handle->cur_idx = new_idx;
1345 handle->sent_buffer_cnt++;
1346 LOGD("sent packet %d", handle->sent_buffer_cnt);
1348 ret = _mm_evas_pipe_write(handle, UPDATE_TBM_SURF);
1349 if (ret != MM_ERROR_NONE) {
1350 handle->pkt_info[new_idx].packet = NULL;
1351 handle->pkt_info[new_idx].tbm_surf = NULL;
1352 handle->pkt_info[new_idx].prev_idx = -1;
1353 handle->cur_idx = handle->pkt_info[new_idx].prev_idx;
1354 handle->sent_buffer_cnt--;
1355 LOGW("Failed to ecore_pipe_write() for updating tbm surf\n");
1359 LOGW("no tbm_surf");
1362 g_mutex_unlock(&handle->idx_lock);
1368 g_mutex_unlock(&handle->idx_lock);
1369 /* destroy media_packet immediately */
1370 g_mutex_lock(&handle->mp_lock);
1371 LOGD("can't write. destroy packet [%p]", packet);
1372 if (handle && handle->packet_rendered_cb) {
1373 handle->packet_rendered_cb(packet, handle->packet_rendered_cb_user);
1375 if (media_packet_destroy(packet) != MEDIA_PACKET_ERROR_NONE)
1376 LOGE("media_packet_destroy failed %p", packet);
1379 g_mutex_unlock(&handle->mp_lock);
1382 LOGD("can't write. destroy packet [%p]", packet);
1383 if (media_packet_destroy(packet) != MEDIA_PACKET_ERROR_NONE)
1384 LOGE("media_packet_destroy failed %p", packet);
1389 int mm_evas_renderer_create(MMHandleType *handle, Evas_Object *eo)
1391 int ret = MM_ERROR_NONE;
1392 mm_evas_info *evas_info = NULL;
1396 MMEVAS_RETURN_VAL_IF_FAIL(handle, MM_ERROR_EVASRENDER_INVALID_ARGUMENT);
1397 MMEVAS_RETURN_VAL_IF_FAIL(eo, MM_ERROR_EVASRENDER_INVALID_ARGUMENT);
1399 ret = _mm_evas_renderer_create(&evas_info);
1400 if (ret != MM_ERROR_NONE) {
1401 LOGE("fail to create evas_info");
1404 ret = _mm_evas_renderer_set_info(evas_info, eo);
1405 if (ret != MM_ERROR_NONE) {
1406 LOGE("fail to init evas_info");
1407 if (_mm_evas_renderer_destroy(&evas_info) != MM_ERROR_NONE)
1408 LOGE("fail to destroy evas_info");
1412 *handle = (MMHandleType)evas_info;
1414 return MM_ERROR_NONE;
1417 int mm_evas_renderer_destroy(MMHandleType *handle)
1419 int ret = MM_ERROR_NONE;
1420 mm_evas_info *evas_info = (mm_evas_info *)*handle;
1424 MMEVAS_RETURN_VAL_IF_FAIL(evas_info, MM_ERROR_EVASRENDER_NOT_INITIALIZED);
1426 ret = _mm_evas_renderer_destroy(&evas_info);
1427 if (ret != MM_ERROR_NONE) {
1428 LOGE("fail to destroy evas_info");
1435 return MM_ERROR_NONE;
1438 int mm_evas_renderer_set_visible(MMHandleType handle, bool visible)
1440 int ret = MM_ERROR_NONE;
1441 mm_evas_info *evas_info = (mm_evas_info *)handle;
1445 MMEVAS_RETURN_VAL_IF_FAIL(evas_info, MM_ERROR_EVASRENDER_NOT_INITIALIZED);
1447 if (evas_info->visible != visible) {
1448 evas_info->visible = visible;
1449 ret = _mm_evas_pipe_write(evas_info, UPDATE_VISIBILITY);
1457 int mm_evas_renderer_get_visible(MMHandleType handle, bool *visible)
1459 mm_evas_info *evas_info = (mm_evas_info *)handle;
1463 MMEVAS_RETURN_VAL_IF_FAIL(evas_info, MM_ERROR_EVASRENDER_NOT_INITIALIZED);
1465 *visible = evas_info->visible;
1469 return MM_ERROR_NONE;
1472 int mm_evas_renderer_set_rotation(MMHandleType handle, int rotate)
1474 int ret = MM_ERROR_NONE;
1475 mm_evas_info *evas_info = (mm_evas_info *)handle;
1480 MMEVAS_RETURN_VAL_IF_FAIL(evas_info, MM_ERROR_EVASRENDER_NOT_INITIALIZED);
1484 value = EVAS_IMAGE_ORIENT_0;
1487 value = EVAS_IMAGE_ORIENT_90;
1490 value = EVAS_IMAGE_ORIENT_180;
1493 value = EVAS_IMAGE_ORIENT_270;
1496 return MM_ERROR_EVASRENDER_INVALID_ARGUMENT;
1499 if (evas_info->rotate != value) {
1500 evas_info->update_needed = TRUE;
1501 evas_info->rotate = value;
1502 evas_info->rendering_info_changed = TRUE;
1504 ret = _mm_evas_pipe_write(evas_info, UPDATE_TBM_SURF);
1512 int mm_evas_renderer_get_rotation(MMHandleType handle, int *rotate)
1514 mm_evas_info *evas_info = (mm_evas_info *)handle;
1518 MMEVAS_RETURN_VAL_IF_FAIL(evas_info, MM_ERROR_EVASRENDER_NOT_INITIALIZED);
1520 switch (evas_info->rotate) {
1521 case EVAS_IMAGE_ORIENT_0:
1524 case EVAS_IMAGE_ORIENT_90:
1525 *rotate = DEGREE_90;
1527 case EVAS_IMAGE_ORIENT_180:
1528 *rotate = DEGREE_180;
1530 case EVAS_IMAGE_ORIENT_270:
1531 *rotate = DEGREE_270;
1534 return MM_ERROR_EVASRENDER_INVALID_ARGUMENT;
1539 return MM_ERROR_NONE;
1542 int mm_evas_renderer_set_geometry(MMHandleType handle, int mode)
1544 int ret = MM_ERROR_NONE;
1545 mm_evas_info *evas_info = (mm_evas_info *)handle;
1549 MMEVAS_RETURN_VAL_IF_FAIL(evas_info, MM_ERROR_EVASRENDER_NOT_INITIALIZED);
1550 MMEVAS_RETURN_VAL_IF_FAIL(mode >= DISP_GEO_METHOD_LETTER_BOX && mode < DISP_GEO_METHOD_NUM, MM_ERROR_EVASRENDER_INVALID_ARGUMENT);
1552 if (evas_info->display_geometry_method != mode) {
1553 evas_info->update_needed = TRUE;
1554 evas_info->pre_display_geometry_method = evas_info->display_geometry_method;
1555 evas_info->display_geometry_method = mode;
1556 evas_info->rendering_info_changed = TRUE;
1558 /* ecore_pipe_write is needed, because of setting ratio for letterbox mode */
1559 ret = _mm_evas_pipe_write(evas_info, UPDATE_TBM_SURF);
1567 int mm_evas_renderer_get_geometry(MMHandleType handle, int *mode)
1569 mm_evas_info *evas_info = (mm_evas_info *)handle;
1573 MMEVAS_RETURN_VAL_IF_FAIL(evas_info, MM_ERROR_EVASRENDER_NOT_INITIALIZED);
1575 *mode = evas_info->display_geometry_method;
1579 return MM_ERROR_NONE;
1582 int mm_evas_renderer_set_roi_area(MMHandleType handle, int x, int y, int w, int h)
1584 int ret = MM_ERROR_NONE;
1585 mm_evas_info *evas_info = (mm_evas_info *)handle;
1589 MMEVAS_RETURN_VAL_IF_FAIL(evas_info, MM_ERROR_EVASRENDER_NOT_INITIALIZED);
1591 if (w <= 0 || h <= 0) {
1592 LOGE("invalid resolution w(%d), h(%d)", w, h);
1593 return MM_ERROR_EVASRENDER_INVALID_ARGUMENT;
1596 if (evas_info->dst_roi.x != x || evas_info->dst_roi.y != y
1597 || evas_info->dst_roi.w != w || evas_info->dst_roi.h != h) {
1598 evas_info->dst_roi.x = x;
1599 evas_info->dst_roi.y = y;
1600 evas_info->dst_roi.w = w;
1601 evas_info->dst_roi.h = h;
1602 evas_info->update_needed = TRUE;
1603 evas_info->is_set_roi_area = TRUE;
1604 evas_info->rendering_info_changed = TRUE;
1606 /* pipe_write could be needed because ratio can be changed on pause state */
1607 ret = _mm_evas_pipe_write(evas_info, UPDATE_TBM_SURF);
1615 int mm_evas_renderer_get_roi_area(MMHandleType handle, int *x, int *y, int *w, int *h)
1617 mm_evas_info *evas_info = (mm_evas_info *)handle;
1621 MMEVAS_RETURN_VAL_IF_FAIL(evas_info, MM_ERROR_EVASRENDER_NOT_INITIALIZED);
1623 *x = evas_info->dst_roi.x;
1624 *y = evas_info->dst_roi.y;
1625 *w = evas_info->dst_roi.w;
1626 *h = evas_info->dst_roi.h;
1630 return MM_ERROR_NONE;
1633 int mm_evas_renderer_set_flip(MMHandleType handle, int flip)
1635 int ret = MM_ERROR_NONE;
1636 mm_evas_info *evas_info = (mm_evas_info *)handle;
1641 MMEVAS_RETURN_VAL_IF_FAIL(evas_info, MM_ERROR_EVASRENDER_NOT_INITIALIZED);
1645 value = EVAS_IMAGE_ORIENT_NONE;
1647 case FLIP_HORIZONTAL:
1648 value = EVAS_IMAGE_FLIP_HORIZONTAL;
1651 value = EVAS_IMAGE_FLIP_VERTICAL;
1654 value = EVAS_IMAGE_ORIENT_180;
1657 return MM_ERROR_EVASRENDER_INVALID_ARGUMENT;
1660 if (evas_info->flip != value) {
1661 evas_info->update_needed = TRUE;
1662 evas_info->flip = value;
1665 ret = _mm_evas_pipe_write(evas_info, UPDATE_TBM_SURF);
1672 int mm_evas_renderer_get_flip(MMHandleType handle, int *flip)
1674 mm_evas_info *evas_info = (mm_evas_info *)handle;
1678 MMEVAS_RETURN_VAL_IF_FAIL(evas_info, MM_ERROR_EVASRENDER_NOT_INITIALIZED);
1680 switch (evas_info->flip) {
1681 case EVAS_IMAGE_ORIENT_NONE:
1684 case EVAS_IMAGE_FLIP_HORIZONTAL:
1685 *flip = FLIP_HORIZONTAL;
1687 case EVAS_IMAGE_FLIP_VERTICAL:
1688 *flip = FLIP_VERTICAL;
1690 case EVAS_IMAGE_ORIENT_180:
1694 return MM_ERROR_EVASRENDER_INVALID_ARGUMENT;
1699 return MM_ERROR_NONE;
1702 int mm_evas_renderer_retrieve_all_packets(MMHandleType handle, bool keep_screen)
1704 int ret = MM_ERROR_NONE;
1705 mm_evas_info *evas_info = (mm_evas_info*) handle;
1709 MMEVAS_RETURN_VAL_IF_FAIL(evas_info, MM_ERROR_EVASRENDER_NOT_INITIALIZED);
1711 ret = _mm_evas_renderer_retrieve_all_packets(evas_info, keep_screen);
1718 int mm_evas_renderer_set_packet_rendered_callback(MMHandleType handle, mm_evas_renderer_media_packet_rendered_cb callback, void *user_data)
1720 mm_evas_info *evas_info = (mm_evas_info*) handle;
1724 MMEVAS_RETURN_VAL_IF_FAIL(evas_info, MM_ERROR_EVASRENDER_NOT_INITIALIZED);
1726 evas_info->packet_rendered_cb = callback;
1727 evas_info->packet_rendered_cb_user = user_data;
1729 LOGW("set rendered callback %p, user_data %p", evas_info->packet_rendered_cb, evas_info->packet_rendered_cb_user);
1733 return MM_ERROR_NONE;