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