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