4 * Copyright (c) 2000 - 2012 Samsung Electronics Co., Ltd. All rights reserved.
6 * Contact: Sangchul Lee <sc11.lee@samsung.com>
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)
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.
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
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>
36 #include "evaspixmapsink.h"
40 /* Samsung extension headers */
41 /* For xv extension header for buffer transfer (output) */
46 #include <sys/ioctl.h>
50 #include <dri2/dri2.h>
51 #include <libdrm/drm.h>
52 #include <tbm_bufmgr.h>
54 /* max channel count *********************************************************/
55 #define SCMN_IMGB_MAX_PLANE (4)
57 /* image buffer definition ***************************************************
59 +------------------------------------------+ ---
62 | +---------------------------+ --- | |
64 | |<---------- w[] ---------->| | | |
72 | +---------------------------+ --- | |
74 +------------------------------------------+ ---
76 |<----------------- s[] ------------------>|
81 /* width of each image plane */
82 int w[SCMN_IMGB_MAX_PLANE];
83 /* height of each image plane */
84 int h[SCMN_IMGB_MAX_PLANE];
85 /* stride of each image plane */
86 int s[SCMN_IMGB_MAX_PLANE];
87 /* elevation of each image plane */
88 int e[SCMN_IMGB_MAX_PLANE];
89 /* user space address of each image plane */
90 void *a[SCMN_IMGB_MAX_PLANE];
91 /* physical address of each image plane, if needs */
92 void *p[SCMN_IMGB_MAX_PLANE];
93 /* color space type of image */
95 /* left postion, if needs */
97 /* top position, if needs */
104 int dma_buf_fd[SCMN_IMGB_MAX_PLANE];
105 /* buffer share method */
106 int buf_share_method;
107 /* Y plane size in case of ST12 */
109 /* UV plane size in case of ST12 */
111 /* Tizen buffer object */
112 void *bo[SCMN_IMGB_MAX_PLANE];
117 /* TZ memory buffer */
121 /* Debugging category */
122 #include <gst/gstinfo.h>
123 GST_DEBUG_CATEGORY_STATIC (gst_debug_evaspixmapsink);
124 #define GST_CAT_DEFAULT gst_debug_evaspixmapsink
125 GST_DEBUG_CATEGORY_STATIC (GST_CAT_PERFORMANCE);
136 DISP_GEO_METHOD_LETTER_BOX = 0,
137 DISP_GEO_METHOD_ORIGIN_SIZE,
138 DISP_GEO_METHOD_FULL_SCREEN,
139 DISP_GEO_METHOD_CROPPED_FULL_SCREEN,
140 DISP_GEO_METHOD_CUSTOM_ROI,
152 #define DEF_DISPLAY_GEOMETRY_METHOD DISP_GEO_METHOD_LETTER_BOX
153 #define DEF_DISPLAY_FLIP FLIP_NONE
154 #define GST_TYPE_EVASPIXMAPSINK_FLIP (gst_evaspixmapsink_flip_get_type())
155 #define GST_TYPE_EVASPIXMAPSINK_ROTATE_ANGLE (gst_evaspixmapsink_rotate_angle_get_type())
156 #define GST_TYPE_EVASPIXMAPSINK_DISPLAY_GEOMETRY_METHOD (gst_evaspixmapsink_display_geometry_method_get_type())
159 /* macro ******************************************************/
160 #define EVASPIXMAPSINK_SET_PIXMAP_ID_TO_GEM_INFO( x_evaspixmapsink, x_pixmap_id ) \
164 XV_DATA_PTR data = (XV_DATA_PTR)x_evaspixmapsink->evas_pixmap_buf->xvimage->data; \
165 if (data->YBuf > 0) { \
166 for (i = 0; i < MAX_GEM_BUFFER_NUM; i++) { \
167 if (evaspixmapsink->gem_info[i].gem_name == data->YBuf) { \
168 evaspixmapsink->gem_info[i].ref_pixmap = x_pixmap_id; \
169 GST_LOG_OBJECT (x_evaspixmapsink,"pixmap(%d) is marked at index(%d) of gem_info(YBuf)->gem_handle(%d)", x_pixmap_id, i, evaspixmapsink->gem_info[i].gem_handle); \
174 if (data->CbBuf > 0) { \
175 for (i = 0; i < MAX_GEM_BUFFER_NUM; i++) { \
176 if (evaspixmapsink->gem_info[i].gem_name == data->CbBuf) { \
177 evaspixmapsink->gem_info[i].ref_pixmap = x_pixmap_id; \
178 GST_LOG_OBJECT (x_evaspixmapsink,"pixmap(%d) is marked at index(%d) of gem_info(CbBuf)->gem_handle(%d)", x_pixmap_id, i, evaspixmapsink->gem_info[i].gem_handle); \
183 if (data->CrBuf > 0) { \
184 for (i = 0; i < MAX_GEM_BUFFER_NUM; i++) { \
185 if (evaspixmapsink->gem_info[i].gem_name == data->CrBuf) { \
186 evaspixmapsink->gem_info[i].ref_pixmap = x_pixmap_id; \
187 GST_LOG_OBJECT (x_evaspixmapsink,"pixmap(%d) is marked at index(%d) of gem_info(CrBuf)->gem_handle(%d)", x_pixmap_id, i, evaspixmapsink->gem_info[i].gem_handle); \
194 #define EVASPIXMAPSINK_SET_EVAS_OBJECT_EVENT_CALLBACK( x_evas_image_object, x_usr_data ) \
197 evas_object_event_callback_add (x_evas_image_object, EVAS_CALLBACK_DEL, evas_callback_del_event, x_usr_data); \
198 evas_object_event_callback_add (x_evas_image_object, EVAS_CALLBACK_RESIZE, evas_callback_resize_event, x_usr_data); \
199 evas_object_event_callback_add (x_evas_image_object, EVAS_CALLBACK_SHOW, evas_callback_show_event, x_usr_data); \
200 evas_object_event_callback_add (x_evas_image_object, EVAS_CALLBACK_HIDE, evas_callback_hide_event, x_usr_data); \
203 #define EVASPIXMAPSINK_UNSET_EVAS_OBJECT_EVENT_CALLBACK( x_evas_image_object ) \
206 evas_object_event_callback_del (x_evas_image_object, EVAS_CALLBACK_DEL, evas_callback_del_event); \
207 evas_object_event_callback_del (x_evas_image_object, EVAS_CALLBACK_RESIZE, evas_callback_resize_event); \
208 evas_object_event_callback_del (x_evas_image_object, EVAS_CALLBACK_SHOW, evas_callback_show_event); \
209 evas_object_event_callback_del (x_evas_image_object, EVAS_CALLBACK_HIDE, evas_callback_hide_event); \
213 gst_evaspixmapsink_flip_get_type(void)
215 static GType evaspixmapsink_flip_type = 0;
216 static const GEnumValue flip_type[] = {
217 { FLIP_NONE, "Flip NONE", "FLIP_NONE"},
218 { FLIP_HORIZONTAL, "Flip HORIZONTAL", "FLIP_HORIZONTAL"},
219 { FLIP_VERTICAL, "Flip VERTICAL", "FLIP_VERTICAL"},
220 { FLIP_BOTH, "Flip BOTH", "FLIP_BOTH"},
221 { FLIP_NUM, NULL, NULL},
224 if (!evaspixmapsink_flip_type) {
225 evaspixmapsink_flip_type = g_enum_register_static("GstEvasPixmapSinkFlipType", flip_type);
228 return evaspixmapsink_flip_type;
232 gst_evaspixmapsink_rotate_angle_get_type(void)
234 static GType evaspixmapsink_rotate_angle_type = 0;
235 static const GEnumValue rotate_angle_type[] = {
236 { 0, "No rotate", "DEGREE_0"},
237 { 1, "Rotate 90 degree", "DEGREE_90"},
238 { 2, "Rotate 180 degree", "DEGREE_180"},
239 { 3, "Rotate 270 degree", "DEGREE_270"},
243 if (!evaspixmapsink_rotate_angle_type) {
244 evaspixmapsink_rotate_angle_type = g_enum_register_static("GstEvasPixmapSinkRotateAngleType", rotate_angle_type);
247 return evaspixmapsink_rotate_angle_type;
251 gst_evaspixmapsink_display_geometry_method_get_type(void)
253 static GType evaspixmapsink_display_geometry_method_type = 0;
254 static const GEnumValue display_geometry_method_type[] = {
255 { 0, "Letter box", "LETTER_BOX"},
256 { 1, "Origin size", "ORIGIN_SIZE"},
257 { 2, "Full-screen", "FULL_SCREEN"},
258 { 3, "Cropped Full-screen", "CROPPED_FULL_SCREEN"},
259 { 4, "Explicitely described destination ROI", "CUSTOM_ROI"},
263 if (!evaspixmapsink_display_geometry_method_type) {
264 evaspixmapsink_display_geometry_method_type = g_enum_register_static("GstEvasPixmapSinkDisplayGeometryMethodType", display_geometry_method_type);
267 return evaspixmapsink_display_geometry_method_type;
273 unsigned long functions;
274 unsigned long decorations;
276 unsigned long status;
278 MotifWmHints, MwmHints;
280 #define MWM_HINTS_DECORATIONS (1L << 1)
282 static void gst_evaspixmapsink_reset (GstEvasPixmapSink *evaspixmapsink);
283 static GstBufferClass *evaspixmap_buffer_parent_class = NULL;
284 static void gst_evaspixmap_buffer_finalize (GstEvasPixmapBuffer *evaspixmapbuf);
285 static void gst_evaspixmapsink_xcontext_clear (GstEvasPixmapSink *evaspixmapsink);
286 static void gst_evaspixmapsink_xpixmap_destroy (GstEvasPixmapSink *evaspixmapsink, GstXPixmap *xpixmap);
287 static void gst_evaspixmapsink_xpixmap_update_geometry (GstEvasPixmapSink *evaspixmapsink, int idx);
288 static gboolean gst_evaspixmap_buffer_put (GstEvasPixmapSink *evaspixmapsink, GstEvasPixmapBuffer *evaspixmapbuf);
289 static gboolean gst_evaspixmapsink_xpixmap_link (GstEvasPixmapSink *evaspixmapsink);
290 static void gst_evaspixmapsink_xpixmap_clear (GstEvasPixmapSink *evaspixmapsink, GstXPixmap *xpixmap);
291 static gint gst_evaspixmapsink_get_format_from_caps (GstEvasPixmapSink *evaspixmapsink, GstCaps *caps);
292 static void drm_close_gem(GstEvasPixmapSink *evaspixmapsink, unsigned int gem_handle);
293 static void drm_fini_close_gem_handle(GstEvasPixmapSink *evaspixmapsink, Pixmap pixmap_id);
294 static void evas_callback_resize_event (void *data, Evas *e, Evas_Object *obj, void *event_info);
295 static void evas_callback_del_event (void *data, Evas *e, Evas_Object *obj, void *event_info);
296 static void evas_callback_show_event (void *data, Evas *e, Evas_Object *obj, void *event_info);
297 static void evas_callback_hide_event (void *data, Evas *e, Evas_Object *obj, void *event_info);
299 /* Default template - initiated with class struct to allow gst-register to work
301 static GstStaticPadTemplate gst_evaspixmapsink_sink_template_factory =
302 GST_STATIC_PAD_TEMPLATE ("sink",
305 GST_STATIC_CAPS ("video/x-raw-rgb, "
306 "framerate = (fraction) [ 0, MAX ], "
307 "width = (int) [ 1, MAX ], "
308 "height = (int) [ 1, MAX ]; "
310 "framerate = (fraction) [ 0, MAX ], "
311 "width = (int) [ 1, MAX ], " "height = (int) [ 1, MAX ]")
323 PROP_PIXEL_ASPECT_RATIO,
327 PROP_AUTOPAINT_COLORKEY,
333 PROP_DISPLAY_GEOMETRY_METHOD,
345 static GstVideoSinkClass *parent_class = NULL;
347 /* ============================================================= */
349 /* Private Methods */
351 /* ============================================================= */
353 /* evaspixmap buffers */
355 #define GST_TYPE_EVASPIXMAP_BUFFER (gst_evaspixmap_buffer_get_type())
357 #define GST_IS_EVASPIXMAP_BUFFER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_EVASPIXMAP_BUFFER))
358 #define GST_EVASPIXMAP_BUFFER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_EVASPIXMAP_BUFFER, GstEvasPixmapBuffer))
360 static int get_millis_time()
363 clock_gettime(CLOCK_MONOTONIC, &tp);
364 return (tp.tv_sec * 1000) + (tp.tv_nsec / 1000000L);
368 ecore_pipe_callback_handler (void *data, void *buffer, unsigned int nbyte)
370 GstEvasPixmapSink *evaspixmapsink = (GstEvasPixmapSink*)data;
371 GST_DEBUG_OBJECT (evaspixmapsink,"[START] Evas_Object(0x%x)", evaspixmapsink->eo);
372 MMTA_ACUM_ITEM_BEGIN("evaspixmapsink - ecore thread cb : TOTAL", FALSE);
375 GstXPixmap *xpixmap = NULL;
378 GST_WARNING_OBJECT (evaspixmapsink,"data is NULL..");
381 if (!evaspixmapsink->eo) {
382 GST_WARNING_OBJECT (evaspixmapsink,"evas object is NULL..");
385 if (!evaspixmapsink->visible) {
386 GST_WARNING_OBJECT (evaspixmapsink,"visible is false..");
390 /* mapping evas object with xpixmap */
391 if (evaspixmapsink->do_link) {
392 GST_DEBUG_OBJECT (evaspixmapsink,"do link");
393 evas_object_image_size_set(evaspixmapsink->eo, evaspixmapsink->w, evaspixmapsink->h);
394 if (evaspixmapsink->xpixmap[idx]->pixmap) {
395 Evas_Native_Surface surf;
396 surf.version = EVAS_NATIVE_SURFACE_VERSION;
397 surf.type = EVAS_NATIVE_SURFACE_X11;
398 surf.data.x11.visual = ecore_x_default_visual_get(ecore_x_display_get(), ecore_x_default_screen_get());
399 surf.data.x11.pixmap = evaspixmapsink->xpixmap[idx]->pixmap;
400 __ta__("evaspixmapsink - ecore thread cb : _native_surface_set(LINK)", evas_object_image_native_surface_set(evaspixmapsink->eo, &surf); );
401 evaspixmapsink->do_link = FALSE;
403 GST_WARNING_OBJECT (evaspixmapsink,"pixmap is NULL..");
406 for (i = 0; i < evaspixmapsink->num_of_pixmaps; i++) {
407 if (evaspixmapsink->xpixmap[i]->prev_pixmap && evaspixmapsink->xpixmap[i]->prev_gc && evaspixmapsink->prev_damage[i]) {
408 GST_LOG_OBJECT (evaspixmapsink,"Free pixmap(%d), gc(%x), destroy previous damage(%d)",
409 evaspixmapsink->xpixmap[i]->prev_pixmap, evaspixmapsink->xpixmap[i]->prev_gc, evaspixmapsink->prev_damage[i]);
410 g_mutex_lock (evaspixmapsink->x_lock);
411 XFreePixmap(evaspixmapsink->xcontext->disp, evaspixmapsink->xpixmap[i]->prev_pixmap);
412 XFreeGC (evaspixmapsink->xcontext->disp, evaspixmapsink->xpixmap[i]->prev_gc);
413 XDamageDestroy(evaspixmapsink->xcontext->disp, evaspixmapsink->prev_damage[i]);
414 XSync(evaspixmapsink->xcontext->disp, FALSE);
415 g_mutex_unlock (evaspixmapsink->x_lock);
416 evaspixmapsink->xpixmap[i]->prev_pixmap = 0;
417 evaspixmapsink->xpixmap[i]->prev_gc = 0;
418 evaspixmapsink->prev_damage[i] = NULL;
423 GST_DEBUG_OBJECT (evaspixmapsink,"update");
424 /* update evas image object size */
425 if (evaspixmapsink->use_origin_size) {
426 evas_object_geometry_get(evaspixmapsink->eo, NULL, NULL, &evaspixmapsink->w, &evaspixmapsink->h);
429 g_mutex_lock (evaspixmapsink->pixmap_ref_lock);
431 /* find a oldest damaged pixmap */
433 for (i = 0; i < evaspixmapsink->num_of_pixmaps; i++) {
434 if (evaspixmapsink->last_updated_idx == i) {
437 xpixmap = evaspixmapsink->xpixmap[i];
438 if (xpixmap->ref > 0 && xpixmap->damaged_time) {
439 if (temp_time == 0) {
440 temp_time = xpixmap->damaged_time;
443 if (temp_time > xpixmap->damaged_time) {
444 temp_time = xpixmap->damaged_time;
452 xpixmap = evaspixmapsink->xpixmap[idx];
453 if (xpixmap->pixmap) {
454 if (evaspixmapsink->last_updated_idx != idx) {
455 Evas_Native_Surface surf;
456 surf.version = EVAS_NATIVE_SURFACE_VERSION;
457 surf.type = EVAS_NATIVE_SURFACE_X11;
458 surf.data.x11.visual = ecore_x_default_visual_get(ecore_x_display_get(), ecore_x_default_screen_get());
459 surf.data.x11.pixmap = xpixmap->pixmap;
460 if (evaspixmapsink->eo) {
461 evas_object_image_native_surface_set(evaspixmapsink->eo, NULL);
463 __ta__("evaspixmapsink - ecore thread cb : _native_surface_set", evas_object_image_native_surface_set(evaspixmapsink->eo, &surf); );
464 GST_LOG_OBJECT (evaspixmapsink,"update, native_surface_set of xpixmap[%d]",idx);
465 if (evaspixmapsink->last_updated_idx == -1) {
466 xpixmap->damaged_time = 0;
467 GST_INFO_OBJECT (evaspixmapsink,"this is the first time to request to update(do not DECREASE ref-count) : pixmap(%d), refcount(%d), damaged_time(%d), idx(%d)",
468 xpixmap->pixmap, xpixmap->ref, xpixmap->damaged_time, idx);
470 xpixmap = evaspixmapsink->xpixmap[evaspixmapsink->last_updated_idx];
472 xpixmap->damaged_time = 0;
473 GST_INFO_OBJECT (evaspixmapsink,"pixmap ref-count DECREASED : pixmap(%d), refcount(%d), damaged_time(%d), idx(%d)",
474 xpixmap->pixmap, xpixmap->ref, xpixmap->damaged_time, evaspixmapsink->last_updated_idx);
476 evaspixmapsink->last_updated_idx = idx;
479 MMTA_ACUM_ITEM_BEGIN("evaspixmapsink evas_object_image update", FALSE);
480 evas_object_image_pixels_dirty_set (evaspixmapsink->eo, 1);
481 evas_object_image_fill_set(evaspixmapsink->eo, 0, 0, evaspixmapsink->w, evaspixmapsink->h);
482 evas_object_image_data_update_add(evaspixmapsink->eo, 0, 0, evaspixmapsink->w, evaspixmapsink->h);
483 MMTA_ACUM_ITEM_END("evaspixmapsink evas_object_image update", FALSE);
484 //GST_LOG_OBJECT (evaspixmapsink,"request to update : pixmap idx(%d), ref(%d)", idx, xpixmap->ref);
486 GST_ERROR_OBJECT (evaspixmapsink,"pixmap is NULL..");
488 g_mutex_unlock (evaspixmapsink->pixmap_ref_lock);
491 MMTA_ACUM_ITEM_END("evaspixmapsink - ecore thread cb : TOTAL", FALSE);
493 GST_DEBUG_OBJECT (evaspixmapsink,"[END]");
496 static inline gboolean
497 is_evas_image_object (Evas_Object *obj)
501 GST_ERROR ("evas image object is NULL..");
504 type = evas_object_type_get (obj);
506 GST_ERROR ("could not find type of the evas object..");
509 if (strcmp (type, "image") == 0) {
516 evas_callback_resize_event (void *data, Evas *e, Evas_Object *obj, void *event_info)
520 float former_ratio = 0;
522 float abs_margin = 0;
525 GstEvasPixmapSink *evaspixmapsink = (GstEvasPixmapSink *)data;
526 GST_DEBUG_OBJECT (evaspixmapsink,"[START] evas_image_object(%x), tid(%u)", obj, (unsigned int)pthread_self());
528 evas_object_geometry_get(evaspixmapsink->eo, NULL, NULL, &w, &h);
529 GST_DEBUG_OBJECT (evaspixmapsink,"resized : w(%d), h(%d)", w, h);
530 if (!evaspixmapsink->use_origin_size &&
531 (evaspixmapsink->w != w || evaspixmapsink->h != h)) {
532 former_ratio = (float)evaspixmapsink->w / evaspixmapsink->h;
533 ratio = (float)w / h;
534 evaspixmapsink->w = w;
535 evaspixmapsink->h = h;
538 GST_DEBUG_OBJECT (evaspixmapsink,"resized : ratio(%.3f=>%.3f)", former_ratio, ratio);
539 if ( former_ratio >= ratio ) {
540 abs_margin = former_ratio - ratio;
542 abs_margin = ratio - former_ratio;
544 /* re-link_pixmap can only be set when ratio is changed */
545 if ( abs_margin >= MARGIN_OF_ERROR ) {
547 if (!gst_evaspixmapsink_xpixmap_link(evaspixmapsink)) {
548 GST_ERROR_OBJECT (evaspixmapsink,"link evas image object with pixmap failed...");
551 for (i = 0; i < MAX_GEM_BUFFER_NUM; i++) {
552 if (evaspixmapsink->gem_info[i].ref_pixmap > 0) {
553 GST_LOG_OBJECT (evaspixmapsink,"set ref_pixmap(%d) to 0 in gem_info[%d]", evaspixmapsink->gem_info[i].ref_pixmap, i);
554 evaspixmapsink->gem_info[i].ref_pixmap = 0;
562 if (GST_STATE(evaspixmapsink) == GST_STATE_PAUSED) {
563 gst_evaspixmap_buffer_put (evaspixmapsink, evaspixmapsink->evas_pixmap_buf);
566 GST_DEBUG_OBJECT (evaspixmapsink,"[END]");
570 evas_callback_del_event (void *data, Evas *e, Evas_Object *obj, void *event_info)
572 GstEvasPixmapSink *evaspixmapsink = data;
573 if (!evaspixmapsink) {
574 GST_WARNING ("evaspixmapsink is NULL..");
577 GST_DEBUG_OBJECT (evaspixmapsink,"[START]");
579 EVASPIXMAPSINK_UNSET_EVAS_OBJECT_EVENT_CALLBACK( evaspixmapsink->eo );
580 if (evaspixmapsink->eo) {
581 evas_object_image_native_surface_set(evaspixmapsink->eo, NULL);
582 evaspixmapsink->eo = NULL;
585 GST_DEBUG_OBJECT (evaspixmapsink,"[END]");
589 evas_callback_show_event (void *data, Evas *e, Evas_Object *obj, void *event_info)
591 GstEvasPixmapSink *evaspixmapsink = (GstEvasPixmapSink *)data;
592 GST_INFO_OBJECT (evaspixmapsink,"show evas_image_object(%x) from pid(%d), tid(%u)", obj, getpid(), (unsigned int)pthread_self());
596 evas_callback_hide_event (void *data, Evas *e, Evas_Object *obj, void *event_info)
598 GstEvasPixmapSink *evaspixmapsink = (GstEvasPixmapSink *)data;
599 GST_INFO_OBJECT (evaspixmapsink,"hide evas_image_object(%x) from pid(%d), tid(%u)", obj, getpid(), (unsigned int)pthread_self());
603 static gboolean error_caught = FALSE;
606 gst_evaspixmapsink_handle_xerror (Display * display, XErrorEvent * xevent)
608 char error_msg[1024];
610 XGetErrorText (display, xevent->error_code, error_msg, 1024);
611 GST_DEBUG ("evaspixmapsink triggered an XError. error: %s", error_msg);
617 /* This function checks that it is actually really possible to create an image
620 gst_evaspixmapsink_check_xshm_calls (GstXContext * xcontext)
623 XShmSegmentInfo SHMInfo;
625 int (*handler) (Display *, XErrorEvent *);
626 gboolean result = FALSE;
627 gboolean did_attach = FALSE;
629 g_return_val_if_fail (xcontext != NULL, FALSE);
631 /* Sync to ensure any older errors are already processed */
632 XSync (xcontext->disp, FALSE);
634 /* Set defaults so we don't free these later unnecessarily */
635 SHMInfo.shmaddr = ((void *) -1);
638 /* Setting an error handler to catch failure */
639 error_caught = FALSE;
640 handler = XSetErrorHandler (gst_evaspixmapsink_handle_xerror);
642 /* Trying to create a 1x1 picture */
643 GST_DEBUG ("XvShmCreateImage of 1x1");
644 xvimage = XvShmCreateImage (xcontext->disp, xcontext->xv_port_id,
645 xcontext->im_format, NULL, 1, 1, &SHMInfo);
647 /* Might cause an error, sync to ensure it is noticed */
648 XSync (xcontext->disp, FALSE);
649 if (!xvimage || error_caught) {
650 GST_WARNING ("could not XvShmCreateImage a 1x1 image");
653 size = xvimage->data_size;
655 SHMInfo.shmid = shmget (IPC_PRIVATE, size, IPC_CREAT | 0777);
656 if (SHMInfo.shmid == -1) {
657 GST_WARNING ("could not get shared memory of %d bytes", size);
661 SHMInfo.shmaddr = shmat (SHMInfo.shmid, NULL, 0);
662 if (SHMInfo.shmaddr == ((void *) -1)) {
663 GST_WARNING ("Failed to shmat: %s", g_strerror (errno));
664 /* Clean up the shared memory segment */
665 shmctl (SHMInfo.shmid, IPC_RMID, NULL);
669 xvimage->data = SHMInfo.shmaddr;
670 SHMInfo.readOnly = FALSE;
672 if (XShmAttach (xcontext->disp, &SHMInfo) == 0) {
673 GST_WARNING ("Failed to XShmAttach");
674 /* Clean up the shared memory segment */
675 shmctl (SHMInfo.shmid, IPC_RMID, NULL);
679 /* Sync to ensure we see any errors we caused */
680 XSync (xcontext->disp, FALSE);
682 /* Delete the shared memory segment as soon as everyone is attached.
683 * This way, it will be deleted as soon as we detach later, and not
684 * leaked if we crash. */
685 shmctl (SHMInfo.shmid, IPC_RMID, NULL);
688 GST_DEBUG ("XServer ShmAttached to 0x%x, id 0x%lx", SHMInfo.shmid,
692 /* store whether we succeeded in result */
695 GST_WARNING ("MIT-SHM extension check failed at XShmAttach. "
696 "Not using shared memory.");
700 /* Sync to ensure we swallow any errors we caused and reset error_caught */
701 XSync (xcontext->disp, FALSE);
703 error_caught = FALSE;
704 XSetErrorHandler (handler);
707 GST_DEBUG ("XServer ShmDetaching from 0x%x id 0x%lx",
708 SHMInfo.shmid, SHMInfo.shmseg);
709 XShmDetach (xcontext->disp, &SHMInfo);
710 XSync (xcontext->disp, FALSE);
712 if (SHMInfo.shmaddr != ((void *) -1))
713 shmdt (SHMInfo.shmaddr);
718 #endif /* HAVE_XSHM */
720 /* This function destroys a GstEvasPixmap handling XShm availability */
722 gst_evaspixmap_buffer_destroy (GstEvasPixmapBuffer *evaspixmapbuf)
724 GstEvasPixmapSink *evaspixmapsink;
726 evaspixmapsink = evaspixmapbuf->evaspixmapsink;
727 if (G_UNLIKELY (evaspixmapsink == NULL)) {
730 GST_DEBUG_OBJECT (evaspixmapsink, "Destroying buffer");
732 g_return_if_fail (GST_IS_EVASPIXMAPSINK (evaspixmapsink));
734 GST_OBJECT_LOCK (evaspixmapsink);
736 /* We might have some buffers destroyed after changing state to NULL */
737 if (evaspixmapsink->xcontext == NULL) {
738 GST_DEBUG_OBJECT (evaspixmapsink,"Destroying XvImage after Xcontext");
740 /* Need to free the shared memory segment even if the x context
741 * was already cleaned up */
742 if (evaspixmapbuf->SHMInfo.shmaddr != ((void *) -1)) {
743 shmdt (evaspixmapbuf->SHMInfo.shmaddr);
748 g_mutex_lock (evaspixmapsink->x_lock);
751 if (evaspixmapsink->xcontext->use_xshm) {
752 if (evaspixmapbuf->SHMInfo.shmaddr != ((void *) -1)) {
753 GST_DEBUG_OBJECT (evaspixmapsink,"XServer ShmDetaching from 0x%x id 0x%lx", evaspixmapbuf->SHMInfo.shmid, evaspixmapbuf->SHMInfo.shmseg);
754 XShmDetach (evaspixmapsink->xcontext->disp, &evaspixmapbuf->SHMInfo);
755 XSync (evaspixmapsink->xcontext->disp, FALSE);
756 shmdt (evaspixmapbuf->SHMInfo.shmaddr);
758 if (evaspixmapbuf->xvimage)
759 XFree (evaspixmapbuf->xvimage);
761 #endif /* HAVE_XSHM */
763 if (evaspixmapbuf->xvimage) {
764 if (evaspixmapbuf->xvimage->data) {
765 g_free (evaspixmapbuf->xvimage->data);
767 XFree (evaspixmapbuf->xvimage);
771 XSync (evaspixmapsink->xcontext->disp, FALSE);
773 g_mutex_unlock (evaspixmapsink->x_lock);
776 GST_OBJECT_UNLOCK (evaspixmapsink);
777 evaspixmapbuf->evaspixmapsink = NULL;
778 gst_object_unref (evaspixmapsink);
780 GST_MINI_OBJECT_CLASS (evaspixmap_buffer_parent_class)->finalize (GST_MINI_OBJECT(evaspixmapbuf));
786 GST_WARNING ("no sink found");
792 gst_evaspixmap_buffer_finalize (GstEvasPixmapBuffer *evaspixmapbuf)
794 GstEvasPixmapSink *evaspixmapsink;
796 evaspixmapsink = evaspixmapbuf->evaspixmapsink;
797 if (G_UNLIKELY (evaspixmapsink == NULL)) {
798 GST_WARNING_OBJECT (evaspixmapsink,"no sink found");
801 g_return_if_fail (GST_IS_EVASPIXMAPSINK (evaspixmapsink));
803 /* If our geometry changed we can't reuse that image. */
804 GST_LOG_OBJECT (evaspixmapsink,"destroy image as sink is shutting down");
805 gst_evaspixmap_buffer_destroy (evaspixmapbuf);
809 gst_evaspixmap_buffer_free (GstEvasPixmapBuffer *evaspixmapbuf)
811 /* make sure it is not recycled */
812 evaspixmapbuf->width = -1;
813 evaspixmapbuf->height = -1;
814 gst_buffer_unref (GST_BUFFER (evaspixmapbuf));
818 gst_evaspixmap_buffer_init (GstEvasPixmapBuffer *evaspixmapbuf, gpointer g_class)
821 evaspixmapbuf->SHMInfo.shmaddr = ((void *) -1);
822 evaspixmapbuf->SHMInfo.shmid = -1;
827 gst_evaspixmap_buffer_class_init (gpointer g_class, gpointer class_data)
829 GstMiniObjectClass *mini_object_class = GST_MINI_OBJECT_CLASS (g_class);
831 evaspixmap_buffer_parent_class = g_type_class_peek_parent (g_class);
833 mini_object_class->finalize = (GstMiniObjectFinalizeFunction) gst_evaspixmap_buffer_finalize;
837 gst_evaspixmap_buffer_get_type (void)
839 static GType _gst_evaspixmap_buffer_type;
841 if (G_UNLIKELY (_gst_evaspixmap_buffer_type == 0)) {
842 static const GTypeInfo evaspixmap_buffer_info = {
843 sizeof (GstBufferClass),
846 gst_evaspixmap_buffer_class_init,
849 sizeof (GstEvasPixmapBuffer),
851 (GInstanceInitFunc) gst_evaspixmap_buffer_init,
854 _gst_evaspixmap_buffer_type = g_type_register_static (GST_TYPE_BUFFER,
855 "GstEvasPixmapBuffer", &evaspixmap_buffer_info, 0);
857 return _gst_evaspixmap_buffer_type;
860 /* This function handles GstEvasPixmapBuffer creation depending on XShm availability */
861 static GstEvasPixmapBuffer*
862 gst_evaspixmap_buffer_new (GstEvasPixmapSink *evaspixmapsink, GstCaps *caps)
864 GstEvasPixmapBuffer *evaspixmapbuf = NULL;
865 GstStructure *structure = NULL;
866 gboolean succeeded = FALSE;
867 int (*handler) (Display *, XErrorEvent *);
869 g_return_val_if_fail (GST_IS_EVASPIXMAPSINK (evaspixmapsink), NULL);
875 evaspixmapbuf = (GstEvasPixmapBuffer*) gst_mini_object_new (GST_TYPE_EVASPIXMAP_BUFFER);
876 GST_DEBUG_OBJECT (evaspixmapsink,"Creating new EvasPixmapBuffer");
878 structure = gst_caps_get_structure (caps, 0);
880 if (!gst_structure_get_int (structure, "width", &evaspixmapbuf->width) || !gst_structure_get_int (structure, "height", &evaspixmapbuf->height)) {
881 GST_WARNING_OBJECT (evaspixmapsink,"failed getting geometry from caps %" GST_PTR_FORMAT, caps);
884 GST_LOG_OBJECT (evaspixmapsink,"creating %dx%d", evaspixmapbuf->width, evaspixmapbuf->height);
886 GST_LOG_OBJECT (evaspixmapsink,"aligned size %dx%d", evaspixmapsink->aligned_width, evaspixmapsink->aligned_height);
887 if (evaspixmapsink->aligned_width == 0 || evaspixmapsink->aligned_height == 0) {
888 GST_INFO_OBJECT (evaspixmapsink,"aligned size is zero. set size of caps.");
889 evaspixmapsink->aligned_width = evaspixmapbuf->width;
890 evaspixmapsink->aligned_height = evaspixmapbuf->height;
893 evaspixmapbuf->im_format = gst_evaspixmapsink_get_format_from_caps (evaspixmapsink, caps);
894 if (evaspixmapbuf->im_format == -1) {
895 GST_WARNING_OBJECT (evaspixmapsink,"failed to get format from caps %"GST_PTR_FORMAT, caps);
896 GST_ELEMENT_ERROR (evaspixmapsink, RESOURCE, WRITE,("Failed to create output image buffer of %dx%d pixels",
897 evaspixmapbuf->width, evaspixmapbuf->height), ("Invalid input caps"));
901 GST_INFO_OBJECT (evaspixmapsink, "FOURCC format : %c%c%c%c", evaspixmapbuf->im_format, evaspixmapbuf->im_format>>8,
902 evaspixmapbuf->im_format>>16, evaspixmapbuf->im_format>>24);
904 evaspixmapbuf->evaspixmapsink = gst_object_ref (evaspixmapsink);
906 g_mutex_lock (evaspixmapsink->x_lock);
908 /* Sync to ensure we swallow any errors we caused and reset error_caught */
909 XSync (evaspixmapsink->xcontext->disp, FALSE);
911 /* Setting an error handler to catch failure */
912 error_caught = FALSE;
913 handler = XSetErrorHandler (gst_evaspixmapsink_handle_xerror);
916 if (evaspixmapsink->xcontext->use_xshm) {
918 evaspixmapbuf->xvimage = XvShmCreateImage (evaspixmapsink->xcontext->disp, evaspixmapsink->xcontext->xv_port_id, evaspixmapbuf->im_format, NULL,
919 evaspixmapsink->aligned_width, evaspixmapsink->aligned_height, &evaspixmapbuf->SHMInfo);
920 if (!evaspixmapbuf->xvimage || error_caught) {
922 GST_ERROR_OBJECT (evaspixmapsink,"error_caught!");
924 if(!evaspixmapbuf->xvimage) {
925 GST_ERROR_OBJECT (evaspixmapsink,"XvShmCreateImage() failed");
927 g_mutex_unlock (evaspixmapsink->x_lock);
928 /* Reset error handler */
929 error_caught = FALSE;
930 XSetErrorHandler (handler);
932 GST_ELEMENT_ERROR (evaspixmapsink, RESOURCE, WRITE,("Failed to create output image buffer of %dx%d pixels",evaspixmapbuf->width,
933 evaspixmapbuf->height),("could not XvShmCreateImage a %dx%d image",evaspixmapbuf->width, evaspixmapbuf->height));
937 /* we have to use the returned data_size for our shm size */
938 evaspixmapbuf->size = evaspixmapbuf->xvimage->data_size;
939 GST_LOG_OBJECT (evaspixmapsink,"XShm image size is %" G_GSIZE_FORMAT, evaspixmapbuf->size);
941 /* calculate the expected size. This is only for sanity checking the
942 * number we get from X. */
943 switch (evaspixmapbuf->im_format) {
944 case GST_MAKE_FOURCC ('I', '4', '2', '0'):
945 case GST_MAKE_FOURCC ('Y', 'V', '1', '2'):
952 pitches[0] = GST_ROUND_UP_4 (evaspixmapbuf->width);
953 offsets[1] = offsets[0] + pitches[0] * GST_ROUND_UP_2 (evaspixmapbuf->height);
954 pitches[1] = GST_ROUND_UP_8 (evaspixmapbuf->width) / 2;
956 offsets[1] + pitches[1] * GST_ROUND_UP_2 (evaspixmapbuf->height) / 2;
957 pitches[2] = GST_ROUND_UP_8 (pitches[0]) / 2;
959 expected_size = offsets[2] + pitches[2] * GST_ROUND_UP_2 (evaspixmapbuf->height) / 2;
961 for (plane = 0; plane < evaspixmapbuf->xvimage->num_planes; plane++) {
962 GST_DEBUG_OBJECT (evaspixmapsink,"Plane %u has a expected pitch of %d bytes, " "offset of %d",
963 plane, pitches[plane], offsets[plane]);
967 case GST_MAKE_FOURCC ('Y', 'U', 'Y', '2'):
968 case GST_MAKE_FOURCC ('U', 'Y', 'V', 'Y'):
969 expected_size = evaspixmapbuf->height * GST_ROUND_UP_4 (evaspixmapbuf->width * 2);
971 case GST_MAKE_FOURCC ('S', 'T', '1', '2'):
972 case GST_MAKE_FOURCC ('S', 'N', '1', '2'):
973 case GST_MAKE_FOURCC ('S', 'U', 'Y', 'V'):
974 case GST_MAKE_FOURCC ('S', 'U', 'Y', '2'):
975 case GST_MAKE_FOURCC ('S', '4', '2', '0'):
976 case GST_MAKE_FOURCC ('S', 'Y', 'V', 'Y'):
977 case GST_MAKE_FOURCC ('I', 'T', 'L', 'V'):
978 case GST_MAKE_FOURCC ('S', 'R', '3', '2'):
979 expected_size = sizeof(SCMN_IMGB);
985 if (expected_size != 0 && evaspixmapbuf->size != expected_size) {
986 GST_WARNING_OBJECT (evaspixmapsink,"unexpected XShm image size (got %" G_GSIZE_FORMAT ", expected %d)", evaspixmapbuf->size, expected_size);
989 /* Be verbose about our XvImage stride */
992 for (plane = 0; plane < evaspixmapbuf->xvimage->num_planes; plane++) {
993 GST_DEBUG_OBJECT (evaspixmapsink,"Plane %u has a pitch of %d bytes, ""offset of %d", plane,
994 evaspixmapbuf->xvimage->pitches[plane], evaspixmapbuf->xvimage->offsets[plane]);
998 evaspixmapbuf->SHMInfo.shmid = shmget (IPC_PRIVATE, evaspixmapbuf->size,IPC_CREAT | 0777);
999 if (evaspixmapbuf->SHMInfo.shmid == -1) {
1000 g_mutex_unlock (evaspixmapsink->x_lock);
1001 GST_ELEMENT_ERROR (evaspixmapsink, RESOURCE, WRITE,
1002 ("Failed to create output image buffer of %dx%d pixels", evaspixmapbuf->width, evaspixmapbuf->height),
1003 ("could not get shared memory of %" G_GSIZE_FORMAT " bytes",evaspixmapbuf->size));
1004 goto beach_unlocked;
1007 evaspixmapbuf->SHMInfo.shmaddr = shmat (evaspixmapbuf->SHMInfo.shmid, NULL, 0);
1008 if (evaspixmapbuf->SHMInfo.shmaddr == ((void *) -1)) {
1009 g_mutex_unlock (evaspixmapsink->x_lock);
1010 GST_ELEMENT_ERROR (evaspixmapsink, RESOURCE, WRITE,
1011 ("Failed to create output image buffer of %dx%d pixels",
1012 evaspixmapbuf->width, evaspixmapbuf->height),
1013 ("Failed to shmat: %s", g_strerror (errno)));
1014 /* Clean up the shared memory segment */
1015 shmctl (evaspixmapbuf->SHMInfo.shmid, IPC_RMID, NULL);
1016 goto beach_unlocked;
1019 evaspixmapbuf->xvimage->data = evaspixmapbuf->SHMInfo.shmaddr;
1020 evaspixmapbuf->SHMInfo.readOnly = FALSE;
1022 if (XShmAttach (evaspixmapsink->xcontext->disp, &evaspixmapbuf->SHMInfo) == 0) {
1023 /* Clean up the shared memory segment */
1024 shmctl (evaspixmapbuf->SHMInfo.shmid, IPC_RMID, NULL);
1026 g_mutex_unlock (evaspixmapsink->x_lock);
1027 GST_ELEMENT_ERROR (evaspixmapsink, RESOURCE, WRITE,
1028 ("Failed to create output image buffer of %dx%d pixels",
1029 evaspixmapbuf->width, evaspixmapbuf->height), ("Failed to XShmAttach"));
1030 goto beach_unlocked;
1033 XSync (evaspixmapsink->xcontext->disp, FALSE);
1035 /* Delete the shared memory segment as soon as we everyone is attached.
1036 * This way, it will be deleted as soon as we detach later, and not
1037 * leaked if we crash. */
1038 shmctl (evaspixmapbuf->SHMInfo.shmid, IPC_RMID, NULL);
1040 GST_DEBUG_OBJECT (evaspixmapsink,"XServer ShmAttached to 0x%x, id 0x%lx", evaspixmapbuf->SHMInfo.shmid, evaspixmapbuf->SHMInfo.shmseg);
1042 #endif /* HAVE_XSHM */
1044 evaspixmapbuf->xvimage = XvCreateImage (evaspixmapsink->xcontext->disp, evaspixmapsink->xcontext->xv_port_id,
1045 evaspixmapbuf->im_format, NULL, evaspixmapsink->aligned_width, evaspixmapsink->aligned_height);
1046 if (!evaspixmapbuf->xvimage || error_caught) {
1047 g_mutex_unlock (evaspixmapsink->x_lock);
1048 /* Reset error handler */
1049 error_caught = FALSE;
1050 XSetErrorHandler (handler);
1052 GST_ELEMENT_ERROR (evaspixmapsink, RESOURCE, WRITE,
1053 ("Failed to create outputimage buffer of %dx%d pixels",
1054 evaspixmapbuf->width, evaspixmapbuf->height),
1055 ("could not XvCreateImage a %dx%d image",
1056 evaspixmapbuf->width, evaspixmapbuf->height));
1057 goto beach_unlocked;
1060 /* we have to use the returned data_size for our image size */
1061 evaspixmapbuf->size = evaspixmapbuf->xvimage->data_size;
1062 evaspixmapbuf->xvimage->data = g_malloc (evaspixmapbuf->size);
1064 XSync (evaspixmapsink->xcontext->disp, FALSE);
1067 /* Reset error handler */
1068 error_caught = FALSE;
1069 XSetErrorHandler (handler);
1073 GST_BUFFER_DATA (evaspixmapbuf) = (guchar *) evaspixmapbuf->xvimage->data;
1074 GST_BUFFER_SIZE (evaspixmapbuf) = evaspixmapbuf->size;
1076 g_mutex_unlock (evaspixmapsink->x_lock);
1080 gst_evaspixmap_buffer_free (evaspixmapbuf);
1081 evaspixmapbuf = NULL;
1084 return evaspixmapbuf;
1087 /* This function puts a GstEvasPixmapBuffer on a GstEvasPixmapSink's pixmap. Returns FALSE
1088 * if no pixmap was available */
1090 gst_evaspixmap_buffer_put (GstEvasPixmapSink *evaspixmapsink, GstEvasPixmapBuffer *evaspixmapbuf)
1092 GstVideoRectangle result;
1094 GstVideoRectangle src_origin = { 0, 0, 0, 0};
1095 GstVideoRectangle src_input = { 0, 0, 0, 0};
1096 GstVideoRectangle src = { 0, 0, 0, 0};
1097 GstVideoRectangle dst = { 0, 0, 0, 0};
1101 GstXPixmap *xpixmap = NULL;
1103 MMTA_ACUM_ITEM_BEGIN("evaspixmapsink evaspixmap_buffer_put()", FALSE);
1105 /* We take the flow_lock. If expose is in there we don't want to run
1106 concurrently from the data flow thread */
1107 g_mutex_lock (evaspixmapsink->flow_lock);
1109 if (G_UNLIKELY (evaspixmapsink->xpixmap[idx] == NULL)) {
1110 GST_WARNING_OBJECT (evaspixmapsink, "xpixmap is NULL. Skip buffer_put." );
1111 g_mutex_unlock(evaspixmapsink->flow_lock);
1114 if (evaspixmapsink->visible == FALSE) {
1115 GST_WARNING_OBJECT (evaspixmapsink, "visible is FALSE. Skip buffer_put." );
1116 g_mutex_unlock(evaspixmapsink->flow_lock);
1119 if (!evaspixmapbuf) {
1120 GST_WARNING_OBJECT (evaspixmapsink, "evaspixmapbuf is NULL. Skip buffer_put." );
1121 g_mutex_unlock(evaspixmapsink->flow_lock);
1125 g_mutex_lock (evaspixmapsink->pixmap_ref_lock);
1126 if (evaspixmapsink->last_updated_idx == -1) {
1127 /* if it has never been updated any frame in Ecore thread, do below */
1129 xpixmap = evaspixmapsink->xpixmap[idx];
1131 GST_LOG_OBJECT (evaspixmapsink, "last_updated_idx(%d), we use index[%d] of pixmap buffers : pixmap(%d), ref(%d)",
1132 evaspixmapsink->last_updated_idx, idx, xpixmap->pixmap, xpixmap->ref);
1134 for (idx = 0; idx < evaspixmapsink->num_of_pixmaps; idx++) {
1135 if (idx == evaspixmapsink->last_updated_idx) {
1138 xpixmap = evaspixmapsink->xpixmap[idx];
1139 if (xpixmap->ref == 0 && xpixmap->damaged_time == 0) {
1141 GST_LOG_OBJECT (evaspixmapsink, "found an available pixmap(%d) : xpixmap[%d]", xpixmap->pixmap, idx);
1142 GST_INFO_OBJECT (evaspixmapsink,"pixmap ref-count INCREASED : pixmap(%d), refcount(%d)", xpixmap->pixmap, xpixmap->ref);
1147 if (idx == evaspixmapsink->num_of_pixmaps) {
1148 GST_LOG_OBJECT (evaspixmapsink, "Could not find a pixmap with idle state, skip buffer_put." );
1149 g_mutex_unlock (evaspixmapsink->pixmap_ref_lock);
1150 g_mutex_unlock(evaspixmapsink->flow_lock);
1154 g_mutex_unlock (evaspixmapsink->pixmap_ref_lock);
1156 gst_evaspixmapsink_xpixmap_update_geometry(evaspixmapsink, idx);
1159 src_origin.x = src_origin.y = src_input.x = src_input.y = 0;
1160 src_input.w = src_origin.w = evaspixmapsink->video_width;
1161 src_input.h = src_origin.h = evaspixmapsink->video_height;
1162 if (evaspixmapsink->use_origin_size ||
1163 (evaspixmapsink->rotate_angle == DEGREE_0 ||
1164 evaspixmapsink->rotate_angle == DEGREE_180)) {
1165 src.w = src_origin.w;
1166 src.h = src_origin.h;
1168 src.w = src_origin.h;
1169 src.h = src_origin.w;
1172 dst.w = evaspixmapsink->render_rect.w; /* pixmap width */
1173 dst.h = evaspixmapsink->render_rect.h; /* pixmap height */
1175 if (!evaspixmapsink->use_origin_size) {
1176 static Atom atom_rotation = None;
1177 static Atom atom_hflip = None;
1178 static Atom atom_vflip = None;
1179 gboolean set_hflip = FALSE;
1180 gboolean set_vflip = FALSE;
1182 /* compensation of size information (between evas image object's and pixmap's) */
1183 if (evaspixmapsink->sizediff_width > 1) {
1184 if (evaspixmapsink->sizediff_height > 1) {
1185 dst.w -= (evaspixmapsink->sizediff_width >> 1) << 1;
1186 dst.h -= (evaspixmapsink->sizediff_height >> 1) << 1;
1188 dst.w -= (evaspixmapsink->sizediff_width >> 1) << 1;
1190 } else if (evaspixmapsink->sizediff_height > 1) {
1191 dst.h -= (evaspixmapsink->sizediff_height >> 1) << 1;
1194 switch (evaspixmapsink->display_geometry_method) {
1195 case DISP_GEO_METHOD_LETTER_BOX:
1196 gst_video_sink_center_rect (src, dst, &result, TRUE);
1197 result.x += evaspixmapsink->render_rect.x;
1198 result.y += evaspixmapsink->render_rect.y;
1199 GST_DEBUG_OBJECT (evaspixmapsink, "GEO_METHOD : letter box");
1201 case DISP_GEO_METHOD_ORIGIN_SIZE:
1202 gst_video_sink_center_rect (src, dst, &result, FALSE);
1203 gst_video_sink_center_rect (dst, src, &src_input, FALSE);
1204 GST_DEBUG_OBJECT (evaspixmapsink, "GEO_METHOD : origin size");
1205 if (evaspixmapsink->rotate_angle == DEGREE_90 ||
1206 evaspixmapsink->rotate_angle == DEGREE_270) {
1207 src_input.x = src_input.x ^ src_input.y;
1208 src_input.y = src_input.x ^ src_input.y;
1209 src_input.x = src_input.x ^ src_input.y;
1210 src_input.w = src_input.w ^ src_input.h;
1211 src_input.h = src_input.w ^ src_input.h;
1212 src_input.w = src_input.w ^ src_input.h;
1215 case DISP_GEO_METHOD_FULL_SCREEN:
1216 result.x = result.y = 0;
1217 result.w = evaspixmapsink->xpixmap[idx]->width;
1218 result.h = evaspixmapsink->xpixmap[idx]->height;
1219 GST_DEBUG_OBJECT (evaspixmapsink, "GEO_METHOD : full screen");
1221 case DISP_GEO_METHOD_CROPPED_FULL_SCREEN:
1222 GST_DEBUG_OBJECT (evaspixmapsink, "GEO_METHOD : cropped full screen");
1223 gst_video_sink_center_rect(dst, src, &src_input, TRUE);
1224 result.x = result.y = 0;
1227 if (evaspixmapsink->rotate_angle == DEGREE_90 ||
1228 evaspixmapsink->rotate_angle == DEGREE_270) {
1229 src_input.x = src_input.x ^ src_input.y;
1230 src_input.y = src_input.x ^ src_input.y;
1231 src_input.x = src_input.x ^ src_input.y;
1232 src_input.w = src_input.w ^ src_input.h;
1233 src_input.h = src_input.w ^ src_input.h;
1234 src_input.w = src_input.w ^ src_input.h;
1237 case DISP_GEO_METHOD_CUSTOM_ROI:
1238 switch (evaspixmapsink->rotate_angle) {
1240 result.w = evaspixmapsink->dst_roi.h;
1241 result.h = evaspixmapsink->dst_roi.w;
1242 result.x = evaspixmapsink->dst_roi.y;
1243 result.y = evaspixmapsink->xpixmap[idx]->height - evaspixmapsink->dst_roi.x - evaspixmapsink->dst_roi.w;
1246 result.w = evaspixmapsink->dst_roi.w;
1247 result.h = evaspixmapsink->dst_roi.h;
1248 result.x = evaspixmapsink->xpixmap[idx]->width - result.w - evaspixmapsink->dst_roi.x;
1249 result.y = evaspixmapsink->xpixmap[idx]->height - result.h - evaspixmapsink->dst_roi.y;
1252 result.w = evaspixmapsink->dst_roi.h;
1253 result.h = evaspixmapsink->dst_roi.w;
1254 result.x = evaspixmapsink->xpixmap[idx]->width - evaspixmapsink->dst_roi.y - evaspixmapsink->dst_roi.h;
1255 result.y = evaspixmapsink->dst_roi.x;
1258 result.x = evaspixmapsink->dst_roi.x;
1259 result.y = evaspixmapsink->dst_roi.y;
1260 result.w = evaspixmapsink->dst_roi.w;
1261 result.h = evaspixmapsink->dst_roi.h;
1264 GST_LOG_OBJECT(evaspixmapsink, "rotate[%d], ROI input[%d,%d,%dx%d] > result[%d,%d,%dx%d]",
1265 evaspixmapsink->rotate_angle,
1266 evaspixmapsink->dst_roi.x, evaspixmapsink->dst_roi.y, evaspixmapsink->dst_roi.w, evaspixmapsink->dst_roi.h,
1267 result.x, result.y, result.w, result.h);
1272 GST_DEBUG_OBJECT (evaspixmapsink, "GEO_METHOD : src(%dx%d), dst(%dx%d), result(%dx%d), result_x(%d), result_y(%d)",
1273 src.w,src.h,dst.w,dst.h,result.w,result.h,result.x,result.y);
1275 switch( evaspixmapsink->rotate_angle ) {
1288 GST_WARNING_OBJECT( evaspixmapsink, "Unsupported rotation [%d]... set DEGREE 0.",
1289 evaspixmapsink->rotate_angle );
1293 /* set display rotation */
1294 if (atom_rotation == None) {
1295 atom_rotation = XInternAtom(evaspixmapsink->xcontext->disp, "_USER_WM_PORT_ATTRIBUTE_ROTATION", False);
1298 ret = XvSetPortAttribute(evaspixmapsink->xcontext->disp, evaspixmapsink->xcontext->xv_port_id, atom_rotation, rotate);
1299 if (ret != Success) {
1300 GST_ERROR_OBJECT( evaspixmapsink, "XvSetPortAttribute failed[%d]. disp[%x],xv_port_id[%d],atom[%x],rotate[%d]",
1301 ret, evaspixmapsink->xcontext->disp, evaspixmapsink->xcontext->xv_port_id, atom_rotation, rotate );
1305 /* set display flip */
1306 if (atom_hflip == None) {
1307 atom_hflip = XInternAtom(evaspixmapsink->xcontext->disp, "_USER_WM_PORT_ATTRIBUTE_HFLIP", False);
1309 if (atom_vflip == None) {
1310 atom_vflip = XInternAtom(evaspixmapsink->xcontext->disp, "_USER_WM_PORT_ATTRIBUTE_VFLIP", False);
1313 switch (evaspixmapsink->flip) {
1314 case FLIP_HORIZONTAL:
1332 GST_INFO_OBJECT(evaspixmapsink, "set rotate %d HFLIP %d, VFLIP %d", rotate, set_hflip, set_vflip);
1334 ret = XvSetPortAttribute(evaspixmapsink->xcontext->disp, evaspixmapsink->xcontext->xv_port_id, atom_hflip, set_hflip);
1335 if (ret != Success) {
1336 GST_WARNING("set HFLIP failed[%d]. disp[%x],xv_port_id[%d],atom[%x],hflip[%d]",
1337 ret, evaspixmapsink->xcontext->disp, evaspixmapsink->xcontext->xv_port_id, atom_hflip, set_hflip);
1339 ret = XvSetPortAttribute(evaspixmapsink->xcontext->disp, evaspixmapsink->xcontext->xv_port_id, atom_vflip, set_vflip);
1340 if (ret != Success) {
1341 GST_WARNING("set VFLIP failed[%d]. disp[%x],xv_port_id[%d],atom[%x],vflip[%d]",
1342 ret, evaspixmapsink->xcontext->disp, evaspixmapsink->xcontext->xv_port_id, atom_vflip, set_vflip);
1346 result.x = result.y = 0;
1347 result.w = evaspixmapsink->xpixmap[idx]->width;
1348 result.h = evaspixmapsink->xpixmap[idx]->height;
1349 GST_INFO_OBJECT (evaspixmapsink, "USE ORIGIN SIZE, no geometry method, no rotation/flip" );
1352 g_mutex_lock (evaspixmapsink->x_lock);
1354 /* We scale to the pixmap's geometry */
1356 if (evaspixmapsink->xcontext->use_xshm) {
1357 GST_LOG_OBJECT (evaspixmapsink,"XvShmPutImage with image %dx%d and pixmap %dx%d, from xvimage %"
1359 evaspixmapbuf->width, evaspixmapbuf->height,
1360 evaspixmapsink->render_rect.w, evaspixmapsink->render_rect.h, evaspixmapbuf);
1362 /* Trim as proper size */
1363 if (src_input.w % 2 == 1) {
1366 if (src_input.h % 2 == 1) {
1370 GST_LOG_OBJECT (evaspixmapsink, "screen[%dx%d],pixmap[%d,%d,%dx%d],method[%d],rotate[%d],src[%dx%d],dst[%d,%d,%dx%d],input[%d,%d,%dx%d],result[%d,%d,%dx%d]",
1371 evaspixmapsink->scr_w, evaspixmapsink->scr_h,
1372 evaspixmapsink->xpixmap[idx]->x, evaspixmapsink->xpixmap[idx]->y, evaspixmapsink->xpixmap[idx]->width, evaspixmapsink->xpixmap[idx]->height,
1373 evaspixmapsink->display_geometry_method, rotate,
1374 src_origin.w, src_origin.h,
1375 dst.x, dst.y, dst.w, dst.h,
1376 src_input.x, src_input.y, src_input.w, src_input.h,
1377 result.x, result.y, result.w, result.h );
1379 if (evaspixmapsink->visible) {
1380 if (evaspixmapsink->buf_shared_type == BUF_SHARE_METHOD_FD) {
1381 EVASPIXMAPSINK_SET_PIXMAP_ID_TO_GEM_INFO (evaspixmapsink, evaspixmapsink->xpixmap[idx]->pixmap);
1383 ret = XvShmPutImage (evaspixmapsink->xcontext->disp,
1384 evaspixmapsink->xcontext->xv_port_id,
1385 evaspixmapsink->xpixmap[idx]->pixmap,
1386 evaspixmapsink->xpixmap[idx]->gc, evaspixmapbuf->xvimage,
1387 src_input.x, src_input.y, src_input.w, src_input.h,
1388 result.x, result.y, result.w, result.h, FALSE);
1389 GST_LOG_OBJECT (evaspixmapsink, "XvShmPutImage return value [%d]", ret );
1391 GST_WARNING_OBJECT (evaspixmapsink, "visible is FALSE. skip this image..." );
1394 #endif /* HAVE_XSHM */
1396 if (evaspixmapsink->visible) {
1397 XvPutImage (evaspixmapsink->xcontext->disp,
1398 evaspixmapsink->xcontext->xv_port_id,
1399 evaspixmapsink->xpixmap[idx]->pixmap,
1400 evaspixmapsink->xpixmap[idx]->gc, evaspixmapbuf->xvimage,
1401 evaspixmapsink->disp_x, evaspixmapsink->disp_y,
1402 evaspixmapsink->disp_width, evaspixmapsink->disp_height,
1403 result.x, result.y, result.w, result.h);
1405 GST_WARNING_OBJECT (evaspixmapsink, "visible is FALSE. skip this image..." );
1408 XSync (evaspixmapsink->xcontext->disp, FALSE);
1410 g_mutex_unlock (evaspixmapsink->x_lock);
1411 g_mutex_unlock (evaspixmapsink->flow_lock);
1413 MMTA_ACUM_ITEM_END("evaspixmapsink evaspixmap_buffer_put()", FALSE);
1419 drm_init(GstEvasPixmapSink *evaspixmapsink)
1427 char *driverName = NULL;
1428 char *deviceName = NULL;
1429 struct drm_auth auth_arg = {0};
1431 evaspixmapsink->drm_fd = -1;
1433 dpy = XOpenDisplay(0);
1436 if (!DRI2QueryExtension(dpy, &eventBase, &errorBase)) {
1437 GST_ERROR_OBJECT (evaspixmapsink,"failed to DRI2QueryExtension()");
1441 if (!DRI2QueryVersion(dpy, &dri2Major, &dri2Minor)) {
1442 GST_ERROR_OBJECT (evaspixmapsink,"failed to DRI2QueryVersion");
1446 if (!DRI2Connect(dpy, RootWindow(dpy, DefaultScreen(dpy)), &driverName, &deviceName)) {
1447 GST_ERROR_OBJECT (evaspixmapsink,"failed to DRI2Connect");
1451 if (!driverName || !deviceName) {
1452 GST_ERROR_OBJECT (evaspixmapsink,"driverName or deviceName is not valid");
1456 GST_INFO_OBJECT (evaspixmapsink,"Open drm device : %s", deviceName);
1458 /* get the drm_fd though opening the deviceName */
1459 evaspixmapsink->drm_fd = open(deviceName, O_RDWR);
1460 if (evaspixmapsink->drm_fd < 0) {
1461 GST_ERROR_OBJECT (evaspixmapsink,"cannot open drm device (%s)", deviceName);
1465 /* get magic from drm to authentication */
1466 if (ioctl(evaspixmapsink->drm_fd, DRM_IOCTL_GET_MAGIC, &auth_arg)) {
1467 GST_ERROR_OBJECT (evaspixmapsink,"cannot get drm auth magic");
1468 close(evaspixmapsink->drm_fd);
1469 evaspixmapsink->drm_fd = -1;
1473 if (!DRI2Authenticate(dpy, RootWindow(dpy, DefaultScreen(dpy)), auth_arg.magic)) {
1474 GST_ERROR_OBJECT (evaspixmapsink,"cannot get drm authentication from X");
1475 close(evaspixmapsink->drm_fd);
1476 evaspixmapsink->drm_fd = -1;
1480 /* init gem handle */
1481 for (i = 0; i < MAX_GEM_BUFFER_NUM; i++) {
1482 evaspixmapsink->gem_info[i].dmabuf_fd = 0;
1483 evaspixmapsink->gem_info[i].gem_handle = 0;
1484 evaspixmapsink->gem_info[i].gem_name = 0;
1485 evaspixmapsink->gem_info[i].bo = 0;
1486 evaspixmapsink->gem_info[i].ref_pixmap = 0;
1508 drm_fini(GstEvasPixmapSink *evaspixmapsink)
1510 if (evaspixmapsink->drm_fd >= 0) {
1511 GST_INFO_OBJECT (evaspixmapsink,"close drm_fd(%d)", evaspixmapsink->drm_fd);
1512 close(evaspixmapsink->drm_fd);
1513 evaspixmapsink->drm_fd = -1;
1518 drm_init_convert_dmabuf_gemname(GstEvasPixmapSink *evaspixmapsink, int dmabuf_fd)
1520 struct drm_prime_handle prime_arg = {0,};
1521 struct drm_gem_flink flink_arg = {0,};
1524 if (evaspixmapsink->drm_fd < 0) {
1525 GST_ERROR_OBJECT (evaspixmapsink,"DRM is not opened");
1529 if (dmabuf_fd <= 0) {
1530 GST_DEBUG_OBJECT (evaspixmapsink,"Ignore wrong dmabuf fd(%d)", dmabuf_fd); /* temporarily change log level to DEBUG for reducing WARNING level log */
1534 /* check duplicated dmabuf fd */
1535 for (i = 0 ; i < MAX_GEM_BUFFER_NUM ; i++) {
1536 if (evaspixmapsink->gem_info[i].dmabuf_fd == dmabuf_fd) {
1537 GST_LOG_OBJECT (evaspixmapsink,"already got fd(%u) with name(%u)", dmabuf_fd, evaspixmapsink->gem_info[i].gem_name);
1538 return evaspixmapsink->gem_info[i].gem_name;
1541 if (evaspixmapsink->gem_info[i].dmabuf_fd == 0) {
1542 GST_LOG_OBJECT (evaspixmapsink,"empty gem_info[%d] found", i);
1547 if (i == MAX_GEM_BUFFER_NUM) {
1548 GST_WARNING_OBJECT (evaspixmapsink,"too many buffers[dmabuf_fd(%d). skip it]", dmabuf_fd);
1552 evaspixmapsink->gem_info[i].dmabuf_fd = dmabuf_fd;
1553 prime_arg.fd = dmabuf_fd;
1554 if (ioctl(evaspixmapsink->drm_fd, DRM_IOCTL_PRIME_FD_TO_HANDLE, &prime_arg)) {
1555 GST_ERROR_OBJECT (evaspixmapsink,"non dmabuf fd(%d)", dmabuf_fd);
1559 evaspixmapsink->gem_info[i].gem_handle = prime_arg.handle;
1560 GST_LOG_OBJECT (evaspixmapsink,"gem_info[%d].gem_handle = %u", i, prime_arg.handle);
1562 flink_arg.handle = prime_arg.handle;
1563 if (ioctl(evaspixmapsink->drm_fd, DRM_IOCTL_GEM_FLINK, &flink_arg)) {
1564 GST_ERROR_OBJECT (evaspixmapsink,"cannot convert drm handle to name");
1568 evaspixmapsink->gem_info[i].gem_name = flink_arg.name;
1569 GST_LOG_OBJECT (evaspixmapsink,"gem_info[%d].gem_name = %u", i, flink_arg.name);
1571 return flink_arg.name;
1575 tbm_init_convert_bo_gemname(GstEvasPixmapSink *evaspixmapsink, unsigned int bo)
1580 GST_DEBUG_OBJECT (evaspixmapsink,"Ignore wrong bo(%u)", bo); /* temporarily change log level to DEBUG for reducing WARNING level log */
1584 /* check duplicated dmabuf bo */
1585 for (i = 0 ; i < MAX_GEM_BUFFER_NUM ; i++) {
1586 if (evaspixmapsink->gem_info[i].bo == bo) {
1587 GST_LOG_OBJECT (evaspixmapsink,"already got bo(%u) with name(%u)", bo, evaspixmapsink->gem_info[i].gem_name);
1588 return evaspixmapsink->gem_info[i].gem_name;
1591 if (evaspixmapsink->gem_info[i].bo == 0) {
1592 GST_LOG_OBJECT (evaspixmapsink,"empty gem_info[%d] found", i);
1597 if (i == MAX_GEM_BUFFER_NUM) {
1598 GST_WARNING_OBJECT (evaspixmapsink,"too many buffers[dmabuf_bo(%d). skip it]", bo);
1602 evaspixmapsink->gem_info[i].bo = bo;
1603 evaspixmapsink->gem_info[i].gem_name = tbm_bo_export(bo);
1604 GST_LOG_OBJECT (evaspixmapsink,"gem_info[%d].gem_name = %u", i, evaspixmapsink->gem_info[i].gem_name);
1606 return evaspixmapsink->gem_info[i].gem_name;
1610 drm_fini_close_gem_handle(GstEvasPixmapSink *evaspixmapsink, Pixmap pixmap_id)
1613 if (evaspixmapsink->drm_fd >= 0) {
1614 if (pixmap_id == 0) {
1615 for (i = 0; i < MAX_GEM_BUFFER_NUM; i++) {
1616 if (evaspixmapsink->gem_info[i].dmabuf_fd > 0) {
1617 if (evaspixmapsink->buf_shared_type == BUF_SHARE_METHOD_FD) {
1618 GST_INFO_OBJECT (evaspixmapsink,"close gem_handle(%u)", evaspixmapsink->gem_info[i].gem_handle);
1619 drm_close_gem(evaspixmapsink, evaspixmapsink->gem_info[i].gem_handle);
1621 evaspixmapsink->gem_info[i].dmabuf_fd = 0;
1622 evaspixmapsink->gem_info[i].gem_handle = 0;
1623 evaspixmapsink->gem_info[i].gem_name = 0;
1624 evaspixmapsink->gem_info[i].bo = 0;
1625 evaspixmapsink->gem_info[i].ref_pixmap = 0;
1630 for (i = 0; i < MAX_GEM_BUFFER_NUM; i++) {
1631 if (evaspixmapsink->gem_info[i].dmabuf_fd > 0 && evaspixmapsink->gem_info[i].ref_pixmap == pixmap_id) {
1632 if (evaspixmapsink->buf_shared_type == BUF_SHARE_METHOD_FD) {
1633 GST_INFO_OBJECT (evaspixmapsink,"close gem_handle(%u) for pixmap_id(%d)",
1634 evaspixmapsink->gem_info[i].gem_handle, pixmap_id);
1635 drm_close_gem(evaspixmapsink, evaspixmapsink->gem_info[i].gem_handle);
1637 evaspixmapsink->gem_info[i].dmabuf_fd = 0;
1638 evaspixmapsink->gem_info[i].gem_handle = 0;
1639 evaspixmapsink->gem_info[i].gem_name = 0;
1640 evaspixmapsink->gem_info[i].bo = 0;
1641 evaspixmapsink->gem_info[i].ref_pixmap = 0;
1650 drm_close_gem(GstEvasPixmapSink *evaspixmapsink, unsigned int gem_handle)
1652 struct drm_gem_close close_arg = {0,};
1654 if (evaspixmapsink->drm_fd < 0) {
1655 GST_ERROR_OBJECT (evaspixmapsink,"DRM is not opened");
1659 if (gem_handle == 0) {
1660 GST_ERROR_OBJECT (evaspixmapsink,"invalid gem_handle(%d)",gem_handle);
1664 close_arg.handle = gem_handle;
1665 if (gem_handle > 0 && ioctl(evaspixmapsink->drm_fd, DRM_IOCTL_GEM_CLOSE, &close_arg)) {
1666 GST_ERROR_OBJECT (evaspixmapsink,"cannot close drm gem handle(%d)", gem_handle);
1673 /* This function destroys a GstXPixmap */
1675 gst_evaspixmapsink_xpixmap_destroy (GstEvasPixmapSink *evaspixmapsink, GstXPixmap *xpixmap)
1677 g_return_if_fail (xpixmap != NULL);
1678 g_return_if_fail (GST_IS_EVASPIXMAPSINK (evaspixmapsink));
1680 g_mutex_lock (evaspixmapsink->x_lock);
1682 if(xpixmap->pixmap) {
1683 GST_LOG_OBJECT (evaspixmapsink,"Free pixmap(%d)", xpixmap->pixmap);
1684 XFreePixmap(evaspixmapsink->xcontext->disp, xpixmap->pixmap);
1685 xpixmap->pixmap = 0;
1689 XFreeGC (evaspixmapsink->xcontext->disp, xpixmap->gc);
1692 XSync (evaspixmapsink->xcontext->disp, FALSE);
1694 g_mutex_unlock (evaspixmapsink->x_lock);
1700 gst_evaspixmapsink_xpixmap_update_geometry (GstEvasPixmapSink *evaspixmapsink, int idx)
1703 XWindowAttributes root_attr;
1705 int cur_pixmap_x = 0;
1706 int cur_pixmap_y = 0;
1707 unsigned int cur_pixmap_width = 0;
1708 unsigned int cur_pixmap_height = 0;
1709 unsigned int cur_pixmap_border_width = 0;
1710 unsigned int cur_pixmap_depth = 0;
1712 g_return_if_fail (GST_IS_EVASPIXMAPSINK (evaspixmapsink));
1714 /* Update the window geometry */
1715 g_mutex_lock (evaspixmapsink->x_lock);
1716 if (G_UNLIKELY (evaspixmapsink->xpixmap[idx] == NULL)) {
1717 g_mutex_unlock (evaspixmapsink->x_lock);
1721 /* Get root window and size of current pixmap */
1722 XGetGeometry( evaspixmapsink->xcontext->disp, evaspixmapsink->xpixmap[idx]->pixmap, &root_window,
1723 &cur_pixmap_x, &cur_pixmap_y, /* relative x, y, for pixmap these are alway 0 */
1724 &cur_pixmap_width, &cur_pixmap_height,
1725 &cur_pixmap_border_width, &cur_pixmap_depth ); /* cur_pixmap_border_width, cur_pixmap_depth are not used */
1727 evaspixmapsink->xpixmap[idx]->width = cur_pixmap_width;
1728 evaspixmapsink->xpixmap[idx]->height = cur_pixmap_height;
1730 evaspixmapsink->xpixmap[idx]->x = cur_pixmap_x;
1731 evaspixmapsink->xpixmap[idx]->y = cur_pixmap_y;
1733 /* Get size of root window == size of screen */
1734 XGetWindowAttributes(evaspixmapsink->xcontext->disp, root_window, &root_attr);
1736 evaspixmapsink->scr_w = root_attr.width;
1737 evaspixmapsink->scr_h = root_attr.height;
1739 if (!evaspixmapsink->have_render_rect) {
1740 evaspixmapsink->render_rect.x = evaspixmapsink->render_rect.y = 0;
1741 evaspixmapsink->render_rect.w = cur_pixmap_width;
1742 evaspixmapsink->render_rect.h = cur_pixmap_height;
1745 GST_LOG_OBJECT (evaspixmapsink,"screen size %dx%d, current pixmap geometry %d,%d,%dx%d, render_rect %d,%d,%dx%d",
1746 evaspixmapsink->scr_w, evaspixmapsink->scr_h,
1747 evaspixmapsink->xpixmap[idx]->x, evaspixmapsink->xpixmap[idx]->y,
1748 evaspixmapsink->xpixmap[idx]->width, evaspixmapsink->xpixmap[idx]->height,
1749 evaspixmapsink->render_rect.x, evaspixmapsink->render_rect.y,
1750 evaspixmapsink->render_rect.w, evaspixmapsink->render_rect.h);
1752 g_mutex_unlock (evaspixmapsink->x_lock);
1756 gst_evaspixmapsink_xpixmap_clear (GstEvasPixmapSink *evaspixmapsink, GstXPixmap *xpixmap)
1758 g_return_if_fail (xpixmap != NULL);
1759 g_return_if_fail (GST_IS_EVASPIXMAPSINK (evaspixmapsink));
1761 if (!xpixmap->pixmap) {
1762 GST_WARNING_OBJECT (evaspixmapsink,"pixmap was not created..");
1766 g_mutex_lock (evaspixmapsink->x_lock);
1768 if (!evaspixmapsink->xcontext) {
1769 GST_WARNING_OBJECT (evaspixmapsink,"xcontext is null..");
1770 g_mutex_unlock (evaspixmapsink->x_lock);
1774 if (evaspixmapsink->stop_video) {
1775 XvStopVideo (evaspixmapsink->xcontext->disp, evaspixmapsink->xcontext->xv_port_id, xpixmap->pixmap);
1777 XSync (evaspixmapsink->xcontext->disp, FALSE);
1779 g_mutex_unlock (evaspixmapsink->x_lock);
1781 g_mutex_lock (evaspixmapsink->pixmap_ref_lock);
1782 evaspixmapsink->last_updated_idx = -1;
1784 xpixmap->damaged_time = 0;
1785 g_mutex_unlock (evaspixmapsink->pixmap_ref_lock);
1788 /* This function commits our internal colorbalance settings to our grabbed Xv
1789 port. If the xcontext is not initialized yet it simply returns */
1791 gst_evaspixmapsink_update_colorbalance (GstEvasPixmapSink *evaspixmapsink)
1793 GList *channels = NULL;
1795 g_return_if_fail (GST_IS_EVASPIXMAPSINK (evaspixmapsink));
1797 /* If we haven't initialized the X context we can't update anything */
1798 if (evaspixmapsink->xcontext == NULL)
1801 /* Don't set the attributes if they haven't been changed, to avoid
1802 * rounding errors changing the values */
1803 if (!evaspixmapsink->cb_changed)
1806 /* For each channel of the colorbalance we calculate the correct value
1807 doing range conversion and then set the Xv port attribute to match our
1809 channels = evaspixmapsink->xcontext->channels_list;
1812 if (channels->data && GST_IS_COLOR_BALANCE_CHANNEL (channels->data)) {
1813 GstColorBalanceChannel *channel = NULL;
1816 gdouble convert_coef;
1818 channel = GST_COLOR_BALANCE_CHANNEL (channels->data);
1819 g_object_ref (channel);
1821 /* Our range conversion coef */
1822 convert_coef = (channel->max_value - channel->min_value) / 2000.0;
1824 if (g_ascii_strcasecmp (channel->label, "XV_HUE") == 0) {
1825 value = evaspixmapsink->hue;
1826 } else if (g_ascii_strcasecmp (channel->label, "XV_SATURATION") == 0) {
1827 value = evaspixmapsink->saturation;
1828 } else if (g_ascii_strcasecmp (channel->label, "XV_CONTRAST") == 0) {
1829 value = evaspixmapsink->contrast;
1830 } else if (g_ascii_strcasecmp (channel->label, "XV_BRIGHTNESS") == 0) {
1831 value = evaspixmapsink->brightness;
1833 g_warning ("got an unknown channel %s", channel->label);
1834 g_object_unref (channel);
1838 /* Committing to Xv port */
1839 g_mutex_lock (evaspixmapsink->x_lock);
1841 XInternAtom (evaspixmapsink->xcontext->disp, channel->label, True);
1842 if (prop_atom != None) {
1845 floor (0.5 + (value + 1000) * convert_coef + channel->min_value);
1846 XvSetPortAttribute (evaspixmapsink->xcontext->disp,
1847 evaspixmapsink->xcontext->xv_port_id, prop_atom, xv_value);
1849 g_mutex_unlock (evaspixmapsink->x_lock);
1851 g_object_unref (channel);
1853 channels = g_list_next (channels);
1858 gst_lookup_xv_port_from_adaptor (GstXContext *xcontext, XvAdaptorInfo *adaptors, int adaptor_no)
1863 /* Do we support XvImageMask ? */
1864 if (!(adaptors[adaptor_no].type & XvImageMask)) {
1865 GST_DEBUG ("XV Adaptor %s has no support for XvImageMask", adaptors[adaptor_no].name);
1869 /* We found such an adaptor, looking for an available port */
1870 for (j = 0; j < adaptors[adaptor_no].num_ports && !xcontext->xv_port_id; j++) {
1871 /* We try to grab the port */
1872 res = XvGrabPort (xcontext->disp, adaptors[adaptor_no].base_id + j, 0);
1873 if (Success == res) {
1874 xcontext->xv_port_id = adaptors[adaptor_no].base_id + j;
1875 GST_DEBUG ("XV Adaptor %s with %ld ports", adaptors[adaptor_no].name, adaptors[adaptor_no].num_ports);
1877 GST_DEBUG ("GrabPort %d for XV Adaptor %s failed: %d", j, adaptors[adaptor_no].name, res);
1882 /* This function generates a caps with all supported format by the first
1883 Xv grabable port we find. We store each one of the supported formats in a
1884 format list and append the format to a newly created caps that we return
1885 If this function does not return NULL because of an error, it also grabs
1886 the port via XvGrabPort */
1888 gst_evaspixmapsink_get_xv_support (GstEvasPixmapSink *evaspixmapsink, GstXContext *xcontext)
1891 XvAdaptorInfo *adaptors;
1893 XvImageFormatValues *formats = NULL;
1895 XvEncodingInfo *encodings = NULL;
1896 gulong max_w = G_MAXINT, max_h = G_MAXINT;
1897 GstCaps *caps = NULL;
1898 GstCaps *rgb_caps = NULL;
1900 g_return_val_if_fail (xcontext != NULL, NULL);
1902 /* First let's check that XVideo extension is available */
1903 if (!XQueryExtension (xcontext->disp, "XVideo", &i, &i, &i)) {
1904 GST_ELEMENT_ERROR (evaspixmapsink, RESOURCE, SETTINGS,
1905 ("Could not initialise Xv output"),
1906 ("XVideo extension is not available"));
1910 /* Then we get adaptors list */
1911 if (Success != XvQueryAdaptors (xcontext->disp, xcontext->root,
1912 &xcontext->nb_adaptors, &adaptors)) {
1913 GST_ELEMENT_ERROR (evaspixmapsink, RESOURCE, SETTINGS,
1914 ("Could not initialise Xv output"),
1915 ("Failed getting XV adaptors list"));
1919 xcontext->xv_port_id = 0;
1921 GST_DEBUG_OBJECT (evaspixmapsink,"Found %u XV adaptor(s)", xcontext->nb_adaptors);
1923 xcontext->adaptors =
1924 (gchar **) g_malloc0 (xcontext->nb_adaptors * sizeof (gchar *));
1926 /* Now fill up our adaptor name array */
1927 for (i = 0; i < xcontext->nb_adaptors; i++) {
1928 xcontext->adaptors[i] = g_strdup (adaptors[i].name);
1931 if (evaspixmapsink->adaptor_no < xcontext->nb_adaptors) {
1932 /* Find xv port from user defined adaptor */
1933 gst_lookup_xv_port_from_adaptor (xcontext, adaptors, evaspixmapsink->adaptor_no);
1936 if (!xcontext->xv_port_id) {
1937 /* Now search for an adaptor that supports XvImageMask */
1938 for (i = 0; i < xcontext->nb_adaptors && !xcontext->xv_port_id; i++) {
1939 gst_lookup_xv_port_from_adaptor (xcontext, adaptors, i);
1940 evaspixmapsink->adaptor_no = i;
1944 XvFreeAdaptorInfo (adaptors);
1946 if (!xcontext->xv_port_id) {
1947 evaspixmapsink->adaptor_no = -1;
1948 GST_ELEMENT_ERROR (evaspixmapsink, RESOURCE, BUSY,
1949 ("Could not initialise Xv output"), ("No port available"));
1953 /* Set XV_AUTOPAINT_COLORKEY and XV_DOUBLE_BUFFER and XV_COLORKEY */
1955 int count, todo = 3;
1956 XvAttribute *const attr = XvQueryPortAttributes (xcontext->disp,
1957 xcontext->xv_port_id, &count);
1958 static const char autopaint[] = "XV_AUTOPAINT_COLORKEY";
1959 static const char dbl_buffer[] = "XV_DOUBLE_BUFFER";
1960 static const char colorkey[] = "XV_COLORKEY";
1962 GST_DEBUG_OBJECT (evaspixmapsink,"Checking %d Xv port attributes", count);
1964 evaspixmapsink->have_autopaint_colorkey = FALSE;
1965 evaspixmapsink->have_double_buffer = FALSE;
1966 evaspixmapsink->have_colorkey = FALSE;
1968 for (i = 0; ((i < count) && todo); i++)
1969 if (!strcmp (attr[i].name, autopaint)) {
1970 const Atom atom = XInternAtom (xcontext->disp, autopaint, False);
1972 /* turn on autopaint colorkey */
1973 XvSetPortAttribute (xcontext->disp, xcontext->xv_port_id, atom,
1974 (evaspixmapsink->autopaint_colorkey ? 1 : 0));
1976 evaspixmapsink->have_autopaint_colorkey = TRUE;
1977 } else if (!strcmp (attr[i].name, dbl_buffer)) {
1978 const Atom atom = XInternAtom (xcontext->disp, dbl_buffer, False);
1980 XvSetPortAttribute (xcontext->disp, xcontext->xv_port_id, atom,
1981 (evaspixmapsink->double_buffer ? 1 : 0));
1983 evaspixmapsink->have_double_buffer = TRUE;
1984 } else if (!strcmp (attr[i].name, colorkey)) {
1985 /* Set the colorkey, default is something that is dark but hopefully
1986 * won't randomly appear on the screen elsewhere (ie not black or greys)
1987 * can be overridden by setting "colorkey" property
1989 const Atom atom = XInternAtom (xcontext->disp, colorkey, False);
1991 gboolean set_attr = TRUE;
1994 /* set a colorkey in the right format RGB565/RGB888
1995 * We only handle these 2 cases, because they're the only types of
1996 * devices we've encountered. If we don't recognise it, leave it alone
1998 cr = (evaspixmapsink->colorkey >> 16);
1999 cg = (evaspixmapsink->colorkey >> 8) & 0xFF;
2000 cb = (evaspixmapsink->colorkey) & 0xFF;
2001 switch (xcontext->depth) {
2002 case 16: /* RGB 565 */
2006 ckey = (cr << 11) | (cg << 5) | cb;
2009 case 32: /* RGB 888 / ARGB 8888 */
2010 ckey = (cr << 16) | (cg << 8) | cb;
2013 GST_DEBUG_OBJECT (evaspixmapsink,"Unknown bit depth %d for Xv Colorkey - not adjusting", xcontext->depth);
2019 ckey = CLAMP (ckey, (guint32) attr[i].min_value,
2020 (guint32) attr[i].max_value);
2021 GST_LOG_OBJECT (evaspixmapsink,"Setting color key for display depth %d to 0x%x", xcontext->depth, ckey);
2023 XvSetPortAttribute (xcontext->disp, xcontext->xv_port_id, atom,
2027 evaspixmapsink->have_colorkey = TRUE;
2033 /* Get the list of encodings supported by the adapter and look for the
2034 * XV_IMAGE encoding so we can determine the maximum width and height
2036 XvQueryEncodings (xcontext->disp, xcontext->xv_port_id, &nb_encodings,
2039 for (i = 0; i < nb_encodings; i++) {
2040 GST_LOG_OBJECT (evaspixmapsink,
2041 "Encoding %d, name %s, max wxh %lux%lu rate %d/%d",
2042 i, encodings[i].name, encodings[i].width, encodings[i].height,
2043 encodings[i].rate.numerator, encodings[i].rate.denominator);
2044 if (strcmp (encodings[i].name, "XV_IMAGE") == 0) {
2045 max_w = encodings[i].width;
2046 max_h = encodings[i].height;
2047 evaspixmapsink->scr_w = max_w;
2048 evaspixmapsink->scr_h = max_h;
2052 XvFreeEncodingInfo (encodings);
2054 /* We get all image formats supported by our port */
2055 formats = XvListImageFormats (xcontext->disp,
2056 xcontext->xv_port_id, &nb_formats);
2057 caps = gst_caps_new_empty ();
2058 for (i = 0; i < nb_formats; i++) {
2059 GstCaps *format_caps = NULL;
2060 gboolean is_rgb_format = FALSE;
2062 /* We set the image format of the xcontext to an existing one. This
2063 is just some valid image format for making our xshm calls check before
2064 caps negotiation really happens. */
2065 xcontext->im_format = formats[i].id;
2067 switch (formats[i].type) {
2070 XvImageFormatValues *fmt = &(formats[i]);
2071 gint endianness = G_BIG_ENDIAN;
2073 if (fmt->byte_order == LSBFirst) {
2074 /* our caps system handles 24/32bpp RGB as big-endian. */
2075 if (fmt->bits_per_pixel == 24 || fmt->bits_per_pixel == 32) {
2076 fmt->red_mask = GUINT32_TO_BE (fmt->red_mask);
2077 fmt->green_mask = GUINT32_TO_BE (fmt->green_mask);
2078 fmt->blue_mask = GUINT32_TO_BE (fmt->blue_mask);
2080 if (fmt->bits_per_pixel == 24) {
2081 fmt->red_mask >>= 8;
2082 fmt->green_mask >>= 8;
2083 fmt->blue_mask >>= 8;
2086 endianness = G_LITTLE_ENDIAN;
2089 format_caps = gst_caps_new_simple ("video/x-raw-rgb",
2090 "format", GST_TYPE_FOURCC, formats[i].id,
2091 "endianness", G_TYPE_INT, endianness,
2092 "depth", G_TYPE_INT, fmt->depth,
2093 "bpp", G_TYPE_INT, fmt->bits_per_pixel,
2094 "red_mask", G_TYPE_INT, fmt->red_mask,
2095 "green_mask", G_TYPE_INT, fmt->green_mask,
2096 "blue_mask", G_TYPE_INT, fmt->blue_mask,
2097 "width", GST_TYPE_INT_RANGE, 1, max_w,
2098 "height", GST_TYPE_INT_RANGE, 1, max_h,
2099 "framerate", GST_TYPE_FRACTION_RANGE, 0, 1, G_MAXINT, 1, NULL);
2101 is_rgb_format = TRUE;
2105 format_caps = gst_caps_new_simple ("video/x-raw-yuv",
2106 "format", GST_TYPE_FOURCC, formats[i].id,
2107 "width", GST_TYPE_INT_RANGE, 1, max_w,
2108 "height", GST_TYPE_INT_RANGE, 1, max_h,
2109 "framerate", GST_TYPE_FRACTION_RANGE, 0, 1, G_MAXINT, 1, NULL);
2112 g_assert_not_reached ();
2117 GstEvasPixmapFormat *format = NULL;
2119 format = g_new0 (GstEvasPixmapFormat, 1);
2121 format->format = formats[i].id;
2122 format->caps = gst_caps_copy (format_caps);
2123 xcontext->formats_list = g_list_append (xcontext->formats_list, format);
2126 if (is_rgb_format) {
2127 if (rgb_caps == NULL)
2128 rgb_caps = format_caps;
2130 gst_caps_append (rgb_caps, format_caps);
2132 gst_caps_append (caps, format_caps);
2136 /* Collected all caps into either the caps or rgb_caps structures.
2137 * Append rgb_caps on the end of YUV, so that YUV is always preferred */
2139 gst_caps_append (caps, rgb_caps);
2144 GST_DEBUG_OBJECT (evaspixmapsink,"Generated the following caps: %" GST_PTR_FORMAT, caps);
2146 if (gst_caps_is_empty (caps)) {
2147 gst_caps_unref (caps);
2148 XvUngrabPort (xcontext->disp, xcontext->xv_port_id, 0);
2149 GST_ELEMENT_ERROR (evaspixmapsink, STREAM, WRONG_TYPE, (NULL),
2150 ("No supported format found"));
2158 gst_evaspixmapsink_event_thread (GstEvasPixmapSink * evaspixmapsink)
2160 g_return_val_if_fail (GST_IS_EVASPIXMAPSINK (evaspixmapsink), NULL);
2161 int damage_base = 0;
2162 int damage_err_base = 0;
2163 int damage_case = 0;
2166 Display *disp = NULL;
2168 GST_OBJECT_LOCK (evaspixmapsink);
2170 if (evaspixmapsink->xcontext && evaspixmapsink->xcontext->disp) {
2171 disp = evaspixmapsink->xcontext->disp;
2173 GST_ERROR_OBJECT (evaspixmapsink,"evaspixmapsink->xcontext(->disp) is not ready");
2177 if (!XDamageQueryExtension(evaspixmapsink->xcontext->disp, &damage_base, &damage_err_base)) {
2178 GST_ERROR_OBJECT (evaspixmapsink,"XDamageQueryExtension() failed");
2181 damage_case = (int)damage_base + XDamageNotify;
2183 while (evaspixmapsink->running) {
2184 GST_OBJECT_UNLOCK (evaspixmapsink);
2186 g_mutex_lock (evaspixmapsink->x_lock);
2187 while (XPending (disp)) {
2188 XNextEvent (disp, &e);
2189 if (e.type == damage_case ) {
2190 XDamageNotifyEvent *damage_ev = (XDamageNotifyEvent *)&e;
2191 for (i = 0; i < evaspixmapsink->num_of_pixmaps; i++) {
2192 GstXPixmap *xpixmap = evaspixmapsink->xpixmap[i];
2193 if (xpixmap && damage_ev->drawable == xpixmap->pixmap) {
2194 g_mutex_lock(evaspixmapsink->pixmap_ref_lock);
2196 /* set it only if damage event comes from _buffer_put() */
2197 xpixmap->damaged_time = (gint)get_millis_time();
2199 GST_LOG_OBJECT (evaspixmapsink,"event_handler : got a damage event for pixmap(%d), refcount(%d), damaged_time(%d)",
2200 xpixmap->pixmap, xpixmap->ref, xpixmap->damaged_time);
2201 g_mutex_unlock(evaspixmapsink->pixmap_ref_lock);
2203 __ta__("evaspixmapsink ecore_pipe_write", ecore_pipe_write(evaspixmapsink->epipe, evaspixmapsink, sizeof(GstEvasPixmapSink)););
2204 GST_DEBUG_OBJECT (evaspixmapsink,"event_handler : after call ecore_pipe_write() for pixmap(%d)", xpixmap->pixmap);
2205 XDamageSubtract (evaspixmapsink->xcontext->disp, evaspixmapsink->damage[i], None, None );
2207 if (evaspixmapsink->buf_shared_type == BUF_SHARE_METHOD_FD) {
2208 if (GST_STATE(evaspixmapsink) == GST_STATE_PLAYING) {
2209 drm_fini_close_gem_handle(evaspixmapsink, xpixmap->pixmap);
2215 if (i == evaspixmapsink->num_of_pixmaps) {
2216 GST_WARNING_OBJECT (evaspixmapsink,"event_handler : could not find corresponding pixmap with this damage event(%d)", damage_ev->drawable);
2219 GST_LOG_OBJECT (evaspixmapsink,"event_handler : unidentified event(%d)", e.type);
2223 //XSync (disp, FALSE);
2224 g_mutex_unlock (evaspixmapsink->x_lock);
2226 g_usleep (G_USEC_PER_SEC / 40);
2227 GST_OBJECT_LOCK (evaspixmapsink);
2229 GST_OBJECT_UNLOCK (evaspixmapsink);
2234 gst_evaspixmapsink_manage_event_thread (GstEvasPixmapSink *evaspixmapsink)
2236 /* don't start the thread too early */
2237 if (evaspixmapsink->xcontext == NULL) {
2238 GST_ERROR_OBJECT (evaspixmapsink,"xcontext is NULL..");
2242 GST_OBJECT_LOCK (evaspixmapsink);
2244 if (!evaspixmapsink->event_thread) {
2245 /* Setup our event listening thread */
2246 GST_DEBUG_OBJECT (evaspixmapsink,"run xevent thread");
2247 evaspixmapsink->running = TRUE;
2248 evaspixmapsink->event_thread = g_thread_create ( (GThreadFunc) gst_evaspixmapsink_event_thread, evaspixmapsink, TRUE, NULL);
2250 GST_WARNING_OBJECT (evaspixmapsink,"there already existed the event_thread.. keep going");
2251 /* Do not finalize the thread in here, Only finalize the thread by calling gst_evaspixmapsink_reset() */
2254 GST_OBJECT_UNLOCK (evaspixmapsink);
2258 /* This function calculates the pixel aspect ratio based on the properties
2259 * in the xcontext structure and stores it there. */
2261 gst_evaspixmapsink_calculate_pixel_aspect_ratio (GstXContext *xcontext)
2263 static const gint par[][2] = {
2264 {1, 1}, /* regular screen */
2265 {16, 15}, /* PAL TV */
2266 {11, 10}, /* 525 line Rec.601 video */
2267 {54, 59}, /* 625 line Rec.601 video */
2268 {64, 45}, /* 1280x1024 on 16:9 display */
2269 {5, 3}, /* 1280x1024 on 4:3 display */
2270 {4, 3} /* 800x600 on 16:9 display */
2277 #define DELTA(idx) (ABS (ratio - ((gdouble) par[idx][0] / par[idx][1])))
2279 /* first calculate the "real" ratio based on the X values;
2280 * which is the "physical" w/h divided by the w/h in pixels of the display */
2281 ratio = (gdouble) (xcontext->widthmm * xcontext->height)
2282 / (xcontext->heightmm * xcontext->width);
2284 /* DirectFB's X in 720x576 reports the physical dimensions wrong, so
2286 if (xcontext->width == 720 && xcontext->height == 576) {
2287 ratio = 4.0 * 576 / (3.0 * 720);
2289 GST_DEBUG ("calculated pixel aspect ratio: %f", ratio);
2290 /* now find the one from par[][2] with the lowest delta to the real one */
2294 for (i = 1; i < sizeof (par) / (sizeof (gint) * 2); ++i) {
2295 gdouble this_delta = DELTA (i);
2297 if (this_delta < delta) {
2303 GST_DEBUG ("Decided on index %d (%d/%d)", index,
2304 par[index][0], par[index][1]);
2306 g_free (xcontext->par);
2307 xcontext->par = g_new0 (GValue, 1);
2308 g_value_init (xcontext->par, GST_TYPE_FRACTION);
2309 gst_value_set_fraction (xcontext->par, par[index][0], par[index][1]);
2310 GST_DEBUG ("set xcontext PAR to %d/%d",
2311 gst_value_get_fraction_numerator (xcontext->par),
2312 gst_value_get_fraction_denominator (xcontext->par));
2315 /* This function gets the X Display and global info about it. Everything is
2316 stored in our object and will be cleaned when the object is disposed. Note
2317 here that caps for supported format are generated without any window or
2320 gst_evaspixmapsink_xcontext_get (GstEvasPixmapSink *evaspixmapsink)
2322 GstXContext *xcontext = NULL;
2323 XPixmapFormatValues *px_formats = NULL;
2324 gint nb_formats = 0, i, j, N_attr;
2325 XvAttribute *xv_attr;
2327 const char *channels[4] = { "XV_HUE", "XV_SATURATION", "XV_BRIGHTNESS", "XV_CONTRAST"};
2329 g_return_val_if_fail (GST_IS_EVASPIXMAPSINK (evaspixmapsink), NULL);
2331 xcontext = g_new0 (GstXContext, 1);
2332 xcontext->im_format = 0;
2334 g_mutex_lock (evaspixmapsink->x_lock);
2336 xcontext->disp = XOpenDisplay (evaspixmapsink->display_name);
2338 if (!xcontext->disp) {
2339 g_mutex_unlock (evaspixmapsink->x_lock);
2341 GST_ELEMENT_ERROR (evaspixmapsink, RESOURCE, WRITE, ("Could not initialise Xv output"), ("Could not open display"));
2345 xcontext->screen = DefaultScreenOfDisplay (xcontext->disp);
2346 xcontext->screen_num = DefaultScreen (xcontext->disp);
2347 xcontext->visual = DefaultVisual (xcontext->disp, xcontext->screen_num);
2348 xcontext->root = DefaultRootWindow (xcontext->disp);
2349 xcontext->white = XWhitePixel (xcontext->disp, xcontext->screen_num);
2350 xcontext->black = XBlackPixel (xcontext->disp, xcontext->screen_num);
2351 xcontext->depth = DefaultDepthOfScreen (xcontext->screen);
2353 xcontext->width = DisplayWidth (xcontext->disp, xcontext->screen_num);
2354 xcontext->height = DisplayHeight (xcontext->disp, xcontext->screen_num);
2355 xcontext->widthmm = DisplayWidthMM (xcontext->disp, xcontext->screen_num);
2356 xcontext->heightmm = DisplayHeightMM (xcontext->disp, xcontext->screen_num);
2358 GST_DEBUG_OBJECT (evaspixmapsink,"X reports %dx%d pixels and %d mm x %d mm", xcontext->width, xcontext->height, xcontext->widthmm, xcontext->heightmm);
2360 gst_evaspixmapsink_calculate_pixel_aspect_ratio (xcontext);
2361 /* We get supported pixmap formats at supported depth */
2362 px_formats = XListPixmapFormats (xcontext->disp, &nb_formats);
2365 XCloseDisplay (xcontext->disp);
2366 g_mutex_unlock (evaspixmapsink->x_lock);
2367 g_free (xcontext->par);
2369 GST_ELEMENT_ERROR (evaspixmapsink, RESOURCE, SETTINGS,
2370 ("Could not initialise Xv output"), ("Could not get pixel formats"));
2374 /* We get bpp value corresponding to our running depth */
2375 for (i = 0; i < nb_formats; i++) {
2376 if (px_formats[i].depth == xcontext->depth)
2377 xcontext->bpp = px_formats[i].bits_per_pixel;
2382 xcontext->endianness = (ImageByteOrder (xcontext->disp) == LSBFirst) ? G_LITTLE_ENDIAN : G_BIG_ENDIAN;
2384 /* our caps system handles 24/32bpp RGB as big-endian. */
2385 if ((xcontext->bpp == 24 || xcontext->bpp == 32) && xcontext->endianness == G_LITTLE_ENDIAN) {
2386 xcontext->endianness = G_BIG_ENDIAN;
2387 xcontext->visual->red_mask = GUINT32_TO_BE (xcontext->visual->red_mask);
2388 xcontext->visual->green_mask = GUINT32_TO_BE (xcontext->visual->green_mask);
2389 xcontext->visual->blue_mask = GUINT32_TO_BE (xcontext->visual->blue_mask);
2390 if (xcontext->bpp == 24) {
2391 xcontext->visual->red_mask >>= 8;
2392 xcontext->visual->green_mask >>= 8;
2393 xcontext->visual->blue_mask >>= 8;
2397 xcontext->caps = gst_evaspixmapsink_get_xv_support (evaspixmapsink, xcontext);
2399 if (!xcontext->caps) {
2400 XCloseDisplay (xcontext->disp);
2401 g_mutex_unlock (evaspixmapsink->x_lock);
2402 g_free (xcontext->par);
2404 /* GST_ELEMENT_ERROR is thrown by gst_evaspixmapsink_get_xv_support */
2408 /* Search for XShm extension support */
2409 if (XShmQueryExtension (xcontext->disp) && gst_evaspixmapsink_check_xshm_calls (xcontext)) {
2410 xcontext->use_xshm = TRUE;
2411 GST_DEBUG_OBJECT (evaspixmapsink,"evaspixmapsink is using XShm extension");
2413 #endif /* HAVE_XSHM */
2415 xcontext->use_xshm = FALSE;
2416 GST_DEBUG_OBJECT (evaspixmapsink,"evaspixmapsink is not using XShm extension");
2419 xv_attr = XvQueryPortAttributes (xcontext->disp, xcontext->xv_port_id, &N_attr);
2421 /* Generate the channels list */
2422 for (i = 0; i < (sizeof (channels) / sizeof (char *)); i++) {
2423 XvAttribute *matching_attr = NULL;
2425 /* Retrieve the property atom if it exists. If it doesn't exist,
2426 * the attribute itself must not either, so we can skip */
2427 prop_atom = XInternAtom (xcontext->disp, channels[i], True);
2428 if (prop_atom == None) {
2432 if (xv_attr != NULL) {
2433 for (j = 0; j < N_attr && matching_attr == NULL; ++j) {
2434 if (!g_ascii_strcasecmp (channels[i], xv_attr[j].name)) {
2435 matching_attr = xv_attr + j;
2440 if (matching_attr) {
2441 GstColorBalanceChannel *channel;
2442 channel = g_object_new (GST_TYPE_COLOR_BALANCE_CHANNEL, NULL);
2443 channel->label = g_strdup (channels[i]);
2444 channel->min_value = matching_attr->min_value;
2445 channel->max_value = matching_attr->max_value;
2447 xcontext->channels_list = g_list_append (xcontext->channels_list, channel);
2449 /* If the colorbalance settings have not been touched we get Xv values
2450 as defaults and update our internal variables */
2451 if (!evaspixmapsink->cb_changed) {
2453 XvGetPortAttribute (xcontext->disp, xcontext->xv_port_id, prop_atom, &val);
2454 /* Normalize val to [-1000, 1000] */
2455 val = floor (0.5 + -1000 + 2000 * (val - channel->min_value) / (double) (channel->max_value - channel->min_value));
2457 if (!g_ascii_strcasecmp (channels[i], "XV_HUE")) {
2458 evaspixmapsink->hue = val;
2459 } else if (!g_ascii_strcasecmp (channels[i], "XV_SATURATION")) {
2460 evaspixmapsink->saturation = val;
2461 } else if (!g_ascii_strcasecmp (channels[i], "XV_BRIGHTNESS")) {
2462 evaspixmapsink->brightness = val;
2463 } else if (!g_ascii_strcasecmp (channels[i], "XV_CONTRAST")) {
2464 evaspixmapsink->contrast = val;
2474 g_mutex_unlock (evaspixmapsink->x_lock);
2479 /* This function cleans the X context. Closing the Display, releasing the XV
2480 port and unrefing the caps for supported formats. */
2482 gst_evaspixmapsink_xcontext_clear (GstEvasPixmapSink *evaspixmapsink)
2484 GList *formats_list, *channels_list;
2485 GstXContext *xcontext;
2488 g_return_if_fail (GST_IS_EVASPIXMAPSINK (evaspixmapsink));
2490 GST_OBJECT_LOCK (evaspixmapsink);
2491 if (evaspixmapsink->xcontext == NULL) {
2492 GST_OBJECT_UNLOCK (evaspixmapsink);
2496 /* Take the XContext from the sink and clean it up */
2497 xcontext = evaspixmapsink->xcontext;
2498 evaspixmapsink->xcontext = NULL;
2500 GST_OBJECT_UNLOCK (evaspixmapsink);
2502 formats_list = xcontext->formats_list;
2504 while (formats_list) {
2505 GstEvasPixmapFormat *format = formats_list->data;
2507 gst_caps_unref (format->caps);
2509 formats_list = g_list_next (formats_list);
2512 if (xcontext->formats_list)
2513 g_list_free (xcontext->formats_list);
2515 channels_list = xcontext->channels_list;
2517 while (channels_list) {
2518 GstColorBalanceChannel *channel = channels_list->data;
2520 g_object_unref (channel);
2521 channels_list = g_list_next (channels_list);
2524 if (xcontext->channels_list)
2525 g_list_free (xcontext->channels_list);
2527 gst_caps_unref (xcontext->caps);
2529 for (i = 0; i < xcontext->nb_adaptors; i++) {
2530 g_free (xcontext->adaptors[i]);
2533 g_free (xcontext->adaptors);
2535 g_free (xcontext->par);
2537 g_mutex_lock (evaspixmapsink->x_lock);
2539 GST_DEBUG_OBJECT (evaspixmapsink,"Closing display and freeing X Context");
2541 XvUngrabPort (xcontext->disp, xcontext->xv_port_id, 0);
2543 XCloseDisplay (xcontext->disp);
2545 g_mutex_unlock (evaspixmapsink->x_lock);
2552 /* This function tries to get a format matching with a given caps in the
2553 supported list of formats we generated in gst_evaspixmapsink_get_xv_support */
2555 gst_evaspixmapsink_get_format_from_caps (GstEvasPixmapSink *evaspixmapsink, GstCaps *caps)
2559 g_return_val_if_fail (GST_IS_EVASPIXMAPSINK (evaspixmapsink), 0);
2561 list = evaspixmapsink->xcontext->formats_list;
2564 GstEvasPixmapFormat *format = list->data;
2567 if (gst_caps_can_intersect (caps, format->caps)) {
2568 return format->format;
2571 list = g_list_next (list);
2578 gst_evaspixmapsink_getcaps (GstBaseSink *bsink)
2580 GstEvasPixmapSink *evaspixmapsink;
2582 evaspixmapsink = GST_EVASPIXMAPSINK (bsink);
2584 if (evaspixmapsink->xcontext)
2585 return gst_caps_ref (evaspixmapsink->xcontext->caps);
2588 gst_caps_copy (gst_pad_get_pad_template_caps (GST_VIDEO_SINK_PAD
2593 gst_evaspixmapsink_setcaps (GstBaseSink *bsink, GstCaps *caps)
2595 GstEvasPixmapSink *evaspixmapsink;
2596 GstStructure *structure;
2597 guint32 im_format = 0;
2599 gint video_width, video_height;
2600 gint disp_x, disp_y;
2601 gint disp_width, disp_height;
2602 gint video_par_n, video_par_d; /* video's PAR */
2603 gint display_par_n, display_par_d; /* display's PAR */
2604 const GValue *caps_par;
2605 const GValue *caps_disp_reg;
2608 gboolean enable_last_buffer;
2610 evaspixmapsink = GST_EVASPIXMAPSINK (bsink);
2612 GST_DEBUG_OBJECT (evaspixmapsink,"In setcaps. Possible caps %" GST_PTR_FORMAT ", setting caps %" GST_PTR_FORMAT, evaspixmapsink->xcontext->caps, caps);
2614 if (!gst_caps_can_intersect (evaspixmapsink->xcontext->caps, caps)) {
2615 goto incompatible_caps;
2618 structure = gst_caps_get_structure (caps, 0);
2619 ret = gst_structure_get_int (structure, "width", &video_width);
2620 ret &= gst_structure_get_int (structure, "height", &video_height);
2621 fps = gst_structure_get_value (structure, "framerate");
2622 ret &= (fps != NULL);
2625 goto incomplete_caps;
2628 evaspixmapsink->aligned_width = video_width;
2629 evaspixmapsink->aligned_height = video_height;
2631 /* get enable-last-buffer */
2632 g_object_get(G_OBJECT(evaspixmapsink), "enable-last-buffer", &enable_last_buffer, NULL);
2633 GST_INFO_OBJECT (evaspixmapsink,"current enable-last-buffer : %d", enable_last_buffer);
2634 /* flush if enable-last-buffer is TRUE */
2635 if (enable_last_buffer) {
2636 GST_INFO_OBJECT (evaspixmapsink,"flush last-buffer");
2637 g_object_set(G_OBJECT(evaspixmapsink), "enable-last-buffer", FALSE, NULL);
2638 g_object_set(G_OBJECT(evaspixmapsink), "enable-last-buffer", TRUE, NULL);
2641 evaspixmapsink->fps_n = gst_value_get_fraction_numerator (fps);
2642 evaspixmapsink->fps_d = gst_value_get_fraction_denominator (fps);
2644 evaspixmapsink->video_width = video_width;
2645 evaspixmapsink->video_height = video_height;
2647 im_format = gst_evaspixmapsink_get_format_from_caps (evaspixmapsink, caps);
2648 if (im_format == -1) {
2649 goto invalid_format;
2652 /* get aspect ratio from caps if it's present, and
2653 * convert video width and height to a display width and height
2654 * using wd / hd = wv / hv * PARv / PARd */
2656 /* get video's PAR */
2657 caps_par = gst_structure_get_value (structure, "pixel-aspect-ratio");
2659 video_par_n = gst_value_get_fraction_numerator (caps_par);
2660 video_par_d = gst_value_get_fraction_denominator (caps_par);
2665 /* get display's PAR */
2666 if (evaspixmapsink->par) {
2667 display_par_n = gst_value_get_fraction_numerator (evaspixmapsink->par);
2668 display_par_d = gst_value_get_fraction_denominator (evaspixmapsink->par);
2674 /* get the display region */
2675 caps_disp_reg = gst_structure_get_value (structure, "display-region");
2676 if (caps_disp_reg) {
2677 disp_x = g_value_get_int (gst_value_array_get_value (caps_disp_reg, 0));
2678 disp_y = g_value_get_int (gst_value_array_get_value (caps_disp_reg, 1));
2679 disp_width = g_value_get_int (gst_value_array_get_value (caps_disp_reg, 2));
2680 disp_height = g_value_get_int (gst_value_array_get_value (caps_disp_reg, 3));
2682 disp_x = disp_y = 0;
2683 disp_width = video_width;
2684 disp_height = video_height;
2687 if (!gst_video_calculate_display_ratio (&num, &den, video_width, video_height, video_par_n, video_par_d, display_par_n, display_par_d)) {
2691 evaspixmapsink->disp_x = disp_x;
2692 evaspixmapsink->disp_y = disp_y;
2693 evaspixmapsink->disp_width = disp_width;
2694 evaspixmapsink->disp_height = disp_height;
2696 GST_DEBUG_OBJECT (evaspixmapsink,"video width/height: %dx%d, calculated display ratio: %d/%d", video_width, video_height, num, den);
2698 /* now find a width x height that respects this display ratio.
2699 * prefer those that have one of w/h the same as the incoming video
2700 * using wd / hd = num / den */
2702 /* start with same height, because of interlaced video */
2703 /* check hd / den is an integer scale factor, and scale wd with the PAR */
2704 if (video_height % den == 0) {
2705 GST_DEBUG_OBJECT (evaspixmapsink,"keeping video height");
2706 GST_VIDEO_SINK_WIDTH (evaspixmapsink) = (guint) gst_util_uint64_scale_int (video_height, num, den);
2707 GST_VIDEO_SINK_HEIGHT (evaspixmapsink) = video_height;
2708 } else if (video_width % num == 0) {
2709 GST_DEBUG_OBJECT (evaspixmapsink,"keeping video width");
2710 GST_VIDEO_SINK_WIDTH (evaspixmapsink) = video_width;
2711 GST_VIDEO_SINK_HEIGHT (evaspixmapsink) = (guint) gst_util_uint64_scale_int (video_width, den, num);
2713 GST_DEBUG_OBJECT (evaspixmapsink,"approximating while keeping video height");
2714 GST_VIDEO_SINK_WIDTH (evaspixmapsink) = (guint) gst_util_uint64_scale_int (video_height, num, den);
2715 GST_VIDEO_SINK_HEIGHT (evaspixmapsink) = video_height;
2717 GST_DEBUG_OBJECT (evaspixmapsink,"scaling to %dx%d", GST_VIDEO_SINK_WIDTH (evaspixmapsink), GST_VIDEO_SINK_HEIGHT (evaspixmapsink));
2719 /* Creating our window and our image with the display size in pixels */
2720 if (GST_VIDEO_SINK_WIDTH (evaspixmapsink) <= 0 || GST_VIDEO_SINK_HEIGHT (evaspixmapsink) <= 0) {
2721 goto no_display_size;
2724 g_mutex_lock (evaspixmapsink->flow_lock);
2726 /* We renew our evaspixmap buffer only if size or format changed;
2727 * the evaspixmap buffer is the same size as the video pixel size */
2728 if ((evaspixmapsink->evas_pixmap_buf) && ((im_format != evaspixmapsink->evas_pixmap_buf->im_format)
2729 || (video_width != evaspixmapsink->evas_pixmap_buf->width) || (video_height != evaspixmapsink->evas_pixmap_buf->height))) {
2730 GST_DEBUG_OBJECT (evaspixmapsink,"old format %" GST_FOURCC_FORMAT ", new format %" GST_FOURCC_FORMAT,
2731 GST_FOURCC_ARGS (evaspixmapsink->evas_pixmap_buf->im_format), GST_FOURCC_ARGS (im_format));
2732 GST_DEBUG_OBJECT (evaspixmapsink,"renewing evaspixmap buffer");
2733 gst_buffer_unref (GST_BUFFER (evaspixmapsink->evas_pixmap_buf));
2734 evaspixmapsink->evas_pixmap_buf = NULL;
2737 g_mutex_unlock (evaspixmapsink->flow_lock);
2739 if (evaspixmapsink->eo) {
2740 if (!gst_evaspixmapsink_xpixmap_link (evaspixmapsink)) {
2741 GST_ERROR_OBJECT (evaspixmapsink,"link evas image object with pixmap failed...");
2744 gst_evaspixmapsink_manage_event_thread (evaspixmapsink);
2747 GST_ERROR_OBJECT (evaspixmapsink,"setcaps success, but there is no evas image object..");
2756 GST_ERROR_OBJECT (evaspixmapsink,"caps incompatible");
2761 GST_DEBUG_OBJECT (evaspixmapsink,"Failed to retrieve either width, ""height or framerate from intersected caps");
2766 GST_DEBUG_OBJECT (evaspixmapsink,"Could not locate image format from caps %" GST_PTR_FORMAT, caps);
2771 GST_ELEMENT_ERROR (evaspixmapsink, CORE, NEGOTIATION, (NULL), ("Error calculating the output display ratio of the video."));
2776 GST_ELEMENT_ERROR (evaspixmapsink, CORE, NEGOTIATION, (NULL), ("Error calculating the output display ratio of the video."));
2781 static GstStateChangeReturn
2782 gst_evaspixmapsink_change_state (GstElement *element, GstStateChange transition)
2784 GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
2785 GstEvasPixmapSink *evaspixmapsink;
2787 evaspixmapsink = GST_EVASPIXMAPSINK (element);
2789 switch (transition) {
2790 case GST_STATE_CHANGE_NULL_TO_READY:
2791 g_mutex_lock (evaspixmapsink->flow_lock);
2792 GST_WARNING_OBJECT (evaspixmapsink,"GST_STATE_CHANGE_NULL_TO_READY");
2794 /* open drm to use gem */
2795 if (drm_init(evaspixmapsink)) {
2796 GST_ERROR_OBJECT (evaspixmapsink,"drm_init() failure");
2797 g_mutex_unlock (evaspixmapsink->flow_lock);
2798 return GST_STATE_CHANGE_FAILURE;
2801 /* check if there exist evas image object, need to write code related to making internal evas image object */
2802 if (!is_evas_image_object (evaspixmapsink->eo)) {
2803 GST_ERROR_OBJECT (evaspixmapsink,"There is no evas image object..");
2804 g_mutex_unlock (evaspixmapsink->flow_lock);
2805 return GST_STATE_CHANGE_FAILURE;
2808 /* Set xcontext and display */
2809 if (!evaspixmapsink->xcontext) {
2810 evaspixmapsink->xcontext = gst_evaspixmapsink_xcontext_get (evaspixmapsink);
2811 if (!evaspixmapsink->xcontext) {
2812 GST_ERROR_OBJECT (evaspixmapsink,"could not get xcontext..");
2813 g_mutex_unlock (evaspixmapsink->flow_lock);
2814 return GST_STATE_CHANGE_FAILURE;
2818 /* update object's par with calculated one if not set yet */
2819 if (!evaspixmapsink->par) {
2820 evaspixmapsink->par = g_new0 (GValue, 1);
2821 gst_value_init_and_copy (evaspixmapsink->par, evaspixmapsink->xcontext->par);
2822 GST_DEBUG_OBJECT (evaspixmapsink,"set calculated PAR on object's PAR");
2825 /* call XSynchronize with the current value of synchronous */
2826 GST_DEBUG_OBJECT (evaspixmapsink,"XSynchronize called with %s", evaspixmapsink->synchronous ? "TRUE" : "FALSE");
2827 XSynchronize (evaspixmapsink->xcontext->disp, evaspixmapsink->synchronous);
2828 gst_evaspixmapsink_update_colorbalance (evaspixmapsink);
2830 g_mutex_unlock (evaspixmapsink->flow_lock);
2833 case GST_STATE_CHANGE_READY_TO_PAUSED:
2834 GST_WARNING_OBJECT (evaspixmapsink,"GST_STATE_CHANGE_READY_TO_PAUSED");
2837 case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
2838 GST_WARNING_OBJECT (evaspixmapsink,"GST_STATE_CHANGE_PAUSED_TO_PLAYING");
2845 ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
2847 switch (transition) {
2848 case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
2849 GST_WARNING_OBJECT (evaspixmapsink,"GST_STATE_CHANGE_PLAYING_TO_PAUSED");
2852 case GST_STATE_CHANGE_PAUSED_TO_READY:
2853 GST_WARNING_OBJECT (evaspixmapsink,"GST_STATE_CHANGE_PAUSED_TO_READY");
2854 evaspixmapsink->fps_n = 0;
2855 evaspixmapsink->fps_d = 1;
2856 GST_VIDEO_SINK_WIDTH (evaspixmapsink) = 0;
2857 GST_VIDEO_SINK_HEIGHT (evaspixmapsink) = 0;
2858 drm_fini_close_gem_handle(evaspixmapsink, 0);
2861 case GST_STATE_CHANGE_READY_TO_NULL:
2862 GST_WARNING_OBJECT (evaspixmapsink,"GST_STATE_CHANGE_READY_TO_NULL");
2863 gst_evaspixmapsink_reset(evaspixmapsink);
2865 drm_fini(evaspixmapsink);
2875 gst_evaspixmapsink_get_times (GstBaseSink *bsink, GstBuffer *buf, GstClockTime *start, GstClockTime *end)
2877 GstEvasPixmapSink *evaspixmapsink;
2879 evaspixmapsink = GST_EVASPIXMAPSINK (bsink);
2881 if (GST_BUFFER_TIMESTAMP_IS_VALID (buf)) {
2882 *start = GST_BUFFER_TIMESTAMP (buf);
2883 if (GST_BUFFER_DURATION_IS_VALID (buf)) {
2884 *end = *start + GST_BUFFER_DURATION (buf);
2886 if (evaspixmapsink->fps_n > 0) {
2888 gst_util_uint64_scale_int (GST_SECOND, evaspixmapsink->fps_d,
2889 evaspixmapsink->fps_n);
2895 static GstFlowReturn
2896 gst_evaspixmapsink_show_frame (GstVideoSink *vsink, GstBuffer *buf)
2898 GstEvasPixmapSink *evaspixmapsink;
2899 XV_DATA_PTR img_data = NULL;
2900 SCMN_IMGB *scmn_imgb = NULL;
2903 MMTA_ACUM_ITEM_BEGIN("evaspixmapsink gst_evaspixmapsink_show_frame()", FALSE);
2905 evaspixmapsink = GST_EVASPIXMAPSINK (vsink);
2907 if( evaspixmapsink->stop_video ) {
2908 GST_INFO_OBJECT (evaspixmapsink, "Stop video is TRUE. so skip show frame..." );
2912 if (!evaspixmapsink->evas_pixmap_buf) {
2913 GST_DEBUG_OBJECT (evaspixmapsink,"creating our evaspixmap buffer");
2914 format = gst_evaspixmapsink_get_format_from_caps(evaspixmapsink, GST_BUFFER_CAPS(buf));
2916 case GST_MAKE_FOURCC('S', 'T', '1', '2'):
2917 case GST_MAKE_FOURCC('S', 'N', '1', '2'):
2918 case GST_MAKE_FOURCC('S', '4', '2', '0'):
2919 case GST_MAKE_FOURCC('S', 'U', 'Y', '2'):
2920 case GST_MAKE_FOURCC('S', 'U', 'Y', 'V'):
2921 case GST_MAKE_FOURCC('S', 'Y', 'V', 'Y'):
2922 case GST_MAKE_FOURCC('I', 'T', 'L', 'V'):
2923 case GST_MAKE_FOURCC('S', 'R', '3', '2'):
2924 scmn_imgb = (SCMN_IMGB *)GST_BUFFER_MALLOCDATA(buf);
2925 if(scmn_imgb == NULL) {
2926 GST_DEBUG_OBJECT (evaspixmapsink, "scmn_imgb is NULL. Skip buffer put..." );
2929 /* skip buffer if aligned size is smaller than size of caps */
2930 if (scmn_imgb->s[0] < evaspixmapsink->video_width || scmn_imgb->e[0] < evaspixmapsink->video_height) {
2931 GST_WARNING_OBJECT (evaspixmapsink,"invalid size[caps:%dx%d,aligned:%dx%d]. Skip this buffer...",
2932 evaspixmapsink->video_width, evaspixmapsink->video_height, scmn_imgb->s[0], scmn_imgb->e[0]);
2935 evaspixmapsink->aligned_width = scmn_imgb->s[0];
2936 evaspixmapsink->aligned_height = scmn_imgb->e[0];
2937 GST_DEBUG_OBJECT (evaspixmapsink,"video width,height[%dx%d]",evaspixmapsink->video_width, evaspixmapsink->video_height);
2938 GST_INFO_OBJECT (evaspixmapsink,"Use aligned width,height[%dx%d]",evaspixmapsink->aligned_width, evaspixmapsink->aligned_height);
2941 GST_INFO_OBJECT (evaspixmapsink,"Use original width,height of caps");
2944 evaspixmapsink->evas_pixmap_buf = gst_evaspixmap_buffer_new (evaspixmapsink, GST_BUFFER_CAPS (buf));
2945 if (!evaspixmapsink->evas_pixmap_buf) {
2946 /* The create method should have posted an informative error */
2949 if (evaspixmapsink->evas_pixmap_buf->size < GST_BUFFER_SIZE (buf)) {
2950 GST_ELEMENT_ERROR (evaspixmapsink, RESOURCE, WRITE, ("Failed to create output image buffer of %dx%d pixels", evaspixmapsink->evas_pixmap_buf->width, evaspixmapsink->evas_pixmap_buf->height),("XServer allocated buffer size did not match input buffer"));
2951 gst_evaspixmap_buffer_destroy (evaspixmapsink->evas_pixmap_buf);
2952 evaspixmapsink->evas_pixmap_buf = NULL;
2957 switch (evaspixmapsink->evas_pixmap_buf->im_format) {
2958 /* Cases for specified formats of Samsung extension */
2959 case GST_MAKE_FOURCC('S', 'T', '1', '2'):
2960 case GST_MAKE_FOURCC('S', 'N', '1', '2'):
2961 case GST_MAKE_FOURCC('S', '4', '2', '0'):
2962 case GST_MAKE_FOURCC('S', 'U', 'Y', '2'):
2963 case GST_MAKE_FOURCC('S', 'U', 'Y', 'V'):
2964 case GST_MAKE_FOURCC('S', 'Y', 'V', 'Y'):
2965 case GST_MAKE_FOURCC('I', 'T', 'L', 'V'):
2966 case GST_MAKE_FOURCC('S', 'R', '3', '2'):
2968 GST_DEBUG_OBJECT (evaspixmapsink,"Samsung extension display format activated. fourcc:%d", evaspixmapsink->evas_pixmap_buf->im_format);
2970 if (evaspixmapsink->evas_pixmap_buf->xvimage->data) {
2971 img_data = (XV_DATA_PTR) evaspixmapsink->evas_pixmap_buf->xvimage->data;
2972 XV_INIT_DATA(img_data);
2973 scmn_imgb = (SCMN_IMGB *)GST_BUFFER_MALLOCDATA(buf);
2974 if (scmn_imgb == NULL) {
2975 GST_DEBUG_OBJECT (evaspixmapsink, "scmn_imgb is NULL. Skip buffer put..." );
2979 if (scmn_imgb->buf_share_method == BUF_SHARE_METHOD_PADDR) {
2980 img_data->YBuf = (unsigned int)scmn_imgb->p[0];
2981 img_data->CbBuf = (unsigned int)scmn_imgb->p[1];
2982 img_data->CrBuf = (unsigned int)scmn_imgb->p[2];
2983 img_data->BufType = XV_BUF_TYPE_LEGACY;
2985 } else if (scmn_imgb->buf_share_method == BUF_SHARE_METHOD_FD) {
2986 /* set gem information to gem_info structure of handle and convert dma-buf fd into drm gem name */
2987 img_data->YBuf = drm_init_convert_dmabuf_gemname(evaspixmapsink, (int)scmn_imgb->dma_buf_fd[0]);
2988 img_data->CbBuf = drm_init_convert_dmabuf_gemname(evaspixmapsink, (int)scmn_imgb->dma_buf_fd[1]);
2989 img_data->CrBuf = drm_init_convert_dmabuf_gemname(evaspixmapsink, (int)scmn_imgb->dma_buf_fd[2]);
2990 img_data->BufType = XV_BUF_TYPE_DMABUF;
2991 if (evaspixmapsink->buf_shared_type != BUF_SHARE_METHOD_FD) {
2992 evaspixmapsink->buf_shared_type = BUF_SHARE_METHOD_FD;
2993 GST_WARNING_OBJECT (evaspixmapsink, "BUF SHARED TYPE : FD");
2996 } else if (scmn_imgb->buf_share_method == BUF_SHARE_METHOD_TIZEN_BUFFER) {
2997 img_data->bo[0] = scmn_imgb->bo[0];
2998 img_data->bo[1] = scmn_imgb->bo[1];
2999 img_data->bo[2] = scmn_imgb->bo[2];
3000 GST_DEBUG("TBM bo %p %p %p", img_data->bo[0], img_data->bo[1], img_data->bo[2]);
3002 if (img_data->bo[0]) {
3003 img_data->YBuf = tbm_init_convert_bo_gemname(evaspixmapsink, img_data->bo[0]);
3005 if (img_data->bo[1]) {
3006 img_data->CbBuf = tbm_init_convert_bo_gemname(evaspixmapsink, img_data->bo[1]);
3008 if (img_data->bo[2]) {
3009 img_data->CrBuf = tbm_init_convert_bo_gemname(evaspixmapsink, img_data->bo[2]);
3011 if (evaspixmapsink->buf_shared_type != BUF_SHARE_METHOD_TIZEN_BUFFER) {
3012 evaspixmapsink->buf_shared_type = BUF_SHARE_METHOD_TIZEN_BUFFER;
3013 GST_WARNING_OBJECT (evaspixmapsink, "BUF SHARED TYPE : TIZEN BUFFER");
3016 GST_WARNING_OBJECT (evaspixmapsink, "Not supported, buf_share_method(%d)", scmn_imgb->buf_share_method);
3019 if (!img_data->YBuf) {
3020 GST_WARNING_OBJECT (evaspixmapsink, "img_data->YBuf is NULL. skip buffer put..." );
3023 GST_LOG_OBJECT(evaspixmapsink, "YBuf[%d], CbBuf[%d], CrBuf[%d]",
3024 img_data->YBuf, img_data->CbBuf, img_data->CrBuf );
3026 GST_WARNING_OBJECT (evaspixmapsink, "xvimage->data is NULL. skip buffer put..." );
3033 if (evaspixmapsink->buf_shared_type != BUF_SHARE_METHOD_NONE) {
3034 evaspixmapsink->buf_shared_type = BUF_SHARE_METHOD_NONE;
3036 GST_DEBUG_OBJECT (evaspixmapsink,"Normal format activated. fourcc = %d", evaspixmapsink->evas_pixmap_buf->im_format);
3037 __ta__("evaspixmapsink memcpy in _show_frame", memcpy (evaspixmapsink->evas_pixmap_buf->xvimage->data, GST_BUFFER_DATA (buf),
3038 MIN (GST_BUFFER_SIZE (buf), evaspixmapsink->evas_pixmap_buf->size)););
3042 if (!gst_evaspixmap_buffer_put (evaspixmapsink, evaspixmapsink->evas_pixmap_buf)) {
3043 MMTA_ACUM_ITEM_END("evaspixmapsink gst_evaspixmapsink_show_frame()", FALSE);
3047 MMTA_ACUM_ITEM_END("evaspixmapsink gst_evaspixmapsink_show_frame()", FALSE);
3054 /* No image available. That's very bad ! */
3055 GST_WARNING_OBJECT (evaspixmapsink,"could not create image");
3056 return GST_FLOW_ERROR;
3061 gst_evaspixmapsink_event (GstBaseSink *sink, GstEvent *event)
3063 GstEvasPixmapSink *evaspixmapsink = GST_EVASPIXMAPSINK (sink);
3065 switch (GST_EVENT_TYPE (event)) {
3066 case GST_EVENT_FLUSH_START:
3067 GST_DEBUG_OBJECT (evaspixmapsink,"GST_EVENT_FLUSH_START");
3069 case GST_EVENT_FLUSH_STOP:
3070 GST_DEBUG_OBJECT (evaspixmapsink,"GST_EVENT_FLUSH_STOP");
3075 if (GST_BASE_SINK_CLASS (parent_class)->event) {
3076 return GST_BASE_SINK_CLASS (parent_class)->event (sink, event);
3082 /* Interfaces stuff */
3085 gst_evaspixmapsink_interface_supported (GstImplementsInterface *iface, GType type)
3087 g_assert (type == GST_TYPE_NAVIGATION || type == GST_TYPE_COLOR_BALANCE || type == GST_TYPE_PROPERTY_PROBE);
3092 gst_evaspixmapsink_interface_init (GstImplementsInterfaceClass *klass)
3094 klass->supported = gst_evaspixmapsink_interface_supported;
3098 gst_evaspixmapsink_navigation_send_event (GstNavigation *navigation, GstStructure *structure)
3100 GstEvasPixmapSink *evaspixmapsink = GST_EVASPIXMAPSINK (navigation);
3104 if ((peer = gst_pad_get_peer (GST_VIDEO_SINK_PAD (evaspixmapsink)))) {
3106 GstVideoRectangle result;
3107 gdouble x, y, xscale = 1.0, yscale = 1.0;
3109 event = gst_event_new_navigation (structure);
3111 /* We take the flow_lock while we look at the window */
3112 g_mutex_lock (evaspixmapsink->flow_lock);
3114 for (i = 0; i < evaspixmapsink->num_of_pixmaps; i ++) {
3115 if (!evaspixmapsink->xpixmap[i]) {
3116 g_mutex_unlock (evaspixmapsink->flow_lock);
3121 memcpy (&result, &evaspixmapsink->render_rect, sizeof (GstVideoRectangle));
3123 g_mutex_unlock (evaspixmapsink->flow_lock);
3125 /* We calculate scaling using the original video frames geometry to include
3126 pixel aspect ratio scaling. */
3127 xscale = (gdouble) evaspixmapsink->video_width / result.w;
3128 yscale = (gdouble) evaspixmapsink->video_height / result.h;
3130 /* Converting pointer coordinates to the non scaled geometry */
3131 if (gst_structure_get_double (structure, "pointer_x", &x)) {
3132 x = MIN (x, result.x + result.w);
3133 x = MAX (x - result.x, 0);
3134 gst_structure_set (structure, "pointer_x", G_TYPE_DOUBLE,
3135 (gdouble) x * xscale, NULL);
3137 if (gst_structure_get_double (structure, "pointer_y", &y)) {
3138 y = MIN (y, result.y + result.h);
3139 y = MAX (y - result.y, 0);
3140 gst_structure_set (structure, "pointer_y", G_TYPE_DOUBLE,
3141 (gdouble) y * yscale, NULL);
3144 gst_pad_send_event (peer, event);
3145 gst_object_unref (peer);
3150 gst_evaspixmapsink_navigation_init (GstNavigationInterface *iface)
3152 iface->send_event = gst_evaspixmapsink_navigation_send_event;
3156 gst_evaspixmapsink_colorbalance_list_channels (GstColorBalance *balance)
3158 GstEvasPixmapSink *evaspixmapsink = GST_EVASPIXMAPSINK (balance);
3160 g_return_val_if_fail (GST_IS_EVASPIXMAPSINK (evaspixmapsink), NULL);
3162 if (evaspixmapsink->xcontext)
3163 return evaspixmapsink->xcontext->channels_list;
3169 gst_evaspixmapsink_colorbalance_set_value (GstColorBalance *balance, GstColorBalanceChannel *channel, gint value)
3171 GstEvasPixmapSink *evaspixmapsink = GST_EVASPIXMAPSINK (balance);
3173 g_return_if_fail (GST_IS_EVASPIXMAPSINK (evaspixmapsink));
3174 g_return_if_fail (channel->label != NULL);
3176 evaspixmapsink->cb_changed = TRUE;
3178 /* Normalize val to [-1000, 1000] */
3179 value = floor (0.5 + -1000 + 2000 * (value - channel->min_value) /
3180 (double) (channel->max_value - channel->min_value));
3182 if (g_ascii_strcasecmp (channel->label, "XV_HUE") == 0) {
3183 evaspixmapsink->hue = value;
3184 } else if (g_ascii_strcasecmp (channel->label, "XV_SATURATION") == 0) {
3185 evaspixmapsink->saturation = value;
3186 } else if (g_ascii_strcasecmp (channel->label, "XV_CONTRAST") == 0) {
3187 evaspixmapsink->contrast = value;
3188 } else if (g_ascii_strcasecmp (channel->label, "XV_BRIGHTNESS") == 0) {
3189 evaspixmapsink->brightness = value;
3191 g_warning ("got an unknown channel %s", channel->label);
3195 gst_evaspixmapsink_update_colorbalance (evaspixmapsink);
3199 gst_evaspixmapsink_colorbalance_get_value (GstColorBalance *balance, GstColorBalanceChannel *channel)
3201 GstEvasPixmapSink *evaspixmapsink = GST_EVASPIXMAPSINK (balance);
3204 g_return_val_if_fail (GST_IS_EVASPIXMAPSINK (evaspixmapsink), 0);
3205 g_return_val_if_fail (channel->label != NULL, 0);
3207 if (g_ascii_strcasecmp (channel->label, "XV_HUE") == 0) {
3208 value = evaspixmapsink->hue;
3209 } else if (g_ascii_strcasecmp (channel->label, "XV_SATURATION") == 0) {
3210 value = evaspixmapsink->saturation;
3211 } else if (g_ascii_strcasecmp (channel->label, "XV_CONTRAST") == 0) {
3212 value = evaspixmapsink->contrast;
3213 } else if (g_ascii_strcasecmp (channel->label, "XV_BRIGHTNESS") == 0) {
3214 value = evaspixmapsink->brightness;
3216 g_warning ("got an unknown channel %s", channel->label);
3219 /* Normalize val to [channel->min_value, channel->max_value] */
3220 value = channel->min_value + (channel->max_value - channel->min_value) * (value + 1000) / 2000;
3226 gst_evaspixmapsink_colorbalance_init (GstColorBalanceClass *iface)
3228 GST_COLOR_BALANCE_TYPE (iface) = GST_COLOR_BALANCE_HARDWARE;
3229 iface->list_channels = gst_evaspixmapsink_colorbalance_list_channels;
3230 iface->set_value = gst_evaspixmapsink_colorbalance_set_value;
3231 iface->get_value = gst_evaspixmapsink_colorbalance_get_value;
3234 static const GList *
3235 gst_evaspixmapsink_probe_get_properties (GstPropertyProbe *probe)
3237 GObjectClass *klass = G_OBJECT_GET_CLASS (probe);
3238 static GList *list = NULL;
3241 list = g_list_append (NULL, g_object_class_find_property (klass, "device"));
3242 list = g_list_append (list, g_object_class_find_property (klass, "autopaint-colorkey"));
3243 list = g_list_append (list, g_object_class_find_property (klass, "double-buffer"));
3244 list = g_list_append (list, g_object_class_find_property (klass, "colorkey"));
3251 gst_evaspixmapsink_probe_probe_property (GstPropertyProbe *probe, guint prop_id, const GParamSpec *pspec)
3253 GstEvasPixmapSink *evaspixmapsink = GST_EVASPIXMAPSINK (probe);
3257 case PROP_AUTOPAINT_COLORKEY:
3258 case PROP_DOUBLE_BUFFER:
3260 GST_DEBUG_OBJECT (evaspixmapsink,"probing device list and get capabilities");
3261 if (!evaspixmapsink->xcontext) {
3262 GST_DEBUG_OBJECT (evaspixmapsink,"generating xcontext");
3263 evaspixmapsink->xcontext = gst_evaspixmapsink_xcontext_get (evaspixmapsink);
3264 if (!evaspixmapsink->xcontext) {
3265 GST_ERROR_OBJECT (evaspixmapsink,"could not get xcontext..");
3270 G_OBJECT_WARN_INVALID_PROPERTY_ID (probe, prop_id, pspec);
3276 gst_evaspixmapsink_probe_needs_probe (GstPropertyProbe *probe, guint prop_id, const GParamSpec *pspec)
3278 GstEvasPixmapSink *evaspixmapsink = GST_EVASPIXMAPSINK (probe);
3279 gboolean ret = FALSE;
3283 case PROP_AUTOPAINT_COLORKEY:
3284 case PROP_DOUBLE_BUFFER:
3286 if (evaspixmapsink->xcontext != NULL) {
3293 G_OBJECT_WARN_INVALID_PROPERTY_ID (probe, prop_id, pspec);
3300 static GValueArray *
3301 gst_evaspixmapsink_probe_get_values (GstPropertyProbe *probe, guint prop_id, const GParamSpec *pspec)
3303 GstEvasPixmapSink *evaspixmapsink = GST_EVASPIXMAPSINK (probe);
3304 GValueArray *array = NULL;
3306 if (G_UNLIKELY (!evaspixmapsink->xcontext)) {
3307 GST_WARNING_OBJECT (evaspixmapsink,"we don't have any xcontext, can't "
3316 GValue value = { 0 };
3318 array = g_value_array_new (evaspixmapsink->xcontext->nb_adaptors);
3319 g_value_init (&value, G_TYPE_STRING);
3321 for (i = 0; i < evaspixmapsink->xcontext->nb_adaptors; i++) {
3322 gchar *adaptor_id_s = g_strdup_printf ("%u", i);
3324 g_value_set_string (&value, adaptor_id_s);
3325 g_value_array_append (array, &value);
3326 g_free (adaptor_id_s);
3328 g_value_unset (&value);
3331 case PROP_AUTOPAINT_COLORKEY:
3332 if (evaspixmapsink->have_autopaint_colorkey) {
3333 GValue value = { 0 };
3335 array = g_value_array_new (2);
3336 g_value_init (&value, G_TYPE_BOOLEAN);
3337 g_value_set_boolean (&value, FALSE);
3338 g_value_array_append (array, &value);
3339 g_value_set_boolean (&value, TRUE);
3340 g_value_array_append (array, &value);
3341 g_value_unset (&value);
3344 case PROP_DOUBLE_BUFFER:
3345 if (evaspixmapsink->have_double_buffer) {
3346 GValue value = { 0 };
3348 array = g_value_array_new (2);
3349 g_value_init (&value, G_TYPE_BOOLEAN);
3350 g_value_set_boolean (&value, FALSE);
3351 g_value_array_append (array, &value);
3352 g_value_set_boolean (&value, TRUE);
3353 g_value_array_append (array, &value);
3354 g_value_unset (&value);
3358 if (evaspixmapsink->have_colorkey) {
3359 GValue value = { 0 };
3361 array = g_value_array_new (1);
3362 g_value_init (&value, GST_TYPE_INT_RANGE);
3363 gst_value_set_int_range (&value, 0, 0xffffff);
3364 g_value_array_append (array, &value);
3365 g_value_unset (&value);
3369 G_OBJECT_WARN_INVALID_PROPERTY_ID (probe, prop_id, pspec);
3378 gst_evaspixmapsink_property_probe_interface_init (GstPropertyProbeInterface *iface)
3380 iface->get_properties = gst_evaspixmapsink_probe_get_properties;
3381 iface->probe_property = gst_evaspixmapsink_probe_probe_property;
3382 iface->needs_probe = gst_evaspixmapsink_probe_needs_probe;
3383 iface->get_values = gst_evaspixmapsink_probe_get_values;
3387 gst_evaspixmapsink_xpixmap_link (GstEvasPixmapSink *evaspixmapsink)
3390 Pixmap *pixmap_id[NUM_OF_PIXMAP];
3391 int evas_object_width = 0;
3392 int evas_object_height = 0;
3393 int pixmap_width = 0;
3394 int pixmap_height = 0;
3395 unsigned int xw = 0;
3396 unsigned int xh = 0;
3399 GST_DEBUG_OBJECT (evaspixmapsink,"[START]");
3401 if (!evaspixmapsink) {
3402 GST_ERROR_OBJECT (evaspixmapsink,"could not get evaspixmapsink..");
3405 g_mutex_lock (evaspixmapsink->flow_lock);
3407 /* Set xcontext and display */
3408 if (!evaspixmapsink->xcontext) {
3409 GST_WARNING_OBJECT (evaspixmapsink,"there's no xcontext, try to get one..");
3410 evaspixmapsink->xcontext = gst_evaspixmapsink_xcontext_get (evaspixmapsink);
3411 if (!evaspixmapsink->xcontext) {
3412 GST_ERROR_OBJECT (evaspixmapsink,"could not get xcontext..");
3417 /* Set evas image object size */
3418 evas_object_geometry_get(evaspixmapsink->eo, NULL, NULL, &evas_object_width, &evas_object_height);
3420 /* check if it is redundant request */
3421 for (i = 0; i < evaspixmapsink->num_of_pixmaps; i++) {
3422 if (evaspixmapsink->xpixmap[i]) {
3423 if (!evaspixmapsink->use_origin_size && evaspixmapsink->xpixmap[i]->width && evaspixmapsink->xpixmap[i]->height) {
3424 if (evaspixmapsink->xpixmap[i]->width == evas_object_width && evaspixmapsink->xpixmap[i]->height == evas_object_height) {
3425 GST_WARNING_OBJECT (evaspixmapsink,"pixmap was already created(w:%d, h:%d), skip it..",
3426 evaspixmapsink->xpixmap[i]->width, evaspixmapsink->xpixmap[i]->height);
3433 dpy = evaspixmapsink->xcontext->disp;
3435 if (evaspixmapsink->use_origin_size || !evas_object_width || !evas_object_height) {
3436 pixmap_width = evaspixmapsink->video_width;
3437 pixmap_height = evaspixmapsink->video_height;
3438 GST_INFO_OBJECT (evaspixmapsink,"set size to media src size(%dx%d)", pixmap_width, pixmap_height);
3441 g_mutex_lock (evaspixmapsink->x_lock);
3442 evaspixmapsink->sizediff_width = 0;
3443 evaspixmapsink->sizediff_height = 0;
3444 if (evaspixmapsink->use_origin_size || !evas_object_width || !evas_object_height) {
3445 XvQueryBestSize(dpy, evaspixmapsink->xcontext->xv_port_id,0,0,0, pixmap_width, pixmap_height, &xw, &xh);
3446 if (!evas_object_width || !evas_object_height) {
3447 evaspixmapsink->w = xw;
3448 evaspixmapsink->h = xh;
3450 evaspixmapsink->w = evas_object_width;
3451 evaspixmapsink->h = evas_object_height;
3453 GST_DEBUG_OBJECT (evaspixmapsink,"XvQueryBestSize : xv_port_id(%d), w(%d),h(%d) => xw(%d),xh(%d)", evaspixmapsink->xcontext->xv_port_id, pixmap_width, pixmap_height, xw, xh);
3455 XvQueryBestSize(dpy, evaspixmapsink->xcontext->xv_port_id,0,0,0, evas_object_width, evas_object_height, &xw, &xh);
3456 GST_DEBUG_OBJECT (evaspixmapsink,"XvQueryBestSize : xv_port_id(%d), w(%d),h(%d) => xw(%d),xh(%d)", evaspixmapsink->xcontext->xv_port_id, evas_object_width, evas_object_height, xw, xh);
3457 evaspixmapsink->w = xw;
3458 evaspixmapsink->h = xh;
3459 /* update difference of size information (between evas image object's and pixmap's) */
3460 evaspixmapsink->sizediff_width = xw - evas_object_width;
3461 evaspixmapsink->sizediff_height = xh - evas_object_height;
3464 /* create xpixmap structure */
3465 for (i = 0; i < evaspixmapsink->num_of_pixmaps; i++) {
3466 if (!evaspixmapsink->xpixmap[i]) {
3467 /* xpixmap can be created in this function only */
3468 evaspixmapsink->xpixmap[i] = g_new0 (GstXPixmap, 1);
3469 if(!evaspixmapsink->xpixmap[i]) {
3470 GST_ERROR_OBJECT (evaspixmapsink,"xpixmap is not valid..");
3472 for (j = 0; j < i; j++) {
3473 g_free(evaspixmapsink->xpixmap[j]);
3475 goto GO_OUT_OF_FUNC;
3482 GST_WARNING_OBJECT (evaspixmapsink,"skip creating pixmap..xw(%d),xh(%d)",xw,xh);
3483 goto GO_OUT_OF_FUNC;
3485 /* multiple pixmaps creation */
3486 for (i = 0; i < evaspixmapsink->num_of_pixmaps; i++) {
3487 pixmap_id[i] = XCreatePixmap(dpy, DefaultRootWindow(dpy), xw, xh, DefaultDepth(dpy, DefaultScreen(dpy)));
3488 if ( (int)pixmap_id[i] == BadAlloc || (int)pixmap_id[i] == BadDrawable || (int)pixmap_id[i] == BadValue ) {
3489 GST_ERROR_OBJECT (evaspixmapsink,"pixmap[%d] allocation error..", i);
3491 for (j = 0; j < i; j++) {
3492 XFreePixmap(dpy, pixmap_id[j]);
3494 goto GO_OUT_OF_FUNC;
3496 GST_INFO_OBJECT (evaspixmapsink,"creation pixmap_id[%d]:%d success", i, pixmap_id[i]);
3497 GST_DEBUG_OBJECT (evaspixmapsink,"evas_object_width(%d),evas_object_height(%d),pixmap:%d,depth:%d",
3498 evas_object_width,evas_object_height,pixmap_id[i],DefaultDepth(dpy, DefaultScreen(dpy)));
3502 for (i = 0; i < evaspixmapsink->num_of_pixmaps; i++) {
3503 if (evaspixmapsink->xpixmap[i]->pixmap && pixmap_id[i] != evaspixmapsink->xpixmap[i]->pixmap) {
3504 g_mutex_unlock (evaspixmapsink->x_lock);
3505 g_mutex_lock (evaspixmapsink->pixmap_ref_lock);
3506 /* If we reset another pixmap, do below */
3507 evaspixmapsink->xpixmap[i]->prev_pixmap = evaspixmapsink->xpixmap[i]->pixmap;
3508 evaspixmapsink->xpixmap[i]->prev_gc = evaspixmapsink->xpixmap[i]->gc;
3509 evaspixmapsink->xpixmap[i]->pixmap = 0;
3510 evaspixmapsink->xpixmap[i]->ref = 0;
3511 evaspixmapsink->xpixmap[i]->damaged_time = 0;
3512 g_mutex_unlock (evaspixmapsink->pixmap_ref_lock);
3513 g_mutex_lock (evaspixmapsink->x_lock);
3517 for (i = 0; i < evaspixmapsink->num_of_pixmaps; i++) {
3518 /* Set pixmap id and create GC */
3519 evaspixmapsink->xpixmap[i]->pixmap = pixmap_id[i];
3520 evaspixmapsink->xpixmap[i]->gc = XCreateGC(dpy, evaspixmapsink->xpixmap[i]->pixmap, 0,0);
3521 evaspixmapsink->xpixmap[i]->width = xw;
3522 evaspixmapsink->xpixmap[i]->height = xh;
3524 /* Create XDamage */
3525 if (evaspixmapsink->damage[i]) {
3526 evaspixmapsink->prev_damage[i] = evaspixmapsink->damage[i];
3528 evaspixmapsink->damage[i] = XDamageCreate (dpy, evaspixmapsink->xpixmap[i]->pixmap, XDamageReportRawRectangles);
3530 GST_WARNING_OBJECT (evaspixmapsink,"xpixmap[%d]->(pixmap:%d,gc:%p), damage[%d]:%d",
3531 i, evaspixmapsink->xpixmap[i]->pixmap, evaspixmapsink->xpixmap[i]->gc, i, evaspixmapsink->damage[i]);
3536 /* Set flag for mapping evas object with xpixmap */
3537 evaspixmapsink->do_link = TRUE;
3538 ecore_pipe_write(evaspixmapsink->epipe, evaspixmapsink, sizeof(GstEvasPixmapSink));
3540 gst_evaspixmapsink_update_colorbalance (evaspixmapsink);
3542 g_mutex_unlock (evaspixmapsink->x_lock);
3546 g_mutex_lock (evaspixmapsink->pixmap_ref_lock);
3547 evaspixmapsink->last_updated_idx = -1;
3548 g_mutex_unlock (evaspixmapsink->pixmap_ref_lock);
3550 g_mutex_unlock (evaspixmapsink->flow_lock);
3552 GST_DEBUG_OBJECT (evaspixmapsink,"[END]");
3557 g_mutex_unlock (evaspixmapsink->x_lock);
3558 g_mutex_unlock (evaspixmapsink->flow_lock);
3563 gst_evaspixmapsink_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
3565 GstEvasPixmapSink *evaspixmapsink;
3566 g_return_if_fail (GST_IS_EVASPIXMAPSINK (object));
3567 evaspixmapsink = GST_EVASPIXMAPSINK (object);
3571 evaspixmapsink->hue = g_value_get_int (value);
3572 evaspixmapsink->cb_changed = TRUE;
3573 gst_evaspixmapsink_update_colorbalance (evaspixmapsink);
3576 evaspixmapsink->contrast = g_value_get_int (value);
3577 evaspixmapsink->cb_changed = TRUE;
3578 gst_evaspixmapsink_update_colorbalance (evaspixmapsink);
3580 case PROP_BRIGHTNESS:
3581 evaspixmapsink->brightness = g_value_get_int (value);
3582 evaspixmapsink->cb_changed = TRUE;
3583 gst_evaspixmapsink_update_colorbalance (evaspixmapsink);
3585 case PROP_SATURATION:
3586 evaspixmapsink->saturation = g_value_get_int (value);
3587 evaspixmapsink->cb_changed = TRUE;
3588 gst_evaspixmapsink_update_colorbalance (evaspixmapsink);
3591 evaspixmapsink->display_name = g_strdup (g_value_get_string (value));
3593 case PROP_SYNCHRONOUS:
3594 evaspixmapsink->synchronous = g_value_get_boolean (value);
3595 if (evaspixmapsink->xcontext) {
3596 XSynchronize (evaspixmapsink->xcontext->disp, evaspixmapsink->synchronous);
3597 GST_DEBUG_OBJECT (evaspixmapsink,"XSynchronize called with %s", evaspixmapsink->synchronous ? "TRUE" : "FALSE");
3600 case PROP_PIXEL_ASPECT_RATIO:
3601 g_free (evaspixmapsink->par);
3602 evaspixmapsink->par = g_new0 (GValue, 1);
3603 g_value_init (evaspixmapsink->par, GST_TYPE_FRACTION);
3604 if (!g_value_transform (value, evaspixmapsink->par)) {
3605 g_warning ("Could not transform string to aspect ratio");
3606 gst_value_set_fraction (evaspixmapsink->par, 1, 1);
3608 GST_DEBUG_OBJECT (evaspixmapsink,"set PAR to %d/%d", gst_value_get_fraction_numerator (evaspixmapsink->par), gst_value_get_fraction_denominator (evaspixmapsink->par));
3611 evaspixmapsink->adaptor_no = atoi (g_value_get_string (value));
3613 case PROP_DOUBLE_BUFFER:
3614 evaspixmapsink->double_buffer = g_value_get_boolean (value);
3616 case PROP_AUTOPAINT_COLORKEY:
3617 evaspixmapsink->autopaint_colorkey = g_value_get_boolean (value);
3620 evaspixmapsink->colorkey = g_value_get_int (value);
3622 case PROP_PIXMAP_WIDTH:
3624 /* To do : code related to pixmap re-link */
3625 GST_LOG_OBJECT (evaspixmapsink, "Not supported");
3628 case PROP_PIXMAP_HEIGHT:
3630 /* To do : code related to pixmap re-link */
3631 GST_LOG_OBJECT (evaspixmapsink, "Not supported");
3634 case PROP_DISPLAY_GEOMETRY_METHOD:
3636 guint new_val = g_value_get_enum (value);
3637 if (evaspixmapsink->display_geometry_method != new_val) {
3638 evaspixmapsink->display_geometry_method = new_val;
3639 GST_INFO_OBJECT (evaspixmapsink,"Overlay geometry method update, display_geometry_method(%d)",evaspixmapsink->display_geometry_method);
3640 if( evaspixmapsink->display_geometry_method != DISP_GEO_METHOD_FULL_SCREEN &&
3641 evaspixmapsink->display_geometry_method != DISP_GEO_METHOD_CROPPED_FULL_SCREEN ) {
3642 if( evaspixmapsink->xcontext ) {
3643 g_mutex_lock( evaspixmapsink->flow_lock );
3645 for (i = 0; i < evaspixmapsink->num_of_pixmaps; i++) {
3646 if (evaspixmapsink->xpixmap[i]) {
3647 gst_evaspixmapsink_xpixmap_clear (evaspixmapsink, evaspixmapsink->xpixmap[i]);
3650 g_mutex_unlock( evaspixmapsink->flow_lock );
3653 if (evaspixmapsink->xcontext) {
3654 gst_evaspixmap_buffer_put (evaspixmapsink, evaspixmapsink->evas_pixmap_buf);
3659 case PROP_DST_ROI_X:
3660 evaspixmapsink->dst_roi.x = g_value_get_int (value);
3661 GST_INFO_OBJECT (evaspixmapsink, "ROI_X(%d)",evaspixmapsink->dst_roi.x );
3663 case PROP_DST_ROI_Y:
3664 evaspixmapsink->dst_roi.y = g_value_get_int (value);
3665 GST_INFO_OBJECT (evaspixmapsink, "ROI_Y(%d)",evaspixmapsink->dst_roi.y );
3667 case PROP_DST_ROI_W:
3668 evaspixmapsink->dst_roi.w = g_value_get_int (value);
3669 GST_INFO_OBJECT (evaspixmapsink, "ROI_W(%d)",evaspixmapsink->dst_roi.w );
3671 case PROP_DST_ROI_H:
3672 evaspixmapsink->dst_roi.h = g_value_get_int (value);
3673 GST_INFO_OBJECT (evaspixmapsink, "ROI_H(%d)",evaspixmapsink->dst_roi.h );
3675 case PROP_STOP_VIDEO:
3676 evaspixmapsink->stop_video = g_value_get_int (value);
3677 g_mutex_lock( evaspixmapsink->flow_lock );
3678 if( evaspixmapsink->stop_video ) {
3679 GST_INFO_OBJECT (evaspixmapsink, "XPixmap CLEAR when set video-stop property" );
3681 for (i = 0; i < evaspixmapsink->num_of_pixmaps; i++) {
3682 if (evaspixmapsink->xpixmap[i]) {
3683 gst_evaspixmapsink_xpixmap_clear (evaspixmapsink, evaspixmapsink->xpixmap[i]);
3687 GST_INFO_OBJECT (evaspixmapsink, "video-stop property(%d)", evaspixmapsink->stop_video);
3689 g_mutex_unlock( evaspixmapsink->flow_lock );
3691 case PROP_EVAS_OBJECT:
3693 Evas_Object *eo = g_value_get_pointer (value);
3694 if ( is_evas_image_object (eo)) {
3695 if (!evaspixmapsink->epipe) {
3696 evaspixmapsink->epipe = ecore_pipe_add (ecore_pipe_callback_handler, evaspixmapsink);
3697 if (!evaspixmapsink->epipe) {
3698 GST_ERROR_OBJECT (evaspixmapsink,"Cannot set evas-object property: ecore_pipe_add() failed");
3702 if (evaspixmapsink->eo == NULL) {
3703 evaspixmapsink->eo = eo;
3704 /* add evas object callbacks on a new evas image object */
3705 EVASPIXMAPSINK_SET_EVAS_OBJECT_EVENT_CALLBACK (eo, evaspixmapsink);
3706 if (GST_STATE(evaspixmapsink) < GST_STATE_PAUSED) {
3707 GST_INFO_OBJECT (evaspixmapsink,"It's the first time the new evas image object(%x) is set, skip gst_evaspixmapsink_xpixmap_link()..", eo);
3710 if (!gst_evaspixmapsink_xpixmap_link(evaspixmapsink)) {
3711 GST_WARNING_OBJECT (evaspixmapsink,"link evas image object with pixmap failed...");
3712 evaspixmapsink->eo = NULL;
3717 if (eo == evaspixmapsink->eo) {
3718 GST_LOG_OBJECT (evaspixmapsink,"new evas image object(%x) is same as the previous one(%x)", eo, evaspixmapsink->eo);
3720 GST_INFO_OBJECT (evaspixmapsink,"new evas image object(%x), previous one(%x)", eo, evaspixmapsink->eo);
3721 /* delete evas object callbacks registrated on a former evas image object */
3722 EVASPIXMAPSINK_UNSET_EVAS_OBJECT_EVENT_CALLBACK (evaspixmapsink->eo);
3723 evaspixmapsink->eo = eo;
3724 if (!gst_evaspixmapsink_xpixmap_link(evaspixmapsink)) {
3725 GST_WARNING_OBJECT (evaspixmapsink,"link evas image object with pixmap failed...");
3726 evaspixmapsink->eo = NULL;
3729 /* add evas object callbacks on a new evas image object */
3730 EVASPIXMAPSINK_SET_EVAS_OBJECT_EVENT_CALLBACK (eo, evaspixmapsink);
3732 GST_INFO_OBJECT (evaspixmapsink,"Evas image object(%x) is set", evaspixmapsink->eo);
3734 GST_ERROR_OBJECT (evaspixmapsink,"Cannot set evas-object property: value is not an evas image object");
3739 evaspixmapsink->flip = g_value_get_enum(value);
3741 case PROP_ROTATE_ANGLE:
3742 evaspixmapsink->rotate_angle = g_value_get_enum (value);
3746 gboolean visible = g_value_get_boolean (value);
3747 if (evaspixmapsink->visible != visible) {
3748 evaspixmapsink->visible = visible;
3749 if (evaspixmapsink->eo) {
3752 g_mutex_lock( evaspixmapsink->flow_lock );
3753 for (i = 0; i < evaspixmapsink->num_of_pixmaps; i++) {
3754 if (evaspixmapsink->xpixmap[i]) {
3755 gst_evaspixmapsink_xpixmap_clear (evaspixmapsink, evaspixmapsink->xpixmap[i]);
3758 g_mutex_unlock( evaspixmapsink->flow_lock );
3759 evas_object_hide(evaspixmapsink->eo);
3760 GST_INFO_OBJECT (evaspixmapsink,"object hide..");
3762 evas_object_show(evaspixmapsink->eo);
3763 GST_INFO_OBJECT (evaspixmapsink,"object show..");
3764 gst_evaspixmap_buffer_put (evaspixmapsink, evaspixmapsink->evas_pixmap_buf);
3767 GST_WARNING_OBJECT (evaspixmapsink,"evas image object was not set");
3772 case PROP_ORIGIN_SIZE:
3773 evaspixmapsink->use_origin_size = g_value_get_boolean (value);
3774 GST_INFO_OBJECT (evaspixmapsink,"set origin-size (%d)",evaspixmapsink->use_origin_size);
3775 if (evaspixmapsink->previous_origin_size != evaspixmapsink->use_origin_size) {
3776 if (!gst_evaspixmapsink_xpixmap_link(evaspixmapsink)) {
3777 GST_WARNING_OBJECT (evaspixmapsink,"link evas image object with pixmap failed...");
3779 evaspixmapsink->previous_origin_size = evaspixmapsink->use_origin_size;
3783 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
3789 gst_evaspixmapsink_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
3791 GstEvasPixmapSink *evaspixmapsink;
3793 g_return_if_fail (GST_IS_EVASPIXMAPSINK (object));
3795 evaspixmapsink = GST_EVASPIXMAPSINK (object);
3799 g_value_set_int (value, evaspixmapsink->hue);
3802 g_value_set_int (value, evaspixmapsink->contrast);
3804 case PROP_BRIGHTNESS:
3805 g_value_set_int (value, evaspixmapsink->brightness);
3807 case PROP_SATURATION:
3808 g_value_set_int (value, evaspixmapsink->saturation);
3811 g_value_set_string (value, evaspixmapsink->display_name);
3813 case PROP_SYNCHRONOUS:
3814 g_value_set_boolean (value, evaspixmapsink->synchronous);
3816 case PROP_PIXEL_ASPECT_RATIO:
3817 if (evaspixmapsink->par) {
3818 if (!g_value_transform (evaspixmapsink->par, value)) {
3819 g_warning ("g_value_transform() failure");
3825 char *adaptor_no_s = g_strdup_printf ("%u", evaspixmapsink->adaptor_no);
3826 g_value_set_string (value, adaptor_no_s);
3827 g_free (adaptor_no_s);
3830 case PROP_DEVICE_NAME:
3831 if (evaspixmapsink->xcontext && evaspixmapsink->xcontext->adaptors) {
3832 g_value_set_string (value,
3833 evaspixmapsink->xcontext->adaptors[evaspixmapsink->adaptor_no]);
3835 g_value_set_string (value, NULL);
3838 case PROP_DOUBLE_BUFFER:
3839 g_value_set_boolean (value, evaspixmapsink->double_buffer);
3841 case PROP_AUTOPAINT_COLORKEY:
3842 g_value_set_boolean (value, evaspixmapsink->autopaint_colorkey);
3845 g_value_set_int (value, evaspixmapsink->colorkey);
3847 case PROP_PIXMAP_WIDTH:
3849 GST_LOG_OBJECT (evaspixmapsink, "Not supported");
3852 case PROP_PIXMAP_HEIGHT:
3854 GST_LOG_OBJECT (evaspixmapsink, "Not supported");
3857 case PROP_DISPLAY_GEOMETRY_METHOD:
3858 g_value_set_enum (value, evaspixmapsink->display_geometry_method);
3860 case PROP_DST_ROI_X:
3861 g_value_set_int (value, evaspixmapsink->dst_roi.x);
3863 case PROP_DST_ROI_Y:
3864 g_value_set_int (value, evaspixmapsink->dst_roi.y);
3866 case PROP_DST_ROI_W:
3867 g_value_set_int (value, evaspixmapsink->dst_roi.w);
3869 case PROP_DST_ROI_H:
3870 g_value_set_int (value, evaspixmapsink->dst_roi.h);
3872 case PROP_STOP_VIDEO:
3873 g_value_set_int (value, evaspixmapsink->stop_video);
3875 case PROP_EVAS_OBJECT:
3876 g_value_set_pointer (value, evaspixmapsink->eo);
3879 g_value_set_enum(value, evaspixmapsink->flip);
3881 case PROP_ROTATE_ANGLE:
3882 g_value_set_enum (value, evaspixmapsink->rotate_angle);
3885 g_value_set_boolean (value, evaspixmapsink->visible);
3887 case PROP_ORIGIN_SIZE:
3888 g_value_set_boolean (value, evaspixmapsink->use_origin_size);
3891 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
3897 gst_evaspixmapsink_reset (GstEvasPixmapSink *evaspixmapsink)
3899 GST_DEBUG_OBJECT (evaspixmapsink,"[START]");
3902 GST_OBJECT_LOCK (evaspixmapsink);
3903 evaspixmapsink->running = FALSE;
3906 /* grab thread and mark it as NULL */
3907 thread = evaspixmapsink->event_thread;
3908 evaspixmapsink->event_thread = NULL;
3909 GST_OBJECT_UNLOCK (evaspixmapsink);
3911 /* Wait for our event thread to finish before we clean up our stuff. */
3913 g_thread_join (thread);
3916 for (i = 0; i < evaspixmapsink->num_of_pixmaps; i++) {
3917 if(evaspixmapsink->damage[i]) {
3918 XDamageDestroy(evaspixmapsink->xcontext->disp, evaspixmapsink->damage[i]);
3919 evaspixmapsink->damage[i] = NULL;
3922 EVASPIXMAPSINK_UNSET_EVAS_OBJECT_EVENT_CALLBACK( evaspixmapsink->eo );
3924 if (evaspixmapsink->evas_pixmap_buf) {
3925 gst_buffer_unref (GST_BUFFER_CAST (evaspixmapsink->evas_pixmap_buf));
3926 evaspixmapsink->evas_pixmap_buf = NULL;
3929 for (i = 0; i < evaspixmapsink->num_of_pixmaps; i++) {
3930 gst_evaspixmapsink_xpixmap_clear (evaspixmapsink, evaspixmapsink->xpixmap[i]);
3931 gst_evaspixmapsink_xpixmap_destroy (evaspixmapsink, evaspixmapsink->xpixmap[i]);
3932 evaspixmapsink->xpixmap[i] = NULL;
3934 if (evaspixmapsink->eo) {
3935 evas_object_image_native_surface_set(evaspixmapsink->eo, NULL);
3936 evaspixmapsink->eo = NULL;
3939 evaspixmapsink->render_rect.x = evaspixmapsink->render_rect.y =
3940 evaspixmapsink->render_rect.w = evaspixmapsink->render_rect.h = 0;
3941 evaspixmapsink->have_render_rect = FALSE;
3943 gst_evaspixmapsink_xcontext_clear (evaspixmapsink);
3945 GST_DEBUG_OBJECT (evaspixmapsink,"[END]");
3948 /* Finalize is called only once, dispose can be called multiple times.
3949 * We use mutexes and don't reset stuff to NULL here so let's register
3952 gst_evaspixmapsink_finalize (GObject *object)
3954 GstEvasPixmapSink *evaspixmapsink;
3955 evaspixmapsink = GST_EVASPIXMAPSINK (object);
3956 GST_DEBUG_OBJECT (evaspixmapsink,"[START]");
3958 if (evaspixmapsink->display_name) {
3959 g_free (evaspixmapsink->display_name);
3960 evaspixmapsink->display_name = NULL;
3962 if (evaspixmapsink->par) {
3963 g_free (evaspixmapsink->par);
3964 evaspixmapsink->par = NULL;
3966 if (evaspixmapsink->x_lock) {
3967 g_mutex_free (evaspixmapsink->x_lock);
3968 evaspixmapsink->x_lock = NULL;
3970 if (evaspixmapsink->flow_lock) {
3971 g_mutex_free (evaspixmapsink->flow_lock);
3972 evaspixmapsink->flow_lock = NULL;
3974 if (evaspixmapsink->pixmap_ref_lock) {
3975 g_mutex_free (evaspixmapsink->pixmap_ref_lock);
3976 evaspixmapsink->pixmap_ref_lock = NULL;
3978 if (evaspixmapsink->epipe) {
3979 ecore_pipe_del (evaspixmapsink->epipe);
3980 evaspixmapsink->epipe = NULL;
3983 GST_DEBUG_OBJECT (evaspixmapsink,"[END]");
3985 G_OBJECT_CLASS (parent_class)->finalize (object);
3987 MMTA_ACUM_ITEM_SHOW_RESULT_TO(MMTA_SHOW_FILE);
3992 gst_evaspixmapsink_init (GstEvasPixmapSink *evaspixmapsink)
3996 GST_DEBUG_OBJECT (evaspixmapsink,"[START]");
3998 evaspixmapsink->display_name = NULL;
3999 evaspixmapsink->adaptor_no = 0;
4000 evaspixmapsink->xcontext = NULL;
4002 for (i = 0; i < NUM_OF_PIXMAP; i++) {
4003 evaspixmapsink->xpixmap[i] = NULL;
4004 evaspixmapsink->damage[i] = 0;
4007 evaspixmapsink->evas_pixmap_buf = NULL;
4009 evaspixmapsink->hue = evaspixmapsink->saturation = 0;
4010 evaspixmapsink->contrast = evaspixmapsink->brightness = 0;
4011 evaspixmapsink->cb_changed = FALSE;
4013 evaspixmapsink->fps_n = 0;
4014 evaspixmapsink->fps_d = 0;
4015 evaspixmapsink->video_width = 0;
4016 evaspixmapsink->video_height = 0;
4018 evaspixmapsink->x_lock = g_mutex_new ();
4019 evaspixmapsink->flow_lock = g_mutex_new ();
4020 evaspixmapsink->pixmap_ref_lock = g_mutex_new();
4022 evaspixmapsink->synchronous = FALSE;
4023 evaspixmapsink->double_buffer = TRUE;
4024 evaspixmapsink->par = NULL;
4025 evaspixmapsink->autopaint_colorkey = TRUE;
4026 evaspixmapsink->running = FALSE;
4028 /* on 16bit displays this becomes r,g,b = 1,2,3
4029 * on 24bit displays this becomes r,g,b = 8,8,16
4030 * as a port atom value
4032 evaspixmapsink->colorkey = (8 << 16) | (8 << 8) | 16;
4034 evaspixmapsink->display_geometry_method = DEF_DISPLAY_GEOMETRY_METHOD;
4035 evaspixmapsink->dst_roi.x = 0;
4036 evaspixmapsink->dst_roi.y = 0;
4037 evaspixmapsink->dst_roi.w = 0;
4038 evaspixmapsink->dst_roi.h = 0;
4039 evaspixmapsink->scr_w = 0;
4040 evaspixmapsink->scr_h = 0;
4041 evaspixmapsink->aligned_width = 0;
4042 evaspixmapsink->aligned_height = 0;
4043 evaspixmapsink->stop_video = FALSE;
4044 evaspixmapsink->eo = NULL;
4045 evaspixmapsink->epipe = NULL;
4046 evaspixmapsink->do_link = FALSE;
4047 evaspixmapsink->flip = DEF_DISPLAY_FLIP;
4048 evaspixmapsink->rotate_angle = DEGREE_0;
4049 evaspixmapsink->visible = TRUE;
4050 evaspixmapsink->use_origin_size = FALSE;
4051 evaspixmapsink->previous_origin_size = FALSE;
4053 evaspixmapsink->num_of_pixmaps = NUM_OF_PIXMAP;
4055 evaspixmapsink->buf_shared_type = BUF_SHARE_METHOD_NONE;
4059 GST_DEBUG_OBJECT (evaspixmapsink,"[END]");
4063 gst_evaspixmapsink_base_init (gpointer g_class)
4065 GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
4067 gst_element_class_set_details_simple (element_class,
4068 "EvasPixmapSink", "Sink/Video",
4069 "evas image object videosink based on Xv extension", "Sangchul Lee <sc11.lee@samsung.com>");
4071 gst_element_class_add_pad_template (element_class,
4072 gst_static_pad_template_get (&gst_evaspixmapsink_sink_template_factory));
4076 gst_evaspixmapsink_class_init (GstEvasPixmapSinkClass *klass)
4078 GObjectClass *gobject_class;
4079 GstElementClass *gstelement_class;
4080 GstBaseSinkClass *gstbasesink_class;
4081 GstVideoSinkClass *videosink_class;
4083 gobject_class = (GObjectClass *) klass;
4084 gstelement_class = (GstElementClass *) klass;
4085 gstbasesink_class = (GstBaseSinkClass *) klass;
4086 videosink_class = (GstVideoSinkClass *) klass;
4088 parent_class = g_type_class_peek_parent (klass);
4090 gobject_class->set_property = gst_evaspixmapsink_set_property;
4091 gobject_class->get_property = gst_evaspixmapsink_get_property;
4093 g_object_class_install_property (gobject_class, PROP_CONTRAST,
4094 g_param_spec_int ("contrast", "Contrast", "The contrast of the video",
4095 -1000, 1000, 0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
4096 g_object_class_install_property (gobject_class, PROP_BRIGHTNESS,
4097 g_param_spec_int ("brightness", "Brightness",
4098 "The brightness of the video", -1000, 1000, 0,
4099 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
4100 g_object_class_install_property (gobject_class, PROP_HUE,
4101 g_param_spec_int ("hue", "Hue", "The hue of the video", -1000, 1000, 0,
4102 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
4103 g_object_class_install_property (gobject_class, PROP_SATURATION,
4104 g_param_spec_int ("saturation", "Saturation",
4105 "The saturation of the video", -1000, 1000, 0,
4106 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
4107 g_object_class_install_property (gobject_class, PROP_DISPLAY,
4108 g_param_spec_string ("display", "Display", "X Display name", NULL,
4109 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
4110 g_object_class_install_property (gobject_class, PROP_SYNCHRONOUS,
4111 g_param_spec_boolean ("synchronous", "Synchronous",
4112 "When enabled, runs "
4113 "the X display in synchronous mode. (used only for debugging)", FALSE,
4114 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
4115 g_object_class_install_property (gobject_class, PROP_PIXEL_ASPECT_RATIO,
4116 g_param_spec_string ("pixel-aspect-ratio", "Pixel Aspect Ratio",
4117 "The pixel aspect ratio of the device", "1/1",
4118 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
4119 g_object_class_install_property (gobject_class, PROP_DEVICE,
4120 g_param_spec_string ("device", "Adaptor number",
4121 "The number of the video adaptor", "0",
4122 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
4123 g_object_class_install_property (gobject_class, PROP_DEVICE_NAME,
4124 g_param_spec_string ("device-name", "Adaptor name",
4125 "The name of the video adaptor", NULL,
4126 G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
4129 * GstEvasPixmapSink:double-buffer
4131 * Whether to double-buffer the output.
4135 g_object_class_install_property (gobject_class, PROP_DOUBLE_BUFFER,
4136 g_param_spec_boolean ("double-buffer", "Double-buffer",
4137 "Whether to double-buffer the output", TRUE,
4138 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
4140 * GstEvasPixmapSink:autopaint-colorkey
4142 * Whether to autofill overlay with colorkey
4146 g_object_class_install_property (gobject_class, PROP_AUTOPAINT_COLORKEY,
4147 g_param_spec_boolean ("autopaint-colorkey", "Autofill with colorkey",
4148 "Whether to autofill overlay with colorkey", TRUE,
4149 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
4151 * GstEvasPixmapSink:colorkey
4153 * Color to use for the overlay mask.
4157 g_object_class_install_property (gobject_class, PROP_COLORKEY,
4158 g_param_spec_int ("colorkey", "Colorkey",
4159 "Color to use for the overlay mask", G_MININT, G_MAXINT, 0,
4160 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
4163 * GstEvasPixmapSink:pixmap-width
4165 * Actual width of the pixmap.
4167 g_object_class_install_property (gobject_class, PROP_PIXMAP_WIDTH,
4168 g_param_spec_uint64 ("pixmap-width", "pixmap-width", "Width of the pixmap", 0, G_MAXUINT64, 0, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
4171 * GstEvasPixmapSink:pixmap-height
4173 * Actual height of the pixmap.
4175 g_object_class_install_property (gobject_class, PROP_PIXMAP_HEIGHT,
4176 g_param_spec_uint64 ("pixmap-height", "pixmap-height", "Height of the pixmap", 0, G_MAXUINT64, 0, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
4179 * GstEvasPixmapSink:display-geometry-method
4181 * Display geometrical method setting
4183 g_object_class_install_property(gobject_class, PROP_DISPLAY_GEOMETRY_METHOD,
4184 g_param_spec_enum("display-geometry-method", "Display geometry method",
4185 "Geometrical method for display",
4186 GST_TYPE_EVASPIXMAPSINK_DISPLAY_GEOMETRY_METHOD, DEF_DISPLAY_GEOMETRY_METHOD,
4187 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
4190 * GstEvasPixmapSink:dst-roi-x
4192 * X value of Destination ROI
4194 g_object_class_install_property (gobject_class, PROP_DST_ROI_X,
4195 g_param_spec_int ("dst-roi-x", "Dst-ROI-X",
4196 "X value of Destination ROI(only effective \"CUSTOM_ROI\")", 0, XV_SCREEN_SIZE_WIDTH, 0,
4197 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
4200 * GstEvasPixmapSink:dst-roi-y
4202 * Y value of Destination ROI
4204 g_object_class_install_property (gobject_class, PROP_DST_ROI_Y,
4205 g_param_spec_int ("dst-roi-y", "Dst-ROI-Y",
4206 "Y value of Destination ROI(only effective \"CUSTOM_ROI\")", 0, XV_SCREEN_SIZE_HEIGHT, 0,
4207 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
4210 * GstEvasPixmapSink:dst-roi-w
4212 * W value of Destination ROI
4214 g_object_class_install_property (gobject_class, PROP_DST_ROI_W,
4215 g_param_spec_int ("dst-roi-w", "Dst-ROI-W",
4216 "W value of Destination ROI(only effective \"CUSTOM_ROI\")", 0, XV_SCREEN_SIZE_WIDTH, 0,
4217 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
4220 * GstEvasPixmapSink:dst-roi-h
4222 * H value of Destination ROI
4224 g_object_class_install_property (gobject_class, PROP_DST_ROI_H,
4225 g_param_spec_int ("dst-roi-h", "Dst-ROI-H",
4226 "H value of Destination ROI(only effective \"CUSTOM_ROI\")", 0, XV_SCREEN_SIZE_HEIGHT, 0,
4227 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
4230 * GstEvasPixmapSink:stop-video
4232 * Stop video for releasing video source buffer
4234 g_object_class_install_property (gobject_class, PROP_STOP_VIDEO,
4235 g_param_spec_int ("stop-video", "Stop-Video", "Stop video for releasing video source buffer", 0, 1, 0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
4238 * GstEvasPixmapSink:evas-object
4240 * Evas image object for rendering
4242 g_object_class_install_property (gobject_class, PROP_EVAS_OBJECT,
4243 g_param_spec_pointer ("evas-object", "Destination Evas Object", "Destination evas image object", G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
4246 * GstEvasPixmapSink:display-flip
4248 * Display flip setting
4250 g_object_class_install_property(gobject_class, PROP_FLIP,
4251 g_param_spec_enum("flip", "Display flip",
4253 GST_TYPE_EVASPIXMAPSINK_FLIP, DEF_DISPLAY_FLIP,
4254 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
4257 * GstEvasPixmapSink:rotate
4259 * draw rotation angle setting
4261 g_object_class_install_property(gobject_class, PROP_ROTATE_ANGLE,
4262 g_param_spec_enum("rotate", "Rotate angle", "Rotate angle of display output",GST_TYPE_EVASPIXMAPSINK_ROTATE_ANGLE, DEGREE_0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
4265 * GstEvasPixmapSink:visible
4267 * visible setting for a evas image object
4269 g_object_class_install_property (gobject_class, PROP_VISIBLE,
4270 g_param_spec_boolean ("visible", "Visible", "When setting it false, evas image object does not show", TRUE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
4273 * GstEvasPixmapSink:origin-size
4275 * Set pixmap size with media source's width and height
4277 g_object_class_install_property (gobject_class, PROP_ORIGIN_SIZE,
4278 g_param_spec_boolean ("origin-size", "Origin-Size", "When setting it true, pixmap will be created with media source's width and height", FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
4280 gobject_class->finalize = gst_evaspixmapsink_finalize;
4282 gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_evaspixmapsink_change_state);
4283 gstbasesink_class->get_caps = GST_DEBUG_FUNCPTR (gst_evaspixmapsink_getcaps);
4284 gstbasesink_class->set_caps = GST_DEBUG_FUNCPTR (gst_evaspixmapsink_setcaps);
4285 gstbasesink_class->get_times = GST_DEBUG_FUNCPTR (gst_evaspixmapsink_get_times);
4286 gstbasesink_class->event = GST_DEBUG_FUNCPTR (gst_evaspixmapsink_event);
4287 videosink_class->show_frame = GST_DEBUG_FUNCPTR (gst_evaspixmapsink_show_frame);
4290 /* Object typing & Creation */
4292 gst_evaspixmapsink_get_type (void)
4294 static GType evaspixmapsink_type = 0;
4296 if (!evaspixmapsink_type) {
4297 static const GTypeInfo evaspixmapsink_info = {
4298 sizeof (GstEvasPixmapSinkClass),
4299 gst_evaspixmapsink_base_init,
4301 (GClassInitFunc) gst_evaspixmapsink_class_init,
4304 sizeof (GstEvasPixmapSink),
4306 (GInstanceInitFunc) gst_evaspixmapsink_init,
4308 static const GInterfaceInfo iface_info = {
4309 (GInterfaceInitFunc) gst_evaspixmapsink_interface_init,
4313 static const GInterfaceInfo navigation_info = {
4314 (GInterfaceInitFunc) gst_evaspixmapsink_navigation_init,
4318 static const GInterfaceInfo colorbalance_info = {
4319 (GInterfaceInitFunc) gst_evaspixmapsink_colorbalance_init,
4323 static const GInterfaceInfo propertyprobe_info = {
4324 (GInterfaceInitFunc) gst_evaspixmapsink_property_probe_interface_init,
4328 evaspixmapsink_type = g_type_register_static (GST_TYPE_VIDEO_SINK, "GstEvasPixmapSink", &evaspixmapsink_info, 0);
4330 g_type_add_interface_static (evaspixmapsink_type, GST_TYPE_IMPLEMENTS_INTERFACE, &iface_info);
4331 g_type_add_interface_static (evaspixmapsink_type, GST_TYPE_NAVIGATION, &navigation_info);
4332 g_type_add_interface_static (evaspixmapsink_type, GST_TYPE_COLOR_BALANCE, &colorbalance_info);
4333 g_type_add_interface_static (evaspixmapsink_type, GST_TYPE_PROPERTY_PROBE, &propertyprobe_info);
4335 /* register type and create class in a more safe place instead of at
4336 * runtime since the type registration and class creation is not
4338 g_type_class_ref (gst_evaspixmap_buffer_get_type ());
4341 return evaspixmapsink_type;
4345 plugin_init (GstPlugin *plugin)
4347 if (!gst_element_register (plugin, "evaspixmapsink", GST_RANK_NONE, GST_TYPE_EVASPIXMAPSINK)) {
4350 GST_DEBUG_CATEGORY_INIT (gst_debug_evaspixmapsink, "evaspixmapsink", 0, "evaspixmapsink element");
4351 GST_DEBUG_CATEGORY_GET (GST_CAT_PERFORMANCE, "GST_PERFORMANCE");
4356 GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, GST_VERSION_MINOR,
4357 "evaspixmapsink","Evas image object render plugin using Xv extension", plugin_init,
4358 VERSION, GST_LICENSE, GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN)