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