Initialize Tizen 2.3
[framework/multimedia/gst-plugins-ext0.10.git] / mobile / evaspixmapsink / evaspixmapsink.c
1 /*
2  * EvasPixmapSink
3  *
4  * Copyright (c) 2000 - 2012 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 #ifdef HAVE_CONFIG_H
25 #include "config.h"
26 #endif
27
28 /* Our interfaces */
29 #include <gst/interfaces/navigation.h>
30 #include <gst/interfaces/colorbalance.h>
31 #include <gst/interfaces/propertyprobe.h>
32 /* Helper functions */
33 #include <gst/video/video.h>
34
35 /* Object header */
36 #include "evaspixmapsink.h"
37
38 #include <time.h>
39
40 /* Samsung extension headers */
41 /* For xv extension header for buffer transfer (output) */
42 #include "xv_types.h"
43
44 /* headers for drm */
45 #include <sys/stat.h>
46 #include <sys/ioctl.h>
47 #include <fcntl.h>
48 #include <unistd.h>
49 #include <X11/Xmd.h>
50 #include <dri2/dri2.h>
51 #include <libdrm/drm.h>
52
53 /* max channel count *********************************************************/
54 #define SCMN_IMGB_MAX_PLANE         (4)
55
56 /* image buffer definition ***************************************************
57
58     +------------------------------------------+ ---
59     |                                          |  ^
60     |     a[], p[]                             |  |
61     |     +---------------------------+ ---    |  |
62     |     |                           |  ^     |  |
63     |     |<---------- w[] ---------->|  |     |  |
64     |     |                           |  |     |  |
65     |     |                           |        |
66     |     |                           |  h[]   |  e[]
67     |     |                           |        |
68     |     |                           |  |     |  |
69     |     |                           |  |     |  |
70     |     |                           |  v     |  |
71     |     +---------------------------+ ---    |  |
72     |                                          |  v
73     +------------------------------------------+ ---
74
75     |<----------------- s[] ------------------>|
76 */
77
78 typedef struct
79 {
80         /* width of each image plane */
81         int w[SCMN_IMGB_MAX_PLANE];
82         /* height of each image plane */
83         int h[SCMN_IMGB_MAX_PLANE];
84         /* stride of each image plane */
85         int s[SCMN_IMGB_MAX_PLANE];
86         /* elevation of each image plane */
87         int e[SCMN_IMGB_MAX_PLANE];
88         /* user space address of each image plane */
89         void *a[SCMN_IMGB_MAX_PLANE];
90         /* physical address of each image plane, if needs */
91         void *p[SCMN_IMGB_MAX_PLANE];
92         /* color space type of image */
93         int cs;
94         /* left postion, if needs */
95         int x;
96         /* top position, if needs */
97         int y;
98         /* to align memory */
99         int __dummy2;
100         /* arbitrary data */
101         int data[16];
102         /* dma buf fd */
103         int dma_buf_fd[SCMN_IMGB_MAX_PLANE];
104         /* buffer share method */
105         int buf_share_method;
106         /* Y plane size in case of ST12 */
107         int y_size;
108         /* UV plane size in case of ST12 */
109         int uv_size;
110         /* Tizen buffer object */
111         void *bo[SCMN_IMGB_MAX_PLANE];
112         /* JPEG data */
113         void *jpeg_data;
114         /* JPEG size */
115         int jpeg_size;
116         /* TZ memory buffer */
117         int tz_enable;
118 } SCMN_IMGB;
119
120 /* Debugging category */
121 #include <gst/gstinfo.h>
122 GST_DEBUG_CATEGORY_STATIC (gst_debug_evaspixmapsink);
123 #define GST_CAT_DEFAULT gst_debug_evaspixmapsink
124 GST_DEBUG_CATEGORY_STATIC (GST_CAT_PERFORMANCE);
125
126 enum {
127     UPDATE_FALSE,
128     UPDATE_TRUE
129 };
130
131 enum {
132     DEGREE_0,
133     DEGREE_90,
134     DEGREE_180,
135     DEGREE_270,
136     DEGREE_NUM,
137 };
138
139 enum {
140     DISP_GEO_METHOD_LETTER_BOX = 0,
141     DISP_GEO_METHOD_ORIGIN_SIZE,
142     DISP_GEO_METHOD_FULL_SCREEN,
143     DISP_GEO_METHOD_CROPPED_FULL_SCREEN,
144     DISP_GEO_METHOD_CUSTOM_ROI,
145     DISP_GEO_METHOD_NUM,
146 };
147
148 enum {
149     FLIP_NONE = 0,
150     FLIP_HORIZONTAL,
151     FLIP_VERTICAL,
152     FLIP_BOTH,
153     FLIP_NUM,
154 };
155
156 #define DEF_DISPLAY_GEOMETRY_METHOD                     DISP_GEO_METHOD_LETTER_BOX
157 #define DEF_DISPLAY_FLIP                                FLIP_NONE
158 #define GST_TYPE_EVASPIXMAPSINK_FLIP                    (gst_evaspixmapsink_flip_get_type())
159 #define GST_TYPE_EVASPIXMAPSINK_ROTATE_ANGLE            (gst_evaspixmapsink_rotate_angle_get_type())
160 #define GST_TYPE_EVASPIXMAPSINK_DISPLAY_GEOMETRY_METHOD (gst_evaspixmapsink_display_geometry_method_get_type())
161 #define SIZE_FOR_UPDATE_VISIBILITY                      sizeof(gchar)
162 #define EPIPE_REQUEST_LIMIT                             20
163
164 /* macro ******************************************************/
165 #define EVASPIXMAPSINK_SET_PIXMAP_ID_TO_GEM_INFO( x_evaspixmapsink, x_pixmap_id ) \
166 do \
167 { \
168         int i = 0; \
169         XV_DATA_PTR data = (XV_DATA_PTR)x_evaspixmapsink->evas_pixmap_buf->xvimage->data; \
170         if (data->YBuf > 0) { \
171                 for (i = 0; i < MAX_GEM_BUFFER_NUM; i++) { \
172                         if (evaspixmapsink->gem_info[i].gem_name == data->YBuf) { \
173                                 evaspixmapsink->gem_info[i].ref_pixmap = x_pixmap_id; \
174                                 GST_LOG_OBJECT (x_evaspixmapsink,"pixmap(%d) is marked at index(%d) of gem_info(YBuf)->gem_handle(%d)", x_pixmap_id, i, evaspixmapsink->gem_info[i].gem_handle); \
175                                 break; \
176                         } \
177                 } \
178         } \
179         if (data->CbBuf > 0) { \
180                 for (i = 0; i < MAX_GEM_BUFFER_NUM; i++) { \
181                         if (evaspixmapsink->gem_info[i].gem_name == data->CbBuf) { \
182                                 evaspixmapsink->gem_info[i].ref_pixmap = x_pixmap_id; \
183                                 GST_LOG_OBJECT (x_evaspixmapsink,"pixmap(%d) is marked at index(%d) of gem_info(CbBuf)->gem_handle(%d)", x_pixmap_id, i, evaspixmapsink->gem_info[i].gem_handle); \
184                                 break; \
185                         } \
186                 } \
187         } \
188         if (data->CrBuf > 0) { \
189                 for (i = 0; i < MAX_GEM_BUFFER_NUM; i++) { \
190                         if (evaspixmapsink->gem_info[i].gem_name == data->CrBuf) { \
191                                 evaspixmapsink->gem_info[i].ref_pixmap = x_pixmap_id; \
192                                 GST_LOG_OBJECT (x_evaspixmapsink,"pixmap(%d) is marked at index(%d) of gem_info(CrBuf)->gem_handle(%d)", x_pixmap_id, i, evaspixmapsink->gem_info[i].gem_handle); \
193                                 break; \
194                         } \
195                 } \
196         } \
197 }while(0)
198
199 #define EVASPIXMAPSINK_SET_EVAS_OBJECT_EVENT_CALLBACK( x_evas_image_object, x_usr_data ) \
200 do \
201 { \
202         evas_object_event_callback_add (x_evas_image_object, EVAS_CALLBACK_DEL, evas_callback_del_event, x_usr_data); \
203         evas_object_event_callback_add (x_evas_image_object, EVAS_CALLBACK_RESIZE, evas_callback_resize_event, x_usr_data); \
204         evas_object_event_callback_add (x_evas_image_object, EVAS_CALLBACK_SHOW, evas_callback_show_event, x_usr_data); \
205         evas_object_event_callback_add (x_evas_image_object, EVAS_CALLBACK_HIDE, evas_callback_hide_event, x_usr_data); \
206 }while(0)
207
208 #define EVASPIXMAPSINK_UNSET_EVAS_OBJECT_EVENT_CALLBACK( x_evas_image_object ) \
209 do \
210 { \
211         evas_object_event_callback_del (x_evas_image_object, EVAS_CALLBACK_DEL, evas_callback_del_event); \
212         evas_object_event_callback_del (x_evas_image_object, EVAS_CALLBACK_RESIZE, evas_callback_resize_event); \
213         evas_object_event_callback_del (x_evas_image_object, EVAS_CALLBACK_SHOW, evas_callback_show_event); \
214         evas_object_event_callback_del (x_evas_image_object, EVAS_CALLBACK_HIDE, evas_callback_hide_event); \
215 }while(0)
216
217 static GType
218 gst_evaspixmapsink_flip_get_type(void)
219 {
220         static GType evaspixmapsink_flip_type = 0;
221         static const GEnumValue flip_type[] = {
222                 { FLIP_NONE,       "Flip NONE", "FLIP_NONE"},
223                 { FLIP_HORIZONTAL, "Flip HORIZONTAL", "FLIP_HORIZONTAL"},
224                 { FLIP_VERTICAL,   "Flip VERTICAL", "FLIP_VERTICAL"},
225                 { FLIP_BOTH,       "Flip BOTH", "FLIP_BOTH"},
226                 { FLIP_NUM, NULL, NULL},
227         };
228
229         if (!evaspixmapsink_flip_type) {
230                 evaspixmapsink_flip_type = g_enum_register_static("GstEvasPixmapSinkFlipType", flip_type);
231         }
232
233         return evaspixmapsink_flip_type;
234 }
235
236 static GType
237 gst_evaspixmapsink_rotate_angle_get_type(void)
238 {
239         static GType evaspixmapsink_rotate_angle_type = 0;
240         static const GEnumValue rotate_angle_type[] = {
241                 { 0, "No rotate", "DEGREE_0"},
242                 { 1, "Rotate 90 degree", "DEGREE_90"},
243                 { 2, "Rotate 180 degree", "DEGREE_180"},
244                 { 3, "Rotate 270 degree", "DEGREE_270"},
245                 { 4, NULL, NULL},
246         };
247
248         if (!evaspixmapsink_rotate_angle_type) {
249                 evaspixmapsink_rotate_angle_type = g_enum_register_static("GstEvasPixmapSinkRotateAngleType", rotate_angle_type);
250         }
251
252         return evaspixmapsink_rotate_angle_type;
253 }
254
255 static GType
256 gst_evaspixmapsink_display_geometry_method_get_type(void)
257 {
258         static GType evaspixmapsink_display_geometry_method_type = 0;
259         static const GEnumValue display_geometry_method_type[] = {
260                 { 0, "Letter box", "LETTER_BOX"},
261                 { 1, "Origin size", "ORIGIN_SIZE"},
262                 { 2, "Full-screen", "FULL_SCREEN"},
263                 { 3, "Cropped Full-screen", "CROPPED_FULL_SCREEN"},
264                 { 4, "Explicitely described destination ROI", "CUSTOM_ROI"},
265                 { 5, NULL, NULL},
266         };
267
268         if (!evaspixmapsink_display_geometry_method_type) {
269                 evaspixmapsink_display_geometry_method_type = g_enum_register_static("GstEvasPixmapSinkDisplayGeometryMethodType", display_geometry_method_type);
270         }
271
272         return evaspixmapsink_display_geometry_method_type;
273 }
274
275 typedef struct
276 {
277   unsigned long flags;
278   unsigned long functions;
279   unsigned long decorations;
280   long input_mode;
281   unsigned long status;
282 }
283 MotifWmHints, MwmHints;
284
285 #define MWM_HINTS_DECORATIONS   (1L << 1)
286
287 static void gst_evaspixmapsink_reset (GstEvasPixmapSink *evaspixmapsink);
288 static GstBufferClass *evaspixmap_buffer_parent_class = NULL;
289 static void gst_evaspixmap_buffer_finalize (GstEvasPixmapBuffer *evaspixmapbuf);
290 static void gst_evaspixmapsink_xcontext_clear (GstEvasPixmapSink *evaspixmapsink);
291 static void gst_evaspixmapsink_xpixmap_destroy (GstEvasPixmapSink *evaspixmapsink, GstXPixmap *xpixmap);
292 static void gst_evaspixmapsink_xpixmap_update_geometry (GstEvasPixmapSink *evaspixmapsink, int idx);
293 static gboolean gst_evaspixmap_buffer_put (GstEvasPixmapSink *evaspixmapsink, GstEvasPixmapBuffer *evaspixmapbuf);
294 static gboolean gst_evaspixmapsink_xpixmap_link (GstEvasPixmapSink *evaspixmapsink);
295 static void gst_evaspixmapsink_xpixmap_clear (GstEvasPixmapSink *evaspixmapsink, GstXPixmap *xpixmap);
296 static gint gst_evaspixmapsink_get_format_from_caps (GstEvasPixmapSink *evaspixmapsink, GstCaps *caps);
297 static void drm_close_gem(GstEvasPixmapSink *evaspixmapsink, unsigned int gem_handle);
298 static void drm_fini_close_gem_handle(GstEvasPixmapSink *evaspixmapsink, Pixmap pixmap_id);
299 static void evas_callback_resize_event (void *data, Evas *e, Evas_Object *obj, void *event_info);
300 static void evas_callback_del_event (void *data, Evas *e, Evas_Object *obj, void *event_info);
301 static void evas_callback_show_event (void *data, Evas *e, Evas_Object *obj, void *event_info);
302 static void evas_callback_hide_event (void *data, Evas *e, Evas_Object *obj, void *event_info);
303
304 /* Default template - initiated with class struct to allow gst-register to work
305    without X running */
306 static GstStaticPadTemplate gst_evaspixmapsink_sink_template_factory =
307     GST_STATIC_PAD_TEMPLATE ("sink",
308     GST_PAD_SINK,
309     GST_PAD_ALWAYS,
310     GST_STATIC_CAPS ("video/x-raw-rgb, "
311         "framerate = (fraction) [ 0, MAX ], "
312         "width = (int) [ 1, MAX ], "
313         "height = (int) [ 1, MAX ]; "
314         "video/x-raw-yuv, "
315         "framerate = (fraction) [ 0, MAX ], "
316         "width = (int) [ 1, MAX ], " "height = (int) [ 1, MAX ]")
317     );
318
319 enum
320 {
321   PROP_0,
322   PROP_CONTRAST,
323   PROP_BRIGHTNESS,
324   PROP_HUE,
325   PROP_SATURATION,
326   PROP_DISPLAY,
327   PROP_SYNCHRONOUS,
328   PROP_PIXEL_ASPECT_RATIO,
329   PROP_DEVICE,
330   PROP_DEVICE_NAME,
331   PROP_DOUBLE_BUFFER,
332   PROP_AUTOPAINT_COLORKEY,
333   PROP_COLORKEY,
334   PROP_PIXMAP_WIDTH,
335   PROP_PIXMAP_HEIGHT,
336   PROP_FLIP,
337   PROP_ROTATE_ANGLE,
338   PROP_DISPLAY_GEOMETRY_METHOD,
339   PROP_ZOOM,
340   PROP_DST_ROI_X,
341   PROP_DST_ROI_Y,
342   PROP_DST_ROI_W,
343   PROP_DST_ROI_H,
344   PROP_STOP_VIDEO,
345   PROP_EVAS_OBJECT,
346   PROP_VISIBLE,
347   PROP_ORIGIN_SIZE,
348 };
349
350 static GstVideoSinkClass *parent_class = NULL;
351
352 /* ============================================================= */
353 /*                                                               */
354 /*                       Private Methods                         */
355 /*                                                               */
356 /* ============================================================= */
357
358 /* evaspixmap buffers */
359
360 #define GST_TYPE_EVASPIXMAP_BUFFER (gst_evaspixmap_buffer_get_type())
361
362 #define GST_IS_EVASPIXMAP_BUFFER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_EVASPIXMAP_BUFFER))
363 #define GST_EVASPIXMAP_BUFFER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_EVASPIXMAP_BUFFER, GstEvasPixmapBuffer))
364
365 static int get_millis_time()
366 {
367     struct timespec tp;
368     clock_gettime(CLOCK_MONOTONIC, &tp);
369     return (tp.tv_sec * 1000) + (tp.tv_nsec / 1000000L);
370 }
371
372 static void
373 ecore_pipe_callback_handler (void *data, void *buffer, unsigned int nbyte)
374 {
375         GstEvasPixmapSink *evaspixmapsink = (GstEvasPixmapSink*)data;
376         GST_DEBUG_OBJECT (evaspixmapsink,"[START] Evas_Object(0x%x)", evaspixmapsink->eo);
377         MMTA_ACUM_ITEM_BEGIN("evaspixmapsink - ecore thread cb : TOTAL", FALSE);
378         int i = 0;
379         guint idx = 0;
380         GstXPixmap *xpixmap = NULL;
381
382         if (!data ) {
383                 GST_WARNING_OBJECT (evaspixmapsink,"data is NULL..");
384                 return;
385         }
386         evaspixmapsink->epipe_request_count--;
387         if (!evaspixmapsink->eo) {
388                 GST_WARNING_OBJECT (evaspixmapsink,"evas object is NULL..");
389                 return;
390         }
391
392         /* setting evas object hide and show */
393         if (nbyte == SIZE_FOR_UPDATE_VISIBILITY) {
394                 if(!evaspixmapsink->visible) {
395                         evas_object_hide(evaspixmapsink->eo);
396                         GST_INFO_OBJECT (evaspixmapsink, "object hide");
397                 } else {
398                         if (!evas_object_image_native_surface_get(evaspixmapsink->eo)) {
399                                 GST_WARNING_OBJECT (evaspixmapsink, "native surface is not set, skip evas_object_show()..");
400                         } else {
401                                 evas_object_show(evaspixmapsink->eo);
402                                 GST_INFO_OBJECT (evaspixmapsink, "object show");
403                         }
404                 }
405                 return;
406         }
407
408         /* mapping evas object with xpixmap */
409         if (evaspixmapsink->do_link) {
410                 GST_DEBUG_OBJECT (evaspixmapsink,"do link");
411                 evas_object_image_size_set(evaspixmapsink->eo, evaspixmapsink->w, evaspixmapsink->h);
412                 if (evaspixmapsink->xpixmap[idx]->pixmap) {
413                         Evas_Native_Surface surf;
414                         surf.version = EVAS_NATIVE_SURFACE_VERSION;
415                         surf.type = EVAS_NATIVE_SURFACE_X11;
416                         surf.data.x11.visual = ecore_x_default_visual_get(ecore_x_display_get(), ecore_x_default_screen_get());
417                         surf.data.x11.pixmap = evaspixmapsink->xpixmap[idx]->pixmap;
418                         __ta__("evaspixmapsink - ecore thread cb : _native_surface_set(LINK)", evas_object_image_native_surface_set(evaspixmapsink->eo, &surf); );
419                         evaspixmapsink->do_link = FALSE;
420                 } else {
421                         GST_WARNING_OBJECT (evaspixmapsink,"pixmap is NULL..");
422                         return;
423                 }
424                 for (i = 0; i < evaspixmapsink->num_of_pixmaps; i++) {
425                         if (evaspixmapsink->xpixmap[i]->prev_pixmap && evaspixmapsink->xpixmap[i]->prev_gc && evaspixmapsink->prev_damage[i]) {
426                                 GST_LOG_OBJECT (evaspixmapsink,"Free pixmap(%d), gc(%x), destroy previous damage(%d)",
427                                                 evaspixmapsink->xpixmap[i]->prev_pixmap, evaspixmapsink->xpixmap[i]->prev_gc, evaspixmapsink->prev_damage[i]);
428                                 g_mutex_lock (evaspixmapsink->x_lock);
429                                 XFreePixmap(evaspixmapsink->xcontext->disp, evaspixmapsink->xpixmap[i]->prev_pixmap);
430                                 XFreeGC (evaspixmapsink->xcontext->disp, evaspixmapsink->xpixmap[i]->prev_gc);
431                                 XDamageDestroy(evaspixmapsink->xcontext->disp, evaspixmapsink->prev_damage[i]);
432                                 XSync(evaspixmapsink->xcontext->disp, FALSE);
433                                 g_mutex_unlock (evaspixmapsink->x_lock);
434                                 evaspixmapsink->xpixmap[i]->prev_pixmap = 0;
435                                 evaspixmapsink->xpixmap[i]->prev_gc = 0;
436                                 evaspixmapsink->prev_damage[i] = NULL;
437                         }
438                 }
439                 if (evaspixmapsink->visible && !evas_object_visible_get(evaspixmapsink->eo)) {
440                         evas_object_show(evaspixmapsink->eo);
441                         GST_WARNING_OBJECT (evaspixmapsink, "object show (lazy)");
442                 }
443
444         } else {
445                 GST_DEBUG_OBJECT (evaspixmapsink,"update");
446                 /* update evas image object size */
447                 if (evaspixmapsink->use_origin_size) {
448                         evas_object_geometry_get(evaspixmapsink->eo, NULL, NULL, &evaspixmapsink->w, &evaspixmapsink->h);
449                 }
450
451                 g_mutex_lock (evaspixmapsink->pixmap_ref_lock);
452
453                 /* find a oldest damaged pixmap */
454                 int temp_time = 0;
455                 for (i = 0; i < evaspixmapsink->num_of_pixmaps; i++) {
456                         if (evaspixmapsink->last_updated_idx == i) {
457                                 continue;
458                         } else {
459                                 xpixmap = evaspixmapsink->xpixmap[i];
460                                 if (xpixmap->ref > 0 && xpixmap->damaged_time) {
461                                         if (temp_time == 0) {
462                                                 temp_time = xpixmap->damaged_time;
463                                                 idx = i;
464                                         } else {
465                                                 if (temp_time > xpixmap->damaged_time) {
466                                                         temp_time = xpixmap->damaged_time;
467                                                         idx = i;
468                                                 }
469                                         }
470                                 }
471                         }
472                 }
473
474                 xpixmap = evaspixmapsink->xpixmap[idx];
475                 if (xpixmap->pixmap) {
476                         if (evaspixmapsink->last_updated_idx != idx) {
477                                 Evas_Native_Surface surf;
478                                 surf.version = EVAS_NATIVE_SURFACE_VERSION;
479                                 surf.type = EVAS_NATIVE_SURFACE_X11;
480                                 surf.data.x11.visual = ecore_x_default_visual_get(ecore_x_display_get(), ecore_x_default_screen_get());
481                                 surf.data.x11.pixmap = xpixmap->pixmap;
482                                 if (evaspixmapsink->eo) {
483                                         evas_object_image_native_surface_set(evaspixmapsink->eo, NULL);
484                                 }
485                                 __ta__("evaspixmapsink - ecore thread cb : _native_surface_set", evas_object_image_native_surface_set(evaspixmapsink->eo, &surf); );
486                                 GST_LOG_OBJECT (evaspixmapsink,"update, native_surface_set of xpixmap[%d]",idx);
487                                 if (evaspixmapsink->last_updated_idx == -1) {
488                                         xpixmap->damaged_time = 0;
489                                         GST_INFO_OBJECT (evaspixmapsink,"this is the first time to request to update(do not DECREASE ref-count) : pixmap(%d), refcount(%d), damaged_time(%d), idx(%d)",
490                                                                         xpixmap->pixmap, xpixmap->ref, xpixmap->damaged_time, idx);
491                                 } else {
492                                         xpixmap = evaspixmapsink->xpixmap[evaspixmapsink->last_updated_idx];
493                                         xpixmap->ref--;
494                                         xpixmap->damaged_time = 0;
495                                         GST_INFO_OBJECT (evaspixmapsink,"pixmap ref-count DECREASED : pixmap(%d), refcount(%d), damaged_time(%d), idx(%d)",
496                                                                                         xpixmap->pixmap, xpixmap->ref, xpixmap->damaged_time, evaspixmapsink->last_updated_idx);
497                                 }
498                                 evaspixmapsink->last_updated_idx = idx;
499                         }
500
501                         MMTA_ACUM_ITEM_BEGIN("evaspixmapsink evas_object_image update", FALSE);
502                         evas_object_image_pixels_dirty_set (evaspixmapsink->eo, 1);
503                         evas_object_image_fill_set(evaspixmapsink->eo, 0, 0, evaspixmapsink->w, evaspixmapsink->h);
504                         evas_object_image_data_update_add(evaspixmapsink->eo, 0, 0, evaspixmapsink->w, evaspixmapsink->h);
505                         MMTA_ACUM_ITEM_END("evaspixmapsink evas_object_image update", FALSE);
506                         //GST_LOG_OBJECT (evaspixmapsink,"request to update : pixmap idx(%d), ref(%d)", idx, xpixmap->ref);
507                 } else {
508                         GST_ERROR_OBJECT (evaspixmapsink,"pixmap is NULL..");
509                 }
510                 g_mutex_unlock (evaspixmapsink->pixmap_ref_lock);
511         }
512
513         MMTA_ACUM_ITEM_END("evaspixmapsink - ecore thread cb : TOTAL", FALSE);
514
515         GST_DEBUG_OBJECT (evaspixmapsink,"[END]");
516 }
517
518 static inline gboolean
519 is_evas_image_object (Evas_Object *obj)
520 {
521         const char *type;
522         if (!obj) {
523                 GST_ERROR ("evas image object is NULL..");
524                 return FALSE;
525         }
526         type = evas_object_type_get (obj);
527         if (!type) {
528                 GST_ERROR ("could not find type of the evas object..");
529                 return FALSE;
530         }
531         if (strcmp (type, "image") == 0) {
532                 return TRUE;
533         }
534         return FALSE;
535 }
536
537 static void
538 evas_callback_resize_event (void *data, Evas *e, Evas_Object *obj, void *event_info)
539 {
540         int w = 0;
541         int h = 0;
542         float former_ratio = 0;
543         float ratio = 0;
544         int i = 0;
545 #ifdef COMPARE_RATIO
546         float abs_margin = 0;
547 #endif
548
549         GstEvasPixmapSink *evaspixmapsink = (GstEvasPixmapSink *)data;
550         GST_DEBUG_OBJECT (evaspixmapsink,"[START] evas_image_object(%x), tid(%u)", obj, (unsigned int)pthread_self());
551
552         evas_object_geometry_get(evaspixmapsink->eo, NULL, NULL, &w, &h);
553         GST_DEBUG_OBJECT (evaspixmapsink,"resized : w(%d), h(%d)", w, h);
554         if (!evaspixmapsink->use_origin_size &&
555                         (evaspixmapsink->w != w || evaspixmapsink->h != h)) {
556                 former_ratio = (float)evaspixmapsink->w / evaspixmapsink->h;
557                 ratio = (float)w / h;
558                 evaspixmapsink->w = w;
559                 evaspixmapsink->h = h;
560
561 #ifdef COMPARE_RATIO
562                 GST_DEBUG_OBJECT (evaspixmapsink,"resized : ratio(%.3f=>%.3f)", former_ratio, ratio);
563                 if ( former_ratio >= ratio ) {
564                         abs_margin = former_ratio - ratio;
565                 } else {
566                         abs_margin = ratio - former_ratio;
567                 }
568                 /* re-link_pixmap can only be set when ratio is changed */
569                 if ( abs_margin >= MARGIN_OF_ERROR ) {
570 #endif
571                         if (!gst_evaspixmapsink_xpixmap_link(evaspixmapsink)) {
572                                 GST_ERROR_OBJECT (evaspixmapsink,"link evas image object with pixmap failed...");
573                                 return;
574                         }
575                         for (i = 0; i < MAX_GEM_BUFFER_NUM; i++) {
576                                 if (evaspixmapsink->gem_info[i].ref_pixmap > 0) {
577                                         GST_LOG_OBJECT (evaspixmapsink,"set ref_pixmap(%d) to 0 in gem_info[%d]", evaspixmapsink->gem_info[i].ref_pixmap, i);
578                                         evaspixmapsink->gem_info[i].ref_pixmap = 0;
579                                 }
580                         }
581 #ifdef COMPARE_RATIO
582                 }
583 #endif
584         }
585
586         if (GST_STATE(evaspixmapsink) == GST_STATE_PAUSED) {
587                 gst_evaspixmap_buffer_put (evaspixmapsink, evaspixmapsink->evas_pixmap_buf);
588         }
589
590         GST_DEBUG_OBJECT (evaspixmapsink,"[END]");
591 }
592
593 static void
594 evas_callback_del_event (void *data, Evas *e, Evas_Object *obj, void *event_info)
595 {
596         GstEvasPixmapSink *evaspixmapsink = data;
597         if (!evaspixmapsink) {
598                 GST_WARNING ("evaspixmapsink is NULL..");
599                 return;
600         }
601         GST_DEBUG_OBJECT (evaspixmapsink,"[START]");
602
603         EVASPIXMAPSINK_UNSET_EVAS_OBJECT_EVENT_CALLBACK( evaspixmapsink->eo );
604         if (evaspixmapsink->eo) {
605                 evas_object_image_native_surface_set(evaspixmapsink->eo, NULL);
606                 evaspixmapsink->eo = NULL;
607         }
608
609         GST_DEBUG_OBJECT (evaspixmapsink,"[END]");
610 }
611
612 static void
613 evas_callback_show_event (void *data, Evas *e, Evas_Object *obj, void *event_info)
614 {
615         GstEvasPixmapSink *evaspixmapsink = (GstEvasPixmapSink *)data;
616         GST_INFO_OBJECT (evaspixmapsink,"show evas_image_object(%x) from pid(%d), tid(%u)", obj, getpid(), (unsigned int)pthread_self());
617 }
618
619 static void
620 evas_callback_hide_event (void *data, Evas *e, Evas_Object *obj, void *event_info)
621 {
622         GstEvasPixmapSink *evaspixmapsink = (GstEvasPixmapSink *)data;
623         GST_INFO_OBJECT (evaspixmapsink,"hide evas_image_object(%x) from pid(%d), tid(%u)", obj, getpid(), (unsigned int)pthread_self());
624 }
625
626 /* X11 stuff */
627 static gboolean error_caught = FALSE;
628
629 static int
630 gst_evaspixmapsink_handle_xerror (Display * display, XErrorEvent * xevent)
631 {
632   char error_msg[1024];
633
634   XGetErrorText (display, xevent->error_code, error_msg, 1024);
635   GST_ERROR ("evaspixmapsink triggered an XError. error(%s), display(%p), xevent->request_code(%d)", error_msg, display, xevent->request_code);
636   error_caught = TRUE;
637   return 0;
638 }
639
640 #ifdef HAVE_XSHM
641 /* This function checks that it is actually really possible to create an image
642    using XShm */
643 static gboolean
644 gst_evaspixmapsink_check_xshm_calls (GstXContext * xcontext)
645 {
646   XvImage *xvimage;
647   XShmSegmentInfo SHMInfo;
648   gint size;
649   int (*handler) (Display *, XErrorEvent *);
650   gboolean result = FALSE;
651   gboolean did_attach = FALSE;
652
653   g_return_val_if_fail (xcontext != NULL, FALSE);
654
655   /* Sync to ensure any older errors are already processed */
656   XSync (xcontext->disp, FALSE);
657
658   /* Set defaults so we don't free these later unnecessarily */
659   SHMInfo.shmaddr = ((void *) -1);
660   SHMInfo.shmid = -1;
661
662   /* Setting an error handler to catch failure */
663   error_caught = FALSE;
664   handler = XSetErrorHandler (gst_evaspixmapsink_handle_xerror);
665
666   /* Trying to create a 1x1 picture */
667   GST_DEBUG ("XvShmCreateImage of 1x1");
668   xvimage = XvShmCreateImage (xcontext->disp, xcontext->xv_port_id,
669       xcontext->im_format, NULL, 1, 1, &SHMInfo);
670
671   /* Might cause an error, sync to ensure it is noticed */
672   XSync (xcontext->disp, FALSE);
673   if (!xvimage || error_caught) {
674     GST_WARNING ("could not XvShmCreateImage a 1x1 image");
675     goto beach;
676   }
677   size = xvimage->data_size;
678
679   SHMInfo.shmid = shmget (IPC_PRIVATE, size, IPC_CREAT | 0777);
680   if (SHMInfo.shmid == -1) {
681     GST_WARNING ("could not get shared memory of %d bytes", size);
682     goto beach;
683   }
684
685   SHMInfo.shmaddr = shmat (SHMInfo.shmid, NULL, 0);
686   if (SHMInfo.shmaddr == ((void *) -1)) {
687     GST_WARNING ("Failed to shmat: %s", g_strerror (errno));
688     /* Clean up the shared memory segment */
689     shmctl (SHMInfo.shmid, IPC_RMID, NULL);
690     goto beach;
691   }
692
693   xvimage->data = SHMInfo.shmaddr;
694   SHMInfo.readOnly = FALSE;
695
696   if (XShmAttach (xcontext->disp, &SHMInfo) == 0) {
697     GST_WARNING ("Failed to XShmAttach");
698     /* Clean up the shared memory segment */
699     shmctl (SHMInfo.shmid, IPC_RMID, NULL);
700     goto beach;
701   }
702
703   /* Sync to ensure we see any errors we caused */
704   XSync (xcontext->disp, FALSE);
705
706   /* Delete the shared memory segment as soon as everyone is attached.
707    * This way, it will be deleted as soon as we detach later, and not
708    * leaked if we crash. */
709   shmctl (SHMInfo.shmid, IPC_RMID, NULL);
710
711   if (!error_caught) {
712     GST_DEBUG ("XServer ShmAttached to 0x%x, id 0x%lx", SHMInfo.shmid,
713         SHMInfo.shmseg);
714
715     did_attach = TRUE;
716     /* store whether we succeeded in result */
717     result = TRUE;
718   } else {
719     GST_WARNING ("MIT-SHM extension check failed at XShmAttach. "
720         "Not using shared memory.");
721   }
722
723 beach:
724   /* Sync to ensure we swallow any errors we caused and reset error_caught */
725   XSync (xcontext->disp, FALSE);
726
727   error_caught = FALSE;
728   XSetErrorHandler (handler);
729
730   if (did_attach) {
731     GST_DEBUG ("XServer ShmDetaching from 0x%x id 0x%lx",
732         SHMInfo.shmid, SHMInfo.shmseg);
733     XShmDetach (xcontext->disp, &SHMInfo);
734     XSync (xcontext->disp, FALSE);
735   }
736   if (SHMInfo.shmaddr != ((void *) -1))
737     shmdt (SHMInfo.shmaddr);
738   if (xvimage)
739     XFree (xvimage);
740   return result;
741 }
742 #endif /* HAVE_XSHM */
743
744 /* This function destroys a GstEvasPixmap handling XShm availability */
745 static void
746 gst_evaspixmap_buffer_destroy (GstEvasPixmapBuffer *evaspixmapbuf)
747 {
748         GstEvasPixmapSink *evaspixmapsink;
749
750         evaspixmapsink = evaspixmapbuf->evaspixmapsink;
751         if (G_UNLIKELY (evaspixmapsink == NULL)) {
752                 goto no_sink;
753         }
754         GST_DEBUG_OBJECT (evaspixmapsink, "Destroying buffer");
755
756         g_return_if_fail (GST_IS_EVASPIXMAPSINK (evaspixmapsink));
757
758         GST_OBJECT_LOCK (evaspixmapsink);
759
760         /* We might have some buffers destroyed after changing state to NULL */
761         if (evaspixmapsink->xcontext == NULL) {
762                 GST_DEBUG_OBJECT (evaspixmapsink,"Destroying XvImage after Xcontext");
763 #ifdef HAVE_XSHM
764                 /* Need to free the shared memory segment even if the x context
765                 * was already cleaned up */
766                 if (evaspixmapbuf->SHMInfo.shmaddr != ((void *) -1)) {
767                         shmdt (evaspixmapbuf->SHMInfo.shmaddr);
768                 }
769 #endif
770                 goto beach;
771         }
772         g_mutex_lock (evaspixmapsink->x_lock);
773
774 #ifdef HAVE_XSHM
775         if (evaspixmapsink->xcontext->use_xshm) {
776                 if (evaspixmapbuf->SHMInfo.shmaddr != ((void *) -1)) {
777                         GST_DEBUG_OBJECT (evaspixmapsink,"XServer ShmDetaching from 0x%x id 0x%lx", evaspixmapbuf->SHMInfo.shmid, evaspixmapbuf->SHMInfo.shmseg);
778                         XShmDetach (evaspixmapsink->xcontext->disp, &evaspixmapbuf->SHMInfo);
779                         XSync (evaspixmapsink->xcontext->disp, FALSE);
780                         shmdt (evaspixmapbuf->SHMInfo.shmaddr);
781                 }
782                 if (evaspixmapbuf->xvimage)
783                 XFree (evaspixmapbuf->xvimage);
784         } else
785 #endif /* HAVE_XSHM */
786         {
787                 if (evaspixmapbuf->xvimage) {
788                         if (evaspixmapbuf->xvimage->data) {
789                                 g_free (evaspixmapbuf->xvimage->data);
790                         }
791                         XFree (evaspixmapbuf->xvimage);
792                 }
793         }
794
795         XSync (evaspixmapsink->xcontext->disp, FALSE);
796
797         g_mutex_unlock (evaspixmapsink->x_lock);
798
799 beach:
800         GST_OBJECT_UNLOCK (evaspixmapsink);
801         evaspixmapbuf->evaspixmapsink = NULL;
802         gst_object_unref (evaspixmapsink);
803
804         GST_MINI_OBJECT_CLASS (evaspixmap_buffer_parent_class)->finalize (GST_MINI_OBJECT(evaspixmapbuf));
805
806         return;
807
808         no_sink:
809         {
810                 GST_WARNING ("no sink found");
811                 return;
812         }
813 }
814
815 static void
816 gst_evaspixmap_buffer_finalize (GstEvasPixmapBuffer *evaspixmapbuf)
817 {
818         GstEvasPixmapSink *evaspixmapsink;
819
820         evaspixmapsink = evaspixmapbuf->evaspixmapsink;
821         if (G_UNLIKELY (evaspixmapsink == NULL)) {
822                 GST_WARNING_OBJECT (evaspixmapsink,"no sink found");
823                 return;
824         }
825         g_return_if_fail (GST_IS_EVASPIXMAPSINK (evaspixmapsink));
826
827          /* If our geometry changed we can't reuse that image. */
828         GST_LOG_OBJECT (evaspixmapsink,"destroy image as sink is shutting down");
829         gst_evaspixmap_buffer_destroy (evaspixmapbuf);
830 }
831
832 static void
833 gst_evaspixmap_buffer_free (GstEvasPixmapBuffer *evaspixmapbuf)
834 {
835   /* make sure it is not recycled */
836   evaspixmapbuf->width = -1;
837   evaspixmapbuf->height = -1;
838   gst_buffer_unref (GST_BUFFER (evaspixmapbuf));
839 }
840
841 static void
842 gst_evaspixmap_buffer_init (GstEvasPixmapBuffer *evaspixmapbuf, gpointer g_class)
843 {
844 #ifdef HAVE_XSHM
845   evaspixmapbuf->SHMInfo.shmaddr = ((void *) -1);
846   evaspixmapbuf->SHMInfo.shmid = -1;
847 #endif
848 }
849
850 static void
851 gst_evaspixmap_buffer_class_init (gpointer g_class, gpointer class_data)
852 {
853   GstMiniObjectClass *mini_object_class = GST_MINI_OBJECT_CLASS (g_class);
854
855   evaspixmap_buffer_parent_class = g_type_class_peek_parent (g_class);
856
857   mini_object_class->finalize = (GstMiniObjectFinalizeFunction) gst_evaspixmap_buffer_finalize;
858 }
859
860 static GType
861 gst_evaspixmap_buffer_get_type (void)
862 {
863   static GType _gst_evaspixmap_buffer_type;
864
865   if (G_UNLIKELY (_gst_evaspixmap_buffer_type == 0)) {
866     static const GTypeInfo evaspixmap_buffer_info = {
867       sizeof (GstBufferClass),
868       NULL,
869       NULL,
870       gst_evaspixmap_buffer_class_init,
871       NULL,
872       NULL,
873       sizeof (GstEvasPixmapBuffer),
874       0,
875       (GInstanceInitFunc) gst_evaspixmap_buffer_init,
876       NULL
877     };
878     _gst_evaspixmap_buffer_type = g_type_register_static (GST_TYPE_BUFFER,
879         "GstEvasPixmapBuffer", &evaspixmap_buffer_info, 0);
880   }
881   return _gst_evaspixmap_buffer_type;
882 }
883
884 /* This function handles GstEvasPixmapBuffer creation depending on XShm availability */
885 static GstEvasPixmapBuffer*
886 gst_evaspixmap_buffer_new (GstEvasPixmapSink *evaspixmapsink, GstCaps *caps)
887 {
888         GstEvasPixmapBuffer *evaspixmapbuf = NULL;
889         GstStructure *structure = NULL;
890         gboolean succeeded = FALSE;
891         int (*handler) (Display *, XErrorEvent *);
892
893         g_return_val_if_fail (GST_IS_EVASPIXMAPSINK (evaspixmapsink), NULL);
894
895         if (caps == NULL) {
896                 return NULL;
897         }
898
899         evaspixmapbuf = (GstEvasPixmapBuffer*) gst_mini_object_new (GST_TYPE_EVASPIXMAP_BUFFER);
900         GST_DEBUG_OBJECT (evaspixmapsink,"Creating new EvasPixmapBuffer");
901
902         structure = gst_caps_get_structure (caps, 0);
903
904         if (!gst_structure_get_int (structure, "width", &evaspixmapbuf->width) || !gst_structure_get_int (structure, "height", &evaspixmapbuf->height)) {
905                 GST_WARNING_OBJECT (evaspixmapsink,"failed getting geometry from caps %" GST_PTR_FORMAT, caps);
906         }
907
908         GST_LOG_OBJECT (evaspixmapsink,"creating %dx%d", evaspixmapbuf->width, evaspixmapbuf->height);
909
910         GST_LOG_OBJECT (evaspixmapsink,"aligned size %dx%d", evaspixmapsink->aligned_width, evaspixmapsink->aligned_height);
911         if (evaspixmapsink->aligned_width == 0 || evaspixmapsink->aligned_height == 0) {
912                 GST_INFO_OBJECT (evaspixmapsink,"aligned size is zero. set size of caps.");
913                 evaspixmapsink->aligned_width = evaspixmapbuf->width;
914                 evaspixmapsink->aligned_height = evaspixmapbuf->height;
915         }
916
917         evaspixmapbuf->im_format = gst_evaspixmapsink_get_format_from_caps (evaspixmapsink, caps);
918         if (evaspixmapbuf->im_format == -1) {
919                 GST_WARNING_OBJECT (evaspixmapsink,"failed to get format from caps %"GST_PTR_FORMAT, caps);
920                 GST_ELEMENT_ERROR (evaspixmapsink, RESOURCE, WRITE,("Failed to create output image buffer of %dx%d pixels",
921                                    evaspixmapbuf->width, evaspixmapbuf->height), ("Invalid input caps"));
922                 goto beach_unlocked;
923         }
924
925         GST_INFO_OBJECT (evaspixmapsink, "FOURCC format : %c%c%c%c", evaspixmapbuf->im_format, evaspixmapbuf->im_format>>8,
926                         evaspixmapbuf->im_format>>16, evaspixmapbuf->im_format>>24);
927
928         evaspixmapbuf->evaspixmapsink = gst_object_ref (evaspixmapsink);
929
930         g_mutex_lock (evaspixmapsink->x_lock);
931
932         /* Sync to ensure we swallow any errors we caused and reset error_caught */
933         XSync (evaspixmapsink->xcontext->disp, FALSE);
934
935         /* Setting an error handler to catch failure */
936         error_caught = FALSE;
937         handler = XSetErrorHandler (gst_evaspixmapsink_handle_xerror);
938
939 #ifdef HAVE_XSHM
940         if (evaspixmapsink->xcontext->use_xshm) {
941                 int expected_size;
942                 evaspixmapbuf->xvimage = XvShmCreateImage (evaspixmapsink->xcontext->disp, evaspixmapsink->xcontext->xv_port_id, evaspixmapbuf->im_format, NULL,
943                 evaspixmapsink->aligned_width, evaspixmapsink->aligned_height, &evaspixmapbuf->SHMInfo);
944                 if (!evaspixmapbuf->xvimage || error_caught) {
945                         if (error_caught) {
946                                 GST_ERROR_OBJECT (evaspixmapsink,"error_caught!");
947                         }
948                         if(!evaspixmapbuf->xvimage) {
949                                 GST_ERROR_OBJECT (evaspixmapsink,"XvShmCreateImage() failed");
950                         }
951                         g_mutex_unlock (evaspixmapsink->x_lock);
952                         /* Reset error handler */
953                         error_caught = FALSE;
954                         XSetErrorHandler (handler);
955                         /* Push an error */
956                         GST_ELEMENT_ERROR (evaspixmapsink, RESOURCE, WRITE,("Failed to create output image buffer of %dx%d pixels",evaspixmapbuf->width,
957                                    evaspixmapbuf->height),("could not XvShmCreateImage a %dx%d image",evaspixmapbuf->width, evaspixmapbuf->height));
958                         goto beach_unlocked;
959                 }
960
961                 /* we have to use the returned data_size for our shm size */
962                 evaspixmapbuf->size = evaspixmapbuf->xvimage->data_size;
963                 GST_LOG_OBJECT (evaspixmapsink,"XShm image size is %" G_GSIZE_FORMAT, evaspixmapbuf->size);
964
965                 /* calculate the expected size.  This is only for sanity checking the
966                 * number we get from X. */
967                 switch (evaspixmapbuf->im_format) {
968                 case GST_MAKE_FOURCC ('I', '4', '2', '0'):
969                 case GST_MAKE_FOURCC ('Y', 'V', '1', '2'):
970                 {
971                         gint pitches[3];
972                         gint offsets[3];
973                         guint plane;
974
975                         offsets[0] = 0;
976                         pitches[0] = GST_ROUND_UP_4 (evaspixmapbuf->width);
977                         offsets[1] = offsets[0] + pitches[0] * GST_ROUND_UP_2 (evaspixmapbuf->height);
978                         pitches[1] = GST_ROUND_UP_8 (evaspixmapbuf->width) / 2;
979                         offsets[2] =
980                         offsets[1] + pitches[1] * GST_ROUND_UP_2 (evaspixmapbuf->height) / 2;
981                         pitches[2] = GST_ROUND_UP_8 (pitches[0]) / 2;
982
983                         expected_size = offsets[2] + pitches[2] * GST_ROUND_UP_2 (evaspixmapbuf->height) / 2;
984
985                         for (plane = 0; plane < evaspixmapbuf->xvimage->num_planes; plane++) {
986                                 GST_DEBUG_OBJECT (evaspixmapsink,"Plane %u has a expected pitch of %d bytes, " "offset of %d",
987                                                 plane, pitches[plane], offsets[plane]);
988                         }
989                         break;
990                 }
991                 case GST_MAKE_FOURCC ('Y', 'U', 'Y', '2'):
992                 case GST_MAKE_FOURCC ('U', 'Y', 'V', 'Y'):
993                         expected_size = evaspixmapbuf->height * GST_ROUND_UP_4 (evaspixmapbuf->width * 2);
994                         break;
995                 case GST_MAKE_FOURCC ('S', 'T', '1', '2'):
996                 case GST_MAKE_FOURCC ('S', 'N', '1', '2'):
997                 case GST_MAKE_FOURCC ('S', 'U', 'Y', 'V'):
998                 case GST_MAKE_FOURCC ('S', 'U', 'Y', '2'):
999                 case GST_MAKE_FOURCC ('S', '4', '2', '0'):
1000                 case GST_MAKE_FOURCC ('S', 'Y', 'V', 'Y'):
1001                 case GST_MAKE_FOURCC ('I', 'T', 'L', 'V'):
1002                 case GST_MAKE_FOURCC ('S', 'R', '3', '2'):
1003                         expected_size = sizeof(SCMN_IMGB);
1004                         break;
1005                 default:
1006                         expected_size = 0;
1007                         break;
1008                 }
1009                 if (expected_size != 0 && evaspixmapbuf->size != expected_size) {
1010                         GST_WARNING_OBJECT (evaspixmapsink,"unexpected XShm image size (got %" G_GSIZE_FORMAT ", expected %d)", evaspixmapbuf->size, expected_size);
1011                 }
1012
1013                 /* Be verbose about our XvImage stride */
1014                 {
1015                         guint plane;
1016                         for (plane = 0; plane < evaspixmapbuf->xvimage->num_planes; plane++) {
1017                                 GST_DEBUG_OBJECT (evaspixmapsink,"Plane %u has a pitch of %d bytes, ""offset of %d", plane,
1018                                                 evaspixmapbuf->xvimage->pitches[plane], evaspixmapbuf->xvimage->offsets[plane]);
1019                         }
1020                 }
1021
1022                 evaspixmapbuf->SHMInfo.shmid = shmget (IPC_PRIVATE, evaspixmapbuf->size,IPC_CREAT | 0777);
1023                 if (evaspixmapbuf->SHMInfo.shmid == -1) {
1024                         g_mutex_unlock (evaspixmapsink->x_lock);
1025                         GST_ELEMENT_ERROR (evaspixmapsink, RESOURCE, WRITE,
1026                                 ("Failed to create output image buffer of %dx%d pixels", evaspixmapbuf->width, evaspixmapbuf->height),
1027                                 ("could not get shared memory of %" G_GSIZE_FORMAT " bytes",evaspixmapbuf->size));
1028                         goto beach_unlocked;
1029                 }
1030
1031                 evaspixmapbuf->SHMInfo.shmaddr = shmat (evaspixmapbuf->SHMInfo.shmid, NULL, 0);
1032                 if (evaspixmapbuf->SHMInfo.shmaddr == ((void *) -1)) {
1033                         g_mutex_unlock (evaspixmapsink->x_lock);
1034                         GST_ELEMENT_ERROR (evaspixmapsink, RESOURCE, WRITE,
1035                                 ("Failed to create output image buffer of %dx%d pixels",
1036                                 evaspixmapbuf->width, evaspixmapbuf->height),
1037                                 ("Failed to shmat: %s", g_strerror (errno)));
1038                         /* Clean up the shared memory segment */
1039                         shmctl (evaspixmapbuf->SHMInfo.shmid, IPC_RMID, NULL);
1040                         goto beach_unlocked;
1041                 }
1042
1043                 evaspixmapbuf->xvimage->data = evaspixmapbuf->SHMInfo.shmaddr;
1044                 evaspixmapbuf->SHMInfo.readOnly = FALSE;
1045
1046                 if (XShmAttach (evaspixmapsink->xcontext->disp, &evaspixmapbuf->SHMInfo) == 0) {
1047                 /* Clean up the shared memory segment */
1048                 shmctl (evaspixmapbuf->SHMInfo.shmid, IPC_RMID, NULL);
1049
1050                 g_mutex_unlock (evaspixmapsink->x_lock);
1051                 GST_ELEMENT_ERROR (evaspixmapsink, RESOURCE, WRITE,
1052                         ("Failed to create output image buffer of %dx%d pixels",
1053                         evaspixmapbuf->width, evaspixmapbuf->height), ("Failed to XShmAttach"));
1054                 goto beach_unlocked;
1055                 }
1056
1057                 XSync (evaspixmapsink->xcontext->disp, FALSE);
1058
1059                 /* Delete the shared memory segment as soon as we everyone is attached.
1060                 * This way, it will be deleted as soon as we detach later, and not
1061                 * leaked if we crash. */
1062                 shmctl (evaspixmapbuf->SHMInfo.shmid, IPC_RMID, NULL);
1063
1064                 GST_DEBUG_OBJECT (evaspixmapsink,"XServer ShmAttached to 0x%x, id 0x%lx", evaspixmapbuf->SHMInfo.shmid, evaspixmapbuf->SHMInfo.shmseg);
1065         } else
1066 #endif /* HAVE_XSHM */
1067         {
1068                 evaspixmapbuf->xvimage = XvCreateImage (evaspixmapsink->xcontext->disp, evaspixmapsink->xcontext->xv_port_id,
1069                 evaspixmapbuf->im_format, NULL, evaspixmapsink->aligned_width, evaspixmapsink->aligned_height);
1070                 if (!evaspixmapbuf->xvimage || error_caught) {
1071                         g_mutex_unlock (evaspixmapsink->x_lock);
1072                         /* Reset error handler */
1073                         error_caught = FALSE;
1074                         XSetErrorHandler (handler);
1075                         /* Push an error */
1076                         GST_ELEMENT_ERROR (evaspixmapsink, RESOURCE, WRITE,
1077                                 ("Failed to create outputimage buffer of %dx%d pixels",
1078                                 evaspixmapbuf->width, evaspixmapbuf->height),
1079                                 ("could not XvCreateImage a %dx%d image",
1080                                 evaspixmapbuf->width, evaspixmapbuf->height));
1081                         goto beach_unlocked;
1082                 }
1083
1084                 /* we have to use the returned data_size for our image size */
1085                 evaspixmapbuf->size = evaspixmapbuf->xvimage->data_size;
1086                 evaspixmapbuf->xvimage->data = g_malloc (evaspixmapbuf->size);
1087
1088                 XSync (evaspixmapsink->xcontext->disp, FALSE);
1089         }
1090
1091         /* Reset error handler */
1092         error_caught = FALSE;
1093         XSetErrorHandler (handler);
1094
1095         succeeded = TRUE;
1096
1097         GST_BUFFER_DATA (evaspixmapbuf) = (guchar *) evaspixmapbuf->xvimage->data;
1098         GST_BUFFER_SIZE (evaspixmapbuf) = evaspixmapbuf->size;
1099
1100         g_mutex_unlock (evaspixmapsink->x_lock);
1101
1102 beach_unlocked:
1103         if (!succeeded) {
1104                 gst_evaspixmap_buffer_free (evaspixmapbuf);
1105                 evaspixmapbuf = NULL;
1106         }
1107
1108         return evaspixmapbuf;
1109 }
1110
1111 /* This function puts a GstEvasPixmapBuffer on a GstEvasPixmapSink's pixmap. Returns FALSE
1112  * if no pixmap was available  */
1113 static gboolean
1114 gst_evaspixmap_buffer_put (GstEvasPixmapSink *evaspixmapsink, GstEvasPixmapBuffer *evaspixmapbuf)
1115 {
1116         GstVideoRectangle result;
1117
1118         GstVideoRectangle src_origin = { 0, 0, 0, 0};
1119         GstVideoRectangle src_input  = { 0, 0, 0, 0};
1120         GstVideoRectangle src = { 0, 0, 0, 0};
1121         GstVideoRectangle dst = { 0, 0, 0, 0};
1122         int rotate = 0;
1123         int ret = 0;
1124         int idx = 0;
1125         GstXPixmap *xpixmap = NULL;
1126
1127         MMTA_ACUM_ITEM_BEGIN("evaspixmapsink evaspixmap_buffer_put()", FALSE);
1128
1129         /* We take the flow_lock. If expose is in there we don't want to run
1130         concurrently from the data flow thread */
1131         g_mutex_lock (evaspixmapsink->flow_lock);
1132
1133         if (G_UNLIKELY (evaspixmapsink->xpixmap[idx] == NULL)) {
1134                 GST_WARNING_OBJECT (evaspixmapsink, "xpixmap is NULL. Skip buffer_put." );
1135                 g_mutex_unlock(evaspixmapsink->flow_lock);
1136                 return FALSE;
1137         }
1138         if (evaspixmapsink->visible == FALSE) {
1139                 GST_WARNING_OBJECT (evaspixmapsink, "visible is FALSE. Skip buffer_put." );
1140                 g_mutex_unlock(evaspixmapsink->flow_lock);
1141                 return TRUE;
1142         }
1143         if (!evaspixmapbuf) {
1144                 GST_WARNING_OBJECT (evaspixmapsink, "evaspixmapbuf is NULL. Skip buffer_put." );
1145                 g_mutex_unlock(evaspixmapsink->flow_lock);
1146                 return TRUE;
1147         }
1148
1149         g_mutex_lock (evaspixmapsink->pixmap_ref_lock);
1150         if (evaspixmapsink->last_updated_idx == -1) {
1151                 /* if it has never been updated any frame in Ecore thread, do below */
1152                 idx = 0;
1153                 xpixmap = evaspixmapsink->xpixmap[idx];
1154                 xpixmap->ref = 1;
1155                 GST_LOG_OBJECT (evaspixmapsink, "last_updated_idx(%d), we use index[%d] of pixmap buffers : pixmap(%d), ref(%d)",
1156                                 evaspixmapsink->last_updated_idx, idx, xpixmap->pixmap, xpixmap->ref);
1157         } else {
1158                 for (idx = 0; idx < evaspixmapsink->num_of_pixmaps; idx++) {
1159                         if (idx == evaspixmapsink->last_updated_idx) {
1160                                 continue;
1161                         } else {
1162                                 xpixmap = evaspixmapsink->xpixmap[idx];
1163                                 if (xpixmap->ref == 0 && xpixmap->damaged_time == 0) {
1164                                         xpixmap->ref++;
1165                                         GST_LOG_OBJECT (evaspixmapsink, "found an available pixmap(%d) : xpixmap[%d]", xpixmap->pixmap, idx);
1166                                         GST_INFO_OBJECT (evaspixmapsink,"pixmap ref-count INCREASED : pixmap(%d), refcount(%d)", xpixmap->pixmap, xpixmap->ref);
1167                                         break;
1168                                 }
1169                         }
1170                 }
1171                 if (idx == evaspixmapsink->num_of_pixmaps) {
1172                         GST_LOG_OBJECT (evaspixmapsink, "Could not find a pixmap with idle state, skip buffer_put." );
1173                         g_mutex_unlock (evaspixmapsink->pixmap_ref_lock);
1174                         g_mutex_unlock(evaspixmapsink->flow_lock);
1175                         return TRUE;
1176                 }
1177         }
1178         g_mutex_unlock (evaspixmapsink->pixmap_ref_lock);
1179
1180         gst_evaspixmapsink_xpixmap_update_geometry(evaspixmapsink, idx);
1181
1182         src.x = src.y = 0;
1183         src_origin.x = src_origin.y = src_input.x = src_input.y = 0;
1184         src_input.w = src_origin.w = evaspixmapsink->video_width;
1185         src_input.h = src_origin.h = evaspixmapsink->video_height;
1186         if (evaspixmapsink->use_origin_size ||
1187                 (evaspixmapsink->rotate_angle == DEGREE_0 ||
1188                 evaspixmapsink->rotate_angle == DEGREE_180)) {
1189                 src.w = src_origin.w;
1190                 src.h = src_origin.h;
1191         } else {
1192                 src.w = src_origin.h;
1193                 src.h = src_origin.w;
1194         }
1195
1196         dst.w = evaspixmapsink->render_rect.w; /* pixmap width */
1197         dst.h = evaspixmapsink->render_rect.h; /* pixmap height */
1198
1199         if (!evaspixmapsink->use_origin_size) {
1200                 static Atom atom_rotation = None;
1201                 static Atom atom_hflip = None;
1202                 static Atom atom_vflip = None;
1203                 gboolean set_hflip = FALSE;
1204                 gboolean set_vflip = FALSE;
1205
1206                 /* compensation of size information (between evas image object's and pixmap's) */
1207                 if (evaspixmapsink->sizediff_width > 1) {
1208                         if (evaspixmapsink->sizediff_height > 1) {
1209                                 dst.w -= (evaspixmapsink->sizediff_width >> 1) << 1;
1210                                 dst.h -= (evaspixmapsink->sizediff_height >> 1) << 1;
1211                         } else {
1212                                 dst.w -= (evaspixmapsink->sizediff_width >> 1) << 1;
1213                         }
1214                 } else if (evaspixmapsink->sizediff_height > 1) {
1215                         dst.h -= (evaspixmapsink->sizediff_height >> 1) << 1;
1216                 }
1217
1218                 switch (evaspixmapsink->display_geometry_method) {
1219                 case DISP_GEO_METHOD_LETTER_BOX:
1220                         gst_video_sink_center_rect (src, dst, &result, TRUE);
1221                         result.x += evaspixmapsink->render_rect.x;
1222                         result.y += evaspixmapsink->render_rect.y;
1223                         GST_DEBUG_OBJECT (evaspixmapsink, "GEO_METHOD : letter box");
1224                         break;
1225                 case DISP_GEO_METHOD_ORIGIN_SIZE:
1226                         gst_video_sink_center_rect (src, dst, &result, FALSE);
1227                         gst_video_sink_center_rect (dst, src, &src_input, FALSE);
1228                         GST_DEBUG_OBJECT (evaspixmapsink, "GEO_METHOD : origin size");
1229                         if (evaspixmapsink->rotate_angle == DEGREE_90 ||
1230                                 evaspixmapsink->rotate_angle == DEGREE_270) {
1231                                 src_input.x = src_input.x ^ src_input.y;
1232                                 src_input.y = src_input.x ^ src_input.y;
1233                                 src_input.x = src_input.x ^ src_input.y;
1234                                 src_input.w = src_input.w ^ src_input.h;
1235                                 src_input.h = src_input.w ^ src_input.h;
1236                                 src_input.w = src_input.w ^ src_input.h;
1237                         }
1238                         break;
1239                 case DISP_GEO_METHOD_FULL_SCREEN:
1240                         result.x = result.y = 0;
1241                         result.w = evaspixmapsink->xpixmap[idx]->width;
1242                         result.h = evaspixmapsink->xpixmap[idx]->height;
1243                         GST_DEBUG_OBJECT (evaspixmapsink, "GEO_METHOD : full screen");
1244                         break;
1245                 case DISP_GEO_METHOD_CROPPED_FULL_SCREEN:
1246                         GST_DEBUG_OBJECT (evaspixmapsink, "GEO_METHOD : cropped full screen");
1247                         gst_video_sink_center_rect(dst, src, &src_input, TRUE);
1248                         result.x = result.y = 0;
1249                         result.w = dst.w;
1250                         result.h = dst.h;
1251                         if (evaspixmapsink->rotate_angle == DEGREE_90 ||
1252                                 evaspixmapsink->rotate_angle == DEGREE_270) {
1253                                 src_input.x = src_input.x ^ src_input.y;
1254                                 src_input.y = src_input.x ^ src_input.y;
1255                                 src_input.x = src_input.x ^ src_input.y;
1256                                 src_input.w = src_input.w ^ src_input.h;
1257                                 src_input.h = src_input.w ^ src_input.h;
1258                                 src_input.w = src_input.w ^ src_input.h;
1259                         }
1260                         break;
1261                 case DISP_GEO_METHOD_CUSTOM_ROI:
1262                         switch (evaspixmapsink->rotate_angle) {
1263                         case DEGREE_90:
1264                                 result.w = evaspixmapsink->dst_roi.h;
1265                                 result.h = evaspixmapsink->dst_roi.w;
1266                                 result.x = evaspixmapsink->dst_roi.y;
1267                                 result.y = evaspixmapsink->xpixmap[idx]->height - evaspixmapsink->dst_roi.x - evaspixmapsink->dst_roi.w;
1268                                 break;
1269                         case DEGREE_180:
1270                                 result.w = evaspixmapsink->dst_roi.w;
1271                                 result.h = evaspixmapsink->dst_roi.h;
1272                                 result.x = evaspixmapsink->xpixmap[idx]->width - result.w - evaspixmapsink->dst_roi.x;
1273                                 result.y = evaspixmapsink->xpixmap[idx]->height - result.h - evaspixmapsink->dst_roi.y;
1274                                 break;
1275                         case DEGREE_270:
1276                                 result.w = evaspixmapsink->dst_roi.h;
1277                                 result.h = evaspixmapsink->dst_roi.w;
1278                                 result.x = evaspixmapsink->xpixmap[idx]->width - evaspixmapsink->dst_roi.y - evaspixmapsink->dst_roi.h;
1279                                 result.y = evaspixmapsink->dst_roi.x;
1280                                 break;
1281                         default:
1282                                 result.x = evaspixmapsink->dst_roi.x;
1283                                 result.y = evaspixmapsink->dst_roi.y;
1284                                 result.w = evaspixmapsink->dst_roi.w;
1285                                 result.h = evaspixmapsink->dst_roi.h;
1286                                 break;
1287                         }
1288                         GST_LOG_OBJECT(evaspixmapsink, "rotate[%d], ROI input[%d,%d,%dx%d] > result[%d,%d,%dx%d]",
1289                                         evaspixmapsink->rotate_angle,
1290                                         evaspixmapsink->dst_roi.x, evaspixmapsink->dst_roi.y, evaspixmapsink->dst_roi.w, evaspixmapsink->dst_roi.h,
1291                                         result.x, result.y, result.w, result.h);
1292                         break;
1293                 default:
1294                         break;
1295                 }
1296                 GST_DEBUG_OBJECT (evaspixmapsink, "GEO_METHOD : src(%dx%d), dst(%dx%d), result(%dx%d), result_x(%d), result_y(%d)",
1297                                 src.w,src.h,dst.w,dst.h,result.w,result.h,result.x,result.y);
1298
1299                 switch( evaspixmapsink->rotate_angle ) {
1300                         case DEGREE_0:
1301                         break;
1302                         case DEGREE_90:
1303                         rotate = 270;
1304                         break;
1305                         case DEGREE_180:
1306                         rotate = 180;
1307                         break;
1308                         case DEGREE_270:
1309                         rotate = 90;
1310                         break;
1311                         default:
1312                         GST_WARNING_OBJECT( evaspixmapsink, "Unsupported rotation [%d]... set DEGREE 0.",
1313                                         evaspixmapsink->rotate_angle );
1314                         break;
1315                 }
1316
1317                 /* set display rotation */
1318                 if (atom_rotation == None) {
1319                         atom_rotation = XInternAtom(evaspixmapsink->xcontext->disp, "_USER_WM_PORT_ATTRIBUTE_ROTATION", False);
1320                 }
1321
1322                 ret = XvSetPortAttribute(evaspixmapsink->xcontext->disp, evaspixmapsink->xcontext->xv_port_id, atom_rotation, rotate);
1323                 if (ret != Success) {
1324                         GST_ERROR_OBJECT( evaspixmapsink, "XvSetPortAttribute failed[%d]. disp[%x],xv_port_id[%d],atom[%x],rotate[%d]",
1325                                         ret, evaspixmapsink->xcontext->disp, evaspixmapsink->xcontext->xv_port_id, atom_rotation, rotate );
1326                         return FALSE;
1327                 }
1328
1329                 /* set display flip */
1330                 if (atom_hflip == None) {
1331                         atom_hflip = XInternAtom(evaspixmapsink->xcontext->disp, "_USER_WM_PORT_ATTRIBUTE_HFLIP", False);
1332                 }
1333                 if (atom_vflip == None) {
1334                         atom_vflip = XInternAtom(evaspixmapsink->xcontext->disp, "_USER_WM_PORT_ATTRIBUTE_VFLIP", False);
1335                 }
1336
1337                 switch (evaspixmapsink->flip) {
1338                 case FLIP_HORIZONTAL:
1339                         set_hflip = TRUE;
1340                         set_vflip = FALSE;
1341                         break;
1342                 case FLIP_VERTICAL:
1343                         set_hflip = FALSE;
1344                         set_vflip = TRUE;
1345                         break;
1346                 case FLIP_BOTH:
1347                         set_hflip = TRUE;
1348                         set_vflip = TRUE;
1349                         break;
1350                 case FLIP_NONE:
1351                 default:
1352                         set_hflip = FALSE;
1353                         set_vflip = FALSE;
1354                         break;
1355                 }
1356                 GST_INFO_OBJECT(evaspixmapsink, "set rotate %d HFLIP %d, VFLIP %d", rotate, set_hflip, set_vflip);
1357
1358                 ret = XvSetPortAttribute(evaspixmapsink->xcontext->disp, evaspixmapsink->xcontext->xv_port_id, atom_hflip, set_hflip);
1359                 if (ret != Success) {
1360                         GST_WARNING("set HFLIP failed[%d]. disp[%x],xv_port_id[%d],atom[%x],hflip[%d]",
1361                                         ret, evaspixmapsink->xcontext->disp, evaspixmapsink->xcontext->xv_port_id, atom_hflip, set_hflip);
1362                 }
1363                 ret = XvSetPortAttribute(evaspixmapsink->xcontext->disp, evaspixmapsink->xcontext->xv_port_id, atom_vflip, set_vflip);
1364                 if (ret != Success) {
1365                         GST_WARNING("set VFLIP failed[%d]. disp[%x],xv_port_id[%d],atom[%x],vflip[%d]",
1366                                         ret, evaspixmapsink->xcontext->disp, evaspixmapsink->xcontext->xv_port_id, atom_vflip, set_vflip);
1367                 }
1368
1369         } else {
1370                 result.x = result.y = 0;
1371                 result.w = evaspixmapsink->xpixmap[idx]->width;
1372                 result.h = evaspixmapsink->xpixmap[idx]->height;
1373                 GST_INFO_OBJECT (evaspixmapsink, "USE ORIGIN SIZE, no geometry method, no rotation/flip" );
1374         }
1375
1376         g_mutex_lock (evaspixmapsink->x_lock);
1377
1378   /* We scale to the pixmap's geometry */
1379 #ifdef HAVE_XSHM
1380         if (evaspixmapsink->xcontext->use_xshm) {
1381                 GST_LOG_OBJECT (evaspixmapsink,"XvShmPutImage with image %dx%d and pixmap %dx%d, from xvimage %"
1382                                 GST_PTR_FORMAT,
1383                                 evaspixmapbuf->width, evaspixmapbuf->height,
1384                                 evaspixmapsink->render_rect.w, evaspixmapsink->render_rect.h, evaspixmapbuf);
1385
1386         /* Trim as proper size */
1387         if (src_input.w % 2 == 1) {
1388                 src_input.w += 1;
1389         }
1390         if (src_input.h % 2 == 1) {
1391                 src_input.h += 1;
1392         }
1393
1394         GST_LOG_OBJECT (evaspixmapsink, "screen[%dx%d],pixmap[%d,%d,%dx%d],method[%d],rotate[%d],src[%dx%d],dst[%d,%d,%dx%d],input[%d,%d,%dx%d],result[%d,%d,%dx%d]",
1395                 evaspixmapsink->scr_w, evaspixmapsink->scr_h,
1396                 evaspixmapsink->xpixmap[idx]->x, evaspixmapsink->xpixmap[idx]->y, evaspixmapsink->xpixmap[idx]->width, evaspixmapsink->xpixmap[idx]->height,
1397                 evaspixmapsink->display_geometry_method, rotate,
1398                 src_origin.w, src_origin.h,
1399                 dst.x, dst.y, dst.w, dst.h,
1400                 src_input.x, src_input.y, src_input.w, src_input.h,
1401                 result.x, result.y, result.w, result.h );
1402
1403         if (evaspixmapsink->visible) {
1404                 if (evaspixmapsink->buf_shared_type == BUF_SHARE_METHOD_FD) {
1405                         EVASPIXMAPSINK_SET_PIXMAP_ID_TO_GEM_INFO (evaspixmapsink, evaspixmapsink->xpixmap[idx]->pixmap);
1406                 }
1407                 ret = XvShmPutImage (evaspixmapsink->xcontext->disp,
1408                         evaspixmapsink->xcontext->xv_port_id,
1409                         evaspixmapsink->xpixmap[idx]->pixmap,
1410                         evaspixmapsink->xpixmap[idx]->gc, evaspixmapbuf->xvimage,
1411                         src_input.x, src_input.y, src_input.w, src_input.h,
1412                         result.x, result.y, result.w, result.h, FALSE);
1413                 GST_LOG_OBJECT (evaspixmapsink, "XvShmPutImage return value [%d]", ret );
1414         } else {
1415                 GST_WARNING_OBJECT (evaspixmapsink, "visible is FALSE. skip this image..." );
1416         }
1417   } else
1418 #endif /* HAVE_XSHM */
1419         {
1420                 if (evaspixmapsink->visible) {
1421                         XvPutImage (evaspixmapsink->xcontext->disp,
1422                                         evaspixmapsink->xcontext->xv_port_id,
1423                                         evaspixmapsink->xpixmap[idx]->pixmap,
1424                                         evaspixmapsink->xpixmap[idx]->gc, evaspixmapbuf->xvimage,
1425                                         evaspixmapsink->disp_x, evaspixmapsink->disp_y,
1426                                         evaspixmapsink->disp_width, evaspixmapsink->disp_height,
1427                                         result.x, result.y, result.w, result.h);
1428                 } else {
1429                         GST_WARNING_OBJECT (evaspixmapsink, "visible is FALSE. skip this image..." );
1430                 }
1431         }
1432         XSync (evaspixmapsink->xcontext->disp, FALSE);
1433
1434         g_mutex_unlock (evaspixmapsink->x_lock);
1435         g_mutex_unlock (evaspixmapsink->flow_lock);
1436
1437         MMTA_ACUM_ITEM_END("evaspixmapsink evaspixmap_buffer_put()", FALSE);
1438
1439         return TRUE;
1440 }
1441
1442 static int
1443 drm_init(GstEvasPixmapSink *evaspixmapsink)
1444 {
1445         Display *dpy;
1446         int i = 0;
1447         int eventBase = 0;
1448         int errorBase = 0;
1449         int dri2Major = 0;
1450         int dri2Minor = 0;
1451         char *driverName = NULL;
1452         char *deviceName = NULL;
1453         struct drm_auth auth_arg = {0};
1454
1455         evaspixmapsink->drm_fd = -1;
1456
1457         dpy = XOpenDisplay(0);
1458
1459         /* DRI2 */
1460         if (!DRI2QueryExtension(dpy, &eventBase, &errorBase)) {
1461                 GST_ERROR_OBJECT (evaspixmapsink,"failed to DRI2QueryExtension()");
1462                 goto ERROR_CASE;
1463         }
1464
1465         if (!DRI2QueryVersion(dpy, &dri2Major, &dri2Minor)) {
1466                 GST_ERROR_OBJECT (evaspixmapsink,"failed to DRI2QueryVersion");
1467                 goto ERROR_CASE;
1468         }
1469
1470         if (!DRI2Connect(dpy, RootWindow(dpy, DefaultScreen(dpy)), &driverName, &deviceName)) {
1471                 GST_ERROR_OBJECT (evaspixmapsink,"failed to DRI2Connect");
1472                 goto ERROR_CASE;
1473         }
1474
1475         if (!driverName || !deviceName) {
1476                 GST_ERROR_OBJECT (evaspixmapsink,"driverName or deviceName is not valid");
1477                 goto ERROR_CASE;
1478         }
1479
1480         GST_INFO_OBJECT (evaspixmapsink,"Open drm device : %s", deviceName);
1481
1482         /* get the drm_fd though opening the deviceName */
1483         evaspixmapsink->drm_fd = open(deviceName, O_RDWR);
1484         if (evaspixmapsink->drm_fd < 0) {
1485                 GST_ERROR_OBJECT (evaspixmapsink,"cannot open drm device (%s)", deviceName);
1486                 goto ERROR_CASE;
1487         }
1488
1489         /* get magic from drm to authentication */
1490         if (ioctl(evaspixmapsink->drm_fd, DRM_IOCTL_GET_MAGIC, &auth_arg)) {
1491                 GST_ERROR_OBJECT (evaspixmapsink,"cannot get drm auth magic");
1492                 close(evaspixmapsink->drm_fd);
1493                 evaspixmapsink->drm_fd = -1;
1494                 goto ERROR_CASE;
1495         }
1496
1497         if (!DRI2Authenticate(dpy, RootWindow(dpy, DefaultScreen(dpy)), auth_arg.magic)) {
1498                 GST_ERROR_OBJECT (evaspixmapsink,"cannot get drm authentication from X");
1499                 close(evaspixmapsink->drm_fd);
1500                 evaspixmapsink->drm_fd = -1;
1501                 goto ERROR_CASE;
1502         }
1503
1504         /* init gem handle */
1505         for (i = 0; i < MAX_GEM_BUFFER_NUM; i++) {
1506                 evaspixmapsink->gem_info[i].dmabuf_fd = 0;
1507                 evaspixmapsink->gem_info[i].gem_handle = 0;
1508                 evaspixmapsink->gem_info[i].gem_name = 0;
1509                 evaspixmapsink->gem_info[i].bo = 0;
1510                 evaspixmapsink->gem_info[i].ref_pixmap = 0;
1511         }
1512
1513         XCloseDisplay(dpy);
1514         free(driverName);
1515         free(deviceName);
1516
1517         return 0;
1518
1519 ERROR_CASE:
1520         XCloseDisplay(dpy);
1521         if (driverName) {
1522                 free(driverName);
1523         }
1524         if (deviceName) {
1525                 free(deviceName);
1526         }
1527
1528         return -1;
1529 }
1530
1531 static void
1532 drm_fini(GstEvasPixmapSink *evaspixmapsink)
1533 {
1534         if (evaspixmapsink->drm_fd >= 0) {
1535                 GST_INFO_OBJECT (evaspixmapsink,"close drm_fd(%d)", evaspixmapsink->drm_fd);
1536                 close(evaspixmapsink->drm_fd);
1537                 evaspixmapsink->drm_fd = -1;
1538         }
1539 }
1540
1541 static unsigned int
1542 drm_init_convert_dmabuf_gemname(GstEvasPixmapSink *evaspixmapsink, int dmabuf_fd)
1543 {
1544         struct drm_prime_handle prime_arg = {0,};
1545         struct drm_gem_flink flink_arg = {0,};
1546         int i = 0;
1547
1548         if (evaspixmapsink->drm_fd < 0) {
1549                 GST_ERROR_OBJECT (evaspixmapsink,"DRM is not opened");
1550                 return 0;
1551         }
1552
1553         if (dmabuf_fd <= 0) {
1554                 GST_DEBUG_OBJECT (evaspixmapsink,"Ignore wrong dmabuf fd(%d)", dmabuf_fd);              /* temporarily change log level to DEBUG for reducing WARNING level log */
1555                 return 0;
1556         }
1557
1558         /* check duplicated dmabuf fd */
1559         for (i = 0 ; i < MAX_GEM_BUFFER_NUM ; i++) {
1560                 if (evaspixmapsink->gem_info[i].dmabuf_fd == dmabuf_fd) {
1561                         GST_LOG_OBJECT (evaspixmapsink,"already got fd(%u) with name(%u)", dmabuf_fd, evaspixmapsink->gem_info[i].gem_name);
1562                         return evaspixmapsink->gem_info[i].gem_name;
1563                 }
1564
1565                 if (evaspixmapsink->gem_info[i].dmabuf_fd == 0) {
1566                         GST_LOG_OBJECT (evaspixmapsink,"empty gem_info[%d] found", i);
1567                         break;
1568                 }
1569         }
1570
1571         if (i == MAX_GEM_BUFFER_NUM) {
1572                 GST_WARNING_OBJECT (evaspixmapsink,"too many buffers[dmabuf_fd(%d). skip it]", dmabuf_fd);
1573                 return 0;
1574         }
1575
1576         evaspixmapsink->gem_info[i].dmabuf_fd = dmabuf_fd;
1577         prime_arg.fd = dmabuf_fd;
1578         if (ioctl(evaspixmapsink->drm_fd, DRM_IOCTL_PRIME_FD_TO_HANDLE, &prime_arg)) {
1579                 GST_ERROR_OBJECT (evaspixmapsink,"non dmabuf fd(%d)", dmabuf_fd);
1580                 return 0;
1581         }
1582
1583         evaspixmapsink->gem_info[i].gem_handle = prime_arg.handle;
1584         GST_LOG_OBJECT (evaspixmapsink,"gem_info[%d].gem_handle = %u", i, prime_arg.handle);
1585
1586         flink_arg.handle = prime_arg.handle;
1587         if (ioctl(evaspixmapsink->drm_fd, DRM_IOCTL_GEM_FLINK, &flink_arg)) {
1588                 GST_ERROR_OBJECT (evaspixmapsink,"cannot convert drm handle to name");
1589                 return 0;
1590         }
1591
1592         evaspixmapsink->gem_info[i].gem_name = flink_arg.name;
1593         GST_LOG_OBJECT (evaspixmapsink,"gem_info[%d].gem_name = %u", i, flink_arg.name);
1594
1595         return flink_arg.name;
1596 }
1597
1598 static unsigned int
1599 tbm_init_convert_bo_gemname(GstEvasPixmapSink *evaspixmapsink, tbm_bo bo)
1600 {
1601         int i = 0;
1602
1603         if (bo == NULL) {
1604                 GST_DEBUG_OBJECT (evaspixmapsink,"Ignore wrong bo(%u)", bo);            /* temporarily change log level to DEBUG for reducing WARNING level log */
1605                 return 0;
1606         }
1607
1608         /* check duplicated dmabuf bo */
1609         for (i = 0 ; i < MAX_GEM_BUFFER_NUM ; i++) {
1610                 if (evaspixmapsink->gem_info[i].bo == bo) {
1611                         GST_LOG_OBJECT (evaspixmapsink,"already got bo(%u) with name(%u)", bo, evaspixmapsink->gem_info[i].gem_name);
1612                         return evaspixmapsink->gem_info[i].gem_name;
1613                 }
1614
1615                 if (evaspixmapsink->gem_info[i].bo == 0) {
1616                         GST_LOG_OBJECT (evaspixmapsink,"empty gem_info[%d] found", i);
1617                         break;
1618                 }
1619         }
1620
1621         if (i == MAX_GEM_BUFFER_NUM) {
1622                 GST_WARNING_OBJECT (evaspixmapsink,"too many buffers[dmabuf_bo(%d). skip it]", bo);
1623                 return 0;
1624         }
1625
1626         evaspixmapsink->gem_info[i].bo = bo;
1627         evaspixmapsink->gem_info[i].gem_name = tbm_bo_export(bo);
1628         GST_LOG_OBJECT (evaspixmapsink,"gem_info[%d].gem_name = %u", i, evaspixmapsink->gem_info[i].gem_name);
1629
1630         return evaspixmapsink->gem_info[i].gem_name;
1631 }
1632
1633 static void
1634 drm_fini_close_gem_handle(GstEvasPixmapSink *evaspixmapsink, Pixmap pixmap_id)
1635 {
1636         int i = 0;
1637         if (evaspixmapsink->drm_fd >= 0) {
1638                 if (pixmap_id == 0) {
1639                         for (i = 0; i < MAX_GEM_BUFFER_NUM; i++) {
1640                                 if (evaspixmapsink->gem_info[i].dmabuf_fd > 0 || evaspixmapsink->gem_info[i].bo > 0) {
1641                                         if (evaspixmapsink->buf_shared_type == BUF_SHARE_METHOD_FD) {
1642                                                 GST_INFO_OBJECT (evaspixmapsink,"close gem_handle(%u)", evaspixmapsink->gem_info[i].gem_handle);
1643                                                 drm_close_gem(evaspixmapsink, evaspixmapsink->gem_info[i].gem_handle);
1644                                         }
1645                                         evaspixmapsink->gem_info[i].dmabuf_fd = 0;
1646                                         evaspixmapsink->gem_info[i].gem_handle = 0;
1647                                         evaspixmapsink->gem_info[i].gem_name = 0;
1648                                         evaspixmapsink->gem_info[i].bo = 0;
1649                                         evaspixmapsink->gem_info[i].ref_pixmap = 0;
1650                                         GST_LOG_OBJECT (evaspixmapsink,"gem_info[%d] is cleared",i);
1651                                 }
1652                         }
1653                 } else {
1654                         for (i = 0; i < MAX_GEM_BUFFER_NUM; i++) {
1655                                 if (evaspixmapsink->gem_info[i].ref_pixmap == pixmap_id) {
1656                                         if (evaspixmapsink->buf_shared_type == BUF_SHARE_METHOD_FD) {
1657                                                 GST_INFO_OBJECT (evaspixmapsink,"close gem_handle(%u) for pixmap_id(%d)",
1658                                                                                 evaspixmapsink->gem_info[i].gem_handle, pixmap_id);
1659                                                 drm_close_gem(evaspixmapsink, evaspixmapsink->gem_info[i].gem_handle);
1660                                         }
1661                                         evaspixmapsink->gem_info[i].dmabuf_fd = 0;
1662                                         evaspixmapsink->gem_info[i].gem_handle = 0;
1663                                         evaspixmapsink->gem_info[i].gem_name = 0;
1664                                         evaspixmapsink->gem_info[i].bo = 0;
1665                                         evaspixmapsink->gem_info[i].ref_pixmap = 0;
1666                                         GST_LOG_OBJECT (evaspixmapsink,"gem_info[%d] is cleared",i);
1667                                         break;
1668                                 }
1669                         }
1670                 }
1671         }
1672 }
1673
1674 static void
1675 drm_close_gem(GstEvasPixmapSink *evaspixmapsink, unsigned int gem_handle)
1676 {
1677         struct drm_gem_close close_arg = {0,};
1678
1679         if (evaspixmapsink->drm_fd < 0) {
1680                 GST_ERROR_OBJECT (evaspixmapsink,"DRM is not opened");
1681                 return;
1682         }
1683
1684         if (gem_handle == 0) {
1685                 GST_ERROR_OBJECT (evaspixmapsink,"invalid gem_handle(%d)",gem_handle);
1686                 return;
1687         }
1688
1689         close_arg.handle = gem_handle;
1690         if (gem_handle > 0 && ioctl(evaspixmapsink->drm_fd, DRM_IOCTL_GEM_CLOSE, &close_arg)) {
1691                 GST_ERROR_OBJECT (evaspixmapsink,"cannot close drm gem handle(%d)", gem_handle);
1692                 return;
1693         }
1694
1695         return;
1696 }
1697
1698 /* This function destroys a GstXPixmap */
1699 static void
1700 gst_evaspixmapsink_xpixmap_destroy (GstEvasPixmapSink *evaspixmapsink, GstXPixmap *xpixmap)
1701 {
1702         g_return_if_fail (xpixmap != NULL);
1703         g_return_if_fail (GST_IS_EVASPIXMAPSINK (evaspixmapsink));
1704
1705         g_mutex_lock (evaspixmapsink->x_lock);
1706
1707         if(xpixmap->pixmap) {
1708                 GST_LOG_OBJECT (evaspixmapsink,"Free pixmap(%d)", xpixmap->pixmap);
1709                 XFreePixmap(evaspixmapsink->xcontext->disp, xpixmap->pixmap);
1710                 xpixmap->pixmap = 0;
1711         }
1712
1713         if (xpixmap->gc) {
1714                 XFreeGC (evaspixmapsink->xcontext->disp, xpixmap->gc);
1715         }
1716
1717         XSync (evaspixmapsink->xcontext->disp, FALSE);
1718
1719         g_mutex_unlock (evaspixmapsink->x_lock);
1720
1721         g_free (xpixmap);
1722 }
1723
1724 static void
1725 gst_evaspixmapsink_xpixmap_update_geometry (GstEvasPixmapSink *evaspixmapsink, int idx)
1726 {
1727         Window root_window;
1728         XWindowAttributes root_attr;
1729
1730         int cur_pixmap_x = 0;
1731         int cur_pixmap_y = 0;
1732         unsigned int cur_pixmap_width = 0;
1733         unsigned int cur_pixmap_height = 0;
1734         unsigned int cur_pixmap_border_width = 0;
1735         unsigned int cur_pixmap_depth = 0;
1736
1737         g_return_if_fail (GST_IS_EVASPIXMAPSINK (evaspixmapsink));
1738
1739         /* Update the window geometry */
1740         g_mutex_lock (evaspixmapsink->x_lock);
1741         if (G_UNLIKELY (evaspixmapsink->xpixmap[idx] == NULL)) {
1742                 g_mutex_unlock (evaspixmapsink->x_lock);
1743                 return;
1744         }
1745
1746         /* Get root window and size of current pixmap */
1747         XGetGeometry( evaspixmapsink->xcontext->disp, evaspixmapsink->xpixmap[idx]->pixmap, &root_window,
1748                         &cur_pixmap_x, &cur_pixmap_y, /* relative x, y, for pixmap these are alway 0 */
1749                         &cur_pixmap_width, &cur_pixmap_height,
1750                         &cur_pixmap_border_width, &cur_pixmap_depth ); /* cur_pixmap_border_width, cur_pixmap_depth are not used */
1751
1752         evaspixmapsink->xpixmap[idx]->width = cur_pixmap_width;
1753         evaspixmapsink->xpixmap[idx]->height = cur_pixmap_height;
1754
1755         evaspixmapsink->xpixmap[idx]->x = cur_pixmap_x;
1756         evaspixmapsink->xpixmap[idx]->y = cur_pixmap_y;
1757
1758         /* Get size of root window == size of screen */
1759         XGetWindowAttributes(evaspixmapsink->xcontext->disp, root_window, &root_attr);
1760
1761         evaspixmapsink->scr_w = root_attr.width;
1762         evaspixmapsink->scr_h = root_attr.height;
1763
1764         if (!evaspixmapsink->have_render_rect) {
1765                 evaspixmapsink->render_rect.x = evaspixmapsink->render_rect.y = 0;
1766                 evaspixmapsink->render_rect.w = cur_pixmap_width;
1767                 evaspixmapsink->render_rect.h = cur_pixmap_height;
1768         }
1769
1770         GST_LOG_OBJECT (evaspixmapsink,"screen size %dx%d, current pixmap geometry %d,%d,%dx%d, render_rect %d,%d,%dx%d",
1771                         evaspixmapsink->scr_w, evaspixmapsink->scr_h,
1772                         evaspixmapsink->xpixmap[idx]->x, evaspixmapsink->xpixmap[idx]->y,
1773                         evaspixmapsink->xpixmap[idx]->width, evaspixmapsink->xpixmap[idx]->height,
1774                         evaspixmapsink->render_rect.x, evaspixmapsink->render_rect.y,
1775                         evaspixmapsink->render_rect.w, evaspixmapsink->render_rect.h);
1776
1777         g_mutex_unlock (evaspixmapsink->x_lock);
1778 }
1779
1780 static void
1781 gst_evaspixmapsink_xpixmap_clear (GstEvasPixmapSink *evaspixmapsink, GstXPixmap *xpixmap)
1782 {
1783         g_return_if_fail (xpixmap != NULL);
1784         g_return_if_fail (GST_IS_EVASPIXMAPSINK (evaspixmapsink));
1785
1786         if (!xpixmap->pixmap) {
1787                 GST_WARNING_OBJECT (evaspixmapsink,"pixmap was not created..");
1788                 return;
1789         }
1790
1791         g_mutex_lock (evaspixmapsink->x_lock);
1792
1793         if (!evaspixmapsink->xcontext) {
1794                 GST_WARNING_OBJECT (evaspixmapsink,"xcontext is null..");
1795                 g_mutex_unlock (evaspixmapsink->x_lock);
1796                 return;
1797         }
1798
1799         if (evaspixmapsink->stop_video) {
1800                 XvStopVideo (evaspixmapsink->xcontext->disp, evaspixmapsink->xcontext->xv_port_id, xpixmap->pixmap);
1801         }
1802         XSync (evaspixmapsink->xcontext->disp, FALSE);
1803
1804         g_mutex_unlock (evaspixmapsink->x_lock);
1805
1806         g_mutex_lock (evaspixmapsink->pixmap_ref_lock);
1807         evaspixmapsink->last_updated_idx = -1;
1808         xpixmap->ref = 0;
1809         xpixmap->damaged_time = 0;
1810         g_mutex_unlock (evaspixmapsink->pixmap_ref_lock);
1811 }
1812
1813 /* This function commits our internal colorbalance settings to our grabbed Xv
1814    port. If the xcontext is not initialized yet it simply returns */
1815 static void
1816 gst_evaspixmapsink_update_colorbalance (GstEvasPixmapSink *evaspixmapsink)
1817 {
1818   GList *channels = NULL;
1819
1820   g_return_if_fail (GST_IS_EVASPIXMAPSINK (evaspixmapsink));
1821
1822   /* If we haven't initialized the X context we can't update anything */
1823   if (evaspixmapsink->xcontext == NULL)
1824     return;
1825
1826   /* Don't set the attributes if they haven't been changed, to avoid
1827    * rounding errors changing the values */
1828   if (!evaspixmapsink->cb_changed)
1829     return;
1830
1831   /* For each channel of the colorbalance we calculate the correct value
1832      doing range conversion and then set the Xv port attribute to match our
1833      values. */
1834   channels = evaspixmapsink->xcontext->channels_list;
1835
1836   while (channels) {
1837     if (channels->data && GST_IS_COLOR_BALANCE_CHANNEL (channels->data)) {
1838       GstColorBalanceChannel *channel = NULL;
1839       Atom prop_atom;
1840       gint value = 0;
1841       gdouble convert_coef;
1842
1843       channel = GST_COLOR_BALANCE_CHANNEL (channels->data);
1844       g_object_ref (channel);
1845
1846       /* Our range conversion coef */
1847       convert_coef = (channel->max_value - channel->min_value) / 2000.0;
1848
1849       if (g_ascii_strcasecmp (channel->label, "XV_HUE") == 0) {
1850         value = evaspixmapsink->hue;
1851       } else if (g_ascii_strcasecmp (channel->label, "XV_SATURATION") == 0) {
1852         value = evaspixmapsink->saturation;
1853       } else if (g_ascii_strcasecmp (channel->label, "XV_CONTRAST") == 0) {
1854         value = evaspixmapsink->contrast;
1855       } else if (g_ascii_strcasecmp (channel->label, "XV_BRIGHTNESS") == 0) {
1856         value = evaspixmapsink->brightness;
1857       } else {
1858         g_warning ("got an unknown channel %s", channel->label);
1859         g_object_unref (channel);
1860         return;
1861       }
1862
1863       /* Committing to Xv port */
1864       g_mutex_lock (evaspixmapsink->x_lock);
1865       prop_atom =
1866           XInternAtom (evaspixmapsink->xcontext->disp, channel->label, True);
1867       if (prop_atom != None) {
1868         int xv_value;
1869         xv_value =
1870             floor (0.5 + (value + 1000) * convert_coef + channel->min_value);
1871         XvSetPortAttribute (evaspixmapsink->xcontext->disp,
1872             evaspixmapsink->xcontext->xv_port_id, prop_atom, xv_value);
1873       }
1874       g_mutex_unlock (evaspixmapsink->x_lock);
1875
1876       g_object_unref (channel);
1877     }
1878     channels = g_list_next (channels);
1879   }
1880 }
1881
1882 static void
1883 gst_lookup_xv_port_from_adaptor (GstXContext *xcontext, XvAdaptorInfo *adaptors, int adaptor_no)
1884 {
1885   gint j;
1886   gint res;
1887
1888   /* Do we support XvImageMask ? */
1889   if (!(adaptors[adaptor_no].type & XvImageMask)) {
1890     GST_DEBUG ("XV Adaptor %s has no support for XvImageMask", adaptors[adaptor_no].name);
1891     return;
1892   }
1893
1894   /* We found such an adaptor, looking for an available port */
1895   for (j = 0; j < adaptors[adaptor_no].num_ports && !xcontext->xv_port_id; j++) {
1896     /* We try to grab the port */
1897     res = XvGrabPort (xcontext->disp, adaptors[adaptor_no].base_id + j, 0);
1898     if (Success == res) {
1899       xcontext->xv_port_id = adaptors[adaptor_no].base_id + j;
1900       GST_DEBUG ("XV Adaptor %s with %ld ports", adaptors[adaptor_no].name, adaptors[adaptor_no].num_ports);
1901     } else {
1902       GST_DEBUG ("GrabPort %d for XV Adaptor %s failed: %d", j, adaptors[adaptor_no].name, res);
1903     }
1904   }
1905 }
1906
1907 /* This function generates a caps with all supported format by the first
1908    Xv grabable port we find. We store each one of the supported formats in a
1909    format list and append the format to a newly created caps that we return
1910    If this function does not return NULL because of an error, it also grabs
1911    the port via XvGrabPort */
1912 static GstCaps*
1913 gst_evaspixmapsink_get_xv_support (GstEvasPixmapSink *evaspixmapsink, GstXContext *xcontext)
1914 {
1915   gint i;
1916   XvAdaptorInfo *adaptors;
1917   gint nb_formats;
1918   XvImageFormatValues *formats = NULL;
1919   guint nb_encodings;
1920   XvEncodingInfo *encodings = NULL;
1921   gulong max_w = G_MAXINT, max_h = G_MAXINT;
1922   GstCaps *caps = NULL;
1923   GstCaps *rgb_caps = NULL;
1924
1925   g_return_val_if_fail (xcontext != NULL, NULL);
1926
1927   /* First let's check that XVideo extension is available */
1928   if (!XQueryExtension (xcontext->disp, "XVideo", &i, &i, &i)) {
1929     GST_ELEMENT_ERROR (evaspixmapsink, RESOURCE, SETTINGS,
1930         ("Could not initialise Xv output"),
1931         ("XVideo extension is not available"));
1932     return NULL;
1933   }
1934
1935   /* Then we get adaptors list */
1936   if (Success != XvQueryAdaptors (xcontext->disp, xcontext->root,
1937           &xcontext->nb_adaptors, &adaptors)) {
1938     GST_ELEMENT_ERROR (evaspixmapsink, RESOURCE, SETTINGS,
1939         ("Could not initialise Xv output"),
1940         ("Failed getting XV adaptors list"));
1941     return NULL;
1942   }
1943
1944   xcontext->xv_port_id = 0;
1945
1946   GST_DEBUG_OBJECT (evaspixmapsink,"Found %u XV adaptor(s)", xcontext->nb_adaptors);
1947
1948   xcontext->adaptors =
1949       (gchar **) g_malloc0 (xcontext->nb_adaptors * sizeof (gchar *));
1950
1951   /* Now fill up our adaptor name array */
1952   for (i = 0; i < xcontext->nb_adaptors; i++) {
1953     xcontext->adaptors[i] = g_strdup (adaptors[i].name);
1954   }
1955
1956   if (evaspixmapsink->adaptor_no < xcontext->nb_adaptors) {
1957     /* Find xv port from user defined adaptor */
1958     gst_lookup_xv_port_from_adaptor (xcontext, adaptors, evaspixmapsink->adaptor_no);
1959   }
1960
1961   if (!xcontext->xv_port_id) {
1962     /* Now search for an adaptor that supports XvImageMask */
1963     for (i = 0; i < xcontext->nb_adaptors && !xcontext->xv_port_id; i++) {
1964       gst_lookup_xv_port_from_adaptor (xcontext, adaptors, i);
1965       evaspixmapsink->adaptor_no = i;
1966     }
1967   }
1968
1969   XvFreeAdaptorInfo (adaptors);
1970
1971   if (!xcontext->xv_port_id) {
1972     evaspixmapsink->adaptor_no = -1;
1973     GST_ELEMENT_ERROR (evaspixmapsink, RESOURCE, BUSY,
1974         ("Could not initialise Xv output"), ("No port available"));
1975     return NULL;
1976   }
1977
1978   /* Set XV_AUTOPAINT_COLORKEY and XV_DOUBLE_BUFFER and XV_COLORKEY */
1979   {
1980     int count, todo = 3;
1981     XvAttribute *const attr = XvQueryPortAttributes (xcontext->disp,
1982         xcontext->xv_port_id, &count);
1983     static const char autopaint[] = "XV_AUTOPAINT_COLORKEY";
1984     static const char dbl_buffer[] = "XV_DOUBLE_BUFFER";
1985     static const char colorkey[] = "XV_COLORKEY";
1986
1987     GST_DEBUG_OBJECT (evaspixmapsink,"Checking %d Xv port attributes", count);
1988
1989     evaspixmapsink->have_autopaint_colorkey = FALSE;
1990     evaspixmapsink->have_double_buffer = FALSE;
1991     evaspixmapsink->have_colorkey = FALSE;
1992
1993     for (i = 0; ((i < count) && todo); i++)
1994       if (!strcmp (attr[i].name, autopaint)) {
1995         const Atom atom = XInternAtom (xcontext->disp, autopaint, False);
1996
1997         /* turn on autopaint colorkey */
1998         XvSetPortAttribute (xcontext->disp, xcontext->xv_port_id, atom,
1999             (evaspixmapsink->autopaint_colorkey ? 1 : 0));
2000         todo--;
2001         evaspixmapsink->have_autopaint_colorkey = TRUE;
2002       } else if (!strcmp (attr[i].name, dbl_buffer)) {
2003         const Atom atom = XInternAtom (xcontext->disp, dbl_buffer, False);
2004
2005         XvSetPortAttribute (xcontext->disp, xcontext->xv_port_id, atom,
2006             (evaspixmapsink->double_buffer ? 1 : 0));
2007         todo--;
2008         evaspixmapsink->have_double_buffer = TRUE;
2009       } else if (!strcmp (attr[i].name, colorkey)) {
2010         /* Set the colorkey, default is something that is dark but hopefully
2011          * won't randomly appear on the screen elsewhere (ie not black or greys)
2012          * can be overridden by setting "colorkey" property
2013          */
2014         const Atom atom = XInternAtom (xcontext->disp, colorkey, False);
2015         guint32 ckey = 0;
2016         gboolean set_attr = TRUE;
2017         guint cr, cg, cb;
2018
2019         /* set a colorkey in the right format RGB565/RGB888
2020          * We only handle these 2 cases, because they're the only types of
2021          * devices we've encountered. If we don't recognise it, leave it alone
2022          */
2023         cr = (evaspixmapsink->colorkey >> 16);
2024         cg = (evaspixmapsink->colorkey >> 8) & 0xFF;
2025         cb = (evaspixmapsink->colorkey) & 0xFF;
2026         switch (xcontext->depth) {
2027           case 16:             /* RGB 565 */
2028             cr >>= 3;
2029             cg >>= 2;
2030             cb >>= 3;
2031             ckey = (cr << 11) | (cg << 5) | cb;
2032             break;
2033           case 24:
2034           case 32:             /* RGB 888 / ARGB 8888 */
2035             ckey = (cr << 16) | (cg << 8) | cb;
2036             break;
2037           default:
2038             GST_DEBUG_OBJECT (evaspixmapsink,"Unknown bit depth %d for Xv Colorkey - not adjusting", xcontext->depth);
2039             set_attr = FALSE;
2040             break;
2041         }
2042
2043         if (set_attr) {
2044           ckey = CLAMP (ckey, (guint32) attr[i].min_value,
2045               (guint32) attr[i].max_value);
2046           GST_LOG_OBJECT (evaspixmapsink,"Setting color key for display depth %d to 0x%x", xcontext->depth, ckey);
2047
2048           XvSetPortAttribute (xcontext->disp, xcontext->xv_port_id, atom,
2049               (gint) ckey);
2050         }
2051         todo--;
2052         evaspixmapsink->have_colorkey = TRUE;
2053       }
2054
2055     XFree (attr);
2056   }
2057
2058   /* Get the list of encodings supported by the adapter and look for the
2059    * XV_IMAGE encoding so we can determine the maximum width and height
2060    * supported */
2061   XvQueryEncodings (xcontext->disp, xcontext->xv_port_id, &nb_encodings,
2062       &encodings);
2063
2064   for (i = 0; i < nb_encodings; i++) {
2065     GST_LOG_OBJECT (evaspixmapsink,
2066         "Encoding %d, name %s, max wxh %lux%lu rate %d/%d",
2067         i, encodings[i].name, encodings[i].width, encodings[i].height,
2068         encodings[i].rate.numerator, encodings[i].rate.denominator);
2069     if (strcmp (encodings[i].name, "XV_IMAGE") == 0) {
2070       max_w = encodings[i].width;
2071       max_h = encodings[i].height;
2072       evaspixmapsink->scr_w = max_w;
2073       evaspixmapsink->scr_h = max_h;
2074     }
2075   }
2076
2077   XvFreeEncodingInfo (encodings);
2078
2079   /* We get all image formats supported by our port */
2080   formats = XvListImageFormats (xcontext->disp,
2081       xcontext->xv_port_id, &nb_formats);
2082   caps = gst_caps_new_empty ();
2083   for (i = 0; i < nb_formats; i++) {
2084     GstCaps *format_caps = NULL;
2085     gboolean is_rgb_format = FALSE;
2086
2087     /* We set the image format of the xcontext to an existing one. This
2088        is just some valid image format for making our xshm calls check before
2089        caps negotiation really happens. */
2090     xcontext->im_format = formats[i].id;
2091
2092     switch (formats[i].type) {
2093       case XvRGB:
2094       {
2095         XvImageFormatValues *fmt = &(formats[i]);
2096         gint endianness = G_BIG_ENDIAN;
2097
2098         if (fmt->byte_order == LSBFirst) {
2099           /* our caps system handles 24/32bpp RGB as big-endian. */
2100           if (fmt->bits_per_pixel == 24 || fmt->bits_per_pixel == 32) {
2101             fmt->red_mask = GUINT32_TO_BE (fmt->red_mask);
2102             fmt->green_mask = GUINT32_TO_BE (fmt->green_mask);
2103             fmt->blue_mask = GUINT32_TO_BE (fmt->blue_mask);
2104
2105             if (fmt->bits_per_pixel == 24) {
2106               fmt->red_mask >>= 8;
2107               fmt->green_mask >>= 8;
2108               fmt->blue_mask >>= 8;
2109             }
2110           } else
2111             endianness = G_LITTLE_ENDIAN;
2112         }
2113
2114         format_caps = gst_caps_new_simple ("video/x-raw-rgb",
2115             "format", GST_TYPE_FOURCC, formats[i].id,
2116             "endianness", G_TYPE_INT, endianness,
2117             "depth", G_TYPE_INT, fmt->depth,
2118             "bpp", G_TYPE_INT, fmt->bits_per_pixel,
2119             "red_mask", G_TYPE_INT, fmt->red_mask,
2120             "green_mask", G_TYPE_INT, fmt->green_mask,
2121             "blue_mask", G_TYPE_INT, fmt->blue_mask,
2122             "width", GST_TYPE_INT_RANGE, 1, max_w,
2123             "height", GST_TYPE_INT_RANGE, 1, max_h,
2124             "framerate", GST_TYPE_FRACTION_RANGE, 0, 1, G_MAXINT, 1, NULL);
2125
2126         is_rgb_format = TRUE;
2127         break;
2128       }
2129       case XvYUV:
2130         format_caps = gst_caps_new_simple ("video/x-raw-yuv",
2131             "format", GST_TYPE_FOURCC, formats[i].id,
2132             "width", GST_TYPE_INT_RANGE, 1, max_w,
2133             "height", GST_TYPE_INT_RANGE, 1, max_h,
2134             "framerate", GST_TYPE_FRACTION_RANGE, 0, 1, G_MAXINT, 1, NULL);
2135         break;
2136       default:
2137         g_assert_not_reached ();
2138         break;
2139     }
2140
2141     if (format_caps) {
2142       GstEvasPixmapFormat *format = NULL;
2143
2144       format = g_new0 (GstEvasPixmapFormat, 1);
2145       if (format) {
2146         format->format = formats[i].id;
2147         format->caps = gst_caps_copy (format_caps);
2148         xcontext->formats_list = g_list_append (xcontext->formats_list, format);
2149       }
2150
2151       if (is_rgb_format) {
2152         if (rgb_caps == NULL)
2153           rgb_caps = format_caps;
2154         else
2155           gst_caps_append (rgb_caps, format_caps);
2156       } else
2157         gst_caps_append (caps, format_caps);
2158     }
2159   }
2160
2161   /* Collected all caps into either the caps or rgb_caps structures.
2162    * Append rgb_caps on the end of YUV, so that YUV is always preferred */
2163   if (rgb_caps)
2164     gst_caps_append (caps, rgb_caps);
2165
2166   if (formats)
2167     XFree (formats);
2168
2169   GST_DEBUG_OBJECT (evaspixmapsink,"Generated the following caps: %" GST_PTR_FORMAT, caps);
2170
2171   if (gst_caps_is_empty (caps)) {
2172     gst_caps_unref (caps);
2173     XvUngrabPort (xcontext->disp, xcontext->xv_port_id, 0);
2174     GST_ELEMENT_ERROR (evaspixmapsink, STREAM, WRONG_TYPE, (NULL),
2175         ("No supported format found"));
2176     return NULL;
2177   }
2178
2179   return caps;
2180 }
2181
2182 static gpointer
2183 gst_evaspixmapsink_event_thread (GstEvasPixmapSink * evaspixmapsink)
2184 {
2185         g_return_val_if_fail (GST_IS_EVASPIXMAPSINK (evaspixmapsink), NULL);
2186         int damage_base = 0;
2187         int damage_err_base = 0;
2188         int damage_case = 0;
2189         XEvent e;
2190         int i = 0;
2191         Display *disp = NULL;
2192
2193         GST_OBJECT_LOCK (evaspixmapsink);
2194
2195         if (evaspixmapsink->xcontext && evaspixmapsink->xcontext->disp) {
2196                 disp = evaspixmapsink->xcontext->disp;
2197         } else {
2198                 GST_ERROR_OBJECT (evaspixmapsink,"evaspixmapsink->xcontext(->disp) is not ready");
2199                 return NULL;
2200         }
2201
2202         if (!XDamageQueryExtension(evaspixmapsink->xcontext->disp, &damage_base, &damage_err_base)) {
2203                 GST_ERROR_OBJECT (evaspixmapsink,"XDamageQueryExtension() failed");
2204                 return NULL;
2205         }
2206         damage_case = (int)damage_base + XDamageNotify;
2207
2208         while (evaspixmapsink->running) {
2209                 GST_OBJECT_UNLOCK (evaspixmapsink);
2210
2211                 g_mutex_lock (evaspixmapsink->x_lock);
2212                 while (XPending (disp)) {
2213                         XNextEvent (disp, &e);
2214                         g_mutex_unlock (evaspixmapsink->x_lock);
2215                         if (e.type == damage_case ) {
2216                                 XDamageNotifyEvent *damage_ev = (XDamageNotifyEvent *)&e;
2217                                 for (i = 0; i < evaspixmapsink->num_of_pixmaps; i++) {
2218                                         GstXPixmap *xpixmap = evaspixmapsink->xpixmap[i];
2219                                         if (xpixmap && damage_ev->drawable == xpixmap->pixmap) {
2220                                                 g_mutex_lock(evaspixmapsink->pixmap_ref_lock);
2221                                                 if (xpixmap->ref) {
2222                                                         /* set it only if damage event comes from _buffer_put() */
2223                                                         xpixmap->damaged_time = (gint)get_millis_time();
2224                                                 }
2225                                                 g_mutex_unlock(evaspixmapsink->pixmap_ref_lock);
2226                                                 GST_DEBUG_OBJECT (evaspixmapsink,"event_handler : got a damage event for pixmap(%d), refcount(%d), damaged_time(%d)",
2227                                                                                 xpixmap->pixmap, xpixmap->ref, xpixmap->damaged_time);
2228                                                 if (evaspixmapsink->epipe_request_count > EPIPE_REQUEST_LIMIT) {
2229                                                         GST_WARNING_OBJECT (evaspixmapsink,"event_handler : epipe_request_count(%d), skip ecore_pipe_write()", evaspixmapsink->epipe_request_count);
2230                                                 } else {
2231                                                         __ta__("evaspixmapsink ecore_pipe_write", ecore_pipe_write(evaspixmapsink->epipe, evaspixmapsink, sizeof(GstEvasPixmapSink)););
2232                                                         evaspixmapsink->epipe_request_count++;
2233                                                         GST_DEBUG_OBJECT (evaspixmapsink,"event_handler : after call ecore_pipe_write() for pixmap(%d)", xpixmap->pixmap);
2234                                                 }
2235                                                 g_mutex_lock (evaspixmapsink->x_lock);
2236                                                 XDamageSubtract (evaspixmapsink->xcontext->disp, evaspixmapsink->damage[i], None, None );
2237                                                 g_mutex_unlock (evaspixmapsink->x_lock);
2238
2239                                                 if (evaspixmapsink->buf_shared_type == BUF_SHARE_METHOD_FD) {
2240                                                         if (GST_STATE(evaspixmapsink) == GST_STATE_PLAYING) {
2241                                                                 drm_fini_close_gem_handle(evaspixmapsink, xpixmap->pixmap);
2242                                                         }
2243                                                 }
2244                                                 break;
2245                                         }
2246                                 }
2247                                 if (i == evaspixmapsink->num_of_pixmaps) {
2248                                         GST_WARNING_OBJECT (evaspixmapsink,"event_handler : could not find corresponding pixmap with this damage event(%d)", damage_ev->drawable);
2249                                 }
2250                         } else {
2251                                 GST_LOG_OBJECT (evaspixmapsink,"event_handler : unidentified event(%d)", e.type);
2252                                 g_mutex_lock (evaspixmapsink->x_lock);
2253                                 continue;
2254                         }
2255                         g_mutex_lock (evaspixmapsink->x_lock);
2256                 }
2257                 //XSync (disp, FALSE);
2258                 g_mutex_unlock (evaspixmapsink->x_lock);
2259
2260                 g_usleep (G_USEC_PER_SEC / 40);
2261                 GST_OBJECT_LOCK (evaspixmapsink);
2262         }
2263         GST_OBJECT_UNLOCK (evaspixmapsink);
2264         return NULL;
2265 }
2266
2267 static void
2268 gst_evaspixmapsink_manage_event_thread (GstEvasPixmapSink *evaspixmapsink)
2269 {
2270         /* don't start the thread too early */
2271         if (evaspixmapsink->xcontext == NULL) {
2272                 GST_ERROR_OBJECT (evaspixmapsink,"xcontext is NULL..");
2273                 return;
2274         }
2275
2276         GST_OBJECT_LOCK (evaspixmapsink);
2277
2278         if (!evaspixmapsink->event_thread) {
2279                 /* Setup our event listening thread */
2280                 GST_DEBUG_OBJECT (evaspixmapsink,"run xevent thread");
2281                 evaspixmapsink->running = TRUE;
2282                 evaspixmapsink->event_thread = g_thread_create ( (GThreadFunc) gst_evaspixmapsink_event_thread, evaspixmapsink, TRUE, NULL);
2283         } else {
2284                 GST_WARNING_OBJECT (evaspixmapsink,"there already existed the event_thread.. keep going");
2285                 /* Do not finalize the thread in here, Only finalize the thread by calling gst_evaspixmapsink_reset() */
2286         }
2287
2288         GST_OBJECT_UNLOCK (evaspixmapsink);
2289 }
2290
2291
2292 /* This function calculates the pixel aspect ratio based on the properties
2293  * in the xcontext structure and stores it there. */
2294 static void
2295 gst_evaspixmapsink_calculate_pixel_aspect_ratio (GstXContext *xcontext)
2296 {
2297   static const gint par[][2] = {
2298     {1, 1},                     /* regular screen */
2299     {16, 15},                   /* PAL TV */
2300     {11, 10},                   /* 525 line Rec.601 video */
2301     {54, 59},                   /* 625 line Rec.601 video */
2302     {64, 45},                   /* 1280x1024 on 16:9 display */
2303     {5, 3},                     /* 1280x1024 on 4:3 display */
2304     {4, 3}                      /*  800x600 on 16:9 display */
2305   };
2306   gint i;
2307   gint index;
2308   gdouble ratio;
2309   gdouble delta;
2310
2311 #define DELTA(idx) (ABS (ratio - ((gdouble) par[idx][0] / par[idx][1])))
2312
2313   /* first calculate the "real" ratio based on the X values;
2314    * which is the "physical" w/h divided by the w/h in pixels of the display */
2315   ratio = (gdouble) (xcontext->widthmm * xcontext->height)
2316       / (xcontext->heightmm * xcontext->width);
2317
2318   /* DirectFB's X in 720x576 reports the physical dimensions wrong, so
2319    * override here */
2320   if (xcontext->width == 720 && xcontext->height == 576) {
2321     ratio = 4.0 * 576 / (3.0 * 720);
2322   }
2323   GST_DEBUG ("calculated pixel aspect ratio: %f", ratio);
2324   /* now find the one from par[][2] with the lowest delta to the real one */
2325   delta = DELTA (0);
2326   index = 0;
2327
2328   for (i = 1; i < sizeof (par) / (sizeof (gint) * 2); ++i) {
2329     gdouble this_delta = DELTA (i);
2330
2331     if (this_delta < delta) {
2332       index = i;
2333       delta = this_delta;
2334     }
2335   }
2336
2337   GST_DEBUG ("Decided on index %d (%d/%d)", index,
2338       par[index][0], par[index][1]);
2339
2340   g_free (xcontext->par);
2341   xcontext->par = g_new0 (GValue, 1);
2342   g_value_init (xcontext->par, GST_TYPE_FRACTION);
2343   gst_value_set_fraction (xcontext->par, par[index][0], par[index][1]);
2344   GST_DEBUG ("set xcontext PAR to %d/%d",
2345       gst_value_get_fraction_numerator (xcontext->par),
2346       gst_value_get_fraction_denominator (xcontext->par));
2347 }
2348
2349 /* This function gets the X Display and global info about it. Everything is
2350    stored in our object and will be cleaned when the object is disposed. Note
2351    here that caps for supported format are generated without any window or
2352    image creation */
2353 static GstXContext*
2354 gst_evaspixmapsink_xcontext_get (GstEvasPixmapSink *evaspixmapsink)
2355 {
2356         GstXContext *xcontext = NULL;
2357         XPixmapFormatValues *px_formats = NULL;
2358         gint nb_formats = 0, i, j, N_attr;
2359         XvAttribute *xv_attr;
2360         Atom prop_atom;
2361         const char *channels[4] = { "XV_HUE", "XV_SATURATION", "XV_BRIGHTNESS", "XV_CONTRAST"};
2362
2363         g_return_val_if_fail (GST_IS_EVASPIXMAPSINK (evaspixmapsink), NULL);
2364
2365         xcontext = g_new0 (GstXContext, 1);
2366         xcontext->im_format = 0;
2367
2368         g_mutex_lock (evaspixmapsink->x_lock);
2369
2370         xcontext->disp = XOpenDisplay (evaspixmapsink->display_name);
2371
2372         if (!xcontext->disp) {
2373                 g_mutex_unlock (evaspixmapsink->x_lock);
2374                 g_free (xcontext);
2375                 GST_ELEMENT_ERROR (evaspixmapsink, RESOURCE, WRITE, ("Could not initialise Xv output"), ("Could not open display"));
2376                 return NULL;
2377         }
2378
2379         xcontext->screen = DefaultScreenOfDisplay (xcontext->disp);
2380         xcontext->screen_num = DefaultScreen (xcontext->disp);
2381         xcontext->visual = DefaultVisual (xcontext->disp, xcontext->screen_num);
2382         xcontext->root = DefaultRootWindow (xcontext->disp);
2383         xcontext->white = XWhitePixel (xcontext->disp, xcontext->screen_num);
2384         xcontext->black = XBlackPixel (xcontext->disp, xcontext->screen_num);
2385         xcontext->depth = DefaultDepthOfScreen (xcontext->screen);
2386
2387         xcontext->width = DisplayWidth (xcontext->disp, xcontext->screen_num);
2388         xcontext->height = DisplayHeight (xcontext->disp, xcontext->screen_num);
2389         xcontext->widthmm = DisplayWidthMM (xcontext->disp, xcontext->screen_num);
2390         xcontext->heightmm = DisplayHeightMM (xcontext->disp, xcontext->screen_num);
2391
2392         GST_DEBUG_OBJECT (evaspixmapsink,"X reports %dx%d pixels and %d mm x %d mm", xcontext->width, xcontext->height, xcontext->widthmm, xcontext->heightmm);
2393
2394         gst_evaspixmapsink_calculate_pixel_aspect_ratio (xcontext);
2395         /* We get supported pixmap formats at supported depth */
2396         px_formats = XListPixmapFormats (xcontext->disp, &nb_formats);
2397
2398         if (!px_formats) {
2399                 XCloseDisplay (xcontext->disp);
2400                 g_mutex_unlock (evaspixmapsink->x_lock);
2401                 g_free (xcontext->par);
2402                 g_free (xcontext);
2403                 GST_ELEMENT_ERROR (evaspixmapsink, RESOURCE, SETTINGS,
2404                 ("Could not initialise Xv output"), ("Could not get pixel formats"));
2405                 return NULL;
2406         }
2407
2408         /* We get bpp value corresponding to our running depth */
2409         for (i = 0; i < nb_formats; i++) {
2410                 if (px_formats[i].depth == xcontext->depth)
2411                 xcontext->bpp = px_formats[i].bits_per_pixel;
2412         }
2413
2414         XFree (px_formats);
2415
2416         xcontext->endianness = (ImageByteOrder (xcontext->disp) == LSBFirst) ? G_LITTLE_ENDIAN : G_BIG_ENDIAN;
2417
2418         /* our caps system handles 24/32bpp RGB as big-endian. */
2419         if ((xcontext->bpp == 24 || xcontext->bpp == 32) && xcontext->endianness == G_LITTLE_ENDIAN) {
2420                 xcontext->endianness = G_BIG_ENDIAN;
2421                 xcontext->visual->red_mask = GUINT32_TO_BE (xcontext->visual->red_mask);
2422                 xcontext->visual->green_mask = GUINT32_TO_BE (xcontext->visual->green_mask);
2423                 xcontext->visual->blue_mask = GUINT32_TO_BE (xcontext->visual->blue_mask);
2424                 if (xcontext->bpp == 24) {
2425                         xcontext->visual->red_mask >>= 8;
2426                         xcontext->visual->green_mask >>= 8;
2427                         xcontext->visual->blue_mask >>= 8;
2428                 }
2429         }
2430
2431         xcontext->caps = gst_evaspixmapsink_get_xv_support (evaspixmapsink, xcontext);
2432
2433         if (!xcontext->caps) {
2434                 XCloseDisplay (xcontext->disp);
2435                 g_mutex_unlock (evaspixmapsink->x_lock);
2436                 g_free (xcontext->par);
2437                 g_free (xcontext);
2438                 /* GST_ELEMENT_ERROR is thrown by gst_evaspixmapsink_get_xv_support */
2439                 return NULL;
2440         }
2441 #ifdef HAVE_XSHM
2442         /* Search for XShm extension support */
2443         if (XShmQueryExtension (xcontext->disp) && gst_evaspixmapsink_check_xshm_calls (xcontext)) {
2444                 xcontext->use_xshm = TRUE;
2445                 GST_DEBUG_OBJECT (evaspixmapsink,"evaspixmapsink is using XShm extension");
2446         } else
2447 #endif /* HAVE_XSHM */
2448         {
2449                 xcontext->use_xshm = FALSE;
2450                 GST_DEBUG_OBJECT (evaspixmapsink,"evaspixmapsink is not using XShm extension");
2451         }
2452
2453         xv_attr = XvQueryPortAttributes (xcontext->disp, xcontext->xv_port_id, &N_attr);
2454
2455         /* Generate the channels list */
2456         for (i = 0; i < (sizeof (channels) / sizeof (char *)); i++) {
2457                 XvAttribute *matching_attr = NULL;
2458
2459                 /* Retrieve the property atom if it exists. If it doesn't exist,
2460                 * the attribute itself must not either, so we can skip */
2461                 prop_atom = XInternAtom (xcontext->disp, channels[i], True);
2462                 if (prop_atom == None) {
2463                         continue;
2464                 }
2465
2466                 if (xv_attr != NULL) {
2467                         for (j = 0; j < N_attr && matching_attr == NULL; ++j) {
2468                                 if (!g_ascii_strcasecmp (channels[i], xv_attr[j].name)) {
2469                                         matching_attr = xv_attr + j;
2470                                 }
2471                         }
2472                 }
2473
2474                 if (matching_attr) {
2475                         GstColorBalanceChannel *channel;
2476                         channel = g_object_new (GST_TYPE_COLOR_BALANCE_CHANNEL, NULL);
2477                         channel->label = g_strdup (channels[i]);
2478                         channel->min_value = matching_attr->min_value;
2479                         channel->max_value = matching_attr->max_value;
2480
2481                         xcontext->channels_list = g_list_append (xcontext->channels_list, channel);
2482
2483                         /* If the colorbalance settings have not been touched we get Xv values
2484                                 as defaults and update our internal variables */
2485                         if (!evaspixmapsink->cb_changed) {
2486                                 gint val;
2487                                 XvGetPortAttribute (xcontext->disp, xcontext->xv_port_id, prop_atom, &val);
2488                                 /* Normalize val to [-1000, 1000] */
2489                                 val = floor (0.5 + -1000 + 2000 * (val - channel->min_value) /  (double) (channel->max_value - channel->min_value));
2490
2491                                 if (!g_ascii_strcasecmp (channels[i], "XV_HUE")) {
2492                                         evaspixmapsink->hue = val;
2493                                 } else if (!g_ascii_strcasecmp (channels[i], "XV_SATURATION")) {
2494                                         evaspixmapsink->saturation = val;
2495                                 } else if (!g_ascii_strcasecmp (channels[i], "XV_BRIGHTNESS")) {
2496                                         evaspixmapsink->brightness = val;
2497                                 } else if (!g_ascii_strcasecmp (channels[i], "XV_CONTRAST")) {
2498                                         evaspixmapsink->contrast = val;
2499                                 }
2500                         }
2501                 }
2502         }
2503
2504         if (xv_attr) {
2505                 XFree (xv_attr);
2506         }
2507
2508         g_mutex_unlock (evaspixmapsink->x_lock);
2509
2510         return xcontext;
2511 }
2512
2513 /* This function cleans the X context. Closing the Display, releasing the XV
2514    port and unrefing the caps for supported formats. */
2515 static void
2516 gst_evaspixmapsink_xcontext_clear (GstEvasPixmapSink *evaspixmapsink)
2517 {
2518   GList *formats_list, *channels_list;
2519   GstXContext *xcontext;
2520   gint i = 0;
2521
2522   g_return_if_fail (GST_IS_EVASPIXMAPSINK (evaspixmapsink));
2523
2524   GST_OBJECT_LOCK (evaspixmapsink);
2525   if (evaspixmapsink->xcontext == NULL) {
2526     GST_OBJECT_UNLOCK (evaspixmapsink);
2527     return;
2528   }
2529
2530   /* Take the XContext from the sink and clean it up */
2531   xcontext = evaspixmapsink->xcontext;
2532   evaspixmapsink->xcontext = NULL;
2533
2534   GST_OBJECT_UNLOCK (evaspixmapsink);
2535
2536   formats_list = xcontext->formats_list;
2537
2538   while (formats_list) {
2539     GstEvasPixmapFormat *format = formats_list->data;
2540
2541     gst_caps_unref (format->caps);
2542     g_free (format);
2543     formats_list = g_list_next (formats_list);
2544   }
2545
2546   if (xcontext->formats_list)
2547     g_list_free (xcontext->formats_list);
2548
2549   channels_list = xcontext->channels_list;
2550
2551   while (channels_list) {
2552     GstColorBalanceChannel *channel = channels_list->data;
2553
2554     g_object_unref (channel);
2555     channels_list = g_list_next (channels_list);
2556   }
2557
2558   if (xcontext->channels_list)
2559     g_list_free (xcontext->channels_list);
2560
2561   gst_caps_unref (xcontext->caps);
2562
2563   for (i = 0; i < xcontext->nb_adaptors; i++) {
2564     g_free (xcontext->adaptors[i]);
2565   }
2566
2567   g_free (xcontext->adaptors);
2568
2569   g_free (xcontext->par);
2570
2571   g_mutex_lock (evaspixmapsink->x_lock);
2572
2573   GST_DEBUG_OBJECT (evaspixmapsink,"Closing display and freeing X Context");
2574
2575   XvUngrabPort (xcontext->disp, xcontext->xv_port_id, 0);
2576
2577   XCloseDisplay (xcontext->disp);
2578
2579   g_mutex_unlock (evaspixmapsink->x_lock);
2580
2581   g_free (xcontext);
2582 }
2583
2584 /* Element stuff */
2585
2586 /* This function tries to get a format matching with a given caps in the
2587    supported list of formats we generated in gst_evaspixmapsink_get_xv_support */
2588 static gint
2589 gst_evaspixmapsink_get_format_from_caps (GstEvasPixmapSink *evaspixmapsink, GstCaps *caps)
2590 {
2591   GList *list = NULL;
2592
2593   g_return_val_if_fail (GST_IS_EVASPIXMAPSINK (evaspixmapsink), 0);
2594
2595   list = evaspixmapsink->xcontext->formats_list;
2596
2597   while (list) {
2598     GstEvasPixmapFormat *format = list->data;
2599
2600     if (format) {
2601       if (gst_caps_can_intersect (caps, format->caps)) {
2602         return format->format;
2603       }
2604     }
2605     list = g_list_next (list);
2606   }
2607
2608   return -1;
2609 }
2610
2611 static GstCaps *
2612 gst_evaspixmapsink_getcaps (GstBaseSink *bsink)
2613 {
2614   GstEvasPixmapSink *evaspixmapsink;
2615
2616   evaspixmapsink = GST_EVASPIXMAPSINK (bsink);
2617
2618   if (evaspixmapsink->xcontext)
2619     return gst_caps_ref (evaspixmapsink->xcontext->caps);
2620
2621   return
2622       gst_caps_copy (gst_pad_get_pad_template_caps (GST_VIDEO_SINK_PAD
2623           (evaspixmapsink)));
2624 }
2625
2626 static gboolean
2627 gst_evaspixmapsink_setcaps (GstBaseSink *bsink, GstCaps *caps)
2628 {
2629         GstEvasPixmapSink *evaspixmapsink;
2630         GstStructure *structure;
2631         guint32 im_format = 0;
2632         gboolean ret;
2633         gint video_width, video_height;
2634         gint disp_x, disp_y;
2635         gint disp_width, disp_height;
2636         gint video_par_n, video_par_d;        /* video's PAR */
2637         gint display_par_n, display_par_d;    /* display's PAR */
2638         const GValue *caps_par;
2639         const GValue *caps_disp_reg;
2640         const GValue *fps;
2641         guint num, den;
2642         gboolean enable_last_buffer;
2643
2644         evaspixmapsink = GST_EVASPIXMAPSINK (bsink);
2645
2646         GST_DEBUG_OBJECT (evaspixmapsink,"In setcaps. Possible caps %" GST_PTR_FORMAT ", setting caps %" GST_PTR_FORMAT, evaspixmapsink->xcontext->caps, caps);
2647
2648         if (!gst_caps_can_intersect (evaspixmapsink->xcontext->caps, caps)) {
2649                 goto incompatible_caps;
2650         }
2651
2652         structure = gst_caps_get_structure (caps, 0);
2653         ret = gst_structure_get_int (structure, "width", &video_width);
2654         ret &= gst_structure_get_int (structure, "height", &video_height);
2655         fps = gst_structure_get_value (structure, "framerate");
2656         ret &= (fps != NULL);
2657
2658         if (!ret) {
2659                 goto incomplete_caps;
2660         }
2661
2662         evaspixmapsink->aligned_width = video_width;
2663         evaspixmapsink->aligned_height = video_height;
2664
2665         /* get enable-last-buffer */
2666         g_object_get(G_OBJECT(evaspixmapsink), "enable-last-buffer", &enable_last_buffer, NULL);
2667         GST_INFO_OBJECT (evaspixmapsink,"current enable-last-buffer : %d", enable_last_buffer);
2668         /* flush if enable-last-buffer is TRUE */
2669         if (enable_last_buffer) {
2670                 GST_INFO_OBJECT (evaspixmapsink,"flush last-buffer");
2671                 g_object_set(G_OBJECT(evaspixmapsink), "enable-last-buffer", FALSE, NULL);
2672                 g_object_set(G_OBJECT(evaspixmapsink), "enable-last-buffer", TRUE, NULL);
2673         }
2674
2675         evaspixmapsink->fps_n = gst_value_get_fraction_numerator (fps);
2676         evaspixmapsink->fps_d = gst_value_get_fraction_denominator (fps);
2677
2678         evaspixmapsink->video_width = video_width;
2679         evaspixmapsink->video_height = video_height;
2680
2681         im_format = gst_evaspixmapsink_get_format_from_caps (evaspixmapsink, caps);
2682         if (im_format == -1) {
2683                 goto invalid_format;
2684         }
2685
2686         /* get aspect ratio from caps if it's present, and
2687         * convert video width and height to a display width and height
2688         * using wd / hd = wv / hv * PARv / PARd */
2689
2690         /* get video's PAR */
2691         caps_par = gst_structure_get_value (structure, "pixel-aspect-ratio");
2692         if (caps_par) {
2693                 video_par_n = gst_value_get_fraction_numerator (caps_par);
2694                 video_par_d = gst_value_get_fraction_denominator (caps_par);
2695         } else {
2696                 video_par_n = 1;
2697                 video_par_d = 1;
2698         }
2699         /* get display's PAR */
2700         if (evaspixmapsink->par) {
2701                 display_par_n = gst_value_get_fraction_numerator (evaspixmapsink->par);
2702                 display_par_d = gst_value_get_fraction_denominator (evaspixmapsink->par);
2703         } else {
2704                 display_par_n = 1;
2705                 display_par_d = 1;
2706         }
2707
2708         /* get the display region */
2709         caps_disp_reg = gst_structure_get_value (structure, "display-region");
2710         if (caps_disp_reg) {
2711                 disp_x = g_value_get_int (gst_value_array_get_value (caps_disp_reg, 0));
2712                 disp_y = g_value_get_int (gst_value_array_get_value (caps_disp_reg, 1));
2713                 disp_width = g_value_get_int (gst_value_array_get_value (caps_disp_reg, 2));
2714                 disp_height = g_value_get_int (gst_value_array_get_value (caps_disp_reg, 3));
2715         } else {
2716                 disp_x = disp_y = 0;
2717                 disp_width = video_width;
2718                 disp_height = video_height;
2719         }
2720
2721         if (!gst_video_calculate_display_ratio (&num, &den, video_width, video_height, video_par_n, video_par_d, display_par_n, display_par_d)) {
2722                 goto no_disp_ratio;
2723         }
2724
2725         evaspixmapsink->disp_x = disp_x;
2726         evaspixmapsink->disp_y = disp_y;
2727         evaspixmapsink->disp_width = disp_width;
2728         evaspixmapsink->disp_height = disp_height;
2729
2730         GST_DEBUG_OBJECT (evaspixmapsink,"video width/height: %dx%d, calculated display ratio: %d/%d",  video_width, video_height, num, den);
2731
2732         /* now find a width x height that respects this display ratio.
2733         * prefer those that have one of w/h the same as the incoming video
2734         * using wd / hd = num / den */
2735
2736         /* start with same height, because of interlaced video */
2737         /* check hd / den is an integer scale factor, and scale wd with the PAR */
2738         if (video_height % den == 0) {
2739                 GST_DEBUG_OBJECT (evaspixmapsink,"keeping video height");
2740                 GST_VIDEO_SINK_WIDTH (evaspixmapsink) = (guint) gst_util_uint64_scale_int (video_height, num, den);
2741                 GST_VIDEO_SINK_HEIGHT (evaspixmapsink) = video_height;
2742         } else if (video_width % num == 0) {
2743                 GST_DEBUG_OBJECT (evaspixmapsink,"keeping video width");
2744                 GST_VIDEO_SINK_WIDTH (evaspixmapsink) = video_width;
2745                 GST_VIDEO_SINK_HEIGHT (evaspixmapsink) = (guint) gst_util_uint64_scale_int (video_width, den, num);
2746         } else {
2747                 GST_DEBUG_OBJECT (evaspixmapsink,"approximating while keeping video height");
2748                 GST_VIDEO_SINK_WIDTH (evaspixmapsink) = (guint) gst_util_uint64_scale_int (video_height, num, den);
2749                 GST_VIDEO_SINK_HEIGHT (evaspixmapsink) = video_height;
2750         }
2751         GST_DEBUG_OBJECT (evaspixmapsink,"scaling to %dx%d", GST_VIDEO_SINK_WIDTH (evaspixmapsink), GST_VIDEO_SINK_HEIGHT (evaspixmapsink));
2752
2753         /* Creating our window and our image with the display size in pixels */
2754         if (GST_VIDEO_SINK_WIDTH (evaspixmapsink) <= 0 || GST_VIDEO_SINK_HEIGHT (evaspixmapsink) <= 0) {
2755                 goto no_display_size;
2756         }
2757
2758         g_mutex_lock (evaspixmapsink->flow_lock);
2759
2760         /* We renew our evaspixmap buffer only if size or format changed;
2761         * the evaspixmap buffer is the same size as the video pixel size */
2762         if ((evaspixmapsink->evas_pixmap_buf) && ((im_format != evaspixmapsink->evas_pixmap_buf->im_format)
2763                 || (video_width != evaspixmapsink->evas_pixmap_buf->width) || (video_height != evaspixmapsink->evas_pixmap_buf->height))) {
2764                 GST_DEBUG_OBJECT (evaspixmapsink,"old format %" GST_FOURCC_FORMAT ", new format %" GST_FOURCC_FORMAT,
2765                                 GST_FOURCC_ARGS (evaspixmapsink->evas_pixmap_buf->im_format), GST_FOURCC_ARGS (im_format));
2766                 GST_DEBUG_OBJECT (evaspixmapsink,"renewing evaspixmap buffer");
2767                 gst_buffer_unref (GST_BUFFER (evaspixmapsink->evas_pixmap_buf));
2768                 evaspixmapsink->evas_pixmap_buf = NULL;
2769         }
2770
2771         g_mutex_unlock (evaspixmapsink->flow_lock);
2772
2773         if (evaspixmapsink->eo) {
2774                 if (!gst_evaspixmapsink_xpixmap_link (evaspixmapsink)) {
2775                         GST_ERROR_OBJECT (evaspixmapsink,"link evas image object with pixmap failed...");
2776                         return FALSE;
2777                 } else {
2778                         gst_evaspixmapsink_manage_event_thread (evaspixmapsink);
2779                 }
2780         } else {
2781                 GST_ERROR_OBJECT (evaspixmapsink,"setcaps success, but there is no evas image object..");
2782                 return FALSE;
2783         }
2784
2785         return TRUE;
2786
2787         /* ERRORS */
2788         incompatible_caps:
2789         {
2790                 GST_ERROR_OBJECT (evaspixmapsink,"caps incompatible");
2791                 return FALSE;
2792         }
2793         incomplete_caps:
2794         {
2795                 GST_DEBUG_OBJECT (evaspixmapsink,"Failed to retrieve either width, ""height or framerate from intersected caps");
2796                 return FALSE;
2797         }
2798         invalid_format:
2799         {
2800                 GST_DEBUG_OBJECT (evaspixmapsink,"Could not locate image format from caps %" GST_PTR_FORMAT, caps);
2801                 return FALSE;
2802         }
2803         no_disp_ratio:
2804         {
2805                 GST_ELEMENT_ERROR (evaspixmapsink, CORE, NEGOTIATION, (NULL), ("Error calculating the output display ratio of the video."));
2806                 return FALSE;
2807         }
2808         no_display_size:
2809         {
2810                 GST_ELEMENT_ERROR (evaspixmapsink, CORE, NEGOTIATION, (NULL), ("Error calculating the output display ratio of the video."));
2811                 return FALSE;
2812         }
2813 }
2814
2815 static GstStateChangeReturn
2816 gst_evaspixmapsink_change_state (GstElement *element, GstStateChange transition)
2817 {
2818         GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
2819         GstEvasPixmapSink *evaspixmapsink;
2820
2821         evaspixmapsink = GST_EVASPIXMAPSINK (element);
2822
2823         switch (transition) {
2824         case GST_STATE_CHANGE_NULL_TO_READY:
2825                 g_mutex_lock (evaspixmapsink->flow_lock);
2826                 GST_WARNING_OBJECT (evaspixmapsink,"GST_STATE_CHANGE_NULL_TO_READY");
2827
2828                 /* open drm to use gem */
2829                 if (drm_init(evaspixmapsink)) {
2830                         GST_ERROR_OBJECT (evaspixmapsink,"drm_init() failure");
2831                         g_mutex_unlock (evaspixmapsink->flow_lock);
2832                         return GST_STATE_CHANGE_FAILURE;
2833                 }
2834
2835                 /* check if there exist evas image object, need to write code related to making internal evas image object */
2836                 if (!is_evas_image_object (evaspixmapsink->eo)) {
2837                         GST_ERROR_OBJECT (evaspixmapsink,"There is no evas image object..");
2838                         g_mutex_unlock (evaspixmapsink->flow_lock);
2839                         return GST_STATE_CHANGE_FAILURE;
2840                 }
2841
2842                 /* Set xcontext and display */
2843                 if (!evaspixmapsink->xcontext) {
2844                         evaspixmapsink->xcontext = gst_evaspixmapsink_xcontext_get (evaspixmapsink);
2845                         if (!evaspixmapsink->xcontext) {
2846                                 GST_ERROR_OBJECT (evaspixmapsink,"could not get xcontext..");
2847                                 g_mutex_unlock (evaspixmapsink->flow_lock);
2848                                 return GST_STATE_CHANGE_FAILURE;
2849                         }
2850                 }
2851
2852                 /* update object's par with calculated one if not set yet */
2853                 if (!evaspixmapsink->par) {
2854                         evaspixmapsink->par = g_new0 (GValue, 1);
2855                         gst_value_init_and_copy (evaspixmapsink->par, evaspixmapsink->xcontext->par);
2856                         GST_DEBUG_OBJECT (evaspixmapsink,"set calculated PAR on object's PAR");
2857                 }
2858
2859                 /* call XSynchronize with the current value of synchronous */
2860                 GST_DEBUG_OBJECT (evaspixmapsink,"XSynchronize called with %s", evaspixmapsink->synchronous ? "TRUE" : "FALSE");
2861                 XSynchronize (evaspixmapsink->xcontext->disp, evaspixmapsink->synchronous);
2862                 gst_evaspixmapsink_update_colorbalance (evaspixmapsink);
2863
2864                 g_mutex_unlock (evaspixmapsink->flow_lock);
2865                 break;
2866
2867         case GST_STATE_CHANGE_READY_TO_PAUSED:
2868                 GST_WARNING_OBJECT (evaspixmapsink,"GST_STATE_CHANGE_READY_TO_PAUSED");
2869                 break;
2870
2871         case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
2872                 GST_WARNING_OBJECT (evaspixmapsink,"GST_STATE_CHANGE_PAUSED_TO_PLAYING");
2873                 break;
2874
2875         default:
2876                 break;
2877         }
2878
2879         ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
2880
2881         switch (transition) {
2882         case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
2883                 GST_WARNING_OBJECT (evaspixmapsink,"GST_STATE_CHANGE_PLAYING_TO_PAUSED");
2884                 break;
2885
2886         case GST_STATE_CHANGE_PAUSED_TO_READY:
2887         {
2888                 int i = 0;
2889                 GST_WARNING_OBJECT (evaspixmapsink,"GST_STATE_CHANGE_PAUSED_TO_READY");
2890                 evaspixmapsink->fps_n = 0;
2891                 evaspixmapsink->fps_d = 1;
2892                 GST_VIDEO_SINK_WIDTH (evaspixmapsink) = 0;
2893                 GST_VIDEO_SINK_HEIGHT (evaspixmapsink) = 0;
2894                 drm_fini_close_gem_handle(evaspixmapsink, 0);
2895         }
2896                 break;
2897
2898         case GST_STATE_CHANGE_READY_TO_NULL:
2899                 GST_WARNING_OBJECT (evaspixmapsink,"GST_STATE_CHANGE_READY_TO_NULL");
2900                 gst_evaspixmapsink_reset(evaspixmapsink);
2901                 /* close drm */
2902                 drm_fini(evaspixmapsink);
2903                 break;
2904
2905         default:
2906                 break;
2907         }
2908         return ret;
2909 }
2910
2911 static void
2912 gst_evaspixmapsink_get_times (GstBaseSink *bsink, GstBuffer *buf, GstClockTime *start, GstClockTime *end)
2913 {
2914   GstEvasPixmapSink *evaspixmapsink;
2915
2916   evaspixmapsink = GST_EVASPIXMAPSINK (bsink);
2917
2918   if (GST_BUFFER_TIMESTAMP_IS_VALID (buf)) {
2919     *start = GST_BUFFER_TIMESTAMP (buf);
2920     if (GST_BUFFER_DURATION_IS_VALID (buf)) {
2921       *end = *start + GST_BUFFER_DURATION (buf);
2922     } else {
2923       if (evaspixmapsink->fps_n > 0) {
2924         *end = *start +
2925             gst_util_uint64_scale_int (GST_SECOND, evaspixmapsink->fps_d,
2926             evaspixmapsink->fps_n);
2927       }
2928     }
2929   }
2930 }
2931
2932 static GstFlowReturn
2933 gst_evaspixmapsink_show_frame (GstVideoSink *vsink, GstBuffer *buf)
2934 {
2935         GstEvasPixmapSink *evaspixmapsink;
2936         XV_DATA_PTR img_data = NULL;
2937         SCMN_IMGB *scmn_imgb = NULL;
2938         gint format = 0;
2939
2940         MMTA_ACUM_ITEM_BEGIN("evaspixmapsink gst_evaspixmapsink_show_frame()", FALSE);
2941
2942         evaspixmapsink = GST_EVASPIXMAPSINK (vsink);
2943
2944         if( evaspixmapsink->stop_video ) {
2945                 GST_INFO_OBJECT (evaspixmapsink, "Stop video is TRUE. so skip show frame..." );
2946                 return GST_FLOW_OK;
2947         }
2948
2949         if (!evaspixmapsink->evas_pixmap_buf) {
2950                 GST_DEBUG_OBJECT (evaspixmapsink,"creating our evaspixmap buffer");
2951                 format = gst_evaspixmapsink_get_format_from_caps(evaspixmapsink, GST_BUFFER_CAPS(buf));
2952                 switch (format) {
2953                 case GST_MAKE_FOURCC('S', 'T', '1', '2'):
2954                 case GST_MAKE_FOURCC('S', 'N', '1', '2'):
2955                 case GST_MAKE_FOURCC('S', '4', '2', '0'):
2956                 case GST_MAKE_FOURCC('S', 'U', 'Y', '2'):
2957                 case GST_MAKE_FOURCC('S', 'U', 'Y', 'V'):
2958                 case GST_MAKE_FOURCC('S', 'Y', 'V', 'Y'):
2959                 case GST_MAKE_FOURCC('I', 'T', 'L', 'V'):
2960                 case GST_MAKE_FOURCC('S', 'R', '3', '2'):
2961                         scmn_imgb = (SCMN_IMGB *)GST_BUFFER_MALLOCDATA(buf);
2962                         if(scmn_imgb == NULL) {
2963                                 GST_DEBUG_OBJECT (evaspixmapsink, "scmn_imgb is NULL. Skip buffer put..." );
2964                                 return GST_FLOW_OK;
2965                         }
2966                          /* skip buffer if aligned size is smaller than size of caps */
2967                         if (scmn_imgb->s[0] < evaspixmapsink->video_width || scmn_imgb->e[0] < evaspixmapsink->video_height) {
2968                                 GST_WARNING_OBJECT (evaspixmapsink,"invalid size[caps:%dx%d,aligned:%dx%d]. Skip this buffer...",
2969                                                 evaspixmapsink->video_width, evaspixmapsink->video_height, scmn_imgb->s[0], scmn_imgb->e[0]);
2970                                 return GST_FLOW_OK;
2971                         }
2972                         evaspixmapsink->aligned_width = scmn_imgb->s[0];
2973                         evaspixmapsink->aligned_height = scmn_imgb->e[0];
2974                         GST_DEBUG_OBJECT (evaspixmapsink,"video width,height[%dx%d]",evaspixmapsink->video_width, evaspixmapsink->video_height);
2975                         GST_INFO_OBJECT (evaspixmapsink,"Use aligned width,height[%dx%d]",evaspixmapsink->aligned_width, evaspixmapsink->aligned_height);
2976                         break;
2977                 default:
2978                         GST_INFO_OBJECT (evaspixmapsink,"Use original width,height of caps");
2979                         break;
2980                 }
2981                 evaspixmapsink->evas_pixmap_buf = gst_evaspixmap_buffer_new (evaspixmapsink, GST_BUFFER_CAPS (buf));
2982                 if (!evaspixmapsink->evas_pixmap_buf) {
2983                         /* The create method should have posted an informative error */
2984                         goto no_image;
2985                 }
2986                 if (evaspixmapsink->evas_pixmap_buf->size < GST_BUFFER_SIZE (buf)) {
2987                         GST_ELEMENT_ERROR (evaspixmapsink, RESOURCE, WRITE, ("Failed to create output image buffer of %dx%d pixels",    evaspixmapsink->evas_pixmap_buf->width, evaspixmapsink->evas_pixmap_buf->height),("XServer allocated buffer size did not match input buffer"));
2988                         gst_evaspixmap_buffer_destroy (evaspixmapsink->evas_pixmap_buf);
2989                         evaspixmapsink->evas_pixmap_buf = NULL;
2990                         goto no_image;
2991                 }
2992         }
2993
2994         switch (evaspixmapsink->evas_pixmap_buf->im_format) {
2995         /* Cases for specified formats of Samsung extension */
2996         case GST_MAKE_FOURCC('S', 'T', '1', '2'):
2997         case GST_MAKE_FOURCC('S', 'N', '1', '2'):
2998         case GST_MAKE_FOURCC('S', '4', '2', '0'):
2999         case GST_MAKE_FOURCC('S', 'U', 'Y', '2'):
3000         case GST_MAKE_FOURCC('S', 'U', 'Y', 'V'):
3001         case GST_MAKE_FOURCC('S', 'Y', 'V', 'Y'):
3002         case GST_MAKE_FOURCC('I', 'T', 'L', 'V'):
3003         case GST_MAKE_FOURCC('S', 'R', '3', '2'):
3004         {
3005                 GST_DEBUG_OBJECT (evaspixmapsink,"Samsung extension display format activated. fourcc:%d", evaspixmapsink->evas_pixmap_buf->im_format);
3006
3007                 if (evaspixmapsink->evas_pixmap_buf->xvimage->data) {
3008                         img_data = (XV_DATA_PTR) evaspixmapsink->evas_pixmap_buf->xvimage->data;
3009                         XV_INIT_DATA(img_data);
3010                         scmn_imgb = (SCMN_IMGB *)GST_BUFFER_MALLOCDATA(buf);
3011                         if (scmn_imgb == NULL) {
3012                                 GST_DEBUG_OBJECT (evaspixmapsink, "scmn_imgb is NULL. Skip buffer put..." );
3013                                 return GST_FLOW_OK;
3014                         }
3015
3016                         if (scmn_imgb->buf_share_method == BUF_SHARE_METHOD_PADDR) {
3017                                 img_data->YBuf = (unsigned int)scmn_imgb->p[0];
3018                                 img_data->CbBuf = (unsigned int)scmn_imgb->p[1];
3019                                 img_data->CrBuf = (unsigned int)scmn_imgb->p[2];
3020                                 img_data->BufType = XV_BUF_TYPE_LEGACY;
3021
3022                         } else if (scmn_imgb->buf_share_method == BUF_SHARE_METHOD_FD) {
3023                                 /* set gem information to gem_info structure of handle and convert dma-buf fd into drm gem name  */
3024                                 img_data->YBuf = drm_init_convert_dmabuf_gemname(evaspixmapsink, (int)scmn_imgb->dma_buf_fd[0]);
3025                                 img_data->CbBuf = drm_init_convert_dmabuf_gemname(evaspixmapsink, (int)scmn_imgb->dma_buf_fd[1]);
3026                                 img_data->CrBuf = drm_init_convert_dmabuf_gemname(evaspixmapsink, (int)scmn_imgb->dma_buf_fd[2]);
3027                                 img_data->BufType = XV_BUF_TYPE_DMABUF;
3028                                 if (evaspixmapsink->buf_shared_type != BUF_SHARE_METHOD_FD) {
3029                                         evaspixmapsink->buf_shared_type = BUF_SHARE_METHOD_FD;
3030                                         GST_WARNING_OBJECT (evaspixmapsink, "BUF SHARED TYPE : FD");
3031                                 }
3032
3033                         } else if (scmn_imgb->buf_share_method == BUF_SHARE_METHOD_TIZEN_BUFFER) {
3034                                 img_data->bo[0] = scmn_imgb->bo[0];
3035                                 img_data->bo[1] = scmn_imgb->bo[1];
3036                                 img_data->bo[2] = scmn_imgb->bo[2];
3037                                 GST_DEBUG("TBM bo %p %p %p", img_data->bo[0], img_data->bo[1], img_data->bo[2]);
3038                                 /* export bo */
3039                                 if (img_data->bo[0]) {
3040                                         img_data->YBuf = tbm_init_convert_bo_gemname(evaspixmapsink, (tbm_bo)img_data->bo[0]);
3041                                 }
3042                                 if (img_data->bo[1]) {
3043                                         img_data->CbBuf = tbm_init_convert_bo_gemname(evaspixmapsink, (tbm_bo)img_data->bo[1]);
3044                                 }
3045                                 if (img_data->bo[2]) {
3046                                         img_data->CrBuf = tbm_init_convert_bo_gemname(evaspixmapsink, (tbm_bo)img_data->bo[2]);
3047                                 }
3048                                 if (evaspixmapsink->buf_shared_type != BUF_SHARE_METHOD_TIZEN_BUFFER) {
3049                                         evaspixmapsink->buf_shared_type = BUF_SHARE_METHOD_TIZEN_BUFFER;
3050                                         GST_WARNING_OBJECT (evaspixmapsink, "BUF SHARED TYPE : TIZEN BUFFER");
3051                                 }
3052                         } else {
3053                                 GST_WARNING_OBJECT (evaspixmapsink, "Not supported, buf_share_method(%d)", scmn_imgb->buf_share_method);
3054                                 return GST_FLOW_OK;
3055                         }
3056                         if (!img_data->YBuf) {
3057                                 GST_WARNING_OBJECT (evaspixmapsink, "img_data->YBuf is NULL. skip buffer put..." );
3058                                 return GST_FLOW_OK;
3059                         }
3060                         GST_LOG_OBJECT(evaspixmapsink, "YBuf[%d], CbBuf[%d], CrBuf[%d]",
3061                                         img_data->YBuf, img_data->CbBuf, img_data->CrBuf );
3062                 } else {
3063                         GST_WARNING_OBJECT (evaspixmapsink, "xvimage->data is NULL. skip buffer put..." );
3064                         return GST_FLOW_OK;
3065                 }
3066                 break;
3067         }
3068         default:
3069         {
3070                 if (evaspixmapsink->buf_shared_type != BUF_SHARE_METHOD_NONE) {
3071                         evaspixmapsink->buf_shared_type = BUF_SHARE_METHOD_NONE;
3072                 }
3073                 GST_DEBUG_OBJECT (evaspixmapsink,"Normal format activated. fourcc = %d", evaspixmapsink->evas_pixmap_buf->im_format);
3074                 __ta__("evaspixmapsink memcpy in _show_frame", memcpy (evaspixmapsink->evas_pixmap_buf->xvimage->data, GST_BUFFER_DATA (buf),
3075                 MIN (GST_BUFFER_SIZE (buf), evaspixmapsink->evas_pixmap_buf->size)););
3076                 break;
3077         }
3078         }
3079         if (!gst_evaspixmap_buffer_put (evaspixmapsink, evaspixmapsink->evas_pixmap_buf)) {
3080                 MMTA_ACUM_ITEM_END("evaspixmapsink gst_evaspixmapsink_show_frame()", FALSE);
3081                 return GST_FLOW_OK;
3082         }
3083
3084         MMTA_ACUM_ITEM_END("evaspixmapsink gst_evaspixmapsink_show_frame()", FALSE);
3085
3086         return GST_FLOW_OK;
3087
3088         /* ERRORS */
3089         no_image:
3090         {
3091                 /* No image available. That's very bad ! */
3092                 GST_WARNING_OBJECT (evaspixmapsink,"could not create image");
3093                 return GST_FLOW_ERROR;
3094         }
3095 }
3096
3097 static gboolean
3098 gst_evaspixmapsink_event (GstBaseSink *sink, GstEvent *event)
3099 {
3100         GstEvasPixmapSink *evaspixmapsink = GST_EVASPIXMAPSINK (sink);
3101
3102         switch (GST_EVENT_TYPE (event)) {
3103         case GST_EVENT_FLUSH_START:
3104                 GST_DEBUG_OBJECT (evaspixmapsink,"GST_EVENT_FLUSH_START");
3105                 break;
3106         case GST_EVENT_FLUSH_STOP:
3107                 GST_DEBUG_OBJECT (evaspixmapsink,"GST_EVENT_FLUSH_STOP");
3108                 break;
3109         default:
3110                 break;
3111         }
3112         if (GST_BASE_SINK_CLASS (parent_class)->event) {
3113                 return GST_BASE_SINK_CLASS (parent_class)->event (sink, event);
3114         } else {
3115                 return TRUE;
3116         }
3117 }
3118
3119 /* Interfaces stuff */
3120
3121 static gboolean
3122 gst_evaspixmapsink_interface_supported (GstImplementsInterface *iface, GType type)
3123 {
3124   g_assert (type == GST_TYPE_NAVIGATION || type == GST_TYPE_COLOR_BALANCE || type == GST_TYPE_PROPERTY_PROBE);
3125   return TRUE;
3126 }
3127
3128 static void
3129 gst_evaspixmapsink_interface_init (GstImplementsInterfaceClass *klass)
3130 {
3131   klass->supported = gst_evaspixmapsink_interface_supported;
3132 }
3133
3134 static void
3135 gst_evaspixmapsink_navigation_send_event (GstNavigation *navigation, GstStructure *structure)
3136 {
3137   GstEvasPixmapSink *evaspixmapsink = GST_EVASPIXMAPSINK (navigation);
3138   GstPad *peer;
3139   int i = 0;
3140
3141   if ((peer = gst_pad_get_peer (GST_VIDEO_SINK_PAD (evaspixmapsink)))) {
3142     GstEvent *event;
3143     GstVideoRectangle result;
3144     gdouble x, y, xscale = 1.0, yscale = 1.0;
3145
3146     event = gst_event_new_navigation (structure);
3147
3148     /* We take the flow_lock while we look at the window */
3149     g_mutex_lock (evaspixmapsink->flow_lock);
3150
3151     for (i = 0; i < evaspixmapsink->num_of_pixmaps; i ++) {
3152       if (!evaspixmapsink->xpixmap[i]) {
3153         g_mutex_unlock (evaspixmapsink->flow_lock);
3154         return;
3155       }
3156     }
3157
3158     memcpy (&result, &evaspixmapsink->render_rect, sizeof (GstVideoRectangle));
3159
3160     g_mutex_unlock (evaspixmapsink->flow_lock);
3161
3162     /* We calculate scaling using the original video frames geometry to include
3163        pixel aspect ratio scaling. */
3164     xscale = (gdouble) evaspixmapsink->video_width / result.w;
3165     yscale = (gdouble) evaspixmapsink->video_height / result.h;
3166
3167     /* Converting pointer coordinates to the non scaled geometry */
3168     if (gst_structure_get_double (structure, "pointer_x", &x)) {
3169       x = MIN (x, result.x + result.w);
3170       x = MAX (x - result.x, 0);
3171       gst_structure_set (structure, "pointer_x", G_TYPE_DOUBLE,
3172           (gdouble) x * xscale, NULL);
3173     }
3174     if (gst_structure_get_double (structure, "pointer_y", &y)) {
3175       y = MIN (y, result.y + result.h);
3176       y = MAX (y - result.y, 0);
3177       gst_structure_set (structure, "pointer_y", G_TYPE_DOUBLE,
3178           (gdouble) y * yscale, NULL);
3179     }
3180
3181     gst_pad_send_event (peer, event);
3182     gst_object_unref (peer);
3183   }
3184 }
3185
3186 static void
3187 gst_evaspixmapsink_navigation_init (GstNavigationInterface *iface)
3188 {
3189   iface->send_event = gst_evaspixmapsink_navigation_send_event;
3190 }
3191
3192 static const GList*
3193 gst_evaspixmapsink_colorbalance_list_channels (GstColorBalance *balance)
3194 {
3195   GstEvasPixmapSink *evaspixmapsink = GST_EVASPIXMAPSINK (balance);
3196
3197   g_return_val_if_fail (GST_IS_EVASPIXMAPSINK (evaspixmapsink), NULL);
3198
3199   if (evaspixmapsink->xcontext)
3200     return evaspixmapsink->xcontext->channels_list;
3201   else
3202     return NULL;
3203 }
3204
3205 static void
3206 gst_evaspixmapsink_colorbalance_set_value (GstColorBalance *balance, GstColorBalanceChannel *channel, gint value)
3207 {
3208   GstEvasPixmapSink *evaspixmapsink = GST_EVASPIXMAPSINK (balance);
3209
3210   g_return_if_fail (GST_IS_EVASPIXMAPSINK (evaspixmapsink));
3211   g_return_if_fail (channel->label != NULL);
3212
3213   evaspixmapsink->cb_changed = TRUE;
3214
3215   /* Normalize val to [-1000, 1000] */
3216   value = floor (0.5 + -1000 + 2000 * (value - channel->min_value) /
3217       (double) (channel->max_value - channel->min_value));
3218
3219   if (g_ascii_strcasecmp (channel->label, "XV_HUE") == 0) {
3220     evaspixmapsink->hue = value;
3221   } else if (g_ascii_strcasecmp (channel->label, "XV_SATURATION") == 0) {
3222     evaspixmapsink->saturation = value;
3223   } else if (g_ascii_strcasecmp (channel->label, "XV_CONTRAST") == 0) {
3224     evaspixmapsink->contrast = value;
3225   } else if (g_ascii_strcasecmp (channel->label, "XV_BRIGHTNESS") == 0) {
3226     evaspixmapsink->brightness = value;
3227   } else {
3228     g_warning ("got an unknown channel %s", channel->label);
3229     return;
3230   }
3231
3232   gst_evaspixmapsink_update_colorbalance (evaspixmapsink);
3233 }
3234
3235 static gint
3236 gst_evaspixmapsink_colorbalance_get_value (GstColorBalance *balance, GstColorBalanceChannel *channel)
3237 {
3238   GstEvasPixmapSink *evaspixmapsink = GST_EVASPIXMAPSINK (balance);
3239   gint value = 0;
3240
3241   g_return_val_if_fail (GST_IS_EVASPIXMAPSINK (evaspixmapsink), 0);
3242   g_return_val_if_fail (channel->label != NULL, 0);
3243
3244   if (g_ascii_strcasecmp (channel->label, "XV_HUE") == 0) {
3245     value = evaspixmapsink->hue;
3246   } else if (g_ascii_strcasecmp (channel->label, "XV_SATURATION") == 0) {
3247     value = evaspixmapsink->saturation;
3248   } else if (g_ascii_strcasecmp (channel->label, "XV_CONTRAST") == 0) {
3249     value = evaspixmapsink->contrast;
3250   } else if (g_ascii_strcasecmp (channel->label, "XV_BRIGHTNESS") == 0) {
3251     value = evaspixmapsink->brightness;
3252   } else {
3253     g_warning ("got an unknown channel %s", channel->label);
3254   }
3255
3256   /* Normalize val to [channel->min_value, channel->max_value] */
3257   value = channel->min_value + (channel->max_value - channel->min_value) * (value + 1000) / 2000;
3258
3259   return value;
3260 }
3261
3262 static void
3263 gst_evaspixmapsink_colorbalance_init (GstColorBalanceClass *iface)
3264 {
3265   GST_COLOR_BALANCE_TYPE (iface) = GST_COLOR_BALANCE_HARDWARE;
3266   iface->list_channels = gst_evaspixmapsink_colorbalance_list_channels;
3267   iface->set_value = gst_evaspixmapsink_colorbalance_set_value;
3268   iface->get_value = gst_evaspixmapsink_colorbalance_get_value;
3269 }
3270
3271 static const GList *
3272 gst_evaspixmapsink_probe_get_properties (GstPropertyProbe *probe)
3273 {
3274         GObjectClass *klass = G_OBJECT_GET_CLASS (probe);
3275         static GList *list = NULL;
3276
3277         if (!list) {
3278                 list = g_list_append (NULL, g_object_class_find_property (klass, "device"));
3279                 list = g_list_append (list, g_object_class_find_property (klass, "autopaint-colorkey"));
3280                 list = g_list_append (list, g_object_class_find_property (klass, "double-buffer"));
3281                 list = g_list_append (list, g_object_class_find_property (klass, "colorkey"));
3282         }
3283
3284         return list;
3285 }
3286
3287 static void
3288 gst_evaspixmapsink_probe_probe_property (GstPropertyProbe *probe, guint prop_id, const GParamSpec *pspec)
3289 {
3290   GstEvasPixmapSink *evaspixmapsink = GST_EVASPIXMAPSINK (probe);
3291
3292   switch (prop_id) {
3293     case PROP_DEVICE:
3294     case PROP_AUTOPAINT_COLORKEY:
3295     case PROP_DOUBLE_BUFFER:
3296     case PROP_COLORKEY:
3297       GST_DEBUG_OBJECT (evaspixmapsink,"probing device list and get capabilities");
3298       if (!evaspixmapsink->xcontext) {
3299         GST_DEBUG_OBJECT (evaspixmapsink,"generating xcontext");
3300         evaspixmapsink->xcontext = gst_evaspixmapsink_xcontext_get (evaspixmapsink);
3301         if (!evaspixmapsink->xcontext) {
3302           GST_ERROR_OBJECT (evaspixmapsink,"could not get xcontext..");
3303         }
3304       }
3305       break;
3306     default:
3307       G_OBJECT_WARN_INVALID_PROPERTY_ID (probe, prop_id, pspec);
3308       break;
3309   }
3310 }
3311
3312 static gboolean
3313 gst_evaspixmapsink_probe_needs_probe (GstPropertyProbe *probe, guint prop_id, const GParamSpec *pspec)
3314 {
3315   GstEvasPixmapSink *evaspixmapsink = GST_EVASPIXMAPSINK (probe);
3316   gboolean ret = FALSE;
3317
3318   switch (prop_id) {
3319     case PROP_DEVICE:
3320     case PROP_AUTOPAINT_COLORKEY:
3321     case PROP_DOUBLE_BUFFER:
3322     case PROP_COLORKEY:
3323       if (evaspixmapsink->xcontext != NULL) {
3324         ret = FALSE;
3325       } else {
3326         ret = TRUE;
3327       }
3328       break;
3329     default:
3330       G_OBJECT_WARN_INVALID_PROPERTY_ID (probe, prop_id, pspec);
3331       break;
3332   }
3333
3334   return ret;
3335 }
3336
3337 static GValueArray *
3338 gst_evaspixmapsink_probe_get_values (GstPropertyProbe *probe, guint prop_id, const GParamSpec *pspec)
3339 {
3340   GstEvasPixmapSink *evaspixmapsink = GST_EVASPIXMAPSINK (probe);
3341   GValueArray *array = NULL;
3342
3343   if (G_UNLIKELY (!evaspixmapsink->xcontext)) {
3344     GST_WARNING_OBJECT (evaspixmapsink,"we don't have any xcontext, can't "
3345         "get values");
3346     goto beach;
3347   }
3348
3349   switch (prop_id) {
3350     case PROP_DEVICE:
3351     {
3352       guint i;
3353       GValue value = { 0 };
3354
3355       array = g_value_array_new (evaspixmapsink->xcontext->nb_adaptors);
3356       g_value_init (&value, G_TYPE_STRING);
3357
3358       for (i = 0; i < evaspixmapsink->xcontext->nb_adaptors; i++) {
3359         gchar *adaptor_id_s = g_strdup_printf ("%u", i);
3360
3361         g_value_set_string (&value, adaptor_id_s);
3362         g_value_array_append (array, &value);
3363         g_free (adaptor_id_s);
3364       }
3365       g_value_unset (&value);
3366       break;
3367     }
3368     case PROP_AUTOPAINT_COLORKEY:
3369       if (evaspixmapsink->have_autopaint_colorkey) {
3370         GValue value = { 0 };
3371
3372         array = g_value_array_new (2);
3373         g_value_init (&value, G_TYPE_BOOLEAN);
3374         g_value_set_boolean (&value, FALSE);
3375         g_value_array_append (array, &value);
3376         g_value_set_boolean (&value, TRUE);
3377         g_value_array_append (array, &value);
3378         g_value_unset (&value);
3379       }
3380       break;
3381     case PROP_DOUBLE_BUFFER:
3382       if (evaspixmapsink->have_double_buffer) {
3383         GValue value = { 0 };
3384
3385         array = g_value_array_new (2);
3386         g_value_init (&value, G_TYPE_BOOLEAN);
3387         g_value_set_boolean (&value, FALSE);
3388         g_value_array_append (array, &value);
3389         g_value_set_boolean (&value, TRUE);
3390         g_value_array_append (array, &value);
3391         g_value_unset (&value);
3392       }
3393       break;
3394     case PROP_COLORKEY:
3395       if (evaspixmapsink->have_colorkey) {
3396         GValue value = { 0 };
3397
3398         array = g_value_array_new (1);
3399         g_value_init (&value, GST_TYPE_INT_RANGE);
3400         gst_value_set_int_range (&value, 0, 0xffffff);
3401         g_value_array_append (array, &value);
3402         g_value_unset (&value);
3403       }
3404       break;
3405     default:
3406       G_OBJECT_WARN_INVALID_PROPERTY_ID (probe, prop_id, pspec);
3407       break;
3408   }
3409
3410 beach:
3411   return array;
3412 }
3413
3414 static void
3415 gst_evaspixmapsink_property_probe_interface_init (GstPropertyProbeInterface *iface)
3416 {
3417         iface->get_properties = gst_evaspixmapsink_probe_get_properties;
3418         iface->probe_property = gst_evaspixmapsink_probe_probe_property;
3419         iface->needs_probe = gst_evaspixmapsink_probe_needs_probe;
3420         iface->get_values = gst_evaspixmapsink_probe_get_values;
3421 }
3422
3423 static gboolean
3424 gst_evaspixmapsink_xpixmap_link (GstEvasPixmapSink *evaspixmapsink)
3425 {
3426         Display *dpy;
3427         Pixmap *pixmap_id[NUM_OF_PIXMAP];
3428         int evas_object_width = 0;
3429         int evas_object_height = 0;
3430         int pixmap_width = 0;
3431         int pixmap_height = 0;
3432         unsigned int xw = 0;
3433         unsigned int xh = 0;
3434         int i = 0;
3435
3436         GST_DEBUG_OBJECT (evaspixmapsink,"[START]");
3437
3438         if (!evaspixmapsink) {
3439                 GST_ERROR_OBJECT (evaspixmapsink,"could not get evaspixmapsink..");
3440                 return FALSE;
3441         }
3442         g_mutex_lock (evaspixmapsink->flow_lock);
3443
3444         /* Set xcontext and display */
3445         if (!evaspixmapsink->xcontext) {
3446                 GST_WARNING_OBJECT (evaspixmapsink,"there's no xcontext, try to get one..");
3447                 evaspixmapsink->xcontext = gst_evaspixmapsink_xcontext_get (evaspixmapsink);
3448                 if (!evaspixmapsink->xcontext) {
3449                         GST_ERROR_OBJECT (evaspixmapsink,"could not get xcontext..");
3450                         return FALSE;
3451                 }
3452         }
3453
3454         /* Set evas image object size */
3455         evas_object_geometry_get(evaspixmapsink->eo, NULL, NULL, &evas_object_width, &evas_object_height);
3456
3457         /* check if it is redundant request */
3458         for (i = 0; i < evaspixmapsink->num_of_pixmaps; i++) {
3459                 if (evaspixmapsink->xpixmap[i]) {
3460                         if (!evaspixmapsink->use_origin_size && evaspixmapsink->xpixmap[i]->width && evaspixmapsink->xpixmap[i]->height) {
3461                                 if (evaspixmapsink->xpixmap[i]->width == evas_object_width && evaspixmapsink->xpixmap[i]->height == evas_object_height) {
3462                                         GST_WARNING_OBJECT (evaspixmapsink,"pixmap was already created(w:%d, h:%d), skip it..",
3463                                                 evaspixmapsink->xpixmap[i]->width, evaspixmapsink->xpixmap[i]->height);
3464                                         for (i = 0; i < evaspixmapsink->num_of_pixmaps; i++) {
3465                                                 XSetForeground (evaspixmapsink->xcontext->disp, evaspixmapsink->xpixmap[i]->gc, evaspixmapsink->xcontext->black);
3466                                                 XFillRectangle (evaspixmapsink->xcontext->disp, evaspixmapsink->xpixmap[i]->pixmap, evaspixmapsink->xpixmap[i]->gc,
3467                                                         0, 0, evaspixmapsink->xpixmap[i]->width, evaspixmapsink->xpixmap[i]->height);
3468                                                 GST_LOG_OBJECT (evaspixmapsink,"fill black to xpixmap[%d] with size(w:%d,h:%d)", evaspixmapsink->xpixmap[i]->pixmap,
3469                                                                 evaspixmapsink->xpixmap[i]->width, evaspixmapsink->xpixmap[i]->height);
3470                                         }
3471                                         goto SKIP_LINK;
3472                                 }
3473                         }
3474                 }
3475         }
3476
3477         dpy = evaspixmapsink->xcontext->disp;
3478
3479         if (evaspixmapsink->use_origin_size || !evas_object_width || !evas_object_height) {
3480                 pixmap_width = evaspixmapsink->video_width;
3481                 pixmap_height = evaspixmapsink->video_height;
3482                 GST_INFO_OBJECT (evaspixmapsink,"set size to media src size(%dx%d)", pixmap_width, pixmap_height);
3483         }
3484
3485         g_mutex_lock (evaspixmapsink->x_lock);
3486         evaspixmapsink->sizediff_width = 0;
3487         evaspixmapsink->sizediff_height = 0;
3488         if (evaspixmapsink->use_origin_size || !evas_object_width || !evas_object_height) {
3489                 XvQueryBestSize(dpy, evaspixmapsink->xcontext->xv_port_id,0,0,0, pixmap_width, pixmap_height, &xw, &xh);
3490                 if (!evas_object_width || !evas_object_height) {
3491                         evaspixmapsink->w = xw;
3492                         evaspixmapsink->h = xh;
3493                 } else {
3494                         evaspixmapsink->w = evas_object_width;
3495                         evaspixmapsink->h = evas_object_height;
3496                 }
3497                 GST_DEBUG_OBJECT (evaspixmapsink,"XvQueryBestSize : xv_port_id(%d), w(%d),h(%d) => xw(%d),xh(%d)", evaspixmapsink->xcontext->xv_port_id, pixmap_width, pixmap_height, xw, xh);
3498         } else {
3499                 XvQueryBestSize(dpy, evaspixmapsink->xcontext->xv_port_id,0,0,0, evas_object_width, evas_object_height, &xw, &xh);
3500                 GST_DEBUG_OBJECT (evaspixmapsink,"XvQueryBestSize : xv_port_id(%d), w(%d),h(%d) => xw(%d),xh(%d)", evaspixmapsink->xcontext->xv_port_id, evas_object_width, evas_object_height, xw, xh);
3501                 evaspixmapsink->w = xw;
3502                 evaspixmapsink->h = xh;
3503                 /* update difference of size information (between evas image object's and pixmap's) */
3504                 evaspixmapsink->sizediff_width = xw - evas_object_width;
3505                 evaspixmapsink->sizediff_height = xh - evas_object_height;
3506         }
3507
3508         /* create xpixmap structure */
3509         for (i = 0; i < evaspixmapsink->num_of_pixmaps; i++) {
3510                 if (!evaspixmapsink->xpixmap[i]) {
3511                         /* xpixmap can be created in this function only */
3512                         evaspixmapsink->xpixmap[i] = g_new0 (GstXPixmap, 1);
3513                         if(!evaspixmapsink->xpixmap[i]) {
3514                                 GST_ERROR_OBJECT (evaspixmapsink,"xpixmap is not valid..");
3515                                 int j = 0;
3516                                 for (j = 0; j < i; j++) {
3517                                         g_free(evaspixmapsink->xpixmap[j]);
3518                                 }
3519                                 goto GO_OUT_OF_FUNC;
3520                         }
3521                 }
3522         }
3523
3524         /* create pixmap */
3525         if (!xw || !xh) {
3526                 GST_WARNING_OBJECT (evaspixmapsink,"skip creating pixmap..xw(%d),xh(%d)",xw,xh);
3527                 goto GO_OUT_OF_FUNC;
3528         } else {
3529                 /* multiple pixmaps creation */
3530                 for (i = 0; i < evaspixmapsink->num_of_pixmaps; i++) {
3531                         pixmap_id[i] = XCreatePixmap(dpy, DefaultRootWindow(dpy), xw, xh, DefaultDepth(dpy, DefaultScreen(dpy)));
3532                         if ( (int)pixmap_id[i] == BadAlloc || (int)pixmap_id[i] == BadDrawable || (int)pixmap_id[i] == BadValue ) {
3533                                 GST_ERROR_OBJECT (evaspixmapsink,"pixmap[%d] allocation error..", i);
3534                                 int j = 0;
3535                                 for (j = 0; j < i; j++) {
3536                                         XFreePixmap(dpy, pixmap_id[j]);
3537                                 }
3538                                 goto GO_OUT_OF_FUNC;
3539                         }
3540                         GST_INFO_OBJECT (evaspixmapsink,"creation pixmap_id[%d]:%d success", i, pixmap_id[i]);
3541                         GST_DEBUG_OBJECT (evaspixmapsink,"evas_object_width(%d),evas_object_height(%d),pixmap:%d,depth:%d",
3542                                                                 evas_object_width,evas_object_height,pixmap_id[i],DefaultDepth(dpy, DefaultScreen(dpy)));
3543                 }
3544         }
3545
3546         for (i = 0; i < evaspixmapsink->num_of_pixmaps; i++) {
3547                 if (evaspixmapsink->xpixmap[i]->pixmap && pixmap_id[i] != evaspixmapsink->xpixmap[i]->pixmap) {
3548                         g_mutex_unlock (evaspixmapsink->x_lock);
3549                         g_mutex_lock (evaspixmapsink->pixmap_ref_lock);
3550                         /* If we reset another pixmap, do below */
3551                         evaspixmapsink->xpixmap[i]->prev_pixmap = evaspixmapsink->xpixmap[i]->pixmap;
3552                         evaspixmapsink->xpixmap[i]->prev_gc = evaspixmapsink->xpixmap[i]->gc;
3553                         evaspixmapsink->xpixmap[i]->pixmap = 0;
3554                         evaspixmapsink->xpixmap[i]->ref = 0;
3555                         evaspixmapsink->xpixmap[i]->damaged_time = 0;
3556                         g_mutex_unlock (evaspixmapsink->pixmap_ref_lock);
3557                         g_mutex_lock (evaspixmapsink->x_lock);
3558                 }
3559         }
3560
3561         for (i = 0; i < evaspixmapsink->num_of_pixmaps; i++) {
3562                 /* Set pixmap id and create GC */
3563                 evaspixmapsink->xpixmap[i]->pixmap = pixmap_id[i];
3564                 evaspixmapsink->xpixmap[i]->gc = XCreateGC(dpy, evaspixmapsink->xpixmap[i]->pixmap, 0,0);
3565                 evaspixmapsink->xpixmap[i]->width = xw;
3566                 evaspixmapsink->xpixmap[i]->height = xh;
3567
3568                 /* Create XDamage */
3569                 if (evaspixmapsink->damage[i]) {
3570                         evaspixmapsink->prev_damage[i] = evaspixmapsink->damage[i];
3571                 }
3572                 evaspixmapsink->damage[i] = XDamageCreate (dpy, evaspixmapsink->xpixmap[i]->pixmap, XDamageReportRawRectangles);
3573
3574                 GST_WARNING_OBJECT (evaspixmapsink,"xpixmap[%d]->(pixmap:%d,gc:%p), damage[%d]:%d",
3575                                         i, evaspixmapsink->xpixmap[i]->pixmap, evaspixmapsink->xpixmap[i]->gc, i, evaspixmapsink->damage[i]);
3576
3577                 /* Fill blackcolor for the new pixmap */
3578                 XSetForeground (evaspixmapsink->xcontext->disp, evaspixmapsink->xpixmap[i]->gc, evaspixmapsink->xcontext->black);
3579                 XFillRectangle (evaspixmapsink->xcontext->disp, pixmap_id[i], evaspixmapsink->xpixmap[i]->gc,
3580                                         0, 0, evaspixmapsink->w, evaspixmapsink->h);
3581                 GST_LOG_OBJECT (evaspixmapsink,"fill black to xpixmap[%d] with size(w:%d,h:%d)", pixmap_id[i],
3582                                         evaspixmapsink->w, evaspixmapsink->h);
3583         }
3584
3585         XSync(dpy, FALSE);
3586
3587         /* Set flag for mapping evas object with xpixmap */
3588         evaspixmapsink->do_link = TRUE;
3589         if (evaspixmapsink->epipe_request_count > EPIPE_REQUEST_LIMIT) {
3590                 GST_WARNING_OBJECT (evaspixmapsink,"epipe_request_count(%d), skip ecore_pipe_write()", evaspixmapsink->epipe_request_count);
3591         } else {
3592                 ecore_pipe_write(evaspixmapsink->epipe, evaspixmapsink, sizeof(GstEvasPixmapSink));
3593                 evaspixmapsink->epipe_request_count++;
3594         }
3595
3596         gst_evaspixmapsink_update_colorbalance (evaspixmapsink);
3597
3598         g_mutex_unlock (evaspixmapsink->x_lock);
3599
3600
3601 SKIP_LINK:
3602         g_mutex_lock (evaspixmapsink->pixmap_ref_lock);
3603         evaspixmapsink->last_updated_idx = -1;
3604         g_mutex_unlock (evaspixmapsink->pixmap_ref_lock);
3605
3606         g_mutex_unlock (evaspixmapsink->flow_lock);
3607
3608         GST_DEBUG_OBJECT (evaspixmapsink,"[END]");
3609
3610         return TRUE;
3611
3612 GO_OUT_OF_FUNC:
3613         g_mutex_unlock (evaspixmapsink->x_lock);
3614         g_mutex_unlock (evaspixmapsink->flow_lock);
3615         return FALSE;
3616 }
3617
3618 static void
3619 gst_evaspixmapsink_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
3620 {
3621         GstEvasPixmapSink *evaspixmapsink;
3622         g_return_if_fail (GST_IS_EVASPIXMAPSINK (object));
3623         evaspixmapsink = GST_EVASPIXMAPSINK (object);
3624
3625         switch (prop_id) {
3626         case PROP_HUE:
3627                 evaspixmapsink->hue = g_value_get_int (value);
3628                 evaspixmapsink->cb_changed = TRUE;
3629                 gst_evaspixmapsink_update_colorbalance (evaspixmapsink);
3630                 break;
3631         case PROP_CONTRAST:
3632                 evaspixmapsink->contrast = g_value_get_int (value);
3633                 evaspixmapsink->cb_changed = TRUE;
3634                 gst_evaspixmapsink_update_colorbalance (evaspixmapsink);
3635                 break;
3636         case PROP_BRIGHTNESS:
3637                 evaspixmapsink->brightness = g_value_get_int (value);
3638                 evaspixmapsink->cb_changed = TRUE;
3639                 gst_evaspixmapsink_update_colorbalance (evaspixmapsink);
3640                 break;
3641         case PROP_SATURATION:
3642                 evaspixmapsink->saturation = g_value_get_int (value);
3643                 evaspixmapsink->cb_changed = TRUE;
3644                 gst_evaspixmapsink_update_colorbalance (evaspixmapsink);
3645                 break;
3646         case PROP_DISPLAY:
3647                 evaspixmapsink->display_name = g_strdup (g_value_get_string (value));
3648                 break;
3649         case PROP_SYNCHRONOUS:
3650                 evaspixmapsink->synchronous = g_value_get_boolean (value);
3651                 if (evaspixmapsink->xcontext) {
3652                         XSynchronize (evaspixmapsink->xcontext->disp, evaspixmapsink->synchronous);
3653                         GST_DEBUG_OBJECT (evaspixmapsink,"XSynchronize called with %s", evaspixmapsink->synchronous ? "TRUE" : "FALSE");
3654                 }
3655                 break;
3656         case PROP_PIXEL_ASPECT_RATIO:
3657                 g_free (evaspixmapsink->par);
3658                 evaspixmapsink->par = g_new0 (GValue, 1);
3659                 g_value_init (evaspixmapsink->par, GST_TYPE_FRACTION);
3660                 if (!g_value_transform (value, evaspixmapsink->par)) {
3661                         g_warning ("Could not transform string to aspect ratio");
3662                         gst_value_set_fraction (evaspixmapsink->par, 1, 1);
3663                 }
3664                 GST_DEBUG_OBJECT (evaspixmapsink,"set PAR to %d/%d", gst_value_get_fraction_numerator (evaspixmapsink->par), gst_value_get_fraction_denominator (evaspixmapsink->par));
3665                 break;
3666         case PROP_DEVICE:
3667                 evaspixmapsink->adaptor_no = atoi (g_value_get_string (value));
3668                 break;
3669         case PROP_DOUBLE_BUFFER:
3670                 evaspixmapsink->double_buffer = g_value_get_boolean (value);
3671                 break;
3672         case PROP_AUTOPAINT_COLORKEY:
3673                 evaspixmapsink->autopaint_colorkey = g_value_get_boolean (value);
3674                 break;
3675         case PROP_COLORKEY:
3676                 evaspixmapsink->colorkey = g_value_get_int (value);
3677                 break;
3678         case PROP_PIXMAP_WIDTH:
3679         {
3680                 /* To do : code related to pixmap re-link */
3681                 GST_LOG_OBJECT (evaspixmapsink, "Not supported");
3682                 break;
3683         }
3684         case PROP_PIXMAP_HEIGHT:
3685         {
3686                 /* To do : code related to pixmap re-link */
3687                 GST_LOG_OBJECT (evaspixmapsink, "Not supported");
3688                 break;
3689         }
3690         case PROP_DISPLAY_GEOMETRY_METHOD:
3691         {
3692                 guint new_val = g_value_get_enum (value);
3693                 if (evaspixmapsink->display_geometry_method != new_val) {
3694                         evaspixmapsink->display_geometry_method = new_val;
3695                         GST_INFO_OBJECT (evaspixmapsink,"Overlay geometry method update, display_geometry_method(%d)",evaspixmapsink->display_geometry_method);
3696                         if( evaspixmapsink->display_geometry_method != DISP_GEO_METHOD_FULL_SCREEN &&
3697                                   evaspixmapsink->display_geometry_method != DISP_GEO_METHOD_CROPPED_FULL_SCREEN ) {
3698                                 if( evaspixmapsink->xcontext ) {
3699                                         g_mutex_lock( evaspixmapsink->flow_lock );
3700                                         int i = 0;
3701                                         for (i = 0; i < evaspixmapsink->num_of_pixmaps; i++) {
3702                                                 if (evaspixmapsink->xpixmap[i]) {
3703                                                         gst_evaspixmapsink_xpixmap_clear (evaspixmapsink, evaspixmapsink->xpixmap[i]);
3704                                                 }
3705                                         }
3706                                         g_mutex_unlock( evaspixmapsink->flow_lock );
3707                                 }
3708                         }
3709                         if (evaspixmapsink->xcontext) {
3710                                 gst_evaspixmap_buffer_put (evaspixmapsink, evaspixmapsink->evas_pixmap_buf);
3711                         }
3712                 }
3713                 break;
3714         }
3715         case PROP_DST_ROI_X:
3716                 evaspixmapsink->dst_roi.x = g_value_get_int (value);
3717                 GST_INFO_OBJECT (evaspixmapsink, "ROI_X(%d)",evaspixmapsink->dst_roi.x );
3718                 break;
3719         case PROP_DST_ROI_Y:
3720                 evaspixmapsink->dst_roi.y = g_value_get_int (value);
3721                 GST_INFO_OBJECT (evaspixmapsink, "ROI_Y(%d)",evaspixmapsink->dst_roi.y );
3722                 break;
3723         case PROP_DST_ROI_W:
3724                 evaspixmapsink->dst_roi.w = g_value_get_int (value);
3725                 GST_INFO_OBJECT (evaspixmapsink, "ROI_W(%d)",evaspixmapsink->dst_roi.w );
3726                 break;
3727         case PROP_DST_ROI_H:
3728                 evaspixmapsink->dst_roi.h = g_value_get_int (value);
3729                 GST_INFO_OBJECT (evaspixmapsink, "ROI_H(%d)",evaspixmapsink->dst_roi.h );
3730                 break;
3731         case PROP_STOP_VIDEO:
3732                 evaspixmapsink->stop_video = g_value_get_int (value);
3733                 g_mutex_lock( evaspixmapsink->flow_lock );
3734                 if( evaspixmapsink->stop_video ) {
3735                         GST_INFO_OBJECT (evaspixmapsink, "XPixmap CLEAR when set video-stop property" );
3736                         int i = 0;
3737                         for (i = 0; i < evaspixmapsink->num_of_pixmaps; i++) {
3738                                 if (evaspixmapsink->xpixmap[i]) {
3739                                         gst_evaspixmapsink_xpixmap_clear (evaspixmapsink, evaspixmapsink->xpixmap[i]);
3740                                 }
3741                         }
3742                 }
3743                 GST_INFO_OBJECT (evaspixmapsink, "video-stop property(%d)", evaspixmapsink->stop_video);
3744
3745                 g_mutex_unlock( evaspixmapsink->flow_lock );
3746                 break;
3747         case PROP_EVAS_OBJECT:
3748         {
3749                 Evas_Object *eo = g_value_get_pointer (value);
3750                 if ( is_evas_image_object (eo)) {
3751                         if (!evaspixmapsink->epipe) {
3752                                 evaspixmapsink->epipe = ecore_pipe_add (ecore_pipe_callback_handler, evaspixmapsink);
3753                                 if (!evaspixmapsink->epipe) {
3754                                         GST_ERROR_OBJECT (evaspixmapsink,"Cannot set evas-object property: ecore_pipe_add() failed");
3755                                         break;
3756                                 }
3757                         }
3758                         if (evaspixmapsink->eo == NULL) {
3759                                 evaspixmapsink->eo = eo;
3760                                 /* add evas object callbacks on a new evas image object */
3761                                 EVASPIXMAPSINK_SET_EVAS_OBJECT_EVENT_CALLBACK (eo, evaspixmapsink);
3762                                 if (GST_STATE(evaspixmapsink) < GST_STATE_PAUSED) {
3763                                         GST_INFO_OBJECT (evaspixmapsink,"It's the first time the new evas image object(%x) is set, skip gst_evaspixmapsink_xpixmap_link()..", eo);
3764                                         break;
3765                                 } else {
3766                                         if (!gst_evaspixmapsink_xpixmap_link(evaspixmapsink)) {
3767                                                 GST_WARNING_OBJECT (evaspixmapsink,"link evas image object with pixmap failed...");
3768                                                 evaspixmapsink->eo = NULL;
3769                                                 break;
3770                                         }
3771                                 }
3772                         }
3773                         if (eo == evaspixmapsink->eo) {
3774                                 GST_LOG_OBJECT (evaspixmapsink,"new evas image object(%x) is same as the previous one(%x)", eo, evaspixmapsink->eo);
3775                         } else {
3776                                 GST_INFO_OBJECT (evaspixmapsink,"new evas image object(%x), previous one(%x)", eo, evaspixmapsink->eo);
3777                                 /* delete evas object callbacks registrated on a former evas image object */
3778                                 EVASPIXMAPSINK_UNSET_EVAS_OBJECT_EVENT_CALLBACK (evaspixmapsink->eo);
3779                                 evaspixmapsink->eo = eo;
3780                                 if (!gst_evaspixmapsink_xpixmap_link(evaspixmapsink)) {
3781                                         GST_WARNING_OBJECT (evaspixmapsink,"link evas image object with pixmap failed...");
3782                                         evaspixmapsink->eo = NULL;
3783                                         break;
3784                                 }
3785                                 /* add evas object callbacks on a new evas image object */
3786                                 EVASPIXMAPSINK_SET_EVAS_OBJECT_EVENT_CALLBACK (eo, evaspixmapsink);
3787                         }
3788                         GST_INFO_OBJECT (evaspixmapsink,"Evas image object(%x) is set", evaspixmapsink->eo);
3789                 } else {
3790                         GST_ERROR_OBJECT (evaspixmapsink,"Cannot set evas-object property: value is not an evas image object");
3791                 }
3792                 break;
3793         }
3794         case PROP_FLIP:
3795                 evaspixmapsink->flip = g_value_get_enum(value);
3796                 break;
3797         case PROP_ROTATE_ANGLE:
3798                 evaspixmapsink->rotate_angle = g_value_get_enum (value);
3799                 break;
3800         case PROP_VISIBLE:
3801         {
3802                 Eina_Bool r;
3803                 gboolean visible = g_value_get_boolean (value);
3804                 GST_INFO_OBJECT (evaspixmapsink,"evaspixmapsink->visible(%d), new value of visible(%d)", evaspixmapsink->visible, visible);
3805                 if (evaspixmapsink->visible != visible) {
3806                         evaspixmapsink->visible = visible;
3807                         if (evaspixmapsink->eo) {
3808                                 evaspixmapsink->update_visibility = UPDATE_TRUE;
3809                                 if (evaspixmapsink->epipe_request_count > EPIPE_REQUEST_LIMIT) {
3810                                         GST_WARNING_OBJECT (evaspixmapsink,"skip ecore_pipe_write()", evaspixmapsink->epipe_request_count);
3811                                         if (visible) {
3812                                                 evas_object_show(evaspixmapsink->eo);
3813                                                 GST_WARNING_OBJECT (evaspixmapsink, "object show (forcely)");
3814                                         }
3815                                 } else {
3816                                         r = ecore_pipe_write (evaspixmapsink->epipe, &evaspixmapsink->update_visibility, SIZE_FOR_UPDATE_VISIBILITY);
3817                                         evaspixmapsink->epipe_request_count++;
3818                                 }
3819                                 if (r == EINA_FALSE)  {
3820                                         GST_WARNING ("Failed to ecore_pipe_write() for updating visibility)\n");
3821                                 }
3822                                 if (!visible) {
3823                                         int i = 0;
3824                                         g_mutex_lock( evaspixmapsink->flow_lock );
3825                                         for (i = 0; i < evaspixmapsink->num_of_pixmaps; i++) {
3826                                                 if (evaspixmapsink->xpixmap[i]) {
3827                                                         gst_evaspixmapsink_xpixmap_clear (evaspixmapsink, evaspixmapsink->xpixmap[i]);
3828                                                 }
3829                                         }
3830                                         evas_object_hide(evaspixmapsink->eo);
3831                                         GST_INFO_OBJECT (evaspixmapsink, "object hide (forcely)");
3832                                         g_mutex_unlock( evaspixmapsink->flow_lock );
3833                                 } else {
3834                                         gst_evaspixmap_buffer_put (evaspixmapsink, evaspixmapsink->evas_pixmap_buf);
3835                                 }
3836                         } else {
3837                                 GST_WARNING_OBJECT (evaspixmapsink,"evas image object was not set");
3838                         }
3839                 }
3840                 break;
3841         }
3842         case PROP_ORIGIN_SIZE:
3843                 evaspixmapsink->use_origin_size = g_value_get_boolean (value);
3844                 GST_INFO_OBJECT (evaspixmapsink,"set origin-size (%d)",evaspixmapsink->use_origin_size);
3845                 if (evaspixmapsink->previous_origin_size != evaspixmapsink->use_origin_size) {
3846                         if (!gst_evaspixmapsink_xpixmap_link(evaspixmapsink)) {
3847                                 GST_WARNING_OBJECT (evaspixmapsink,"link evas image object with pixmap failed...");
3848                         }
3849                         evaspixmapsink->previous_origin_size = evaspixmapsink->use_origin_size;
3850                 }
3851                 break;
3852         default:
3853                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
3854                 break;
3855         }
3856 }
3857
3858 static void
3859 gst_evaspixmapsink_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
3860 {
3861         GstEvasPixmapSink *evaspixmapsink;
3862
3863         g_return_if_fail (GST_IS_EVASPIXMAPSINK (object));
3864
3865         evaspixmapsink = GST_EVASPIXMAPSINK (object);
3866
3867         switch (prop_id) {
3868         case PROP_HUE:
3869                 g_value_set_int (value, evaspixmapsink->hue);
3870                 break;
3871         case PROP_CONTRAST:
3872                 g_value_set_int (value, evaspixmapsink->contrast);
3873                 break;
3874         case PROP_BRIGHTNESS:
3875                 g_value_set_int (value, evaspixmapsink->brightness);
3876                 break;
3877         case PROP_SATURATION:
3878                 g_value_set_int (value, evaspixmapsink->saturation);
3879                 break;
3880         case PROP_DISPLAY:
3881                 g_value_set_string (value, evaspixmapsink->display_name);
3882                 break;
3883         case PROP_SYNCHRONOUS:
3884                 g_value_set_boolean (value, evaspixmapsink->synchronous);
3885                 break;
3886         case PROP_PIXEL_ASPECT_RATIO:
3887                 if (evaspixmapsink->par) {
3888                         if (!g_value_transform (evaspixmapsink->par, value)) {
3889                                 g_warning ("g_value_transform() failure");
3890                         }
3891                 }
3892                 break;
3893         case PROP_DEVICE:
3894         {
3895                 char *adaptor_no_s = g_strdup_printf ("%u", evaspixmapsink->adaptor_no);
3896                 g_value_set_string (value, adaptor_no_s);
3897                 g_free (adaptor_no_s);
3898                 break;
3899         }
3900         case PROP_DEVICE_NAME:
3901                 if (evaspixmapsink->xcontext && evaspixmapsink->xcontext->adaptors) {
3902                         g_value_set_string (value,
3903                         evaspixmapsink->xcontext->adaptors[evaspixmapsink->adaptor_no]);
3904                 } else {
3905                         g_value_set_string (value, NULL);
3906                 }
3907                 break;
3908         case PROP_DOUBLE_BUFFER:
3909                 g_value_set_boolean (value, evaspixmapsink->double_buffer);
3910                 break;
3911         case PROP_AUTOPAINT_COLORKEY:
3912                 g_value_set_boolean (value, evaspixmapsink->autopaint_colorkey);
3913                 break;
3914         case PROP_COLORKEY:
3915                 g_value_set_int (value, evaspixmapsink->colorkey);
3916                 break;
3917         case PROP_PIXMAP_WIDTH:
3918         {
3919                 GST_LOG_OBJECT (evaspixmapsink, "Not supported");
3920                 break;
3921         }
3922         case PROP_PIXMAP_HEIGHT:
3923         {
3924                 GST_LOG_OBJECT (evaspixmapsink, "Not supported");
3925                 break;
3926         }
3927         case PROP_DISPLAY_GEOMETRY_METHOD:
3928                 g_value_set_enum (value, evaspixmapsink->display_geometry_method);
3929                 break;
3930         case PROP_DST_ROI_X:
3931                 g_value_set_int (value, evaspixmapsink->dst_roi.x);
3932                 break;
3933         case PROP_DST_ROI_Y:
3934                 g_value_set_int (value, evaspixmapsink->dst_roi.y);
3935                 break;
3936         case PROP_DST_ROI_W:
3937                 g_value_set_int (value, evaspixmapsink->dst_roi.w);
3938                 break;
3939         case PROP_DST_ROI_H:
3940                 g_value_set_int (value, evaspixmapsink->dst_roi.h);
3941                 break;
3942         case PROP_STOP_VIDEO:
3943                 g_value_set_int (value, evaspixmapsink->stop_video);
3944                 break;
3945         case PROP_EVAS_OBJECT:
3946                 g_value_set_pointer (value, evaspixmapsink->eo);
3947                 break;
3948         case PROP_FLIP:
3949                 g_value_set_enum(value, evaspixmapsink->flip);
3950                 break;
3951         case PROP_ROTATE_ANGLE:
3952                 g_value_set_enum (value, evaspixmapsink->rotate_angle);
3953                 break;
3954         case PROP_VISIBLE:
3955                 g_value_set_boolean (value, evaspixmapsink->visible);
3956                 break;
3957         case PROP_ORIGIN_SIZE:
3958                 g_value_set_boolean (value, evaspixmapsink->use_origin_size);
3959                 break;
3960         default:
3961                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
3962                 break;
3963   }
3964 }
3965
3966 static void
3967 gst_evaspixmapsink_reset (GstEvasPixmapSink *evaspixmapsink)
3968 {
3969         GST_WARNING_OBJECT (evaspixmapsink,"[START]");
3970
3971         GThread *thread;
3972         GST_OBJECT_LOCK (evaspixmapsink);
3973         evaspixmapsink->running = FALSE;
3974         int i = 0;
3975
3976         /* grab thread and mark it as NULL */
3977         thread = evaspixmapsink->event_thread;
3978         evaspixmapsink->event_thread = NULL;
3979         GST_OBJECT_UNLOCK (evaspixmapsink);
3980
3981         /* Wait for our event thread to finish before we clean up our stuff. */
3982         if (thread) {
3983                 g_thread_join (thread);
3984         }
3985
3986         for (i = 0; i < evaspixmapsink->num_of_pixmaps; i++) {
3987                 if(evaspixmapsink->damage[i]) {
3988                         XDamageDestroy(evaspixmapsink->xcontext->disp, evaspixmapsink->damage[i]);
3989                         evaspixmapsink->damage[i] = NULL;
3990                 }
3991         }
3992         EVASPIXMAPSINK_UNSET_EVAS_OBJECT_EVENT_CALLBACK( evaspixmapsink->eo );
3993
3994         if (evaspixmapsink->evas_pixmap_buf) {
3995                 gst_buffer_unref (GST_BUFFER_CAST (evaspixmapsink->evas_pixmap_buf));
3996                 evaspixmapsink->evas_pixmap_buf = NULL;
3997         }
3998
3999         for (i = 0; i < evaspixmapsink->num_of_pixmaps; i++) {
4000                 gst_evaspixmapsink_xpixmap_clear (evaspixmapsink, evaspixmapsink->xpixmap[i]);
4001                 gst_evaspixmapsink_xpixmap_destroy (evaspixmapsink, evaspixmapsink->xpixmap[i]);
4002                 evaspixmapsink->xpixmap[i] = NULL;
4003         }
4004         if (evaspixmapsink->eo) {
4005                 evas_object_image_native_surface_set(evaspixmapsink->eo, NULL);
4006                 evaspixmapsink->eo = NULL;
4007         }
4008
4009         evaspixmapsink->render_rect.x = evaspixmapsink->render_rect.y =
4010         evaspixmapsink->render_rect.w = evaspixmapsink->render_rect.h = 0;
4011         evaspixmapsink->have_render_rect = FALSE;
4012
4013         evaspixmapsink->epipe_request_count = 0;
4014
4015         gst_evaspixmapsink_xcontext_clear (evaspixmapsink);
4016
4017         GST_WARNING_OBJECT (evaspixmapsink,"[END]");
4018 }
4019
4020 /* Finalize is called only once, dispose can be called multiple times.
4021  * We use mutexes and don't reset stuff to NULL here so let's register
4022  * as a finalize. */
4023 static void
4024 gst_evaspixmapsink_finalize (GObject *object)
4025 {
4026         GstEvasPixmapSink *evaspixmapsink;
4027         evaspixmapsink = GST_EVASPIXMAPSINK (object);
4028         GST_DEBUG_OBJECT (evaspixmapsink,"[START]");
4029
4030         if (evaspixmapsink->display_name) {
4031                 g_free (evaspixmapsink->display_name);
4032                 evaspixmapsink->display_name = NULL;
4033         }
4034         if (evaspixmapsink->par) {
4035                 g_free (evaspixmapsink->par);
4036                 evaspixmapsink->par = NULL;
4037         }
4038         if (evaspixmapsink->x_lock) {
4039                 g_mutex_free (evaspixmapsink->x_lock);
4040                 evaspixmapsink->x_lock = NULL;
4041         }
4042         if (evaspixmapsink->flow_lock) {
4043                 g_mutex_free (evaspixmapsink->flow_lock);
4044                 evaspixmapsink->flow_lock = NULL;
4045         }
4046         if (evaspixmapsink->pixmap_ref_lock) {
4047                 g_mutex_free (evaspixmapsink->pixmap_ref_lock);
4048                 evaspixmapsink->pixmap_ref_lock = NULL;
4049         }
4050         if (evaspixmapsink->epipe) {
4051                 ecore_pipe_del (evaspixmapsink->epipe);
4052                 evaspixmapsink->epipe = NULL;
4053         }
4054
4055         GST_DEBUG_OBJECT (evaspixmapsink,"[END]");
4056
4057         G_OBJECT_CLASS (parent_class)->finalize (object);
4058
4059         MMTA_ACUM_ITEM_SHOW_RESULT_TO(MMTA_SHOW_FILE);
4060         MMTA_RELEASE();
4061 }
4062
4063 static void
4064 gst_evaspixmapsink_init (GstEvasPixmapSink *evaspixmapsink)
4065 {
4066         int i = 0;
4067
4068         GST_DEBUG_OBJECT (evaspixmapsink,"[START]");
4069
4070         evaspixmapsink->display_name = NULL;
4071         evaspixmapsink->adaptor_no = 0;
4072         evaspixmapsink->xcontext = NULL;
4073
4074         for (i = 0; i < NUM_OF_PIXMAP; i++) {
4075                 evaspixmapsink->xpixmap[i] = NULL;
4076                 evaspixmapsink->damage[i] = 0;
4077         }
4078
4079         evaspixmapsink->evas_pixmap_buf = NULL;
4080
4081         evaspixmapsink->hue = evaspixmapsink->saturation = 0;
4082         evaspixmapsink->contrast = evaspixmapsink->brightness = 0;
4083         evaspixmapsink->cb_changed = FALSE;
4084
4085         evaspixmapsink->fps_n = 0;
4086         evaspixmapsink->fps_d = 0;
4087         evaspixmapsink->video_width = 0;
4088         evaspixmapsink->video_height = 0;
4089
4090         evaspixmapsink->x_lock = g_mutex_new ();
4091         evaspixmapsink->flow_lock = g_mutex_new ();
4092         evaspixmapsink->pixmap_ref_lock = g_mutex_new();
4093
4094         evaspixmapsink->synchronous = FALSE;
4095         evaspixmapsink->double_buffer = TRUE;
4096         evaspixmapsink->par = NULL;
4097         evaspixmapsink->autopaint_colorkey = TRUE;
4098         evaspixmapsink->running = FALSE;
4099
4100         /* on 16bit displays this becomes r,g,b = 1,2,3
4101         * on 24bit displays this becomes r,g,b = 8,8,16
4102         * as a port atom value
4103         */
4104         evaspixmapsink->colorkey = (8 << 16) | (8 << 8) | 16;
4105
4106         evaspixmapsink->display_geometry_method = DEF_DISPLAY_GEOMETRY_METHOD;
4107         evaspixmapsink->dst_roi.x = 0;
4108         evaspixmapsink->dst_roi.y = 0;
4109         evaspixmapsink->dst_roi.w = 0;
4110         evaspixmapsink->dst_roi.h = 0;
4111         evaspixmapsink->scr_w = 0;
4112         evaspixmapsink->scr_h = 0;
4113         evaspixmapsink->aligned_width = 0;
4114         evaspixmapsink->aligned_height = 0;
4115         evaspixmapsink->stop_video = FALSE;
4116         evaspixmapsink->eo = NULL;
4117         evaspixmapsink->epipe = NULL;
4118         evaspixmapsink->epipe_request_count = 0;
4119         evaspixmapsink->do_link = FALSE;
4120         evaspixmapsink->flip = DEF_DISPLAY_FLIP;
4121         evaspixmapsink->rotate_angle = DEGREE_0;
4122         evaspixmapsink->visible = TRUE;
4123         evaspixmapsink->update_visibility = UPDATE_FALSE;
4124         evaspixmapsink->use_origin_size = FALSE;
4125         evaspixmapsink->previous_origin_size = FALSE;
4126
4127         evaspixmapsink->num_of_pixmaps = NUM_OF_PIXMAP;
4128
4129         evaspixmapsink->buf_shared_type = BUF_SHARE_METHOD_NONE;
4130
4131         MMTA_INIT();
4132
4133         GST_DEBUG_OBJECT (evaspixmapsink,"[END]");
4134  }
4135
4136 static void
4137 gst_evaspixmapsink_base_init (gpointer g_class)
4138 {
4139   GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
4140
4141   gst_element_class_set_details_simple (element_class,
4142       "EvasPixmapSink", "Sink/Video",
4143       "evas image object videosink based on Xv extension", "Sangchul Lee <sc11.lee@samsung.com>");
4144
4145   gst_element_class_add_pad_template (element_class,
4146       gst_static_pad_template_get (&gst_evaspixmapsink_sink_template_factory));
4147 }
4148
4149 static void
4150 gst_evaspixmapsink_class_init (GstEvasPixmapSinkClass *klass)
4151 {
4152   GObjectClass *gobject_class;
4153   GstElementClass *gstelement_class;
4154   GstBaseSinkClass *gstbasesink_class;
4155   GstVideoSinkClass *videosink_class;
4156
4157   gobject_class = (GObjectClass *) klass;
4158   gstelement_class = (GstElementClass *) klass;
4159   gstbasesink_class = (GstBaseSinkClass *) klass;
4160   videosink_class = (GstVideoSinkClass *) klass;
4161
4162   parent_class = g_type_class_peek_parent (klass);
4163
4164   gobject_class->set_property = gst_evaspixmapsink_set_property;
4165   gobject_class->get_property = gst_evaspixmapsink_get_property;
4166
4167   g_object_class_install_property (gobject_class, PROP_CONTRAST,
4168       g_param_spec_int ("contrast", "Contrast", "The contrast of the video",
4169           -1000, 1000, 0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
4170   g_object_class_install_property (gobject_class, PROP_BRIGHTNESS,
4171       g_param_spec_int ("brightness", "Brightness",
4172           "The brightness of the video", -1000, 1000, 0,
4173           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
4174   g_object_class_install_property (gobject_class, PROP_HUE,
4175       g_param_spec_int ("hue", "Hue", "The hue of the video", -1000, 1000, 0,
4176           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
4177   g_object_class_install_property (gobject_class, PROP_SATURATION,
4178       g_param_spec_int ("saturation", "Saturation",
4179           "The saturation of the video", -1000, 1000, 0,
4180           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
4181   g_object_class_install_property (gobject_class, PROP_DISPLAY,
4182       g_param_spec_string ("display", "Display", "X Display name", NULL,
4183           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
4184   g_object_class_install_property (gobject_class, PROP_SYNCHRONOUS,
4185       g_param_spec_boolean ("synchronous", "Synchronous",
4186           "When enabled, runs "
4187           "the X display in synchronous mode. (used only for debugging)", FALSE,
4188           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
4189   g_object_class_install_property (gobject_class, PROP_PIXEL_ASPECT_RATIO,
4190       g_param_spec_string ("pixel-aspect-ratio", "Pixel Aspect Ratio",
4191           "The pixel aspect ratio of the device", "1/1",
4192           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
4193   g_object_class_install_property (gobject_class, PROP_DEVICE,
4194       g_param_spec_string ("device", "Adaptor number",
4195           "The number of the video adaptor", "0",
4196           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
4197   g_object_class_install_property (gobject_class, PROP_DEVICE_NAME,
4198       g_param_spec_string ("device-name", "Adaptor name",
4199           "The name of the video adaptor", NULL,
4200           G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
4201
4202   /**
4203    * GstEvasPixmapSink:double-buffer
4204    *
4205    * Whether to double-buffer the output.
4206    *
4207    * Since: 0.10.14
4208    */
4209   g_object_class_install_property (gobject_class, PROP_DOUBLE_BUFFER,
4210       g_param_spec_boolean ("double-buffer", "Double-buffer",
4211           "Whether to double-buffer the output", TRUE,
4212           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
4213   /**
4214    * GstEvasPixmapSink:autopaint-colorkey
4215    *
4216    * Whether to autofill overlay with colorkey
4217    *
4218    * Since: 0.10.21
4219    */
4220   g_object_class_install_property (gobject_class, PROP_AUTOPAINT_COLORKEY,
4221       g_param_spec_boolean ("autopaint-colorkey", "Autofill with colorkey",
4222           "Whether to autofill overlay with colorkey", TRUE,
4223           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
4224   /**
4225    * GstEvasPixmapSink:colorkey
4226    *
4227    * Color to use for the overlay mask.
4228    *
4229    * Since: 0.10.21
4230    */
4231   g_object_class_install_property (gobject_class, PROP_COLORKEY,
4232       g_param_spec_int ("colorkey", "Colorkey",
4233           "Color to use for the overlay mask", G_MININT, G_MAXINT, 0,
4234           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
4235
4236   /**
4237    * GstEvasPixmapSink:pixmap-width
4238    *
4239    * Actual width of the pixmap.
4240    */
4241   g_object_class_install_property (gobject_class, PROP_PIXMAP_WIDTH,
4242       g_param_spec_uint64 ("pixmap-width", "pixmap-width", "Width of the pixmap", 0, G_MAXUINT64, 0, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
4243
4244   /**
4245    * GstEvasPixmapSink:pixmap-height
4246    *
4247    * Actual height of the pixmap.
4248    */
4249   g_object_class_install_property (gobject_class, PROP_PIXMAP_HEIGHT,
4250       g_param_spec_uint64 ("pixmap-height", "pixmap-height", "Height of the pixmap", 0, G_MAXUINT64, 0, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
4251
4252   /**
4253    * GstEvasPixmapSink:display-geometry-method
4254    *
4255    * Display geometrical method setting
4256    */
4257   g_object_class_install_property(gobject_class, PROP_DISPLAY_GEOMETRY_METHOD,
4258     g_param_spec_enum("display-geometry-method", "Display geometry method",
4259       "Geometrical method for display",
4260       GST_TYPE_EVASPIXMAPSINK_DISPLAY_GEOMETRY_METHOD, DEF_DISPLAY_GEOMETRY_METHOD,
4261       G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
4262
4263   /**
4264    * GstEvasPixmapSink:dst-roi-x
4265    *
4266    * X value of Destination ROI
4267    */
4268   g_object_class_install_property (gobject_class, PROP_DST_ROI_X,
4269       g_param_spec_int ("dst-roi-x", "Dst-ROI-X",
4270           "X value of Destination ROI(only effective \"CUSTOM_ROI\")", 0, XV_SCREEN_SIZE_WIDTH, 0,
4271           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
4272
4273   /**
4274    * GstEvasPixmapSink:dst-roi-y
4275    *
4276    * Y value of Destination ROI
4277    */
4278   g_object_class_install_property (gobject_class, PROP_DST_ROI_Y,
4279       g_param_spec_int ("dst-roi-y", "Dst-ROI-Y",
4280           "Y value of Destination ROI(only effective \"CUSTOM_ROI\")", 0, XV_SCREEN_SIZE_HEIGHT, 0,
4281           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
4282
4283   /**
4284    * GstEvasPixmapSink:dst-roi-w
4285    *
4286    * W value of Destination ROI
4287    */
4288   g_object_class_install_property (gobject_class, PROP_DST_ROI_W,
4289       g_param_spec_int ("dst-roi-w", "Dst-ROI-W",
4290           "W value of Destination ROI(only effective \"CUSTOM_ROI\")", 0, XV_SCREEN_SIZE_WIDTH, 0,
4291           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
4292
4293   /**
4294    * GstEvasPixmapSink:dst-roi-h
4295    *
4296    * H value of Destination ROI
4297    */
4298   g_object_class_install_property (gobject_class, PROP_DST_ROI_H,
4299       g_param_spec_int ("dst-roi-h", "Dst-ROI-H",
4300           "H value of Destination ROI(only effective \"CUSTOM_ROI\")", 0, XV_SCREEN_SIZE_HEIGHT, 0,
4301           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
4302
4303   /**
4304    * GstEvasPixmapSink:stop-video
4305    *
4306    * Stop video for releasing video source buffer
4307    */
4308   g_object_class_install_property (gobject_class, PROP_STOP_VIDEO,
4309       g_param_spec_int ("stop-video", "Stop-Video", "Stop video for releasing video source buffer", 0, 1, 0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
4310
4311   /**
4312    * GstEvasPixmapSink:evas-object
4313    *
4314    * Evas image object for rendering
4315    */
4316   g_object_class_install_property (gobject_class, PROP_EVAS_OBJECT,
4317     g_param_spec_pointer ("evas-object", "Destination Evas Object",     "Destination evas image object", G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
4318
4319   /**
4320    * GstEvasPixmapSink:display-flip
4321    *
4322    * Display flip setting
4323    */
4324   g_object_class_install_property(gobject_class, PROP_FLIP,
4325     g_param_spec_enum("flip", "Display flip",
4326       "Flip for display",
4327       GST_TYPE_EVASPIXMAPSINK_FLIP, DEF_DISPLAY_FLIP,
4328       G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
4329
4330   /**
4331    * GstEvasPixmapSink:rotate
4332    *
4333    * draw rotation angle setting
4334    */
4335   g_object_class_install_property(gobject_class, PROP_ROTATE_ANGLE,
4336     g_param_spec_enum("rotate", "Rotate angle", "Rotate angle of display output",GST_TYPE_EVASPIXMAPSINK_ROTATE_ANGLE, DEGREE_0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
4337
4338   /**
4339    * GstEvasPixmapSink:visible
4340    *
4341    * visible setting for a evas image object
4342    */
4343   g_object_class_install_property (gobject_class, PROP_VISIBLE,
4344         g_param_spec_boolean ("visible", "Visible", "When setting it false, evas image object does not show", TRUE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
4345
4346    /**
4347    * GstEvasPixmapSink:origin-size
4348    *
4349    * Set pixmap size with media source's width and height
4350    */
4351   g_object_class_install_property (gobject_class, PROP_ORIGIN_SIZE,
4352         g_param_spec_boolean ("origin-size", "Origin-Size", "When setting it true, pixmap will be created with media source's width and height", FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
4353
4354   gobject_class->finalize = gst_evaspixmapsink_finalize;
4355
4356   gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_evaspixmapsink_change_state);
4357   gstbasesink_class->get_caps = GST_DEBUG_FUNCPTR (gst_evaspixmapsink_getcaps);
4358   gstbasesink_class->set_caps = GST_DEBUG_FUNCPTR (gst_evaspixmapsink_setcaps);
4359   gstbasesink_class->get_times = GST_DEBUG_FUNCPTR (gst_evaspixmapsink_get_times);
4360   gstbasesink_class->event = GST_DEBUG_FUNCPTR (gst_evaspixmapsink_event);
4361   videosink_class->show_frame = GST_DEBUG_FUNCPTR (gst_evaspixmapsink_show_frame);
4362 }
4363
4364 /* Object typing & Creation */
4365 GType
4366 gst_evaspixmapsink_get_type (void)
4367 {
4368   static GType evaspixmapsink_type = 0;
4369
4370   if (!evaspixmapsink_type) {
4371     static const GTypeInfo evaspixmapsink_info = {
4372       sizeof (GstEvasPixmapSinkClass),
4373       gst_evaspixmapsink_base_init,
4374       NULL,
4375       (GClassInitFunc) gst_evaspixmapsink_class_init,
4376       NULL,
4377       NULL,
4378       sizeof (GstEvasPixmapSink),
4379       0,
4380       (GInstanceInitFunc) gst_evaspixmapsink_init,
4381     };
4382     static const GInterfaceInfo iface_info = {
4383       (GInterfaceInitFunc) gst_evaspixmapsink_interface_init,
4384       NULL,
4385       NULL,
4386     };
4387     static const GInterfaceInfo navigation_info = {
4388       (GInterfaceInitFunc) gst_evaspixmapsink_navigation_init,
4389       NULL,
4390       NULL,
4391     };
4392     static const GInterfaceInfo colorbalance_info = {
4393       (GInterfaceInitFunc) gst_evaspixmapsink_colorbalance_init,
4394       NULL,
4395       NULL,
4396     };
4397     static const GInterfaceInfo propertyprobe_info = {
4398       (GInterfaceInitFunc) gst_evaspixmapsink_property_probe_interface_init,
4399       NULL,
4400       NULL,
4401     };
4402     evaspixmapsink_type = g_type_register_static (GST_TYPE_VIDEO_SINK, "GstEvasPixmapSink", &evaspixmapsink_info, 0);
4403
4404     g_type_add_interface_static (evaspixmapsink_type, GST_TYPE_IMPLEMENTS_INTERFACE, &iface_info);
4405     g_type_add_interface_static (evaspixmapsink_type, GST_TYPE_NAVIGATION, &navigation_info);
4406     g_type_add_interface_static (evaspixmapsink_type, GST_TYPE_COLOR_BALANCE, &colorbalance_info);
4407     g_type_add_interface_static (evaspixmapsink_type, GST_TYPE_PROPERTY_PROBE, &propertyprobe_info);
4408
4409     /* register type and create class in a more safe place instead of at
4410      * runtime since the type registration and class creation is not
4411      * threadsafe. */
4412     g_type_class_ref (gst_evaspixmap_buffer_get_type ());
4413   }
4414
4415   return evaspixmapsink_type;
4416 }
4417
4418 static gboolean
4419 plugin_init (GstPlugin *plugin)
4420 {
4421         if (!gst_element_register (plugin, "evaspixmapsink", GST_RANK_NONE, GST_TYPE_EVASPIXMAPSINK)) {
4422                 return FALSE;
4423         }
4424         GST_DEBUG_CATEGORY_INIT (gst_debug_evaspixmapsink, "evaspixmapsink", 0, "evaspixmapsink element");
4425         GST_DEBUG_CATEGORY_GET (GST_CAT_PERFORMANCE, "GST_PERFORMANCE");
4426
4427         return TRUE;
4428 }
4429
4430 GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, GST_VERSION_MINOR,
4431         "evaspixmapsink","Evas image object render plugin using Xv extension", plugin_init,
4432         VERSION, GST_LICENSE, GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN)