tizen 2.3.1 release
[framework/multimedia/gst-plugins-ext0.10.git] / evasimagesink / src / gstevasimagesink.c
1 /*
2  * evasimagesink
3  *
4  * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact: Sangchul Lee <sc11.lee@samsung.com>
7  *
8  * This library is free software; you can redistribute it and/or modify it under
9  * the terms of the GNU Lesser General Public License as published by the
10  * Free Software Foundation; either version 2.1 of the License, or (at your option)
11  * any later version.
12  *
13  * This library is distributed in the hope that it will be useful, but WITHOUT ANY
14  * WARRANTY; without even the implied warranty of MERCHANTABILITY or
15  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
16  * License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public License
19  * along with this library; if not, write to the Free Software Foundation, Inc., 51
20  * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21  *
22  */
23
24 /**
25  * SECTION:element-evasimagesink
26  * Gstreamer Evas Video Sink - draw video on the given Evas Image Object
27  */
28
29 #ifdef HAVE_CONFIG_H
30 #include <config.h>
31 #endif
32
33 #include <sys/types.h>
34 #include <gst/gst.h>
35 #include <gst/video/video.h>
36 #include <gst/video/gstvideosink.h>
37 #include <Evas.h>
38 #include <Ecore.h>
39 #include <Ecore_X.h>
40
41 #include "gstevasimagesink.h"
42
43 #define CAP_WIDTH "width"
44 #define CAP_HEIGHT "height"
45 //#define DUMP_IMG
46
47 GST_DEBUG_CATEGORY_STATIC (gst_evas_image_sink_debug);
48 #define GST_CAT_DEFAULT gst_evas_image_sink_debug
49
50 /* Enumerations */
51 enum
52 {
53         /* FILL ME */
54         LAST_SIGNAL
55 };
56
57 enum
58 {
59         PROP_0,
60         PROP_EVAS_OBJECT,
61         PROP_EVAS_OBJECT_SHOW,
62 #ifdef USE_TBM_SURFACE
63         PROP_ROTATE_ANGLE,
64         PROP_DISPLAY_GEOMETRY_METHOD,
65         PROP_ENABLE_FLUSH_BUFFER,
66         PROP_FLIP
67 #endif
68 };
69
70 enum
71 {
72         UPDATE_FALSE,
73         UPDATE_TRUE
74 };
75
76 #define COLOR_DEPTH 4
77 #define GL_X11_ENGINE "gl_x11"
78 #define DO_RENDER_FROM_FIMC 1
79 #define SIZE_FOR_UPDATE_VISIBILITY sizeof(gchar)
80
81 #ifdef USE_TBM_SURFACE
82 #define MAX_ECOREPIPE_BUFFER_CNT 4
83 #define DEBUGLOG_DEFAULT_COUNT 8
84 #define SIZE_FOR_NATIVE_INDEX sizeof(gint)
85
86 /* max channel count *********************************************************/
87 #define SCMN_IMGB_MAX_PLANE         (4)
88
89 /* image buffer definition ***************************************************
90
91     +------------------------------------------+ ---
92     |                                          |  ^
93     |     a[], p[]                             |  |
94     |     +---------------------------+ ---    |  |
95     |     |                           |  ^     |  |
96     |     |<---------- w[] ---------->|  |     |  |
97     |     |                           |  |     |  |
98     |     |                           |        |
99     |     |                           |  h[]   |  e[]
100     |     |                           |        |
101     |     |                           |  |     |  |
102     |     |                           |  |     |  |
103     |     |                           |  v     |  |
104     |     +---------------------------+ ---    |  |
105     |                                          |  v
106     +------------------------------------------+ ---
107
108     |<----------------- s[] ------------------>|
109 */
110
111 typedef struct
112 {
113         /* width of each image plane */
114         int w[SCMN_IMGB_MAX_PLANE];
115         /* height of each image plane */
116         int h[SCMN_IMGB_MAX_PLANE];
117         /* stride of each image plane */
118         int s[SCMN_IMGB_MAX_PLANE];
119         /* elevation of each image plane */
120         int e[SCMN_IMGB_MAX_PLANE];
121         /* user space address of each image plane */
122         void *a[SCMN_IMGB_MAX_PLANE];
123         /* physical address of each image plane, if needs */
124         void *p[SCMN_IMGB_MAX_PLANE];
125         /* color space type of image */
126         int cs;
127         /* left postion, if needs */
128         int x;
129         /* top position, if needs */
130         int y;
131         /* to align memory */
132         int __dummy2;
133         /* arbitrary data */
134         int data[16];
135         /* dma buf fd */
136         int fd[SCMN_IMGB_MAX_PLANE];
137         /* buffer share method */
138         int buf_share_method;
139         /* Y plane size in case of ST12 */
140         int y_size;
141         /* UV plane size in case of ST12 */
142         int uv_size;
143         /* Tizen buffer object */
144         void *bo[SCMN_IMGB_MAX_PLANE];
145         /* JPEG data */
146         void *jpeg_data;
147         /* JPEG size */
148         int jpeg_size;
149         /* TZ memory buffer */
150         int tz_enable;
151 } SCMN_IMGB;
152 #endif
153
154 #define EVASIMAGESINK_SET_EVAS_OBJECT_EVENT_CALLBACK( x_evas_image_object, x_usr_data ) \
155 do \
156 { \
157         if (x_evas_image_object) { \
158                 GST_LOG("object callback add"); \
159                 evas_object_event_callback_add (x_evas_image_object, EVAS_CALLBACK_DEL, evas_callback_del_event, x_usr_data); \
160                 evas_object_event_callback_add (x_evas_image_object, EVAS_CALLBACK_RESIZE, evas_callback_resize_event, x_usr_data); \
161         } \
162 }while(0)
163
164 #define EVASIMAGESINK_UNSET_EVAS_OBJECT_EVENT_CALLBACK( x_evas_image_object ) \
165 do \
166 { \
167         if (x_evas_image_object) { \
168                 GST_LOG("object callback del"); \
169                 evas_object_event_callback_del (x_evas_image_object, EVAS_CALLBACK_DEL, evas_callback_del_event); \
170                 evas_object_event_callback_del (x_evas_image_object, EVAS_CALLBACK_RESIZE, evas_callback_resize_event); \
171         } \
172 }while(0)
173
174 #ifdef USE_TBM_SURFACE
175 #define EVASIMAGESINK_SET_EVAS_EVENT_CALLBACK( x_evas, x_usr_data ) \
176 do \
177 { \
178         if (x_evas) { \
179                 GST_DEBUG("callback add... evas_callback_render_pre.. evas : %p esink : %p", x_evas, x_usr_data); \
180                 evas_event_callback_add (x_evas, EVAS_CALLBACK_RENDER_PRE, evas_callback_render_pre, x_usr_data); \
181         } \
182 }while(0)
183
184 #define EVASIMAGESINK_UNSET_EVAS_EVENT_CALLBACK( x_evas ) \
185 do \
186 { \
187         if (x_evas) { \
188                 GST_DEBUG("callback del... evas_callback_render_pre"); \
189                 evas_event_callback_del (x_evas, EVAS_CALLBACK_RENDER_PRE, evas_callback_render_pre); \
190         } \
191 }while(0)
192 #endif
193
194 GMutex *instance_lock;
195 guint instance_lock_count;
196
197 static inline gboolean
198 is_evas_image_object (Evas_Object *obj)
199 {
200         const char *type;
201         if (!obj) {
202                 return FALSE;
203         }
204         type = evas_object_type_get (obj);
205         if (!type) {
206                 return FALSE;
207         }
208         if (strcmp (type, "image") == 0) {
209                 return TRUE;
210         }
211         return FALSE;
212 }
213
214 #ifdef USE_TBM_SURFACE
215 gint
216 gst_evas_image_sink_ref_count (GstBuffer * buf)
217 {
218         return GST_OBJECT_REFCOUNT_VALUE(GST_BUFFER_CAST(buf));
219 }
220 #endif
221
222 /* the capabilities of the inputs.
223  *
224  * BGRx format
225  */
226 static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE ("sink",
227                 GST_PAD_SINK,
228                 GST_PAD_ALWAYS,
229 #ifdef USE_FIMCC
230                 GST_STATIC_CAPS (GST_VIDEO_CAPS_BGRx));
231 #endif
232 #ifdef USE_TBM_SURFACE
233                 GST_STATIC_CAPS(GST_VIDEO_CAPS_YUV ("I420") ";"
234                                                 GST_VIDEO_CAPS_YUV ("NV12") ";"
235                                                 GST_VIDEO_CAPS_YUV ("SN12"))
236 );
237 #endif
238 GST_BOILERPLATE (GstEvasImageSink, gst_evas_image_sink, GstVideoSink, GST_TYPE_VIDEO_SINK);
239
240 static void gst_evas_image_sink_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec);
241 static void gst_evas_image_sink_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec);
242 static gboolean gst_evas_image_sink_set_caps (GstBaseSink *base_sink, GstCaps *caps);
243 static GstFlowReturn gst_evas_image_sink_show_frame (GstVideoSink *video_sink, GstBuffer *buf);
244 static gboolean gst_evas_image_sink_event (GstBaseSink *sink, GstEvent *event);
245 static GstStateChangeReturn gst_evas_image_sink_change_state (GstElement *element, GstStateChange transition);
246 static void evas_callback_del_event (void *data, Evas *e, Evas_Object *obj, void *event_info);
247 static void evas_callback_resize_event (void *data, Evas *e, Evas_Object *obj, void *event_info);
248 #ifdef USE_TBM_SURFACE
249 static void evas_callback_render_pre (void *data, Evas *e, void *event_info);
250 static GstFlowReturn gst_esink_epipe_reset(GstEvasImageSink *esink);
251 static gboolean gst_esink_make_flush_buffer(GstEvasImageSink *esink);
252 static void _release_flush_buffer(GstEvasImageSink *esink);
253 static void gst_evas_image_sink_update_geometry (GstEvasImageSink *esink, GstVideoRectangle *result);
254 static void gst_evas_image_sink_apply_geometry (GstEvasImageSink *esink);
255 #endif
256 #ifdef DUMP_IMG
257 int util_write_rawdata (const char *file, const void *data, unsigned int size);
258 int g_cnt = 0;
259 #endif
260
261 static void
262 gst_evas_image_sink_base_init (gpointer gclass)
263 {
264         GstElementClass *element_class = GST_ELEMENT_CLASS (gclass);
265
266         gst_element_class_set_details_simple (element_class,
267                 "EvasImageSink",
268                 "VideoSink",
269                 "Video sink element for evas image object",
270                 "Samsung Electronics <www.samsung.com>");
271
272         gst_element_class_add_pad_template (element_class,
273         gst_static_pad_template_get (&sink_factory));
274 }
275
276 static void
277 gst_evas_image_sink_class_init (GstEvasImageSinkClass *klass)
278 {
279         GObjectClass *gobject_class;
280         GstBaseSinkClass *gstbasesink_class;
281         GstVideoSinkClass *gstvideosink_class;
282         GstElementClass *gstelement_class;
283
284         gobject_class = (GObjectClass *) klass;
285         gstbasesink_class = GST_BASE_SINK_CLASS (klass);
286         gstvideosink_class = GST_VIDEO_SINK_CLASS (klass);
287         gstelement_class = (GstElementClass *) klass;
288
289         gobject_class->set_property = gst_evas_image_sink_set_property;
290         gobject_class->get_property = gst_evas_image_sink_get_property;
291
292         g_object_class_install_property (gobject_class, PROP_EVAS_OBJECT,
293                 g_param_spec_pointer ("evas-object", "Destination Evas Object", "Destination evas image object", G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
294         g_object_class_install_property (gobject_class, PROP_EVAS_OBJECT_SHOW,
295                 g_param_spec_boolean ("visible", "Show Evas Object", "When disabled, evas object does not show", TRUE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
296 #ifdef USE_TBM_SURFACE
297         g_object_class_install_property(gobject_class, PROP_ROTATE_ANGLE,
298                 g_param_spec_int("rotate", "Rotate angle", "Rotate angle of display output", DEGREE_0, DEGREE_NUM, DEGREE_0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
299         g_object_class_install_property(gobject_class, PROP_DISPLAY_GEOMETRY_METHOD,
300                 g_param_spec_int("display-geometry-method", "Display geometry method",
301                         "Geometrical method for display", DISP_GEO_METHOD_LETTER_BOX, DISP_GEO_METHOD_NUM, DISP_GEO_METHOD_LETTER_BOX, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
302         g_object_class_install_property (gobject_class, PROP_ENABLE_FLUSH_BUFFER,
303                 g_param_spec_boolean("enable-flush-buffer", "Enable flush buffer mechanism",
304                         "Enable flush buffer mechanism when state change(PAUSED_TO_READY)",
305                         TRUE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
306         g_object_class_install_property(gobject_class, PROP_FLIP,
307                 g_param_spec_int("flip", "Display flip",
308                         "Flip for display", FLIP_NONE, FLIP_NUM, FLIP_NONE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
309 #endif
310         gstvideosink_class->show_frame = GST_DEBUG_FUNCPTR (gst_evas_image_sink_show_frame);
311         gstbasesink_class->set_caps = GST_DEBUG_FUNCPTR (gst_evas_image_sink_set_caps);
312         gstbasesink_class->event = GST_DEBUG_FUNCPTR (gst_evas_image_sink_event);
313         gstelement_class->change_state = GST_DEBUG_FUNCPTR(gst_evas_image_sink_change_state);
314 }
315
316 static void
317 gst_evas_image_sink_fini (gpointer data, GObject *obj)
318 {
319         GST_DEBUG ("[ENTER]");
320
321         GstEvasImageSink *esink = GST_EVASIMAGESINK (obj);
322         if (!esink) {
323                 return;
324         }
325 #ifdef USE_FIMCC
326         if (esink->oldbuf) {
327                 gst_buffer_unref (esink->oldbuf);
328         }
329 #endif
330
331         if (esink->eo) {
332 #ifdef USE_TBM_SURFACE
333                 EVASIMAGESINK_UNSET_EVAS_EVENT_CALLBACK (evas_object_evas_get(esink->eo));
334                 GST_DEBUG("unset EVASIMAGESINK_UNSET_EVAS_EVENT_CALLBACK esink : %p, esink->eo : %x", esink, esink->eo);
335 #endif
336                 EVASIMAGESINK_UNSET_EVAS_OBJECT_EVENT_CALLBACK (esink->eo);
337                 GST_DEBUG("unset EVASIMAGESINK_UNSET_EVAS_OBJECT_EVENT_CALLBACK esink : %p, esink->eo : %x", esink, esink->eo);
338                 evas_object_image_data_set(esink->eo, NULL);
339         }
340 #ifdef USE_TBM_SURFACE
341         if (esink->display_buffer_lock) {
342                 g_mutex_free (esink->display_buffer_lock);
343                 esink->display_buffer_lock = NULL;
344         }
345         if (esink->flow_lock) {
346                 g_mutex_free (esink->flow_lock);
347                 esink->flow_lock = NULL;
348         }
349         esink->eo = NULL;
350         esink->epipe = NULL;
351 #endif
352         g_mutex_lock (instance_lock);
353         instance_lock_count--;
354         g_mutex_unlock (instance_lock);
355         if (instance_lock_count == 0) {
356                 g_mutex_free (instance_lock);
357                 instance_lock = NULL;
358         }
359
360         GST_DEBUG ("[LEAVE]");
361 }
362
363 #ifdef USE_TBM_SURFACE
364 static void
365 gst_evas_image_sink_reset (GstEvasImageSink *esink)
366 {
367         int i = 0;
368         tbm_bo_handle bo_handle;
369
370         GST_DEBUG("gst_evas_image_sink_reset start");
371
372         g_mutex_lock(esink->display_buffer_lock);
373
374         for(i=0; i<NATIVE_BUFFER_NUM; i++)
375         {
376                 if(esink->displaying_buffer[i].tbm_surf)
377                 {
378                         tbm_surface_destroy(esink->displaying_buffer[i].tbm_surf);
379                         esink->displaying_buffer[i].tbm_surf = NULL;
380                 }
381                 if(esink->displaying_buffer[i].buffer)
382                 {
383                         if(esink->displaying_buffer[i].ref_count)
384                         {
385                                 if(esink->displaying_buffer[i].bo) {
386                                         bo_handle = tbm_bo_map(esink->displaying_buffer[i].bo, TBM_DEVICE_CPU, TBM_OPTION_READ|TBM_OPTION_WRITE);
387                                         if (!bo_handle.ptr) {
388                                                 GST_WARNING("failed to map bo [%p]", esink->displaying_buffer[i].bo);
389                                         }
390                                         else
391                                                 tbm_bo_unmap(esink->displaying_buffer[i].bo);
392                                 }
393                                 else
394                                         GST_WARNING("there is no bo information. so skip to map bo");
395
396                                 GST_WARNING("[reset] unreffing gst %p", esink->displaying_buffer[i].buffer);
397
398                                 while(esink->displaying_buffer[i].ref_count)
399                                 {
400                                         GST_WARNING("index[%d]'s buffer ref count=%d",i,gst_evas_image_sink_ref_count (esink->displaying_buffer[i].buffer));
401                                         esink->displaying_buffer[i].ref_count--;
402                                         gst_buffer_unref(esink->displaying_buffer[i].buffer);
403                                 }
404                         }
405                         esink->displaying_buffer[i].buffer = NULL;
406                 }
407                 if(esink->displaying_buffer[i].bo)
408                         esink->displaying_buffer[i].bo = NULL;
409         }
410         esink->prev_buf = NULL;
411         esink->prev_index = -1;
412         esink->cur_index = -1;
413
414         esink->eo_size.x = esink->eo_size.y =
415         esink->eo_size.w = esink->eo_size.h = 0;
416         esink->use_ratio = FALSE;
417         esink->sent_buffer_cnt = 0;
418
419         g_mutex_unlock(esink->display_buffer_lock);
420 }
421 #endif
422
423 #ifdef USE_FIMCC
424 static void
425 evas_image_sink_cb_pipe (void *data, void *buffer, unsigned int nbyte)
426 #endif
427 #ifdef USE_TBM_SURFACE
428 static void
429 evas_image_sink_cb_pipe (void *data, int *buffer_index, unsigned int nbyte)
430 #endif
431 {
432         GstEvasImageSink *esink = data;
433 #ifdef USE_FIMCC
434         GstBuffer *buf;
435         void *img_data;
436 #endif
437         GST_DEBUG ("[ENTER]");
438         if (!esink || !esink->eo) {
439                 GST_WARNING ("esink : %p, or eo is NULL returning", esink);
440                 return;
441         }
442         GST_LOG("esink : %p, esink->eo : %x", esink, esink->eo);
443         if (nbyte == SIZE_FOR_UPDATE_VISIBILITY) {
444                 if(!esink->object_show) {
445                         evas_object_hide(esink->eo);
446                         GST_INFO ("object hide..");
447                 } else {
448                         evas_object_show(esink->eo);
449                         GST_INFO ("object show..");
450                 }
451                 GST_DEBUG ("[LEAVE]");
452                 return;
453         }
454 #ifdef USE_FIMCC
455         if (!buffer || nbyte != sizeof (GstBuffer *)) {
456                 GST_WARNING ("buffer %p, nbyte : %d, sizeof(GstBuffer *) : %d", buffer, nbyte, sizeof (GstBuffer *));
457                 return;
458         }
459 #endif
460 #ifdef USE_TBM_SURFACE
461         int index = 0;
462         index = *buffer_index;
463         if ((index<0 || index>=NATIVE_BUFFER_NUM) || nbyte != SIZE_FOR_NATIVE_INDEX)    {
464                 GST_WARNING ("index : %d, nbyte : %d", index, nbyte);
465                 return;
466         }
467 #endif
468         if (GST_STATE(esink) < GST_STATE_PAUSED) {
469                 GST_WARNING ("WRONG-STATE(%d) for rendering, skip this frame", GST_STATE(esink));
470                 return;
471         }
472
473 #ifdef USE_FIMCC
474         memcpy (&buf, buffer, sizeof (GstBuffer *));
475         if (!buf) {
476                 GST_ERROR ("There is no buffer");
477                 return;
478         }
479         if (esink->present_data_addr == -1) {
480                 /* if present_data_addr is -1, we don't use this member variable */
481         } else if (esink->present_data_addr != DO_RENDER_FROM_FIMC) {
482                 GST_WARNING ("skip rendering this buffer, present_data_addr:%d, DO_RENDER_FROM_FIMC:%d", esink->present_data_addr, DO_RENDER_FROM_FIMC);
483                 return;
484         }
485 #endif
486 #ifdef USE_TBM_SURFACE
487         g_mutex_lock(esink->display_buffer_lock);
488         if(esink->tbm_surface_format == TBM_FORMAT_NV12) {
489                 if (!esink->displaying_buffer[index].tbm_surf) {
490                         GST_ERROR("the index's nbuffer was already NULL, so return");
491                         g_mutex_unlock(esink->display_buffer_lock);
492                         return;
493                 }
494                 GST_LOG("received (bo %p, gst %p) index num : %d", esink->displaying_buffer[index].bo, esink->displaying_buffer[index].buffer, index);
495         } else if(esink->tbm_surface_format == TBM_FORMAT_YUV420) {
496                 GST_LOG("received (bo %p) index num : %d", esink->displaying_buffer[index].bo, index);
497         }
498
499         Evas_Native_Surface surf;
500         surf.type = EVAS_NATIVE_SURFACE_TBM;
501         surf.version = EVAS_NATIVE_SURFACE_VERSION;
502         surf.data.tizen.buffer = esink->displaying_buffer[index].tbm_surf;
503         surf.data.tizen.rot = esink->rotate_angle;
504         surf.data.tizen.flip = esink->flip;
505
506         GST_LOG("received (bo %p, gst %p) index num : %d", esink->displaying_buffer[index].bo, esink->displaying_buffer[index].buffer, index);
507
508         GstVideoRectangle result = {0};
509
510         evas_object_geometry_get(esink->eo, &esink->eo_size.x, &esink->eo_size.y, &esink->eo_size.w, &esink->eo_size.h);
511         if (!esink->eo_size.w || !esink->eo_size.h) {
512                 GST_ERROR ("there is no information for evas object size");
513                 g_mutex_unlock(esink->display_buffer_lock);
514                 return;
515         }
516         gst_evas_image_sink_update_geometry(esink, &result);
517         if(!result.w || !result.h)
518         {
519                 GST_ERROR("no information about geometry (%d, %d)", result.w, result.h);
520                 g_mutex_unlock(esink->display_buffer_lock);
521                 return;
522         }
523
524         if(esink->use_ratio)
525         {
526                 surf.data.tizen.ratio = (float) esink->w / esink->h;
527                 GST_LOG("set ratio for letter mode");
528         }
529         evas_object_size_hint_align_set(esink->eo, EVAS_HINT_FILL, EVAS_HINT_FILL);
530         evas_object_size_hint_weight_set(esink->eo, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
531         if ( !esink->is_evas_object_size_set && esink->w > 0 && esink->h > 0) {
532                 evas_object_image_size_set(esink->eo, esink->w, esink->h);
533                 esink->is_evas_object_size_set = TRUE;
534         }
535 #ifdef DUMP_IMG
536         int ret = 0;
537         char file_name[128];
538         char *dump_data;
539         guint size = esink->w*esink->h + (esink->w/2*esink->h/2)*2; //this size is for I420 format
540         tbm_bo_handle vaddr_dump;
541         if(g_cnt<20)
542         {
543                 GST_WARNING ("DUMP IMG_%2.2d : buffer size(%d)", g_cnt, size);
544                 sprintf(file_name, "DUMP_IMG_%2.2d.dump", g_cnt++);
545
546                 dump_data = g_malloc(size);
547                 vaddr_dump = tbm_bo_map(esink->displaying_buffer[index].bo, TBM_DEVICE_CPU, TBM_OPTION_READ|TBM_OPTION_WRITE);
548                 if (vaddr_dump.ptr) {
549                         tbm_bo_unmap(esink->displaying_buffer[index].bo);
550                 }
551                 memcpy (dump_data, vaddr_dump.ptr, size);
552
553                 ret = util_write_rawdata(file_name, dump_data, size);
554                 if (ret) {
555                 GST_ERROR_OBJECT (esink, "util_write_rawdata() failed");
556                 }
557                 g_free(dump_data);
558         }
559 #endif
560     evas_object_image_native_surface_set(esink->eo, &surf);
561         GST_DEBUG("native surface set finish");
562
563         if(result.x || result.y)
564                 GST_LOG("coordinate x, y (%d, %d) for locating video to center", result.x, result.y);
565         evas_object_image_fill_set(esink->eo, result.x, result.y, result.w, result.h);
566
567         evas_object_image_pixels_dirty_set(esink->eo, EINA_TRUE);
568         GST_DEBUG_OBJECT (esink, "GEO_METHOD : src(%dx%d), dst(%dx%d), dst_x(%d), dst_y(%d), rotate(%d), flip(%d)",
569                 esink->w, esink->h, esink->eo_size.w, esink->eo_size.h, esink->eo_size.x, esink->eo_size.y, esink->rotate_angle, esink->flip);
570
571         /* unref previous buffer */
572         if(esink->tbm_surface_format == TBM_FORMAT_NV12) {
573                 if(esink->prev_buf && esink->displaying_buffer[esink->prev_index].ref_count)
574                 {
575                         GST_DEBUG("before index %d's ref_count =%d, gst_buf %p",esink->prev_index,esink->displaying_buffer[esink->prev_index].ref_count, esink->prev_buf);
576                         esink->displaying_buffer[esink->prev_index].ref_count--;
577                         GST_DEBUG("after index %d's ref_count =%d, gst_buf %p",esink->prev_index,esink->displaying_buffer[esink->prev_index].ref_count, esink->prev_buf);
578                         /* Print debug log for 8 frame */
579                         if(esink->debuglog_cnt_ecoreCbPipe > 0)
580                         {
581                                 GST_WARNING("(%d) ecore_cb_pipe unref index[%d] .. gst_buf %p", DEBUGLOG_DEFAULT_COUNT-(esink->debuglog_cnt_ecoreCbPipe), esink->prev_index, esink->prev_buf);
582                                 esink->debuglog_cnt_ecoreCbPipe--;
583                         }
584                         if (esink->sent_buffer_cnt == MAX_ECOREPIPE_BUFFER_CNT)
585                                 GST_WARNING("sent buffer cnt 4->3 so skip will be stop");
586
587                         esink->sent_buffer_cnt--;
588                         GST_DEBUG("prev gst_buffer %p's unref Start!!", esink->prev_buf);
589                         gst_buffer_unref(esink->prev_buf);
590                         GST_DEBUG("prev gst_buffer %p's unref End!!", esink->prev_buf);
591                 } else {
592                         GST_DEBUG("ref_count=%d  unref prev gst_buffer %p", esink->displaying_buffer[esink->prev_index].ref_count,esink->prev_buf);
593                 }
594
595                 GST_DEBUG("Current gst_buf %p and index=%d is overwrited to Prev gst_buf %p & index %d",
596                         esink->displaying_buffer[index].buffer, index, esink->prev_buf, esink->prev_index );
597                 esink->prev_buf = esink->displaying_buffer[index].buffer;
598                 esink->prev_index = index;
599         }else if(esink->tbm_surface_format == TBM_FORMAT_YUV420) {
600                 /* Print debug log for 8 frame */
601                 if(esink->debuglog_cnt_ecoreCbPipe > 0)
602                 {
603                         GST_WARNING("(%d) ecore_cb_pipe set native surface [%d]  tbm_surf[%p]",
604                                 DEBUGLOG_DEFAULT_COUNT-(esink->debuglog_cnt_ecoreCbPipe), index, esink->displaying_buffer[index].tbm_surf);
605                         esink->debuglog_cnt_ecoreCbPipe--;
606                 }
607                 if (esink->sent_buffer_cnt == MAX_ECOREPIPE_BUFFER_CNT)
608                         GST_WARNING("sent buffer cnt 4->3 so skip will be stop");
609
610                 esink->sent_buffer_cnt--;
611         }
612 #endif
613 #ifdef USE_FIMCC
614         if ( !esink->is_evas_object_size_set && esink->w > 0 && esink->h > 0) {
615                         evas_object_image_size_set (esink->eo, esink->w, esink->h);
616                         GST_DEBUG("evas_object_image_size_set(), width(%d),height(%d)", esink->w, esink->h);
617                         esink->is_evas_object_size_set = TRUE;
618         }
619         if (esink->gl_zerocopy) {
620                 img_data = evas_object_image_data_get (esink->eo, EINA_TRUE);
621                 if (!img_data || !GST_BUFFER_DATA(buf)) {
622                         GST_WARNING ("Cannot get image data from evas object or cannot get gstbuffer data");
623                         evas_object_image_data_set(esink->eo, img_data);
624                 } else {
625                         GST_DEBUG ("img_data(%x), GST_BUFFER_DATA(buf):%x, esink->w(%d),esink->h(%d), esink->eo(%x)",img_data,GST_BUFFER_DATA(buf),esink->w,esink->h,esink->eo);
626                         memcpy (img_data, GST_BUFFER_DATA (buf), esink->w * esink->h * COLOR_DEPTH);
627                         evas_object_image_pixels_dirty_set (esink->eo, 1);
628                         evas_object_image_data_set(esink->eo, img_data);
629                 }
630                 gst_buffer_unref (buf);
631         } else {
632                 GST_DEBUG ("GST_BUFFER_DATA(buf):%x, esink->eo(%x)",GST_BUFFER_DATA(buf),esink->eo);
633                 evas_object_image_data_set (esink->eo, GST_BUFFER_DATA (buf));
634                 evas_object_image_pixels_dirty_set (esink->eo, 1);
635                 if (esink->oldbuf) {
636                         gst_buffer_unref(esink->oldbuf);
637                 }
638                 esink->oldbuf = buf;
639         }
640 #endif
641 #ifdef USE_TBM_SURFACE
642         g_mutex_unlock(esink->display_buffer_lock);
643 #endif
644         GST_DEBUG ("[LEAVE]");
645 }
646 #ifdef USE_TBM_SURFACE
647 static void
648 gst_evas_image_sink_update_geometry (GstEvasImageSink *esink, GstVideoRectangle *result)
649 {
650         if (!esink || !esink->eo) {
651                 GST_WARNING("there is no esink");
652                 return;
653         }
654
655         result->x = 0;
656         result->y = 0;
657
658         switch (esink->display_geometry_method)
659         {
660                 case DISP_GEO_METHOD_LETTER_BOX:        // 0
661                         /* set black padding for letter box mode */
662                         GST_DEBUG("letter box mode");
663                         esink->use_ratio = TRUE;
664                         result->w = esink->eo_size.w;
665                         result->h = esink->eo_size.h;
666                         break;
667                 case DISP_GEO_METHOD_ORIGIN_SIZE:       // 1
668                         GST_DEBUG("origin size mode");
669                         esink->use_ratio = FALSE;
670                         /* set coordinate for each case */
671                         result->x = (esink->eo_size.w-esink->w) / 2;
672                         result->y = (esink->eo_size.h-esink->h) / 2;
673                         result->w = esink->w;
674                         result->h = esink->h;
675                         break;
676                 case DISP_GEO_METHOD_FULL_SCREEN:       // 2
677                         GST_DEBUG("full screen mode");
678                         esink->use_ratio = FALSE;
679                         result->w = esink->eo_size.w;
680                         result->h = esink->eo_size.h;
681                         break;
682                 case DISP_GEO_METHOD_CROPPED_FULL_SCREEN:       // 3
683                         GST_DEBUG("cropped full screen mode");
684                         esink->use_ratio = FALSE;
685                         /* compare evas object's ratio with video's */
686                         if((esink->eo_size.w/esink->eo_size.h) > (esink->w/esink->h))
687                         {
688                                 result->w = esink->eo_size.w;
689                                 result->h = esink->eo_size.w * esink->h / esink->w;
690                                 result->y = -(result->h-esink->eo_size.h) / 2;
691                         }
692                         else
693                         {
694                                 result->w = esink->eo_size.h * esink->w / esink->h;
695                                 result->h = esink->eo_size.h;
696                                 result->x = -(result->w-esink->eo_size.w) / 2;
697                         }
698                         break;
699                 case DISP_GEO_METHOD_ORIGIN_SIZE_OR_LETTER_BOX: // 4
700                         GST_DEBUG("origin size or letter box mode");
701                         /* if video size is smaller than evas object's, it will be set to origin size mode */
702                         if((esink->eo_size.w > esink->w) && (esink->eo_size.h > esink->h))
703                         {
704                                 GST_DEBUG("origin size mode");
705                                 esink->use_ratio = FALSE;
706                                 /* set coordinate for each case */
707                                 result->x = (esink->eo_size.w-esink->w) / 2;
708                                 result->y = (esink->eo_size.h-esink->h) / 2;
709                                 result->w = esink->w;
710                                 result->h = esink->h;
711                         }
712                         else
713                         {
714                                 GST_DEBUG("letter box mode");
715                                 esink->use_ratio = TRUE;
716                                 result->w = esink->eo_size.w;
717                                 result->h = esink->eo_size.h;
718                         }
719                         break;
720                 default:
721                         GST_WARNING("unsupported mode.");
722                         break;
723         }
724         GST_DEBUG("geometry result [%d, %d, %d, %d]", result->x, result->y, result->w, result->h);
725 }
726 static void
727 gst_evas_image_sink_apply_geometry (GstEvasImageSink *esink)
728 {
729         if (!esink || !esink->eo) {
730                 GST_WARNING("there is no esink");
731                 return;
732         }
733
734         Evas_Native_Surface *surf = evas_object_image_native_surface_get(esink->eo);
735         GstVideoRectangle result = {0};
736
737         if(surf)
738         {
739                 GST_DEBUG("native surface exists");
740                 surf->data.tizen.rot = esink->rotate_angle;
741                 surf->data.tizen.flip = esink->flip;
742                 evas_object_image_native_surface_set(esink->eo, surf);
743
744                 gst_evas_image_sink_update_geometry(esink, &result);
745
746                 if(esink->use_ratio)
747                 {
748                         surf->data.tizen.ratio = (float) esink->w / esink->h;
749                         GST_LOG("set ratio for letter mode");
750                 }
751
752                 if(result.x || result.y)
753                         GST_LOG("coordinate x, y (%d, %d) for locating video to center", result.x, result.y);
754
755                 evas_object_image_fill_set(esink->eo, result.x, result.y, result.w, result.h);
756         }
757         else
758                 GST_WARNING("there is no surf");
759 }
760 #endif
761
762 static void
763 gst_evas_image_sink_init (GstEvasImageSink *esink, GstEvasImageSinkClass *gclass)
764 {
765         GST_DEBUG ("[ENTER]");
766
767         esink->eo = NULL;
768         esink->epipe = NULL;
769         esink->object_show = FALSE;
770         esink->update_visibility = UPDATE_FALSE;
771         esink->is_evas_object_size_set = FALSE;
772 #ifdef USE_FIMCC
773         esink->gl_zerocopy = FALSE;
774         esink->present_data_addr = -1;
775 #endif
776 #ifdef USE_TBM_SURFACE
777         esink->display_buffer_lock = g_mutex_new ();
778         esink->flow_lock = g_mutex_new ();
779         int i = 0;
780         for (i=0; i<NATIVE_BUFFER_NUM; i++)
781         {
782                 esink->displaying_buffer[i].tbm_surf = NULL;
783                 esink->displaying_buffer[i].buffer = NULL;
784                 esink->displaying_buffer[i].bo = NULL;
785                 esink->displaying_buffer[i].ref_count = 0;
786         }
787         esink->prev_buf = NULL;
788         esink->prev_index = -1;
789         esink->cur_index = -1;
790         esink->enable_flush_buffer = TRUE;
791         esink->need_flush = FALSE;
792         esink->display_geometry_method = DISP_GEO_METHOD_LETTER_BOX;
793         esink->flip = FLIP_NONE;
794         esink->eo_size.x = esink->eo_size.y =
795         esink->eo_size.w = esink->eo_size.h = 0;
796         esink->use_ratio = FALSE;
797         esink->sent_buffer_cnt = 0;
798         esink->debuglog_cnt_showFrame = DEBUGLOG_DEFAULT_COUNT;
799         esink->debuglog_cnt_ecoreCbPipe = DEBUGLOG_DEFAULT_COUNT;
800
801         esink->src_buf_idx = 0;
802         esink->is_buffer_allocated = FALSE;
803 #endif
804         if(!instance_lock) {
805                 instance_lock = g_mutex_new();
806         }
807         g_mutex_lock (instance_lock);
808         instance_lock_count++;
809         g_mutex_unlock (instance_lock);
810
811         g_object_weak_ref (G_OBJECT (esink), gst_evas_image_sink_fini, NULL);
812
813         GST_DEBUG ("[LEAVE]");
814 }
815
816 static void
817 evas_callback_del_event (void *data, Evas *e, Evas_Object *obj, void *event_info)
818 {
819         GST_DEBUG ("[ENTER]");
820
821         GstEvasImageSink *esink = data;
822         if (!esink) {
823                 return;
824         }
825 #ifdef USE_FIMCC
826         if (esink->oldbuf) {
827                 gst_buffer_unref (esink->oldbuf);
828                 esink->oldbuf = NULL;
829         }
830 #endif
831         if (esink->eo) {
832 #ifdef USE_TBM_SURFACE
833                 EVASIMAGESINK_UNSET_EVAS_EVENT_CALLBACK (evas_object_evas_get(esink->eo));
834                 GST_DEBUG("unset EVASIMAGESINK_UNSET_EVAS_EVENT_CALLBACK esink : %p, esink->eo : %x", esink, esink->eo);
835 #endif
836                 EVASIMAGESINK_UNSET_EVAS_OBJECT_EVENT_CALLBACK (esink->eo);
837                 GST_DEBUG("unset EVASIMAGESINK_UNSET_EVAS_OBJECT_EVENT_CALLBACK esink : %p, esink->eo : %x", esink, esink->eo);
838
839                 evas_object_image_data_set(esink->eo, NULL);
840                 esink->eo = NULL;
841         }
842         GST_DEBUG ("[LEAVE]");
843 }
844
845 static void
846 evas_callback_resize_event (void *data, Evas *e, Evas_Object *obj, void *event_info)
847 {
848         int x, y, w, h;
849         x = y = w = h = 0;
850
851         GST_DEBUG ("[ENTER]");
852
853         GstEvasImageSink *esink = data;
854         if (!esink || !esink->eo) {
855                 return;
856         }
857
858         evas_object_geometry_get(esink->eo, &x, &y, &w, &h);
859         if (!w || !h) {
860                 GST_WARNING ("evas object size (w:%d,h:%d) was not set", w, h);
861         } else {
862 #ifdef USE_TBM_SURFACE
863                 esink->eo_size.x = x;
864                 esink->eo_size.y = y;
865                 esink->eo_size.w = w;
866                 esink->eo_size.h = h;
867                 GST_WARNING ("resize (x:%d, y:%d, w:%d, h:%d)", x, y, w, h);
868                 gst_evas_image_sink_apply_geometry(esink);
869 #endif
870 #ifdef USE_FIMCC
871                 evas_object_image_fill_set(esink->eo, 0, 0, w, h);
872                 GST_DEBUG ("evas object fill set (w:%d,h:%d)", w, h);
873 #endif
874         }
875         GST_DEBUG ("[LEAVE]");
876 }
877 #ifdef USE_TBM_SURFACE
878 static void
879 evas_callback_render_pre (void *data, Evas *e, void *event_info)
880 {
881         GstEvasImageSink *esink = data;
882         if (!esink || !esink->eo) {
883                 GST_WARNING("there is no esink info.... esink : %p, or eo is NULL returning", esink);
884                 return;
885         }
886         if(esink->need_flush && esink->flush_buffer)
887         {
888                 g_mutex_lock(esink->display_buffer_lock);
889                 Evas_Native_Surface surf;
890                 GstVideoRectangle result = {0};
891
892                 evas_object_geometry_get(esink->eo, &esink->eo_size.x, &esink->eo_size.y, &esink->eo_size.w, &esink->eo_size.h);
893                 if (!esink->eo_size.w || !esink->eo_size.h) {
894                         GST_ERROR ("there is no information for evas object size");
895                         return;
896                 }
897                 gst_evas_image_sink_update_geometry(esink, &result);
898                 if(!result.w || !result.h)
899                 {
900                         GST_ERROR("no information about geometry (%d, %d)", result.w, result.h);
901                         return;
902                 }
903
904                 if(esink->use_ratio)
905                 {
906                         surf.data.tizen.ratio = (float) esink->w / esink->h;
907                         GST_LOG("set ratio for letter mode");
908                 }
909                 evas_object_size_hint_align_set(esink->eo, EVAS_HINT_FILL, EVAS_HINT_FILL);
910                 evas_object_size_hint_weight_set(esink->eo, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
911                 if ( !esink->is_evas_object_size_set && esink->w > 0 && esink->h > 0) {
912                         evas_object_image_size_set(esink->eo, esink->w, esink->h);
913                         esink->is_evas_object_size_set = TRUE;
914                 }
915
916                 if(result.x || result.y)
917                         GST_LOG("coordinate x, y (%d, %d) for locating video to center", result.x, result.y);
918
919                 evas_object_image_fill_set(esink->eo, result.x, result.y, result.w, result.h);
920
921                 surf.type = EVAS_NATIVE_SURFACE_TBM;
922                 surf.version = EVAS_NATIVE_SURFACE_VERSION;
923                 surf.data.tizen.buffer = esink->flush_buffer->tbm_surf;
924                 surf.data.tizen.rot = esink->rotate_angle;
925                 surf.data.tizen.flip = esink->flip;
926                 GST_DEBUG("use esink->flush buffer->tbm_surf (%p), rotate(%d), flip(%d)",
927                         esink->flush_buffer->tbm_surf, esink->rotate_angle, esink->flip);
928                 evas_object_image_native_surface_set(esink->eo, &surf);
929                 g_mutex_unlock(esink->display_buffer_lock);
930                 esink->need_flush = FALSE;
931         }
932         evas_object_image_pixels_dirty_set (esink->eo, EINA_TRUE);
933         GST_LOG("dirty set finish");
934 }
935
936 static gboolean
937 gst_evas_image_sink_release_source_buffer(GstEvasImageSink *esink)
938 {
939         int i = 0;
940         tbm_bo_handle bo_handle;
941         g_mutex_lock(esink->display_buffer_lock);
942
943         for(i = 0; i < NATIVE_BUFFER_NUM; i++) {
944                 GST_WARNING("[reset] reset gst %p", esink->displaying_buffer[i].buffer);
945                 esink->displaying_buffer[i].bo = NULL;
946                 esink->displaying_buffer[i].tbm_surf = NULL;
947                 esink->displaying_buffer[i].ref_count = 0;
948         }
949
950         for(i = 0; i < SOURCE_BUFFER_NUM; i++) {
951                 if(esink->src_buffer_info[i].bo) {
952                         tbm_bo_unmap(esink->src_buffer_info[i].bo);
953                         esink->src_buffer_info[i].bo = NULL;
954                 }
955
956                 if (esink->src_buffer_info[i].tbm_surf) {
957                         tbm_surface_destroy(esink->src_buffer_info[i].tbm_surf);
958                         esink->src_buffer_info[i].tbm_surf = NULL;
959                 }
960         }
961
962         esink->is_buffer_allocated = FALSE;
963         esink->src_buf_idx = 0;
964         esink->prev_buf = NULL;
965         esink->prev_index = -1;
966         esink->cur_index = -1;
967
968         esink->eo_size.x = esink->eo_size.y =
969         esink->eo_size.w = esink->eo_size.h = 0;
970         esink->use_ratio = FALSE;
971         esink->sent_buffer_cnt = 0;
972
973         g_mutex_unlock(esink->display_buffer_lock);
974
975         return TRUE;
976 }
977
978 static gboolean
979 gst_evas_image_sink_allocate_source_buffer(GstEvasImageSink *esink)
980 {
981         int size = 0;
982         int idx = 0;
983         tbm_bo bo;
984         tbm_bo_handle vaddr;
985         GstFlowReturn ret=GST_FLOW_OK;
986
987         if (esink == NULL) {
988                 GST_ERROR("handle is NULL");
989                 return FALSE;
990         }
991
992         for(idx=0; idx < SOURCE_BUFFER_NUM; idx++) {
993                 if(!esink->src_buffer_info[idx].tbm_surf) {
994                         /* create tbm surface */
995                         esink->src_buffer_info[idx].tbm_surf = tbm_surface_create(esink->w, esink->h, esink->tbm_surface_format);
996                 }
997                 if(!esink->src_buffer_info[idx].tbm_surf)
998                 {
999                         GST_ERROR("tbm_surf is NULL!!");
1000                         goto ALLOC_FAILED;
1001                 }
1002
1003                 /* get bo and size */
1004                 bo = tbm_surface_internal_get_bo(esink->src_buffer_info[idx].tbm_surf, 0);
1005                 size = tbm_bo_size(bo);
1006                 if(!bo || !size)
1007                 {
1008                         GST_ERROR("bo(%p), size(%d)", bo, size);
1009                         goto ALLOC_FAILED;
1010                 }
1011                 esink->src_buffer_info[idx].bo = bo;
1012
1013                 vaddr = tbm_bo_map(bo, TBM_DEVICE_CPU, TBM_OPTION_READ|TBM_OPTION_WRITE);
1014                 if (!vaddr.ptr) {
1015                         GST_WARNING_OBJECT(esink, "get vaddr failed pointer = %p", vaddr.ptr);
1016                         tbm_bo_unmap(bo);
1017                         goto ALLOC_FAILED;
1018                 } else {
1019                         memset (vaddr.ptr, 0x0, size);
1020                         GST_LOG_OBJECT (esink, "tbm_bo_map(VADDR) finished, bo(%p), vaddr(%p)", bo, vaddr.ptr);
1021                 }
1022
1023                 esink->src_buffer_info[idx].usr_addr = vaddr.ptr;
1024
1025                 GST_WARNING_OBJECT(esink, "src buffer index:%d , tbm surface : %p", idx, esink->src_buffer_info[idx].tbm_surf);
1026         }
1027
1028         return TRUE;
1029
1030 ALLOC_FAILED:
1031         gst_evas_image_sink_release_source_buffer(esink);
1032         return FALSE;
1033 }
1034 #endif
1035
1036 static int
1037 evas_image_sink_get_size_from_caps (GstCaps *caps, int *w, int *h)
1038 {
1039         gboolean r;
1040         int width, height;
1041         GstStructure *s;
1042
1043         if (!caps || !w || !h) {
1044                 return -1;
1045         }
1046         s = gst_caps_get_structure (caps, 0);
1047         if (!s) {
1048                 return -1;
1049         }
1050
1051         r = gst_structure_get_int (s, CAP_WIDTH, &width);
1052         if (r == FALSE) {
1053                 GST_DEBUG("fail to get width from caps");
1054                 return -1;
1055         }
1056
1057         r = gst_structure_get_int (s, CAP_HEIGHT, &height);
1058         if (r == FALSE) {
1059                 GST_DEBUG("fail to get height from caps");
1060                 return -1;
1061         }
1062
1063         *w = width;
1064         *h = height;
1065         GST_DEBUG ("size w(%d), h(%d)", width, height);
1066
1067         return 0;
1068 }
1069 #ifdef USE_FIMCC
1070 static gboolean
1071 is_zerocopy_supported (Evas *e)
1072 {
1073         Eina_List *engines, *l;
1074         int cur_id;
1075         int id;
1076         char *name;
1077
1078         if (!e) {
1079                 return FALSE;
1080         }
1081
1082         engines = evas_render_method_list ();
1083         if (!engines) {
1084                 return FALSE;
1085         }
1086
1087         cur_id = evas_output_method_get (e);
1088
1089         EINA_LIST_FOREACH (engines, l, name) {
1090                 id = evas_render_method_lookup (name);
1091                 if (name && id == cur_id) {
1092                         if (!strcmp (name, GL_X11_ENGINE)) {
1093                                 return TRUE;
1094                         }
1095                         break;
1096                 }
1097         }
1098         return FALSE;
1099 }
1100
1101 static int
1102 evas_image_sink_event_parse_data (GstEvasImageSink *esink, GstEvent *event)
1103 {
1104         const GstStructure *st;
1105         guint st_data_addr = 0;
1106         gint st_data_width = 0;
1107         gint st_data_height = 0;
1108
1109         g_return_val_if_fail (event != NULL, FALSE);
1110         g_return_val_if_fail (esink != NULL, FALSE);
1111
1112         if (GST_EVENT_TYPE (event) != GST_EVENT_CUSTOM_DOWNSTREAM_OOB) {
1113                 GST_WARNING ("it's not a custom downstream oob event");
1114                 return -1;
1115         }
1116         st = gst_event_get_structure (event);
1117         if (st == NULL || !gst_structure_has_name (st, "GstStructureForCustomEvent")) {
1118                 GST_WARNING ("structure in a given event is not proper");
1119                 return -1;
1120         }
1121         if (!gst_structure_get_uint (st, "data-addr", &st_data_addr)) {
1122                 GST_WARNING ("parsing data-addr failed");
1123                 return -1;
1124         }
1125         esink->present_data_addr = st_data_addr;
1126
1127         return 0;
1128 }
1129 #endif
1130 static gboolean
1131 gst_evas_image_sink_event (GstBaseSink *sink, GstEvent *event)
1132 {
1133 #ifdef USE_FIMCC
1134         GstEvasImageSink *esink = GST_EVASIMAGESINK (sink);
1135         GstMessage *msg;
1136         gchar *str;
1137 #endif
1138         switch (GST_EVENT_TYPE (event)) {
1139                 case GST_EVENT_FLUSH_START:
1140                         GST_DEBUG ("GST_EVENT_FLUSH_START");
1141                         break;
1142                 case GST_EVENT_FLUSH_STOP:
1143                         GST_DEBUG ("GST_EVENT_FLUSH_STOP");
1144                         break;
1145                 case GST_EVENT_EOS:
1146                         GST_DEBUG ("GST_EVENT_EOS");
1147                         break;
1148 #ifdef USE_FIMCC
1149                 case GST_EVENT_CUSTOM_DOWNSTREAM_OOB:
1150                         if(!evas_image_sink_event_parse_data(esink, event)) {
1151                                 GST_DEBUG ("GST_EVENT_CUSTOM_DOWNSTREAM_OOB, present_data_addr:%x",esink->present_data_addr);
1152                         } else {
1153                                 GST_ERROR ("evas_image_sink_event_parse_data() failed");
1154                         }
1155                         break;
1156 #endif
1157                 default:
1158                         break;
1159         }
1160         if (GST_BASE_SINK_CLASS (parent_class)->event) {
1161                 return GST_BASE_SINK_CLASS (parent_class)->event (sink, event);
1162         } else {
1163                 return TRUE;
1164         }
1165 }
1166
1167 static GstStateChangeReturn
1168 gst_evas_image_sink_change_state (GstElement *element, GstStateChange transition)
1169 {
1170         GstStateChangeReturn ret_state = GST_STATE_CHANGE_SUCCESS;
1171         GstEvasImageSink *esink = NULL;
1172         GstFlowReturn ret=GST_FLOW_OK;
1173         esink = GST_EVASIMAGESINK(element);
1174
1175         if(!esink) {
1176                 GST_ERROR("can not get evasimagesink from element");
1177                 return GST_STATE_CHANGE_FAILURE;
1178         }
1179
1180         switch (transition) {
1181                 case GST_STATE_CHANGE_NULL_TO_READY:
1182                         GST_WARNING ("*** STATE_CHANGE_NULL_TO_READY ***");
1183 #ifdef USE_TBM_SURFACE
1184                         g_mutex_lock (esink->flow_lock);
1185                         if (!is_evas_image_object (esink->eo)) {
1186                                 GST_ERROR_OBJECT (esink, "There is no evas image object..");
1187                                 g_mutex_unlock (esink->flow_lock);
1188                                 return GST_STATE_CHANGE_FAILURE;
1189                         }
1190                         g_mutex_unlock (esink->flow_lock);
1191 #endif
1192                         break;
1193                 case GST_STATE_CHANGE_READY_TO_PAUSED:
1194                         GST_WARNING ("*** STATE_CHANGE_READY_TO_PAUSED ***");
1195                         break;
1196                 case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
1197 #ifdef USE_TBM_SURFACE
1198                         /* Print debug log for 8 frame */
1199                         esink->debuglog_cnt_showFrame = DEBUGLOG_DEFAULT_COUNT;
1200                         esink->debuglog_cnt_ecoreCbPipe = DEBUGLOG_DEFAULT_COUNT;
1201 #endif
1202                         GST_WARNING ("*** STATE_CHANGE_PAUSED_TO_PLAYING ***");
1203                         break;
1204                 default:
1205                         break;
1206         }
1207
1208         ret_state = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
1209
1210         switch (transition) {
1211                 case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
1212                         GST_WARNING ("*** STATE_CHANGE_PLAYING_TO_PAUSED ***");
1213                         break;
1214                 case GST_STATE_CHANGE_PAUSED_TO_READY:
1215                         GST_WARNING ("*** STATE_CHANGE_PAUSED_TO_READY ***");
1216 #ifdef USE_TBM_SURFACE
1217                         Eina_Bool r;
1218                         /* flush buffer, we will copy last buffer to keep image data and reset buffer list */
1219                         GST_WARNING("esink->enable_flush_buffer : %d", esink->enable_flush_buffer);
1220                         if(esink->enable_flush_buffer && esink->tbm_surface_format == TBM_FORMAT_NV12)
1221                         {
1222                                  if (gst_esink_make_flush_buffer(esink) == FALSE) {
1223                                         ret = gst_esink_epipe_reset(esink);
1224                                         if(ret) {
1225                                                 GST_ERROR_OBJECT(esink, "evas epipe reset ret=%d, need to check",ret);
1226                                                 return GST_STATE_CHANGE_FAILURE;
1227                                         }
1228                                         gst_evas_image_sink_reset(esink);
1229                                 }
1230                         }
1231                         else {
1232                                 ret = gst_esink_epipe_reset(esink);
1233                                 if(ret) {
1234                                         GST_ERROR_OBJECT(esink, "evas epipe reset ret=%d, need to check",ret);
1235                                         return GST_STATE_CHANGE_FAILURE;
1236                                 }
1237                                 if(esink->tbm_surface_format == TBM_FORMAT_NV12) {
1238                                         gst_evas_image_sink_reset(esink);
1239                                 } else if(esink->tbm_surface_format == TBM_FORMAT_YUV420) {
1240                                         gst_evas_image_sink_release_source_buffer(esink);
1241                                 }
1242                         }
1243 #endif
1244                         break;
1245                 case GST_STATE_CHANGE_READY_TO_NULL:
1246                         GST_WARNING ("*** STATE_CHANGE_READY_TO_NULL ***");
1247 #ifdef USE_TBM_SURFACE
1248                         if(esink->flush_buffer)
1249                                 _release_flush_buffer(esink);
1250                         EVASIMAGESINK_UNSET_EVAS_EVENT_CALLBACK (evas_object_evas_get(esink->eo));
1251 #endif
1252                         EVASIMAGESINK_UNSET_EVAS_OBJECT_EVENT_CALLBACK (esink->eo);
1253                         if (esink->epipe) {
1254                                 GST_DEBUG("ecore-pipe will delete");
1255                                 ecore_pipe_del (esink->epipe);
1256                                 esink->epipe = NULL;
1257                         }
1258                         break;
1259                 default:
1260                         break;
1261         }
1262
1263         return ret_state;
1264 }
1265
1266 static void
1267 gst_evas_image_sink_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
1268 {
1269         GstEvasImageSink *esink = GST_EVASIMAGESINK (object);
1270         Evas_Object *eo;
1271
1272         g_mutex_lock (instance_lock);
1273
1274         switch (prop_id) {
1275         case PROP_EVAS_OBJECT:
1276                 eo = g_value_get_pointer (value);
1277                 if (is_evas_image_object (eo)) {
1278                         if (eo != esink->eo) {
1279                                 Eina_Bool r;
1280 #ifdef USE_TBM_SURFACE
1281                                 EVASIMAGESINK_UNSET_EVAS_EVENT_CALLBACK (evas_object_evas_get(esink->eo));
1282 #endif
1283                                 /* delete evas object callbacks registrated on a previous evas image object */
1284                                 EVASIMAGESINK_UNSET_EVAS_OBJECT_EVENT_CALLBACK (esink->eo);
1285                                 esink->eo = eo;
1286
1287                                 /* add evas object callbacks on a new evas image object */
1288                                 EVASIMAGESINK_SET_EVAS_OBJECT_EVENT_CALLBACK (esink->eo, esink);
1289 #ifdef USE_TBM_SURFACE
1290                                 GST_WARNING("register render callback [esink : %p, esink->eo : %x]", esink, esink->eo);
1291                                 EVASIMAGESINK_SET_EVAS_EVENT_CALLBACK (evas_object_evas_get(esink->eo), esink);
1292                                 evas_object_geometry_get(esink->eo, &esink->eo_size.x, &esink->eo_size.y, &esink->eo_size.w, &esink->eo_size.h);
1293                                 GST_WARNING ("evas object size (x:%d, y:%d, w:%d, h:%d)", esink->eo_size.x, esink->eo_size.y, esink->eo_size.w, esink->eo_size.h);
1294 #endif
1295 #ifdef USE_FIMCC
1296                                 esink->gl_zerocopy = is_zerocopy_supported (evas_object_evas_get (eo));
1297                                 if (esink->gl_zerocopy) {
1298                                         evas_object_image_content_hint_set (esink->eo, EVAS_IMAGE_CONTENT_HINT_DYNAMIC);
1299                                         GST_DEBUG("Enable gl zerocopy");
1300                                 }
1301 #endif
1302                                 GST_DEBUG("Evas Image Object(%x) is set", esink->eo);
1303                                 esink->is_evas_object_size_set = FALSE;
1304                                 esink->object_show = TRUE;
1305                                 esink->update_visibility = UPDATE_TRUE;
1306                                 if (esink->epipe) {
1307                                         r = ecore_pipe_write (esink->epipe, &esink->update_visibility, SIZE_FOR_UPDATE_VISIBILITY);
1308                                         if (r == EINA_FALSE)  {
1309                                                 GST_WARNING ("Failed to ecore_pipe_write() for updating visibility\n");
1310                                         }
1311                                 }
1312                         }
1313                 } else {
1314                         GST_ERROR ("Cannot set evas-object property: value is not an evas image object");
1315                 }
1316                 break;
1317
1318         case PROP_EVAS_OBJECT_SHOW:
1319         {
1320                 Eina_Bool r;
1321                 esink->object_show = g_value_get_boolean (value);
1322                 if( !is_evas_image_object(esink->eo) ) {
1323                         GST_WARNING ("Cannot apply visible(show-object) property: cannot get an evas object\n");
1324                         break;
1325                 }
1326                 esink->update_visibility = UPDATE_TRUE;
1327                 GST_LOG("esink->update_visibility : %d", esink->update_visibility);
1328                 if (esink->epipe) {
1329                         r = ecore_pipe_write (esink->epipe, &esink->update_visibility, SIZE_FOR_UPDATE_VISIBILITY);
1330                         if (r == EINA_FALSE)  {
1331                                 GST_WARNING ("Failed to ecore_pipe_write() for updating visibility)\n");
1332                         }
1333                 }
1334                 break;
1335         }
1336 #ifdef USE_TBM_SURFACE
1337         case PROP_ROTATE_ANGLE:
1338         {
1339                 int rotate = 0;
1340                 rotate = g_value_get_int (value);
1341                 switch(rotate)
1342                 {
1343                         case DEGREE_0:
1344                                 esink->rotate_angle = 0;
1345                                 break;
1346                         case DEGREE_90:
1347                                 esink->rotate_angle = 90;
1348                                 break;
1349                         case DEGREE_180:
1350                                 esink->rotate_angle = 180;
1351                                 break;
1352                         case DEGREE_270:
1353                                 esink->rotate_angle = 270;
1354                                 break;
1355                         default:
1356                                 break;
1357                 }
1358                 GST_INFO("update rotate_angle : %d", esink->rotate_angle);
1359                 break;
1360         }
1361         case PROP_DISPLAY_GEOMETRY_METHOD:
1362         {
1363                 Eina_Bool r;
1364                 guint geometry = g_value_get_int (value);
1365                 if (esink->display_geometry_method != geometry) {
1366                         esink->display_geometry_method = geometry;
1367                         GST_INFO_OBJECT (esink, "Overlay geometry method update, display_geometry_method(%d)", esink->display_geometry_method);
1368                 }
1369
1370                 g_mutex_lock(esink->display_buffer_lock);
1371
1372                 if(esink->cur_index!=-1 && esink->epipe)
1373                 {
1374                         GST_WARNING("apply property esink->cur_index =%d",esink->cur_index);
1375                         esink->displaying_buffer[esink->cur_index].ref_count++;
1376                         gst_buffer_ref(esink->displaying_buffer[esink->cur_index].buffer);
1377                         esink->sent_buffer_cnt++;
1378                         r = ecore_pipe_write (esink->epipe, &esink->cur_index, SIZE_FOR_NATIVE_INDEX);
1379
1380                         if (r == EINA_FALSE)  {
1381                               GST_WARNING("ecore_pipe_write fail");
1382                                   esink->displaying_buffer[esink->cur_index].ref_count--;
1383                                   gst_buffer_unref(esink->displaying_buffer[esink->cur_index].buffer);
1384                                   esink->sent_buffer_cnt--;
1385                      }
1386                 }
1387                 g_mutex_unlock(esink->display_buffer_lock);
1388                 break;
1389         }
1390         case PROP_ENABLE_FLUSH_BUFFER:
1391                 esink->enable_flush_buffer = g_value_get_boolean(value);
1392                 break;
1393         case PROP_FLIP:
1394         {
1395                 esink->flip = g_value_get_int(value);
1396                 GST_INFO("update flip : %d", esink->flip);
1397                 break;
1398         }
1399 #endif
1400         default:
1401                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1402                 break;
1403         }
1404
1405         g_mutex_unlock (instance_lock);
1406 }
1407
1408 static void
1409 gst_evas_image_sink_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
1410 {
1411         GstEvasImageSink *esink = GST_EVASIMAGESINK (object);
1412
1413         switch (prop_id) {
1414         case PROP_EVAS_OBJECT:
1415                 g_value_set_pointer (value, esink->eo);
1416                 break;
1417         case PROP_EVAS_OBJECT_SHOW:
1418                 g_value_set_boolean (value, esink->object_show);
1419                 break;
1420 #ifdef USE_TBM_SURFACE
1421         case PROP_ROTATE_ANGLE:
1422                 g_value_set_int (value, esink->rotate_angle);
1423                 break;
1424         case PROP_DISPLAY_GEOMETRY_METHOD:
1425                 g_value_set_int (value, esink->display_geometry_method);
1426                 break;
1427         case PROP_ENABLE_FLUSH_BUFFER:
1428                 g_value_set_boolean(value, esink->enable_flush_buffer);
1429                 break;
1430         case PROP_FLIP:
1431                 g_value_set_int(value, esink->flip);
1432                 break;
1433 #endif
1434         default:
1435                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1436                 break;
1437         }
1438 }
1439
1440 static gboolean
1441 gst_evas_image_sink_set_caps (GstBaseSink *base_sink, GstCaps *caps)
1442 {
1443         int r;
1444         int w, h;
1445         GstEvasImageSink *esink = GST_EVASIMAGESINK (base_sink);
1446         GstStructure *structure = NULL;
1447         guint32 format = 0;
1448
1449         esink->is_evas_object_size_set = FALSE;
1450         r = evas_image_sink_get_size_from_caps (caps, &w, &h);
1451         if (!r) {
1452                 esink->w = w;
1453                 esink->h = h;
1454                 GST_DEBUG ("set size w(%d), h(%d)", w, h);
1455         }
1456
1457         structure = gst_caps_get_structure (caps, 0);
1458         if (!structure) {
1459                 return FALSE;
1460         }
1461
1462         if (!gst_structure_get_fourcc (structure, "format", &format)) {
1463                 GST_DEBUG ("format(dst) is not set...it may be rgb series");
1464         }
1465
1466         GST_DEBUG_OBJECT(esink, "source color format is %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (format));
1467
1468 #ifdef USE_TBM_SURFACE
1469         if (format == GST_MAKE_FOURCC('S','N','1','2') || format == GST_MAKE_FOURCC('N','V','1','2') ) {
1470                 esink->tbm_surface_format = TBM_FORMAT_NV12;
1471         } else if (format == GST_MAKE_FOURCC('I','4','2','0')){
1472                 esink->tbm_surface_format = TBM_FORMAT_YUV420;
1473         } else {
1474                 GST_ERROR("cannot parse fourcc format from caps.");
1475                 return FALSE;
1476         }
1477 #endif
1478
1479         return TRUE;
1480 }
1481
1482 static GstFlowReturn
1483 gst_evas_image_sink_show_frame (GstVideoSink *video_sink, GstBuffer *buf)
1484 {
1485         GstEvasImageSink *esink = GST_EVASIMAGESINK (video_sink);
1486         Eina_Bool r;
1487
1488         GST_LOG("[ENTER] show frame");
1489 #ifdef USE_TBM_SURFACE
1490         if (!gst_evas_image_sink_ref_count (buf))
1491         {
1492                 GST_WARNING("ref count is 0.. skip show frame");
1493                 return GST_FLOW_OK;
1494         }
1495 #endif
1496         g_mutex_lock (instance_lock);
1497 #ifdef USE_FIMCC
1498         if (esink->present_data_addr == -1) {
1499                 /* if present_data_addr is -1, we don't use this member variable */
1500         } else if (esink->present_data_addr != DO_RENDER_FROM_FIMC) {
1501                 GST_WARNING ("skip rendering this buffer, present_data_addr:%d, DO_RENDER_FROM_FIMC:%d", esink->present_data_addr, DO_RENDER_FROM_FIMC);
1502                 g_mutex_unlock (instance_lock);
1503                 return GST_FLOW_OK;
1504         }
1505 #endif
1506         if (!esink->epipe) {
1507                 esink->epipe = ecore_pipe_add ((Ecore_Pipe_Cb)evas_image_sink_cb_pipe, esink);
1508                 if (!esink->epipe) {
1509                         GST_ERROR ("ecore-pipe create failed");
1510                         g_mutex_unlock (instance_lock);
1511                         return GST_FLOW_ERROR;
1512                 }
1513                 GST_DEBUG("ecore-pipe create success");
1514         }
1515 #ifdef USE_TBM_SURFACE
1516         int i = 0;
1517         int index = -1;
1518         SCMN_IMGB *scmn_imgb = NULL;
1519         gboolean exist_bo = FALSE;
1520
1521         GST_LOG ("BUF: gst_buf= %p ts= %" GST_TIME_FORMAT " size= %lu,  mallocdata= %p",
1522                 buf, GST_TIME_ARGS(GST_BUFFER_TIMESTAMP (buf)), GST_BUFFER_SIZE (buf), GST_BUFFER_MALLOCDATA(buf));
1523
1524         if(esink->tbm_surface_format == TBM_FORMAT_NV12) {
1525                 /* get received buffer informations */
1526                 scmn_imgb = (SCMN_IMGB *)GST_BUFFER_MALLOCDATA(buf);
1527                 if (!scmn_imgb) {
1528                         GST_WARNING("scmn_imgb is NULL. Skip..." );
1529                         g_mutex_unlock (instance_lock);
1530                         return GST_FLOW_OK;
1531                 }
1532                 if (scmn_imgb->buf_share_method == BUF_SHARE_METHOD_TIZEN_BUFFER)
1533                 {
1534                         /* check whether bo is new or not */
1535                         for(i=0; i<NATIVE_BUFFER_NUM; i++)
1536                         {
1537                                 if(esink->displaying_buffer[i].bo==scmn_imgb->bo[0])
1538                                 {
1539                                         GST_DEBUG("it is already saved bo %p (index num : %d)", esink->displaying_buffer[i].bo, i);
1540                                         index = i;
1541                                         exist_bo = TRUE;
1542                                         break;
1543                                 }
1544                                 else
1545                                         exist_bo = FALSE;
1546                         }
1547                         /* keep bo */
1548                         if(!exist_bo)
1549                         {
1550                                 /* find empty buffer space for indexing */
1551                                 for(i=0; i<NATIVE_BUFFER_NUM; i++)
1552                                 {
1553                                         if(!esink->displaying_buffer[i].bo)
1554                                         {
1555                                                 index = i;
1556                                                 break;
1557                                         }
1558                                 }
1559                                 if(index!=-1)
1560                                 {
1561                                         /* keep informations */
1562                                         esink->displaying_buffer[index].buffer = buf;
1563                                         esink->displaying_buffer[index].bo = scmn_imgb->bo[0];
1564                                         GST_WARNING("TBM bo %p / gst_buf %p", esink->displaying_buffer[index].bo, esink->displaying_buffer[index].buffer);
1565
1566                                         /* create new tbm surface */
1567                                         esink->displaying_buffer[index].tbm_surf = tbm_surface_internal_create_with_bos(esink->w, esink->h,
1568                                           TBM_FORMAT_NV12, esink->displaying_buffer[index].bo, TBM_BO_DEFAULT);
1569                                         if(!esink->displaying_buffer[index].tbm_surf)
1570                                         {
1571                                                 GST_WARNING("there is no tbm surface.. bo : %p,  gst_buf : %p", esink->displaying_buffer[index].bo, esink->displaying_buffer[index].buffer);
1572                                                 g_mutex_unlock (instance_lock);
1573                                                 return GST_FLOW_OK;
1574                                         }
1575
1576                                         GST_WARNING("create tbm surface : %p", esink->displaying_buffer[index].tbm_surf);
1577                                 }
1578                         }
1579                         /* because it has same bo, use existing tbm surface */
1580                         else
1581                         {
1582                                 if(index!=-1)
1583                                 {
1584                                         esink->displaying_buffer[index].buffer = buf;
1585                                         GST_DEBUG("existing tbm surface %p.. bo %p,  gst_buf %p", esink->displaying_buffer[index].tbm_surf, esink->displaying_buffer[index].bo, esink->displaying_buffer[index].buffer);
1586                                         exist_bo = FALSE;
1587                                 }
1588                         }
1589
1590                         /* if it couldn't find proper index */
1591                         if(index == -1)
1592                                 GST_WARNING("all spaces are using!!!");
1593                         else
1594                                 GST_DEBUG("selected buffer index %d", index);
1595
1596                 }
1597                 else if (scmn_imgb->buf_share_method == BUF_SHARE_METHOD_FLUSH_BUFFER)
1598                 {
1599                         /* flush buffer, we will copy last buffer to keep image data and reset buffer list */
1600                         GST_WARNING_OBJECT(esink, "FLUSH_BUFFER: gst_buf= %p ts= %" GST_TIME_FORMAT " size= %lu,  mallocdata= %p",
1601                         buf, GST_TIME_ARGS(GST_BUFFER_TIMESTAMP (buf)), GST_BUFFER_SIZE (buf), GST_BUFFER_MALLOCDATA(buf));
1602                         gst_buffer_ref (buf);
1603                         if (gst_esink_make_flush_buffer(esink))
1604                                 GST_WARNING("made flush buffer");
1605                         gst_buffer_unref (buf);
1606                 }
1607                 else
1608                 {
1609                         GST_ERROR("it is not TBM buffer.. %d", scmn_imgb->buf_share_method);
1610                 }
1611         } else if(esink->tbm_surface_format == TBM_FORMAT_YUV420) {
1612                 static int skip_count_i420=0;
1613                 if(esink->sent_buffer_cnt >= MAX_ECOREPIPE_BUFFER_CNT) {
1614                         if(!(skip_count_i420++%20)) {
1615                                 GST_WARNING("[%d]EA buffer was already sent to ecore pipe, and %d frame skipped", esink->sent_buffer_cnt,skip_count_i420);
1616                         }
1617                         g_mutex_unlock (instance_lock);
1618                         return GST_FLOW_OK;
1619                 }
1620
1621                 if(!esink->is_buffer_allocated) {
1622                         /* Allocate TBM buffer for non-zero copy case */
1623                         if(!gst_evas_image_sink_allocate_source_buffer(esink)) {
1624                                 GST_ERROR_OBJECT(esink, "Buffer allocation failed");
1625                                 g_mutex_unlock (instance_lock);
1626                                 return GST_FLOW_ERROR;
1627                         }
1628                         esink->is_buffer_allocated = TRUE;
1629                 }
1630
1631                 skip_count_i420 = 0; //for skip log in I420
1632
1633                 /* check whether bo is new or not */
1634                 for(i=0; i<NATIVE_BUFFER_NUM; i++) {
1635                         if(esink->displaying_buffer[i].bo == esink->src_buffer_info[esink->src_buf_idx].bo) {
1636                                 GST_DEBUG_OBJECT(esink, "it is already saved bo %p (index num : %d)", esink->displaying_buffer[i].bo, i);
1637                                 index = i;
1638                                 exist_bo = TRUE;
1639                                 break;
1640                         }
1641                         else
1642                                 exist_bo = FALSE;
1643                 }
1644
1645                 /* keep bo */
1646                 if(!exist_bo) {
1647                         /* find empty buffer space for indexing */
1648                         for(i=0; i<NATIVE_BUFFER_NUM; i++) {
1649                                 if(!esink->displaying_buffer[i].bo) {
1650                                         index = i;
1651                                         break;
1652                                 }
1653                         }
1654
1655                         if(index!=-1) {
1656                                 /* keep informations */
1657                                 esink->displaying_buffer[index].bo = esink->src_buffer_info[esink->src_buf_idx].bo;
1658                                 esink->displaying_buffer[index].tbm_surf = esink->src_buffer_info[esink->src_buf_idx].tbm_surf;
1659
1660                                 GST_DEBUG_OBJECT(esink, "gst_buf %p, TBM bo %p.. gst_buf vaddr %p .. src data size(%lu)",
1661                                         buf, esink->displaying_buffer[index].bo, GST_BUFFER_DATA(buf), GST_BUFFER_SIZE(buf));
1662
1663                                 memcpy(esink->src_buffer_info[esink->src_buf_idx].usr_addr, GST_BUFFER_DATA(buf), GST_BUFFER_SIZE(buf));
1664                         }
1665                 } else {
1666                         /* because it has same bo, use existing tbm surface */
1667                         if(index!=-1) {
1668                                 memcpy(esink->src_buffer_info[esink->src_buf_idx].usr_addr, GST_BUFFER_DATA(buf), GST_BUFFER_SIZE(buf));
1669
1670                                 GST_DEBUG_OBJECT(esink, "existing tbm surface %p.. gst_buf %p, bo %p,  gst_buf vaddr %p",
1671                                         esink->displaying_buffer[index].tbm_surf, buf, esink->displaying_buffer[index].bo, GST_BUFFER_DATA(buf));
1672                                 exist_bo = FALSE;
1673                         }
1674                 }
1675
1676                 /* if it couldn't find proper index */
1677                 if(index == -1)
1678                         GST_WARNING_OBJECT(esink, "all spaces are being used!!!");
1679                 else
1680                         GST_DEBUG_OBJECT(esink, "selected buffer index %d", index);
1681
1682         } else {
1683                 GST_ERROR_OBJECT(esink, "unsupported color format");
1684                 g_mutex_unlock (instance_lock);
1685                 return GST_FLOW_ERROR;
1686         }
1687 #endif
1688         if (esink->object_show && index != -1) {
1689 #ifdef USE_FIMCC
1690                 gst_buffer_ref (buf);
1691                 r = ecore_pipe_write (esink->epipe, &buf, sizeof (GstBuffer *));
1692                 if (r == EINA_FALSE)  {
1693                         //add error handling
1694                         GST_WARNING("ecore_pipe_write fail");
1695                         gst_buffer_unref (buf);
1696                 }
1697 #endif
1698 #ifdef USE_TBM_SURFACE
1699                 int old_curidx=esink->cur_index ;
1700                 static int skip_count=0;
1701                 g_mutex_lock(esink->display_buffer_lock);
1702
1703                 if(esink->tbm_surface_format == TBM_FORMAT_NV12 && scmn_imgb->buf_share_method != BUF_SHARE_METHOD_FLUSH_BUFFER) {
1704                         if (esink->sent_buffer_cnt < MAX_ECOREPIPE_BUFFER_CNT) {
1705                                 GST_LOG("[show_frame] before refcount : %d .. gst_buf : %p", gst_evas_image_sink_ref_count (buf), buf);
1706                                 gst_buffer_ref (buf);
1707                                 esink->displaying_buffer[index].ref_count++;
1708                                 esink->cur_index = index;
1709                                 GST_LOG("index %d set refcount increase as %d", index,esink->displaying_buffer[index].ref_count);
1710                                 GST_LOG("[show_frame] after refcount : %d .. gst_buf : %p", gst_evas_image_sink_ref_count (buf), buf);
1711
1712                                 /* Print debug log for 8 frame */
1713                                 if(esink->debuglog_cnt_showFrame > 0)
1714                                 {
1715                                         GST_WARNING("(%d) ecore_pipe_write index[%d]  gst_buf : %p", DEBUGLOG_DEFAULT_COUNT-(esink->debuglog_cnt_showFrame),
1716                                                 esink->cur_index, esink->displaying_buffer[esink->cur_index].buffer);
1717                                         esink->debuglog_cnt_showFrame--;
1718                                 }
1719
1720                                 esink->sent_buffer_cnt++;
1721                                 skip_count =0 ;
1722
1723                                 r = ecore_pipe_write (esink->epipe, &esink->cur_index , SIZE_FOR_NATIVE_INDEX);
1724
1725                                 if (r == EINA_FALSE)  {
1726                                         GST_LOG("[show_frame] before refcount : %d .. gst_buf : %p", gst_evas_image_sink_ref_count (buf), buf);
1727                                         esink->cur_index = old_curidx;
1728                                         if(esink->displaying_buffer[index].ref_count)
1729                                         {
1730                                                 esink->displaying_buffer[index].ref_count--;
1731                                                 esink->sent_buffer_cnt--;
1732                                                 gst_buffer_unref(buf);
1733                                                 GST_ERROR("finish unreffing");
1734                                         }
1735                                 }
1736                         } else {
1737                                 /* If buffer count which is sent to ecore pipe, is upper 3, Print Error log */
1738                                 if(!(skip_count++%20)) {
1739                                         GST_WARNING("[%d]EA buffer was already sent to ecore pipe, and %d frame skipped", esink->sent_buffer_cnt,skip_count);
1740                                 }
1741                         }
1742                 } else if (esink->tbm_surface_format == TBM_FORMAT_YUV420) {
1743                         esink->cur_index = index;
1744                         GST_LOG("index %d", index);
1745                         GST_LOG("[show_frame] gst_buf vaddr %p", esink->src_buffer_info[esink->src_buf_idx].usr_addr);
1746
1747                         /* Print debug log for 8 frame */
1748                         if(esink->debuglog_cnt_showFrame > 0)
1749                         {
1750                                 GST_WARNING("(%d) ecore_pipe_write :  index[%d], bo[%p], tbm_surf[%p], gst_buf[%p], gst_buf vaddr [%p]", DEBUGLOG_DEFAULT_COUNT-(esink->debuglog_cnt_showFrame),
1751                                         esink->cur_index, esink->displaying_buffer[index].bo, esink->displaying_buffer[index].tbm_surf, buf, esink->src_buffer_info[esink->src_buf_idx].usr_addr);
1752                                 esink->debuglog_cnt_showFrame--;
1753                         }
1754
1755                         esink->sent_buffer_cnt++;
1756
1757                         esink->src_buf_idx++;
1758                     r = ecore_pipe_write (esink->epipe, &esink->cur_index , SIZE_FOR_NATIVE_INDEX);
1759
1760                         if (r == EINA_FALSE)  {
1761                                 esink->cur_index = old_curidx;
1762                                 esink->sent_buffer_cnt--;
1763                                 esink->src_buf_idx--;
1764                                 GST_ERROR("ecore_pipe_write is failed. index[%d], bo[%p], tbm_surf[%p], gst_buf vaddr [%p]",
1765                                         index, esink->displaying_buffer[index].bo, esink->displaying_buffer[index].tbm_surf, esink->src_buffer_info[esink->src_buf_idx].usr_addr);
1766                         }
1767                         esink->src_buf_idx = esink->src_buf_idx % SOURCE_BUFFER_NUM;
1768                 }
1769
1770                 g_mutex_unlock(esink->display_buffer_lock);
1771 #endif
1772                 GST_DEBUG ("ecore_pipe_write() was called with gst_buf= %p..  gst_buf Vaddr=%p, mallocdata= %p", buf, GST_BUFFER_DATA(buf), GST_BUFFER_MALLOCDATA(buf));
1773         } else {
1774                 GST_WARNING ("skip ecore_pipe_write(). becuase of esink->object_show(%d) index(%d)", esink->object_show, index);
1775         }
1776         g_mutex_unlock (instance_lock);
1777         GST_DEBUG ("Leave");
1778         return GST_FLOW_OK;
1779 }
1780
1781 #ifdef USE_TBM_SURFACE
1782 static GstFlowReturn
1783 gst_esink_epipe_reset(GstEvasImageSink *esink)
1784 {
1785         if (esink == NULL) {
1786                 GST_ERROR("handle is NULL");
1787                 return GST_FLOW_ERROR;
1788         }
1789
1790         if (esink->epipe) {
1791                 GST_DEBUG("ecore-pipe will delete");
1792                 ecore_pipe_del (esink->epipe);
1793                 esink->epipe = NULL;
1794         }
1795
1796         if (!esink->epipe) {
1797                 esink->epipe = ecore_pipe_add ((Ecore_Pipe_Cb)evas_image_sink_cb_pipe, esink);
1798                 if (!esink->epipe) {
1799                         GST_ERROR ("ecore-pipe create failed");
1800                         return GST_FLOW_ERROR;
1801                 }
1802                 GST_DEBUG("ecore-pipe create success");
1803         }
1804
1805         return GST_FLOW_OK;
1806 }
1807
1808
1809 static gboolean gst_esink_make_flush_buffer(GstEvasImageSink *esink)
1810 {
1811         GstEvasImageFlushBuffer *flush_buffer = NULL;
1812         GstEvasImageDisplayingBuffer *display_buffer = NULL;
1813         int size = 0;
1814         tbm_bo bo;
1815         tbm_bo_handle vaddr_src;
1816         tbm_bo_handle vaddr_dst;
1817         GstFlowReturn ret=GST_FLOW_OK;
1818         int src_size = 0;
1819
1820         if (esink == NULL) {
1821                 GST_ERROR("handle is NULL");
1822                 return FALSE;
1823         }
1824
1825         if (esink->cur_index == -1) {
1826                 GST_WARNING_OBJECT(esink, "there is no remained buffer");
1827                 return FALSE;
1828         }
1829
1830         if(esink->flush_buffer)
1831                 _release_flush_buffer(esink);
1832
1833         /* malloc buffer */
1834         flush_buffer = (GstEvasImageFlushBuffer *)malloc(sizeof(GstEvasImageFlushBuffer));
1835         if (flush_buffer == NULL) {
1836                 GST_ERROR_OBJECT(esink, "GstEvasImageFlushBuffer alloc failed");
1837                 return FALSE;
1838         }
1839
1840         memset(flush_buffer, 0x0, sizeof(GstEvasImageFlushBuffer));
1841
1842         display_buffer = &(esink->displaying_buffer[esink->cur_index]);
1843         GST_WARNING_OBJECT(esink, "cur_index [%d]",
1844                                                                   esink->cur_index);
1845         if(!display_buffer || !display_buffer->bo)
1846         {
1847                 GST_WARNING("display_buffer(%p) or bo (%p) is NULL!!", display_buffer, display_buffer->bo);
1848                 goto FLUSH_BUFFER_FAILED;
1849         }
1850
1851         /* create tbm surface */
1852         flush_buffer->tbm_surf = tbm_surface_create(esink->w, esink->h, TBM_FORMAT_NV12);
1853
1854         if(!flush_buffer->tbm_surf)
1855         {
1856                 GST_ERROR("tbm_surf is NULL!!");
1857                 goto FLUSH_BUFFER_FAILED;
1858         }
1859
1860         /* get bo and size */
1861         bo = tbm_surface_internal_get_bo(flush_buffer->tbm_surf, 0);
1862         size = tbm_bo_size(bo);
1863         if(!bo || !size)
1864         {
1865                 GST_ERROR("bo(%p), size(%d)", bo, size);
1866                 goto FLUSH_BUFFER_FAILED;
1867         }
1868         flush_buffer->bo = bo;
1869
1870         src_size = display_buffer->buffer->size;
1871
1872         vaddr_src = tbm_bo_map(display_buffer->bo, TBM_DEVICE_CPU, TBM_OPTION_READ|TBM_OPTION_WRITE);
1873         vaddr_dst = tbm_bo_map(bo, TBM_DEVICE_CPU, TBM_OPTION_READ|TBM_OPTION_WRITE);
1874         if (!vaddr_src.ptr || !vaddr_dst.ptr) {
1875                 GST_WARNING_OBJECT(esink, "get vaddr failed src %p, dst %p", vaddr_src.ptr, vaddr_dst.ptr);
1876                 if (vaddr_src.ptr) {
1877                         tbm_bo_unmap(display_buffer->bo);
1878                 }
1879                 if (vaddr_dst.ptr) {
1880                         tbm_bo_unmap(bo);
1881                 }
1882                 goto FLUSH_BUFFER_FAILED;
1883         } else {
1884                 memset (vaddr_dst.ptr, 0x0, size);
1885                 GST_WARNING_OBJECT (esink, "tbm_bo_map(VADDR) finished, bo(%p), vaddr(%p)", bo, vaddr_dst.ptr);
1886         }
1887
1888         /* copy buffer */
1889         memcpy(vaddr_dst.ptr, vaddr_src.ptr, src_size);
1890
1891         tbm_bo_unmap(display_buffer->bo);
1892         tbm_bo_unmap(bo);
1893
1894         GST_WARNING_OBJECT(esink, "copy done.. tbm surface : %p src_size : %d", flush_buffer->tbm_surf, src_size);
1895
1896         esink->flush_buffer = flush_buffer;
1897
1898         /* initialize buffer list */
1899        if (esink->object_show)
1900                esink->need_flush = TRUE;
1901
1902        ret = gst_esink_epipe_reset(esink);
1903        if(ret) {
1904               GST_ERROR_OBJECT(esink, "evas epipe reset ret=%d, need to check",ret);
1905               return FALSE;
1906        } else {
1907               GST_ERROR_OBJECT(esink, "evas epipe reset success");
1908        }
1909
1910        gst_evas_image_sink_reset(esink);
1911
1912
1913         return TRUE;
1914
1915 FLUSH_BUFFER_FAILED:
1916         if (flush_buffer) {
1917                 if(flush_buffer->tbm_surf)
1918                 {
1919                         tbm_surface_destroy(flush_buffer->tbm_surf);
1920                         flush_buffer->tbm_surf = NULL;
1921                 }
1922
1923                 free(flush_buffer);
1924                 flush_buffer = NULL;
1925         }
1926         return FALSE;
1927 }
1928
1929  static void _release_flush_buffer(GstEvasImageSink *esink)
1930 {
1931         if (esink == NULL ||
1932             esink->flush_buffer == NULL) {
1933                 GST_WARNING("handle is NULL");
1934                 return;
1935         }
1936
1937         GST_WARNING_OBJECT(esink, "release FLUSH BUFFER start");
1938         if (esink->flush_buffer->bo) {
1939                 esink->flush_buffer->bo = NULL;
1940         }
1941         if(esink->flush_buffer->tbm_surf) {
1942                 tbm_surface_destroy(esink->flush_buffer->tbm_surf);
1943                 esink->flush_buffer->tbm_surf = NULL;
1944         }
1945
1946         GST_WARNING_OBJECT(esink, "release FLUSH BUFFER done");
1947
1948         free(esink->flush_buffer);
1949         esink->flush_buffer = NULL;
1950
1951         return;
1952 }
1953 #endif
1954 #ifdef DUMP_IMG
1955 int util_write_rawdata(const char *file, const void *data, unsigned int size)
1956 {
1957         FILE *fp;
1958         fp = fopen(file, "wb");
1959         if (fp == NULL)
1960                 return -1;
1961         fwrite((char*)data, sizeof(char), size, fp);
1962         fclose(fp);
1963         return 0;
1964 }
1965 #endif
1966
1967 static gboolean
1968 evas_image_sink_init (GstPlugin *evasimagesink)
1969 {
1970         GST_DEBUG_CATEGORY_INIT (gst_evas_image_sink_debug, "evasimagesink", 0, "Evas image object based videosink");
1971
1972         return gst_element_register (evasimagesink, "evasimagesink", GST_RANK_NONE, GST_TYPE_EVASIMAGESINK);
1973 }
1974
1975 #ifndef PACKAGE
1976 #define PACKAGE "gstevasimagesink-plugin-package"
1977 #endif
1978
1979 GST_PLUGIN_DEFINE (
1980         GST_VERSION_MAJOR,
1981         GST_VERSION_MINOR,
1982         "evasimagesink",
1983         "Evas image object based videosink",
1984         evas_image_sink_init,
1985         VERSION,
1986         "LGPL",
1987         "Samsung Electronics Co",
1988         "http://www.samsung.com/"
1989 )