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>
53 /* max channel count *********************************************************/
54 #define SCMN_IMGB_MAX_PLANE (4)
56 /* image buffer definition ***************************************************
58 +------------------------------------------+ ---
61 | +---------------------------+ --- | |
63 | |<---------- w[] ---------->| | | |
71 | +---------------------------+ --- | |
73 +------------------------------------------+ ---
75 |<----------------- s[] ------------------>|
80 /* width of each image plane */
81 int w[SCMN_IMGB_MAX_PLANE];
82 /* height of each image plane */
83 int h[SCMN_IMGB_MAX_PLANE];
84 /* stride of each image plane */
85 int s[SCMN_IMGB_MAX_PLANE];
86 /* elevation of each image plane */
87 int e[SCMN_IMGB_MAX_PLANE];
88 /* user space address of each image plane */
89 void *a[SCMN_IMGB_MAX_PLANE];
90 /* physical address of each image plane, if needs */
91 void *p[SCMN_IMGB_MAX_PLANE];
92 /* color space type of image */
94 /* left postion, if needs */
96 /* top position, if needs */
103 int dma_buf_fd[SCMN_IMGB_MAX_PLANE];
104 /* buffer share method */
105 int buf_share_method;
106 /* Y plane size in case of ST12 */
108 /* UV plane size in case of ST12 */
110 /* Tizen buffer object */
111 void *bo[SCMN_IMGB_MAX_PLANE];
116 /* TZ memory buffer */
120 /* Debugging category */
121 #include <gst/gstinfo.h>
122 GST_DEBUG_CATEGORY_STATIC (gst_debug_evaspixmapsink);
123 #define GST_CAT_DEFAULT gst_debug_evaspixmapsink
124 GST_DEBUG_CATEGORY_STATIC (GST_CAT_PERFORMANCE);
140 DISP_GEO_METHOD_LETTER_BOX = 0,
141 DISP_GEO_METHOD_ORIGIN_SIZE,
142 DISP_GEO_METHOD_FULL_SCREEN,
143 DISP_GEO_METHOD_CROPPED_FULL_SCREEN,
144 DISP_GEO_METHOD_CUSTOM_ROI,
156 #define DEF_DISPLAY_GEOMETRY_METHOD DISP_GEO_METHOD_LETTER_BOX
157 #define DEF_DISPLAY_FLIP FLIP_NONE
158 #define GST_TYPE_EVASPIXMAPSINK_FLIP (gst_evaspixmapsink_flip_get_type())
159 #define GST_TYPE_EVASPIXMAPSINK_ROTATE_ANGLE (gst_evaspixmapsink_rotate_angle_get_type())
160 #define GST_TYPE_EVASPIXMAPSINK_DISPLAY_GEOMETRY_METHOD (gst_evaspixmapsink_display_geometry_method_get_type())
161 #define SIZE_FOR_UPDATE_VISIBILITY sizeof(gchar)
162 #define EPIPE_REQUEST_LIMIT 20
164 /* macro ******************************************************/
165 #define EVASPIXMAPSINK_SET_PIXMAP_ID_TO_GEM_INFO( x_evaspixmapsink, x_pixmap_id ) \
169 XV_DATA_PTR data = (XV_DATA_PTR)x_evaspixmapsink->evas_pixmap_buf->xvimage->data; \
170 if (data->YBuf > 0) { \
171 for (i = 0; i < MAX_GEM_BUFFER_NUM; i++) { \
172 if (evaspixmapsink->gem_info[i].gem_name == data->YBuf) { \
173 evaspixmapsink->gem_info[i].ref_pixmap = x_pixmap_id; \
174 GST_LOG_OBJECT (x_evaspixmapsink,"pixmap(%d) is marked at index(%d) of gem_info(YBuf)->gem_handle(%d)", x_pixmap_id, i, evaspixmapsink->gem_info[i].gem_handle); \
179 if (data->CbBuf > 0) { \
180 for (i = 0; i < MAX_GEM_BUFFER_NUM; i++) { \
181 if (evaspixmapsink->gem_info[i].gem_name == data->CbBuf) { \
182 evaspixmapsink->gem_info[i].ref_pixmap = x_pixmap_id; \
183 GST_LOG_OBJECT (x_evaspixmapsink,"pixmap(%d) is marked at index(%d) of gem_info(CbBuf)->gem_handle(%d)", x_pixmap_id, i, evaspixmapsink->gem_info[i].gem_handle); \
188 if (data->CrBuf > 0) { \
189 for (i = 0; i < MAX_GEM_BUFFER_NUM; i++) { \
190 if (evaspixmapsink->gem_info[i].gem_name == data->CrBuf) { \
191 evaspixmapsink->gem_info[i].ref_pixmap = x_pixmap_id; \
192 GST_LOG_OBJECT (x_evaspixmapsink,"pixmap(%d) is marked at index(%d) of gem_info(CrBuf)->gem_handle(%d)", x_pixmap_id, i, evaspixmapsink->gem_info[i].gem_handle); \
199 #define EVASPIXMAPSINK_SET_EVAS_OBJECT_EVENT_CALLBACK( x_evas_image_object, x_usr_data ) \
202 evas_object_event_callback_add (x_evas_image_object, EVAS_CALLBACK_DEL, evas_callback_del_event, x_usr_data); \
203 evas_object_event_callback_add (x_evas_image_object, EVAS_CALLBACK_RESIZE, evas_callback_resize_event, x_usr_data); \
204 evas_object_event_callback_add (x_evas_image_object, EVAS_CALLBACK_SHOW, evas_callback_show_event, x_usr_data); \
205 evas_object_event_callback_add (x_evas_image_object, EVAS_CALLBACK_HIDE, evas_callback_hide_event, x_usr_data); \
208 #define EVASPIXMAPSINK_UNSET_EVAS_OBJECT_EVENT_CALLBACK( x_evas_image_object ) \
211 evas_object_event_callback_del (x_evas_image_object, EVAS_CALLBACK_DEL, evas_callback_del_event); \
212 evas_object_event_callback_del (x_evas_image_object, EVAS_CALLBACK_RESIZE, evas_callback_resize_event); \
213 evas_object_event_callback_del (x_evas_image_object, EVAS_CALLBACK_SHOW, evas_callback_show_event); \
214 evas_object_event_callback_del (x_evas_image_object, EVAS_CALLBACK_HIDE, evas_callback_hide_event); \
218 gst_evaspixmapsink_flip_get_type(void)
220 static GType evaspixmapsink_flip_type = 0;
221 static const GEnumValue flip_type[] = {
222 { FLIP_NONE, "Flip NONE", "FLIP_NONE"},
223 { FLIP_HORIZONTAL, "Flip HORIZONTAL", "FLIP_HORIZONTAL"},
224 { FLIP_VERTICAL, "Flip VERTICAL", "FLIP_VERTICAL"},
225 { FLIP_BOTH, "Flip BOTH", "FLIP_BOTH"},
226 { FLIP_NUM, NULL, NULL},
229 if (!evaspixmapsink_flip_type) {
230 evaspixmapsink_flip_type = g_enum_register_static("GstEvasPixmapSinkFlipType", flip_type);
233 return evaspixmapsink_flip_type;
237 gst_evaspixmapsink_rotate_angle_get_type(void)
239 static GType evaspixmapsink_rotate_angle_type = 0;
240 static const GEnumValue rotate_angle_type[] = {
241 { 0, "No rotate", "DEGREE_0"},
242 { 1, "Rotate 90 degree", "DEGREE_90"},
243 { 2, "Rotate 180 degree", "DEGREE_180"},
244 { 3, "Rotate 270 degree", "DEGREE_270"},
248 if (!evaspixmapsink_rotate_angle_type) {
249 evaspixmapsink_rotate_angle_type = g_enum_register_static("GstEvasPixmapSinkRotateAngleType", rotate_angle_type);
252 return evaspixmapsink_rotate_angle_type;
256 gst_evaspixmapsink_display_geometry_method_get_type(void)
258 static GType evaspixmapsink_display_geometry_method_type = 0;
259 static const GEnumValue display_geometry_method_type[] = {
260 { 0, "Letter box", "LETTER_BOX"},
261 { 1, "Origin size", "ORIGIN_SIZE"},
262 { 2, "Full-screen", "FULL_SCREEN"},
263 { 3, "Cropped Full-screen", "CROPPED_FULL_SCREEN"},
264 { 4, "Explicitely described destination ROI", "CUSTOM_ROI"},
268 if (!evaspixmapsink_display_geometry_method_type) {
269 evaspixmapsink_display_geometry_method_type = g_enum_register_static("GstEvasPixmapSinkDisplayGeometryMethodType", display_geometry_method_type);
272 return evaspixmapsink_display_geometry_method_type;
278 unsigned long functions;
279 unsigned long decorations;
281 unsigned long status;
283 MotifWmHints, MwmHints;
285 #define MWM_HINTS_DECORATIONS (1L << 1)
287 static void gst_evaspixmapsink_reset (GstEvasPixmapSink *evaspixmapsink);
288 static GstBufferClass *evaspixmap_buffer_parent_class = NULL;
289 static void gst_evaspixmap_buffer_finalize (GstEvasPixmapBuffer *evaspixmapbuf);
290 static void gst_evaspixmapsink_xcontext_clear (GstEvasPixmapSink *evaspixmapsink);
291 static void gst_evaspixmapsink_xpixmap_destroy (GstEvasPixmapSink *evaspixmapsink, GstXPixmap *xpixmap);
292 static void gst_evaspixmapsink_xpixmap_update_geometry (GstEvasPixmapSink *evaspixmapsink, int idx);
293 static gboolean gst_evaspixmap_buffer_put (GstEvasPixmapSink *evaspixmapsink, GstEvasPixmapBuffer *evaspixmapbuf);
294 static gboolean gst_evaspixmapsink_xpixmap_link (GstEvasPixmapSink *evaspixmapsink);
295 static void gst_evaspixmapsink_xpixmap_clear (GstEvasPixmapSink *evaspixmapsink, GstXPixmap *xpixmap);
296 static gint gst_evaspixmapsink_get_format_from_caps (GstEvasPixmapSink *evaspixmapsink, GstCaps *caps);
297 static void drm_close_gem(GstEvasPixmapSink *evaspixmapsink, unsigned int gem_handle);
298 static void drm_fini_close_gem_handle(GstEvasPixmapSink *evaspixmapsink, Pixmap pixmap_id);
299 static void evas_callback_resize_event (void *data, Evas *e, Evas_Object *obj, void *event_info);
300 static void evas_callback_del_event (void *data, Evas *e, Evas_Object *obj, void *event_info);
301 static void evas_callback_show_event (void *data, Evas *e, Evas_Object *obj, void *event_info);
302 static void evas_callback_hide_event (void *data, Evas *e, Evas_Object *obj, void *event_info);
304 /* Default template - initiated with class struct to allow gst-register to work
306 static GstStaticPadTemplate gst_evaspixmapsink_sink_template_factory =
307 GST_STATIC_PAD_TEMPLATE ("sink",
310 GST_STATIC_CAPS ("video/x-raw-rgb, "
311 "framerate = (fraction) [ 0, MAX ], "
312 "width = (int) [ 1, MAX ], "
313 "height = (int) [ 1, MAX ]; "
315 "framerate = (fraction) [ 0, MAX ], "
316 "width = (int) [ 1, MAX ], " "height = (int) [ 1, MAX ]")
328 PROP_PIXEL_ASPECT_RATIO,
332 PROP_AUTOPAINT_COLORKEY,
338 PROP_DISPLAY_GEOMETRY_METHOD,
350 static GstVideoSinkClass *parent_class = NULL;
352 /* ============================================================= */
354 /* Private Methods */
356 /* ============================================================= */
358 /* evaspixmap buffers */
360 #define GST_TYPE_EVASPIXMAP_BUFFER (gst_evaspixmap_buffer_get_type())
362 #define GST_IS_EVASPIXMAP_BUFFER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_EVASPIXMAP_BUFFER))
363 #define GST_EVASPIXMAP_BUFFER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_EVASPIXMAP_BUFFER, GstEvasPixmapBuffer))
365 static int get_millis_time()
368 clock_gettime(CLOCK_MONOTONIC, &tp);
369 return (tp.tv_sec * 1000) + (tp.tv_nsec / 1000000L);
373 ecore_pipe_callback_handler (void *data, void *buffer, unsigned int nbyte)
375 GstEvasPixmapSink *evaspixmapsink = (GstEvasPixmapSink*)data;
376 GST_DEBUG_OBJECT (evaspixmapsink,"[START] Evas_Object(0x%x)", evaspixmapsink->eo);
377 MMTA_ACUM_ITEM_BEGIN("evaspixmapsink - ecore thread cb : TOTAL", FALSE);
380 GstXPixmap *xpixmap = NULL;
383 GST_WARNING_OBJECT (evaspixmapsink,"data is NULL..");
386 evaspixmapsink->epipe_request_count--;
387 if (!evaspixmapsink->eo) {
388 GST_WARNING_OBJECT (evaspixmapsink,"evas object is NULL..");
392 /* setting evas object hide and show */
393 if (nbyte == SIZE_FOR_UPDATE_VISIBILITY) {
394 if(!evaspixmapsink->visible) {
395 evas_object_hide(evaspixmapsink->eo);
396 GST_INFO_OBJECT (evaspixmapsink, "object hide");
398 if (!evas_object_image_native_surface_get(evaspixmapsink->eo)) {
399 GST_WARNING_OBJECT (evaspixmapsink, "native surface is not set, skip evas_object_show()..");
401 evas_object_show(evaspixmapsink->eo);
402 GST_INFO_OBJECT (evaspixmapsink, "object show");
408 /* mapping evas object with xpixmap */
409 if (evaspixmapsink->do_link) {
410 GST_DEBUG_OBJECT (evaspixmapsink,"do link");
411 evas_object_image_size_set(evaspixmapsink->eo, evaspixmapsink->w, evaspixmapsink->h);
412 if (evaspixmapsink->xpixmap[idx]->pixmap) {
413 Evas_Native_Surface surf;
414 surf.version = EVAS_NATIVE_SURFACE_VERSION;
415 surf.type = EVAS_NATIVE_SURFACE_X11;
416 surf.data.x11.visual = ecore_x_default_visual_get(ecore_x_display_get(), ecore_x_default_screen_get());
417 surf.data.x11.pixmap = evaspixmapsink->xpixmap[idx]->pixmap;
418 __ta__("evaspixmapsink - ecore thread cb : _native_surface_set(LINK)", evas_object_image_native_surface_set(evaspixmapsink->eo, &surf); );
419 evaspixmapsink->do_link = FALSE;
421 GST_WARNING_OBJECT (evaspixmapsink,"pixmap is NULL..");
424 for (i = 0; i < evaspixmapsink->num_of_pixmaps; i++) {
425 if (evaspixmapsink->xpixmap[i]->prev_pixmap && evaspixmapsink->xpixmap[i]->prev_gc && evaspixmapsink->prev_damage[i]) {
426 GST_LOG_OBJECT (evaspixmapsink,"Free pixmap(%d), gc(%x), destroy previous damage(%d)",
427 evaspixmapsink->xpixmap[i]->prev_pixmap, evaspixmapsink->xpixmap[i]->prev_gc, evaspixmapsink->prev_damage[i]);
428 g_mutex_lock (evaspixmapsink->x_lock);
429 XFreePixmap(evaspixmapsink->xcontext->disp, evaspixmapsink->xpixmap[i]->prev_pixmap);
430 XFreeGC (evaspixmapsink->xcontext->disp, evaspixmapsink->xpixmap[i]->prev_gc);
431 XDamageDestroy(evaspixmapsink->xcontext->disp, evaspixmapsink->prev_damage[i]);
432 XSync(evaspixmapsink->xcontext->disp, FALSE);
433 g_mutex_unlock (evaspixmapsink->x_lock);
434 evaspixmapsink->xpixmap[i]->prev_pixmap = 0;
435 evaspixmapsink->xpixmap[i]->prev_gc = 0;
436 evaspixmapsink->prev_damage[i] = NULL;
439 if (evaspixmapsink->visible && !evas_object_visible_get(evaspixmapsink->eo)) {
440 evas_object_show(evaspixmapsink->eo);
441 GST_WARNING_OBJECT (evaspixmapsink, "object show (lazy)");
445 GST_DEBUG_OBJECT (evaspixmapsink,"update");
446 /* update evas image object size */
447 if (evaspixmapsink->use_origin_size) {
448 evas_object_geometry_get(evaspixmapsink->eo, NULL, NULL, &evaspixmapsink->w, &evaspixmapsink->h);
451 g_mutex_lock (evaspixmapsink->pixmap_ref_lock);
453 /* find a oldest damaged pixmap */
455 for (i = 0; i < evaspixmapsink->num_of_pixmaps; i++) {
456 if (evaspixmapsink->last_updated_idx == i) {
459 xpixmap = evaspixmapsink->xpixmap[i];
460 if (xpixmap->ref > 0 && xpixmap->damaged_time) {
461 if (temp_time == 0) {
462 temp_time = xpixmap->damaged_time;
465 if (temp_time > xpixmap->damaged_time) {
466 temp_time = xpixmap->damaged_time;
474 xpixmap = evaspixmapsink->xpixmap[idx];
475 if (xpixmap->pixmap) {
476 if (evaspixmapsink->last_updated_idx != idx) {
477 Evas_Native_Surface surf;
478 surf.version = EVAS_NATIVE_SURFACE_VERSION;
479 surf.type = EVAS_NATIVE_SURFACE_X11;
480 surf.data.x11.visual = ecore_x_default_visual_get(ecore_x_display_get(), ecore_x_default_screen_get());
481 surf.data.x11.pixmap = xpixmap->pixmap;
482 if (evaspixmapsink->eo) {
483 evas_object_image_native_surface_set(evaspixmapsink->eo, NULL);
485 __ta__("evaspixmapsink - ecore thread cb : _native_surface_set", evas_object_image_native_surface_set(evaspixmapsink->eo, &surf); );
486 GST_LOG_OBJECT (evaspixmapsink,"update, native_surface_set of xpixmap[%d]",idx);
487 if (evaspixmapsink->last_updated_idx == -1) {
488 xpixmap->damaged_time = 0;
489 GST_INFO_OBJECT (evaspixmapsink,"this is the first time to request to update(do not DECREASE ref-count) : pixmap(%d), refcount(%d), damaged_time(%d), idx(%d)",
490 xpixmap->pixmap, xpixmap->ref, xpixmap->damaged_time, idx);
492 xpixmap = evaspixmapsink->xpixmap[evaspixmapsink->last_updated_idx];
494 xpixmap->damaged_time = 0;
495 GST_INFO_OBJECT (evaspixmapsink,"pixmap ref-count DECREASED : pixmap(%d), refcount(%d), damaged_time(%d), idx(%d)",
496 xpixmap->pixmap, xpixmap->ref, xpixmap->damaged_time, evaspixmapsink->last_updated_idx);
498 evaspixmapsink->last_updated_idx = idx;
501 MMTA_ACUM_ITEM_BEGIN("evaspixmapsink evas_object_image update", FALSE);
502 evas_object_image_pixels_dirty_set (evaspixmapsink->eo, 1);
503 evas_object_image_fill_set(evaspixmapsink->eo, 0, 0, evaspixmapsink->w, evaspixmapsink->h);
504 evas_object_image_data_update_add(evaspixmapsink->eo, 0, 0, evaspixmapsink->w, evaspixmapsink->h);
505 MMTA_ACUM_ITEM_END("evaspixmapsink evas_object_image update", FALSE);
506 //GST_LOG_OBJECT (evaspixmapsink,"request to update : pixmap idx(%d), ref(%d)", idx, xpixmap->ref);
508 GST_ERROR_OBJECT (evaspixmapsink,"pixmap is NULL..");
510 g_mutex_unlock (evaspixmapsink->pixmap_ref_lock);
513 MMTA_ACUM_ITEM_END("evaspixmapsink - ecore thread cb : TOTAL", FALSE);
515 GST_DEBUG_OBJECT (evaspixmapsink,"[END]");
518 static inline gboolean
519 is_evas_image_object (Evas_Object *obj)
523 GST_ERROR ("evas image object is NULL..");
526 type = evas_object_type_get (obj);
528 GST_ERROR ("could not find type of the evas object..");
531 if (strcmp (type, "image") == 0) {
538 evas_callback_resize_event (void *data, Evas *e, Evas_Object *obj, void *event_info)
542 float former_ratio = 0;
546 float abs_margin = 0;
549 GstEvasPixmapSink *evaspixmapsink = (GstEvasPixmapSink *)data;
550 GST_DEBUG_OBJECT (evaspixmapsink,"[START] evas_image_object(%x), tid(%u)", obj, (unsigned int)pthread_self());
552 evas_object_geometry_get(evaspixmapsink->eo, NULL, NULL, &w, &h);
553 GST_DEBUG_OBJECT (evaspixmapsink,"resized : w(%d), h(%d)", w, h);
554 if (!evaspixmapsink->use_origin_size &&
555 (evaspixmapsink->w != w || evaspixmapsink->h != h)) {
556 former_ratio = (float)evaspixmapsink->w / evaspixmapsink->h;
557 ratio = (float)w / h;
558 evaspixmapsink->w = w;
559 evaspixmapsink->h = h;
562 GST_DEBUG_OBJECT (evaspixmapsink,"resized : ratio(%.3f=>%.3f)", former_ratio, ratio);
563 if ( former_ratio >= ratio ) {
564 abs_margin = former_ratio - ratio;
566 abs_margin = ratio - former_ratio;
568 /* re-link_pixmap can only be set when ratio is changed */
569 if ( abs_margin >= MARGIN_OF_ERROR ) {
571 if (!gst_evaspixmapsink_xpixmap_link(evaspixmapsink)) {
572 GST_ERROR_OBJECT (evaspixmapsink,"link evas image object with pixmap failed...");
575 for (i = 0; i < MAX_GEM_BUFFER_NUM; i++) {
576 if (evaspixmapsink->gem_info[i].ref_pixmap > 0) {
577 GST_LOG_OBJECT (evaspixmapsink,"set ref_pixmap(%d) to 0 in gem_info[%d]", evaspixmapsink->gem_info[i].ref_pixmap, i);
578 evaspixmapsink->gem_info[i].ref_pixmap = 0;
586 if (GST_STATE(evaspixmapsink) == GST_STATE_PAUSED) {
587 gst_evaspixmap_buffer_put (evaspixmapsink, evaspixmapsink->evas_pixmap_buf);
590 GST_DEBUG_OBJECT (evaspixmapsink,"[END]");
594 evas_callback_del_event (void *data, Evas *e, Evas_Object *obj, void *event_info)
596 GstEvasPixmapSink *evaspixmapsink = data;
597 if (!evaspixmapsink) {
598 GST_WARNING ("evaspixmapsink is NULL..");
601 GST_DEBUG_OBJECT (evaspixmapsink,"[START]");
603 EVASPIXMAPSINK_UNSET_EVAS_OBJECT_EVENT_CALLBACK( evaspixmapsink->eo );
604 if (evaspixmapsink->eo) {
605 evas_object_image_native_surface_set(evaspixmapsink->eo, NULL);
606 evaspixmapsink->eo = NULL;
609 GST_DEBUG_OBJECT (evaspixmapsink,"[END]");
613 evas_callback_show_event (void *data, Evas *e, Evas_Object *obj, void *event_info)
615 GstEvasPixmapSink *evaspixmapsink = (GstEvasPixmapSink *)data;
616 GST_INFO_OBJECT (evaspixmapsink,"show evas_image_object(%x) from pid(%d), tid(%u)", obj, getpid(), (unsigned int)pthread_self());
620 evas_callback_hide_event (void *data, Evas *e, Evas_Object *obj, void *event_info)
622 GstEvasPixmapSink *evaspixmapsink = (GstEvasPixmapSink *)data;
623 GST_INFO_OBJECT (evaspixmapsink,"hide evas_image_object(%x) from pid(%d), tid(%u)", obj, getpid(), (unsigned int)pthread_self());
627 static gboolean error_caught = FALSE;
630 gst_evaspixmapsink_handle_xerror (Display * display, XErrorEvent * xevent)
632 char error_msg[1024];
634 XGetErrorText (display, xevent->error_code, error_msg, 1024);
635 GST_ERROR ("evaspixmapsink triggered an XError. error(%s), display(%p), xevent->request_code(%d)", error_msg, display, xevent->request_code);
641 /* This function checks that it is actually really possible to create an image
644 gst_evaspixmapsink_check_xshm_calls (GstXContext * xcontext)
647 XShmSegmentInfo SHMInfo;
649 int (*handler) (Display *, XErrorEvent *);
650 gboolean result = FALSE;
651 gboolean did_attach = FALSE;
653 g_return_val_if_fail (xcontext != NULL, FALSE);
655 /* Sync to ensure any older errors are already processed */
656 XSync (xcontext->disp, FALSE);
658 /* Set defaults so we don't free these later unnecessarily */
659 SHMInfo.shmaddr = ((void *) -1);
662 /* Setting an error handler to catch failure */
663 error_caught = FALSE;
664 handler = XSetErrorHandler (gst_evaspixmapsink_handle_xerror);
666 /* Trying to create a 1x1 picture */
667 GST_DEBUG ("XvShmCreateImage of 1x1");
668 xvimage = XvShmCreateImage (xcontext->disp, xcontext->xv_port_id,
669 xcontext->im_format, NULL, 1, 1, &SHMInfo);
671 /* Might cause an error, sync to ensure it is noticed */
672 XSync (xcontext->disp, FALSE);
673 if (!xvimage || error_caught) {
674 GST_WARNING ("could not XvShmCreateImage a 1x1 image");
677 size = xvimage->data_size;
679 SHMInfo.shmid = shmget (IPC_PRIVATE, size, IPC_CREAT | 0777);
680 if (SHMInfo.shmid == -1) {
681 GST_WARNING ("could not get shared memory of %d bytes", size);
685 SHMInfo.shmaddr = shmat (SHMInfo.shmid, NULL, 0);
686 if (SHMInfo.shmaddr == ((void *) -1)) {
687 GST_WARNING ("Failed to shmat: %s", g_strerror (errno));
688 /* Clean up the shared memory segment */
689 shmctl (SHMInfo.shmid, IPC_RMID, NULL);
693 xvimage->data = SHMInfo.shmaddr;
694 SHMInfo.readOnly = FALSE;
696 if (XShmAttach (xcontext->disp, &SHMInfo) == 0) {
697 GST_WARNING ("Failed to XShmAttach");
698 /* Clean up the shared memory segment */
699 shmctl (SHMInfo.shmid, IPC_RMID, NULL);
703 /* Sync to ensure we see any errors we caused */
704 XSync (xcontext->disp, FALSE);
706 /* Delete the shared memory segment as soon as everyone is attached.
707 * This way, it will be deleted as soon as we detach later, and not
708 * leaked if we crash. */
709 shmctl (SHMInfo.shmid, IPC_RMID, NULL);
712 GST_DEBUG ("XServer ShmAttached to 0x%x, id 0x%lx", SHMInfo.shmid,
716 /* store whether we succeeded in result */
719 GST_WARNING ("MIT-SHM extension check failed at XShmAttach. "
720 "Not using shared memory.");
724 /* Sync to ensure we swallow any errors we caused and reset error_caught */
725 XSync (xcontext->disp, FALSE);
727 error_caught = FALSE;
728 XSetErrorHandler (handler);
731 GST_DEBUG ("XServer ShmDetaching from 0x%x id 0x%lx",
732 SHMInfo.shmid, SHMInfo.shmseg);
733 XShmDetach (xcontext->disp, &SHMInfo);
734 XSync (xcontext->disp, FALSE);
736 if (SHMInfo.shmaddr != ((void *) -1))
737 shmdt (SHMInfo.shmaddr);
742 #endif /* HAVE_XSHM */
744 /* This function destroys a GstEvasPixmap handling XShm availability */
746 gst_evaspixmap_buffer_destroy (GstEvasPixmapBuffer *evaspixmapbuf)
748 GstEvasPixmapSink *evaspixmapsink;
750 evaspixmapsink = evaspixmapbuf->evaspixmapsink;
751 if (G_UNLIKELY (evaspixmapsink == NULL)) {
754 GST_DEBUG_OBJECT (evaspixmapsink, "Destroying buffer");
756 g_return_if_fail (GST_IS_EVASPIXMAPSINK (evaspixmapsink));
758 GST_OBJECT_LOCK (evaspixmapsink);
760 /* We might have some buffers destroyed after changing state to NULL */
761 if (evaspixmapsink->xcontext == NULL) {
762 GST_DEBUG_OBJECT (evaspixmapsink,"Destroying XvImage after Xcontext");
764 /* Need to free the shared memory segment even if the x context
765 * was already cleaned up */
766 if (evaspixmapbuf->SHMInfo.shmaddr != ((void *) -1)) {
767 shmdt (evaspixmapbuf->SHMInfo.shmaddr);
772 g_mutex_lock (evaspixmapsink->x_lock);
775 if (evaspixmapsink->xcontext->use_xshm) {
776 if (evaspixmapbuf->SHMInfo.shmaddr != ((void *) -1)) {
777 GST_DEBUG_OBJECT (evaspixmapsink,"XServer ShmDetaching from 0x%x id 0x%lx", evaspixmapbuf->SHMInfo.shmid, evaspixmapbuf->SHMInfo.shmseg);
778 XShmDetach (evaspixmapsink->xcontext->disp, &evaspixmapbuf->SHMInfo);
779 XSync (evaspixmapsink->xcontext->disp, FALSE);
780 shmdt (evaspixmapbuf->SHMInfo.shmaddr);
782 if (evaspixmapbuf->xvimage)
783 XFree (evaspixmapbuf->xvimage);
785 #endif /* HAVE_XSHM */
787 if (evaspixmapbuf->xvimage) {
788 if (evaspixmapbuf->xvimage->data) {
789 g_free (evaspixmapbuf->xvimage->data);
791 XFree (evaspixmapbuf->xvimage);
795 XSync (evaspixmapsink->xcontext->disp, FALSE);
797 g_mutex_unlock (evaspixmapsink->x_lock);
800 GST_OBJECT_UNLOCK (evaspixmapsink);
801 evaspixmapbuf->evaspixmapsink = NULL;
802 gst_object_unref (evaspixmapsink);
804 GST_MINI_OBJECT_CLASS (evaspixmap_buffer_parent_class)->finalize (GST_MINI_OBJECT(evaspixmapbuf));
810 GST_WARNING ("no sink found");
816 gst_evaspixmap_buffer_finalize (GstEvasPixmapBuffer *evaspixmapbuf)
818 GstEvasPixmapSink *evaspixmapsink;
820 evaspixmapsink = evaspixmapbuf->evaspixmapsink;
821 if (G_UNLIKELY (evaspixmapsink == NULL)) {
822 GST_WARNING_OBJECT (evaspixmapsink,"no sink found");
825 g_return_if_fail (GST_IS_EVASPIXMAPSINK (evaspixmapsink));
827 /* If our geometry changed we can't reuse that image. */
828 GST_LOG_OBJECT (evaspixmapsink,"destroy image as sink is shutting down");
829 gst_evaspixmap_buffer_destroy (evaspixmapbuf);
833 gst_evaspixmap_buffer_free (GstEvasPixmapBuffer *evaspixmapbuf)
835 /* make sure it is not recycled */
836 evaspixmapbuf->width = -1;
837 evaspixmapbuf->height = -1;
838 gst_buffer_unref (GST_BUFFER (evaspixmapbuf));
842 gst_evaspixmap_buffer_init (GstEvasPixmapBuffer *evaspixmapbuf, gpointer g_class)
845 evaspixmapbuf->SHMInfo.shmaddr = ((void *) -1);
846 evaspixmapbuf->SHMInfo.shmid = -1;
851 gst_evaspixmap_buffer_class_init (gpointer g_class, gpointer class_data)
853 GstMiniObjectClass *mini_object_class = GST_MINI_OBJECT_CLASS (g_class);
855 evaspixmap_buffer_parent_class = g_type_class_peek_parent (g_class);
857 mini_object_class->finalize = (GstMiniObjectFinalizeFunction) gst_evaspixmap_buffer_finalize;
861 gst_evaspixmap_buffer_get_type (void)
863 static GType _gst_evaspixmap_buffer_type;
865 if (G_UNLIKELY (_gst_evaspixmap_buffer_type == 0)) {
866 static const GTypeInfo evaspixmap_buffer_info = {
867 sizeof (GstBufferClass),
870 gst_evaspixmap_buffer_class_init,
873 sizeof (GstEvasPixmapBuffer),
875 (GInstanceInitFunc) gst_evaspixmap_buffer_init,
878 _gst_evaspixmap_buffer_type = g_type_register_static (GST_TYPE_BUFFER,
879 "GstEvasPixmapBuffer", &evaspixmap_buffer_info, 0);
881 return _gst_evaspixmap_buffer_type;
884 /* This function handles GstEvasPixmapBuffer creation depending on XShm availability */
885 static GstEvasPixmapBuffer*
886 gst_evaspixmap_buffer_new (GstEvasPixmapSink *evaspixmapsink, GstCaps *caps)
888 GstEvasPixmapBuffer *evaspixmapbuf = NULL;
889 GstStructure *structure = NULL;
890 gboolean succeeded = FALSE;
891 int (*handler) (Display *, XErrorEvent *);
893 g_return_val_if_fail (GST_IS_EVASPIXMAPSINK (evaspixmapsink), NULL);
899 evaspixmapbuf = (GstEvasPixmapBuffer*) gst_mini_object_new (GST_TYPE_EVASPIXMAP_BUFFER);
900 GST_DEBUG_OBJECT (evaspixmapsink,"Creating new EvasPixmapBuffer");
902 structure = gst_caps_get_structure (caps, 0);
904 if (!gst_structure_get_int (structure, "width", &evaspixmapbuf->width) || !gst_structure_get_int (structure, "height", &evaspixmapbuf->height)) {
905 GST_WARNING_OBJECT (evaspixmapsink,"failed getting geometry from caps %" GST_PTR_FORMAT, caps);
908 GST_LOG_OBJECT (evaspixmapsink,"creating %dx%d", evaspixmapbuf->width, evaspixmapbuf->height);
910 GST_LOG_OBJECT (evaspixmapsink,"aligned size %dx%d", evaspixmapsink->aligned_width, evaspixmapsink->aligned_height);
911 if (evaspixmapsink->aligned_width == 0 || evaspixmapsink->aligned_height == 0) {
912 GST_INFO_OBJECT (evaspixmapsink,"aligned size is zero. set size of caps.");
913 evaspixmapsink->aligned_width = evaspixmapbuf->width;
914 evaspixmapsink->aligned_height = evaspixmapbuf->height;
917 evaspixmapbuf->im_format = gst_evaspixmapsink_get_format_from_caps (evaspixmapsink, caps);
918 if (evaspixmapbuf->im_format == -1) {
919 GST_WARNING_OBJECT (evaspixmapsink,"failed to get format from caps %"GST_PTR_FORMAT, caps);
920 GST_ELEMENT_ERROR (evaspixmapsink, RESOURCE, WRITE,("Failed to create output image buffer of %dx%d pixels",
921 evaspixmapbuf->width, evaspixmapbuf->height), ("Invalid input caps"));
925 GST_INFO_OBJECT (evaspixmapsink, "FOURCC format : %c%c%c%c", evaspixmapbuf->im_format, evaspixmapbuf->im_format>>8,
926 evaspixmapbuf->im_format>>16, evaspixmapbuf->im_format>>24);
928 evaspixmapbuf->evaspixmapsink = gst_object_ref (evaspixmapsink);
930 g_mutex_lock (evaspixmapsink->x_lock);
932 /* Sync to ensure we swallow any errors we caused and reset error_caught */
933 XSync (evaspixmapsink->xcontext->disp, FALSE);
935 /* Setting an error handler to catch failure */
936 error_caught = FALSE;
937 handler = XSetErrorHandler (gst_evaspixmapsink_handle_xerror);
940 if (evaspixmapsink->xcontext->use_xshm) {
942 evaspixmapbuf->xvimage = XvShmCreateImage (evaspixmapsink->xcontext->disp, evaspixmapsink->xcontext->xv_port_id, evaspixmapbuf->im_format, NULL,
943 evaspixmapsink->aligned_width, evaspixmapsink->aligned_height, &evaspixmapbuf->SHMInfo);
944 if (!evaspixmapbuf->xvimage || error_caught) {
946 GST_ERROR_OBJECT (evaspixmapsink,"error_caught!");
948 if(!evaspixmapbuf->xvimage) {
949 GST_ERROR_OBJECT (evaspixmapsink,"XvShmCreateImage() failed");
951 g_mutex_unlock (evaspixmapsink->x_lock);
952 /* Reset error handler */
953 error_caught = FALSE;
954 XSetErrorHandler (handler);
956 GST_ELEMENT_ERROR (evaspixmapsink, RESOURCE, WRITE,("Failed to create output image buffer of %dx%d pixels",evaspixmapbuf->width,
957 evaspixmapbuf->height),("could not XvShmCreateImage a %dx%d image",evaspixmapbuf->width, evaspixmapbuf->height));
961 /* we have to use the returned data_size for our shm size */
962 evaspixmapbuf->size = evaspixmapbuf->xvimage->data_size;
963 GST_LOG_OBJECT (evaspixmapsink,"XShm image size is %" G_GSIZE_FORMAT, evaspixmapbuf->size);
965 /* calculate the expected size. This is only for sanity checking the
966 * number we get from X. */
967 switch (evaspixmapbuf->im_format) {
968 case GST_MAKE_FOURCC ('I', '4', '2', '0'):
969 case GST_MAKE_FOURCC ('Y', 'V', '1', '2'):
976 pitches[0] = GST_ROUND_UP_4 (evaspixmapbuf->width);
977 offsets[1] = offsets[0] + pitches[0] * GST_ROUND_UP_2 (evaspixmapbuf->height);
978 pitches[1] = GST_ROUND_UP_8 (evaspixmapbuf->width) / 2;
980 offsets[1] + pitches[1] * GST_ROUND_UP_2 (evaspixmapbuf->height) / 2;
981 pitches[2] = GST_ROUND_UP_8 (pitches[0]) / 2;
983 expected_size = offsets[2] + pitches[2] * GST_ROUND_UP_2 (evaspixmapbuf->height) / 2;
985 for (plane = 0; plane < evaspixmapbuf->xvimage->num_planes; plane++) {
986 GST_DEBUG_OBJECT (evaspixmapsink,"Plane %u has a expected pitch of %d bytes, " "offset of %d",
987 plane, pitches[plane], offsets[plane]);
991 case GST_MAKE_FOURCC ('Y', 'U', 'Y', '2'):
992 case GST_MAKE_FOURCC ('U', 'Y', 'V', 'Y'):
993 expected_size = evaspixmapbuf->height * GST_ROUND_UP_4 (evaspixmapbuf->width * 2);
995 case GST_MAKE_FOURCC ('S', 'T', '1', '2'):
996 case GST_MAKE_FOURCC ('S', 'N', '1', '2'):
997 case GST_MAKE_FOURCC ('S', 'U', 'Y', 'V'):
998 case GST_MAKE_FOURCC ('S', 'U', 'Y', '2'):
999 case GST_MAKE_FOURCC ('S', '4', '2', '0'):
1000 case GST_MAKE_FOURCC ('S', 'Y', 'V', 'Y'):
1001 case GST_MAKE_FOURCC ('I', 'T', 'L', 'V'):
1002 case GST_MAKE_FOURCC ('S', 'R', '3', '2'):
1003 expected_size = sizeof(SCMN_IMGB);
1009 if (expected_size != 0 && evaspixmapbuf->size != expected_size) {
1010 GST_WARNING_OBJECT (evaspixmapsink,"unexpected XShm image size (got %" G_GSIZE_FORMAT ", expected %d)", evaspixmapbuf->size, expected_size);
1013 /* Be verbose about our XvImage stride */
1016 for (plane = 0; plane < evaspixmapbuf->xvimage->num_planes; plane++) {
1017 GST_DEBUG_OBJECT (evaspixmapsink,"Plane %u has a pitch of %d bytes, ""offset of %d", plane,
1018 evaspixmapbuf->xvimage->pitches[plane], evaspixmapbuf->xvimage->offsets[plane]);
1022 evaspixmapbuf->SHMInfo.shmid = shmget (IPC_PRIVATE, evaspixmapbuf->size,IPC_CREAT | 0777);
1023 if (evaspixmapbuf->SHMInfo.shmid == -1) {
1024 g_mutex_unlock (evaspixmapsink->x_lock);
1025 GST_ELEMENT_ERROR (evaspixmapsink, RESOURCE, WRITE,
1026 ("Failed to create output image buffer of %dx%d pixels", evaspixmapbuf->width, evaspixmapbuf->height),
1027 ("could not get shared memory of %" G_GSIZE_FORMAT " bytes",evaspixmapbuf->size));
1028 goto beach_unlocked;
1031 evaspixmapbuf->SHMInfo.shmaddr = shmat (evaspixmapbuf->SHMInfo.shmid, NULL, 0);
1032 if (evaspixmapbuf->SHMInfo.shmaddr == ((void *) -1)) {
1033 g_mutex_unlock (evaspixmapsink->x_lock);
1034 GST_ELEMENT_ERROR (evaspixmapsink, RESOURCE, WRITE,
1035 ("Failed to create output image buffer of %dx%d pixels",
1036 evaspixmapbuf->width, evaspixmapbuf->height),
1037 ("Failed to shmat: %s", g_strerror (errno)));
1038 /* Clean up the shared memory segment */
1039 shmctl (evaspixmapbuf->SHMInfo.shmid, IPC_RMID, NULL);
1040 goto beach_unlocked;
1043 evaspixmapbuf->xvimage->data = evaspixmapbuf->SHMInfo.shmaddr;
1044 evaspixmapbuf->SHMInfo.readOnly = FALSE;
1046 if (XShmAttach (evaspixmapsink->xcontext->disp, &evaspixmapbuf->SHMInfo) == 0) {
1047 /* Clean up the shared memory segment */
1048 shmctl (evaspixmapbuf->SHMInfo.shmid, IPC_RMID, NULL);
1050 g_mutex_unlock (evaspixmapsink->x_lock);
1051 GST_ELEMENT_ERROR (evaspixmapsink, RESOURCE, WRITE,
1052 ("Failed to create output image buffer of %dx%d pixels",
1053 evaspixmapbuf->width, evaspixmapbuf->height), ("Failed to XShmAttach"));
1054 goto beach_unlocked;
1057 XSync (evaspixmapsink->xcontext->disp, FALSE);
1059 /* Delete the shared memory segment as soon as we everyone is attached.
1060 * This way, it will be deleted as soon as we detach later, and not
1061 * leaked if we crash. */
1062 shmctl (evaspixmapbuf->SHMInfo.shmid, IPC_RMID, NULL);
1064 GST_DEBUG_OBJECT (evaspixmapsink,"XServer ShmAttached to 0x%x, id 0x%lx", evaspixmapbuf->SHMInfo.shmid, evaspixmapbuf->SHMInfo.shmseg);
1066 #endif /* HAVE_XSHM */
1068 evaspixmapbuf->xvimage = XvCreateImage (evaspixmapsink->xcontext->disp, evaspixmapsink->xcontext->xv_port_id,
1069 evaspixmapbuf->im_format, NULL, evaspixmapsink->aligned_width, evaspixmapsink->aligned_height);
1070 if (!evaspixmapbuf->xvimage || error_caught) {
1071 g_mutex_unlock (evaspixmapsink->x_lock);
1072 /* Reset error handler */
1073 error_caught = FALSE;
1074 XSetErrorHandler (handler);
1076 GST_ELEMENT_ERROR (evaspixmapsink, RESOURCE, WRITE,
1077 ("Failed to create outputimage buffer of %dx%d pixels",
1078 evaspixmapbuf->width, evaspixmapbuf->height),
1079 ("could not XvCreateImage a %dx%d image",
1080 evaspixmapbuf->width, evaspixmapbuf->height));
1081 goto beach_unlocked;
1084 /* we have to use the returned data_size for our image size */
1085 evaspixmapbuf->size = evaspixmapbuf->xvimage->data_size;
1086 evaspixmapbuf->xvimage->data = g_malloc (evaspixmapbuf->size);
1088 XSync (evaspixmapsink->xcontext->disp, FALSE);
1091 /* Reset error handler */
1092 error_caught = FALSE;
1093 XSetErrorHandler (handler);
1097 GST_BUFFER_DATA (evaspixmapbuf) = (guchar *) evaspixmapbuf->xvimage->data;
1098 GST_BUFFER_SIZE (evaspixmapbuf) = evaspixmapbuf->size;
1100 g_mutex_unlock (evaspixmapsink->x_lock);
1104 gst_evaspixmap_buffer_free (evaspixmapbuf);
1105 evaspixmapbuf = NULL;
1108 return evaspixmapbuf;
1111 /* This function puts a GstEvasPixmapBuffer on a GstEvasPixmapSink's pixmap. Returns FALSE
1112 * if no pixmap was available */
1114 gst_evaspixmap_buffer_put (GstEvasPixmapSink *evaspixmapsink, GstEvasPixmapBuffer *evaspixmapbuf)
1116 GstVideoRectangle result;
1118 GstVideoRectangle src_origin = { 0, 0, 0, 0};
1119 GstVideoRectangle src_input = { 0, 0, 0, 0};
1120 GstVideoRectangle src = { 0, 0, 0, 0};
1121 GstVideoRectangle dst = { 0, 0, 0, 0};
1125 GstXPixmap *xpixmap = NULL;
1127 MMTA_ACUM_ITEM_BEGIN("evaspixmapsink evaspixmap_buffer_put()", FALSE);
1129 /* We take the flow_lock. If expose is in there we don't want to run
1130 concurrently from the data flow thread */
1131 g_mutex_lock (evaspixmapsink->flow_lock);
1133 if (G_UNLIKELY (evaspixmapsink->xpixmap[idx] == NULL)) {
1134 GST_WARNING_OBJECT (evaspixmapsink, "xpixmap is NULL. Skip buffer_put." );
1135 g_mutex_unlock(evaspixmapsink->flow_lock);
1138 if (evaspixmapsink->visible == FALSE) {
1139 GST_WARNING_OBJECT (evaspixmapsink, "visible is FALSE. Skip buffer_put." );
1140 g_mutex_unlock(evaspixmapsink->flow_lock);
1143 if (!evaspixmapbuf) {
1144 GST_WARNING_OBJECT (evaspixmapsink, "evaspixmapbuf is NULL. Skip buffer_put." );
1145 g_mutex_unlock(evaspixmapsink->flow_lock);
1149 g_mutex_lock (evaspixmapsink->pixmap_ref_lock);
1150 if (evaspixmapsink->last_updated_idx == -1) {
1151 /* if it has never been updated any frame in Ecore thread, do below */
1153 xpixmap = evaspixmapsink->xpixmap[idx];
1155 GST_LOG_OBJECT (evaspixmapsink, "last_updated_idx(%d), we use index[%d] of pixmap buffers : pixmap(%d), ref(%d)",
1156 evaspixmapsink->last_updated_idx, idx, xpixmap->pixmap, xpixmap->ref);
1158 for (idx = 0; idx < evaspixmapsink->num_of_pixmaps; idx++) {
1159 if (idx == evaspixmapsink->last_updated_idx) {
1162 xpixmap = evaspixmapsink->xpixmap[idx];
1163 if (xpixmap->ref == 0 && xpixmap->damaged_time == 0) {
1165 GST_LOG_OBJECT (evaspixmapsink, "found an available pixmap(%d) : xpixmap[%d]", xpixmap->pixmap, idx);
1166 GST_INFO_OBJECT (evaspixmapsink,"pixmap ref-count INCREASED : pixmap(%d), refcount(%d)", xpixmap->pixmap, xpixmap->ref);
1171 if (idx == evaspixmapsink->num_of_pixmaps) {
1172 GST_LOG_OBJECT (evaspixmapsink, "Could not find a pixmap with idle state, skip buffer_put." );
1173 g_mutex_unlock (evaspixmapsink->pixmap_ref_lock);
1174 g_mutex_unlock(evaspixmapsink->flow_lock);
1178 g_mutex_unlock (evaspixmapsink->pixmap_ref_lock);
1180 gst_evaspixmapsink_xpixmap_update_geometry(evaspixmapsink, idx);
1183 src_origin.x = src_origin.y = src_input.x = src_input.y = 0;
1184 src_input.w = src_origin.w = evaspixmapsink->video_width;
1185 src_input.h = src_origin.h = evaspixmapsink->video_height;
1186 if (evaspixmapsink->use_origin_size ||
1187 (evaspixmapsink->rotate_angle == DEGREE_0 ||
1188 evaspixmapsink->rotate_angle == DEGREE_180)) {
1189 src.w = src_origin.w;
1190 src.h = src_origin.h;
1192 src.w = src_origin.h;
1193 src.h = src_origin.w;
1196 dst.w = evaspixmapsink->render_rect.w; /* pixmap width */
1197 dst.h = evaspixmapsink->render_rect.h; /* pixmap height */
1199 if (!evaspixmapsink->use_origin_size) {
1200 static Atom atom_rotation = None;
1201 static Atom atom_hflip = None;
1202 static Atom atom_vflip = None;
1203 gboolean set_hflip = FALSE;
1204 gboolean set_vflip = FALSE;
1206 /* compensation of size information (between evas image object's and pixmap's) */
1207 if (evaspixmapsink->sizediff_width > 1) {
1208 if (evaspixmapsink->sizediff_height > 1) {
1209 dst.w -= (evaspixmapsink->sizediff_width >> 1) << 1;
1210 dst.h -= (evaspixmapsink->sizediff_height >> 1) << 1;
1212 dst.w -= (evaspixmapsink->sizediff_width >> 1) << 1;
1214 } else if (evaspixmapsink->sizediff_height > 1) {
1215 dst.h -= (evaspixmapsink->sizediff_height >> 1) << 1;
1218 switch (evaspixmapsink->display_geometry_method) {
1219 case DISP_GEO_METHOD_LETTER_BOX:
1220 gst_video_sink_center_rect (src, dst, &result, TRUE);
1221 result.x += evaspixmapsink->render_rect.x;
1222 result.y += evaspixmapsink->render_rect.y;
1223 GST_DEBUG_OBJECT (evaspixmapsink, "GEO_METHOD : letter box");
1225 case DISP_GEO_METHOD_ORIGIN_SIZE:
1226 gst_video_sink_center_rect (src, dst, &result, FALSE);
1227 gst_video_sink_center_rect (dst, src, &src_input, FALSE);
1228 GST_DEBUG_OBJECT (evaspixmapsink, "GEO_METHOD : origin size");
1229 if (evaspixmapsink->rotate_angle == DEGREE_90 ||
1230 evaspixmapsink->rotate_angle == DEGREE_270) {
1231 src_input.x = src_input.x ^ src_input.y;
1232 src_input.y = src_input.x ^ src_input.y;
1233 src_input.x = src_input.x ^ src_input.y;
1234 src_input.w = src_input.w ^ src_input.h;
1235 src_input.h = src_input.w ^ src_input.h;
1236 src_input.w = src_input.w ^ src_input.h;
1239 case DISP_GEO_METHOD_FULL_SCREEN:
1240 result.x = result.y = 0;
1241 result.w = evaspixmapsink->xpixmap[idx]->width;
1242 result.h = evaspixmapsink->xpixmap[idx]->height;
1243 GST_DEBUG_OBJECT (evaspixmapsink, "GEO_METHOD : full screen");
1245 case DISP_GEO_METHOD_CROPPED_FULL_SCREEN:
1246 GST_DEBUG_OBJECT (evaspixmapsink, "GEO_METHOD : cropped full screen");
1247 gst_video_sink_center_rect(dst, src, &src_input, TRUE);
1248 result.x = result.y = 0;
1251 if (evaspixmapsink->rotate_angle == DEGREE_90 ||
1252 evaspixmapsink->rotate_angle == DEGREE_270) {
1253 src_input.x = src_input.x ^ src_input.y;
1254 src_input.y = src_input.x ^ src_input.y;
1255 src_input.x = src_input.x ^ src_input.y;
1256 src_input.w = src_input.w ^ src_input.h;
1257 src_input.h = src_input.w ^ src_input.h;
1258 src_input.w = src_input.w ^ src_input.h;
1261 case DISP_GEO_METHOD_CUSTOM_ROI:
1262 switch (evaspixmapsink->rotate_angle) {
1264 result.w = evaspixmapsink->dst_roi.h;
1265 result.h = evaspixmapsink->dst_roi.w;
1266 result.x = evaspixmapsink->dst_roi.y;
1267 result.y = evaspixmapsink->xpixmap[idx]->height - evaspixmapsink->dst_roi.x - evaspixmapsink->dst_roi.w;
1270 result.w = evaspixmapsink->dst_roi.w;
1271 result.h = evaspixmapsink->dst_roi.h;
1272 result.x = evaspixmapsink->xpixmap[idx]->width - result.w - evaspixmapsink->dst_roi.x;
1273 result.y = evaspixmapsink->xpixmap[idx]->height - result.h - evaspixmapsink->dst_roi.y;
1276 result.w = evaspixmapsink->dst_roi.h;
1277 result.h = evaspixmapsink->dst_roi.w;
1278 result.x = evaspixmapsink->xpixmap[idx]->width - evaspixmapsink->dst_roi.y - evaspixmapsink->dst_roi.h;
1279 result.y = evaspixmapsink->dst_roi.x;
1282 result.x = evaspixmapsink->dst_roi.x;
1283 result.y = evaspixmapsink->dst_roi.y;
1284 result.w = evaspixmapsink->dst_roi.w;
1285 result.h = evaspixmapsink->dst_roi.h;
1288 GST_LOG_OBJECT(evaspixmapsink, "rotate[%d], ROI input[%d,%d,%dx%d] > result[%d,%d,%dx%d]",
1289 evaspixmapsink->rotate_angle,
1290 evaspixmapsink->dst_roi.x, evaspixmapsink->dst_roi.y, evaspixmapsink->dst_roi.w, evaspixmapsink->dst_roi.h,
1291 result.x, result.y, result.w, result.h);
1296 GST_DEBUG_OBJECT (evaspixmapsink, "GEO_METHOD : src(%dx%d), dst(%dx%d), result(%dx%d), result_x(%d), result_y(%d)",
1297 src.w,src.h,dst.w,dst.h,result.w,result.h,result.x,result.y);
1299 switch( evaspixmapsink->rotate_angle ) {
1312 GST_WARNING_OBJECT( evaspixmapsink, "Unsupported rotation [%d]... set DEGREE 0.",
1313 evaspixmapsink->rotate_angle );
1317 /* set display rotation */
1318 if (atom_rotation == None) {
1319 atom_rotation = XInternAtom(evaspixmapsink->xcontext->disp, "_USER_WM_PORT_ATTRIBUTE_ROTATION", False);
1322 ret = XvSetPortAttribute(evaspixmapsink->xcontext->disp, evaspixmapsink->xcontext->xv_port_id, atom_rotation, rotate);
1323 if (ret != Success) {
1324 GST_ERROR_OBJECT( evaspixmapsink, "XvSetPortAttribute failed[%d]. disp[%x],xv_port_id[%d],atom[%x],rotate[%d]",
1325 ret, evaspixmapsink->xcontext->disp, evaspixmapsink->xcontext->xv_port_id, atom_rotation, rotate );
1329 /* set display flip */
1330 if (atom_hflip == None) {
1331 atom_hflip = XInternAtom(evaspixmapsink->xcontext->disp, "_USER_WM_PORT_ATTRIBUTE_HFLIP", False);
1333 if (atom_vflip == None) {
1334 atom_vflip = XInternAtom(evaspixmapsink->xcontext->disp, "_USER_WM_PORT_ATTRIBUTE_VFLIP", False);
1337 switch (evaspixmapsink->flip) {
1338 case FLIP_HORIZONTAL:
1356 GST_INFO_OBJECT(evaspixmapsink, "set rotate %d HFLIP %d, VFLIP %d", rotate, set_hflip, set_vflip);
1358 ret = XvSetPortAttribute(evaspixmapsink->xcontext->disp, evaspixmapsink->xcontext->xv_port_id, atom_hflip, set_hflip);
1359 if (ret != Success) {
1360 GST_WARNING("set HFLIP failed[%d]. disp[%x],xv_port_id[%d],atom[%x],hflip[%d]",
1361 ret, evaspixmapsink->xcontext->disp, evaspixmapsink->xcontext->xv_port_id, atom_hflip, set_hflip);
1363 ret = XvSetPortAttribute(evaspixmapsink->xcontext->disp, evaspixmapsink->xcontext->xv_port_id, atom_vflip, set_vflip);
1364 if (ret != Success) {
1365 GST_WARNING("set VFLIP failed[%d]. disp[%x],xv_port_id[%d],atom[%x],vflip[%d]",
1366 ret, evaspixmapsink->xcontext->disp, evaspixmapsink->xcontext->xv_port_id, atom_vflip, set_vflip);
1370 result.x = result.y = 0;
1371 result.w = evaspixmapsink->xpixmap[idx]->width;
1372 result.h = evaspixmapsink->xpixmap[idx]->height;
1373 GST_INFO_OBJECT (evaspixmapsink, "USE ORIGIN SIZE, no geometry method, no rotation/flip" );
1376 g_mutex_lock (evaspixmapsink->x_lock);
1378 /* We scale to the pixmap's geometry */
1380 if (evaspixmapsink->xcontext->use_xshm) {
1381 GST_LOG_OBJECT (evaspixmapsink,"XvShmPutImage with image %dx%d and pixmap %dx%d, from xvimage %"
1383 evaspixmapbuf->width, evaspixmapbuf->height,
1384 evaspixmapsink->render_rect.w, evaspixmapsink->render_rect.h, evaspixmapbuf);
1386 /* Trim as proper size */
1387 if (src_input.w % 2 == 1) {
1390 if (src_input.h % 2 == 1) {
1394 GST_LOG_OBJECT (evaspixmapsink, "screen[%dx%d],pixmap[%d,%d,%dx%d],method[%d],rotate[%d],src[%dx%d],dst[%d,%d,%dx%d],input[%d,%d,%dx%d],result[%d,%d,%dx%d]",
1395 evaspixmapsink->scr_w, evaspixmapsink->scr_h,
1396 evaspixmapsink->xpixmap[idx]->x, evaspixmapsink->xpixmap[idx]->y, evaspixmapsink->xpixmap[idx]->width, evaspixmapsink->xpixmap[idx]->height,
1397 evaspixmapsink->display_geometry_method, rotate,
1398 src_origin.w, src_origin.h,
1399 dst.x, dst.y, dst.w, dst.h,
1400 src_input.x, src_input.y, src_input.w, src_input.h,
1401 result.x, result.y, result.w, result.h );
1403 if (evaspixmapsink->visible) {
1404 if (evaspixmapsink->buf_shared_type == BUF_SHARE_METHOD_FD) {
1405 EVASPIXMAPSINK_SET_PIXMAP_ID_TO_GEM_INFO (evaspixmapsink, evaspixmapsink->xpixmap[idx]->pixmap);
1407 ret = XvShmPutImage (evaspixmapsink->xcontext->disp,
1408 evaspixmapsink->xcontext->xv_port_id,
1409 evaspixmapsink->xpixmap[idx]->pixmap,
1410 evaspixmapsink->xpixmap[idx]->gc, evaspixmapbuf->xvimage,
1411 src_input.x, src_input.y, src_input.w, src_input.h,
1412 result.x, result.y, result.w, result.h, FALSE);
1413 GST_LOG_OBJECT (evaspixmapsink, "XvShmPutImage return value [%d]", ret );
1415 GST_WARNING_OBJECT (evaspixmapsink, "visible is FALSE. skip this image..." );
1418 #endif /* HAVE_XSHM */
1420 if (evaspixmapsink->visible) {
1421 XvPutImage (evaspixmapsink->xcontext->disp,
1422 evaspixmapsink->xcontext->xv_port_id,
1423 evaspixmapsink->xpixmap[idx]->pixmap,
1424 evaspixmapsink->xpixmap[idx]->gc, evaspixmapbuf->xvimage,
1425 evaspixmapsink->disp_x, evaspixmapsink->disp_y,
1426 evaspixmapsink->disp_width, evaspixmapsink->disp_height,
1427 result.x, result.y, result.w, result.h);
1429 GST_WARNING_OBJECT (evaspixmapsink, "visible is FALSE. skip this image..." );
1432 XSync (evaspixmapsink->xcontext->disp, FALSE);
1434 g_mutex_unlock (evaspixmapsink->x_lock);
1435 g_mutex_unlock (evaspixmapsink->flow_lock);
1437 MMTA_ACUM_ITEM_END("evaspixmapsink evaspixmap_buffer_put()", FALSE);
1443 drm_init(GstEvasPixmapSink *evaspixmapsink)
1451 char *driverName = NULL;
1452 char *deviceName = NULL;
1453 struct drm_auth auth_arg = {0};
1455 evaspixmapsink->drm_fd = -1;
1457 dpy = XOpenDisplay(0);
1460 if (!DRI2QueryExtension(dpy, &eventBase, &errorBase)) {
1461 GST_ERROR_OBJECT (evaspixmapsink,"failed to DRI2QueryExtension()");
1465 if (!DRI2QueryVersion(dpy, &dri2Major, &dri2Minor)) {
1466 GST_ERROR_OBJECT (evaspixmapsink,"failed to DRI2QueryVersion");
1470 if (!DRI2Connect(dpy, RootWindow(dpy, DefaultScreen(dpy)), &driverName, &deviceName)) {
1471 GST_ERROR_OBJECT (evaspixmapsink,"failed to DRI2Connect");
1475 if (!driverName || !deviceName) {
1476 GST_ERROR_OBJECT (evaspixmapsink,"driverName or deviceName is not valid");
1480 GST_INFO_OBJECT (evaspixmapsink,"Open drm device : %s", deviceName);
1482 /* get the drm_fd though opening the deviceName */
1483 evaspixmapsink->drm_fd = open(deviceName, O_RDWR);
1484 if (evaspixmapsink->drm_fd < 0) {
1485 GST_ERROR_OBJECT (evaspixmapsink,"cannot open drm device (%s)", deviceName);
1489 /* get magic from drm to authentication */
1490 if (ioctl(evaspixmapsink->drm_fd, DRM_IOCTL_GET_MAGIC, &auth_arg)) {
1491 GST_ERROR_OBJECT (evaspixmapsink,"cannot get drm auth magic");
1492 close(evaspixmapsink->drm_fd);
1493 evaspixmapsink->drm_fd = -1;
1497 if (!DRI2Authenticate(dpy, RootWindow(dpy, DefaultScreen(dpy)), auth_arg.magic)) {
1498 GST_ERROR_OBJECT (evaspixmapsink,"cannot get drm authentication from X");
1499 close(evaspixmapsink->drm_fd);
1500 evaspixmapsink->drm_fd = -1;
1504 /* init gem handle */
1505 for (i = 0; i < MAX_GEM_BUFFER_NUM; i++) {
1506 evaspixmapsink->gem_info[i].dmabuf_fd = 0;
1507 evaspixmapsink->gem_info[i].gem_handle = 0;
1508 evaspixmapsink->gem_info[i].gem_name = 0;
1509 evaspixmapsink->gem_info[i].bo = 0;
1510 evaspixmapsink->gem_info[i].ref_pixmap = 0;
1532 drm_fini(GstEvasPixmapSink *evaspixmapsink)
1534 if (evaspixmapsink->drm_fd >= 0) {
1535 GST_INFO_OBJECT (evaspixmapsink,"close drm_fd(%d)", evaspixmapsink->drm_fd);
1536 close(evaspixmapsink->drm_fd);
1537 evaspixmapsink->drm_fd = -1;
1542 drm_init_convert_dmabuf_gemname(GstEvasPixmapSink *evaspixmapsink, int dmabuf_fd)
1544 struct drm_prime_handle prime_arg = {0,};
1545 struct drm_gem_flink flink_arg = {0,};
1548 if (evaspixmapsink->drm_fd < 0) {
1549 GST_ERROR_OBJECT (evaspixmapsink,"DRM is not opened");
1553 if (dmabuf_fd <= 0) {
1554 GST_DEBUG_OBJECT (evaspixmapsink,"Ignore wrong dmabuf fd(%d)", dmabuf_fd); /* temporarily change log level to DEBUG for reducing WARNING level log */
1558 /* check duplicated dmabuf fd */
1559 for (i = 0 ; i < MAX_GEM_BUFFER_NUM ; i++) {
1560 if (evaspixmapsink->gem_info[i].dmabuf_fd == dmabuf_fd) {
1561 GST_LOG_OBJECT (evaspixmapsink,"already got fd(%u) with name(%u)", dmabuf_fd, evaspixmapsink->gem_info[i].gem_name);
1562 return evaspixmapsink->gem_info[i].gem_name;
1565 if (evaspixmapsink->gem_info[i].dmabuf_fd == 0) {
1566 GST_LOG_OBJECT (evaspixmapsink,"empty gem_info[%d] found", i);
1571 if (i == MAX_GEM_BUFFER_NUM) {
1572 GST_WARNING_OBJECT (evaspixmapsink,"too many buffers[dmabuf_fd(%d). skip it]", dmabuf_fd);
1576 evaspixmapsink->gem_info[i].dmabuf_fd = dmabuf_fd;
1577 prime_arg.fd = dmabuf_fd;
1578 if (ioctl(evaspixmapsink->drm_fd, DRM_IOCTL_PRIME_FD_TO_HANDLE, &prime_arg)) {
1579 GST_ERROR_OBJECT (evaspixmapsink,"non dmabuf fd(%d)", dmabuf_fd);
1583 evaspixmapsink->gem_info[i].gem_handle = prime_arg.handle;
1584 GST_LOG_OBJECT (evaspixmapsink,"gem_info[%d].gem_handle = %u", i, prime_arg.handle);
1586 flink_arg.handle = prime_arg.handle;
1587 if (ioctl(evaspixmapsink->drm_fd, DRM_IOCTL_GEM_FLINK, &flink_arg)) {
1588 GST_ERROR_OBJECT (evaspixmapsink,"cannot convert drm handle to name");
1592 evaspixmapsink->gem_info[i].gem_name = flink_arg.name;
1593 GST_LOG_OBJECT (evaspixmapsink,"gem_info[%d].gem_name = %u", i, flink_arg.name);
1595 return flink_arg.name;
1599 tbm_init_convert_bo_gemname(GstEvasPixmapSink *evaspixmapsink, tbm_bo bo)
1604 GST_DEBUG_OBJECT (evaspixmapsink,"Ignore wrong bo(%u)", bo); /* temporarily change log level to DEBUG for reducing WARNING level log */
1608 /* check duplicated dmabuf bo */
1609 for (i = 0 ; i < MAX_GEM_BUFFER_NUM ; i++) {
1610 if (evaspixmapsink->gem_info[i].bo == bo) {
1611 GST_LOG_OBJECT (evaspixmapsink,"already got bo(%u) with name(%u)", bo, evaspixmapsink->gem_info[i].gem_name);
1612 return evaspixmapsink->gem_info[i].gem_name;
1615 if (evaspixmapsink->gem_info[i].bo == 0) {
1616 GST_LOG_OBJECT (evaspixmapsink,"empty gem_info[%d] found", i);
1621 if (i == MAX_GEM_BUFFER_NUM) {
1622 GST_WARNING_OBJECT (evaspixmapsink,"too many buffers[dmabuf_bo(%d). skip it]", bo);
1626 evaspixmapsink->gem_info[i].bo = bo;
1627 evaspixmapsink->gem_info[i].gem_name = tbm_bo_export(bo);
1628 GST_LOG_OBJECT (evaspixmapsink,"gem_info[%d].gem_name = %u", i, evaspixmapsink->gem_info[i].gem_name);
1630 return evaspixmapsink->gem_info[i].gem_name;
1634 drm_fini_close_gem_handle(GstEvasPixmapSink *evaspixmapsink, Pixmap pixmap_id)
1637 if (evaspixmapsink->drm_fd >= 0) {
1638 if (pixmap_id == 0) {
1639 for (i = 0; i < MAX_GEM_BUFFER_NUM; i++) {
1640 if (evaspixmapsink->gem_info[i].dmabuf_fd > 0 || evaspixmapsink->gem_info[i].bo > 0) {
1641 if (evaspixmapsink->buf_shared_type == BUF_SHARE_METHOD_FD) {
1642 GST_INFO_OBJECT (evaspixmapsink,"close gem_handle(%u)", evaspixmapsink->gem_info[i].gem_handle);
1643 drm_close_gem(evaspixmapsink, evaspixmapsink->gem_info[i].gem_handle);
1645 evaspixmapsink->gem_info[i].dmabuf_fd = 0;
1646 evaspixmapsink->gem_info[i].gem_handle = 0;
1647 evaspixmapsink->gem_info[i].gem_name = 0;
1648 evaspixmapsink->gem_info[i].bo = 0;
1649 evaspixmapsink->gem_info[i].ref_pixmap = 0;
1650 GST_LOG_OBJECT (evaspixmapsink,"gem_info[%d] is cleared",i);
1654 for (i = 0; i < MAX_GEM_BUFFER_NUM; i++) {
1655 if (evaspixmapsink->gem_info[i].ref_pixmap == pixmap_id) {
1656 if (evaspixmapsink->buf_shared_type == BUF_SHARE_METHOD_FD) {
1657 GST_INFO_OBJECT (evaspixmapsink,"close gem_handle(%u) for pixmap_id(%d)",
1658 evaspixmapsink->gem_info[i].gem_handle, pixmap_id);
1659 drm_close_gem(evaspixmapsink, evaspixmapsink->gem_info[i].gem_handle);
1661 evaspixmapsink->gem_info[i].dmabuf_fd = 0;
1662 evaspixmapsink->gem_info[i].gem_handle = 0;
1663 evaspixmapsink->gem_info[i].gem_name = 0;
1664 evaspixmapsink->gem_info[i].bo = 0;
1665 evaspixmapsink->gem_info[i].ref_pixmap = 0;
1666 GST_LOG_OBJECT (evaspixmapsink,"gem_info[%d] is cleared",i);
1675 drm_close_gem(GstEvasPixmapSink *evaspixmapsink, unsigned int gem_handle)
1677 struct drm_gem_close close_arg = {0,};
1679 if (evaspixmapsink->drm_fd < 0) {
1680 GST_ERROR_OBJECT (evaspixmapsink,"DRM is not opened");
1684 if (gem_handle == 0) {
1685 GST_ERROR_OBJECT (evaspixmapsink,"invalid gem_handle(%d)",gem_handle);
1689 close_arg.handle = gem_handle;
1690 if (gem_handle > 0 && ioctl(evaspixmapsink->drm_fd, DRM_IOCTL_GEM_CLOSE, &close_arg)) {
1691 GST_ERROR_OBJECT (evaspixmapsink,"cannot close drm gem handle(%d)", gem_handle);
1698 /* This function destroys a GstXPixmap */
1700 gst_evaspixmapsink_xpixmap_destroy (GstEvasPixmapSink *evaspixmapsink, GstXPixmap *xpixmap)
1702 g_return_if_fail (xpixmap != NULL);
1703 g_return_if_fail (GST_IS_EVASPIXMAPSINK (evaspixmapsink));
1705 g_mutex_lock (evaspixmapsink->x_lock);
1707 if(xpixmap->pixmap) {
1708 GST_LOG_OBJECT (evaspixmapsink,"Free pixmap(%d)", xpixmap->pixmap);
1709 XFreePixmap(evaspixmapsink->xcontext->disp, xpixmap->pixmap);
1710 xpixmap->pixmap = 0;
1714 XFreeGC (evaspixmapsink->xcontext->disp, xpixmap->gc);
1717 XSync (evaspixmapsink->xcontext->disp, FALSE);
1719 g_mutex_unlock (evaspixmapsink->x_lock);
1725 gst_evaspixmapsink_xpixmap_update_geometry (GstEvasPixmapSink *evaspixmapsink, int idx)
1728 XWindowAttributes root_attr;
1730 int cur_pixmap_x = 0;
1731 int cur_pixmap_y = 0;
1732 unsigned int cur_pixmap_width = 0;
1733 unsigned int cur_pixmap_height = 0;
1734 unsigned int cur_pixmap_border_width = 0;
1735 unsigned int cur_pixmap_depth = 0;
1737 g_return_if_fail (GST_IS_EVASPIXMAPSINK (evaspixmapsink));
1739 /* Update the window geometry */
1740 g_mutex_lock (evaspixmapsink->x_lock);
1741 if (G_UNLIKELY (evaspixmapsink->xpixmap[idx] == NULL)) {
1742 g_mutex_unlock (evaspixmapsink->x_lock);
1746 /* Get root window and size of current pixmap */
1747 XGetGeometry( evaspixmapsink->xcontext->disp, evaspixmapsink->xpixmap[idx]->pixmap, &root_window,
1748 &cur_pixmap_x, &cur_pixmap_y, /* relative x, y, for pixmap these are alway 0 */
1749 &cur_pixmap_width, &cur_pixmap_height,
1750 &cur_pixmap_border_width, &cur_pixmap_depth ); /* cur_pixmap_border_width, cur_pixmap_depth are not used */
1752 evaspixmapsink->xpixmap[idx]->width = cur_pixmap_width;
1753 evaspixmapsink->xpixmap[idx]->height = cur_pixmap_height;
1755 evaspixmapsink->xpixmap[idx]->x = cur_pixmap_x;
1756 evaspixmapsink->xpixmap[idx]->y = cur_pixmap_y;
1758 /* Get size of root window == size of screen */
1759 XGetWindowAttributes(evaspixmapsink->xcontext->disp, root_window, &root_attr);
1761 evaspixmapsink->scr_w = root_attr.width;
1762 evaspixmapsink->scr_h = root_attr.height;
1764 if (!evaspixmapsink->have_render_rect) {
1765 evaspixmapsink->render_rect.x = evaspixmapsink->render_rect.y = 0;
1766 evaspixmapsink->render_rect.w = cur_pixmap_width;
1767 evaspixmapsink->render_rect.h = cur_pixmap_height;
1770 GST_LOG_OBJECT (evaspixmapsink,"screen size %dx%d, current pixmap geometry %d,%d,%dx%d, render_rect %d,%d,%dx%d",
1771 evaspixmapsink->scr_w, evaspixmapsink->scr_h,
1772 evaspixmapsink->xpixmap[idx]->x, evaspixmapsink->xpixmap[idx]->y,
1773 evaspixmapsink->xpixmap[idx]->width, evaspixmapsink->xpixmap[idx]->height,
1774 evaspixmapsink->render_rect.x, evaspixmapsink->render_rect.y,
1775 evaspixmapsink->render_rect.w, evaspixmapsink->render_rect.h);
1777 g_mutex_unlock (evaspixmapsink->x_lock);
1781 gst_evaspixmapsink_xpixmap_clear (GstEvasPixmapSink *evaspixmapsink, GstXPixmap *xpixmap)
1783 g_return_if_fail (xpixmap != NULL);
1784 g_return_if_fail (GST_IS_EVASPIXMAPSINK (evaspixmapsink));
1786 if (!xpixmap->pixmap) {
1787 GST_WARNING_OBJECT (evaspixmapsink,"pixmap was not created..");
1791 g_mutex_lock (evaspixmapsink->x_lock);
1793 if (!evaspixmapsink->xcontext) {
1794 GST_WARNING_OBJECT (evaspixmapsink,"xcontext is null..");
1795 g_mutex_unlock (evaspixmapsink->x_lock);
1799 if (evaspixmapsink->stop_video) {
1800 XvStopVideo (evaspixmapsink->xcontext->disp, evaspixmapsink->xcontext->xv_port_id, xpixmap->pixmap);
1802 XSync (evaspixmapsink->xcontext->disp, FALSE);
1804 g_mutex_unlock (evaspixmapsink->x_lock);
1806 g_mutex_lock (evaspixmapsink->pixmap_ref_lock);
1807 evaspixmapsink->last_updated_idx = -1;
1809 xpixmap->damaged_time = 0;
1810 g_mutex_unlock (evaspixmapsink->pixmap_ref_lock);
1813 /* This function commits our internal colorbalance settings to our grabbed Xv
1814 port. If the xcontext is not initialized yet it simply returns */
1816 gst_evaspixmapsink_update_colorbalance (GstEvasPixmapSink *evaspixmapsink)
1818 GList *channels = NULL;
1820 g_return_if_fail (GST_IS_EVASPIXMAPSINK (evaspixmapsink));
1822 /* If we haven't initialized the X context we can't update anything */
1823 if (evaspixmapsink->xcontext == NULL)
1826 /* Don't set the attributes if they haven't been changed, to avoid
1827 * rounding errors changing the values */
1828 if (!evaspixmapsink->cb_changed)
1831 /* For each channel of the colorbalance we calculate the correct value
1832 doing range conversion and then set the Xv port attribute to match our
1834 channels = evaspixmapsink->xcontext->channels_list;
1837 if (channels->data && GST_IS_COLOR_BALANCE_CHANNEL (channels->data)) {
1838 GstColorBalanceChannel *channel = NULL;
1841 gdouble convert_coef;
1843 channel = GST_COLOR_BALANCE_CHANNEL (channels->data);
1844 g_object_ref (channel);
1846 /* Our range conversion coef */
1847 convert_coef = (channel->max_value - channel->min_value) / 2000.0;
1849 if (g_ascii_strcasecmp (channel->label, "XV_HUE") == 0) {
1850 value = evaspixmapsink->hue;
1851 } else if (g_ascii_strcasecmp (channel->label, "XV_SATURATION") == 0) {
1852 value = evaspixmapsink->saturation;
1853 } else if (g_ascii_strcasecmp (channel->label, "XV_CONTRAST") == 0) {
1854 value = evaspixmapsink->contrast;
1855 } else if (g_ascii_strcasecmp (channel->label, "XV_BRIGHTNESS") == 0) {
1856 value = evaspixmapsink->brightness;
1858 g_warning ("got an unknown channel %s", channel->label);
1859 g_object_unref (channel);
1863 /* Committing to Xv port */
1864 g_mutex_lock (evaspixmapsink->x_lock);
1866 XInternAtom (evaspixmapsink->xcontext->disp, channel->label, True);
1867 if (prop_atom != None) {
1870 floor (0.5 + (value + 1000) * convert_coef + channel->min_value);
1871 XvSetPortAttribute (evaspixmapsink->xcontext->disp,
1872 evaspixmapsink->xcontext->xv_port_id, prop_atom, xv_value);
1874 g_mutex_unlock (evaspixmapsink->x_lock);
1876 g_object_unref (channel);
1878 channels = g_list_next (channels);
1883 gst_lookup_xv_port_from_adaptor (GstXContext *xcontext, XvAdaptorInfo *adaptors, int adaptor_no)
1888 /* Do we support XvImageMask ? */
1889 if (!(adaptors[adaptor_no].type & XvImageMask)) {
1890 GST_DEBUG ("XV Adaptor %s has no support for XvImageMask", adaptors[adaptor_no].name);
1894 /* We found such an adaptor, looking for an available port */
1895 for (j = 0; j < adaptors[adaptor_no].num_ports && !xcontext->xv_port_id; j++) {
1896 /* We try to grab the port */
1897 res = XvGrabPort (xcontext->disp, adaptors[adaptor_no].base_id + j, 0);
1898 if (Success == res) {
1899 xcontext->xv_port_id = adaptors[adaptor_no].base_id + j;
1900 GST_DEBUG ("XV Adaptor %s with %ld ports", adaptors[adaptor_no].name, adaptors[adaptor_no].num_ports);
1902 GST_DEBUG ("GrabPort %d for XV Adaptor %s failed: %d", j, adaptors[adaptor_no].name, res);
1907 /* This function generates a caps with all supported format by the first
1908 Xv grabable port we find. We store each one of the supported formats in a
1909 format list and append the format to a newly created caps that we return
1910 If this function does not return NULL because of an error, it also grabs
1911 the port via XvGrabPort */
1913 gst_evaspixmapsink_get_xv_support (GstEvasPixmapSink *evaspixmapsink, GstXContext *xcontext)
1916 XvAdaptorInfo *adaptors;
1918 XvImageFormatValues *formats = NULL;
1920 XvEncodingInfo *encodings = NULL;
1921 gulong max_w = G_MAXINT, max_h = G_MAXINT;
1922 GstCaps *caps = NULL;
1923 GstCaps *rgb_caps = NULL;
1925 g_return_val_if_fail (xcontext != NULL, NULL);
1927 /* First let's check that XVideo extension is available */
1928 if (!XQueryExtension (xcontext->disp, "XVideo", &i, &i, &i)) {
1929 GST_ELEMENT_ERROR (evaspixmapsink, RESOURCE, SETTINGS,
1930 ("Could not initialise Xv output"),
1931 ("XVideo extension is not available"));
1935 /* Then we get adaptors list */
1936 if (Success != XvQueryAdaptors (xcontext->disp, xcontext->root,
1937 &xcontext->nb_adaptors, &adaptors)) {
1938 GST_ELEMENT_ERROR (evaspixmapsink, RESOURCE, SETTINGS,
1939 ("Could not initialise Xv output"),
1940 ("Failed getting XV adaptors list"));
1944 xcontext->xv_port_id = 0;
1946 GST_DEBUG_OBJECT (evaspixmapsink,"Found %u XV adaptor(s)", xcontext->nb_adaptors);
1948 xcontext->adaptors =
1949 (gchar **) g_malloc0 (xcontext->nb_adaptors * sizeof (gchar *));
1951 /* Now fill up our adaptor name array */
1952 for (i = 0; i < xcontext->nb_adaptors; i++) {
1953 xcontext->adaptors[i] = g_strdup (adaptors[i].name);
1956 if (evaspixmapsink->adaptor_no < xcontext->nb_adaptors) {
1957 /* Find xv port from user defined adaptor */
1958 gst_lookup_xv_port_from_adaptor (xcontext, adaptors, evaspixmapsink->adaptor_no);
1961 if (!xcontext->xv_port_id) {
1962 /* Now search for an adaptor that supports XvImageMask */
1963 for (i = 0; i < xcontext->nb_adaptors && !xcontext->xv_port_id; i++) {
1964 gst_lookup_xv_port_from_adaptor (xcontext, adaptors, i);
1965 evaspixmapsink->adaptor_no = i;
1969 XvFreeAdaptorInfo (adaptors);
1971 if (!xcontext->xv_port_id) {
1972 evaspixmapsink->adaptor_no = -1;
1973 GST_ELEMENT_ERROR (evaspixmapsink, RESOURCE, BUSY,
1974 ("Could not initialise Xv output"), ("No port available"));
1978 /* Set XV_AUTOPAINT_COLORKEY and XV_DOUBLE_BUFFER and XV_COLORKEY */
1980 int count, todo = 3;
1981 XvAttribute *const attr = XvQueryPortAttributes (xcontext->disp,
1982 xcontext->xv_port_id, &count);
1983 static const char autopaint[] = "XV_AUTOPAINT_COLORKEY";
1984 static const char dbl_buffer[] = "XV_DOUBLE_BUFFER";
1985 static const char colorkey[] = "XV_COLORKEY";
1987 GST_DEBUG_OBJECT (evaspixmapsink,"Checking %d Xv port attributes", count);
1989 evaspixmapsink->have_autopaint_colorkey = FALSE;
1990 evaspixmapsink->have_double_buffer = FALSE;
1991 evaspixmapsink->have_colorkey = FALSE;
1993 for (i = 0; ((i < count) && todo); i++)
1994 if (!strcmp (attr[i].name, autopaint)) {
1995 const Atom atom = XInternAtom (xcontext->disp, autopaint, False);
1997 /* turn on autopaint colorkey */
1998 XvSetPortAttribute (xcontext->disp, xcontext->xv_port_id, atom,
1999 (evaspixmapsink->autopaint_colorkey ? 1 : 0));
2001 evaspixmapsink->have_autopaint_colorkey = TRUE;
2002 } else if (!strcmp (attr[i].name, dbl_buffer)) {
2003 const Atom atom = XInternAtom (xcontext->disp, dbl_buffer, False);
2005 XvSetPortAttribute (xcontext->disp, xcontext->xv_port_id, atom,
2006 (evaspixmapsink->double_buffer ? 1 : 0));
2008 evaspixmapsink->have_double_buffer = TRUE;
2009 } else if (!strcmp (attr[i].name, colorkey)) {
2010 /* Set the colorkey, default is something that is dark but hopefully
2011 * won't randomly appear on the screen elsewhere (ie not black or greys)
2012 * can be overridden by setting "colorkey" property
2014 const Atom atom = XInternAtom (xcontext->disp, colorkey, False);
2016 gboolean set_attr = TRUE;
2019 /* set a colorkey in the right format RGB565/RGB888
2020 * We only handle these 2 cases, because they're the only types of
2021 * devices we've encountered. If we don't recognise it, leave it alone
2023 cr = (evaspixmapsink->colorkey >> 16);
2024 cg = (evaspixmapsink->colorkey >> 8) & 0xFF;
2025 cb = (evaspixmapsink->colorkey) & 0xFF;
2026 switch (xcontext->depth) {
2027 case 16: /* RGB 565 */
2031 ckey = (cr << 11) | (cg << 5) | cb;
2034 case 32: /* RGB 888 / ARGB 8888 */
2035 ckey = (cr << 16) | (cg << 8) | cb;
2038 GST_DEBUG_OBJECT (evaspixmapsink,"Unknown bit depth %d for Xv Colorkey - not adjusting", xcontext->depth);
2044 ckey = CLAMP (ckey, (guint32) attr[i].min_value,
2045 (guint32) attr[i].max_value);
2046 GST_LOG_OBJECT (evaspixmapsink,"Setting color key for display depth %d to 0x%x", xcontext->depth, ckey);
2048 XvSetPortAttribute (xcontext->disp, xcontext->xv_port_id, atom,
2052 evaspixmapsink->have_colorkey = TRUE;
2058 /* Get the list of encodings supported by the adapter and look for the
2059 * XV_IMAGE encoding so we can determine the maximum width and height
2061 XvQueryEncodings (xcontext->disp, xcontext->xv_port_id, &nb_encodings,
2064 for (i = 0; i < nb_encodings; i++) {
2065 GST_LOG_OBJECT (evaspixmapsink,
2066 "Encoding %d, name %s, max wxh %lux%lu rate %d/%d",
2067 i, encodings[i].name, encodings[i].width, encodings[i].height,
2068 encodings[i].rate.numerator, encodings[i].rate.denominator);
2069 if (strcmp (encodings[i].name, "XV_IMAGE") == 0) {
2070 max_w = encodings[i].width;
2071 max_h = encodings[i].height;
2072 evaspixmapsink->scr_w = max_w;
2073 evaspixmapsink->scr_h = max_h;
2077 XvFreeEncodingInfo (encodings);
2079 /* We get all image formats supported by our port */
2080 formats = XvListImageFormats (xcontext->disp,
2081 xcontext->xv_port_id, &nb_formats);
2082 caps = gst_caps_new_empty ();
2083 for (i = 0; i < nb_formats; i++) {
2084 GstCaps *format_caps = NULL;
2085 gboolean is_rgb_format = FALSE;
2087 /* We set the image format of the xcontext to an existing one. This
2088 is just some valid image format for making our xshm calls check before
2089 caps negotiation really happens. */
2090 xcontext->im_format = formats[i].id;
2092 switch (formats[i].type) {
2095 XvImageFormatValues *fmt = &(formats[i]);
2096 gint endianness = G_BIG_ENDIAN;
2098 if (fmt->byte_order == LSBFirst) {
2099 /* our caps system handles 24/32bpp RGB as big-endian. */
2100 if (fmt->bits_per_pixel == 24 || fmt->bits_per_pixel == 32) {
2101 fmt->red_mask = GUINT32_TO_BE (fmt->red_mask);
2102 fmt->green_mask = GUINT32_TO_BE (fmt->green_mask);
2103 fmt->blue_mask = GUINT32_TO_BE (fmt->blue_mask);
2105 if (fmt->bits_per_pixel == 24) {
2106 fmt->red_mask >>= 8;
2107 fmt->green_mask >>= 8;
2108 fmt->blue_mask >>= 8;
2111 endianness = G_LITTLE_ENDIAN;
2114 format_caps = gst_caps_new_simple ("video/x-raw-rgb",
2115 "format", GST_TYPE_FOURCC, formats[i].id,
2116 "endianness", G_TYPE_INT, endianness,
2117 "depth", G_TYPE_INT, fmt->depth,
2118 "bpp", G_TYPE_INT, fmt->bits_per_pixel,
2119 "red_mask", G_TYPE_INT, fmt->red_mask,
2120 "green_mask", G_TYPE_INT, fmt->green_mask,
2121 "blue_mask", G_TYPE_INT, fmt->blue_mask,
2122 "width", GST_TYPE_INT_RANGE, 1, max_w,
2123 "height", GST_TYPE_INT_RANGE, 1, max_h,
2124 "framerate", GST_TYPE_FRACTION_RANGE, 0, 1, G_MAXINT, 1, NULL);
2126 is_rgb_format = TRUE;
2130 format_caps = gst_caps_new_simple ("video/x-raw-yuv",
2131 "format", GST_TYPE_FOURCC, formats[i].id,
2132 "width", GST_TYPE_INT_RANGE, 1, max_w,
2133 "height", GST_TYPE_INT_RANGE, 1, max_h,
2134 "framerate", GST_TYPE_FRACTION_RANGE, 0, 1, G_MAXINT, 1, NULL);
2137 g_assert_not_reached ();
2142 GstEvasPixmapFormat *format = NULL;
2144 format = g_new0 (GstEvasPixmapFormat, 1);
2146 format->format = formats[i].id;
2147 format->caps = gst_caps_copy (format_caps);
2148 xcontext->formats_list = g_list_append (xcontext->formats_list, format);
2151 if (is_rgb_format) {
2152 if (rgb_caps == NULL)
2153 rgb_caps = format_caps;
2155 gst_caps_append (rgb_caps, format_caps);
2157 gst_caps_append (caps, format_caps);
2161 /* Collected all caps into either the caps or rgb_caps structures.
2162 * Append rgb_caps on the end of YUV, so that YUV is always preferred */
2164 gst_caps_append (caps, rgb_caps);
2169 GST_DEBUG_OBJECT (evaspixmapsink,"Generated the following caps: %" GST_PTR_FORMAT, caps);
2171 if (gst_caps_is_empty (caps)) {
2172 gst_caps_unref (caps);
2173 XvUngrabPort (xcontext->disp, xcontext->xv_port_id, 0);
2174 GST_ELEMENT_ERROR (evaspixmapsink, STREAM, WRONG_TYPE, (NULL),
2175 ("No supported format found"));
2183 gst_evaspixmapsink_event_thread (GstEvasPixmapSink * evaspixmapsink)
2185 g_return_val_if_fail (GST_IS_EVASPIXMAPSINK (evaspixmapsink), NULL);
2186 int damage_base = 0;
2187 int damage_err_base = 0;
2188 int damage_case = 0;
2191 Display *disp = NULL;
2193 GST_OBJECT_LOCK (evaspixmapsink);
2195 if (evaspixmapsink->xcontext && evaspixmapsink->xcontext->disp) {
2196 disp = evaspixmapsink->xcontext->disp;
2198 GST_ERROR_OBJECT (evaspixmapsink,"evaspixmapsink->xcontext(->disp) is not ready");
2202 if (!XDamageQueryExtension(evaspixmapsink->xcontext->disp, &damage_base, &damage_err_base)) {
2203 GST_ERROR_OBJECT (evaspixmapsink,"XDamageQueryExtension() failed");
2206 damage_case = (int)damage_base + XDamageNotify;
2208 while (evaspixmapsink->running) {
2209 GST_OBJECT_UNLOCK (evaspixmapsink);
2211 g_mutex_lock (evaspixmapsink->x_lock);
2212 while (XPending (disp)) {
2213 XNextEvent (disp, &e);
2214 g_mutex_unlock (evaspixmapsink->x_lock);
2215 if (e.type == damage_case ) {
2216 XDamageNotifyEvent *damage_ev = (XDamageNotifyEvent *)&e;
2217 for (i = 0; i < evaspixmapsink->num_of_pixmaps; i++) {
2218 GstXPixmap *xpixmap = evaspixmapsink->xpixmap[i];
2219 if (xpixmap && damage_ev->drawable == xpixmap->pixmap) {
2220 g_mutex_lock(evaspixmapsink->pixmap_ref_lock);
2222 /* set it only if damage event comes from _buffer_put() */
2223 xpixmap->damaged_time = (gint)get_millis_time();
2225 g_mutex_unlock(evaspixmapsink->pixmap_ref_lock);
2226 GST_DEBUG_OBJECT (evaspixmapsink,"event_handler : got a damage event for pixmap(%d), refcount(%d), damaged_time(%d)",
2227 xpixmap->pixmap, xpixmap->ref, xpixmap->damaged_time);
2228 if (evaspixmapsink->epipe_request_count > EPIPE_REQUEST_LIMIT) {
2229 GST_WARNING_OBJECT (evaspixmapsink,"event_handler : epipe_request_count(%d), skip ecore_pipe_write()", evaspixmapsink->epipe_request_count);
2231 __ta__("evaspixmapsink ecore_pipe_write", ecore_pipe_write(evaspixmapsink->epipe, evaspixmapsink, sizeof(GstEvasPixmapSink)););
2232 evaspixmapsink->epipe_request_count++;
2233 GST_DEBUG_OBJECT (evaspixmapsink,"event_handler : after call ecore_pipe_write() for pixmap(%d)", xpixmap->pixmap);
2235 g_mutex_lock (evaspixmapsink->x_lock);
2236 XDamageSubtract (evaspixmapsink->xcontext->disp, evaspixmapsink->damage[i], None, None );
2237 g_mutex_unlock (evaspixmapsink->x_lock);
2239 if (evaspixmapsink->buf_shared_type == BUF_SHARE_METHOD_FD) {
2240 if (GST_STATE(evaspixmapsink) == GST_STATE_PLAYING) {
2241 drm_fini_close_gem_handle(evaspixmapsink, xpixmap->pixmap);
2247 if (i == evaspixmapsink->num_of_pixmaps) {
2248 GST_WARNING_OBJECT (evaspixmapsink,"event_handler : could not find corresponding pixmap with this damage event(%d)", damage_ev->drawable);
2251 GST_LOG_OBJECT (evaspixmapsink,"event_handler : unidentified event(%d)", e.type);
2252 g_mutex_lock (evaspixmapsink->x_lock);
2255 g_mutex_lock (evaspixmapsink->x_lock);
2257 //XSync (disp, FALSE);
2258 g_mutex_unlock (evaspixmapsink->x_lock);
2260 g_usleep (G_USEC_PER_SEC / 40);
2261 GST_OBJECT_LOCK (evaspixmapsink);
2263 GST_OBJECT_UNLOCK (evaspixmapsink);
2268 gst_evaspixmapsink_manage_event_thread (GstEvasPixmapSink *evaspixmapsink)
2270 /* don't start the thread too early */
2271 if (evaspixmapsink->xcontext == NULL) {
2272 GST_ERROR_OBJECT (evaspixmapsink,"xcontext is NULL..");
2276 GST_OBJECT_LOCK (evaspixmapsink);
2278 if (!evaspixmapsink->event_thread) {
2279 /* Setup our event listening thread */
2280 GST_DEBUG_OBJECT (evaspixmapsink,"run xevent thread");
2281 evaspixmapsink->running = TRUE;
2282 evaspixmapsink->event_thread = g_thread_create ( (GThreadFunc) gst_evaspixmapsink_event_thread, evaspixmapsink, TRUE, NULL);
2284 GST_WARNING_OBJECT (evaspixmapsink,"there already existed the event_thread.. keep going");
2285 /* Do not finalize the thread in here, Only finalize the thread by calling gst_evaspixmapsink_reset() */
2288 GST_OBJECT_UNLOCK (evaspixmapsink);
2292 /* This function calculates the pixel aspect ratio based on the properties
2293 * in the xcontext structure and stores it there. */
2295 gst_evaspixmapsink_calculate_pixel_aspect_ratio (GstXContext *xcontext)
2297 static const gint par[][2] = {
2298 {1, 1}, /* regular screen */
2299 {16, 15}, /* PAL TV */
2300 {11, 10}, /* 525 line Rec.601 video */
2301 {54, 59}, /* 625 line Rec.601 video */
2302 {64, 45}, /* 1280x1024 on 16:9 display */
2303 {5, 3}, /* 1280x1024 on 4:3 display */
2304 {4, 3} /* 800x600 on 16:9 display */
2311 #define DELTA(idx) (ABS (ratio - ((gdouble) par[idx][0] / par[idx][1])))
2313 /* first calculate the "real" ratio based on the X values;
2314 * which is the "physical" w/h divided by the w/h in pixels of the display */
2315 ratio = (gdouble) (xcontext->widthmm * xcontext->height)
2316 / (xcontext->heightmm * xcontext->width);
2318 /* DirectFB's X in 720x576 reports the physical dimensions wrong, so
2320 if (xcontext->width == 720 && xcontext->height == 576) {
2321 ratio = 4.0 * 576 / (3.0 * 720);
2323 GST_DEBUG ("calculated pixel aspect ratio: %f", ratio);
2324 /* now find the one from par[][2] with the lowest delta to the real one */
2328 for (i = 1; i < sizeof (par) / (sizeof (gint) * 2); ++i) {
2329 gdouble this_delta = DELTA (i);
2331 if (this_delta < delta) {
2337 GST_DEBUG ("Decided on index %d (%d/%d)", index,
2338 par[index][0], par[index][1]);
2340 g_free (xcontext->par);
2341 xcontext->par = g_new0 (GValue, 1);
2342 g_value_init (xcontext->par, GST_TYPE_FRACTION);
2343 gst_value_set_fraction (xcontext->par, par[index][0], par[index][1]);
2344 GST_DEBUG ("set xcontext PAR to %d/%d",
2345 gst_value_get_fraction_numerator (xcontext->par),
2346 gst_value_get_fraction_denominator (xcontext->par));
2349 /* This function gets the X Display and global info about it. Everything is
2350 stored in our object and will be cleaned when the object is disposed. Note
2351 here that caps for supported format are generated without any window or
2354 gst_evaspixmapsink_xcontext_get (GstEvasPixmapSink *evaspixmapsink)
2356 GstXContext *xcontext = NULL;
2357 XPixmapFormatValues *px_formats = NULL;
2358 gint nb_formats = 0, i, j, N_attr;
2359 XvAttribute *xv_attr;
2361 const char *channels[4] = { "XV_HUE", "XV_SATURATION", "XV_BRIGHTNESS", "XV_CONTRAST"};
2363 g_return_val_if_fail (GST_IS_EVASPIXMAPSINK (evaspixmapsink), NULL);
2365 xcontext = g_new0 (GstXContext, 1);
2366 xcontext->im_format = 0;
2368 g_mutex_lock (evaspixmapsink->x_lock);
2370 xcontext->disp = XOpenDisplay (evaspixmapsink->display_name);
2372 if (!xcontext->disp) {
2373 g_mutex_unlock (evaspixmapsink->x_lock);
2375 GST_ELEMENT_ERROR (evaspixmapsink, RESOURCE, WRITE, ("Could not initialise Xv output"), ("Could not open display"));
2379 xcontext->screen = DefaultScreenOfDisplay (xcontext->disp);
2380 xcontext->screen_num = DefaultScreen (xcontext->disp);
2381 xcontext->visual = DefaultVisual (xcontext->disp, xcontext->screen_num);
2382 xcontext->root = DefaultRootWindow (xcontext->disp);
2383 xcontext->white = XWhitePixel (xcontext->disp, xcontext->screen_num);
2384 xcontext->black = XBlackPixel (xcontext->disp, xcontext->screen_num);
2385 xcontext->depth = DefaultDepthOfScreen (xcontext->screen);
2387 xcontext->width = DisplayWidth (xcontext->disp, xcontext->screen_num);
2388 xcontext->height = DisplayHeight (xcontext->disp, xcontext->screen_num);
2389 xcontext->widthmm = DisplayWidthMM (xcontext->disp, xcontext->screen_num);
2390 xcontext->heightmm = DisplayHeightMM (xcontext->disp, xcontext->screen_num);
2392 GST_DEBUG_OBJECT (evaspixmapsink,"X reports %dx%d pixels and %d mm x %d mm", xcontext->width, xcontext->height, xcontext->widthmm, xcontext->heightmm);
2394 gst_evaspixmapsink_calculate_pixel_aspect_ratio (xcontext);
2395 /* We get supported pixmap formats at supported depth */
2396 px_formats = XListPixmapFormats (xcontext->disp, &nb_formats);
2399 XCloseDisplay (xcontext->disp);
2400 g_mutex_unlock (evaspixmapsink->x_lock);
2401 g_free (xcontext->par);
2403 GST_ELEMENT_ERROR (evaspixmapsink, RESOURCE, SETTINGS,
2404 ("Could not initialise Xv output"), ("Could not get pixel formats"));
2408 /* We get bpp value corresponding to our running depth */
2409 for (i = 0; i < nb_formats; i++) {
2410 if (px_formats[i].depth == xcontext->depth)
2411 xcontext->bpp = px_formats[i].bits_per_pixel;
2416 xcontext->endianness = (ImageByteOrder (xcontext->disp) == LSBFirst) ? G_LITTLE_ENDIAN : G_BIG_ENDIAN;
2418 /* our caps system handles 24/32bpp RGB as big-endian. */
2419 if ((xcontext->bpp == 24 || xcontext->bpp == 32) && xcontext->endianness == G_LITTLE_ENDIAN) {
2420 xcontext->endianness = G_BIG_ENDIAN;
2421 xcontext->visual->red_mask = GUINT32_TO_BE (xcontext->visual->red_mask);
2422 xcontext->visual->green_mask = GUINT32_TO_BE (xcontext->visual->green_mask);
2423 xcontext->visual->blue_mask = GUINT32_TO_BE (xcontext->visual->blue_mask);
2424 if (xcontext->bpp == 24) {
2425 xcontext->visual->red_mask >>= 8;
2426 xcontext->visual->green_mask >>= 8;
2427 xcontext->visual->blue_mask >>= 8;
2431 xcontext->caps = gst_evaspixmapsink_get_xv_support (evaspixmapsink, xcontext);
2433 if (!xcontext->caps) {
2434 XCloseDisplay (xcontext->disp);
2435 g_mutex_unlock (evaspixmapsink->x_lock);
2436 g_free (xcontext->par);
2438 /* GST_ELEMENT_ERROR is thrown by gst_evaspixmapsink_get_xv_support */
2442 /* Search for XShm extension support */
2443 if (XShmQueryExtension (xcontext->disp) && gst_evaspixmapsink_check_xshm_calls (xcontext)) {
2444 xcontext->use_xshm = TRUE;
2445 GST_DEBUG_OBJECT (evaspixmapsink,"evaspixmapsink is using XShm extension");
2447 #endif /* HAVE_XSHM */
2449 xcontext->use_xshm = FALSE;
2450 GST_DEBUG_OBJECT (evaspixmapsink,"evaspixmapsink is not using XShm extension");
2453 xv_attr = XvQueryPortAttributes (xcontext->disp, xcontext->xv_port_id, &N_attr);
2455 /* Generate the channels list */
2456 for (i = 0; i < (sizeof (channels) / sizeof (char *)); i++) {
2457 XvAttribute *matching_attr = NULL;
2459 /* Retrieve the property atom if it exists. If it doesn't exist,
2460 * the attribute itself must not either, so we can skip */
2461 prop_atom = XInternAtom (xcontext->disp, channels[i], True);
2462 if (prop_atom == None) {
2466 if (xv_attr != NULL) {
2467 for (j = 0; j < N_attr && matching_attr == NULL; ++j) {
2468 if (!g_ascii_strcasecmp (channels[i], xv_attr[j].name)) {
2469 matching_attr = xv_attr + j;
2474 if (matching_attr) {
2475 GstColorBalanceChannel *channel;
2476 channel = g_object_new (GST_TYPE_COLOR_BALANCE_CHANNEL, NULL);
2477 channel->label = g_strdup (channels[i]);
2478 channel->min_value = matching_attr->min_value;
2479 channel->max_value = matching_attr->max_value;
2481 xcontext->channels_list = g_list_append (xcontext->channels_list, channel);
2483 /* If the colorbalance settings have not been touched we get Xv values
2484 as defaults and update our internal variables */
2485 if (!evaspixmapsink->cb_changed) {
2487 XvGetPortAttribute (xcontext->disp, xcontext->xv_port_id, prop_atom, &val);
2488 /* Normalize val to [-1000, 1000] */
2489 val = floor (0.5 + -1000 + 2000 * (val - channel->min_value) / (double) (channel->max_value - channel->min_value));
2491 if (!g_ascii_strcasecmp (channels[i], "XV_HUE")) {
2492 evaspixmapsink->hue = val;
2493 } else if (!g_ascii_strcasecmp (channels[i], "XV_SATURATION")) {
2494 evaspixmapsink->saturation = val;
2495 } else if (!g_ascii_strcasecmp (channels[i], "XV_BRIGHTNESS")) {
2496 evaspixmapsink->brightness = val;
2497 } else if (!g_ascii_strcasecmp (channels[i], "XV_CONTRAST")) {
2498 evaspixmapsink->contrast = val;
2508 g_mutex_unlock (evaspixmapsink->x_lock);
2513 /* This function cleans the X context. Closing the Display, releasing the XV
2514 port and unrefing the caps for supported formats. */
2516 gst_evaspixmapsink_xcontext_clear (GstEvasPixmapSink *evaspixmapsink)
2518 GList *formats_list, *channels_list;
2519 GstXContext *xcontext;
2522 g_return_if_fail (GST_IS_EVASPIXMAPSINK (evaspixmapsink));
2524 GST_OBJECT_LOCK (evaspixmapsink);
2525 if (evaspixmapsink->xcontext == NULL) {
2526 GST_OBJECT_UNLOCK (evaspixmapsink);
2530 /* Take the XContext from the sink and clean it up */
2531 xcontext = evaspixmapsink->xcontext;
2532 evaspixmapsink->xcontext = NULL;
2534 GST_OBJECT_UNLOCK (evaspixmapsink);
2536 formats_list = xcontext->formats_list;
2538 while (formats_list) {
2539 GstEvasPixmapFormat *format = formats_list->data;
2541 gst_caps_unref (format->caps);
2543 formats_list = g_list_next (formats_list);
2546 if (xcontext->formats_list)
2547 g_list_free (xcontext->formats_list);
2549 channels_list = xcontext->channels_list;
2551 while (channels_list) {
2552 GstColorBalanceChannel *channel = channels_list->data;
2554 g_object_unref (channel);
2555 channels_list = g_list_next (channels_list);
2558 if (xcontext->channels_list)
2559 g_list_free (xcontext->channels_list);
2561 gst_caps_unref (xcontext->caps);
2563 for (i = 0; i < xcontext->nb_adaptors; i++) {
2564 g_free (xcontext->adaptors[i]);
2567 g_free (xcontext->adaptors);
2569 g_free (xcontext->par);
2571 g_mutex_lock (evaspixmapsink->x_lock);
2573 GST_DEBUG_OBJECT (evaspixmapsink,"Closing display and freeing X Context");
2575 XvUngrabPort (xcontext->disp, xcontext->xv_port_id, 0);
2577 XCloseDisplay (xcontext->disp);
2579 g_mutex_unlock (evaspixmapsink->x_lock);
2586 /* This function tries to get a format matching with a given caps in the
2587 supported list of formats we generated in gst_evaspixmapsink_get_xv_support */
2589 gst_evaspixmapsink_get_format_from_caps (GstEvasPixmapSink *evaspixmapsink, GstCaps *caps)
2593 g_return_val_if_fail (GST_IS_EVASPIXMAPSINK (evaspixmapsink), 0);
2595 list = evaspixmapsink->xcontext->formats_list;
2598 GstEvasPixmapFormat *format = list->data;
2601 if (gst_caps_can_intersect (caps, format->caps)) {
2602 return format->format;
2605 list = g_list_next (list);
2612 gst_evaspixmapsink_getcaps (GstBaseSink *bsink)
2614 GstEvasPixmapSink *evaspixmapsink;
2616 evaspixmapsink = GST_EVASPIXMAPSINK (bsink);
2618 if (evaspixmapsink->xcontext)
2619 return gst_caps_ref (evaspixmapsink->xcontext->caps);
2622 gst_caps_copy (gst_pad_get_pad_template_caps (GST_VIDEO_SINK_PAD
2627 gst_evaspixmapsink_setcaps (GstBaseSink *bsink, GstCaps *caps)
2629 GstEvasPixmapSink *evaspixmapsink;
2630 GstStructure *structure;
2631 guint32 im_format = 0;
2633 gint video_width, video_height;
2634 gint disp_x, disp_y;
2635 gint disp_width, disp_height;
2636 gint video_par_n, video_par_d; /* video's PAR */
2637 gint display_par_n, display_par_d; /* display's PAR */
2638 const GValue *caps_par;
2639 const GValue *caps_disp_reg;
2642 gboolean enable_last_buffer;
2644 evaspixmapsink = GST_EVASPIXMAPSINK (bsink);
2646 GST_DEBUG_OBJECT (evaspixmapsink,"In setcaps. Possible caps %" GST_PTR_FORMAT ", setting caps %" GST_PTR_FORMAT, evaspixmapsink->xcontext->caps, caps);
2648 if (!gst_caps_can_intersect (evaspixmapsink->xcontext->caps, caps)) {
2649 goto incompatible_caps;
2652 structure = gst_caps_get_structure (caps, 0);
2653 ret = gst_structure_get_int (structure, "width", &video_width);
2654 ret &= gst_structure_get_int (structure, "height", &video_height);
2655 fps = gst_structure_get_value (structure, "framerate");
2656 ret &= (fps != NULL);
2659 goto incomplete_caps;
2662 evaspixmapsink->aligned_width = video_width;
2663 evaspixmapsink->aligned_height = video_height;
2665 /* get enable-last-buffer */
2666 g_object_get(G_OBJECT(evaspixmapsink), "enable-last-buffer", &enable_last_buffer, NULL);
2667 GST_INFO_OBJECT (evaspixmapsink,"current enable-last-buffer : %d", enable_last_buffer);
2668 /* flush if enable-last-buffer is TRUE */
2669 if (enable_last_buffer) {
2670 GST_INFO_OBJECT (evaspixmapsink,"flush last-buffer");
2671 g_object_set(G_OBJECT(evaspixmapsink), "enable-last-buffer", FALSE, NULL);
2672 g_object_set(G_OBJECT(evaspixmapsink), "enable-last-buffer", TRUE, NULL);
2675 evaspixmapsink->fps_n = gst_value_get_fraction_numerator (fps);
2676 evaspixmapsink->fps_d = gst_value_get_fraction_denominator (fps);
2678 evaspixmapsink->video_width = video_width;
2679 evaspixmapsink->video_height = video_height;
2681 im_format = gst_evaspixmapsink_get_format_from_caps (evaspixmapsink, caps);
2682 if (im_format == -1) {
2683 goto invalid_format;
2686 /* get aspect ratio from caps if it's present, and
2687 * convert video width and height to a display width and height
2688 * using wd / hd = wv / hv * PARv / PARd */
2690 /* get video's PAR */
2691 caps_par = gst_structure_get_value (structure, "pixel-aspect-ratio");
2693 video_par_n = gst_value_get_fraction_numerator (caps_par);
2694 video_par_d = gst_value_get_fraction_denominator (caps_par);
2699 /* get display's PAR */
2700 if (evaspixmapsink->par) {
2701 display_par_n = gst_value_get_fraction_numerator (evaspixmapsink->par);
2702 display_par_d = gst_value_get_fraction_denominator (evaspixmapsink->par);
2708 /* get the display region */
2709 caps_disp_reg = gst_structure_get_value (structure, "display-region");
2710 if (caps_disp_reg) {
2711 disp_x = g_value_get_int (gst_value_array_get_value (caps_disp_reg, 0));
2712 disp_y = g_value_get_int (gst_value_array_get_value (caps_disp_reg, 1));
2713 disp_width = g_value_get_int (gst_value_array_get_value (caps_disp_reg, 2));
2714 disp_height = g_value_get_int (gst_value_array_get_value (caps_disp_reg, 3));
2716 disp_x = disp_y = 0;
2717 disp_width = video_width;
2718 disp_height = video_height;
2721 if (!gst_video_calculate_display_ratio (&num, &den, video_width, video_height, video_par_n, video_par_d, display_par_n, display_par_d)) {
2725 evaspixmapsink->disp_x = disp_x;
2726 evaspixmapsink->disp_y = disp_y;
2727 evaspixmapsink->disp_width = disp_width;
2728 evaspixmapsink->disp_height = disp_height;
2730 GST_DEBUG_OBJECT (evaspixmapsink,"video width/height: %dx%d, calculated display ratio: %d/%d", video_width, video_height, num, den);
2732 /* now find a width x height that respects this display ratio.
2733 * prefer those that have one of w/h the same as the incoming video
2734 * using wd / hd = num / den */
2736 /* start with same height, because of interlaced video */
2737 /* check hd / den is an integer scale factor, and scale wd with the PAR */
2738 if (video_height % den == 0) {
2739 GST_DEBUG_OBJECT (evaspixmapsink,"keeping video height");
2740 GST_VIDEO_SINK_WIDTH (evaspixmapsink) = (guint) gst_util_uint64_scale_int (video_height, num, den);
2741 GST_VIDEO_SINK_HEIGHT (evaspixmapsink) = video_height;
2742 } else if (video_width % num == 0) {
2743 GST_DEBUG_OBJECT (evaspixmapsink,"keeping video width");
2744 GST_VIDEO_SINK_WIDTH (evaspixmapsink) = video_width;
2745 GST_VIDEO_SINK_HEIGHT (evaspixmapsink) = (guint) gst_util_uint64_scale_int (video_width, den, num);
2747 GST_DEBUG_OBJECT (evaspixmapsink,"approximating while keeping video height");
2748 GST_VIDEO_SINK_WIDTH (evaspixmapsink) = (guint) gst_util_uint64_scale_int (video_height, num, den);
2749 GST_VIDEO_SINK_HEIGHT (evaspixmapsink) = video_height;
2751 GST_DEBUG_OBJECT (evaspixmapsink,"scaling to %dx%d", GST_VIDEO_SINK_WIDTH (evaspixmapsink), GST_VIDEO_SINK_HEIGHT (evaspixmapsink));
2753 /* Creating our window and our image with the display size in pixels */
2754 if (GST_VIDEO_SINK_WIDTH (evaspixmapsink) <= 0 || GST_VIDEO_SINK_HEIGHT (evaspixmapsink) <= 0) {
2755 goto no_display_size;
2758 g_mutex_lock (evaspixmapsink->flow_lock);
2760 /* We renew our evaspixmap buffer only if size or format changed;
2761 * the evaspixmap buffer is the same size as the video pixel size */
2762 if ((evaspixmapsink->evas_pixmap_buf) && ((im_format != evaspixmapsink->evas_pixmap_buf->im_format)
2763 || (video_width != evaspixmapsink->evas_pixmap_buf->width) || (video_height != evaspixmapsink->evas_pixmap_buf->height))) {
2764 GST_DEBUG_OBJECT (evaspixmapsink,"old format %" GST_FOURCC_FORMAT ", new format %" GST_FOURCC_FORMAT,
2765 GST_FOURCC_ARGS (evaspixmapsink->evas_pixmap_buf->im_format), GST_FOURCC_ARGS (im_format));
2766 GST_DEBUG_OBJECT (evaspixmapsink,"renewing evaspixmap buffer");
2767 gst_buffer_unref (GST_BUFFER (evaspixmapsink->evas_pixmap_buf));
2768 evaspixmapsink->evas_pixmap_buf = NULL;
2771 g_mutex_unlock (evaspixmapsink->flow_lock);
2773 if (evaspixmapsink->eo) {
2774 if (!gst_evaspixmapsink_xpixmap_link (evaspixmapsink)) {
2775 GST_ERROR_OBJECT (evaspixmapsink,"link evas image object with pixmap failed...");
2778 gst_evaspixmapsink_manage_event_thread (evaspixmapsink);
2781 GST_ERROR_OBJECT (evaspixmapsink,"setcaps success, but there is no evas image object..");
2790 GST_ERROR_OBJECT (evaspixmapsink,"caps incompatible");
2795 GST_DEBUG_OBJECT (evaspixmapsink,"Failed to retrieve either width, ""height or framerate from intersected caps");
2800 GST_DEBUG_OBJECT (evaspixmapsink,"Could not locate image format from caps %" GST_PTR_FORMAT, caps);
2805 GST_ELEMENT_ERROR (evaspixmapsink, CORE, NEGOTIATION, (NULL), ("Error calculating the output display ratio of the video."));
2810 GST_ELEMENT_ERROR (evaspixmapsink, CORE, NEGOTIATION, (NULL), ("Error calculating the output display ratio of the video."));
2815 static GstStateChangeReturn
2816 gst_evaspixmapsink_change_state (GstElement *element, GstStateChange transition)
2818 GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
2819 GstEvasPixmapSink *evaspixmapsink;
2821 evaspixmapsink = GST_EVASPIXMAPSINK (element);
2823 switch (transition) {
2824 case GST_STATE_CHANGE_NULL_TO_READY:
2825 g_mutex_lock (evaspixmapsink->flow_lock);
2826 GST_WARNING_OBJECT (evaspixmapsink,"GST_STATE_CHANGE_NULL_TO_READY");
2828 /* open drm to use gem */
2829 if (drm_init(evaspixmapsink)) {
2830 GST_ERROR_OBJECT (evaspixmapsink,"drm_init() failure");
2831 g_mutex_unlock (evaspixmapsink->flow_lock);
2832 return GST_STATE_CHANGE_FAILURE;
2835 /* check if there exist evas image object, need to write code related to making internal evas image object */
2836 if (!is_evas_image_object (evaspixmapsink->eo)) {
2837 GST_ERROR_OBJECT (evaspixmapsink,"There is no evas image object..");
2838 g_mutex_unlock (evaspixmapsink->flow_lock);
2839 return GST_STATE_CHANGE_FAILURE;
2842 /* Set xcontext and display */
2843 if (!evaspixmapsink->xcontext) {
2844 evaspixmapsink->xcontext = gst_evaspixmapsink_xcontext_get (evaspixmapsink);
2845 if (!evaspixmapsink->xcontext) {
2846 GST_ERROR_OBJECT (evaspixmapsink,"could not get xcontext..");
2847 g_mutex_unlock (evaspixmapsink->flow_lock);
2848 return GST_STATE_CHANGE_FAILURE;
2852 /* update object's par with calculated one if not set yet */
2853 if (!evaspixmapsink->par) {
2854 evaspixmapsink->par = g_new0 (GValue, 1);
2855 gst_value_init_and_copy (evaspixmapsink->par, evaspixmapsink->xcontext->par);
2856 GST_DEBUG_OBJECT (evaspixmapsink,"set calculated PAR on object's PAR");
2859 /* call XSynchronize with the current value of synchronous */
2860 GST_DEBUG_OBJECT (evaspixmapsink,"XSynchronize called with %s", evaspixmapsink->synchronous ? "TRUE" : "FALSE");
2861 XSynchronize (evaspixmapsink->xcontext->disp, evaspixmapsink->synchronous);
2862 gst_evaspixmapsink_update_colorbalance (evaspixmapsink);
2864 g_mutex_unlock (evaspixmapsink->flow_lock);
2867 case GST_STATE_CHANGE_READY_TO_PAUSED:
2868 GST_WARNING_OBJECT (evaspixmapsink,"GST_STATE_CHANGE_READY_TO_PAUSED");
2871 case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
2872 GST_WARNING_OBJECT (evaspixmapsink,"GST_STATE_CHANGE_PAUSED_TO_PLAYING");
2879 ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
2881 switch (transition) {
2882 case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
2883 GST_WARNING_OBJECT (evaspixmapsink,"GST_STATE_CHANGE_PLAYING_TO_PAUSED");
2886 case GST_STATE_CHANGE_PAUSED_TO_READY:
2889 GST_WARNING_OBJECT (evaspixmapsink,"GST_STATE_CHANGE_PAUSED_TO_READY");
2890 evaspixmapsink->fps_n = 0;
2891 evaspixmapsink->fps_d = 1;
2892 GST_VIDEO_SINK_WIDTH (evaspixmapsink) = 0;
2893 GST_VIDEO_SINK_HEIGHT (evaspixmapsink) = 0;
2894 drm_fini_close_gem_handle(evaspixmapsink, 0);
2898 case GST_STATE_CHANGE_READY_TO_NULL:
2899 GST_WARNING_OBJECT (evaspixmapsink,"GST_STATE_CHANGE_READY_TO_NULL");
2900 gst_evaspixmapsink_reset(evaspixmapsink);
2902 drm_fini(evaspixmapsink);
2912 gst_evaspixmapsink_get_times (GstBaseSink *bsink, GstBuffer *buf, GstClockTime *start, GstClockTime *end)
2914 GstEvasPixmapSink *evaspixmapsink;
2916 evaspixmapsink = GST_EVASPIXMAPSINK (bsink);
2918 if (GST_BUFFER_TIMESTAMP_IS_VALID (buf)) {
2919 *start = GST_BUFFER_TIMESTAMP (buf);
2920 if (GST_BUFFER_DURATION_IS_VALID (buf)) {
2921 *end = *start + GST_BUFFER_DURATION (buf);
2923 if (evaspixmapsink->fps_n > 0) {
2925 gst_util_uint64_scale_int (GST_SECOND, evaspixmapsink->fps_d,
2926 evaspixmapsink->fps_n);
2932 static GstFlowReturn
2933 gst_evaspixmapsink_show_frame (GstVideoSink *vsink, GstBuffer *buf)
2935 GstEvasPixmapSink *evaspixmapsink;
2936 XV_DATA_PTR img_data = NULL;
2937 SCMN_IMGB *scmn_imgb = NULL;
2940 MMTA_ACUM_ITEM_BEGIN("evaspixmapsink gst_evaspixmapsink_show_frame()", FALSE);
2942 evaspixmapsink = GST_EVASPIXMAPSINK (vsink);
2944 if( evaspixmapsink->stop_video ) {
2945 GST_INFO_OBJECT (evaspixmapsink, "Stop video is TRUE. so skip show frame..." );
2949 if (!evaspixmapsink->evas_pixmap_buf) {
2950 GST_DEBUG_OBJECT (evaspixmapsink,"creating our evaspixmap buffer");
2951 format = gst_evaspixmapsink_get_format_from_caps(evaspixmapsink, GST_BUFFER_CAPS(buf));
2953 case GST_MAKE_FOURCC('S', 'T', '1', '2'):
2954 case GST_MAKE_FOURCC('S', 'N', '1', '2'):
2955 case GST_MAKE_FOURCC('S', '4', '2', '0'):
2956 case GST_MAKE_FOURCC('S', 'U', 'Y', '2'):
2957 case GST_MAKE_FOURCC('S', 'U', 'Y', 'V'):
2958 case GST_MAKE_FOURCC('S', 'Y', 'V', 'Y'):
2959 case GST_MAKE_FOURCC('I', 'T', 'L', 'V'):
2960 case GST_MAKE_FOURCC('S', 'R', '3', '2'):
2961 scmn_imgb = (SCMN_IMGB *)GST_BUFFER_MALLOCDATA(buf);
2962 if(scmn_imgb == NULL) {
2963 GST_DEBUG_OBJECT (evaspixmapsink, "scmn_imgb is NULL. Skip buffer put..." );
2966 /* skip buffer if aligned size is smaller than size of caps */
2967 if (scmn_imgb->s[0] < evaspixmapsink->video_width || scmn_imgb->e[0] < evaspixmapsink->video_height) {
2968 GST_WARNING_OBJECT (evaspixmapsink,"invalid size[caps:%dx%d,aligned:%dx%d]. Skip this buffer...",
2969 evaspixmapsink->video_width, evaspixmapsink->video_height, scmn_imgb->s[0], scmn_imgb->e[0]);
2972 evaspixmapsink->aligned_width = scmn_imgb->s[0];
2973 evaspixmapsink->aligned_height = scmn_imgb->e[0];
2974 GST_DEBUG_OBJECT (evaspixmapsink,"video width,height[%dx%d]",evaspixmapsink->video_width, evaspixmapsink->video_height);
2975 GST_INFO_OBJECT (evaspixmapsink,"Use aligned width,height[%dx%d]",evaspixmapsink->aligned_width, evaspixmapsink->aligned_height);
2978 GST_INFO_OBJECT (evaspixmapsink,"Use original width,height of caps");
2981 evaspixmapsink->evas_pixmap_buf = gst_evaspixmap_buffer_new (evaspixmapsink, GST_BUFFER_CAPS (buf));
2982 if (!evaspixmapsink->evas_pixmap_buf) {
2983 /* The create method should have posted an informative error */
2986 if (evaspixmapsink->evas_pixmap_buf->size < GST_BUFFER_SIZE (buf)) {
2987 GST_ELEMENT_ERROR (evaspixmapsink, RESOURCE, WRITE, ("Failed to create output image buffer of %dx%d pixels", evaspixmapsink->evas_pixmap_buf->width, evaspixmapsink->evas_pixmap_buf->height),("XServer allocated buffer size did not match input buffer"));
2988 gst_evaspixmap_buffer_destroy (evaspixmapsink->evas_pixmap_buf);
2989 evaspixmapsink->evas_pixmap_buf = NULL;
2994 switch (evaspixmapsink->evas_pixmap_buf->im_format) {
2995 /* Cases for specified formats of Samsung extension */
2996 case GST_MAKE_FOURCC('S', 'T', '1', '2'):
2997 case GST_MAKE_FOURCC('S', 'N', '1', '2'):
2998 case GST_MAKE_FOURCC('S', '4', '2', '0'):
2999 case GST_MAKE_FOURCC('S', 'U', 'Y', '2'):
3000 case GST_MAKE_FOURCC('S', 'U', 'Y', 'V'):
3001 case GST_MAKE_FOURCC('S', 'Y', 'V', 'Y'):
3002 case GST_MAKE_FOURCC('I', 'T', 'L', 'V'):
3003 case GST_MAKE_FOURCC('S', 'R', '3', '2'):
3005 GST_DEBUG_OBJECT (evaspixmapsink,"Samsung extension display format activated. fourcc:%d", evaspixmapsink->evas_pixmap_buf->im_format);
3007 if (evaspixmapsink->evas_pixmap_buf->xvimage->data) {
3008 img_data = (XV_DATA_PTR) evaspixmapsink->evas_pixmap_buf->xvimage->data;
3009 XV_INIT_DATA(img_data);
3010 scmn_imgb = (SCMN_IMGB *)GST_BUFFER_MALLOCDATA(buf);
3011 if (scmn_imgb == NULL) {
3012 GST_DEBUG_OBJECT (evaspixmapsink, "scmn_imgb is NULL. Skip buffer put..." );
3016 if (scmn_imgb->buf_share_method == BUF_SHARE_METHOD_PADDR) {
3017 img_data->YBuf = (unsigned int)scmn_imgb->p[0];
3018 img_data->CbBuf = (unsigned int)scmn_imgb->p[1];
3019 img_data->CrBuf = (unsigned int)scmn_imgb->p[2];
3020 img_data->BufType = XV_BUF_TYPE_LEGACY;
3022 } else if (scmn_imgb->buf_share_method == BUF_SHARE_METHOD_FD) {
3023 /* set gem information to gem_info structure of handle and convert dma-buf fd into drm gem name */
3024 img_data->YBuf = drm_init_convert_dmabuf_gemname(evaspixmapsink, (int)scmn_imgb->dma_buf_fd[0]);
3025 img_data->CbBuf = drm_init_convert_dmabuf_gemname(evaspixmapsink, (int)scmn_imgb->dma_buf_fd[1]);
3026 img_data->CrBuf = drm_init_convert_dmabuf_gemname(evaspixmapsink, (int)scmn_imgb->dma_buf_fd[2]);
3027 img_data->BufType = XV_BUF_TYPE_DMABUF;
3028 if (evaspixmapsink->buf_shared_type != BUF_SHARE_METHOD_FD) {
3029 evaspixmapsink->buf_shared_type = BUF_SHARE_METHOD_FD;
3030 GST_WARNING_OBJECT (evaspixmapsink, "BUF SHARED TYPE : FD");
3033 } else if (scmn_imgb->buf_share_method == BUF_SHARE_METHOD_TIZEN_BUFFER) {
3034 img_data->bo[0] = scmn_imgb->bo[0];
3035 img_data->bo[1] = scmn_imgb->bo[1];
3036 img_data->bo[2] = scmn_imgb->bo[2];
3037 GST_DEBUG("TBM bo %p %p %p", img_data->bo[0], img_data->bo[1], img_data->bo[2]);
3039 if (img_data->bo[0]) {
3040 img_data->YBuf = tbm_init_convert_bo_gemname(evaspixmapsink, (tbm_bo)img_data->bo[0]);
3042 if (img_data->bo[1]) {
3043 img_data->CbBuf = tbm_init_convert_bo_gemname(evaspixmapsink, (tbm_bo)img_data->bo[1]);
3045 if (img_data->bo[2]) {
3046 img_data->CrBuf = tbm_init_convert_bo_gemname(evaspixmapsink, (tbm_bo)img_data->bo[2]);
3048 if (evaspixmapsink->buf_shared_type != BUF_SHARE_METHOD_TIZEN_BUFFER) {
3049 evaspixmapsink->buf_shared_type = BUF_SHARE_METHOD_TIZEN_BUFFER;
3050 GST_WARNING_OBJECT (evaspixmapsink, "BUF SHARED TYPE : TIZEN BUFFER");
3053 GST_WARNING_OBJECT (evaspixmapsink, "Not supported, buf_share_method(%d)", scmn_imgb->buf_share_method);
3056 if (!img_data->YBuf) {
3057 GST_WARNING_OBJECT (evaspixmapsink, "img_data->YBuf is NULL. skip buffer put..." );
3060 GST_LOG_OBJECT(evaspixmapsink, "YBuf[%d], CbBuf[%d], CrBuf[%d]",
3061 img_data->YBuf, img_data->CbBuf, img_data->CrBuf );
3063 GST_WARNING_OBJECT (evaspixmapsink, "xvimage->data is NULL. skip buffer put..." );
3070 if (evaspixmapsink->buf_shared_type != BUF_SHARE_METHOD_NONE) {
3071 evaspixmapsink->buf_shared_type = BUF_SHARE_METHOD_NONE;
3073 GST_DEBUG_OBJECT (evaspixmapsink,"Normal format activated. fourcc = %d", evaspixmapsink->evas_pixmap_buf->im_format);
3074 __ta__("evaspixmapsink memcpy in _show_frame", memcpy (evaspixmapsink->evas_pixmap_buf->xvimage->data, GST_BUFFER_DATA (buf),
3075 MIN (GST_BUFFER_SIZE (buf), evaspixmapsink->evas_pixmap_buf->size)););
3079 if (!gst_evaspixmap_buffer_put (evaspixmapsink, evaspixmapsink->evas_pixmap_buf)) {
3080 MMTA_ACUM_ITEM_END("evaspixmapsink gst_evaspixmapsink_show_frame()", FALSE);
3084 MMTA_ACUM_ITEM_END("evaspixmapsink gst_evaspixmapsink_show_frame()", FALSE);
3091 /* No image available. That's very bad ! */
3092 GST_WARNING_OBJECT (evaspixmapsink,"could not create image");
3093 return GST_FLOW_ERROR;
3098 gst_evaspixmapsink_event (GstBaseSink *sink, GstEvent *event)
3100 GstEvasPixmapSink *evaspixmapsink = GST_EVASPIXMAPSINK (sink);
3102 switch (GST_EVENT_TYPE (event)) {
3103 case GST_EVENT_FLUSH_START:
3104 GST_DEBUG_OBJECT (evaspixmapsink,"GST_EVENT_FLUSH_START");
3106 case GST_EVENT_FLUSH_STOP:
3107 GST_DEBUG_OBJECT (evaspixmapsink,"GST_EVENT_FLUSH_STOP");
3112 if (GST_BASE_SINK_CLASS (parent_class)->event) {
3113 return GST_BASE_SINK_CLASS (parent_class)->event (sink, event);
3119 /* Interfaces stuff */
3122 gst_evaspixmapsink_interface_supported (GstImplementsInterface *iface, GType type)
3124 g_assert (type == GST_TYPE_NAVIGATION || type == GST_TYPE_COLOR_BALANCE || type == GST_TYPE_PROPERTY_PROBE);
3129 gst_evaspixmapsink_interface_init (GstImplementsInterfaceClass *klass)
3131 klass->supported = gst_evaspixmapsink_interface_supported;
3135 gst_evaspixmapsink_navigation_send_event (GstNavigation *navigation, GstStructure *structure)
3137 GstEvasPixmapSink *evaspixmapsink = GST_EVASPIXMAPSINK (navigation);
3141 if ((peer = gst_pad_get_peer (GST_VIDEO_SINK_PAD (evaspixmapsink)))) {
3143 GstVideoRectangle result;
3144 gdouble x, y, xscale = 1.0, yscale = 1.0;
3146 event = gst_event_new_navigation (structure);
3148 /* We take the flow_lock while we look at the window */
3149 g_mutex_lock (evaspixmapsink->flow_lock);
3151 for (i = 0; i < evaspixmapsink->num_of_pixmaps; i ++) {
3152 if (!evaspixmapsink->xpixmap[i]) {
3153 g_mutex_unlock (evaspixmapsink->flow_lock);
3158 memcpy (&result, &evaspixmapsink->render_rect, sizeof (GstVideoRectangle));
3160 g_mutex_unlock (evaspixmapsink->flow_lock);
3162 /* We calculate scaling using the original video frames geometry to include
3163 pixel aspect ratio scaling. */
3164 xscale = (gdouble) evaspixmapsink->video_width / result.w;
3165 yscale = (gdouble) evaspixmapsink->video_height / result.h;
3167 /* Converting pointer coordinates to the non scaled geometry */
3168 if (gst_structure_get_double (structure, "pointer_x", &x)) {
3169 x = MIN (x, result.x + result.w);
3170 x = MAX (x - result.x, 0);
3171 gst_structure_set (structure, "pointer_x", G_TYPE_DOUBLE,
3172 (gdouble) x * xscale, NULL);
3174 if (gst_structure_get_double (structure, "pointer_y", &y)) {
3175 y = MIN (y, result.y + result.h);
3176 y = MAX (y - result.y, 0);
3177 gst_structure_set (structure, "pointer_y", G_TYPE_DOUBLE,
3178 (gdouble) y * yscale, NULL);
3181 gst_pad_send_event (peer, event);
3182 gst_object_unref (peer);
3187 gst_evaspixmapsink_navigation_init (GstNavigationInterface *iface)
3189 iface->send_event = gst_evaspixmapsink_navigation_send_event;
3193 gst_evaspixmapsink_colorbalance_list_channels (GstColorBalance *balance)
3195 GstEvasPixmapSink *evaspixmapsink = GST_EVASPIXMAPSINK (balance);
3197 g_return_val_if_fail (GST_IS_EVASPIXMAPSINK (evaspixmapsink), NULL);
3199 if (evaspixmapsink->xcontext)
3200 return evaspixmapsink->xcontext->channels_list;
3206 gst_evaspixmapsink_colorbalance_set_value (GstColorBalance *balance, GstColorBalanceChannel *channel, gint value)
3208 GstEvasPixmapSink *evaspixmapsink = GST_EVASPIXMAPSINK (balance);
3210 g_return_if_fail (GST_IS_EVASPIXMAPSINK (evaspixmapsink));
3211 g_return_if_fail (channel->label != NULL);
3213 evaspixmapsink->cb_changed = TRUE;
3215 /* Normalize val to [-1000, 1000] */
3216 value = floor (0.5 + -1000 + 2000 * (value - channel->min_value) /
3217 (double) (channel->max_value - channel->min_value));
3219 if (g_ascii_strcasecmp (channel->label, "XV_HUE") == 0) {
3220 evaspixmapsink->hue = value;
3221 } else if (g_ascii_strcasecmp (channel->label, "XV_SATURATION") == 0) {
3222 evaspixmapsink->saturation = value;
3223 } else if (g_ascii_strcasecmp (channel->label, "XV_CONTRAST") == 0) {
3224 evaspixmapsink->contrast = value;
3225 } else if (g_ascii_strcasecmp (channel->label, "XV_BRIGHTNESS") == 0) {
3226 evaspixmapsink->brightness = value;
3228 g_warning ("got an unknown channel %s", channel->label);
3232 gst_evaspixmapsink_update_colorbalance (evaspixmapsink);
3236 gst_evaspixmapsink_colorbalance_get_value (GstColorBalance *balance, GstColorBalanceChannel *channel)
3238 GstEvasPixmapSink *evaspixmapsink = GST_EVASPIXMAPSINK (balance);
3241 g_return_val_if_fail (GST_IS_EVASPIXMAPSINK (evaspixmapsink), 0);
3242 g_return_val_if_fail (channel->label != NULL, 0);
3244 if (g_ascii_strcasecmp (channel->label, "XV_HUE") == 0) {
3245 value = evaspixmapsink->hue;
3246 } else if (g_ascii_strcasecmp (channel->label, "XV_SATURATION") == 0) {
3247 value = evaspixmapsink->saturation;
3248 } else if (g_ascii_strcasecmp (channel->label, "XV_CONTRAST") == 0) {
3249 value = evaspixmapsink->contrast;
3250 } else if (g_ascii_strcasecmp (channel->label, "XV_BRIGHTNESS") == 0) {
3251 value = evaspixmapsink->brightness;
3253 g_warning ("got an unknown channel %s", channel->label);
3256 /* Normalize val to [channel->min_value, channel->max_value] */
3257 value = channel->min_value + (channel->max_value - channel->min_value) * (value + 1000) / 2000;
3263 gst_evaspixmapsink_colorbalance_init (GstColorBalanceClass *iface)
3265 GST_COLOR_BALANCE_TYPE (iface) = GST_COLOR_BALANCE_HARDWARE;
3266 iface->list_channels = gst_evaspixmapsink_colorbalance_list_channels;
3267 iface->set_value = gst_evaspixmapsink_colorbalance_set_value;
3268 iface->get_value = gst_evaspixmapsink_colorbalance_get_value;
3271 static const GList *
3272 gst_evaspixmapsink_probe_get_properties (GstPropertyProbe *probe)
3274 GObjectClass *klass = G_OBJECT_GET_CLASS (probe);
3275 static GList *list = NULL;
3278 list = g_list_append (NULL, g_object_class_find_property (klass, "device"));
3279 list = g_list_append (list, g_object_class_find_property (klass, "autopaint-colorkey"));
3280 list = g_list_append (list, g_object_class_find_property (klass, "double-buffer"));
3281 list = g_list_append (list, g_object_class_find_property (klass, "colorkey"));
3288 gst_evaspixmapsink_probe_probe_property (GstPropertyProbe *probe, guint prop_id, const GParamSpec *pspec)
3290 GstEvasPixmapSink *evaspixmapsink = GST_EVASPIXMAPSINK (probe);
3294 case PROP_AUTOPAINT_COLORKEY:
3295 case PROP_DOUBLE_BUFFER:
3297 GST_DEBUG_OBJECT (evaspixmapsink,"probing device list and get capabilities");
3298 if (!evaspixmapsink->xcontext) {
3299 GST_DEBUG_OBJECT (evaspixmapsink,"generating xcontext");
3300 evaspixmapsink->xcontext = gst_evaspixmapsink_xcontext_get (evaspixmapsink);
3301 if (!evaspixmapsink->xcontext) {
3302 GST_ERROR_OBJECT (evaspixmapsink,"could not get xcontext..");
3307 G_OBJECT_WARN_INVALID_PROPERTY_ID (probe, prop_id, pspec);
3313 gst_evaspixmapsink_probe_needs_probe (GstPropertyProbe *probe, guint prop_id, const GParamSpec *pspec)
3315 GstEvasPixmapSink *evaspixmapsink = GST_EVASPIXMAPSINK (probe);
3316 gboolean ret = FALSE;
3320 case PROP_AUTOPAINT_COLORKEY:
3321 case PROP_DOUBLE_BUFFER:
3323 if (evaspixmapsink->xcontext != NULL) {
3330 G_OBJECT_WARN_INVALID_PROPERTY_ID (probe, prop_id, pspec);
3337 static GValueArray *
3338 gst_evaspixmapsink_probe_get_values (GstPropertyProbe *probe, guint prop_id, const GParamSpec *pspec)
3340 GstEvasPixmapSink *evaspixmapsink = GST_EVASPIXMAPSINK (probe);
3341 GValueArray *array = NULL;
3343 if (G_UNLIKELY (!evaspixmapsink->xcontext)) {
3344 GST_WARNING_OBJECT (evaspixmapsink,"we don't have any xcontext, can't "
3353 GValue value = { 0 };
3355 array = g_value_array_new (evaspixmapsink->xcontext->nb_adaptors);
3356 g_value_init (&value, G_TYPE_STRING);
3358 for (i = 0; i < evaspixmapsink->xcontext->nb_adaptors; i++) {
3359 gchar *adaptor_id_s = g_strdup_printf ("%u", i);
3361 g_value_set_string (&value, adaptor_id_s);
3362 g_value_array_append (array, &value);
3363 g_free (adaptor_id_s);
3365 g_value_unset (&value);
3368 case PROP_AUTOPAINT_COLORKEY:
3369 if (evaspixmapsink->have_autopaint_colorkey) {
3370 GValue value = { 0 };
3372 array = g_value_array_new (2);
3373 g_value_init (&value, G_TYPE_BOOLEAN);
3374 g_value_set_boolean (&value, FALSE);
3375 g_value_array_append (array, &value);
3376 g_value_set_boolean (&value, TRUE);
3377 g_value_array_append (array, &value);
3378 g_value_unset (&value);
3381 case PROP_DOUBLE_BUFFER:
3382 if (evaspixmapsink->have_double_buffer) {
3383 GValue value = { 0 };
3385 array = g_value_array_new (2);
3386 g_value_init (&value, G_TYPE_BOOLEAN);
3387 g_value_set_boolean (&value, FALSE);
3388 g_value_array_append (array, &value);
3389 g_value_set_boolean (&value, TRUE);
3390 g_value_array_append (array, &value);
3391 g_value_unset (&value);
3395 if (evaspixmapsink->have_colorkey) {
3396 GValue value = { 0 };
3398 array = g_value_array_new (1);
3399 g_value_init (&value, GST_TYPE_INT_RANGE);
3400 gst_value_set_int_range (&value, 0, 0xffffff);
3401 g_value_array_append (array, &value);
3402 g_value_unset (&value);
3406 G_OBJECT_WARN_INVALID_PROPERTY_ID (probe, prop_id, pspec);
3415 gst_evaspixmapsink_property_probe_interface_init (GstPropertyProbeInterface *iface)
3417 iface->get_properties = gst_evaspixmapsink_probe_get_properties;
3418 iface->probe_property = gst_evaspixmapsink_probe_probe_property;
3419 iface->needs_probe = gst_evaspixmapsink_probe_needs_probe;
3420 iface->get_values = gst_evaspixmapsink_probe_get_values;
3424 gst_evaspixmapsink_xpixmap_link (GstEvasPixmapSink *evaspixmapsink)
3427 Pixmap *pixmap_id[NUM_OF_PIXMAP];
3428 int evas_object_width = 0;
3429 int evas_object_height = 0;
3430 int pixmap_width = 0;
3431 int pixmap_height = 0;
3432 unsigned int xw = 0;
3433 unsigned int xh = 0;
3436 GST_DEBUG_OBJECT (evaspixmapsink,"[START]");
3438 if (!evaspixmapsink) {
3439 GST_ERROR_OBJECT (evaspixmapsink,"could not get evaspixmapsink..");
3442 g_mutex_lock (evaspixmapsink->flow_lock);
3444 /* Set xcontext and display */
3445 if (!evaspixmapsink->xcontext) {
3446 GST_WARNING_OBJECT (evaspixmapsink,"there's no xcontext, try to get one..");
3447 evaspixmapsink->xcontext = gst_evaspixmapsink_xcontext_get (evaspixmapsink);
3448 if (!evaspixmapsink->xcontext) {
3449 GST_ERROR_OBJECT (evaspixmapsink,"could not get xcontext..");
3454 /* Set evas image object size */
3455 evas_object_geometry_get(evaspixmapsink->eo, NULL, NULL, &evas_object_width, &evas_object_height);
3457 /* check if it is redundant request */
3458 for (i = 0; i < evaspixmapsink->num_of_pixmaps; i++) {
3459 if (evaspixmapsink->xpixmap[i]) {
3460 if (!evaspixmapsink->use_origin_size && evaspixmapsink->xpixmap[i]->width && evaspixmapsink->xpixmap[i]->height) {
3461 if (evaspixmapsink->xpixmap[i]->width == evas_object_width && evaspixmapsink->xpixmap[i]->height == evas_object_height) {
3462 GST_WARNING_OBJECT (evaspixmapsink,"pixmap was already created(w:%d, h:%d), skip it..",
3463 evaspixmapsink->xpixmap[i]->width, evaspixmapsink->xpixmap[i]->height);
3464 for (i = 0; i < evaspixmapsink->num_of_pixmaps; i++) {
3465 XSetForeground (evaspixmapsink->xcontext->disp, evaspixmapsink->xpixmap[i]->gc, evaspixmapsink->xcontext->black);
3466 XFillRectangle (evaspixmapsink->xcontext->disp, evaspixmapsink->xpixmap[i]->pixmap, evaspixmapsink->xpixmap[i]->gc,
3467 0, 0, evaspixmapsink->xpixmap[i]->width, evaspixmapsink->xpixmap[i]->height);
3468 GST_LOG_OBJECT (evaspixmapsink,"fill black to xpixmap[%d] with size(w:%d,h:%d)", evaspixmapsink->xpixmap[i]->pixmap,
3469 evaspixmapsink->xpixmap[i]->width, evaspixmapsink->xpixmap[i]->height);
3477 dpy = evaspixmapsink->xcontext->disp;
3479 if (evaspixmapsink->use_origin_size || !evas_object_width || !evas_object_height) {
3480 pixmap_width = evaspixmapsink->video_width;
3481 pixmap_height = evaspixmapsink->video_height;
3482 GST_INFO_OBJECT (evaspixmapsink,"set size to media src size(%dx%d)", pixmap_width, pixmap_height);
3485 g_mutex_lock (evaspixmapsink->x_lock);
3486 evaspixmapsink->sizediff_width = 0;
3487 evaspixmapsink->sizediff_height = 0;
3488 if (evaspixmapsink->use_origin_size || !evas_object_width || !evas_object_height) {
3489 XvQueryBestSize(dpy, evaspixmapsink->xcontext->xv_port_id,0,0,0, pixmap_width, pixmap_height, &xw, &xh);
3490 if (!evas_object_width || !evas_object_height) {
3491 evaspixmapsink->w = xw;
3492 evaspixmapsink->h = xh;
3494 evaspixmapsink->w = evas_object_width;
3495 evaspixmapsink->h = evas_object_height;
3497 GST_DEBUG_OBJECT (evaspixmapsink,"XvQueryBestSize : xv_port_id(%d), w(%d),h(%d) => xw(%d),xh(%d)", evaspixmapsink->xcontext->xv_port_id, pixmap_width, pixmap_height, xw, xh);
3499 XvQueryBestSize(dpy, evaspixmapsink->xcontext->xv_port_id,0,0,0, evas_object_width, evas_object_height, &xw, &xh);
3500 GST_DEBUG_OBJECT (evaspixmapsink,"XvQueryBestSize : xv_port_id(%d), w(%d),h(%d) => xw(%d),xh(%d)", evaspixmapsink->xcontext->xv_port_id, evas_object_width, evas_object_height, xw, xh);
3501 evaspixmapsink->w = xw;
3502 evaspixmapsink->h = xh;
3503 /* update difference of size information (between evas image object's and pixmap's) */
3504 evaspixmapsink->sizediff_width = xw - evas_object_width;
3505 evaspixmapsink->sizediff_height = xh - evas_object_height;
3508 /* create xpixmap structure */
3509 for (i = 0; i < evaspixmapsink->num_of_pixmaps; i++) {
3510 if (!evaspixmapsink->xpixmap[i]) {
3511 /* xpixmap can be created in this function only */
3512 evaspixmapsink->xpixmap[i] = g_new0 (GstXPixmap, 1);
3513 if(!evaspixmapsink->xpixmap[i]) {
3514 GST_ERROR_OBJECT (evaspixmapsink,"xpixmap is not valid..");
3516 for (j = 0; j < i; j++) {
3517 g_free(evaspixmapsink->xpixmap[j]);
3519 goto GO_OUT_OF_FUNC;
3526 GST_WARNING_OBJECT (evaspixmapsink,"skip creating pixmap..xw(%d),xh(%d)",xw,xh);
3527 goto GO_OUT_OF_FUNC;
3529 /* multiple pixmaps creation */
3530 for (i = 0; i < evaspixmapsink->num_of_pixmaps; i++) {
3531 pixmap_id[i] = XCreatePixmap(dpy, DefaultRootWindow(dpy), xw, xh, DefaultDepth(dpy, DefaultScreen(dpy)));
3532 if ( (int)pixmap_id[i] == BadAlloc || (int)pixmap_id[i] == BadDrawable || (int)pixmap_id[i] == BadValue ) {
3533 GST_ERROR_OBJECT (evaspixmapsink,"pixmap[%d] allocation error..", i);
3535 for (j = 0; j < i; j++) {
3536 XFreePixmap(dpy, pixmap_id[j]);
3538 goto GO_OUT_OF_FUNC;
3540 GST_INFO_OBJECT (evaspixmapsink,"creation pixmap_id[%d]:%d success", i, pixmap_id[i]);
3541 GST_DEBUG_OBJECT (evaspixmapsink,"evas_object_width(%d),evas_object_height(%d),pixmap:%d,depth:%d",
3542 evas_object_width,evas_object_height,pixmap_id[i],DefaultDepth(dpy, DefaultScreen(dpy)));
3546 for (i = 0; i < evaspixmapsink->num_of_pixmaps; i++) {
3547 if (evaspixmapsink->xpixmap[i]->pixmap && pixmap_id[i] != evaspixmapsink->xpixmap[i]->pixmap) {
3548 g_mutex_unlock (evaspixmapsink->x_lock);
3549 g_mutex_lock (evaspixmapsink->pixmap_ref_lock);
3550 /* If we reset another pixmap, do below */
3551 evaspixmapsink->xpixmap[i]->prev_pixmap = evaspixmapsink->xpixmap[i]->pixmap;
3552 evaspixmapsink->xpixmap[i]->prev_gc = evaspixmapsink->xpixmap[i]->gc;
3553 evaspixmapsink->xpixmap[i]->pixmap = 0;
3554 evaspixmapsink->xpixmap[i]->ref = 0;
3555 evaspixmapsink->xpixmap[i]->damaged_time = 0;
3556 g_mutex_unlock (evaspixmapsink->pixmap_ref_lock);
3557 g_mutex_lock (evaspixmapsink->x_lock);
3561 for (i = 0; i < evaspixmapsink->num_of_pixmaps; i++) {
3562 /* Set pixmap id and create GC */
3563 evaspixmapsink->xpixmap[i]->pixmap = pixmap_id[i];
3564 evaspixmapsink->xpixmap[i]->gc = XCreateGC(dpy, evaspixmapsink->xpixmap[i]->pixmap, 0,0);
3565 evaspixmapsink->xpixmap[i]->width = xw;
3566 evaspixmapsink->xpixmap[i]->height = xh;
3568 /* Create XDamage */
3569 if (evaspixmapsink->damage[i]) {
3570 evaspixmapsink->prev_damage[i] = evaspixmapsink->damage[i];
3572 evaspixmapsink->damage[i] = XDamageCreate (dpy, evaspixmapsink->xpixmap[i]->pixmap, XDamageReportRawRectangles);
3574 GST_WARNING_OBJECT (evaspixmapsink,"xpixmap[%d]->(pixmap:%d,gc:%p), damage[%d]:%d",
3575 i, evaspixmapsink->xpixmap[i]->pixmap, evaspixmapsink->xpixmap[i]->gc, i, evaspixmapsink->damage[i]);
3577 /* Fill blackcolor for the new pixmap */
3578 XSetForeground (evaspixmapsink->xcontext->disp, evaspixmapsink->xpixmap[i]->gc, evaspixmapsink->xcontext->black);
3579 XFillRectangle (evaspixmapsink->xcontext->disp, pixmap_id[i], evaspixmapsink->xpixmap[i]->gc,
3580 0, 0, evaspixmapsink->w, evaspixmapsink->h);
3581 GST_LOG_OBJECT (evaspixmapsink,"fill black to xpixmap[%d] with size(w:%d,h:%d)", pixmap_id[i],
3582 evaspixmapsink->w, evaspixmapsink->h);
3587 /* Set flag for mapping evas object with xpixmap */
3588 evaspixmapsink->do_link = TRUE;
3589 if (evaspixmapsink->epipe_request_count > EPIPE_REQUEST_LIMIT) {
3590 GST_WARNING_OBJECT (evaspixmapsink,"epipe_request_count(%d), skip ecore_pipe_write()", evaspixmapsink->epipe_request_count);
3592 ecore_pipe_write(evaspixmapsink->epipe, evaspixmapsink, sizeof(GstEvasPixmapSink));
3593 evaspixmapsink->epipe_request_count++;
3596 gst_evaspixmapsink_update_colorbalance (evaspixmapsink);
3598 g_mutex_unlock (evaspixmapsink->x_lock);
3602 g_mutex_lock (evaspixmapsink->pixmap_ref_lock);
3603 evaspixmapsink->last_updated_idx = -1;
3604 g_mutex_unlock (evaspixmapsink->pixmap_ref_lock);
3606 g_mutex_unlock (evaspixmapsink->flow_lock);
3608 GST_DEBUG_OBJECT (evaspixmapsink,"[END]");
3613 g_mutex_unlock (evaspixmapsink->x_lock);
3614 g_mutex_unlock (evaspixmapsink->flow_lock);
3619 gst_evaspixmapsink_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
3621 GstEvasPixmapSink *evaspixmapsink;
3622 g_return_if_fail (GST_IS_EVASPIXMAPSINK (object));
3623 evaspixmapsink = GST_EVASPIXMAPSINK (object);
3627 evaspixmapsink->hue = g_value_get_int (value);
3628 evaspixmapsink->cb_changed = TRUE;
3629 gst_evaspixmapsink_update_colorbalance (evaspixmapsink);
3632 evaspixmapsink->contrast = g_value_get_int (value);
3633 evaspixmapsink->cb_changed = TRUE;
3634 gst_evaspixmapsink_update_colorbalance (evaspixmapsink);
3636 case PROP_BRIGHTNESS:
3637 evaspixmapsink->brightness = g_value_get_int (value);
3638 evaspixmapsink->cb_changed = TRUE;
3639 gst_evaspixmapsink_update_colorbalance (evaspixmapsink);
3641 case PROP_SATURATION:
3642 evaspixmapsink->saturation = g_value_get_int (value);
3643 evaspixmapsink->cb_changed = TRUE;
3644 gst_evaspixmapsink_update_colorbalance (evaspixmapsink);
3647 evaspixmapsink->display_name = g_strdup (g_value_get_string (value));
3649 case PROP_SYNCHRONOUS:
3650 evaspixmapsink->synchronous = g_value_get_boolean (value);
3651 if (evaspixmapsink->xcontext) {
3652 XSynchronize (evaspixmapsink->xcontext->disp, evaspixmapsink->synchronous);
3653 GST_DEBUG_OBJECT (evaspixmapsink,"XSynchronize called with %s", evaspixmapsink->synchronous ? "TRUE" : "FALSE");
3656 case PROP_PIXEL_ASPECT_RATIO:
3657 g_free (evaspixmapsink->par);
3658 evaspixmapsink->par = g_new0 (GValue, 1);
3659 g_value_init (evaspixmapsink->par, GST_TYPE_FRACTION);
3660 if (!g_value_transform (value, evaspixmapsink->par)) {
3661 g_warning ("Could not transform string to aspect ratio");
3662 gst_value_set_fraction (evaspixmapsink->par, 1, 1);
3664 GST_DEBUG_OBJECT (evaspixmapsink,"set PAR to %d/%d", gst_value_get_fraction_numerator (evaspixmapsink->par), gst_value_get_fraction_denominator (evaspixmapsink->par));
3667 evaspixmapsink->adaptor_no = atoi (g_value_get_string (value));
3669 case PROP_DOUBLE_BUFFER:
3670 evaspixmapsink->double_buffer = g_value_get_boolean (value);
3672 case PROP_AUTOPAINT_COLORKEY:
3673 evaspixmapsink->autopaint_colorkey = g_value_get_boolean (value);
3676 evaspixmapsink->colorkey = g_value_get_int (value);
3678 case PROP_PIXMAP_WIDTH:
3680 /* To do : code related to pixmap re-link */
3681 GST_LOG_OBJECT (evaspixmapsink, "Not supported");
3684 case PROP_PIXMAP_HEIGHT:
3686 /* To do : code related to pixmap re-link */
3687 GST_LOG_OBJECT (evaspixmapsink, "Not supported");
3690 case PROP_DISPLAY_GEOMETRY_METHOD:
3692 guint new_val = g_value_get_enum (value);
3693 if (evaspixmapsink->display_geometry_method != new_val) {
3694 evaspixmapsink->display_geometry_method = new_val;
3695 GST_INFO_OBJECT (evaspixmapsink,"Overlay geometry method update, display_geometry_method(%d)",evaspixmapsink->display_geometry_method);
3696 if( evaspixmapsink->display_geometry_method != DISP_GEO_METHOD_FULL_SCREEN &&
3697 evaspixmapsink->display_geometry_method != DISP_GEO_METHOD_CROPPED_FULL_SCREEN ) {
3698 if( evaspixmapsink->xcontext ) {
3699 g_mutex_lock( evaspixmapsink->flow_lock );
3701 for (i = 0; i < evaspixmapsink->num_of_pixmaps; i++) {
3702 if (evaspixmapsink->xpixmap[i]) {
3703 gst_evaspixmapsink_xpixmap_clear (evaspixmapsink, evaspixmapsink->xpixmap[i]);
3706 g_mutex_unlock( evaspixmapsink->flow_lock );
3709 if (evaspixmapsink->xcontext) {
3710 gst_evaspixmap_buffer_put (evaspixmapsink, evaspixmapsink->evas_pixmap_buf);
3715 case PROP_DST_ROI_X:
3716 evaspixmapsink->dst_roi.x = g_value_get_int (value);
3717 GST_INFO_OBJECT (evaspixmapsink, "ROI_X(%d)",evaspixmapsink->dst_roi.x );
3719 case PROP_DST_ROI_Y:
3720 evaspixmapsink->dst_roi.y = g_value_get_int (value);
3721 GST_INFO_OBJECT (evaspixmapsink, "ROI_Y(%d)",evaspixmapsink->dst_roi.y );
3723 case PROP_DST_ROI_W:
3724 evaspixmapsink->dst_roi.w = g_value_get_int (value);
3725 GST_INFO_OBJECT (evaspixmapsink, "ROI_W(%d)",evaspixmapsink->dst_roi.w );
3727 case PROP_DST_ROI_H:
3728 evaspixmapsink->dst_roi.h = g_value_get_int (value);
3729 GST_INFO_OBJECT (evaspixmapsink, "ROI_H(%d)",evaspixmapsink->dst_roi.h );
3731 case PROP_STOP_VIDEO:
3732 evaspixmapsink->stop_video = g_value_get_int (value);
3733 g_mutex_lock( evaspixmapsink->flow_lock );
3734 if( evaspixmapsink->stop_video ) {
3735 GST_INFO_OBJECT (evaspixmapsink, "XPixmap CLEAR when set video-stop property" );
3737 for (i = 0; i < evaspixmapsink->num_of_pixmaps; i++) {
3738 if (evaspixmapsink->xpixmap[i]) {
3739 gst_evaspixmapsink_xpixmap_clear (evaspixmapsink, evaspixmapsink->xpixmap[i]);
3743 GST_INFO_OBJECT (evaspixmapsink, "video-stop property(%d)", evaspixmapsink->stop_video);
3745 g_mutex_unlock( evaspixmapsink->flow_lock );
3747 case PROP_EVAS_OBJECT:
3749 Evas_Object *eo = g_value_get_pointer (value);
3750 if ( is_evas_image_object (eo)) {
3751 if (!evaspixmapsink->epipe) {
3752 evaspixmapsink->epipe = ecore_pipe_add (ecore_pipe_callback_handler, evaspixmapsink);
3753 if (!evaspixmapsink->epipe) {
3754 GST_ERROR_OBJECT (evaspixmapsink,"Cannot set evas-object property: ecore_pipe_add() failed");
3758 if (evaspixmapsink->eo == NULL) {
3759 evaspixmapsink->eo = eo;
3760 /* add evas object callbacks on a new evas image object */
3761 EVASPIXMAPSINK_SET_EVAS_OBJECT_EVENT_CALLBACK (eo, evaspixmapsink);
3762 if (GST_STATE(evaspixmapsink) < GST_STATE_PAUSED) {
3763 GST_INFO_OBJECT (evaspixmapsink,"It's the first time the new evas image object(%x) is set, skip gst_evaspixmapsink_xpixmap_link()..", eo);
3766 if (!gst_evaspixmapsink_xpixmap_link(evaspixmapsink)) {
3767 GST_WARNING_OBJECT (evaspixmapsink,"link evas image object with pixmap failed...");
3768 evaspixmapsink->eo = NULL;
3773 if (eo == evaspixmapsink->eo) {
3774 GST_LOG_OBJECT (evaspixmapsink,"new evas image object(%x) is same as the previous one(%x)", eo, evaspixmapsink->eo);
3776 GST_INFO_OBJECT (evaspixmapsink,"new evas image object(%x), previous one(%x)", eo, evaspixmapsink->eo);
3777 /* delete evas object callbacks registrated on a former evas image object */
3778 EVASPIXMAPSINK_UNSET_EVAS_OBJECT_EVENT_CALLBACK (evaspixmapsink->eo);
3779 evaspixmapsink->eo = eo;
3780 if (!gst_evaspixmapsink_xpixmap_link(evaspixmapsink)) {
3781 GST_WARNING_OBJECT (evaspixmapsink,"link evas image object with pixmap failed...");
3782 evaspixmapsink->eo = NULL;
3785 /* add evas object callbacks on a new evas image object */
3786 EVASPIXMAPSINK_SET_EVAS_OBJECT_EVENT_CALLBACK (eo, evaspixmapsink);
3788 GST_INFO_OBJECT (evaspixmapsink,"Evas image object(%x) is set", evaspixmapsink->eo);
3790 GST_ERROR_OBJECT (evaspixmapsink,"Cannot set evas-object property: value is not an evas image object");
3795 evaspixmapsink->flip = g_value_get_enum(value);
3797 case PROP_ROTATE_ANGLE:
3798 evaspixmapsink->rotate_angle = g_value_get_enum (value);
3803 gboolean visible = g_value_get_boolean (value);
3804 GST_INFO_OBJECT (evaspixmapsink,"evaspixmapsink->visible(%d), new value of visible(%d)", evaspixmapsink->visible, visible);
3805 if (evaspixmapsink->visible != visible) {
3806 evaspixmapsink->visible = visible;
3807 if (evaspixmapsink->eo) {
3808 evaspixmapsink->update_visibility = UPDATE_TRUE;
3809 if (evaspixmapsink->epipe_request_count > EPIPE_REQUEST_LIMIT) {
3810 GST_WARNING_OBJECT (evaspixmapsink,"skip ecore_pipe_write()", evaspixmapsink->epipe_request_count);
3812 evas_object_show(evaspixmapsink->eo);
3813 GST_WARNING_OBJECT (evaspixmapsink, "object show (forcely)");
3816 r = ecore_pipe_write (evaspixmapsink->epipe, &evaspixmapsink->update_visibility, SIZE_FOR_UPDATE_VISIBILITY);
3817 evaspixmapsink->epipe_request_count++;
3819 if (r == EINA_FALSE) {
3820 GST_WARNING ("Failed to ecore_pipe_write() for updating visibility)\n");
3824 g_mutex_lock( evaspixmapsink->flow_lock );
3825 for (i = 0; i < evaspixmapsink->num_of_pixmaps; i++) {
3826 if (evaspixmapsink->xpixmap[i]) {
3827 gst_evaspixmapsink_xpixmap_clear (evaspixmapsink, evaspixmapsink->xpixmap[i]);
3830 evas_object_hide(evaspixmapsink->eo);
3831 GST_INFO_OBJECT (evaspixmapsink, "object hide (forcely)");
3832 g_mutex_unlock( evaspixmapsink->flow_lock );
3834 gst_evaspixmap_buffer_put (evaspixmapsink, evaspixmapsink->evas_pixmap_buf);
3837 GST_WARNING_OBJECT (evaspixmapsink,"evas image object was not set");
3842 case PROP_ORIGIN_SIZE:
3843 evaspixmapsink->use_origin_size = g_value_get_boolean (value);
3844 GST_INFO_OBJECT (evaspixmapsink,"set origin-size (%d)",evaspixmapsink->use_origin_size);
3845 if (evaspixmapsink->previous_origin_size != evaspixmapsink->use_origin_size) {
3846 if (!gst_evaspixmapsink_xpixmap_link(evaspixmapsink)) {
3847 GST_WARNING_OBJECT (evaspixmapsink,"link evas image object with pixmap failed...");
3849 evaspixmapsink->previous_origin_size = evaspixmapsink->use_origin_size;
3853 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
3859 gst_evaspixmapsink_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
3861 GstEvasPixmapSink *evaspixmapsink;
3863 g_return_if_fail (GST_IS_EVASPIXMAPSINK (object));
3865 evaspixmapsink = GST_EVASPIXMAPSINK (object);
3869 g_value_set_int (value, evaspixmapsink->hue);
3872 g_value_set_int (value, evaspixmapsink->contrast);
3874 case PROP_BRIGHTNESS:
3875 g_value_set_int (value, evaspixmapsink->brightness);
3877 case PROP_SATURATION:
3878 g_value_set_int (value, evaspixmapsink->saturation);
3881 g_value_set_string (value, evaspixmapsink->display_name);
3883 case PROP_SYNCHRONOUS:
3884 g_value_set_boolean (value, evaspixmapsink->synchronous);
3886 case PROP_PIXEL_ASPECT_RATIO:
3887 if (evaspixmapsink->par) {
3888 if (!g_value_transform (evaspixmapsink->par, value)) {
3889 g_warning ("g_value_transform() failure");
3895 char *adaptor_no_s = g_strdup_printf ("%u", evaspixmapsink->adaptor_no);
3896 g_value_set_string (value, adaptor_no_s);
3897 g_free (adaptor_no_s);
3900 case PROP_DEVICE_NAME:
3901 if (evaspixmapsink->xcontext && evaspixmapsink->xcontext->adaptors) {
3902 g_value_set_string (value,
3903 evaspixmapsink->xcontext->adaptors[evaspixmapsink->adaptor_no]);
3905 g_value_set_string (value, NULL);
3908 case PROP_DOUBLE_BUFFER:
3909 g_value_set_boolean (value, evaspixmapsink->double_buffer);
3911 case PROP_AUTOPAINT_COLORKEY:
3912 g_value_set_boolean (value, evaspixmapsink->autopaint_colorkey);
3915 g_value_set_int (value, evaspixmapsink->colorkey);
3917 case PROP_PIXMAP_WIDTH:
3919 GST_LOG_OBJECT (evaspixmapsink, "Not supported");
3922 case PROP_PIXMAP_HEIGHT:
3924 GST_LOG_OBJECT (evaspixmapsink, "Not supported");
3927 case PROP_DISPLAY_GEOMETRY_METHOD:
3928 g_value_set_enum (value, evaspixmapsink->display_geometry_method);
3930 case PROP_DST_ROI_X:
3931 g_value_set_int (value, evaspixmapsink->dst_roi.x);
3933 case PROP_DST_ROI_Y:
3934 g_value_set_int (value, evaspixmapsink->dst_roi.y);
3936 case PROP_DST_ROI_W:
3937 g_value_set_int (value, evaspixmapsink->dst_roi.w);
3939 case PROP_DST_ROI_H:
3940 g_value_set_int (value, evaspixmapsink->dst_roi.h);
3942 case PROP_STOP_VIDEO:
3943 g_value_set_int (value, evaspixmapsink->stop_video);
3945 case PROP_EVAS_OBJECT:
3946 g_value_set_pointer (value, evaspixmapsink->eo);
3949 g_value_set_enum(value, evaspixmapsink->flip);
3951 case PROP_ROTATE_ANGLE:
3952 g_value_set_enum (value, evaspixmapsink->rotate_angle);
3955 g_value_set_boolean (value, evaspixmapsink->visible);
3957 case PROP_ORIGIN_SIZE:
3958 g_value_set_boolean (value, evaspixmapsink->use_origin_size);
3961 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
3967 gst_evaspixmapsink_reset (GstEvasPixmapSink *evaspixmapsink)
3969 GST_WARNING_OBJECT (evaspixmapsink,"[START]");
3972 GST_OBJECT_LOCK (evaspixmapsink);
3973 evaspixmapsink->running = FALSE;
3976 /* grab thread and mark it as NULL */
3977 thread = evaspixmapsink->event_thread;
3978 evaspixmapsink->event_thread = NULL;
3979 GST_OBJECT_UNLOCK (evaspixmapsink);
3981 /* Wait for our event thread to finish before we clean up our stuff. */
3983 g_thread_join (thread);
3986 for (i = 0; i < evaspixmapsink->num_of_pixmaps; i++) {
3987 if(evaspixmapsink->damage[i]) {
3988 XDamageDestroy(evaspixmapsink->xcontext->disp, evaspixmapsink->damage[i]);
3989 evaspixmapsink->damage[i] = NULL;
3992 EVASPIXMAPSINK_UNSET_EVAS_OBJECT_EVENT_CALLBACK( evaspixmapsink->eo );
3994 if (evaspixmapsink->evas_pixmap_buf) {
3995 gst_buffer_unref (GST_BUFFER_CAST (evaspixmapsink->evas_pixmap_buf));
3996 evaspixmapsink->evas_pixmap_buf = NULL;
3999 for (i = 0; i < evaspixmapsink->num_of_pixmaps; i++) {
4000 gst_evaspixmapsink_xpixmap_clear (evaspixmapsink, evaspixmapsink->xpixmap[i]);
4001 gst_evaspixmapsink_xpixmap_destroy (evaspixmapsink, evaspixmapsink->xpixmap[i]);
4002 evaspixmapsink->xpixmap[i] = NULL;
4004 if (evaspixmapsink->eo) {
4005 evas_object_image_native_surface_set(evaspixmapsink->eo, NULL);
4006 evaspixmapsink->eo = NULL;
4009 evaspixmapsink->render_rect.x = evaspixmapsink->render_rect.y =
4010 evaspixmapsink->render_rect.w = evaspixmapsink->render_rect.h = 0;
4011 evaspixmapsink->have_render_rect = FALSE;
4013 evaspixmapsink->epipe_request_count = 0;
4015 gst_evaspixmapsink_xcontext_clear (evaspixmapsink);
4017 GST_WARNING_OBJECT (evaspixmapsink,"[END]");
4020 /* Finalize is called only once, dispose can be called multiple times.
4021 * We use mutexes and don't reset stuff to NULL here so let's register
4024 gst_evaspixmapsink_finalize (GObject *object)
4026 GstEvasPixmapSink *evaspixmapsink;
4027 evaspixmapsink = GST_EVASPIXMAPSINK (object);
4028 GST_DEBUG_OBJECT (evaspixmapsink,"[START]");
4030 if (evaspixmapsink->display_name) {
4031 g_free (evaspixmapsink->display_name);
4032 evaspixmapsink->display_name = NULL;
4034 if (evaspixmapsink->par) {
4035 g_free (evaspixmapsink->par);
4036 evaspixmapsink->par = NULL;
4038 if (evaspixmapsink->x_lock) {
4039 g_mutex_free (evaspixmapsink->x_lock);
4040 evaspixmapsink->x_lock = NULL;
4042 if (evaspixmapsink->flow_lock) {
4043 g_mutex_free (evaspixmapsink->flow_lock);
4044 evaspixmapsink->flow_lock = NULL;
4046 if (evaspixmapsink->pixmap_ref_lock) {
4047 g_mutex_free (evaspixmapsink->pixmap_ref_lock);
4048 evaspixmapsink->pixmap_ref_lock = NULL;
4050 if (evaspixmapsink->epipe) {
4051 ecore_pipe_del (evaspixmapsink->epipe);
4052 evaspixmapsink->epipe = NULL;
4055 GST_DEBUG_OBJECT (evaspixmapsink,"[END]");
4057 G_OBJECT_CLASS (parent_class)->finalize (object);
4059 MMTA_ACUM_ITEM_SHOW_RESULT_TO(MMTA_SHOW_FILE);
4064 gst_evaspixmapsink_init (GstEvasPixmapSink *evaspixmapsink)
4068 GST_DEBUG_OBJECT (evaspixmapsink,"[START]");
4070 evaspixmapsink->display_name = NULL;
4071 evaspixmapsink->adaptor_no = 0;
4072 evaspixmapsink->xcontext = NULL;
4074 for (i = 0; i < NUM_OF_PIXMAP; i++) {
4075 evaspixmapsink->xpixmap[i] = NULL;
4076 evaspixmapsink->damage[i] = 0;
4079 evaspixmapsink->evas_pixmap_buf = NULL;
4081 evaspixmapsink->hue = evaspixmapsink->saturation = 0;
4082 evaspixmapsink->contrast = evaspixmapsink->brightness = 0;
4083 evaspixmapsink->cb_changed = FALSE;
4085 evaspixmapsink->fps_n = 0;
4086 evaspixmapsink->fps_d = 0;
4087 evaspixmapsink->video_width = 0;
4088 evaspixmapsink->video_height = 0;
4090 evaspixmapsink->x_lock = g_mutex_new ();
4091 evaspixmapsink->flow_lock = g_mutex_new ();
4092 evaspixmapsink->pixmap_ref_lock = g_mutex_new();
4094 evaspixmapsink->synchronous = FALSE;
4095 evaspixmapsink->double_buffer = TRUE;
4096 evaspixmapsink->par = NULL;
4097 evaspixmapsink->autopaint_colorkey = TRUE;
4098 evaspixmapsink->running = FALSE;
4100 /* on 16bit displays this becomes r,g,b = 1,2,3
4101 * on 24bit displays this becomes r,g,b = 8,8,16
4102 * as a port atom value
4104 evaspixmapsink->colorkey = (8 << 16) | (8 << 8) | 16;
4106 evaspixmapsink->display_geometry_method = DEF_DISPLAY_GEOMETRY_METHOD;
4107 evaspixmapsink->dst_roi.x = 0;
4108 evaspixmapsink->dst_roi.y = 0;
4109 evaspixmapsink->dst_roi.w = 0;
4110 evaspixmapsink->dst_roi.h = 0;
4111 evaspixmapsink->scr_w = 0;
4112 evaspixmapsink->scr_h = 0;
4113 evaspixmapsink->aligned_width = 0;
4114 evaspixmapsink->aligned_height = 0;
4115 evaspixmapsink->stop_video = FALSE;
4116 evaspixmapsink->eo = NULL;
4117 evaspixmapsink->epipe = NULL;
4118 evaspixmapsink->epipe_request_count = 0;
4119 evaspixmapsink->do_link = FALSE;
4120 evaspixmapsink->flip = DEF_DISPLAY_FLIP;
4121 evaspixmapsink->rotate_angle = DEGREE_0;
4122 evaspixmapsink->visible = TRUE;
4123 evaspixmapsink->update_visibility = UPDATE_FALSE;
4124 evaspixmapsink->use_origin_size = FALSE;
4125 evaspixmapsink->previous_origin_size = FALSE;
4127 evaspixmapsink->num_of_pixmaps = NUM_OF_PIXMAP;
4129 evaspixmapsink->buf_shared_type = BUF_SHARE_METHOD_NONE;
4133 GST_DEBUG_OBJECT (evaspixmapsink,"[END]");
4137 gst_evaspixmapsink_base_init (gpointer g_class)
4139 GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
4141 gst_element_class_set_details_simple (element_class,
4142 "EvasPixmapSink", "Sink/Video",
4143 "evas image object videosink based on Xv extension", "Sangchul Lee <sc11.lee@samsung.com>");
4145 gst_element_class_add_pad_template (element_class,
4146 gst_static_pad_template_get (&gst_evaspixmapsink_sink_template_factory));
4150 gst_evaspixmapsink_class_init (GstEvasPixmapSinkClass *klass)
4152 GObjectClass *gobject_class;
4153 GstElementClass *gstelement_class;
4154 GstBaseSinkClass *gstbasesink_class;
4155 GstVideoSinkClass *videosink_class;
4157 gobject_class = (GObjectClass *) klass;
4158 gstelement_class = (GstElementClass *) klass;
4159 gstbasesink_class = (GstBaseSinkClass *) klass;
4160 videosink_class = (GstVideoSinkClass *) klass;
4162 parent_class = g_type_class_peek_parent (klass);
4164 gobject_class->set_property = gst_evaspixmapsink_set_property;
4165 gobject_class->get_property = gst_evaspixmapsink_get_property;
4167 g_object_class_install_property (gobject_class, PROP_CONTRAST,
4168 g_param_spec_int ("contrast", "Contrast", "The contrast of the video",
4169 -1000, 1000, 0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
4170 g_object_class_install_property (gobject_class, PROP_BRIGHTNESS,
4171 g_param_spec_int ("brightness", "Brightness",
4172 "The brightness of the video", -1000, 1000, 0,
4173 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
4174 g_object_class_install_property (gobject_class, PROP_HUE,
4175 g_param_spec_int ("hue", "Hue", "The hue of the video", -1000, 1000, 0,
4176 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
4177 g_object_class_install_property (gobject_class, PROP_SATURATION,
4178 g_param_spec_int ("saturation", "Saturation",
4179 "The saturation of the video", -1000, 1000, 0,
4180 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
4181 g_object_class_install_property (gobject_class, PROP_DISPLAY,
4182 g_param_spec_string ("display", "Display", "X Display name", NULL,
4183 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
4184 g_object_class_install_property (gobject_class, PROP_SYNCHRONOUS,
4185 g_param_spec_boolean ("synchronous", "Synchronous",
4186 "When enabled, runs "
4187 "the X display in synchronous mode. (used only for debugging)", FALSE,
4188 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
4189 g_object_class_install_property (gobject_class, PROP_PIXEL_ASPECT_RATIO,
4190 g_param_spec_string ("pixel-aspect-ratio", "Pixel Aspect Ratio",
4191 "The pixel aspect ratio of the device", "1/1",
4192 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
4193 g_object_class_install_property (gobject_class, PROP_DEVICE,
4194 g_param_spec_string ("device", "Adaptor number",
4195 "The number of the video adaptor", "0",
4196 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
4197 g_object_class_install_property (gobject_class, PROP_DEVICE_NAME,
4198 g_param_spec_string ("device-name", "Adaptor name",
4199 "The name of the video adaptor", NULL,
4200 G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
4203 * GstEvasPixmapSink:double-buffer
4205 * Whether to double-buffer the output.
4209 g_object_class_install_property (gobject_class, PROP_DOUBLE_BUFFER,
4210 g_param_spec_boolean ("double-buffer", "Double-buffer",
4211 "Whether to double-buffer the output", TRUE,
4212 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
4214 * GstEvasPixmapSink:autopaint-colorkey
4216 * Whether to autofill overlay with colorkey
4220 g_object_class_install_property (gobject_class, PROP_AUTOPAINT_COLORKEY,
4221 g_param_spec_boolean ("autopaint-colorkey", "Autofill with colorkey",
4222 "Whether to autofill overlay with colorkey", TRUE,
4223 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
4225 * GstEvasPixmapSink:colorkey
4227 * Color to use for the overlay mask.
4231 g_object_class_install_property (gobject_class, PROP_COLORKEY,
4232 g_param_spec_int ("colorkey", "Colorkey",
4233 "Color to use for the overlay mask", G_MININT, G_MAXINT, 0,
4234 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
4237 * GstEvasPixmapSink:pixmap-width
4239 * Actual width of the pixmap.
4241 g_object_class_install_property (gobject_class, PROP_PIXMAP_WIDTH,
4242 g_param_spec_uint64 ("pixmap-width", "pixmap-width", "Width of the pixmap", 0, G_MAXUINT64, 0, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
4245 * GstEvasPixmapSink:pixmap-height
4247 * Actual height of the pixmap.
4249 g_object_class_install_property (gobject_class, PROP_PIXMAP_HEIGHT,
4250 g_param_spec_uint64 ("pixmap-height", "pixmap-height", "Height of the pixmap", 0, G_MAXUINT64, 0, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
4253 * GstEvasPixmapSink:display-geometry-method
4255 * Display geometrical method setting
4257 g_object_class_install_property(gobject_class, PROP_DISPLAY_GEOMETRY_METHOD,
4258 g_param_spec_enum("display-geometry-method", "Display geometry method",
4259 "Geometrical method for display",
4260 GST_TYPE_EVASPIXMAPSINK_DISPLAY_GEOMETRY_METHOD, DEF_DISPLAY_GEOMETRY_METHOD,
4261 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
4264 * GstEvasPixmapSink:dst-roi-x
4266 * X value of Destination ROI
4268 g_object_class_install_property (gobject_class, PROP_DST_ROI_X,
4269 g_param_spec_int ("dst-roi-x", "Dst-ROI-X",
4270 "X value of Destination ROI(only effective \"CUSTOM_ROI\")", 0, XV_SCREEN_SIZE_WIDTH, 0,
4271 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
4274 * GstEvasPixmapSink:dst-roi-y
4276 * Y value of Destination ROI
4278 g_object_class_install_property (gobject_class, PROP_DST_ROI_Y,
4279 g_param_spec_int ("dst-roi-y", "Dst-ROI-Y",
4280 "Y value of Destination ROI(only effective \"CUSTOM_ROI\")", 0, XV_SCREEN_SIZE_HEIGHT, 0,
4281 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
4284 * GstEvasPixmapSink:dst-roi-w
4286 * W value of Destination ROI
4288 g_object_class_install_property (gobject_class, PROP_DST_ROI_W,
4289 g_param_spec_int ("dst-roi-w", "Dst-ROI-W",
4290 "W value of Destination ROI(only effective \"CUSTOM_ROI\")", 0, XV_SCREEN_SIZE_WIDTH, 0,
4291 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
4294 * GstEvasPixmapSink:dst-roi-h
4296 * H value of Destination ROI
4298 g_object_class_install_property (gobject_class, PROP_DST_ROI_H,
4299 g_param_spec_int ("dst-roi-h", "Dst-ROI-H",
4300 "H value of Destination ROI(only effective \"CUSTOM_ROI\")", 0, XV_SCREEN_SIZE_HEIGHT, 0,
4301 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
4304 * GstEvasPixmapSink:stop-video
4306 * Stop video for releasing video source buffer
4308 g_object_class_install_property (gobject_class, PROP_STOP_VIDEO,
4309 g_param_spec_int ("stop-video", "Stop-Video", "Stop video for releasing video source buffer", 0, 1, 0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
4312 * GstEvasPixmapSink:evas-object
4314 * Evas image object for rendering
4316 g_object_class_install_property (gobject_class, PROP_EVAS_OBJECT,
4317 g_param_spec_pointer ("evas-object", "Destination Evas Object", "Destination evas image object", G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
4320 * GstEvasPixmapSink:display-flip
4322 * Display flip setting
4324 g_object_class_install_property(gobject_class, PROP_FLIP,
4325 g_param_spec_enum("flip", "Display flip",
4327 GST_TYPE_EVASPIXMAPSINK_FLIP, DEF_DISPLAY_FLIP,
4328 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
4331 * GstEvasPixmapSink:rotate
4333 * draw rotation angle setting
4335 g_object_class_install_property(gobject_class, PROP_ROTATE_ANGLE,
4336 g_param_spec_enum("rotate", "Rotate angle", "Rotate angle of display output",GST_TYPE_EVASPIXMAPSINK_ROTATE_ANGLE, DEGREE_0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
4339 * GstEvasPixmapSink:visible
4341 * visible setting for a evas image object
4343 g_object_class_install_property (gobject_class, PROP_VISIBLE,
4344 g_param_spec_boolean ("visible", "Visible", "When setting it false, evas image object does not show", TRUE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
4347 * GstEvasPixmapSink:origin-size
4349 * Set pixmap size with media source's width and height
4351 g_object_class_install_property (gobject_class, PROP_ORIGIN_SIZE,
4352 g_param_spec_boolean ("origin-size", "Origin-Size", "When setting it true, pixmap will be created with media source's width and height", FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
4354 gobject_class->finalize = gst_evaspixmapsink_finalize;
4356 gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_evaspixmapsink_change_state);
4357 gstbasesink_class->get_caps = GST_DEBUG_FUNCPTR (gst_evaspixmapsink_getcaps);
4358 gstbasesink_class->set_caps = GST_DEBUG_FUNCPTR (gst_evaspixmapsink_setcaps);
4359 gstbasesink_class->get_times = GST_DEBUG_FUNCPTR (gst_evaspixmapsink_get_times);
4360 gstbasesink_class->event = GST_DEBUG_FUNCPTR (gst_evaspixmapsink_event);
4361 videosink_class->show_frame = GST_DEBUG_FUNCPTR (gst_evaspixmapsink_show_frame);
4364 /* Object typing & Creation */
4366 gst_evaspixmapsink_get_type (void)
4368 static GType evaspixmapsink_type = 0;
4370 if (!evaspixmapsink_type) {
4371 static const GTypeInfo evaspixmapsink_info = {
4372 sizeof (GstEvasPixmapSinkClass),
4373 gst_evaspixmapsink_base_init,
4375 (GClassInitFunc) gst_evaspixmapsink_class_init,
4378 sizeof (GstEvasPixmapSink),
4380 (GInstanceInitFunc) gst_evaspixmapsink_init,
4382 static const GInterfaceInfo iface_info = {
4383 (GInterfaceInitFunc) gst_evaspixmapsink_interface_init,
4387 static const GInterfaceInfo navigation_info = {
4388 (GInterfaceInitFunc) gst_evaspixmapsink_navigation_init,
4392 static const GInterfaceInfo colorbalance_info = {
4393 (GInterfaceInitFunc) gst_evaspixmapsink_colorbalance_init,
4397 static const GInterfaceInfo propertyprobe_info = {
4398 (GInterfaceInitFunc) gst_evaspixmapsink_property_probe_interface_init,
4402 evaspixmapsink_type = g_type_register_static (GST_TYPE_VIDEO_SINK, "GstEvasPixmapSink", &evaspixmapsink_info, 0);
4404 g_type_add_interface_static (evaspixmapsink_type, GST_TYPE_IMPLEMENTS_INTERFACE, &iface_info);
4405 g_type_add_interface_static (evaspixmapsink_type, GST_TYPE_NAVIGATION, &navigation_info);
4406 g_type_add_interface_static (evaspixmapsink_type, GST_TYPE_COLOR_BALANCE, &colorbalance_info);
4407 g_type_add_interface_static (evaspixmapsink_type, GST_TYPE_PROPERTY_PROBE, &propertyprobe_info);
4409 /* register type and create class in a more safe place instead of at
4410 * runtime since the type registration and class creation is not
4412 g_type_class_ref (gst_evaspixmap_buffer_get_type ());
4415 return evaspixmapsink_type;
4419 plugin_init (GstPlugin *plugin)
4421 if (!gst_element_register (plugin, "evaspixmapsink", GST_RANK_NONE, GST_TYPE_EVASPIXMAPSINK)) {
4424 GST_DEBUG_CATEGORY_INIT (gst_debug_evaspixmapsink, "evaspixmapsink", 0, "evaspixmapsink element");
4425 GST_DEBUG_CATEGORY_GET (GST_CAT_PERFORMANCE, "GST_PERFORMANCE");
4430 GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, GST_VERSION_MINOR,
4431 "evaspixmapsink","Evas image object render plugin using Xv extension", plugin_init,
4432 VERSION, GST_LICENSE, GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN)