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