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
165 int util_write_rawdata (const char *file, const void *data, unsigned int size);
166 typedef struct _BufferInfo
177 DRI2Buffer *dri2_buffers;
181 static BufferInfo *g_bufinfo[NUM_OF_PIXMAP];
182 void * gst_evaspixmapsink_get_buffer (Display *dpy, Pixmap pixmap, int width, int height, int i);
183 void gst_evaspixmapsink_free_buffer (int i);
184 static Bool gst_evaspixmapsink_init_dri2 (BufferInfo *bufinfo);
188 /* macro ******************************************************/
189 #define EVASPIXMAPSINK_SET_PIXMAP_ID_TO_GEM_INFO( x_evaspixmapsink, x_pixmap_id ) \
193 XV_DATA_PTR data = (XV_DATA_PTR)x_evaspixmapsink->evas_pixmap_buf->xvimage->data; \
194 if (data->YBuf > 0) { \
195 for (i = 0; i < MAX_GEM_BUFFER_NUM; i++) { \
196 if (evaspixmapsink->gem_info[i].gem_name == data->YBuf) { \
197 evaspixmapsink->gem_info[i].ref_pixmap = x_pixmap_id; \
198 GST_LOG_OBJECT (x_evaspixmapsink,"pixmap(%d) is marked at index(%d) of gem_info(YBuf)->gem_handle(%d)", x_pixmap_id, i, evaspixmapsink->gem_info[i].gem_handle); \
203 if (data->CbBuf > 0) { \
204 for (i = 0; i < MAX_GEM_BUFFER_NUM; i++) { \
205 if (evaspixmapsink->gem_info[i].gem_name == data->CbBuf) { \
206 evaspixmapsink->gem_info[i].ref_pixmap = x_pixmap_id; \
207 GST_LOG_OBJECT (x_evaspixmapsink,"pixmap(%d) is marked at index(%d) of gem_info(CbBuf)->gem_handle(%d)", x_pixmap_id, i, evaspixmapsink->gem_info[i].gem_handle); \
212 if (data->CrBuf > 0) { \
213 for (i = 0; i < MAX_GEM_BUFFER_NUM; i++) { \
214 if (evaspixmapsink->gem_info[i].gem_name == data->CrBuf) { \
215 evaspixmapsink->gem_info[i].ref_pixmap = x_pixmap_id; \
216 GST_LOG_OBJECT (x_evaspixmapsink,"pixmap(%d) is marked at index(%d) of gem_info(CrBuf)->gem_handle(%d)", x_pixmap_id, i, evaspixmapsink->gem_info[i].gem_handle); \
223 #define EVASPIXMAPSINK_SET_EVAS_OBJECT_EVENT_CALLBACK( x_evas_image_object, x_usr_data ) \
226 evas_object_event_callback_add (x_evas_image_object, EVAS_CALLBACK_DEL, evas_callback_del_event, x_usr_data); \
227 evas_object_event_callback_add (x_evas_image_object, EVAS_CALLBACK_RESIZE, evas_callback_resize_event, x_usr_data); \
228 evas_object_event_callback_add (x_evas_image_object, EVAS_CALLBACK_SHOW, evas_callback_show_event, x_usr_data); \
229 evas_object_event_callback_add (x_evas_image_object, EVAS_CALLBACK_HIDE, evas_callback_hide_event, x_usr_data); \
232 #define EVASPIXMAPSINK_UNSET_EVAS_OBJECT_EVENT_CALLBACK( x_evas_image_object ) \
235 evas_object_event_callback_del (x_evas_image_object, EVAS_CALLBACK_DEL, evas_callback_del_event); \
236 evas_object_event_callback_del (x_evas_image_object, EVAS_CALLBACK_RESIZE, evas_callback_resize_event); \
237 evas_object_event_callback_del (x_evas_image_object, EVAS_CALLBACK_SHOW, evas_callback_show_event); \
238 evas_object_event_callback_del (x_evas_image_object, EVAS_CALLBACK_HIDE, evas_callback_hide_event); \
242 gst_evaspixmapsink_flip_get_type(void)
244 static GType evaspixmapsink_flip_type = 0;
245 static const GEnumValue flip_type[] = {
246 { FLIP_NONE, "Flip NONE", "FLIP_NONE"},
247 { FLIP_HORIZONTAL, "Flip HORIZONTAL", "FLIP_HORIZONTAL"},
248 { FLIP_VERTICAL, "Flip VERTICAL", "FLIP_VERTICAL"},
249 { FLIP_BOTH, "Flip BOTH", "FLIP_BOTH"},
250 { FLIP_NUM, NULL, NULL},
253 if (!evaspixmapsink_flip_type) {
254 evaspixmapsink_flip_type = g_enum_register_static("GstEvasPixmapSinkFlipType", flip_type);
257 return evaspixmapsink_flip_type;
261 gst_evaspixmapsink_rotate_angle_get_type(void)
263 static GType evaspixmapsink_rotate_angle_type = 0;
264 static const GEnumValue rotate_angle_type[] = {
265 { 0, "No rotate", "DEGREE_0"},
266 { 1, "Rotate 90 degree", "DEGREE_90"},
267 { 2, "Rotate 180 degree", "DEGREE_180"},
268 { 3, "Rotate 270 degree", "DEGREE_270"},
272 if (!evaspixmapsink_rotate_angle_type) {
273 evaspixmapsink_rotate_angle_type = g_enum_register_static("GstEvasPixmapSinkRotateAngleType", rotate_angle_type);
276 return evaspixmapsink_rotate_angle_type;
280 gst_evaspixmapsink_display_geometry_method_get_type(void)
282 static GType evaspixmapsink_display_geometry_method_type = 0;
283 static const GEnumValue display_geometry_method_type[] = {
284 { 0, "Letter box", "LETTER_BOX"},
285 { 1, "Origin size", "ORIGIN_SIZE"},
286 { 2, "Full-screen", "FULL_SCREEN"},
287 { 3, "Cropped Full-screen", "CROPPED_FULL_SCREEN"},
288 { 4, "Explicitely described destination ROI", "CUSTOM_ROI"},
292 if (!evaspixmapsink_display_geometry_method_type) {
293 evaspixmapsink_display_geometry_method_type = g_enum_register_static("GstEvasPixmapSinkDisplayGeometryMethodType", display_geometry_method_type);
296 return evaspixmapsink_display_geometry_method_type;
302 unsigned long functions;
303 unsigned long decorations;
305 unsigned long status;
307 MotifWmHints, MwmHints;
309 #define MWM_HINTS_DECORATIONS (1L << 1)
311 static void gst_evaspixmapsink_reset (GstEvasPixmapSink *evaspixmapsink);
312 static GstBufferClass *evaspixmap_buffer_parent_class = NULL;
313 static void gst_evaspixmap_buffer_finalize (GstEvasPixmapBuffer *evaspixmapbuf);
314 static void gst_evaspixmapsink_xcontext_clear (GstEvasPixmapSink *evaspixmapsink);
315 static void gst_evaspixmapsink_xpixmap_destroy (GstEvasPixmapSink *evaspixmapsink, GstXPixmap *xpixmap);
316 static void gst_evaspixmapsink_xpixmap_update_geometry (GstEvasPixmapSink *evaspixmapsink, int idx);
317 static gboolean gst_evaspixmap_buffer_put (GstEvasPixmapSink *evaspixmapsink, GstEvasPixmapBuffer *evaspixmapbuf);
318 static gboolean gst_evaspixmapsink_xpixmap_link (GstEvasPixmapSink *evaspixmapsink);
319 static void gst_evaspixmapsink_xpixmap_clear (GstEvasPixmapSink *evaspixmapsink, GstXPixmap *xpixmap);
320 static gint gst_evaspixmapsink_get_format_from_caps (GstEvasPixmapSink *evaspixmapsink, GstCaps *caps);
321 static void drm_close_gem(GstEvasPixmapSink *evaspixmapsink, unsigned int gem_handle);
322 static void drm_fini_close_gem_handle(GstEvasPixmapSink *evaspixmapsink, Pixmap pixmap_id);
323 static void evas_callback_resize_event (void *data, Evas *e, Evas_Object *obj, void *event_info);
324 static void evas_callback_del_event (void *data, Evas *e, Evas_Object *obj, void *event_info);
325 static void evas_callback_show_event (void *data, Evas *e, Evas_Object *obj, void *event_info);
326 static void evas_callback_hide_event (void *data, Evas *e, Evas_Object *obj, void *event_info);
328 /* Default template - initiated with class struct to allow gst-register to work
330 static GstStaticPadTemplate gst_evaspixmapsink_sink_template_factory =
331 GST_STATIC_PAD_TEMPLATE ("sink",
334 GST_STATIC_CAPS ("video/x-raw-rgb, "
335 "framerate = (fraction) [ 0, MAX ], "
336 "width = (int) [ 1, MAX ], "
337 "height = (int) [ 1, MAX ]; "
339 "framerate = (fraction) [ 0, MAX ], "
340 "width = (int) [ 1, MAX ], " "height = (int) [ 1, MAX ]")
352 PROP_PIXEL_ASPECT_RATIO,
356 PROP_AUTOPAINT_COLORKEY,
362 PROP_DISPLAY_GEOMETRY_METHOD,
374 static GstVideoSinkClass *parent_class = NULL;
376 /* ============================================================= */
378 /* Private Methods */
380 /* ============================================================= */
382 /* evaspixmap buffers */
384 #define GST_TYPE_EVASPIXMAP_BUFFER (gst_evaspixmap_buffer_get_type())
386 #define GST_IS_EVASPIXMAP_BUFFER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_EVASPIXMAP_BUFFER))
387 #define GST_EVASPIXMAP_BUFFER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_EVASPIXMAP_BUFFER, GstEvasPixmapBuffer))
389 static int log_warn_count = 0;
393 static int get_millis_time()
396 clock_gettime(CLOCK_MONOTONIC, &tp);
397 return (tp.tv_sec * 1000) + (tp.tv_nsec / 1000000L);
401 ecore_pipe_callback_handler (void *data, void *buffer, unsigned int nbyte)
404 GST_WARNING ("data is NULL..");
408 GstEvasPixmapSink *evaspixmapsink = (GstEvasPixmapSink*)data;
409 GST_DEBUG_OBJECT (evaspixmapsink,"[START] Evas_Object(0x%x)", evaspixmapsink->eo);
412 GstXPixmap *xpixmap = NULL;
414 g_mutex_lock (evaspixmapsink->flow_lock);
416 evaspixmapsink->epipe_request_count--;
417 if (!evaspixmapsink->eo) {
418 GST_WARNING_OBJECT (evaspixmapsink,"evas object is NULL..");
419 g_mutex_unlock (evaspixmapsink->flow_lock);
423 if (!evaspixmapsink->xcontext) {
424 GST_WARNING_OBJECT (evaspixmapsink,"xcontext is NULL..");
425 g_mutex_unlock (evaspixmapsink->flow_lock);
429 /* setting evas object hide and show */
430 if (nbyte == SIZE_FOR_UPDATE_VISIBILITY) {
431 if(!evaspixmapsink->visible) {
432 evas_object_hide(evaspixmapsink->eo);
433 GST_INFO_OBJECT (evaspixmapsink, "object hide");
435 if (!evas_object_image_native_surface_get(evaspixmapsink->eo)) {
436 GST_WARNING_OBJECT (evaspixmapsink, "native surface is not set, skip evas_object_show()..");
438 evas_object_show(evaspixmapsink->eo);
439 GST_INFO_OBJECT (evaspixmapsink, "object show");
442 g_mutex_unlock (evaspixmapsink->flow_lock);
446 /* mapping evas object with xpixmap */
447 if (evaspixmapsink->do_link) {
448 GST_DEBUG_OBJECT (evaspixmapsink,"do link");
449 evas_object_image_size_set(evaspixmapsink->eo, evaspixmapsink->w, evaspixmapsink->h);
450 if (evaspixmapsink->xpixmap[idx]->pixmap) {
451 Evas_Native_Surface surf;
452 surf.version = EVAS_NATIVE_SURFACE_VERSION;
453 surf.type = EVAS_NATIVE_SURFACE_X11;
454 surf.data.x11.visual = ecore_x_default_visual_get(ecore_x_display_get(), ecore_x_default_screen_get());
455 surf.data.x11.pixmap = evaspixmapsink->xpixmap[idx]->pixmap;
456 evas_object_image_native_surface_set(evaspixmapsink->eo, &surf);
457 evaspixmapsink->do_link = FALSE;
459 GST_WARNING_OBJECT (evaspixmapsink,"pixmap is NULL..");
460 g_mutex_unlock (evaspixmapsink->flow_lock);
463 for (i = 0; i < evaspixmapsink->num_of_pixmaps; i++) {
464 if (evaspixmapsink->xpixmap[i]->prev_pixmap && evaspixmapsink->xpixmap[i]->prev_gc && evaspixmapsink->prev_damage[i]) {
465 GST_LOG_OBJECT (evaspixmapsink,"Free pixmap(%d), gc(%x), destroy previous damage(%d)",
466 evaspixmapsink->xpixmap[i]->prev_pixmap, evaspixmapsink->xpixmap[i]->prev_gc, evaspixmapsink->prev_damage[i]);
467 g_mutex_lock (evaspixmapsink->x_lock);
468 XFreePixmap(evaspixmapsink->xcontext->disp, evaspixmapsink->xpixmap[i]->prev_pixmap);
469 XFreeGC (evaspixmapsink->xcontext->disp, evaspixmapsink->xpixmap[i]->prev_gc);
470 XDamageDestroy(evaspixmapsink->xcontext->disp, evaspixmapsink->prev_damage[i]);
471 XSync(evaspixmapsink->xcontext->disp, FALSE);
472 g_mutex_unlock (evaspixmapsink->x_lock);
473 evaspixmapsink->xpixmap[i]->prev_pixmap = 0;
474 evaspixmapsink->xpixmap[i]->prev_gc = 0;
475 evaspixmapsink->prev_damage[i] = NULL;
478 if (evaspixmapsink->visible && !evas_object_visible_get(evaspixmapsink->eo)) {
479 evas_object_show(evaspixmapsink->eo);
480 GST_WARNING_OBJECT (evaspixmapsink, "object show (lazy)");
484 GST_DEBUG_OBJECT (evaspixmapsink,"update");
485 /* update evas image object size */
486 if (evaspixmapsink->use_origin_size) {
487 evas_object_geometry_get(evaspixmapsink->eo, NULL, NULL, &evaspixmapsink->w, &evaspixmapsink->h);
490 g_mutex_lock (evaspixmapsink->pixmap_ref_lock);
492 /* find a oldest damaged pixmap */
494 for (i = 0; i < evaspixmapsink->num_of_pixmaps; i++) {
495 if (evaspixmapsink->last_updated_idx == i) {
498 xpixmap = evaspixmapsink->xpixmap[i];
499 if (xpixmap->ref > 0 && xpixmap->damaged_time) {
500 if (temp_time == 0) {
501 temp_time = xpixmap->damaged_time;
504 if (temp_time > xpixmap->damaged_time) {
505 temp_time = xpixmap->damaged_time;
513 xpixmap = evaspixmapsink->xpixmap[idx];
514 if (xpixmap->pixmap) {
515 if (evaspixmapsink->last_updated_idx != idx) {
516 Evas_Native_Surface surf;
517 surf.version = EVAS_NATIVE_SURFACE_VERSION;
518 surf.type = EVAS_NATIVE_SURFACE_X11;
519 surf.data.x11.visual = ecore_x_default_visual_get(ecore_x_display_get(), ecore_x_default_screen_get());
520 surf.data.x11.pixmap = xpixmap->pixmap;
521 if (evaspixmapsink->eo) {
522 evas_object_image_native_surface_set(evaspixmapsink->eo, NULL);
524 evas_object_image_native_surface_set(evaspixmapsink->eo, &surf);
525 GST_LOG_OBJECT (evaspixmapsink,"update, native_surface_set of xpixmap[%d]",idx);
526 if (evaspixmapsink->last_updated_idx == -1) {
527 xpixmap->damaged_time = 0;
528 GST_INFO_OBJECT (evaspixmapsink,"this is the first time to request to update(do not DECREASE ref-count) : pixmap(%d), refcount(%d), damaged_time(%d), idx(%d)",
529 xpixmap->pixmap, xpixmap->ref, xpixmap->damaged_time, idx);
531 xpixmap = evaspixmapsink->xpixmap[evaspixmapsink->last_updated_idx];
533 xpixmap->damaged_time = 0;
534 GST_INFO_OBJECT (evaspixmapsink,"pixmap ref-count DECREASED : pixmap(%d), refcount(%d), damaged_time(%d), idx(%d)",
535 xpixmap->pixmap, xpixmap->ref, xpixmap->damaged_time, evaspixmapsink->last_updated_idx);
537 evaspixmapsink->last_updated_idx = idx;
540 evas_object_image_fill_set(evaspixmapsink->eo, 0, 0, evaspixmapsink->w, evaspixmapsink->h);
541 evas_object_image_data_update_add(evaspixmapsink->eo, 0, 0, evaspixmapsink->w, evaspixmapsink->h);
542 //GST_LOG_OBJECT (evaspixmapsink,"request to update : pixmap idx(%d), ref(%d)", idx, xpixmap->ref);
544 GST_ERROR_OBJECT (evaspixmapsink,"pixmap is NULL..");
546 g_mutex_unlock (evaspixmapsink->pixmap_ref_lock);
549 GST_DEBUG_OBJECT (evaspixmapsink,"[END]");
550 g_mutex_unlock (evaspixmapsink->flow_lock);
553 static inline gboolean
554 is_evas_image_object (Evas_Object *obj)
558 GST_ERROR ("evas image object is NULL..");
561 type = evas_object_type_get (obj);
563 GST_ERROR ("could not find type of the evas object..");
566 if (strcmp (type, "image") == 0) {
573 evas_callback_resize_event (void *data, Evas *e, Evas_Object *obj, void *event_info)
577 float former_ratio = 0;
581 float abs_margin = 0;
584 GstEvasPixmapSink *evaspixmapsink = (GstEvasPixmapSink *)data;
585 GST_DEBUG_OBJECT (evaspixmapsink,"[START] evas_image_object(%x), tid(%u)", obj, (unsigned int)pthread_self());
587 evas_object_geometry_get(evaspixmapsink->eo, NULL, NULL, &w, &h);
588 GST_DEBUG_OBJECT (evaspixmapsink,"resized : w(%d), h(%d)", w, h);
589 if (!evaspixmapsink->use_origin_size &&
590 (evaspixmapsink->w != w || evaspixmapsink->h != h)) {
591 former_ratio = (float)evaspixmapsink->w / evaspixmapsink->h;
592 ratio = (float)w / h;
593 evaspixmapsink->w = w;
594 evaspixmapsink->h = h;
597 GST_DEBUG_OBJECT (evaspixmapsink,"resized : ratio(%.3f=>%.3f)", former_ratio, ratio);
598 if ( former_ratio >= ratio ) {
599 abs_margin = former_ratio - ratio;
601 abs_margin = ratio - former_ratio;
603 /* re-link_pixmap can only be set when ratio is changed */
604 if ( abs_margin >= MARGIN_OF_ERROR ) {
606 if (!gst_evaspixmapsink_xpixmap_link(evaspixmapsink)) {
607 GST_ERROR_OBJECT (evaspixmapsink,"link evas image object with pixmap failed...");
610 for (i = 0; i < MAX_GEM_BUFFER_NUM; i++) {
611 if (evaspixmapsink->gem_info[i].ref_pixmap > 0) {
612 GST_LOG_OBJECT (evaspixmapsink,"set ref_pixmap(%d) to 0 in gem_info[%d]", evaspixmapsink->gem_info[i].ref_pixmap, i);
613 evaspixmapsink->gem_info[i].ref_pixmap = 0;
618 * Pixmap is reallocated.
619 * But native surface has old pixmap.
620 * In this case, evas can rendering with old pixmap.
621 * That makes broken image in the window.
622 * So I just unset evas native surface.
624 if (evaspixmapsink->eo) {
625 evas_object_image_native_surface_set(evaspixmapsink->eo, NULL);
626 evas_object_image_data_set(evaspixmapsink->eo, NULL);
633 if (GST_STATE(evaspixmapsink) >= GST_STATE_PAUSED) {
634 gst_evaspixmap_buffer_put (evaspixmapsink, evaspixmapsink->evas_pixmap_buf);
637 GST_DEBUG_OBJECT (evaspixmapsink,"[END]");
641 evas_callback_del_event (void *data, Evas *e, Evas_Object *obj, void *event_info)
643 GstEvasPixmapSink *evaspixmapsink = data;
644 if (!evaspixmapsink) {
645 GST_WARNING ("evaspixmapsink is NULL..");
648 GST_DEBUG_OBJECT (evaspixmapsink,"[START]");
650 EVASPIXMAPSINK_UNSET_EVAS_OBJECT_EVENT_CALLBACK( evaspixmapsink->eo );
651 if (evaspixmapsink->eo) {
652 evas_object_image_native_surface_set(evaspixmapsink->eo, NULL);
653 evaspixmapsink->eo = NULL;
656 GST_DEBUG_OBJECT (evaspixmapsink,"[END]");
660 evas_callback_show_event (void *data, Evas *e, Evas_Object *obj, void *event_info)
662 GstEvasPixmapSink *evaspixmapsink = (GstEvasPixmapSink *)data;
663 GST_INFO_OBJECT (evaspixmapsink,"show evas_image_object(%x) from pid(%d), tid(%u)", obj, getpid(), (unsigned int)pthread_self());
667 evas_callback_hide_event (void *data, Evas *e, Evas_Object *obj, void *event_info)
669 GstEvasPixmapSink *evaspixmapsink = (GstEvasPixmapSink *)data;
670 GST_INFO_OBJECT (evaspixmapsink,"hide evas_image_object(%x) from pid(%d), tid(%u)", obj, getpid(), (unsigned int)pthread_self());
674 static gboolean error_caught = FALSE;
677 gst_evaspixmapsink_handle_xerror (Display * display, XErrorEvent * xevent)
679 char error_msg[1024];
681 XGetErrorText (display, xevent->error_code, error_msg, 1024);
682 if (display != g_my_disp) {
683 GST_WARNING ("evaspixmapsink triggered an XError. but display(%p) is not ours(%p), just skip it. error(%s), xevent->request_code(%d)", display, g_my_disp, error_msg, xevent->request_code);
685 GST_ERROR ("evaspixmapsink triggered an XError. error(%s), display(%p), xevent->request_code(%d)", error_msg, display, xevent->request_code);
692 int util_write_rawdata(const char *file, const void *data, unsigned int size)
696 fp = fopen(file, "wb");
699 GST_WARNING("fopen fail... size : %d", size);
702 fwrite((char*)data, sizeof(char), size, fp);
709 gst_evaspixmapsink_get_buffer (Display *dpy, Pixmap pixmap, int width, int height, int i)
711 if (g_bufinfo[i]!=NULL)
713 GST_ERROR("g_bufinfo!=NULL %p", g_bufinfo[i]);
717 g_bufinfo[i] = calloc (1, sizeof (BufferInfo));
719 g_bufinfo[i]->dpy = dpy;
720 g_bufinfo[i]->pixmap = pixmap;
721 g_bufinfo[i]->width = width;
722 g_bufinfo[i]->height = height;
724 if (!gst_evaspixmapsink_init_dri2 (g_bufinfo[i]))
731 if (g_bufinfo[i]->virtual == NULL)
733 GST_ERROR("g_bufinfo->virtual == NULL");
737 return g_bufinfo[i]->virtual;
741 gst_evaspixmapsink_free_buffer (int i)
743 if (g_bufinfo[i] == NULL)
745 GST_ERROR("g_bufinfo == NULL");
749 if (g_bufinfo[i]==NULL)
751 GST_ERROR("g_bufinfo==NULL");
757 if (g_bufinfo[i]->bo)
758 tbm_bo_unref(g_bufinfo[i]->bo);
759 if (g_bufinfo[i]->dri2_buffers)
760 free(g_bufinfo[i]->dri2_buffers);
761 if (g_bufinfo[i]->bufmgr)
762 tbm_bufmgr_deinit (g_bufinfo[i]->bufmgr);
763 if (g_bufinfo[i]->drm_fd >= 0)
764 close (g_bufinfo[i]->drm_fd);
767 XSync (g_bufinfo[i]->dpy, 0);
772 static Bool gst_evaspixmapsink_init_dri2 (BufferInfo *bufinfo)
776 int dri2_err_base = 0;
777 int dri2Major, dri2Minor;
778 char *driverName = NULL, *deviceName = NULL;
779 unsigned int attachments[1];
780 int dri2_count, dri2_out_count;
781 int dri2_width, dri2_height;
783 tbm_bo_handle bo_handle;
784 screen = DefaultScreen(bufinfo->dpy);
785 if (!DRI2QueryExtension (bufinfo->dpy, &dri2_base, &dri2_err_base))
787 GST_ERROR ("no DRI2 extension. !!\n");
790 if (!DRI2QueryVersion (bufinfo->dpy, &dri2Major, &dri2Minor))
792 GST_ERROR ("fail : DRI2QueryVersion !!\n");
795 if (!DRI2Connect (bufinfo->dpy, RootWindow(bufinfo->dpy, screen), &driverName, &deviceName))
797 GST_ERROR ("fail : DRI2Connect !!\n");
800 bufinfo->drm_fd = open (deviceName, O_RDWR);
801 if (bufinfo->drm_fd < 0)
803 GST_ERROR ("fail : open drm device (%s)\n", deviceName);
806 /* get the drm magic */
807 drmGetMagic(bufinfo->drm_fd, &magic);
808 if (!DRI2Authenticate(bufinfo->dpy, RootWindow(bufinfo->dpy, screen), magic))
810 GST_ERROR ("fail : DRI2Authenticate (%d)\n", magic);
814 bufinfo->bufmgr = tbm_bufmgr_init (bufinfo->drm_fd);
815 if (!bufinfo->bufmgr)
817 GST_ERROR ("fail : init buffer manager \n");
820 DRI2CreateDrawable (bufinfo->dpy, bufinfo->pixmap);
821 attachments[0] = DRI2BufferFrontLeft;
823 bufinfo->dri2_buffers = DRI2GetBuffers (bufinfo->dpy, bufinfo->pixmap, &dri2_width, &dri2_height,
824 attachments, dri2_count, &dri2_out_count);
825 if (!bufinfo->dri2_buffers)
827 GST_ERROR ("fail : get buffers\n");
830 if (!bufinfo->dri2_buffers[0].name)
832 GST_ERROR ("fail : a handle of the dri2 buffer is null \n ");
835 bufinfo->bo = tbm_bo_import (bufinfo->bufmgr, bufinfo->dri2_buffers[0].name);
838 GST_ERROR ("fail : import bo (key:%d)\n", bufinfo->dri2_buffers[0].name);
842 bo_handle = tbm_bo_map(bufinfo->bo, TBM_DEVICE_CPU, TBM_OPTION_WRITE);
845 GST_ERROR ("fail : tbm_bo_map");
848 tbm_bo_unmap (bufinfo->bo);
850 bufinfo->virtual = (void *)bo_handle.ptr;
851 if (!bufinfo->virtual)
853 GST_ERROR ("fail : map \n");
868 tbm_bo_unref(bufinfo->bo);
869 if (bufinfo->dri2_buffers)
870 free(bufinfo->dri2_buffers);
872 tbm_bufmgr_deinit (bufinfo->bufmgr);
873 if (bufinfo->drm_fd >= 0)
874 close (bufinfo->drm_fd);
880 /* This function checks that it is actually really possible to create an image
883 gst_evaspixmapsink_check_xshm_calls (GstXContext * xcontext)
886 XShmSegmentInfo SHMInfo;
888 int (*handler) (Display *, XErrorEvent *);
889 gboolean result = FALSE;
890 gboolean did_attach = FALSE;
892 g_return_val_if_fail (xcontext != NULL, FALSE);
894 /* Sync to ensure any older errors are already processed */
895 XSync (xcontext->disp, FALSE);
897 /* Set defaults so we don't free these later unnecessarily */
898 SHMInfo.shmaddr = ((void *) -1);
901 /* Setting an error handler to catch failure */
902 error_caught = FALSE;
903 handler = XSetErrorHandler (gst_evaspixmapsink_handle_xerror);
905 /* Trying to create a 1x1 picture */
906 GST_DEBUG ("XvShmCreateImage of 1x1");
907 xvimage = XvShmCreateImage (xcontext->disp, xcontext->xv_port_id,
908 xcontext->im_format, NULL, 1, 1, &SHMInfo);
910 /* Might cause an error, sync to ensure it is noticed */
911 XSync (xcontext->disp, FALSE);
912 if (!xvimage || error_caught) {
913 GST_WARNING ("could not XvShmCreateImage a 1x1 image");
916 size = xvimage->data_size;
918 SHMInfo.shmid = shmget (IPC_PRIVATE, size, IPC_CREAT | 0777);
919 if (SHMInfo.shmid == -1) {
920 GST_WARNING ("could not get shared memory of %d bytes", size);
924 SHMInfo.shmaddr = shmat (SHMInfo.shmid, NULL, 0);
925 if (SHMInfo.shmaddr == ((void *) -1)) {
926 GST_WARNING ("Failed to shmat: %s", g_strerror (errno));
927 /* Clean up the shared memory segment */
928 shmctl (SHMInfo.shmid, IPC_RMID, NULL);
932 xvimage->data = SHMInfo.shmaddr;
933 SHMInfo.readOnly = FALSE;
935 if (XShmAttach (xcontext->disp, &SHMInfo) == 0) {
936 GST_WARNING ("Failed to XShmAttach");
937 /* Clean up the shared memory segment */
938 shmctl (SHMInfo.shmid, IPC_RMID, NULL);
942 /* Sync to ensure we see any errors we caused */
943 XSync (xcontext->disp, FALSE);
945 /* Delete the shared memory segment as soon as everyone is attached.
946 * This way, it will be deleted as soon as we detach later, and not
947 * leaked if we crash. */
948 shmctl (SHMInfo.shmid, IPC_RMID, NULL);
951 GST_DEBUG ("XServer ShmAttached to 0x%x, id 0x%lx", SHMInfo.shmid,
955 /* store whether we succeeded in result */
958 GST_WARNING ("MIT-SHM extension check failed at XShmAttach. "
959 "Not using shared memory.");
963 /* Sync to ensure we swallow any errors we caused and reset error_caught */
964 XSync (xcontext->disp, FALSE);
966 error_caught = FALSE;
967 XSetErrorHandler (handler);
970 GST_DEBUG ("XServer ShmDetaching from 0x%x id 0x%lx",
971 SHMInfo.shmid, SHMInfo.shmseg);
972 XShmDetach (xcontext->disp, &SHMInfo);
973 XSync (xcontext->disp, FALSE);
975 if (SHMInfo.shmaddr != ((void *) -1))
976 shmdt (SHMInfo.shmaddr);
981 #endif /* HAVE_XSHM */
983 /* This function destroys a GstEvasPixmap handling XShm availability */
985 gst_evaspixmap_buffer_destroy (GstEvasPixmapBuffer *evaspixmapbuf)
987 GstEvasPixmapSink *evaspixmapsink;
989 evaspixmapsink = evaspixmapbuf->evaspixmapsink;
990 if (G_UNLIKELY (evaspixmapsink == NULL)) {
993 GST_DEBUG_OBJECT (evaspixmapsink, "Destroying buffer");
995 g_return_if_fail (GST_IS_EVASPIXMAPSINK (evaspixmapsink));
997 GST_OBJECT_LOCK (evaspixmapsink);
999 /* We might have some buffers destroyed after changing state to NULL */
1000 if (evaspixmapsink->xcontext == NULL) {
1001 GST_DEBUG_OBJECT (evaspixmapsink,"Destroying XvImage after Xcontext");
1003 /* Need to free the shared memory segment even if the x context
1004 * was already cleaned up */
1005 if (evaspixmapbuf->SHMInfo.shmaddr != ((void *) -1)) {
1006 shmdt (evaspixmapbuf->SHMInfo.shmaddr);
1011 g_mutex_lock (evaspixmapsink->x_lock);
1014 if (evaspixmapsink->xcontext->use_xshm) {
1015 if (evaspixmapbuf->SHMInfo.shmaddr != ((void *) -1)) {
1016 GST_DEBUG_OBJECT (evaspixmapsink,"XServer ShmDetaching from 0x%x id 0x%lx", evaspixmapbuf->SHMInfo.shmid, evaspixmapbuf->SHMInfo.shmseg);
1017 XShmDetach (evaspixmapsink->xcontext->disp, &evaspixmapbuf->SHMInfo);
1018 XSync (evaspixmapsink->xcontext->disp, FALSE);
1019 shmdt (evaspixmapbuf->SHMInfo.shmaddr);
1021 if (evaspixmapbuf->xvimage)
1022 XFree (evaspixmapbuf->xvimage);
1024 #endif /* HAVE_XSHM */
1026 if (evaspixmapbuf->xvimage) {
1027 if (evaspixmapbuf->xvimage->data) {
1028 g_free (evaspixmapbuf->xvimage->data);
1030 XFree (evaspixmapbuf->xvimage);
1034 XSync (evaspixmapsink->xcontext->disp, FALSE);
1036 g_mutex_unlock (evaspixmapsink->x_lock);
1039 GST_OBJECT_UNLOCK (evaspixmapsink);
1040 evaspixmapbuf->evaspixmapsink = NULL;
1041 gst_object_unref (evaspixmapsink);
1043 GST_MINI_OBJECT_CLASS (evaspixmap_buffer_parent_class)->finalize (GST_MINI_OBJECT(evaspixmapbuf));
1049 GST_WARNING ("no sink found");
1055 gst_evaspixmap_buffer_finalize (GstEvasPixmapBuffer *evaspixmapbuf)
1057 GstEvasPixmapSink *evaspixmapsink;
1059 evaspixmapsink = evaspixmapbuf->evaspixmapsink;
1060 if (G_UNLIKELY (evaspixmapsink == NULL)) {
1061 GST_WARNING_OBJECT (evaspixmapsink,"no sink found");
1064 g_return_if_fail (GST_IS_EVASPIXMAPSINK (evaspixmapsink));
1066 /* If our geometry changed we can't reuse that image. */
1067 GST_LOG_OBJECT (evaspixmapsink,"destroy image as sink is shutting down");
1068 gst_evaspixmap_buffer_destroy (evaspixmapbuf);
1072 gst_evaspixmap_buffer_free (GstEvasPixmapBuffer *evaspixmapbuf)
1074 /* make sure it is not recycled */
1075 evaspixmapbuf->width = -1;
1076 evaspixmapbuf->height = -1;
1077 gst_buffer_unref (GST_BUFFER (evaspixmapbuf));
1081 gst_evaspixmap_buffer_init (GstEvasPixmapBuffer *evaspixmapbuf, gpointer g_class)
1084 evaspixmapbuf->SHMInfo.shmaddr = ((void *) -1);
1085 evaspixmapbuf->SHMInfo.shmid = -1;
1090 gst_evaspixmap_buffer_class_init (gpointer g_class, gpointer class_data)
1092 GstMiniObjectClass *mini_object_class = GST_MINI_OBJECT_CLASS (g_class);
1094 evaspixmap_buffer_parent_class = g_type_class_peek_parent (g_class);
1096 mini_object_class->finalize = (GstMiniObjectFinalizeFunction) gst_evaspixmap_buffer_finalize;
1100 gst_evaspixmap_buffer_get_type (void)
1102 static GType _gst_evaspixmap_buffer_type;
1104 if (G_UNLIKELY (_gst_evaspixmap_buffer_type == 0)) {
1105 static const GTypeInfo evaspixmap_buffer_info = {
1106 sizeof (GstBufferClass),
1109 gst_evaspixmap_buffer_class_init,
1112 sizeof (GstEvasPixmapBuffer),
1114 (GInstanceInitFunc) gst_evaspixmap_buffer_init,
1117 _gst_evaspixmap_buffer_type = g_type_register_static (GST_TYPE_BUFFER,
1118 "GstEvasPixmapBuffer", &evaspixmap_buffer_info, 0);
1120 return _gst_evaspixmap_buffer_type;
1123 /* This function handles GstEvasPixmapBuffer creation depending on XShm availability */
1124 static GstEvasPixmapBuffer*
1125 gst_evaspixmap_buffer_new (GstEvasPixmapSink *evaspixmapsink, GstCaps *caps)
1127 GstEvasPixmapBuffer *evaspixmapbuf = NULL;
1128 GstStructure *structure = NULL;
1129 gboolean succeeded = FALSE;
1130 int (*handler) (Display *, XErrorEvent *);
1132 g_return_val_if_fail (GST_IS_EVASPIXMAPSINK (evaspixmapsink), NULL);
1138 evaspixmapbuf = (GstEvasPixmapBuffer*) gst_mini_object_new (GST_TYPE_EVASPIXMAP_BUFFER);
1139 GST_DEBUG_OBJECT (evaspixmapsink,"Creating new EvasPixmapBuffer");
1141 structure = gst_caps_get_structure (caps, 0);
1143 if (!gst_structure_get_int (structure, "width", &evaspixmapbuf->width) || !gst_structure_get_int (structure, "height", &evaspixmapbuf->height)) {
1144 GST_WARNING_OBJECT (evaspixmapsink,"failed getting geometry from caps %" GST_PTR_FORMAT, caps);
1147 GST_LOG_OBJECT (evaspixmapsink,"creating %dx%d", evaspixmapbuf->width, evaspixmapbuf->height);
1149 GST_LOG_OBJECT (evaspixmapsink,"aligned size %dx%d", evaspixmapsink->aligned_width, evaspixmapsink->aligned_height);
1150 if (evaspixmapsink->aligned_width == 0 || evaspixmapsink->aligned_height == 0) {
1151 GST_INFO_OBJECT (evaspixmapsink,"aligned size is zero. set size of caps.");
1152 evaspixmapsink->aligned_width = evaspixmapbuf->width;
1153 evaspixmapsink->aligned_height = evaspixmapbuf->height;
1156 evaspixmapbuf->im_format = gst_evaspixmapsink_get_format_from_caps (evaspixmapsink, caps);
1157 if (evaspixmapbuf->im_format == -1) {
1158 GST_WARNING_OBJECT (evaspixmapsink,"failed to get format from caps %"GST_PTR_FORMAT, caps);
1159 GST_ELEMENT_ERROR (evaspixmapsink, RESOURCE, WRITE,("Failed to create output image buffer of %dx%d pixels",
1160 evaspixmapbuf->width, evaspixmapbuf->height), ("Invalid input caps"));
1161 goto beach_unlocked;
1164 GST_INFO_OBJECT (evaspixmapsink, "FOURCC format : %c%c%c%c", evaspixmapbuf->im_format, evaspixmapbuf->im_format>>8,
1165 evaspixmapbuf->im_format>>16, evaspixmapbuf->im_format>>24);
1167 evaspixmapbuf->evaspixmapsink = gst_object_ref (evaspixmapsink);
1169 g_mutex_lock (evaspixmapsink->x_lock);
1171 /* Sync to ensure we swallow any errors we caused and reset error_caught */
1172 XSync (evaspixmapsink->xcontext->disp, FALSE);
1174 /* Setting an error handler to catch failure */
1175 error_caught = FALSE;
1176 handler = XSetErrorHandler (gst_evaspixmapsink_handle_xerror);
1179 if (evaspixmapsink->xcontext->use_xshm) {
1181 evaspixmapbuf->xvimage = XvShmCreateImage (evaspixmapsink->xcontext->disp, evaspixmapsink->xcontext->xv_port_id, evaspixmapbuf->im_format, NULL,
1182 evaspixmapsink->aligned_width, evaspixmapsink->aligned_height, &evaspixmapbuf->SHMInfo);
1183 if (!evaspixmapbuf->xvimage || error_caught) {
1185 GST_ERROR_OBJECT (evaspixmapsink,"error_caught!");
1187 if(!evaspixmapbuf->xvimage) {
1188 GST_ERROR_OBJECT (evaspixmapsink,"XvShmCreateImage() failed");
1190 g_mutex_unlock (evaspixmapsink->x_lock);
1191 /* Reset error handler */
1192 error_caught = FALSE;
1193 XSetErrorHandler (handler);
1195 GST_ELEMENT_ERROR (evaspixmapsink, RESOURCE, WRITE,("Failed to create output image buffer of %dx%d pixels",evaspixmapbuf->width,
1196 evaspixmapbuf->height),("could not XvShmCreateImage a %dx%d image",evaspixmapbuf->width, evaspixmapbuf->height));
1197 goto beach_unlocked;
1200 /* we have to use the returned data_size for our shm size */
1201 evaspixmapbuf->size = evaspixmapbuf->xvimage->data_size;
1202 GST_LOG_OBJECT (evaspixmapsink,"XShm image size is %" G_GSIZE_FORMAT, evaspixmapbuf->size);
1204 /* calculate the expected size. This is only for sanity checking the
1205 * number we get from X. */
1206 switch (evaspixmapbuf->im_format) {
1207 case GST_MAKE_FOURCC ('I', '4', '2', '0'):
1208 case GST_MAKE_FOURCC ('Y', 'V', '1', '2'):
1215 pitches[0] = GST_ROUND_UP_4 (evaspixmapbuf->width);
1216 offsets[1] = offsets[0] + pitches[0] * GST_ROUND_UP_2 (evaspixmapbuf->height);
1217 pitches[1] = GST_ROUND_UP_8 (evaspixmapbuf->width) / 2;
1219 offsets[1] + pitches[1] * GST_ROUND_UP_2 (evaspixmapbuf->height) / 2;
1220 pitches[2] = GST_ROUND_UP_8 (pitches[0]) / 2;
1222 expected_size = offsets[2] + pitches[2] * GST_ROUND_UP_2 (evaspixmapbuf->height) / 2;
1224 for (plane = 0; plane < evaspixmapbuf->xvimage->num_planes; plane++) {
1225 GST_DEBUG_OBJECT (evaspixmapsink,"Plane %u has a expected pitch of %d bytes, " "offset of %d",
1226 plane, pitches[plane], offsets[plane]);
1230 case GST_MAKE_FOURCC ('Y', 'U', 'Y', '2'):
1231 case GST_MAKE_FOURCC ('U', 'Y', 'V', 'Y'):
1232 expected_size = evaspixmapbuf->height * GST_ROUND_UP_4 (evaspixmapbuf->width * 2);
1234 case GST_MAKE_FOURCC ('S', 'T', '1', '2'):
1235 case GST_MAKE_FOURCC ('S', 'N', '1', '2'):
1236 case GST_MAKE_FOURCC ('S', 'U', 'Y', 'V'):
1237 case GST_MAKE_FOURCC ('S', 'U', 'Y', '2'):
1238 case GST_MAKE_FOURCC ('S', '4', '2', '0'):
1239 case GST_MAKE_FOURCC ('S', 'Y', 'V', 'Y'):
1240 case GST_MAKE_FOURCC ('I', 'T', 'L', 'V'):
1241 case GST_MAKE_FOURCC ('S', 'R', '3', '2'):
1242 expected_size = sizeof(SCMN_IMGB);
1248 if (expected_size != 0 && evaspixmapbuf->size != expected_size) {
1249 GST_WARNING_OBJECT (evaspixmapsink,"unexpected XShm image size (got %" G_GSIZE_FORMAT ", expected %d)", evaspixmapbuf->size, expected_size);
1252 /* Be verbose about our XvImage stride */
1255 for (plane = 0; plane < evaspixmapbuf->xvimage->num_planes; plane++) {
1256 GST_DEBUG_OBJECT (evaspixmapsink,"Plane %u has a pitch of %d bytes, ""offset of %d", plane,
1257 evaspixmapbuf->xvimage->pitches[plane], evaspixmapbuf->xvimage->offsets[plane]);
1261 evaspixmapbuf->SHMInfo.shmid = shmget (IPC_PRIVATE, evaspixmapbuf->size,IPC_CREAT | 0777);
1262 if (evaspixmapbuf->SHMInfo.shmid == -1) {
1263 g_mutex_unlock (evaspixmapsink->x_lock);
1264 GST_ELEMENT_ERROR (evaspixmapsink, RESOURCE, WRITE,
1265 ("Failed to create output image buffer of %dx%d pixels", evaspixmapbuf->width, evaspixmapbuf->height),
1266 ("could not get shared memory of %" G_GSIZE_FORMAT " bytes",evaspixmapbuf->size));
1267 goto beach_unlocked;
1270 evaspixmapbuf->SHMInfo.shmaddr = shmat (evaspixmapbuf->SHMInfo.shmid, NULL, 0);
1271 if (evaspixmapbuf->SHMInfo.shmaddr == ((void *) -1)) {
1272 g_mutex_unlock (evaspixmapsink->x_lock);
1273 GST_ELEMENT_ERROR (evaspixmapsink, RESOURCE, WRITE,
1274 ("Failed to create output image buffer of %dx%d pixels",
1275 evaspixmapbuf->width, evaspixmapbuf->height),
1276 ("Failed to shmat: %s", g_strerror (errno)));
1277 /* Clean up the shared memory segment */
1278 shmctl (evaspixmapbuf->SHMInfo.shmid, IPC_RMID, NULL);
1279 goto beach_unlocked;
1282 evaspixmapbuf->xvimage->data = evaspixmapbuf->SHMInfo.shmaddr;
1283 evaspixmapbuf->SHMInfo.readOnly = FALSE;
1285 if (XShmAttach (evaspixmapsink->xcontext->disp, &evaspixmapbuf->SHMInfo) == 0) {
1286 /* Clean up the shared memory segment */
1287 shmctl (evaspixmapbuf->SHMInfo.shmid, IPC_RMID, NULL);
1289 g_mutex_unlock (evaspixmapsink->x_lock);
1290 GST_ELEMENT_ERROR (evaspixmapsink, RESOURCE, WRITE,
1291 ("Failed to create output image buffer of %dx%d pixels",
1292 evaspixmapbuf->width, evaspixmapbuf->height), ("Failed to XShmAttach"));
1293 goto beach_unlocked;
1296 XSync (evaspixmapsink->xcontext->disp, FALSE);
1298 /* Delete the shared memory segment as soon as we everyone is attached.
1299 * This way, it will be deleted as soon as we detach later, and not
1300 * leaked if we crash. */
1301 shmctl (evaspixmapbuf->SHMInfo.shmid, IPC_RMID, NULL);
1303 GST_DEBUG_OBJECT (evaspixmapsink,"XServer ShmAttached to 0x%x, id 0x%lx", evaspixmapbuf->SHMInfo.shmid, evaspixmapbuf->SHMInfo.shmseg);
1305 #endif /* HAVE_XSHM */
1307 evaspixmapbuf->xvimage = XvCreateImage (evaspixmapsink->xcontext->disp, evaspixmapsink->xcontext->xv_port_id,
1308 evaspixmapbuf->im_format, NULL, evaspixmapsink->aligned_width, evaspixmapsink->aligned_height);
1309 if (!evaspixmapbuf->xvimage || error_caught) {
1310 g_mutex_unlock (evaspixmapsink->x_lock);
1311 /* Reset error handler */
1312 error_caught = FALSE;
1313 XSetErrorHandler (handler);
1315 GST_ELEMENT_ERROR (evaspixmapsink, RESOURCE, WRITE,
1316 ("Failed to create outputimage buffer of %dx%d pixels",
1317 evaspixmapbuf->width, evaspixmapbuf->height),
1318 ("could not XvCreateImage a %dx%d image",
1319 evaspixmapbuf->width, evaspixmapbuf->height));
1320 goto beach_unlocked;
1323 /* we have to use the returned data_size for our image size */
1324 evaspixmapbuf->size = evaspixmapbuf->xvimage->data_size;
1325 evaspixmapbuf->xvimage->data = g_malloc (evaspixmapbuf->size);
1327 XSync (evaspixmapsink->xcontext->disp, FALSE);
1330 /* Reset error handler */
1331 error_caught = FALSE;
1332 XSetErrorHandler (handler);
1336 GST_BUFFER_DATA (evaspixmapbuf) = (guchar *) evaspixmapbuf->xvimage->data;
1337 GST_BUFFER_SIZE (evaspixmapbuf) = evaspixmapbuf->size;
1339 g_mutex_unlock (evaspixmapsink->x_lock);
1343 gst_evaspixmap_buffer_free (evaspixmapbuf);
1344 evaspixmapbuf = NULL;
1347 return evaspixmapbuf;
1350 /* This function puts a GstEvasPixmapBuffer on a GstEvasPixmapSink's pixmap. Returns FALSE
1351 * if no pixmap was available */
1353 gst_evaspixmap_buffer_put (GstEvasPixmapSink *evaspixmapsink, GstEvasPixmapBuffer *evaspixmapbuf)
1355 GstVideoRectangle result;
1357 GstVideoRectangle src_origin = { 0, 0, 0, 0};
1358 GstVideoRectangle src_input = { 0, 0, 0, 0};
1359 GstVideoRectangle src = { 0, 0, 0, 0};
1360 GstVideoRectangle dst = { 0, 0, 0, 0};
1364 GstXPixmap *xpixmap = NULL;
1367 /* We take the flow_lock. If expose is in there we don't want to run
1368 concurrently from the data flow thread */
1369 g_mutex_lock (evaspixmapsink->flow_lock);
1371 if (G_UNLIKELY (evaspixmapsink->xpixmap[idx] == NULL)) {
1372 GST_WARNING_OBJECT (evaspixmapsink, "xpixmap is NULL. Skip buffer_put." );
1373 g_mutex_unlock(evaspixmapsink->flow_lock);
1376 if (evaspixmapsink->visible == FALSE) {
1377 GST_WARNING_OBJECT (evaspixmapsink, "visible is FALSE. Skip buffer_put." );
1378 g_mutex_unlock(evaspixmapsink->flow_lock);
1381 if (!evaspixmapbuf) {
1382 GST_WARNING_OBJECT (evaspixmapsink, "evaspixmapbuf is NULL. Skip buffer_put." );
1383 g_mutex_unlock(evaspixmapsink->flow_lock);
1387 g_mutex_lock (evaspixmapsink->pixmap_ref_lock);
1388 if (evaspixmapsink->last_updated_idx == -1) {
1389 /* if it has never been updated any frame in Ecore thread, do below */
1391 xpixmap = evaspixmapsink->xpixmap[idx];
1393 GST_LOG_OBJECT (evaspixmapsink, "last_updated_idx(%d), we use index[%d] of pixmap buffers : pixmap(%d), ref(%d)",
1394 evaspixmapsink->last_updated_idx, idx, xpixmap->pixmap, xpixmap->ref);
1396 for (idx = 0; idx < evaspixmapsink->num_of_pixmaps; idx++) {
1397 if (idx == evaspixmapsink->last_updated_idx) {
1400 xpixmap = evaspixmapsink->xpixmap[idx];
1401 if (xpixmap->ref == 0 && xpixmap->damaged_time == 0) {
1403 GST_LOG_OBJECT (evaspixmapsink, "found an available pixmap(%d) : xpixmap[%d]", xpixmap->pixmap, idx);
1404 GST_INFO_OBJECT (evaspixmapsink,"pixmap ref-count INCREASED : pixmap(%d), refcount(%d)", xpixmap->pixmap, xpixmap->ref);
1409 if (idx == evaspixmapsink->num_of_pixmaps) {
1410 GST_LOG_OBJECT (evaspixmapsink, "Could not find a pixmap with idle state, skip buffer_put." );
1411 g_mutex_unlock (evaspixmapsink->pixmap_ref_lock);
1412 g_mutex_unlock(evaspixmapsink->flow_lock);
1416 g_mutex_unlock (evaspixmapsink->pixmap_ref_lock);
1418 gst_evaspixmapsink_xpixmap_update_geometry(evaspixmapsink, idx);
1421 src_origin.x = src_origin.y = src_input.x = src_input.y = 0;
1422 src_input.w = src_origin.w = evaspixmapsink->video_width;
1423 src_input.h = src_origin.h = evaspixmapsink->video_height;
1424 if (evaspixmapsink->use_origin_size ||
1425 (evaspixmapsink->rotate_angle == DEGREE_0 ||
1426 evaspixmapsink->rotate_angle == DEGREE_180)) {
1427 src.w = src_origin.w;
1428 src.h = src_origin.h;
1430 src.w = src_origin.h;
1431 src.h = src_origin.w;
1434 dst.w = evaspixmapsink->render_rect.w; /* pixmap width */
1435 dst.h = evaspixmapsink->render_rect.h; /* pixmap height */
1437 if (!evaspixmapsink->use_origin_size) {
1438 static Atom atom_rotation = None;
1439 static Atom atom_hflip = None;
1440 static Atom atom_vflip = None;
1441 gboolean set_hflip = FALSE;
1442 gboolean set_vflip = FALSE;
1444 /* compensation of size information (between evas image object's and pixmap's) */
1445 if (evaspixmapsink->sizediff_width > 1) {
1446 if (evaspixmapsink->sizediff_height > 1) {
1447 dst.w -= (evaspixmapsink->sizediff_width >> 1) << 1;
1448 dst.h -= (evaspixmapsink->sizediff_height >> 1) << 1;
1450 dst.w -= (evaspixmapsink->sizediff_width >> 1) << 1;
1452 } else if (evaspixmapsink->sizediff_height > 1) {
1453 dst.h -= (evaspixmapsink->sizediff_height >> 1) << 1;
1456 switch (evaspixmapsink->display_geometry_method) {
1457 case DISP_GEO_METHOD_LETTER_BOX:
1458 gst_video_sink_center_rect (src, dst, &result, TRUE);
1459 result.x += evaspixmapsink->render_rect.x;
1460 result.y += evaspixmapsink->render_rect.y;
1461 GST_DEBUG_OBJECT (evaspixmapsink, "GEO_METHOD : letter box");
1463 case DISP_GEO_METHOD_ORIGIN_SIZE:
1464 gst_video_sink_center_rect (src, dst, &result, FALSE);
1465 gst_video_sink_center_rect (dst, src, &src_input, FALSE);
1466 GST_DEBUG_OBJECT (evaspixmapsink, "GEO_METHOD : origin size");
1467 if (evaspixmapsink->rotate_angle == DEGREE_90 ||
1468 evaspixmapsink->rotate_angle == DEGREE_270) {
1469 src_input.x = src_input.x ^ src_input.y;
1470 src_input.y = src_input.x ^ src_input.y;
1471 src_input.x = src_input.x ^ src_input.y;
1472 src_input.w = src_input.w ^ src_input.h;
1473 src_input.h = src_input.w ^ src_input.h;
1474 src_input.w = src_input.w ^ src_input.h;
1477 case DISP_GEO_METHOD_FULL_SCREEN:
1478 result.x = result.y = 0;
1479 result.w = evaspixmapsink->xpixmap[idx]->width;
1480 result.h = evaspixmapsink->xpixmap[idx]->height;
1481 GST_DEBUG_OBJECT (evaspixmapsink, "GEO_METHOD : full screen");
1483 case DISP_GEO_METHOD_CROPPED_FULL_SCREEN:
1484 GST_DEBUG_OBJECT (evaspixmapsink, "GEO_METHOD : cropped full screen");
1485 gst_video_sink_center_rect(dst, src, &src_input, TRUE);
1486 result.x = result.y = 0;
1489 if (evaspixmapsink->rotate_angle == DEGREE_90 ||
1490 evaspixmapsink->rotate_angle == DEGREE_270) {
1491 src_input.x = src_input.x ^ src_input.y;
1492 src_input.y = src_input.x ^ src_input.y;
1493 src_input.x = src_input.x ^ src_input.y;
1494 src_input.w = src_input.w ^ src_input.h;
1495 src_input.h = src_input.w ^ src_input.h;
1496 src_input.w = src_input.w ^ src_input.h;
1499 case DISP_GEO_METHOD_CUSTOM_ROI:
1500 switch (evaspixmapsink->rotate_angle) {
1502 result.w = evaspixmapsink->dst_roi.h;
1503 result.h = evaspixmapsink->dst_roi.w;
1504 result.x = evaspixmapsink->dst_roi.y;
1505 result.y = evaspixmapsink->xpixmap[idx]->height - evaspixmapsink->dst_roi.x - evaspixmapsink->dst_roi.w;
1508 result.w = evaspixmapsink->dst_roi.w;
1509 result.h = evaspixmapsink->dst_roi.h;
1510 result.x = evaspixmapsink->xpixmap[idx]->width - result.w - evaspixmapsink->dst_roi.x;
1511 result.y = evaspixmapsink->xpixmap[idx]->height - result.h - evaspixmapsink->dst_roi.y;
1514 result.w = evaspixmapsink->dst_roi.h;
1515 result.h = evaspixmapsink->dst_roi.w;
1516 result.x = evaspixmapsink->xpixmap[idx]->width - evaspixmapsink->dst_roi.y - evaspixmapsink->dst_roi.h;
1517 result.y = evaspixmapsink->dst_roi.x;
1520 result.x = evaspixmapsink->dst_roi.x;
1521 result.y = evaspixmapsink->dst_roi.y;
1522 result.w = evaspixmapsink->dst_roi.w;
1523 result.h = evaspixmapsink->dst_roi.h;
1526 GST_LOG_OBJECT(evaspixmapsink, "rotate[%d], ROI input[%d,%d,%dx%d] > result[%d,%d,%dx%d]",
1527 evaspixmapsink->rotate_angle,
1528 evaspixmapsink->dst_roi.x, evaspixmapsink->dst_roi.y, evaspixmapsink->dst_roi.w, evaspixmapsink->dst_roi.h,
1529 result.x, result.y, result.w, result.h);
1534 GST_DEBUG_OBJECT (evaspixmapsink, "GEO_METHOD : src(%dx%d), dst(%dx%d), result(%dx%d), result_x(%d), result_y(%d)",
1535 src.w,src.h,dst.w,dst.h,result.w,result.h,result.x,result.y);
1537 switch( evaspixmapsink->rotate_angle ) {
1550 GST_WARNING_OBJECT( evaspixmapsink, "Unsupported rotation [%d]... set DEGREE 0.",
1551 evaspixmapsink->rotate_angle );
1555 g_mutex_lock (evaspixmapsink->x_lock);
1557 /* set display rotation */
1558 if (atom_rotation == None) {
1559 atom_rotation = XInternAtom(evaspixmapsink->xcontext->disp, "_USER_WM_PORT_ATTRIBUTE_ROTATION", False);
1561 ret = XvSetPortAttribute(evaspixmapsink->xcontext->disp, evaspixmapsink->xcontext->xv_port_id, atom_rotation, rotate);
1562 if (ret != Success) {
1563 GST_ERROR_OBJECT( evaspixmapsink, "XvSetPortAttribute failed[%d]. disp[%x],xv_port_id[%d],atom[%x],rotate[%d]",
1564 ret, evaspixmapsink->xcontext->disp, evaspixmapsink->xcontext->xv_port_id, atom_rotation, rotate );
1567 /* set display flip */
1568 if (atom_hflip == None) {
1569 atom_hflip = XInternAtom(evaspixmapsink->xcontext->disp, "_USER_WM_PORT_ATTRIBUTE_HFLIP", False);
1571 if (atom_vflip == None) {
1572 atom_vflip = XInternAtom(evaspixmapsink->xcontext->disp, "_USER_WM_PORT_ATTRIBUTE_VFLIP", False);
1575 switch (evaspixmapsink->flip) {
1576 case FLIP_HORIZONTAL:
1594 GST_INFO_OBJECT(evaspixmapsink, "set rotate %d HFLIP %d, VFLIP %d", rotate, set_hflip, set_vflip);
1596 ret = XvSetPortAttribute(evaspixmapsink->xcontext->disp, evaspixmapsink->xcontext->xv_port_id, atom_hflip, set_hflip);
1597 if (ret != Success) {
1598 GST_WARNING("set HFLIP failed[%d]. disp[%x],xv_port_id[%d],atom[%x],hflip[%d]",
1599 ret, evaspixmapsink->xcontext->disp, evaspixmapsink->xcontext->xv_port_id, atom_hflip, set_hflip);
1601 ret = XvSetPortAttribute(evaspixmapsink->xcontext->disp, evaspixmapsink->xcontext->xv_port_id, atom_vflip, set_vflip);
1602 if (ret != Success) {
1603 GST_WARNING("set VFLIP failed[%d]. disp[%x],xv_port_id[%d],atom[%x],vflip[%d]",
1604 ret, evaspixmapsink->xcontext->disp, evaspixmapsink->xcontext->xv_port_id, atom_vflip, set_vflip);
1607 g_mutex_unlock (evaspixmapsink->x_lock);
1610 result.x = result.y = 0;
1611 result.w = evaspixmapsink->xpixmap[idx]->width;
1612 result.h = evaspixmapsink->xpixmap[idx]->height;
1613 GST_INFO_OBJECT (evaspixmapsink, "USE ORIGIN SIZE, no geometry method, no rotation/flip" );
1616 if((evaspixmapsink->result_prev.w != 0 && evaspixmapsink->result_prev.h != 0)
1617 && (evaspixmapsink->src_prev.w==src_origin.w && evaspixmapsink->src_prev.h==src_origin.h)
1618 && (evaspixmapsink->result_prev.w!=result.w || evaspixmapsink->result_prev.h!=result.h))
1620 GST_WARNING("It will execute XFillRectangle..... evaspixmapsink->result_prev.w : %d, evaspixmapsink->result_prev.h: %d, result.w : %d, result.h : %d",
1621 evaspixmapsink->result_prev.w, evaspixmapsink->result_prev.h, result.w, result.h);
1622 for (i = 0; i < evaspixmapsink->num_of_pixmaps; i++) {
1623 XFillRectangle (evaspixmapsink->xcontext->disp, evaspixmapsink->xpixmap[i]->pixmap, evaspixmapsink->xpixmap[i]->gc,
1624 0, 0, evaspixmapsink->xpixmap[i]->width, evaspixmapsink->xpixmap[i]->height);
1625 GST_LOG_OBJECT (evaspixmapsink,"fill black to xpixmap[%d] with size(w:%d,h:%d)", evaspixmapsink->xpixmap[i]->pixmap,
1626 evaspixmapsink->xpixmap[i]->width, evaspixmapsink->xpixmap[i]->height);
1629 g_mutex_lock (evaspixmapsink->x_lock);
1631 /* We scale to the pixmap's geometry */
1633 if (evaspixmapsink->xcontext->use_xshm) {
1634 GST_LOG_OBJECT (evaspixmapsink,"XvShmPutImage with image %dx%d and pixmap %dx%d, from xvimage %"
1636 evaspixmapbuf->width, evaspixmapbuf->height,
1637 evaspixmapsink->render_rect.w, evaspixmapsink->render_rect.h, evaspixmapbuf);
1639 /* Trim as proper size */
1640 if (src_input.w % 2 == 1) {
1643 if (src_input.h % 2 == 1) {
1647 GST_LOG_OBJECT (evaspixmapsink, "screen[%dx%d],pixmap[%d,%d,%dx%d],method[%d],rotate[%d],src[%dx%d],dst[%d,%d,%dx%d],input[%d,%d,%dx%d],result[%d,%d,%dx%d]",
1648 evaspixmapsink->scr_w, evaspixmapsink->scr_h,
1649 evaspixmapsink->xpixmap[idx]->x, evaspixmapsink->xpixmap[idx]->y, evaspixmapsink->xpixmap[idx]->width, evaspixmapsink->xpixmap[idx]->height,
1650 evaspixmapsink->display_geometry_method, rotate,
1651 src_origin.w, src_origin.h,
1652 dst.x, dst.y, dst.w, dst.h,
1653 src_input.x, src_input.y, src_input.w, src_input.h,
1654 result.x, result.y, result.w, result.h );
1656 if (evaspixmapsink->visible) {
1657 if (evaspixmapsink->buf_shared_type == BUF_SHARE_METHOD_FD) {
1658 EVASPIXMAPSINK_SET_PIXMAP_ID_TO_GEM_INFO (evaspixmapsink, evaspixmapsink->xpixmap[idx]->pixmap);
1660 ret = XvShmPutImage (evaspixmapsink->xcontext->disp,
1661 evaspixmapsink->xcontext->xv_port_id,
1662 evaspixmapsink->xpixmap[idx]->pixmap,
1663 evaspixmapsink->xpixmap[idx]->gc, evaspixmapbuf->xvimage,
1664 src_input.x, src_input.y, src_input.w, src_input.h,
1665 result.x, result.y, result.w, result.h, FALSE);
1666 GST_LOG_OBJECT (evaspixmapsink, "XvShmPutImage return value [%d]", ret );
1668 GST_WARNING_OBJECT (evaspixmapsink, "visible is FALSE. skip this image..." );
1671 #endif /* HAVE_XSHM */
1673 if (evaspixmapsink->visible) {
1674 XvPutImage (evaspixmapsink->xcontext->disp,
1675 evaspixmapsink->xcontext->xv_port_id,
1676 evaspixmapsink->xpixmap[idx]->pixmap,
1677 evaspixmapsink->xpixmap[idx]->gc, evaspixmapbuf->xvimage,
1678 evaspixmapsink->disp_x, evaspixmapsink->disp_y,
1679 evaspixmapsink->disp_width, evaspixmapsink->disp_height,
1680 result.x, result.y, result.w, result.h);
1682 GST_WARNING_OBJECT (evaspixmapsink, "visible is FALSE. skip this image..." );
1686 evaspixmapsink->src_prev.w = src_origin.w;
1687 evaspixmapsink->src_prev.h = src_origin.h;
1689 evaspixmapsink->result_prev.w = result.w;
1690 evaspixmapsink->result_prev.h = result.h;
1692 XSync (evaspixmapsink->xcontext->disp, FALSE);
1694 g_mutex_unlock (evaspixmapsink->x_lock);
1695 g_mutex_unlock (evaspixmapsink->flow_lock);
1701 drm_init(GstEvasPixmapSink *evaspixmapsink)
1709 char *driverName = NULL;
1710 char *deviceName = NULL;
1711 struct drm_auth auth_arg = {0};
1713 evaspixmapsink->drm_fd = -1;
1715 dpy = XOpenDisplay(0);
1718 if (!DRI2QueryExtension(dpy, &eventBase, &errorBase)) {
1719 GST_ERROR_OBJECT (evaspixmapsink,"failed to DRI2QueryExtension()");
1723 if (!DRI2QueryVersion(dpy, &dri2Major, &dri2Minor)) {
1724 GST_ERROR_OBJECT (evaspixmapsink,"failed to DRI2QueryVersion");
1728 if (!DRI2Connect(dpy, RootWindow(dpy, DefaultScreen(dpy)), &driverName, &deviceName)) {
1729 GST_ERROR_OBJECT (evaspixmapsink,"failed to DRI2Connect");
1733 if (!driverName || !deviceName) {
1734 GST_ERROR_OBJECT (evaspixmapsink,"driverName or deviceName is not valid");
1738 GST_INFO_OBJECT (evaspixmapsink,"Open drm device : %s", deviceName);
1740 /* get the drm_fd though opening the deviceName */
1741 evaspixmapsink->drm_fd = open(deviceName, O_RDWR);
1742 if (evaspixmapsink->drm_fd < 0) {
1743 GST_ERROR_OBJECT (evaspixmapsink,"cannot open drm device (%s)", deviceName);
1747 /* get magic from drm to authentication */
1748 if (ioctl(evaspixmapsink->drm_fd, DRM_IOCTL_GET_MAGIC, &auth_arg)) {
1749 GST_ERROR_OBJECT (evaspixmapsink,"cannot get drm auth magic");
1750 close(evaspixmapsink->drm_fd);
1751 evaspixmapsink->drm_fd = -1;
1755 if (!DRI2Authenticate(dpy, RootWindow(dpy, DefaultScreen(dpy)), auth_arg.magic)) {
1756 GST_ERROR_OBJECT (evaspixmapsink,"cannot get drm authentication from X");
1757 close(evaspixmapsink->drm_fd);
1758 evaspixmapsink->drm_fd = -1;
1762 /* init gem handle */
1763 for (i = 0; i < MAX_GEM_BUFFER_NUM; i++) {
1764 evaspixmapsink->gem_info[i].dmabuf_fd = 0;
1765 evaspixmapsink->gem_info[i].gem_handle = 0;
1766 evaspixmapsink->gem_info[i].gem_name = 0;
1767 evaspixmapsink->gem_info[i].bo = 0;
1768 evaspixmapsink->gem_info[i].ref_pixmap = 0;
1790 drm_fini(GstEvasPixmapSink *evaspixmapsink)
1792 if (evaspixmapsink->drm_fd >= 0) {
1793 GST_INFO_OBJECT (evaspixmapsink,"close drm_fd(%d)", evaspixmapsink->drm_fd);
1794 close(evaspixmapsink->drm_fd);
1795 evaspixmapsink->drm_fd = -1;
1800 drm_init_convert_dmabuf_gemname(GstEvasPixmapSink *evaspixmapsink, int dmabuf_fd)
1802 struct drm_prime_handle prime_arg = {0,};
1803 struct drm_gem_flink flink_arg = {0,};
1806 if (evaspixmapsink->drm_fd < 0) {
1807 GST_ERROR_OBJECT (evaspixmapsink,"DRM is not opened");
1811 if (dmabuf_fd <= 0) {
1812 GST_DEBUG_OBJECT (evaspixmapsink,"Ignore wrong dmabuf fd(%d)", dmabuf_fd); /* temporarily change log level to DEBUG for reducing WARNING level log */
1816 /* check duplicated dmabuf fd */
1817 for (i = 0 ; i < MAX_GEM_BUFFER_NUM ; i++) {
1818 if (evaspixmapsink->gem_info[i].dmabuf_fd == dmabuf_fd) {
1819 GST_LOG_OBJECT (evaspixmapsink,"already got fd(%u) with name(%u)", dmabuf_fd, evaspixmapsink->gem_info[i].gem_name);
1820 return evaspixmapsink->gem_info[i].gem_name;
1823 if (evaspixmapsink->gem_info[i].dmabuf_fd == 0) {
1824 GST_LOG_OBJECT (evaspixmapsink,"empty gem_info[%d] found", i);
1829 if (i == MAX_GEM_BUFFER_NUM) {
1830 GST_WARNING_OBJECT (evaspixmapsink,"too many buffers[dmabuf_fd(%d). skip it]", dmabuf_fd);
1834 evaspixmapsink->gem_info[i].dmabuf_fd = dmabuf_fd;
1835 prime_arg.fd = dmabuf_fd;
1836 if (ioctl(evaspixmapsink->drm_fd, DRM_IOCTL_PRIME_FD_TO_HANDLE, &prime_arg)) {
1837 GST_ERROR_OBJECT (evaspixmapsink,"non dmabuf fd(%d)", dmabuf_fd);
1841 evaspixmapsink->gem_info[i].gem_handle = prime_arg.handle;
1842 GST_LOG_OBJECT (evaspixmapsink,"gem_info[%d].gem_handle = %u", i, prime_arg.handle);
1844 flink_arg.handle = prime_arg.handle;
1845 if (ioctl(evaspixmapsink->drm_fd, DRM_IOCTL_GEM_FLINK, &flink_arg)) {
1846 GST_ERROR_OBJECT (evaspixmapsink,"cannot convert drm handle to name");
1850 evaspixmapsink->gem_info[i].gem_name = flink_arg.name;
1851 GST_LOG_OBJECT (evaspixmapsink,"gem_info[%d].gem_name = %u", i, flink_arg.name);
1853 return flink_arg.name;
1857 tbm_init_convert_bo_gemname(GstEvasPixmapSink *evaspixmapsink, tbm_bo bo)
1862 GST_DEBUG_OBJECT (evaspixmapsink,"Ignore wrong bo(%u)", bo); /* temporarily change log level to DEBUG for reducing WARNING level log */
1866 /* check duplicated dmabuf bo */
1867 for (i = 0 ; i < MAX_GEM_BUFFER_NUM ; i++) {
1868 if (evaspixmapsink->gem_info[i].bo == bo) {
1869 GST_LOG_OBJECT (evaspixmapsink,"already got bo(%u) with name(%u)", bo, evaspixmapsink->gem_info[i].gem_name);
1870 return evaspixmapsink->gem_info[i].gem_name;
1873 if (evaspixmapsink->gem_info[i].bo == 0) {
1874 GST_LOG_OBJECT (evaspixmapsink,"empty gem_info[%d] found", i);
1879 if (i == MAX_GEM_BUFFER_NUM) {
1880 GST_WARNING_OBJECT (evaspixmapsink,"too many buffers[dmabuf_bo(%d). skip it]", bo);
1884 evaspixmapsink->gem_info[i].bo = bo;
1885 evaspixmapsink->gem_info[i].gem_name = tbm_bo_export(bo);
1886 GST_LOG_OBJECT (evaspixmapsink,"gem_info[%d].gem_name = %u", i, evaspixmapsink->gem_info[i].gem_name);
1888 return evaspixmapsink->gem_info[i].gem_name;
1892 drm_fini_close_gem_handle(GstEvasPixmapSink *evaspixmapsink, Pixmap pixmap_id)
1895 if (evaspixmapsink->drm_fd >= 0) {
1896 if (pixmap_id == 0) {
1897 for (i = 0; i < MAX_GEM_BUFFER_NUM; i++) {
1898 if (evaspixmapsink->gem_info[i].dmabuf_fd > 0 || evaspixmapsink->gem_info[i].bo > 0) {
1899 if (evaspixmapsink->buf_shared_type == BUF_SHARE_METHOD_FD) {
1900 GST_INFO_OBJECT (evaspixmapsink,"close gem_handle(%u)", evaspixmapsink->gem_info[i].gem_handle);
1901 drm_close_gem(evaspixmapsink, evaspixmapsink->gem_info[i].gem_handle);
1903 evaspixmapsink->gem_info[i].dmabuf_fd = 0;
1904 evaspixmapsink->gem_info[i].gem_handle = 0;
1905 evaspixmapsink->gem_info[i].gem_name = 0;
1906 evaspixmapsink->gem_info[i].bo = 0;
1907 evaspixmapsink->gem_info[i].ref_pixmap = 0;
1908 GST_LOG_OBJECT (evaspixmapsink,"gem_info[%d] is cleared",i);
1912 for (i = 0; i < MAX_GEM_BUFFER_NUM; i++) {
1913 if (evaspixmapsink->gem_info[i].ref_pixmap == pixmap_id) {
1914 if (evaspixmapsink->buf_shared_type == BUF_SHARE_METHOD_FD) {
1915 GST_INFO_OBJECT (evaspixmapsink,"close gem_handle(%u) for pixmap_id(%d)",
1916 evaspixmapsink->gem_info[i].gem_handle, pixmap_id);
1917 drm_close_gem(evaspixmapsink, evaspixmapsink->gem_info[i].gem_handle);
1919 evaspixmapsink->gem_info[i].dmabuf_fd = 0;
1920 evaspixmapsink->gem_info[i].gem_handle = 0;
1921 evaspixmapsink->gem_info[i].gem_name = 0;
1922 evaspixmapsink->gem_info[i].bo = 0;
1923 evaspixmapsink->gem_info[i].ref_pixmap = 0;
1924 GST_LOG_OBJECT (evaspixmapsink,"gem_info[%d] is cleared",i);
1933 drm_close_gem(GstEvasPixmapSink *evaspixmapsink, unsigned int gem_handle)
1935 struct drm_gem_close close_arg = {0,};
1937 if (evaspixmapsink->drm_fd < 0) {
1938 GST_ERROR_OBJECT (evaspixmapsink,"DRM is not opened");
1942 if (gem_handle == 0) {
1943 GST_ERROR_OBJECT (evaspixmapsink,"invalid gem_handle(%d)",gem_handle);
1947 close_arg.handle = gem_handle;
1948 if (gem_handle > 0 && ioctl(evaspixmapsink->drm_fd, DRM_IOCTL_GEM_CLOSE, &close_arg)) {
1949 GST_ERROR_OBJECT (evaspixmapsink,"cannot close drm gem handle(%d)", gem_handle);
1956 /* This function destroys a GstXPixmap */
1958 gst_evaspixmapsink_xpixmap_destroy (GstEvasPixmapSink *evaspixmapsink, GstXPixmap *xpixmap)
1960 g_return_if_fail (xpixmap != NULL);
1961 g_return_if_fail (GST_IS_EVASPIXMAPSINK (evaspixmapsink));
1963 g_mutex_lock (evaspixmapsink->x_lock);
1965 if(xpixmap->pixmap) {
1966 GST_LOG_OBJECT (evaspixmapsink,"Free pixmap(%d)", xpixmap->pixmap);
1967 XFreePixmap(evaspixmapsink->xcontext->disp, xpixmap->pixmap);
1968 xpixmap->pixmap = 0;
1972 XFreeGC (evaspixmapsink->xcontext->disp, xpixmap->gc);
1975 XSync (evaspixmapsink->xcontext->disp, FALSE);
1977 g_mutex_unlock (evaspixmapsink->x_lock);
1983 gst_evaspixmapsink_xpixmap_update_geometry (GstEvasPixmapSink *evaspixmapsink, int idx)
1986 XWindowAttributes root_attr;
1988 int cur_pixmap_x = 0;
1989 int cur_pixmap_y = 0;
1990 unsigned int cur_pixmap_width = 0;
1991 unsigned int cur_pixmap_height = 0;
1992 unsigned int cur_pixmap_border_width = 0;
1993 unsigned int cur_pixmap_depth = 0;
1995 g_return_if_fail (GST_IS_EVASPIXMAPSINK (evaspixmapsink));
1997 /* Update the window geometry */
1998 g_mutex_lock (evaspixmapsink->x_lock);
1999 if (G_UNLIKELY (evaspixmapsink->xpixmap[idx] == NULL)) {
2000 g_mutex_unlock (evaspixmapsink->x_lock);
2004 /* Get root window and size of current pixmap */
2005 XGetGeometry( evaspixmapsink->xcontext->disp, evaspixmapsink->xpixmap[idx]->pixmap, &root_window,
2006 &cur_pixmap_x, &cur_pixmap_y, /* relative x, y, for pixmap these are alway 0 */
2007 &cur_pixmap_width, &cur_pixmap_height,
2008 &cur_pixmap_border_width, &cur_pixmap_depth ); /* cur_pixmap_border_width, cur_pixmap_depth are not used */
2010 evaspixmapsink->xpixmap[idx]->width = cur_pixmap_width;
2011 evaspixmapsink->xpixmap[idx]->height = cur_pixmap_height;
2013 evaspixmapsink->xpixmap[idx]->x = cur_pixmap_x;
2014 evaspixmapsink->xpixmap[idx]->y = cur_pixmap_y;
2016 /* Get size of root window == size of screen */
2017 XGetWindowAttributes(evaspixmapsink->xcontext->disp, root_window, &root_attr);
2019 evaspixmapsink->scr_w = root_attr.width;
2020 evaspixmapsink->scr_h = root_attr.height;
2022 if (!evaspixmapsink->have_render_rect) {
2023 evaspixmapsink->render_rect.x = evaspixmapsink->render_rect.y = 0;
2024 evaspixmapsink->render_rect.w = cur_pixmap_width;
2025 evaspixmapsink->render_rect.h = cur_pixmap_height;
2028 GST_LOG_OBJECT (evaspixmapsink,"screen size %dx%d, current pixmap geometry %d,%d,%dx%d, render_rect %d,%d,%dx%d",
2029 evaspixmapsink->scr_w, evaspixmapsink->scr_h,
2030 evaspixmapsink->xpixmap[idx]->x, evaspixmapsink->xpixmap[idx]->y,
2031 evaspixmapsink->xpixmap[idx]->width, evaspixmapsink->xpixmap[idx]->height,
2032 evaspixmapsink->render_rect.x, evaspixmapsink->render_rect.y,
2033 evaspixmapsink->render_rect.w, evaspixmapsink->render_rect.h);
2035 g_mutex_unlock (evaspixmapsink->x_lock);
2039 gst_evaspixmapsink_xpixmap_clear (GstEvasPixmapSink *evaspixmapsink, GstXPixmap *xpixmap)
2041 g_return_if_fail (xpixmap != NULL);
2042 g_return_if_fail (GST_IS_EVASPIXMAPSINK (evaspixmapsink));
2044 if (!xpixmap->pixmap) {
2045 GST_WARNING_OBJECT (evaspixmapsink,"pixmap was not created..");
2049 g_mutex_lock (evaspixmapsink->x_lock);
2051 if (!evaspixmapsink->xcontext) {
2052 GST_WARNING_OBJECT (evaspixmapsink,"xcontext is null..");
2053 g_mutex_unlock (evaspixmapsink->x_lock);
2057 if (evaspixmapsink->stop_video) {
2058 XvStopVideo (evaspixmapsink->xcontext->disp, evaspixmapsink->xcontext->xv_port_id, xpixmap->pixmap);
2060 XSync (evaspixmapsink->xcontext->disp, FALSE);
2062 g_mutex_unlock (evaspixmapsink->x_lock);
2064 g_mutex_lock (evaspixmapsink->pixmap_ref_lock);
2065 evaspixmapsink->last_updated_idx = -1;
2067 xpixmap->damaged_time = 0;
2068 g_mutex_unlock (evaspixmapsink->pixmap_ref_lock);
2071 /* This function commits our internal colorbalance settings to our grabbed Xv
2072 port. If the xcontext is not initialized yet it simply returns */
2074 gst_evaspixmapsink_update_colorbalance (GstEvasPixmapSink *evaspixmapsink)
2076 GList *channels = NULL;
2078 g_return_if_fail (GST_IS_EVASPIXMAPSINK (evaspixmapsink));
2080 /* If we haven't initialized the X context we can't update anything */
2081 if (evaspixmapsink->xcontext == NULL)
2084 /* Don't set the attributes if they haven't been changed, to avoid
2085 * rounding errors changing the values */
2086 if (!evaspixmapsink->cb_changed)
2089 /* For each channel of the colorbalance we calculate the correct value
2090 doing range conversion and then set the Xv port attribute to match our
2092 channels = evaspixmapsink->xcontext->channels_list;
2095 if (channels->data && GST_IS_COLOR_BALANCE_CHANNEL (channels->data)) {
2096 GstColorBalanceChannel *channel = NULL;
2099 gdouble convert_coef;
2101 channel = GST_COLOR_BALANCE_CHANNEL (channels->data);
2102 g_object_ref (channel);
2104 /* Our range conversion coef */
2105 convert_coef = (channel->max_value - channel->min_value) / 2000.0;
2107 if (g_ascii_strcasecmp (channel->label, "XV_HUE") == 0) {
2108 value = evaspixmapsink->hue;
2109 } else if (g_ascii_strcasecmp (channel->label, "XV_SATURATION") == 0) {
2110 value = evaspixmapsink->saturation;
2111 } else if (g_ascii_strcasecmp (channel->label, "XV_CONTRAST") == 0) {
2112 value = evaspixmapsink->contrast;
2113 } else if (g_ascii_strcasecmp (channel->label, "XV_BRIGHTNESS") == 0) {
2114 value = evaspixmapsink->brightness;
2116 g_warning ("got an unknown channel %s", channel->label);
2117 g_object_unref (channel);
2121 /* Committing to Xv port */
2122 g_mutex_lock (evaspixmapsink->x_lock);
2124 XInternAtom (evaspixmapsink->xcontext->disp, channel->label, True);
2125 if (prop_atom != None) {
2128 floor (0.5 + (value + 1000) * convert_coef + channel->min_value);
2129 XvSetPortAttribute (evaspixmapsink->xcontext->disp,
2130 evaspixmapsink->xcontext->xv_port_id, prop_atom, xv_value);
2132 g_mutex_unlock (evaspixmapsink->x_lock);
2134 g_object_unref (channel);
2136 channels = g_list_next (channels);
2141 gst_lookup_xv_port_from_adaptor (GstXContext *xcontext, XvAdaptorInfo *adaptors, int adaptor_no)
2146 /* Do we support XvImageMask ? */
2147 if (!(adaptors[adaptor_no].type & XvImageMask)) {
2148 GST_DEBUG ("XV Adaptor %s has no support for XvImageMask", adaptors[adaptor_no].name);
2152 /* We found such an adaptor, looking for an available port */
2153 for (j = 0; j < adaptors[adaptor_no].num_ports && !xcontext->xv_port_id; j++) {
2154 /* We try to grab the port */
2155 res = XvGrabPort (xcontext->disp, adaptors[adaptor_no].base_id + j, 0);
2156 if (Success == res) {
2157 xcontext->xv_port_id = adaptors[adaptor_no].base_id + j;
2158 GST_DEBUG ("XV Adaptor %s with %ld ports", adaptors[adaptor_no].name, adaptors[adaptor_no].num_ports);
2160 GST_DEBUG ("GrabPort %d for XV Adaptor %s failed: %d", j, adaptors[adaptor_no].name, res);
2165 /* This function generates a caps with all supported format by the first
2166 Xv grabable port we find. We store each one of the supported formats in a
2167 format list and append the format to a newly created caps that we return
2168 If this function does not return NULL because of an error, it also grabs
2169 the port via XvGrabPort */
2171 gst_evaspixmapsink_get_xv_support (GstEvasPixmapSink *evaspixmapsink, GstXContext *xcontext)
2174 XvAdaptorInfo *adaptors;
2176 XvImageFormatValues *formats = NULL;
2178 XvEncodingInfo *encodings = NULL;
2179 gulong max_w = G_MAXINT, max_h = G_MAXINT;
2180 GstCaps *caps = NULL;
2181 GstCaps *rgb_caps = NULL;
2183 g_return_val_if_fail (xcontext != NULL, NULL);
2185 /* First let's check that XVideo extension is available */
2186 if (!XQueryExtension (xcontext->disp, "XVideo", &i, &i, &i)) {
2187 GST_ELEMENT_ERROR (evaspixmapsink, RESOURCE, SETTINGS,
2188 ("Could not initialise Xv output"),
2189 ("XVideo extension is not available"));
2193 /* Then we get adaptors list */
2194 if (Success != XvQueryAdaptors (xcontext->disp, xcontext->root,
2195 &xcontext->nb_adaptors, &adaptors)) {
2196 GST_ELEMENT_ERROR (evaspixmapsink, RESOURCE, SETTINGS,
2197 ("Could not initialise Xv output"),
2198 ("Failed getting XV adaptors list"));
2202 xcontext->xv_port_id = 0;
2204 GST_DEBUG_OBJECT (evaspixmapsink,"Found %u XV adaptor(s)", xcontext->nb_adaptors);
2206 xcontext->adaptors =
2207 (gchar **) g_malloc0 (xcontext->nb_adaptors * sizeof (gchar *));
2209 /* Now fill up our adaptor name array */
2210 for (i = 0; i < xcontext->nb_adaptors; i++) {
2211 xcontext->adaptors[i] = g_strdup (adaptors[i].name);
2214 if (evaspixmapsink->adaptor_no < xcontext->nb_adaptors) {
2215 /* Find xv port from user defined adaptor */
2216 gst_lookup_xv_port_from_adaptor (xcontext, adaptors, evaspixmapsink->adaptor_no);
2219 if (!xcontext->xv_port_id) {
2220 /* Now search for an adaptor that supports XvImageMask */
2221 for (i = 0; i < xcontext->nb_adaptors && !xcontext->xv_port_id; i++) {
2222 gst_lookup_xv_port_from_adaptor (xcontext, adaptors, i);
2223 evaspixmapsink->adaptor_no = i;
2227 XvFreeAdaptorInfo (adaptors);
2229 if (!xcontext->xv_port_id) {
2230 evaspixmapsink->adaptor_no = -1;
2231 GST_ELEMENT_ERROR (evaspixmapsink, RESOURCE, BUSY,
2232 ("Could not initialise Xv output"), ("No port available"));
2236 /* Set XV_AUTOPAINT_COLORKEY and XV_DOUBLE_BUFFER and XV_COLORKEY */
2238 int count, todo = 3;
2239 XvAttribute *const attr = XvQueryPortAttributes (xcontext->disp,
2240 xcontext->xv_port_id, &count);
2241 static const char autopaint[] = "XV_AUTOPAINT_COLORKEY";
2242 static const char dbl_buffer[] = "XV_DOUBLE_BUFFER";
2243 static const char colorkey[] = "XV_COLORKEY";
2245 GST_DEBUG_OBJECT (evaspixmapsink,"Checking %d Xv port attributes", count);
2247 evaspixmapsink->have_autopaint_colorkey = FALSE;
2248 evaspixmapsink->have_double_buffer = FALSE;
2249 evaspixmapsink->have_colorkey = FALSE;
2251 for (i = 0; ((i < count) && todo); i++)
2252 if (!strcmp (attr[i].name, autopaint)) {
2253 const Atom atom = XInternAtom (xcontext->disp, autopaint, False);
2255 /* turn on autopaint colorkey */
2256 XvSetPortAttribute (xcontext->disp, xcontext->xv_port_id, atom,
2257 (evaspixmapsink->autopaint_colorkey ? 1 : 0));
2259 evaspixmapsink->have_autopaint_colorkey = TRUE;
2260 } else if (!strcmp (attr[i].name, dbl_buffer)) {
2261 const Atom atom = XInternAtom (xcontext->disp, dbl_buffer, False);
2263 XvSetPortAttribute (xcontext->disp, xcontext->xv_port_id, atom,
2264 (evaspixmapsink->double_buffer ? 1 : 0));
2266 evaspixmapsink->have_double_buffer = TRUE;
2267 } else if (!strcmp (attr[i].name, colorkey)) {
2268 /* Set the colorkey, default is something that is dark but hopefully
2269 * won't randomly appear on the screen elsewhere (ie not black or greys)
2270 * can be overridden by setting "colorkey" property
2272 const Atom atom = XInternAtom (xcontext->disp, colorkey, False);
2274 gboolean set_attr = TRUE;
2277 /* set a colorkey in the right format RGB565/RGB888
2278 * We only handle these 2 cases, because they're the only types of
2279 * devices we've encountered. If we don't recognise it, leave it alone
2281 cr = (evaspixmapsink->colorkey >> 16);
2282 cg = (evaspixmapsink->colorkey >> 8) & 0xFF;
2283 cb = (evaspixmapsink->colorkey) & 0xFF;
2284 switch (xcontext->depth) {
2285 case 16: /* RGB 565 */
2289 ckey = (cr << 11) | (cg << 5) | cb;
2292 case 32: /* RGB 888 / ARGB 8888 */
2293 ckey = (cr << 16) | (cg << 8) | cb;
2296 GST_DEBUG_OBJECT (evaspixmapsink,"Unknown bit depth %d for Xv Colorkey - not adjusting", xcontext->depth);
2302 ckey = CLAMP (ckey, (guint32) attr[i].min_value,
2303 (guint32) attr[i].max_value);
2304 GST_LOG_OBJECT (evaspixmapsink,"Setting color key for display depth %d to 0x%x", xcontext->depth, ckey);
2306 XvSetPortAttribute (xcontext->disp, xcontext->xv_port_id, atom,
2310 evaspixmapsink->have_colorkey = TRUE;
2316 /* Get the list of encodings supported by the adapter and look for the
2317 * XV_IMAGE encoding so we can determine the maximum width and height
2319 XvQueryEncodings (xcontext->disp, xcontext->xv_port_id, &nb_encodings,
2322 for (i = 0; i < nb_encodings; i++) {
2323 GST_LOG_OBJECT (evaspixmapsink,
2324 "Encoding %d, name %s, max wxh %lux%lu rate %d/%d",
2325 i, encodings[i].name, encodings[i].width, encodings[i].height,
2326 encodings[i].rate.numerator, encodings[i].rate.denominator);
2327 if (strcmp (encodings[i].name, "XV_IMAGE") == 0) {
2328 max_w = encodings[i].width;
2329 max_h = encodings[i].height;
2330 evaspixmapsink->scr_w = max_w;
2331 evaspixmapsink->scr_h = max_h;
2335 XvFreeEncodingInfo (encodings);
2337 /* We get all image formats supported by our port */
2338 formats = XvListImageFormats (xcontext->disp,
2339 xcontext->xv_port_id, &nb_formats);
2340 caps = gst_caps_new_empty ();
2341 for (i = 0; i < nb_formats; i++) {
2342 GstCaps *format_caps = NULL;
2343 gboolean is_rgb_format = FALSE;
2345 /* We set the image format of the xcontext to an existing one. This
2346 is just some valid image format for making our xshm calls check before
2347 caps negotiation really happens. */
2348 xcontext->im_format = formats[i].id;
2350 switch (formats[i].type) {
2353 XvImageFormatValues *fmt = &(formats[i]);
2354 gint endianness = G_BIG_ENDIAN;
2356 if (fmt->byte_order == LSBFirst) {
2357 /* our caps system handles 24/32bpp RGB as big-endian. */
2358 if (fmt->bits_per_pixel == 24 || fmt->bits_per_pixel == 32) {
2359 fmt->red_mask = GUINT32_TO_BE (fmt->red_mask);
2360 fmt->green_mask = GUINT32_TO_BE (fmt->green_mask);
2361 fmt->blue_mask = GUINT32_TO_BE (fmt->blue_mask);
2363 if (fmt->bits_per_pixel == 24) {
2364 fmt->red_mask >>= 8;
2365 fmt->green_mask >>= 8;
2366 fmt->blue_mask >>= 8;
2369 endianness = G_LITTLE_ENDIAN;
2372 format_caps = gst_caps_new_simple ("video/x-raw-rgb",
2373 "format", GST_TYPE_FOURCC, formats[i].id,
2374 "endianness", G_TYPE_INT, endianness,
2375 "depth", G_TYPE_INT, fmt->depth,
2376 "bpp", G_TYPE_INT, fmt->bits_per_pixel,
2377 "red_mask", G_TYPE_INT, fmt->red_mask,
2378 "green_mask", G_TYPE_INT, fmt->green_mask,
2379 "blue_mask", G_TYPE_INT, fmt->blue_mask,
2380 "width", GST_TYPE_INT_RANGE, 1, max_w,
2381 "height", GST_TYPE_INT_RANGE, 1, max_h,
2382 "framerate", GST_TYPE_FRACTION_RANGE, 0, 1, G_MAXINT, 1, NULL);
2384 is_rgb_format = TRUE;
2388 format_caps = gst_caps_new_simple ("video/x-raw-yuv",
2389 "format", GST_TYPE_FOURCC, formats[i].id,
2390 "width", GST_TYPE_INT_RANGE, 1, max_w,
2391 "height", GST_TYPE_INT_RANGE, 1, max_h,
2392 "framerate", GST_TYPE_FRACTION_RANGE, 0, 1, G_MAXINT, 1, NULL);
2395 g_assert_not_reached ();
2400 GstEvasPixmapFormat *format = NULL;
2402 format = g_new0 (GstEvasPixmapFormat, 1);
2404 format->format = formats[i].id;
2405 format->caps = gst_caps_copy (format_caps);
2406 xcontext->formats_list = g_list_append (xcontext->formats_list, format);
2409 if (is_rgb_format) {
2410 if (rgb_caps == NULL)
2411 rgb_caps = format_caps;
2413 gst_caps_append (rgb_caps, format_caps);
2415 gst_caps_append (caps, format_caps);
2419 /* Collected all caps into either the caps or rgb_caps structures.
2420 * Append rgb_caps on the end of YUV, so that YUV is always preferred */
2422 gst_caps_append (caps, rgb_caps);
2427 GST_DEBUG_OBJECT (evaspixmapsink,"Generated the following caps: %" GST_PTR_FORMAT, caps);
2429 if (gst_caps_is_empty (caps)) {
2430 gst_caps_unref (caps);
2431 XvUngrabPort (xcontext->disp, xcontext->xv_port_id, 0);
2432 GST_ELEMENT_ERROR (evaspixmapsink, STREAM, WRONG_TYPE, (NULL),
2433 ("No supported format found"));
2441 gst_evaspixmapsink_event_thread (GstEvasPixmapSink * evaspixmapsink)
2443 g_return_val_if_fail (GST_IS_EVASPIXMAPSINK (evaspixmapsink), NULL);
2444 int damage_base = 0;
2445 int damage_err_base = 0;
2446 int damage_case = 0;
2449 Display *disp = NULL;
2453 char file_name[128];
2458 GST_OBJECT_LOCK (evaspixmapsink);
2460 if (evaspixmapsink->xcontext && evaspixmapsink->xcontext->disp) {
2461 disp = evaspixmapsink->xcontext->disp;
2463 GST_ERROR_OBJECT (evaspixmapsink,"evaspixmapsink->xcontext(->disp) is not ready");
2467 if (!XDamageQueryExtension(evaspixmapsink->xcontext->disp, &damage_base, &damage_err_base)) {
2468 GST_ERROR_OBJECT (evaspixmapsink,"XDamageQueryExtension() failed");
2471 damage_case = (int)damage_base + XDamageNotify;
2473 while (evaspixmapsink->running) {
2474 GST_OBJECT_UNLOCK (evaspixmapsink);
2476 g_mutex_lock (evaspixmapsink->x_lock);
2477 while (XPending (disp)) {
2478 XNextEvent (disp, &e);
2479 g_mutex_unlock (evaspixmapsink->x_lock);
2480 if (e.type == damage_case ) {
2481 XDamageNotifyEvent *damage_ev = (XDamageNotifyEvent *)&e;
2482 for (i = 0; i < evaspixmapsink->num_of_pixmaps; i++) {
2483 GstXPixmap *xpixmap = evaspixmapsink->xpixmap[i];
2484 if (xpixmap && damage_ev->drawable == xpixmap->pixmap) {
2485 g_mutex_lock(evaspixmapsink->pixmap_ref_lock);
2487 /* set it only if damage event comes from _buffer_put() */
2488 xpixmap->damaged_time = (gint)get_millis_time();
2490 g_mutex_unlock(evaspixmapsink->pixmap_ref_lock);
2491 if (GST_STATE(evaspixmapsink) < GST_STATE_PLAYING || log_warn_count < 20) {
2492 GST_WARNING_OBJECT (evaspixmapsink,"event_handler : got a damage event for pixmap(%d), refcount(%d), damaged_time(%d)",
2493 xpixmap->pixmap, xpixmap->ref, xpixmap->damaged_time);
2495 GST_DEBUG_OBJECT (evaspixmapsink,"event_handler : got a damage event for pixmap(%d), refcount(%d), damaged_time(%d)",
2496 xpixmap->pixmap, xpixmap->ref, xpixmap->damaged_time);
2498 if (evaspixmapsink->epipe_request_count > EPIPE_REQUEST_LIMIT) {
2499 GST_WARNING_OBJECT (evaspixmapsink,"event_handler : epipe_request_count(%d), skip ecore_pipe_write()", evaspixmapsink->epipe_request_count);
2501 ecore_pipe_write(evaspixmapsink->epipe, evaspixmapsink, sizeof(GstEvasPixmapSink));
2502 evaspixmapsink->epipe_request_count++;
2503 if (GST_STATE(evaspixmapsink) < GST_STATE_PLAYING || log_warn_count < 20 ) {
2504 GST_WARNING_OBJECT (evaspixmapsink,"event_handler : after call ecore_pipe_write() for pixmap(%d)", xpixmap->pixmap);
2507 GST_DEBUG_OBJECT (evaspixmapsink,"event_handler : after call ecore_pipe_write() for pixmap(%d)", xpixmap->pixmap);
2510 g_mutex_lock (evaspixmapsink->x_lock);
2511 XDamageSubtract (evaspixmapsink->xcontext->disp, evaspixmapsink->damage[i], None, None );
2512 g_mutex_unlock (evaspixmapsink->x_lock);
2515 int dump_w = evaspixmapsink->w + (32 - (evaspixmapsink->w%32)); // for multiples of 32
2518 evaspixmapsink->pixmap_addr[i] = gst_evaspixmapsink_get_buffer(evaspixmapsink->xcontext->disp, evaspixmapsink->xpixmap[i]->pixmap, dump_w, evaspixmapsink->h, i);
2519 GST_ERROR("<DUMP_%2.2d> pixmap[%d] addr %p (w : %d, h : %d)", g_cnt, i, evaspixmapsink->pixmap_addr[i], dump_w, evaspixmapsink->h);
2520 sprintf(file_name, "/opt/usr/media/DUMP_%2.2d.dump", g_cnt);
2522 dump_data = g_malloc(dump_w * evaspixmapsink->h * 4);
2523 memcpy (dump_data, evaspixmapsink->pixmap_addr[i], dump_w * evaspixmapsink->h * 4);
2525 ret = util_write_rawdata(file_name, dump_data, dump_w * evaspixmapsink->h * 4);
2527 GST_ERROR_OBJECT (evaspixmapsink, "util_write_rawdata() failed");
2534 gst_evaspixmapsink_free_buffer (i);
2535 g_bufinfo[i] = NULL;
2537 evaspixmapsink->pixmap_addr[i] = NULL;
2540 if (evaspixmapsink->buf_shared_type == BUF_SHARE_METHOD_FD) {
2541 if (GST_STATE(evaspixmapsink) == GST_STATE_PLAYING) {
2542 drm_fini_close_gem_handle(evaspixmapsink, xpixmap->pixmap);
2548 if (i == evaspixmapsink->num_of_pixmaps) {
2549 GST_WARNING_OBJECT (evaspixmapsink,"event_handler : could not find corresponding pixmap with this damage event(%d)", damage_ev->drawable);
2552 GST_LOG_OBJECT (evaspixmapsink,"event_handler : unidentified event(%d)", e.type);
2553 g_mutex_lock (evaspixmapsink->x_lock);
2556 g_mutex_lock (evaspixmapsink->x_lock);
2558 //XSync (disp, FALSE);
2559 g_mutex_unlock (evaspixmapsink->x_lock);
2561 g_usleep (G_USEC_PER_SEC / 40);
2562 GST_OBJECT_LOCK (evaspixmapsink);
2564 GST_OBJECT_UNLOCK (evaspixmapsink);
2569 gst_evaspixmapsink_manage_event_thread (GstEvasPixmapSink *evaspixmapsink)
2571 /* don't start the thread too early */
2572 if (evaspixmapsink->xcontext == NULL) {
2573 GST_ERROR_OBJECT (evaspixmapsink,"xcontext is NULL..");
2577 GST_OBJECT_LOCK (evaspixmapsink);
2579 if (!evaspixmapsink->event_thread) {
2580 /* Setup our event listening thread */
2581 GST_DEBUG_OBJECT (evaspixmapsink,"run xevent thread");
2582 evaspixmapsink->running = TRUE;
2583 evaspixmapsink->event_thread = g_thread_create ( (GThreadFunc) gst_evaspixmapsink_event_thread, evaspixmapsink, TRUE, NULL);
2585 GST_WARNING_OBJECT (evaspixmapsink,"there already existed the event_thread.. keep going");
2586 /* Do not finalize the thread in here, Only finalize the thread by calling gst_evaspixmapsink_reset() */
2589 GST_OBJECT_UNLOCK (evaspixmapsink);
2593 /* This function calculates the pixel aspect ratio based on the properties
2594 * in the xcontext structure and stores it there. */
2596 gst_evaspixmapsink_calculate_pixel_aspect_ratio (GstXContext *xcontext)
2598 static const gint par[][2] = {
2599 {1, 1}, /* regular screen */
2600 {16, 15}, /* PAL TV */
2601 {11, 10}, /* 525 line Rec.601 video */
2602 {54, 59}, /* 625 line Rec.601 video */
2603 {64, 45}, /* 1280x1024 on 16:9 display */
2604 {5, 3}, /* 1280x1024 on 4:3 display */
2605 {4, 3} /* 800x600 on 16:9 display */
2612 #define DELTA(idx) (ABS (ratio - ((gdouble) par[idx][0] / par[idx][1])))
2614 /* first calculate the "real" ratio based on the X values;
2615 * which is the "physical" w/h divided by the w/h in pixels of the display */
2616 ratio = (gdouble) (xcontext->widthmm * xcontext->height)
2617 / (xcontext->heightmm * xcontext->width);
2619 /* DirectFB's X in 720x576 reports the physical dimensions wrong, so
2621 if (xcontext->width == 720 && xcontext->height == 576) {
2622 ratio = 4.0 * 576 / (3.0 * 720);
2624 GST_DEBUG ("calculated pixel aspect ratio: %f", ratio);
2625 /* now find the one from par[][2] with the lowest delta to the real one */
2629 for (i = 1; i < sizeof (par) / (sizeof (gint) * 2); ++i) {
2630 gdouble this_delta = DELTA (i);
2632 if (this_delta < delta) {
2638 GST_DEBUG ("Decided on index %d (%d/%d)", index,
2639 par[index][0], par[index][1]);
2641 g_free (xcontext->par);
2642 xcontext->par = g_new0 (GValue, 1);
2643 g_value_init (xcontext->par, GST_TYPE_FRACTION);
2644 gst_value_set_fraction (xcontext->par, par[index][0], par[index][1]);
2645 GST_DEBUG ("set xcontext PAR to %d/%d",
2646 gst_value_get_fraction_numerator (xcontext->par),
2647 gst_value_get_fraction_denominator (xcontext->par));
2650 /* This function gets the X Display and global info about it. Everything is
2651 stored in our object and will be cleaned when the object is disposed. Note
2652 here that caps for supported format are generated without any window or
2655 gst_evaspixmapsink_xcontext_get (GstEvasPixmapSink *evaspixmapsink)
2657 GstXContext *xcontext = NULL;
2658 XPixmapFormatValues *px_formats = NULL;
2659 gint nb_formats = 0, i, j, N_attr;
2660 XvAttribute *xv_attr;
2662 const char *channels[4] = { "XV_HUE", "XV_SATURATION", "XV_BRIGHTNESS", "XV_CONTRAST"};
2664 g_return_val_if_fail (GST_IS_EVASPIXMAPSINK (evaspixmapsink), NULL);
2666 xcontext = g_new0 (GstXContext, 1);
2667 xcontext->im_format = 0;
2669 g_mutex_lock (evaspixmapsink->x_lock);
2671 xcontext->disp = XOpenDisplay (evaspixmapsink->display_name);
2672 if (!xcontext->disp) {
2673 g_mutex_unlock (evaspixmapsink->x_lock);
2675 GST_ELEMENT_ERROR (evaspixmapsink, RESOURCE, WRITE, ("Could not initialise Xv output"), ("Could not open display"));
2678 GST_WARNING_OBJECT (evaspixmapsink,"Display(0x%x) is opened", xcontext->disp);
2679 g_my_disp = xcontext->disp;
2681 xcontext->screen = DefaultScreenOfDisplay (xcontext->disp);
2682 xcontext->screen_num = DefaultScreen (xcontext->disp);
2683 xcontext->visual = DefaultVisual (xcontext->disp, xcontext->screen_num);
2684 xcontext->root = DefaultRootWindow (xcontext->disp);
2685 xcontext->white = XWhitePixel (xcontext->disp, xcontext->screen_num);
2686 xcontext->depth = DefaultDepthOfScreen (xcontext->screen);
2688 xcontext->width = DisplayWidth (xcontext->disp, xcontext->screen_num);
2689 xcontext->height = DisplayHeight (xcontext->disp, xcontext->screen_num);
2690 xcontext->widthmm = DisplayWidthMM (xcontext->disp, xcontext->screen_num);
2691 xcontext->heightmm = DisplayHeightMM (xcontext->disp, xcontext->screen_num);
2693 GST_DEBUG_OBJECT (evaspixmapsink,"X reports %dx%d pixels and %d mm x %d mm", xcontext->width, xcontext->height, xcontext->widthmm, xcontext->heightmm);
2695 gst_evaspixmapsink_calculate_pixel_aspect_ratio (xcontext);
2696 /* We get supported pixmap formats at supported depth */
2697 px_formats = XListPixmapFormats (xcontext->disp, &nb_formats);
2700 XCloseDisplay (xcontext->disp);
2701 g_mutex_unlock (evaspixmapsink->x_lock);
2702 g_free (xcontext->par);
2704 GST_ELEMENT_ERROR (evaspixmapsink, RESOURCE, SETTINGS,
2705 ("Could not initialise Xv output"), ("Could not get pixel formats"));
2710 /* We get bpp value corresponding to our running depth */
2711 for (i = 0; i < nb_formats; i++) {
2712 if (px_formats[i].depth == xcontext->depth)
2713 xcontext->bpp = px_formats[i].bits_per_pixel;
2718 xcontext->endianness = (ImageByteOrder (xcontext->disp) == LSBFirst) ? G_LITTLE_ENDIAN : G_BIG_ENDIAN;
2720 /* our caps system handles 24/32bpp RGB as big-endian. */
2721 if ((xcontext->bpp == 24 || xcontext->bpp == 32) && xcontext->endianness == G_LITTLE_ENDIAN) {
2722 xcontext->endianness = G_BIG_ENDIAN;
2723 xcontext->visual->red_mask = GUINT32_TO_BE (xcontext->visual->red_mask);
2724 xcontext->visual->green_mask = GUINT32_TO_BE (xcontext->visual->green_mask);
2725 xcontext->visual->blue_mask = GUINT32_TO_BE (xcontext->visual->blue_mask);
2726 if (xcontext->bpp == 24) {
2727 xcontext->visual->red_mask >>= 8;
2728 xcontext->visual->green_mask >>= 8;
2729 xcontext->visual->blue_mask >>= 8;
2733 xcontext->caps = gst_evaspixmapsink_get_xv_support (evaspixmapsink, xcontext);
2735 if (!xcontext->caps) {
2736 XCloseDisplay (xcontext->disp);
2737 g_mutex_unlock (evaspixmapsink->x_lock);
2738 g_free (xcontext->par);
2740 /* GST_ELEMENT_ERROR is thrown by gst_evaspixmapsink_get_xv_support */
2745 /* Search for XShm extension support */
2746 if (XShmQueryExtension (xcontext->disp) && gst_evaspixmapsink_check_xshm_calls (xcontext)) {
2747 xcontext->use_xshm = TRUE;
2748 GST_DEBUG_OBJECT (evaspixmapsink,"evaspixmapsink is using XShm extension");
2750 #endif /* HAVE_XSHM */
2752 xcontext->use_xshm = FALSE;
2753 GST_DEBUG_OBJECT (evaspixmapsink,"evaspixmapsink is not using XShm extension");
2756 xv_attr = XvQueryPortAttributes (xcontext->disp, xcontext->xv_port_id, &N_attr);
2758 /* Generate the channels list */
2759 for (i = 0; i < (sizeof (channels) / sizeof (char *)); i++) {
2760 XvAttribute *matching_attr = NULL;
2762 /* Retrieve the property atom if it exists. If it doesn't exist,
2763 * the attribute itself must not either, so we can skip */
2764 prop_atom = XInternAtom (xcontext->disp, channels[i], True);
2765 if (prop_atom == None) {
2769 if (xv_attr != NULL) {
2770 for (j = 0; j < N_attr && matching_attr == NULL; ++j) {
2771 if (!g_ascii_strcasecmp (channels[i], xv_attr[j].name)) {
2772 matching_attr = xv_attr + j;
2777 if (matching_attr) {
2778 GstColorBalanceChannel *channel;
2779 channel = g_object_new (GST_TYPE_COLOR_BALANCE_CHANNEL, NULL);
2780 channel->label = g_strdup (channels[i]);
2781 channel->min_value = matching_attr->min_value;
2782 channel->max_value = matching_attr->max_value;
2784 xcontext->channels_list = g_list_append (xcontext->channels_list, channel);
2786 /* If the colorbalance settings have not been touched we get Xv values
2787 as defaults and update our internal variables */
2788 if (!evaspixmapsink->cb_changed) {
2790 XvGetPortAttribute (xcontext->disp, xcontext->xv_port_id, prop_atom, &val);
2791 /* Normalize val to [-1000, 1000] */
2792 val = floor (0.5 + -1000 + 2000 * (val - channel->min_value) / (double) (channel->max_value - channel->min_value));
2794 if (!g_ascii_strcasecmp (channels[i], "XV_HUE")) {
2795 evaspixmapsink->hue = val;
2796 } else if (!g_ascii_strcasecmp (channels[i], "XV_SATURATION")) {
2797 evaspixmapsink->saturation = val;
2798 } else if (!g_ascii_strcasecmp (channels[i], "XV_BRIGHTNESS")) {
2799 evaspixmapsink->brightness = val;
2800 } else if (!g_ascii_strcasecmp (channels[i], "XV_CONTRAST")) {
2801 evaspixmapsink->contrast = val;
2811 g_mutex_unlock (evaspixmapsink->x_lock);
2816 /* This function cleans the X context. Closing the Display, releasing the XV
2817 port and unrefing the caps for supported formats. */
2819 gst_evaspixmapsink_xcontext_clear (GstEvasPixmapSink *evaspixmapsink)
2821 GList *formats_list, *channels_list;
2822 GstXContext *xcontext;
2825 g_return_if_fail (GST_IS_EVASPIXMAPSINK (evaspixmapsink));
2827 GST_OBJECT_LOCK (evaspixmapsink);
2828 if (evaspixmapsink->xcontext == NULL) {
2829 GST_OBJECT_UNLOCK (evaspixmapsink);
2833 /* Take the XContext from the sink and clean it up */
2834 xcontext = evaspixmapsink->xcontext;
2835 evaspixmapsink->xcontext = NULL;
2837 GST_OBJECT_UNLOCK (evaspixmapsink);
2839 formats_list = xcontext->formats_list;
2841 while (formats_list) {
2842 GstEvasPixmapFormat *format = formats_list->data;
2844 gst_caps_unref (format->caps);
2846 formats_list = g_list_next (formats_list);
2849 if (xcontext->formats_list)
2850 g_list_free (xcontext->formats_list);
2852 channels_list = xcontext->channels_list;
2854 while (channels_list) {
2855 GstColorBalanceChannel *channel = channels_list->data;
2857 g_object_unref (channel);
2858 channels_list = g_list_next (channels_list);
2861 if (xcontext->channels_list)
2862 g_list_free (xcontext->channels_list);
2864 gst_caps_unref (xcontext->caps);
2866 for (i = 0; i < xcontext->nb_adaptors; i++) {
2867 g_free (xcontext->adaptors[i]);
2870 g_free (xcontext->adaptors);
2872 g_free (xcontext->par);
2874 g_mutex_lock (evaspixmapsink->x_lock);
2876 GST_DEBUG_OBJECT (evaspixmapsink,"Closing display and freeing X Context");
2878 XvUngrabPort (xcontext->disp, xcontext->xv_port_id, 0);
2880 XCloseDisplay (xcontext->disp);
2883 g_mutex_unlock (evaspixmapsink->x_lock);
2890 /* This function tries to get a format matching with a given caps in the
2891 supported list of formats we generated in gst_evaspixmapsink_get_xv_support */
2893 gst_evaspixmapsink_get_format_from_caps (GstEvasPixmapSink *evaspixmapsink, GstCaps *caps)
2897 g_return_val_if_fail (GST_IS_EVASPIXMAPSINK (evaspixmapsink), 0);
2899 list = evaspixmapsink->xcontext->formats_list;
2902 GstEvasPixmapFormat *format = list->data;
2905 if (gst_caps_can_intersect (caps, format->caps)) {
2906 return format->format;
2909 list = g_list_next (list);
2916 gst_evaspixmapsink_getcaps (GstBaseSink *bsink)
2918 GstEvasPixmapSink *evaspixmapsink;
2920 evaspixmapsink = GST_EVASPIXMAPSINK (bsink);
2922 if (evaspixmapsink->xcontext)
2923 return gst_caps_ref (evaspixmapsink->xcontext->caps);
2926 gst_caps_copy (gst_pad_get_pad_template_caps (GST_VIDEO_SINK_PAD
2931 gst_evaspixmapsink_setcaps (GstBaseSink *bsink, GstCaps *caps)
2933 GstEvasPixmapSink *evaspixmapsink;
2934 GstStructure *structure;
2935 guint32 im_format = 0;
2937 gint video_width, video_height;
2938 gint disp_x, disp_y;
2939 gint disp_width, disp_height;
2940 gint video_par_n, video_par_d; /* video's PAR */
2941 gint display_par_n, display_par_d; /* display's PAR */
2942 const GValue *caps_par;
2943 const GValue *caps_disp_reg;
2946 gboolean enable_last_buffer;
2948 evaspixmapsink = GST_EVASPIXMAPSINK (bsink);
2950 GST_DEBUG_OBJECT (evaspixmapsink,"In setcaps. Possible caps %" GST_PTR_FORMAT ", setting caps %" GST_PTR_FORMAT, evaspixmapsink->xcontext->caps, caps);
2952 if (!gst_caps_can_intersect (evaspixmapsink->xcontext->caps, caps)) {
2953 goto incompatible_caps;
2956 structure = gst_caps_get_structure (caps, 0);
2957 ret = gst_structure_get_int (structure, "width", &video_width);
2958 ret &= gst_structure_get_int (structure, "height", &video_height);
2959 fps = gst_structure_get_value (structure, "framerate");
2960 ret &= (fps != NULL);
2963 goto incomplete_caps;
2966 evaspixmapsink->aligned_width = video_width;
2967 evaspixmapsink->aligned_height = video_height;
2969 /* get combine prop of hevc */
2970 if(gst_structure_get_int (structure, "yuvcombine", &(evaspixmapsink->need_combine_data)))
2972 GST_INFO_OBJECT(evaspixmapsink, "need combine data : %d", evaspixmapsink->need_combine_data);
2976 /*Not need to combine data, just directly copy*/
2977 evaspixmapsink->need_combine_data = 0;
2980 /* get enable-last-buffer */
2981 g_object_get(G_OBJECT(evaspixmapsink), "enable-last-buffer", &enable_last_buffer, NULL);
2982 GST_INFO_OBJECT (evaspixmapsink,"current enable-last-buffer : %d", enable_last_buffer);
2983 /* flush if enable-last-buffer is TRUE */
2984 if (enable_last_buffer) {
2985 GST_INFO_OBJECT (evaspixmapsink,"flush last-buffer");
2986 g_object_set(G_OBJECT(evaspixmapsink), "enable-last-buffer", FALSE, NULL);
2987 g_object_set(G_OBJECT(evaspixmapsink), "enable-last-buffer", TRUE, NULL);
2990 evaspixmapsink->fps_n = gst_value_get_fraction_numerator (fps);
2991 evaspixmapsink->fps_d = gst_value_get_fraction_denominator (fps);
2993 if (evaspixmapsink->video_width != video_width || evaspixmapsink->video_height != video_height) {
2994 evaspixmapsink->src_prev.w = evaspixmapsink->video_width = video_width;
2995 evaspixmapsink->src_prev.h = evaspixmapsink->video_height = video_height;
2996 evaspixmapsink->need_to_fill_black = TRUE;
2999 im_format = gst_evaspixmapsink_get_format_from_caps (evaspixmapsink, caps);
3000 if (im_format == -1) {
3001 goto invalid_format;
3004 /* get aspect ratio from caps if it's present, and
3005 * convert video width and height to a display width and height
3006 * using wd / hd = wv / hv * PARv / PARd */
3008 /* get video's PAR */
3009 caps_par = gst_structure_get_value (structure, "pixel-aspect-ratio");
3011 video_par_n = gst_value_get_fraction_numerator (caps_par);
3012 video_par_d = gst_value_get_fraction_denominator (caps_par);
3017 /* get display's PAR */
3018 if (evaspixmapsink->par) {
3019 display_par_n = gst_value_get_fraction_numerator (evaspixmapsink->par);
3020 display_par_d = gst_value_get_fraction_denominator (evaspixmapsink->par);
3026 /* get the display region */
3027 caps_disp_reg = gst_structure_get_value (structure, "display-region");
3028 if (caps_disp_reg) {
3029 disp_x = g_value_get_int (gst_value_array_get_value (caps_disp_reg, 0));
3030 disp_y = g_value_get_int (gst_value_array_get_value (caps_disp_reg, 1));
3031 disp_width = g_value_get_int (gst_value_array_get_value (caps_disp_reg, 2));
3032 disp_height = g_value_get_int (gst_value_array_get_value (caps_disp_reg, 3));
3034 disp_x = disp_y = 0;
3035 disp_width = video_width;
3036 disp_height = video_height;
3039 if (!gst_video_calculate_display_ratio (&num, &den, video_width, video_height, video_par_n, video_par_d, display_par_n, display_par_d)) {
3043 evaspixmapsink->disp_x = disp_x;
3044 evaspixmapsink->disp_y = disp_y;
3045 evaspixmapsink->disp_width = disp_width;
3046 evaspixmapsink->disp_height = disp_height;
3048 GST_DEBUG_OBJECT (evaspixmapsink,"video width/height: %dx%d, calculated display ratio: %d/%d", video_width, video_height, num, den);
3050 /* now find a width x height that respects this display ratio.
3051 * prefer those that have one of w/h the same as the incoming video
3052 * using wd / hd = num / den */
3054 /* start with same height, because of interlaced video */
3055 /* check hd / den is an integer scale factor, and scale wd with the PAR */
3056 if (video_height % den == 0) {
3057 GST_DEBUG_OBJECT (evaspixmapsink,"keeping video height");
3058 GST_VIDEO_SINK_WIDTH (evaspixmapsink) = (guint) gst_util_uint64_scale_int (video_height, num, den);
3059 GST_VIDEO_SINK_HEIGHT (evaspixmapsink) = video_height;
3060 } else if (video_width % num == 0) {
3061 GST_DEBUG_OBJECT (evaspixmapsink,"keeping video width");
3062 GST_VIDEO_SINK_WIDTH (evaspixmapsink) = video_width;
3063 GST_VIDEO_SINK_HEIGHT (evaspixmapsink) = (guint) gst_util_uint64_scale_int (video_width, den, num);
3065 GST_DEBUG_OBJECT (evaspixmapsink,"approximating while keeping video height");
3066 GST_VIDEO_SINK_WIDTH (evaspixmapsink) = (guint) gst_util_uint64_scale_int (video_height, num, den);
3067 GST_VIDEO_SINK_HEIGHT (evaspixmapsink) = video_height;
3069 GST_DEBUG_OBJECT (evaspixmapsink,"scaling to %dx%d", GST_VIDEO_SINK_WIDTH (evaspixmapsink), GST_VIDEO_SINK_HEIGHT (evaspixmapsink));
3071 /* Creating our window and our image with the display size in pixels */
3072 if (GST_VIDEO_SINK_WIDTH (evaspixmapsink) <= 0 || GST_VIDEO_SINK_HEIGHT (evaspixmapsink) <= 0) {
3073 goto no_display_size;
3076 g_mutex_lock (evaspixmapsink->flow_lock);
3078 /* We renew our evaspixmap buffer only if size or format changed;
3079 * the evaspixmap buffer is the same size as the video pixel size */
3080 if ((evaspixmapsink->evas_pixmap_buf) && ((im_format != evaspixmapsink->evas_pixmap_buf->im_format)
3081 || (video_width != evaspixmapsink->evas_pixmap_buf->width) || (video_height != evaspixmapsink->evas_pixmap_buf->height))) {
3082 GST_DEBUG_OBJECT (evaspixmapsink,"old format %" GST_FOURCC_FORMAT ", new format %" GST_FOURCC_FORMAT,
3083 GST_FOURCC_ARGS (evaspixmapsink->evas_pixmap_buf->im_format), GST_FOURCC_ARGS (im_format));
3084 GST_DEBUG_OBJECT (evaspixmapsink,"renewing evaspixmap buffer");
3085 gst_buffer_unref (GST_BUFFER (evaspixmapsink->evas_pixmap_buf));
3086 evaspixmapsink->evas_pixmap_buf = NULL;
3089 g_mutex_unlock (evaspixmapsink->flow_lock);
3091 if (evaspixmapsink->eo) {
3092 if (!gst_evaspixmapsink_xpixmap_link (evaspixmapsink)) {
3093 GST_ERROR_OBJECT (evaspixmapsink,"link evas image object with pixmap failed...");
3096 gst_evaspixmapsink_manage_event_thread (evaspixmapsink);
3099 GST_ERROR_OBJECT (evaspixmapsink,"setcaps success, but there is no evas image object..");
3108 GST_ERROR_OBJECT (evaspixmapsink,"caps incompatible");
3113 GST_DEBUG_OBJECT (evaspixmapsink,"Failed to retrieve either width, ""height or framerate from intersected caps");
3118 GST_DEBUG_OBJECT (evaspixmapsink,"Could not locate image format from caps %" GST_PTR_FORMAT, caps);
3123 GST_ELEMENT_ERROR (evaspixmapsink, CORE, NEGOTIATION, (NULL), ("Error calculating the output display ratio of the video."));
3128 GST_ELEMENT_ERROR (evaspixmapsink, CORE, NEGOTIATION, (NULL), ("Error calculating the output display ratio of the video."));
3133 static GstStateChangeReturn
3134 gst_evaspixmapsink_change_state (GstElement *element, GstStateChange transition)
3136 GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
3137 GstEvasPixmapSink *evaspixmapsink;
3139 evaspixmapsink = GST_EVASPIXMAPSINK (element);
3141 switch (transition) {
3142 case GST_STATE_CHANGE_NULL_TO_READY:
3143 g_mutex_lock (evaspixmapsink->flow_lock);
3144 GST_WARNING_OBJECT (evaspixmapsink,"GST_STATE_CHANGE_NULL_TO_READY");
3146 /* open drm to use gem */
3147 if (drm_init(evaspixmapsink)) {
3148 GST_ERROR_OBJECT (evaspixmapsink,"drm_init() failure");
3149 g_mutex_unlock (evaspixmapsink->flow_lock);
3150 return GST_STATE_CHANGE_FAILURE;
3153 /* check if there exist evas image object, need to write code related to making internal evas image object */
3154 if (!is_evas_image_object (evaspixmapsink->eo)) {
3155 GST_ERROR_OBJECT (evaspixmapsink,"There is no evas image object..");
3156 g_mutex_unlock (evaspixmapsink->flow_lock);
3157 return GST_STATE_CHANGE_FAILURE;
3160 /* Set xcontext and display */
3161 if (!evaspixmapsink->xcontext) {
3162 evaspixmapsink->xcontext = gst_evaspixmapsink_xcontext_get (evaspixmapsink);
3163 if (!evaspixmapsink->xcontext) {
3164 GST_ERROR_OBJECT (evaspixmapsink,"could not get xcontext..");
3165 g_mutex_unlock (evaspixmapsink->flow_lock);
3166 return GST_STATE_CHANGE_FAILURE;
3170 /* update object's par with calculated one if not set yet */
3171 if (!evaspixmapsink->par) {
3172 evaspixmapsink->par = g_new0 (GValue, 1);
3173 gst_value_init_and_copy (evaspixmapsink->par, evaspixmapsink->xcontext->par);
3174 GST_DEBUG_OBJECT (evaspixmapsink,"set calculated PAR on object's PAR");
3177 /* call XSynchronize with the current value of synchronous */
3178 GST_DEBUG_OBJECT (evaspixmapsink,"XSynchronize called with %s", evaspixmapsink->synchronous ? "TRUE" : "FALSE");
3179 g_mutex_lock (evaspixmapsink->x_lock);
3180 XSynchronize (evaspixmapsink->xcontext->disp, evaspixmapsink->synchronous);
3181 g_mutex_unlock (evaspixmapsink->x_lock);
3182 gst_evaspixmapsink_update_colorbalance (evaspixmapsink);
3184 g_mutex_unlock (evaspixmapsink->flow_lock);
3187 case GST_STATE_CHANGE_READY_TO_PAUSED:
3188 GST_WARNING_OBJECT (evaspixmapsink,"GST_STATE_CHANGE_READY_TO_PAUSED");
3191 case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
3192 GST_WARNING_OBJECT (evaspixmapsink,"GST_STATE_CHANGE_PAUSED_TO_PLAYING");
3199 ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
3201 switch (transition) {
3202 case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
3203 GST_WARNING_OBJECT (evaspixmapsink,"GST_STATE_CHANGE_PLAYING_TO_PAUSED");
3207 case GST_STATE_CHANGE_PAUSED_TO_READY:
3210 GST_WARNING_OBJECT (evaspixmapsink,"GST_STATE_CHANGE_PAUSED_TO_READY");
3211 evaspixmapsink->fps_n = 0;
3212 evaspixmapsink->fps_d = 1;
3213 GST_VIDEO_SINK_WIDTH (evaspixmapsink) = 0;
3214 GST_VIDEO_SINK_HEIGHT (evaspixmapsink) = 0;
3215 drm_fini_close_gem_handle(evaspixmapsink, 0);
3219 case GST_STATE_CHANGE_READY_TO_NULL:
3220 GST_WARNING_OBJECT (evaspixmapsink,"GST_STATE_CHANGE_READY_TO_NULL");
3221 g_mutex_lock (evaspixmapsink->flow_lock);
3222 gst_evaspixmapsink_reset(evaspixmapsink);
3223 g_mutex_unlock (evaspixmapsink->flow_lock);
3225 drm_fini(evaspixmapsink);
3235 gst_evaspixmapsink_get_times (GstBaseSink *bsink, GstBuffer *buf, GstClockTime *start, GstClockTime *end)
3237 GstEvasPixmapSink *evaspixmapsink;
3239 evaspixmapsink = GST_EVASPIXMAPSINK (bsink);
3241 if (GST_BUFFER_TIMESTAMP_IS_VALID (buf)) {
3242 *start = GST_BUFFER_TIMESTAMP (buf);
3243 if (GST_BUFFER_DURATION_IS_VALID (buf)) {
3244 *end = *start + GST_BUFFER_DURATION (buf);
3246 if (evaspixmapsink->fps_n > 0) {
3248 gst_util_uint64_scale_int (GST_SECOND, evaspixmapsink->fps_d,
3249 evaspixmapsink->fps_n);
3256 gst_evaspixmapsink_combine_i420_scmn_data(GstEvasPixmapSink *evaspixmapsink, GstBuffer *buf)
3258 unsigned int outsize = 0;
3259 unsigned char *temp_outbuf = evaspixmapsink->evas_pixmap_buf->xvimage->data;
3261 unsigned char *temp_imgb;
3262 SCMN_IMGB *imgb = NULL;
3263 int stride, w, h, i;
3267 imgb = (SCMN_IMGB *)GST_BUFFER_DATA(buf);
3268 if(imgb == NULL || imgb->a[0] == NULL)
3273 stride = GST_ROUND_UP_4 (imgb->w[0]);
3277 for (i = 0; i < h; i++)
3279 memcpy (temp_outbuf + i * stride, imgb->a[0] + i * imgb->s[0], w);
3282 temp_outbuf += GST_ROUND_UP_4 (imgb->w[0]) * GST_ROUND_UP_2 (imgb->h[0]);
3284 stride = GST_ROUND_UP_4 (GST_ROUND_UP_2 (imgb->w[0]) / 2);
3285 h = GST_ROUND_UP_2 (imgb->h[0]) / 2;
3286 w = GST_ROUND_UP_2 (imgb->w[0]) / 2;
3288 for (i = 0; i < h; i++)
3290 memcpy (temp_outbuf + i * stride, imgb->a[1] + i * imgb->s[1], w);
3293 temp_outbuf += GST_ROUND_UP_4 (GST_ROUND_UP_2 (imgb->w[0]) / 2) * (GST_ROUND_UP_2 (imgb->h[0]) / 2);
3294 /* Same stride, height, width as above */
3296 for (i = 0; i < h; i++)
3298 memcpy (temp_outbuf + i * stride, imgb->a[2] + i * imgb->s[2], w);
3301 outsize = imgb->w[0] * imgb->h[0]* 3 >> 1;
3302 evaspixmapsink->evas_pixmap_buf->size = MIN(outsize, evaspixmapsink->evas_pixmap_buf->size);
3307 static GstFlowReturn
3308 gst_evaspixmapsink_show_frame (GstVideoSink *vsink, GstBuffer *buf)
3310 GstEvasPixmapSink *evaspixmapsink;
3311 XV_DATA_PTR img_data = NULL;
3312 SCMN_IMGB *scmn_imgb = NULL;
3315 evaspixmapsink = GST_EVASPIXMAPSINK (vsink);
3317 if (GST_STATE(evaspixmapsink) < GST_STATE_PLAYING || log_warn_count < 20) {
3318 GST_WARNING_OBJECT (evaspixmapsink, "enter >>>" );
3321 if( evaspixmapsink->stop_video ) {
3322 GST_INFO_OBJECT (evaspixmapsink, "Stop video is TRUE. so skip show frame..." );
3326 if (!evaspixmapsink->evas_pixmap_buf) {
3327 GST_DEBUG_OBJECT (evaspixmapsink,"creating our evaspixmap buffer");
3328 format = gst_evaspixmapsink_get_format_from_caps(evaspixmapsink, GST_BUFFER_CAPS(buf));
3330 case GST_MAKE_FOURCC('S', 'T', '1', '2'):
3331 case GST_MAKE_FOURCC('S', 'N', '1', '2'):
3332 case GST_MAKE_FOURCC('S', '4', '2', '0'):
3333 case GST_MAKE_FOURCC('S', 'U', 'Y', '2'):
3334 case GST_MAKE_FOURCC('S', 'U', 'Y', 'V'):
3335 case GST_MAKE_FOURCC('S', 'Y', 'V', 'Y'):
3336 case GST_MAKE_FOURCC('I', 'T', 'L', 'V'):
3337 case GST_MAKE_FOURCC('S', 'R', '3', '2'):
3338 scmn_imgb = (SCMN_IMGB *)GST_BUFFER_MALLOCDATA(buf);
3339 if(scmn_imgb == NULL) {
3340 GST_DEBUG_OBJECT (evaspixmapsink, "scmn_imgb is NULL. Skip buffer put..." );
3343 /* skip buffer if aligned size is smaller than size of caps */
3344 if (scmn_imgb->s[0] < evaspixmapsink->video_width || scmn_imgb->e[0] < evaspixmapsink->video_height) {
3345 GST_WARNING_OBJECT (evaspixmapsink,"invalid size[caps:%dx%d,aligned:%dx%d]. Skip this buffer...",
3346 evaspixmapsink->video_width, evaspixmapsink->video_height, scmn_imgb->s[0], scmn_imgb->e[0]);
3349 evaspixmapsink->aligned_width = scmn_imgb->s[0];
3350 evaspixmapsink->aligned_height = scmn_imgb->e[0];
3351 GST_DEBUG_OBJECT (evaspixmapsink,"video width,height[%dx%d]",evaspixmapsink->video_width, evaspixmapsink->video_height);
3352 GST_INFO_OBJECT (evaspixmapsink,"Use aligned width,height[%dx%d]",evaspixmapsink->aligned_width, evaspixmapsink->aligned_height);
3355 GST_INFO_OBJECT (evaspixmapsink,"Use original width,height of caps");
3358 evaspixmapsink->evas_pixmap_buf = gst_evaspixmap_buffer_new (evaspixmapsink, GST_BUFFER_CAPS (buf));
3359 if (!evaspixmapsink->evas_pixmap_buf) {
3360 /* The create method should have posted an informative error */
3363 if (evaspixmapsink->evas_pixmap_buf->size < GST_BUFFER_SIZE (buf)) {
3364 GST_ELEMENT_ERROR (evaspixmapsink, RESOURCE, WRITE, ("Failed to create output image buffer of %dx%d pixels", evaspixmapsink->evas_pixmap_buf->width, evaspixmapsink->evas_pixmap_buf->height),("XServer allocated buffer size did not match input buffer"));
3365 gst_evaspixmap_buffer_destroy (evaspixmapsink->evas_pixmap_buf);
3366 evaspixmapsink->evas_pixmap_buf = NULL;
3371 switch (evaspixmapsink->evas_pixmap_buf->im_format) {
3372 /* Cases for specified formats of Samsung extension */
3373 case GST_MAKE_FOURCC('S', 'T', '1', '2'):
3374 case GST_MAKE_FOURCC('S', 'N', '1', '2'):
3375 case GST_MAKE_FOURCC('S', '4', '2', '0'):
3376 case GST_MAKE_FOURCC('S', 'U', 'Y', '2'):
3377 case GST_MAKE_FOURCC('S', 'U', 'Y', 'V'):
3378 case GST_MAKE_FOURCC('S', 'Y', 'V', 'Y'):
3379 case GST_MAKE_FOURCC('I', 'T', 'L', 'V'):
3380 case GST_MAKE_FOURCC('S', 'R', '3', '2'):
3382 GST_DEBUG_OBJECT (evaspixmapsink,"Samsung extension display format activated. fourcc:%d", evaspixmapsink->evas_pixmap_buf->im_format);
3384 if (evaspixmapsink->evas_pixmap_buf->xvimage->data) {
3385 img_data = (XV_DATA_PTR) evaspixmapsink->evas_pixmap_buf->xvimage->data;
3386 XV_INIT_DATA(img_data);
3387 scmn_imgb = (SCMN_IMGB *)GST_BUFFER_MALLOCDATA(buf);
3388 if (scmn_imgb == NULL) {
3389 GST_DEBUG_OBJECT (evaspixmapsink, "scmn_imgb is NULL. Skip buffer put..." );
3393 if (scmn_imgb->buf_share_method == BUF_SHARE_METHOD_PADDR) {
3394 img_data->YBuf = (unsigned int)scmn_imgb->p[0];
3395 img_data->CbBuf = (unsigned int)scmn_imgb->p[1];
3396 img_data->CrBuf = (unsigned int)scmn_imgb->p[2];
3397 img_data->BufType = XV_BUF_TYPE_LEGACY;
3399 } else if (scmn_imgb->buf_share_method == BUF_SHARE_METHOD_FD) {
3400 /* set gem information to gem_info structure of handle and convert dma-buf fd into drm gem name */
3401 img_data->YBuf = drm_init_convert_dmabuf_gemname(evaspixmapsink, (int)scmn_imgb->dma_buf_fd[0]);
3402 img_data->CbBuf = drm_init_convert_dmabuf_gemname(evaspixmapsink, (int)scmn_imgb->dma_buf_fd[1]);
3403 img_data->CrBuf = drm_init_convert_dmabuf_gemname(evaspixmapsink, (int)scmn_imgb->dma_buf_fd[2]);
3404 img_data->BufType = XV_BUF_TYPE_DMABUF;
3405 if (evaspixmapsink->buf_shared_type != BUF_SHARE_METHOD_FD) {
3406 evaspixmapsink->buf_shared_type = BUF_SHARE_METHOD_FD;
3407 GST_WARNING_OBJECT (evaspixmapsink, "BUF SHARED TYPE : FD");
3410 } else if (scmn_imgb->buf_share_method == BUF_SHARE_METHOD_TIZEN_BUFFER) {
3411 img_data->bo[0] = scmn_imgb->bo[0];
3412 img_data->bo[1] = scmn_imgb->bo[1];
3413 img_data->bo[2] = scmn_imgb->bo[2];
3414 GST_DEBUG("TBM bo %p %p %p", img_data->bo[0], img_data->bo[1], img_data->bo[2]);
3416 if (img_data->bo[0]) {
3417 img_data->YBuf = tbm_init_convert_bo_gemname(evaspixmapsink, (tbm_bo)img_data->bo[0]);
3419 if (img_data->bo[1]) {
3420 img_data->CbBuf = tbm_init_convert_bo_gemname(evaspixmapsink, (tbm_bo)img_data->bo[1]);
3422 if (img_data->bo[2]) {
3423 img_data->CrBuf = tbm_init_convert_bo_gemname(evaspixmapsink, (tbm_bo)img_data->bo[2]);
3425 if (evaspixmapsink->buf_shared_type != BUF_SHARE_METHOD_TIZEN_BUFFER) {
3426 evaspixmapsink->buf_shared_type = BUF_SHARE_METHOD_TIZEN_BUFFER;
3427 GST_WARNING_OBJECT (evaspixmapsink, "BUF SHARED TYPE : TIZEN BUFFER");
3430 GST_WARNING_OBJECT (evaspixmapsink, "Not supported, buf_share_method(%d)", scmn_imgb->buf_share_method);
3433 if (!img_data->YBuf) {
3434 GST_WARNING_OBJECT (evaspixmapsink, "img_data->YBuf is NULL. skip buffer put..." );
3437 GST_LOG_OBJECT(evaspixmapsink, "YBuf[%d], CbBuf[%d], CrBuf[%d]",
3438 img_data->YBuf, img_data->CbBuf, img_data->CrBuf );
3440 GST_WARNING_OBJECT (evaspixmapsink, "xvimage->data is NULL. skip buffer put..." );
3447 if (evaspixmapsink->buf_shared_type != BUF_SHARE_METHOD_NONE) {
3448 evaspixmapsink->buf_shared_type = BUF_SHARE_METHOD_NONE;
3450 GST_DEBUG_OBJECT (evaspixmapsink,"Normal format activated. fourcc = %d", evaspixmapsink->evas_pixmap_buf->im_format);
3451 if(evaspixmapsink->need_combine_data == 1)
3453 gst_evaspixmapsink_combine_i420_scmn_data(evaspixmapsink, buf);
3457 memcpy (evaspixmapsink->evas_pixmap_buf->xvimage->data,
3458 GST_BUFFER_DATA (buf),
3459 MIN (GST_BUFFER_SIZE (buf), evaspixmapsink->evas_pixmap_buf->size));
3464 gst_evaspixmap_buffer_put (evaspixmapsink, evaspixmapsink->evas_pixmap_buf);
3468 if (GST_STATE(evaspixmapsink) < GST_STATE_PLAYING || log_warn_count < 20) {
3469 GST_WARNING_OBJECT (evaspixmapsink, "leave <<<" );
3477 /* No image available. That's very bad ! */
3478 GST_WARNING_OBJECT (evaspixmapsink,"could not create image");
3479 return GST_FLOW_ERROR;
3484 gst_evaspixmapsink_event (GstBaseSink *sink, GstEvent *event)
3486 GstEvasPixmapSink *evaspixmapsink = GST_EVASPIXMAPSINK (sink);
3488 switch (GST_EVENT_TYPE (event)) {
3489 case GST_EVENT_FLUSH_START:
3490 GST_DEBUG_OBJECT (evaspixmapsink,"GST_EVENT_FLUSH_START");
3492 case GST_EVENT_FLUSH_STOP:
3493 GST_DEBUG_OBJECT (evaspixmapsink,"GST_EVENT_FLUSH_STOP");
3498 if (GST_BASE_SINK_CLASS (parent_class)->event) {
3499 return GST_BASE_SINK_CLASS (parent_class)->event (sink, event);
3505 /* Interfaces stuff */
3508 gst_evaspixmapsink_interface_supported (GstImplementsInterface *iface, GType type)
3510 g_assert (type == GST_TYPE_NAVIGATION || type == GST_TYPE_COLOR_BALANCE || type == GST_TYPE_PROPERTY_PROBE);
3515 gst_evaspixmapsink_interface_init (GstImplementsInterfaceClass *klass)
3517 klass->supported = gst_evaspixmapsink_interface_supported;
3521 gst_evaspixmapsink_navigation_send_event (GstNavigation *navigation, GstStructure *structure)
3523 GstEvasPixmapSink *evaspixmapsink = GST_EVASPIXMAPSINK (navigation);
3527 if ((peer = gst_pad_get_peer (GST_VIDEO_SINK_PAD (evaspixmapsink)))) {
3529 GstVideoRectangle result;
3530 gdouble x, y, xscale = 1.0, yscale = 1.0;
3532 event = gst_event_new_navigation (structure);
3534 /* We take the flow_lock while we look at the window */
3535 g_mutex_lock (evaspixmapsink->flow_lock);
3537 for (i = 0; i < evaspixmapsink->num_of_pixmaps; i ++) {
3538 if (!evaspixmapsink->xpixmap[i]) {
3539 g_mutex_unlock (evaspixmapsink->flow_lock);
3544 memcpy (&result, &evaspixmapsink->render_rect, sizeof (GstVideoRectangle));
3546 g_mutex_unlock (evaspixmapsink->flow_lock);
3548 /* We calculate scaling using the original video frames geometry to include
3549 pixel aspect ratio scaling. */
3550 xscale = (gdouble) evaspixmapsink->video_width / result.w;
3551 yscale = (gdouble) evaspixmapsink->video_height / result.h;
3553 /* Converting pointer coordinates to the non scaled geometry */
3554 if (gst_structure_get_double (structure, "pointer_x", &x)) {
3555 x = MIN (x, result.x + result.w);
3556 x = MAX (x - result.x, 0);
3557 gst_structure_set (structure, "pointer_x", G_TYPE_DOUBLE,
3558 (gdouble) x * xscale, NULL);
3560 if (gst_structure_get_double (structure, "pointer_y", &y)) {
3561 y = MIN (y, result.y + result.h);
3562 y = MAX (y - result.y, 0);
3563 gst_structure_set (structure, "pointer_y", G_TYPE_DOUBLE,
3564 (gdouble) y * yscale, NULL);
3567 gst_pad_send_event (peer, event);
3568 gst_object_unref (peer);
3573 gst_evaspixmapsink_navigation_init (GstNavigationInterface *iface)
3575 iface->send_event = gst_evaspixmapsink_navigation_send_event;
3579 gst_evaspixmapsink_colorbalance_list_channels (GstColorBalance *balance)
3581 GstEvasPixmapSink *evaspixmapsink = GST_EVASPIXMAPSINK (balance);
3583 g_return_val_if_fail (GST_IS_EVASPIXMAPSINK (evaspixmapsink), NULL);
3585 if (evaspixmapsink->xcontext)
3586 return evaspixmapsink->xcontext->channels_list;
3592 gst_evaspixmapsink_colorbalance_set_value (GstColorBalance *balance, GstColorBalanceChannel *channel, gint value)
3594 GstEvasPixmapSink *evaspixmapsink = GST_EVASPIXMAPSINK (balance);
3596 g_return_if_fail (GST_IS_EVASPIXMAPSINK (evaspixmapsink));
3597 g_return_if_fail (channel->label != NULL);
3599 evaspixmapsink->cb_changed = TRUE;
3601 /* Normalize val to [-1000, 1000] */
3602 value = floor (0.5 + -1000 + 2000 * (value - channel->min_value) /
3603 (double) (channel->max_value - channel->min_value));
3605 if (g_ascii_strcasecmp (channel->label, "XV_HUE") == 0) {
3606 evaspixmapsink->hue = value;
3607 } else if (g_ascii_strcasecmp (channel->label, "XV_SATURATION") == 0) {
3608 evaspixmapsink->saturation = value;
3609 } else if (g_ascii_strcasecmp (channel->label, "XV_CONTRAST") == 0) {
3610 evaspixmapsink->contrast = value;
3611 } else if (g_ascii_strcasecmp (channel->label, "XV_BRIGHTNESS") == 0) {
3612 evaspixmapsink->brightness = value;
3614 g_warning ("got an unknown channel %s", channel->label);
3618 gst_evaspixmapsink_update_colorbalance (evaspixmapsink);
3622 gst_evaspixmapsink_colorbalance_get_value (GstColorBalance *balance, GstColorBalanceChannel *channel)
3624 GstEvasPixmapSink *evaspixmapsink = GST_EVASPIXMAPSINK (balance);
3627 g_return_val_if_fail (GST_IS_EVASPIXMAPSINK (evaspixmapsink), 0);
3628 g_return_val_if_fail (channel->label != NULL, 0);
3630 if (g_ascii_strcasecmp (channel->label, "XV_HUE") == 0) {
3631 value = evaspixmapsink->hue;
3632 } else if (g_ascii_strcasecmp (channel->label, "XV_SATURATION") == 0) {
3633 value = evaspixmapsink->saturation;
3634 } else if (g_ascii_strcasecmp (channel->label, "XV_CONTRAST") == 0) {
3635 value = evaspixmapsink->contrast;
3636 } else if (g_ascii_strcasecmp (channel->label, "XV_BRIGHTNESS") == 0) {
3637 value = evaspixmapsink->brightness;
3639 g_warning ("got an unknown channel %s", channel->label);
3642 /* Normalize val to [channel->min_value, channel->max_value] */
3643 value = channel->min_value + (channel->max_value - channel->min_value) * (value + 1000) / 2000;
3649 gst_evaspixmapsink_colorbalance_init (GstColorBalanceClass *iface)
3651 GST_COLOR_BALANCE_TYPE (iface) = GST_COLOR_BALANCE_HARDWARE;
3652 iface->list_channels = gst_evaspixmapsink_colorbalance_list_channels;
3653 iface->set_value = gst_evaspixmapsink_colorbalance_set_value;
3654 iface->get_value = gst_evaspixmapsink_colorbalance_get_value;
3657 static const GList *
3658 gst_evaspixmapsink_probe_get_properties (GstPropertyProbe *probe)
3660 GObjectClass *klass = G_OBJECT_GET_CLASS (probe);
3661 static GList *list = NULL;
3664 list = g_list_append (NULL, g_object_class_find_property (klass, "device"));
3665 list = g_list_append (list, g_object_class_find_property (klass, "autopaint-colorkey"));
3666 list = g_list_append (list, g_object_class_find_property (klass, "double-buffer"));
3667 list = g_list_append (list, g_object_class_find_property (klass, "colorkey"));
3674 gst_evaspixmapsink_probe_probe_property (GstPropertyProbe *probe, guint prop_id, const GParamSpec *pspec)
3676 GstEvasPixmapSink *evaspixmapsink = GST_EVASPIXMAPSINK (probe);
3680 case PROP_AUTOPAINT_COLORKEY:
3681 case PROP_DOUBLE_BUFFER:
3683 GST_DEBUG_OBJECT (evaspixmapsink,"probing device list and get capabilities");
3684 if (!evaspixmapsink->xcontext) {
3685 GST_DEBUG_OBJECT (evaspixmapsink,"generating xcontext");
3686 evaspixmapsink->xcontext = gst_evaspixmapsink_xcontext_get (evaspixmapsink);
3687 if (!evaspixmapsink->xcontext) {
3688 GST_ERROR_OBJECT (evaspixmapsink,"could not get xcontext..");
3693 G_OBJECT_WARN_INVALID_PROPERTY_ID (probe, prop_id, pspec);
3699 gst_evaspixmapsink_probe_needs_probe (GstPropertyProbe *probe, guint prop_id, const GParamSpec *pspec)
3701 GstEvasPixmapSink *evaspixmapsink = GST_EVASPIXMAPSINK (probe);
3702 gboolean ret = FALSE;
3706 case PROP_AUTOPAINT_COLORKEY:
3707 case PROP_DOUBLE_BUFFER:
3709 if (evaspixmapsink->xcontext != NULL) {
3716 G_OBJECT_WARN_INVALID_PROPERTY_ID (probe, prop_id, pspec);
3723 static GValueArray *
3724 gst_evaspixmapsink_probe_get_values (GstPropertyProbe *probe, guint prop_id, const GParamSpec *pspec)
3726 GstEvasPixmapSink *evaspixmapsink = GST_EVASPIXMAPSINK (probe);
3727 GValueArray *array = NULL;
3729 if (G_UNLIKELY (!evaspixmapsink->xcontext)) {
3730 GST_WARNING_OBJECT (evaspixmapsink,"we don't have any xcontext, can't "
3739 GValue value = { 0 };
3741 array = g_value_array_new (evaspixmapsink->xcontext->nb_adaptors);
3742 g_value_init (&value, G_TYPE_STRING);
3744 for (i = 0; i < evaspixmapsink->xcontext->nb_adaptors; i++) {
3745 gchar *adaptor_id_s = g_strdup_printf ("%u", i);
3747 g_value_set_string (&value, adaptor_id_s);
3748 g_value_array_append (array, &value);
3749 g_free (adaptor_id_s);
3751 g_value_unset (&value);
3754 case PROP_AUTOPAINT_COLORKEY:
3755 if (evaspixmapsink->have_autopaint_colorkey) {
3756 GValue value = { 0 };
3758 array = g_value_array_new (2);
3759 g_value_init (&value, G_TYPE_BOOLEAN);
3760 g_value_set_boolean (&value, FALSE);
3761 g_value_array_append (array, &value);
3762 g_value_set_boolean (&value, TRUE);
3763 g_value_array_append (array, &value);
3764 g_value_unset (&value);
3767 case PROP_DOUBLE_BUFFER:
3768 if (evaspixmapsink->have_double_buffer) {
3769 GValue value = { 0 };
3771 array = g_value_array_new (2);
3772 g_value_init (&value, G_TYPE_BOOLEAN);
3773 g_value_set_boolean (&value, FALSE);
3774 g_value_array_append (array, &value);
3775 g_value_set_boolean (&value, TRUE);
3776 g_value_array_append (array, &value);
3777 g_value_unset (&value);
3781 if (evaspixmapsink->have_colorkey) {
3782 GValue value = { 0 };
3784 array = g_value_array_new (1);
3785 g_value_init (&value, GST_TYPE_INT_RANGE);
3786 gst_value_set_int_range (&value, 0, 0xffffff);
3787 g_value_array_append (array, &value);
3788 g_value_unset (&value);
3792 G_OBJECT_WARN_INVALID_PROPERTY_ID (probe, prop_id, pspec);
3801 gst_evaspixmapsink_property_probe_interface_init (GstPropertyProbeInterface *iface)
3803 iface->get_properties = gst_evaspixmapsink_probe_get_properties;
3804 iface->probe_property = gst_evaspixmapsink_probe_probe_property;
3805 iface->needs_probe = gst_evaspixmapsink_probe_needs_probe;
3806 iface->get_values = gst_evaspixmapsink_probe_get_values;
3810 gst_evaspixmapsink_xpixmap_link (GstEvasPixmapSink *evaspixmapsink)
3813 Pixmap *pixmap_id[NUM_OF_PIXMAP];
3814 int evas_object_width = 0;
3815 int evas_object_height = 0;
3816 int pixmap_width = 0;
3817 int pixmap_height = 0;
3818 unsigned int xw = 0;
3819 unsigned int xh = 0;
3821 XGCValues gc_values_black;
3822 gc_values_black.foreground = 0xff000000;
3825 char file_name[128];
3830 GST_DEBUG_OBJECT (evaspixmapsink,"[START]");
3832 if (!evaspixmapsink) {
3833 GST_ERROR_OBJECT (evaspixmapsink,"could not get evaspixmapsink..");
3836 g_mutex_lock (evaspixmapsink->flow_lock);
3838 /* Set xcontext and display */
3839 if (!evaspixmapsink->xcontext) {
3840 GST_WARNING_OBJECT (evaspixmapsink,"there's no xcontext, try to get one..");
3841 evaspixmapsink->xcontext = gst_evaspixmapsink_xcontext_get (evaspixmapsink);
3842 if (!evaspixmapsink->xcontext) {
3843 GST_ERROR_OBJECT (evaspixmapsink,"could not get xcontext..");
3844 g_mutex_unlock (evaspixmapsink->flow_lock);
3849 /* Set evas image object size */
3850 evas_object_geometry_get(evaspixmapsink->eo, NULL, NULL, &evas_object_width, &evas_object_height);
3852 /* check if it is redundant request */
3853 for (i = 0; i < evaspixmapsink->num_of_pixmaps; i++) {
3854 if (evaspixmapsink->xpixmap[i]) {
3855 if (!evaspixmapsink->use_origin_size && evaspixmapsink->xpixmap[i]->width && evaspixmapsink->xpixmap[i]->height) {
3856 if (evaspixmapsink->xpixmap[i]->width == evas_object_width && evaspixmapsink->xpixmap[i]->height == evas_object_height) {
3857 GST_WARNING_OBJECT (evaspixmapsink,"pixmap was already created(w:%d, h:%d), skip it..",
3858 evaspixmapsink->xpixmap[i]->width, evaspixmapsink->xpixmap[i]->height);
3859 if (evaspixmapsink->need_to_fill_black) {
3860 for (i = 0; i < evaspixmapsink->num_of_pixmaps; i++) {
3861 g_mutex_lock (evaspixmapsink->x_lock);
3862 XFillRectangle (evaspixmapsink->xcontext->disp, evaspixmapsink->xpixmap[i]->pixmap, evaspixmapsink->xpixmap[i]->gc,
3863 0, 0, evaspixmapsink->xpixmap[i]->width, evaspixmapsink->xpixmap[i]->height);
3864 GST_LOG_OBJECT (evaspixmapsink,"fill black to xpixmap[%d] with size(w:%d,h:%d)", evaspixmapsink->xpixmap[i]->pixmap,
3865 evaspixmapsink->xpixmap[i]->width, evaspixmapsink->xpixmap[i]->height);
3867 dump_w = evaspixmapsink->xpixmap[i]->width + (32 - (evaspixmapsink->xpixmap[i]->width%32)); // for multiples of 32
3870 evaspixmapsink->pixmap_addr[i] = gst_evaspixmapsink_get_buffer(evaspixmapsink->xcontext->disp, evaspixmapsink->xpixmap[i]->pixmap, dump_w, evaspixmapsink->xpixmap[i]->height, i);
3871 GST_ERROR("<DUMP_%2.2d> pixmap[%d] addr %p (w : %d, h : %d)", g_cnt, i, evaspixmapsink->pixmap_addr[i], dump_w, evaspixmapsink->xpixmap[i]->height);
3872 sprintf(file_name, "/opt/usr/media/DUMP_%2.2d.dump", g_cnt);
3874 dump_data = g_malloc(dump_w * evaspixmapsink->xpixmap[i]->height * 4);
3875 memcpy (dump_data, evaspixmapsink->pixmap_addr[i], dump_w * evaspixmapsink->xpixmap[i]->height * 4);
3877 ret = util_write_rawdata(file_name, dump_data, dump_w * evaspixmapsink->xpixmap[i]->height * 4);
3879 GST_ERROR_OBJECT (evaspixmapsink, "util_write_rawdata() failed");
3886 gst_evaspixmapsink_free_buffer (i);
3887 g_bufinfo[i] = NULL;
3889 evaspixmapsink->pixmap_addr[i] = NULL;
3892 g_mutex_unlock (evaspixmapsink->x_lock);
3894 evaspixmapsink->need_to_fill_black = FALSE;
3902 dpy = evaspixmapsink->xcontext->disp;
3904 if (evaspixmapsink->use_origin_size || !evas_object_width || !evas_object_height) {
3905 pixmap_width = evaspixmapsink->video_width;
3906 pixmap_height = evaspixmapsink->video_height;
3907 GST_INFO_OBJECT (evaspixmapsink,"set size to media src size(%dx%d)", pixmap_width, pixmap_height);
3910 g_mutex_lock (evaspixmapsink->x_lock);
3911 evaspixmapsink->sizediff_width = 0;
3912 evaspixmapsink->sizediff_height = 0;
3913 if (evaspixmapsink->use_origin_size || !evas_object_width || !evas_object_height) {
3914 XvQueryBestSize(dpy, evaspixmapsink->xcontext->xv_port_id,0,0,0, pixmap_width, pixmap_height, &xw, &xh);
3915 if (!evas_object_width || !evas_object_height) {
3916 evaspixmapsink->w = xw;
3917 evaspixmapsink->h = xh;
3919 evaspixmapsink->w = evas_object_width;
3920 evaspixmapsink->h = evas_object_height;
3922 GST_DEBUG_OBJECT (evaspixmapsink,"XvQueryBestSize : xv_port_id(%d), w(%d),h(%d) => xw(%d),xh(%d)", evaspixmapsink->xcontext->xv_port_id, pixmap_width, pixmap_height, xw, xh);
3924 XvQueryBestSize(dpy, evaspixmapsink->xcontext->xv_port_id,0,0,0, evas_object_width, evas_object_height, &xw, &xh);
3925 GST_DEBUG_OBJECT (evaspixmapsink,"XvQueryBestSize : xv_port_id(%d), w(%d),h(%d) => xw(%d),xh(%d)", evaspixmapsink->xcontext->xv_port_id, evas_object_width, evas_object_height, xw, xh);
3926 evaspixmapsink->w = xw;
3927 evaspixmapsink->h = xh;
3928 /* update difference of size information (between evas image object's and pixmap's) */
3929 evaspixmapsink->sizediff_width = xw - evas_object_width;
3930 evaspixmapsink->sizediff_height = xh - evas_object_height;
3933 /* create xpixmap structure */
3934 for (i = 0; i < evaspixmapsink->num_of_pixmaps; i++) {
3935 if (!evaspixmapsink->xpixmap[i]) {
3936 /* xpixmap can be created in this function only */
3937 evaspixmapsink->xpixmap[i] = g_new0 (GstXPixmap, 1);
3938 if(!evaspixmapsink->xpixmap[i]) {
3939 GST_ERROR_OBJECT (evaspixmapsink,"xpixmap is not valid..");
3941 for (j = 0; j < i; j++) {
3942 g_free(evaspixmapsink->xpixmap[j]);
3944 goto GO_OUT_OF_FUNC;
3951 GST_WARNING_OBJECT (evaspixmapsink,"skip creating pixmap..xw(%d),xh(%d)",xw,xh);
3952 goto GO_OUT_OF_FUNC;
3954 /* multiple pixmaps creation */
3955 for (i = 0; i < evaspixmapsink->num_of_pixmaps; i++) {
3956 pixmap_id[i] = XCreatePixmap(dpy, DefaultRootWindow(dpy), xw, xh, DefaultDepth(dpy, DefaultScreen(dpy)));
3957 if ( (int)pixmap_id[i] == BadAlloc || (int)pixmap_id[i] == BadDrawable || (int)pixmap_id[i] == BadValue ) {
3958 GST_ERROR_OBJECT (evaspixmapsink,"pixmap[%d] allocation error..", i);
3960 for (j = 0; j < i; j++) {
3961 XFreePixmap(dpy, pixmap_id[j]);
3963 goto GO_OUT_OF_FUNC;
3965 evaspixmapsink->need_to_fill_black = FALSE;
3966 GST_INFO_OBJECT (evaspixmapsink,"creation pixmap_id[%d]:%d success", i, pixmap_id[i]);
3967 GST_DEBUG_OBJECT (evaspixmapsink,"evas_object_width(%d),evas_object_height(%d),pixmap:%d,depth:%d",
3968 evas_object_width,evas_object_height,pixmap_id[i],DefaultDepth(dpy, DefaultScreen(dpy)));
3972 for (i = 0; i < evaspixmapsink->num_of_pixmaps; i++) {
3973 if (evaspixmapsink->xpixmap[i]->pixmap && pixmap_id[i] != evaspixmapsink->xpixmap[i]->pixmap) {
3974 g_mutex_unlock (evaspixmapsink->x_lock);
3975 g_mutex_lock (evaspixmapsink->pixmap_ref_lock);
3977 /* If we reset another pixmap, do below */
3978 if (evaspixmapsink->xpixmap[i]->prev_pixmap) {
3979 GST_LOG_OBJECT (evaspixmapsink,"Free pixmap(%d), gc(%x), destroy previous damage(%d)",
3980 evaspixmapsink->xpixmap[i]->prev_pixmap, evaspixmapsink->xpixmap[i]->prev_gc, evaspixmapsink->prev_damage[i]);
3981 g_mutex_lock (evaspixmapsink->x_lock);
3982 XFreePixmap(evaspixmapsink->xcontext->disp, evaspixmapsink->xpixmap[i]->prev_pixmap);
3983 XFreeGC (evaspixmapsink->xcontext->disp, evaspixmapsink->xpixmap[i]->prev_gc);
3984 XDamageDestroy(evaspixmapsink->xcontext->disp, evaspixmapsink->prev_damage[i]);
3985 XSync(evaspixmapsink->xcontext->disp, FALSE);
3986 g_mutex_unlock (evaspixmapsink->x_lock);
3987 evaspixmapsink->prev_damage[i] = NULL;
3989 evaspixmapsink->xpixmap[i]->prev_pixmap = evaspixmapsink->xpixmap[i]->pixmap;
3990 evaspixmapsink->xpixmap[i]->prev_gc = evaspixmapsink->xpixmap[i]->gc;
3991 evaspixmapsink->xpixmap[i]->pixmap = 0;
3992 evaspixmapsink->xpixmap[i]->ref = 0;
3993 evaspixmapsink->xpixmap[i]->damaged_time = 0;
3995 g_mutex_unlock (evaspixmapsink->pixmap_ref_lock);
3996 g_mutex_lock (evaspixmapsink->x_lock);
4000 for (i = 0; i < evaspixmapsink->num_of_pixmaps; i++) {
4001 /* Set pixmap id and create GC */
4002 evaspixmapsink->xpixmap[i]->pixmap = pixmap_id[i];
4003 evaspixmapsink->xpixmap[i]->gc = XCreateGC(dpy, evaspixmapsink->xpixmap[i]->pixmap, GCForeground, &gc_values_black);
4004 evaspixmapsink->xpixmap[i]->width = xw;
4005 evaspixmapsink->xpixmap[i]->height = xh;
4007 /* Create XDamage */
4008 if (evaspixmapsink->damage[i]) {
4009 evaspixmapsink->prev_damage[i] = evaspixmapsink->damage[i];
4011 evaspixmapsink->damage[i] = XDamageCreate (dpy, evaspixmapsink->xpixmap[i]->pixmap, XDamageReportRawRectangles);
4013 GST_WARNING_OBJECT (evaspixmapsink,"xpixmap[%d]->(pixmap:%d,gc:%p), damage[%d]:%d",
4014 i, evaspixmapsink->xpixmap[i]->pixmap, evaspixmapsink->xpixmap[i]->gc, i, evaspixmapsink->damage[i]);
4016 /* Fill blackcolor for the new pixmap */
4017 XFillRectangle (evaspixmapsink->xcontext->disp, pixmap_id[i], evaspixmapsink->xpixmap[i]->gc,
4018 0, 0, evaspixmapsink->w, evaspixmapsink->h);
4019 GST_LOG_OBJECT (evaspixmapsink,"fill black to xpixmap[%d] with size(w:%d,h:%d)", pixmap_id[i],
4020 evaspixmapsink->w, evaspixmapsink->h);
4023 dump_w = evaspixmapsink->w + (32 - (evaspixmapsink->w%32)); // for multiples of 32
4026 evaspixmapsink->pixmap_addr[i] = gst_evaspixmapsink_get_buffer(evaspixmapsink->xcontext->disp, evaspixmapsink->xpixmap[i]->pixmap, dump_w, evaspixmapsink->h, i);
4027 GST_ERROR("<DUMP_%2.2d> pixmap[%d] addr %p (w : %d, h : %d)", g_cnt, i, evaspixmapsink->pixmap_addr[i], dump_w, evaspixmapsink->h);
4028 sprintf(file_name, "/opt/usr/media/DUMP_%2.2d.dump", g_cnt);
4030 dump_data = g_malloc(dump_w * evaspixmapsink->h * 4);
4031 memcpy (dump_data, evaspixmapsink->pixmap_addr[i], dump_w * evaspixmapsink->h * 4);
4033 ret = util_write_rawdata(file_name, dump_data, dump_w * evaspixmapsink->h * 4);
4035 GST_ERROR_OBJECT (evaspixmapsink, "util_write_rawdata() failed");
4042 gst_evaspixmapsink_free_buffer (i);
4043 g_bufinfo[i] = NULL;
4045 evaspixmapsink->pixmap_addr[i] = NULL;
4052 /* Set flag for mapping evas object with xpixmap */
4053 evaspixmapsink->do_link = TRUE;
4054 if (evaspixmapsink->epipe_request_count > EPIPE_REQUEST_LIMIT) {
4055 GST_WARNING_OBJECT (evaspixmapsink,"epipe_request_count(%d), skip ecore_pipe_write()", evaspixmapsink->epipe_request_count);
4057 ecore_pipe_write(evaspixmapsink->epipe, evaspixmapsink, sizeof(GstEvasPixmapSink));
4058 evaspixmapsink->epipe_request_count++;
4061 gst_evaspixmapsink_update_colorbalance (evaspixmapsink);
4063 g_mutex_unlock (evaspixmapsink->x_lock);
4067 g_mutex_lock (evaspixmapsink->pixmap_ref_lock);
4068 evaspixmapsink->last_updated_idx = -1;
4069 g_mutex_unlock (evaspixmapsink->pixmap_ref_lock);
4071 g_mutex_unlock (evaspixmapsink->flow_lock);
4073 GST_DEBUG_OBJECT (evaspixmapsink,"[END]");
4078 g_mutex_unlock (evaspixmapsink->x_lock);
4079 g_mutex_unlock (evaspixmapsink->flow_lock);
4084 gst_evaspixmapsink_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
4086 GstEvasPixmapSink *evaspixmapsink;
4087 g_return_if_fail (GST_IS_EVASPIXMAPSINK (object));
4088 evaspixmapsink = GST_EVASPIXMAPSINK (object);
4092 evaspixmapsink->hue = g_value_get_int (value);
4093 evaspixmapsink->cb_changed = TRUE;
4094 gst_evaspixmapsink_update_colorbalance (evaspixmapsink);
4097 evaspixmapsink->contrast = g_value_get_int (value);
4098 evaspixmapsink->cb_changed = TRUE;
4099 gst_evaspixmapsink_update_colorbalance (evaspixmapsink);
4101 case PROP_BRIGHTNESS:
4102 evaspixmapsink->brightness = g_value_get_int (value);
4103 evaspixmapsink->cb_changed = TRUE;
4104 gst_evaspixmapsink_update_colorbalance (evaspixmapsink);
4106 case PROP_SATURATION:
4107 evaspixmapsink->saturation = g_value_get_int (value);
4108 evaspixmapsink->cb_changed = TRUE;
4109 gst_evaspixmapsink_update_colorbalance (evaspixmapsink);
4112 evaspixmapsink->display_name = g_strdup (g_value_get_string (value));
4114 case PROP_SYNCHRONOUS:
4115 evaspixmapsink->synchronous = g_value_get_boolean (value);
4116 if (evaspixmapsink->xcontext) {
4117 g_mutex_lock (evaspixmapsink->x_lock);
4118 XSynchronize (evaspixmapsink->xcontext->disp, evaspixmapsink->synchronous);
4119 g_mutex_unlock (evaspixmapsink->x_lock);
4120 GST_DEBUG_OBJECT (evaspixmapsink,"XSynchronize called with %s", evaspixmapsink->synchronous ? "TRUE" : "FALSE");
4123 case PROP_PIXEL_ASPECT_RATIO:
4124 g_free (evaspixmapsink->par);
4125 evaspixmapsink->par = g_new0 (GValue, 1);
4126 g_value_init (evaspixmapsink->par, GST_TYPE_FRACTION);
4127 if (!g_value_transform (value, evaspixmapsink->par)) {
4128 g_warning ("Could not transform string to aspect ratio");
4129 gst_value_set_fraction (evaspixmapsink->par, 1, 1);
4131 GST_DEBUG_OBJECT (evaspixmapsink,"set PAR to %d/%d", gst_value_get_fraction_numerator (evaspixmapsink->par), gst_value_get_fraction_denominator (evaspixmapsink->par));
4134 evaspixmapsink->adaptor_no = atoi (g_value_get_string (value));
4136 case PROP_DOUBLE_BUFFER:
4137 evaspixmapsink->double_buffer = g_value_get_boolean (value);
4139 case PROP_AUTOPAINT_COLORKEY:
4140 evaspixmapsink->autopaint_colorkey = g_value_get_boolean (value);
4143 evaspixmapsink->colorkey = g_value_get_int (value);
4145 case PROP_PIXMAP_WIDTH:
4147 /* To do : code related to pixmap re-link */
4148 GST_LOG_OBJECT (evaspixmapsink, "Not supported");
4151 case PROP_PIXMAP_HEIGHT:
4153 /* To do : code related to pixmap re-link */
4154 GST_LOG_OBJECT (evaspixmapsink, "Not supported");
4157 case PROP_DISPLAY_GEOMETRY_METHOD:
4159 guint new_val = g_value_get_enum (value);
4160 if (evaspixmapsink->display_geometry_method != new_val) {
4161 evaspixmapsink->display_geometry_method = new_val;
4162 GST_INFO_OBJECT (evaspixmapsink,"Overlay geometry method update, display_geometry_method(%d)",evaspixmapsink->display_geometry_method);
4163 if( evaspixmapsink->display_geometry_method != DISP_GEO_METHOD_FULL_SCREEN &&
4164 evaspixmapsink->display_geometry_method != DISP_GEO_METHOD_CROPPED_FULL_SCREEN ) {
4165 if( evaspixmapsink->xcontext ) {
4166 g_mutex_lock( evaspixmapsink->flow_lock );
4168 for (i = 0; i < evaspixmapsink->num_of_pixmaps; i++) {
4169 if (evaspixmapsink->xpixmap[i]) {
4170 gst_evaspixmapsink_xpixmap_clear (evaspixmapsink, evaspixmapsink->xpixmap[i]);
4173 g_mutex_unlock( evaspixmapsink->flow_lock );
4176 if (evaspixmapsink->xcontext) {
4177 gst_evaspixmap_buffer_put (evaspixmapsink, evaspixmapsink->evas_pixmap_buf);
4182 case PROP_DST_ROI_X:
4183 evaspixmapsink->dst_roi.x = g_value_get_int (value);
4184 GST_INFO_OBJECT (evaspixmapsink, "ROI_X(%d)",evaspixmapsink->dst_roi.x );
4186 case PROP_DST_ROI_Y:
4187 evaspixmapsink->dst_roi.y = g_value_get_int (value);
4188 GST_INFO_OBJECT (evaspixmapsink, "ROI_Y(%d)",evaspixmapsink->dst_roi.y );
4190 case PROP_DST_ROI_W:
4191 evaspixmapsink->dst_roi.w = g_value_get_int (value);
4192 GST_INFO_OBJECT (evaspixmapsink, "ROI_W(%d)",evaspixmapsink->dst_roi.w );
4194 case PROP_DST_ROI_H:
4195 evaspixmapsink->dst_roi.h = g_value_get_int (value);
4196 GST_INFO_OBJECT (evaspixmapsink, "ROI_H(%d)",evaspixmapsink->dst_roi.h );
4198 case PROP_STOP_VIDEO:
4199 evaspixmapsink->stop_video = g_value_get_int (value);
4200 g_mutex_lock( evaspixmapsink->flow_lock );
4201 if( evaspixmapsink->stop_video ) {
4202 GST_INFO_OBJECT (evaspixmapsink, "XPixmap CLEAR when set video-stop property" );
4204 for (i = 0; i < evaspixmapsink->num_of_pixmaps; i++) {
4205 if (evaspixmapsink->xpixmap[i]) {
4206 gst_evaspixmapsink_xpixmap_clear (evaspixmapsink, evaspixmapsink->xpixmap[i]);
4210 GST_INFO_OBJECT (evaspixmapsink, "video-stop property(%d)", evaspixmapsink->stop_video);
4212 g_mutex_unlock( evaspixmapsink->flow_lock );
4214 case PROP_EVAS_OBJECT:
4216 Evas_Object *eo = g_value_get_pointer (value);
4217 if ( is_evas_image_object (eo)) {
4218 if (!evaspixmapsink->epipe) {
4219 evaspixmapsink->epipe = ecore_pipe_add (ecore_pipe_callback_handler, evaspixmapsink);
4220 if (!evaspixmapsink->epipe) {
4221 GST_ERROR_OBJECT (evaspixmapsink,"Cannot set evas-object property: ecore_pipe_add() failed");
4225 if (evaspixmapsink->eo == NULL) {
4226 evaspixmapsink->eo = eo;
4227 /* add evas object callbacks on a new evas image object */
4228 EVASPIXMAPSINK_SET_EVAS_OBJECT_EVENT_CALLBACK (eo, evaspixmapsink);
4229 if (GST_STATE(evaspixmapsink) < GST_STATE_PAUSED) {
4230 GST_INFO_OBJECT (evaspixmapsink,"It's the first time the new evas image object(%x) is set, skip gst_evaspixmapsink_xpixmap_link()..", eo);
4233 if (!gst_evaspixmapsink_xpixmap_link(evaspixmapsink)) {
4234 GST_WARNING_OBJECT (evaspixmapsink,"link evas image object with pixmap failed...");
4235 evaspixmapsink->eo = NULL;
4240 if (eo == evaspixmapsink->eo) {
4241 GST_LOG_OBJECT (evaspixmapsink,"new evas image object(%x) is same as the previous one(%x)", eo, evaspixmapsink->eo);
4243 GST_INFO_OBJECT (evaspixmapsink,"new evas image object(%x), previous one(%x)", eo, evaspixmapsink->eo);
4244 /* delete evas object callbacks registrated on a former evas image object */
4245 EVASPIXMAPSINK_UNSET_EVAS_OBJECT_EVENT_CALLBACK (evaspixmapsink->eo);
4246 evaspixmapsink->eo = eo;
4247 if (!gst_evaspixmapsink_xpixmap_link(evaspixmapsink)) {
4248 GST_WARNING_OBJECT (evaspixmapsink,"link evas image object with pixmap failed...");
4249 evaspixmapsink->eo = NULL;
4252 /* add evas object callbacks on a new evas image object */
4253 EVASPIXMAPSINK_SET_EVAS_OBJECT_EVENT_CALLBACK (eo, evaspixmapsink);
4255 GST_INFO_OBJECT (evaspixmapsink,"Evas image object(%x) is set", evaspixmapsink->eo);
4257 GST_ERROR_OBJECT (evaspixmapsink,"Cannot set evas-object property: value is not an evas image object");
4262 evaspixmapsink->flip = g_value_get_enum(value);
4264 case PROP_ROTATE_ANGLE:
4265 evaspixmapsink->rotate_angle = g_value_get_enum (value);
4269 Eina_Bool r = EINA_FALSE;
4270 gboolean visible = g_value_get_boolean (value);
4271 GST_INFO_OBJECT (evaspixmapsink,"evaspixmapsink->visible(%d), new value of visible(%d)", evaspixmapsink->visible, visible);
4272 if (evaspixmapsink->visible != visible) {
4273 evaspixmapsink->visible = visible;
4274 if (evaspixmapsink->eo) {
4275 evaspixmapsink->update_visibility = UPDATE_TRUE;
4276 if (evaspixmapsink->epipe_request_count > EPIPE_REQUEST_LIMIT) {
4277 GST_WARNING_OBJECT (evaspixmapsink,"skip ecore_pipe_write()", evaspixmapsink->epipe_request_count);
4279 evas_object_show(evaspixmapsink->eo);
4280 GST_WARNING_OBJECT (evaspixmapsink, "object show (forcely)");
4283 r = ecore_pipe_write (evaspixmapsink->epipe, &evaspixmapsink->update_visibility, SIZE_FOR_UPDATE_VISIBILITY);
4284 if (r == EINA_FALSE) {
4285 GST_WARNING ("Failed to ecore_pipe_write() for updating visibility)\n");
4287 evaspixmapsink->epipe_request_count++;
4292 g_mutex_lock( evaspixmapsink->flow_lock );
4293 for (i = 0; i < evaspixmapsink->num_of_pixmaps; i++) {
4294 if (evaspixmapsink->xpixmap[i]) {
4295 gst_evaspixmapsink_xpixmap_clear (evaspixmapsink, evaspixmapsink->xpixmap[i]);
4298 evas_object_hide(evaspixmapsink->eo);
4299 GST_INFO_OBJECT (evaspixmapsink, "object hide (forcely)");
4300 g_mutex_unlock( evaspixmapsink->flow_lock );
4302 gst_evaspixmap_buffer_put (evaspixmapsink, evaspixmapsink->evas_pixmap_buf);
4305 GST_WARNING_OBJECT (evaspixmapsink,"evas image object was not set");
4310 case PROP_ORIGIN_SIZE:
4311 evaspixmapsink->use_origin_size = g_value_get_boolean (value);
4312 GST_INFO_OBJECT (evaspixmapsink,"set origin-size (%d)",evaspixmapsink->use_origin_size);
4313 if (evaspixmapsink->previous_origin_size != evaspixmapsink->use_origin_size) {
4314 if (!gst_evaspixmapsink_xpixmap_link(evaspixmapsink)) {
4315 GST_WARNING_OBJECT (evaspixmapsink,"link evas image object with pixmap failed...");
4317 evaspixmapsink->previous_origin_size = evaspixmapsink->use_origin_size;
4321 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
4327 gst_evaspixmapsink_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
4329 GstEvasPixmapSink *evaspixmapsink;
4331 g_return_if_fail (GST_IS_EVASPIXMAPSINK (object));
4333 evaspixmapsink = GST_EVASPIXMAPSINK (object);
4337 g_value_set_int (value, evaspixmapsink->hue);
4340 g_value_set_int (value, evaspixmapsink->contrast);
4342 case PROP_BRIGHTNESS:
4343 g_value_set_int (value, evaspixmapsink->brightness);
4345 case PROP_SATURATION:
4346 g_value_set_int (value, evaspixmapsink->saturation);
4349 g_value_set_string (value, evaspixmapsink->display_name);
4351 case PROP_SYNCHRONOUS:
4352 g_value_set_boolean (value, evaspixmapsink->synchronous);
4354 case PROP_PIXEL_ASPECT_RATIO:
4355 if (evaspixmapsink->par) {
4356 if (!g_value_transform (evaspixmapsink->par, value)) {
4357 g_warning ("g_value_transform() failure");
4363 char *adaptor_no_s = g_strdup_printf ("%u", evaspixmapsink->adaptor_no);
4364 g_value_set_string (value, adaptor_no_s);
4365 g_free (adaptor_no_s);
4368 case PROP_DEVICE_NAME:
4369 if (evaspixmapsink->xcontext && evaspixmapsink->xcontext->adaptors) {
4370 g_value_set_string (value,
4371 evaspixmapsink->xcontext->adaptors[evaspixmapsink->adaptor_no]);
4373 g_value_set_string (value, NULL);
4376 case PROP_DOUBLE_BUFFER:
4377 g_value_set_boolean (value, evaspixmapsink->double_buffer);
4379 case PROP_AUTOPAINT_COLORKEY:
4380 g_value_set_boolean (value, evaspixmapsink->autopaint_colorkey);
4383 g_value_set_int (value, evaspixmapsink->colorkey);
4385 case PROP_PIXMAP_WIDTH:
4387 GST_LOG_OBJECT (evaspixmapsink, "Not supported");
4390 case PROP_PIXMAP_HEIGHT:
4392 GST_LOG_OBJECT (evaspixmapsink, "Not supported");
4395 case PROP_DISPLAY_GEOMETRY_METHOD:
4396 g_value_set_enum (value, evaspixmapsink->display_geometry_method);
4398 case PROP_DST_ROI_X:
4399 g_value_set_int (value, evaspixmapsink->dst_roi.x);
4401 case PROP_DST_ROI_Y:
4402 g_value_set_int (value, evaspixmapsink->dst_roi.y);
4404 case PROP_DST_ROI_W:
4405 g_value_set_int (value, evaspixmapsink->dst_roi.w);
4407 case PROP_DST_ROI_H:
4408 g_value_set_int (value, evaspixmapsink->dst_roi.h);
4410 case PROP_STOP_VIDEO:
4411 g_value_set_int (value, evaspixmapsink->stop_video);
4413 case PROP_EVAS_OBJECT:
4414 g_value_set_pointer (value, evaspixmapsink->eo);
4417 g_value_set_enum(value, evaspixmapsink->flip);
4419 case PROP_ROTATE_ANGLE:
4420 g_value_set_enum (value, evaspixmapsink->rotate_angle);
4423 g_value_set_boolean (value, evaspixmapsink->visible);
4425 case PROP_ORIGIN_SIZE:
4426 g_value_set_boolean (value, evaspixmapsink->use_origin_size);
4429 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
4435 gst_evaspixmapsink_reset (GstEvasPixmapSink *evaspixmapsink)
4437 GST_WARNING_OBJECT (evaspixmapsink,"[START]");
4440 GST_OBJECT_LOCK (evaspixmapsink);
4441 evaspixmapsink->running = FALSE;
4444 /* grab thread and mark it as NULL */
4445 thread = evaspixmapsink->event_thread;
4446 evaspixmapsink->event_thread = NULL;
4447 GST_OBJECT_UNLOCK (evaspixmapsink);
4449 /* Wait for our event thread to finish before we clean up our stuff. */
4451 g_thread_join (thread);
4454 for (i = 0; i < evaspixmapsink->num_of_pixmaps; i++) {
4455 if(evaspixmapsink->damage[i]) {
4456 g_mutex_lock (evaspixmapsink->x_lock);
4457 XDamageDestroy(evaspixmapsink->xcontext->disp, evaspixmapsink->damage[i]);
4458 g_mutex_unlock (evaspixmapsink->x_lock);
4459 evaspixmapsink->damage[i] = NULL;
4462 EVASPIXMAPSINK_UNSET_EVAS_OBJECT_EVENT_CALLBACK( evaspixmapsink->eo );
4464 if (evaspixmapsink->evas_pixmap_buf) {
4465 gst_buffer_unref (GST_BUFFER_CAST (evaspixmapsink->evas_pixmap_buf));
4466 evaspixmapsink->evas_pixmap_buf = NULL;
4469 for (i = 0; i < evaspixmapsink->num_of_pixmaps; i++) {
4472 gst_evaspixmapsink_free_buffer (i);
4473 g_bufinfo[i] = NULL;
4475 evaspixmapsink->pixmap_addr[i] = NULL;
4477 gst_evaspixmapsink_xpixmap_clear (evaspixmapsink, evaspixmapsink->xpixmap[i]);
4478 gst_evaspixmapsink_xpixmap_destroy (evaspixmapsink, evaspixmapsink->xpixmap[i]);
4479 evaspixmapsink->xpixmap[i] = NULL;
4481 if (evaspixmapsink->eo) {
4482 evas_object_image_native_surface_set(evaspixmapsink->eo, NULL);
4483 evas_object_image_data_set(evaspixmapsink->eo, NULL);
4484 evaspixmapsink->eo = NULL;
4487 if (evaspixmapsink->epipe) {
4488 ecore_pipe_del (evaspixmapsink->epipe);
4489 evaspixmapsink->epipe = NULL;
4492 evaspixmapsink->render_rect.x = evaspixmapsink->render_rect.y =
4493 evaspixmapsink->render_rect.w = evaspixmapsink->render_rect.h = 0;
4494 evaspixmapsink->have_render_rect = FALSE;
4496 evaspixmapsink->epipe_request_count = 0;
4498 gst_evaspixmapsink_xcontext_clear (evaspixmapsink);
4500 GST_WARNING_OBJECT (evaspixmapsink,"[END]");
4503 /* Finalize is called only once, dispose can be called multiple times.
4504 * We use mutexes and don't reset stuff to NULL here so let's register
4507 gst_evaspixmapsink_finalize (GObject *object)
4509 GstEvasPixmapSink *evaspixmapsink;
4510 evaspixmapsink = GST_EVASPIXMAPSINK (object);
4511 GST_DEBUG_OBJECT (evaspixmapsink,"[START]");
4513 if (evaspixmapsink->display_name) {
4514 g_free (evaspixmapsink->display_name);
4515 evaspixmapsink->display_name = NULL;
4517 if (evaspixmapsink->par) {
4518 g_free (evaspixmapsink->par);
4519 evaspixmapsink->par = NULL;
4521 if (evaspixmapsink->x_lock) {
4522 g_mutex_free (evaspixmapsink->x_lock);
4523 evaspixmapsink->x_lock = NULL;
4525 if (evaspixmapsink->flow_lock) {
4526 g_mutex_free (evaspixmapsink->flow_lock);
4527 evaspixmapsink->flow_lock = NULL;
4529 if (evaspixmapsink->pixmap_ref_lock) {
4530 g_mutex_free (evaspixmapsink->pixmap_ref_lock);
4531 evaspixmapsink->pixmap_ref_lock = NULL;
4534 GST_DEBUG_OBJECT (evaspixmapsink,"[END]");
4536 G_OBJECT_CLASS (parent_class)->finalize (object);
4541 gst_evaspixmapsink_init (GstEvasPixmapSink *evaspixmapsink)
4545 GST_DEBUG_OBJECT (evaspixmapsink,"[START]");
4547 evaspixmapsink->display_name = NULL;
4548 evaspixmapsink->adaptor_no = 0;
4549 evaspixmapsink->xcontext = NULL;
4551 for (i = 0; i < NUM_OF_PIXMAP; i++) {
4552 evaspixmapsink->xpixmap[i] = NULL;
4553 evaspixmapsink->damage[i] = 0;
4555 g_bufinfo[i] = NULL;
4556 evaspixmapsink->pixmap_addr[i] = NULL;
4560 evaspixmapsink->evas_pixmap_buf = NULL;
4562 evaspixmapsink->hue = evaspixmapsink->saturation = 0;
4563 evaspixmapsink->contrast = evaspixmapsink->brightness = 0;
4564 evaspixmapsink->cb_changed = FALSE;
4566 evaspixmapsink->fps_n = 0;
4567 evaspixmapsink->fps_d = 0;
4568 evaspixmapsink->video_width = 0;
4569 evaspixmapsink->video_height = 0;
4570 evaspixmapsink->need_to_fill_black = FALSE;
4572 evaspixmapsink->x_lock = g_mutex_new ();
4573 evaspixmapsink->flow_lock = g_mutex_new ();
4574 evaspixmapsink->pixmap_ref_lock = g_mutex_new();
4576 evaspixmapsink->synchronous = FALSE;
4577 evaspixmapsink->double_buffer = TRUE;
4578 evaspixmapsink->par = NULL;
4579 evaspixmapsink->autopaint_colorkey = TRUE;
4580 evaspixmapsink->running = FALSE;
4582 /* on 16bit displays this becomes r,g,b = 1,2,3
4583 * on 24bit displays this becomes r,g,b = 8,8,16
4584 * as a port atom value
4586 evaspixmapsink->colorkey = (8 << 16) | (8 << 8) | 16;
4588 evaspixmapsink->display_geometry_method = DEF_DISPLAY_GEOMETRY_METHOD;
4589 evaspixmapsink->dst_roi.x = 0;
4590 evaspixmapsink->dst_roi.y = 0;
4591 evaspixmapsink->dst_roi.w = 0;
4592 evaspixmapsink->dst_roi.h = 0;
4593 evaspixmapsink->scr_w = 0;
4594 evaspixmapsink->scr_h = 0;
4595 evaspixmapsink->aligned_width = 0;
4596 evaspixmapsink->aligned_height = 0;
4597 evaspixmapsink->stop_video = FALSE;
4598 evaspixmapsink->eo = NULL;
4599 evaspixmapsink->epipe = NULL;
4600 evaspixmapsink->epipe_request_count = 0;
4601 evaspixmapsink->do_link = FALSE;
4602 evaspixmapsink->flip = DEF_DISPLAY_FLIP;
4603 evaspixmapsink->rotate_angle = DEGREE_0;
4604 evaspixmapsink->visible = TRUE;
4605 evaspixmapsink->update_visibility = UPDATE_FALSE;
4606 evaspixmapsink->use_origin_size = FALSE;
4607 evaspixmapsink->previous_origin_size = FALSE;
4609 evaspixmapsink->num_of_pixmaps = NUM_OF_PIXMAP;
4611 evaspixmapsink->buf_shared_type = BUF_SHARE_METHOD_NONE;
4613 memset(&evaspixmapsink->src_prev, 0, sizeof (GstVideoRectangle));
4614 memset(&evaspixmapsink->result_prev, 0, sizeof (GstVideoRectangle));
4620 GST_DEBUG_OBJECT (evaspixmapsink,"[END]");
4624 gst_evaspixmapsink_base_init (gpointer g_class)
4626 GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
4628 gst_element_class_set_details_simple (element_class,
4629 "EvasPixmapSink", "Sink/Video",
4630 "evas image object videosink based on Xv extension", "Sangchul Lee <sc11.lee@samsung.com>");
4632 gst_element_class_add_pad_template (element_class,
4633 gst_static_pad_template_get (&gst_evaspixmapsink_sink_template_factory));
4637 gst_evaspixmapsink_class_init (GstEvasPixmapSinkClass *klass)
4639 GObjectClass *gobject_class;
4640 GstElementClass *gstelement_class;
4641 GstBaseSinkClass *gstbasesink_class;
4642 GstVideoSinkClass *videosink_class;
4644 gobject_class = (GObjectClass *) klass;
4645 gstelement_class = (GstElementClass *) klass;
4646 gstbasesink_class = (GstBaseSinkClass *) klass;
4647 videosink_class = (GstVideoSinkClass *) klass;
4649 parent_class = g_type_class_peek_parent (klass);
4651 gobject_class->set_property = gst_evaspixmapsink_set_property;
4652 gobject_class->get_property = gst_evaspixmapsink_get_property;
4654 g_object_class_install_property (gobject_class, PROP_CONTRAST,
4655 g_param_spec_int ("contrast", "Contrast", "The contrast of the video",
4656 -1000, 1000, 0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
4657 g_object_class_install_property (gobject_class, PROP_BRIGHTNESS,
4658 g_param_spec_int ("brightness", "Brightness",
4659 "The brightness of the video", -1000, 1000, 0,
4660 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
4661 g_object_class_install_property (gobject_class, PROP_HUE,
4662 g_param_spec_int ("hue", "Hue", "The hue of the video", -1000, 1000, 0,
4663 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
4664 g_object_class_install_property (gobject_class, PROP_SATURATION,
4665 g_param_spec_int ("saturation", "Saturation",
4666 "The saturation of the video", -1000, 1000, 0,
4667 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
4668 g_object_class_install_property (gobject_class, PROP_DISPLAY,
4669 g_param_spec_string ("display", "Display", "X Display name", NULL,
4670 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
4671 g_object_class_install_property (gobject_class, PROP_SYNCHRONOUS,
4672 g_param_spec_boolean ("synchronous", "Synchronous",
4673 "When enabled, runs "
4674 "the X display in synchronous mode. (used only for debugging)", FALSE,
4675 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
4676 g_object_class_install_property (gobject_class, PROP_PIXEL_ASPECT_RATIO,
4677 g_param_spec_string ("pixel-aspect-ratio", "Pixel Aspect Ratio",
4678 "The pixel aspect ratio of the device", "1/1",
4679 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
4680 g_object_class_install_property (gobject_class, PROP_DEVICE,
4681 g_param_spec_string ("device", "Adaptor number",
4682 "The number of the video adaptor", "0",
4683 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
4684 g_object_class_install_property (gobject_class, PROP_DEVICE_NAME,
4685 g_param_spec_string ("device-name", "Adaptor name",
4686 "The name of the video adaptor", NULL,
4687 G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
4690 * GstEvasPixmapSink:double-buffer
4692 * Whether to double-buffer the output.
4696 g_object_class_install_property (gobject_class, PROP_DOUBLE_BUFFER,
4697 g_param_spec_boolean ("double-buffer", "Double-buffer",
4698 "Whether to double-buffer the output", TRUE,
4699 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
4701 * GstEvasPixmapSink:autopaint-colorkey
4703 * Whether to autofill overlay with colorkey
4707 g_object_class_install_property (gobject_class, PROP_AUTOPAINT_COLORKEY,
4708 g_param_spec_boolean ("autopaint-colorkey", "Autofill with colorkey",
4709 "Whether to autofill overlay with colorkey", TRUE,
4710 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
4712 * GstEvasPixmapSink:colorkey
4714 * Color to use for the overlay mask.
4718 g_object_class_install_property (gobject_class, PROP_COLORKEY,
4719 g_param_spec_int ("colorkey", "Colorkey",
4720 "Color to use for the overlay mask", G_MININT, G_MAXINT, 0,
4721 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
4724 * GstEvasPixmapSink:pixmap-width
4726 * Actual width of the pixmap.
4728 g_object_class_install_property (gobject_class, PROP_PIXMAP_WIDTH,
4729 g_param_spec_uint64 ("pixmap-width", "pixmap-width", "Width of the pixmap", 0, G_MAXUINT64, 0, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
4732 * GstEvasPixmapSink:pixmap-height
4734 * Actual height of the pixmap.
4736 g_object_class_install_property (gobject_class, PROP_PIXMAP_HEIGHT,
4737 g_param_spec_uint64 ("pixmap-height", "pixmap-height", "Height of the pixmap", 0, G_MAXUINT64, 0, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
4740 * GstEvasPixmapSink:display-geometry-method
4742 * Display geometrical method setting
4744 g_object_class_install_property(gobject_class, PROP_DISPLAY_GEOMETRY_METHOD,
4745 g_param_spec_enum("display-geometry-method", "Display geometry method",
4746 "Geometrical method for display",
4747 GST_TYPE_EVASPIXMAPSINK_DISPLAY_GEOMETRY_METHOD, DEF_DISPLAY_GEOMETRY_METHOD,
4748 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
4751 * GstEvasPixmapSink:dst-roi-x
4753 * X value of Destination ROI
4755 g_object_class_install_property (gobject_class, PROP_DST_ROI_X,
4756 g_param_spec_int ("dst-roi-x", "Dst-ROI-X",
4757 "X value of Destination ROI(only effective \"CUSTOM_ROI\")", 0, XV_SCREEN_SIZE_WIDTH, 0,
4758 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
4761 * GstEvasPixmapSink:dst-roi-y
4763 * Y value of Destination ROI
4765 g_object_class_install_property (gobject_class, PROP_DST_ROI_Y,
4766 g_param_spec_int ("dst-roi-y", "Dst-ROI-Y",
4767 "Y value of Destination ROI(only effective \"CUSTOM_ROI\")", 0, XV_SCREEN_SIZE_HEIGHT, 0,
4768 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
4771 * GstEvasPixmapSink:dst-roi-w
4773 * W value of Destination ROI
4775 g_object_class_install_property (gobject_class, PROP_DST_ROI_W,
4776 g_param_spec_int ("dst-roi-w", "Dst-ROI-W",
4777 "W value of Destination ROI(only effective \"CUSTOM_ROI\")", 0, XV_SCREEN_SIZE_WIDTH, 0,
4778 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
4781 * GstEvasPixmapSink:dst-roi-h
4783 * H value of Destination ROI
4785 g_object_class_install_property (gobject_class, PROP_DST_ROI_H,
4786 g_param_spec_int ("dst-roi-h", "Dst-ROI-H",
4787 "H value of Destination ROI(only effective \"CUSTOM_ROI\")", 0, XV_SCREEN_SIZE_HEIGHT, 0,
4788 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
4791 * GstEvasPixmapSink:stop-video
4793 * Stop video for releasing video source buffer
4795 g_object_class_install_property (gobject_class, PROP_STOP_VIDEO,
4796 g_param_spec_int ("stop-video", "Stop-Video", "Stop video for releasing video source buffer", 0, 1, 0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
4799 * GstEvasPixmapSink:evas-object
4801 * Evas image object for rendering
4803 g_object_class_install_property (gobject_class, PROP_EVAS_OBJECT,
4804 g_param_spec_pointer ("evas-object", "Destination Evas Object", "Destination evas image object", G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
4807 * GstEvasPixmapSink:display-flip
4809 * Display flip setting
4811 g_object_class_install_property(gobject_class, PROP_FLIP,
4812 g_param_spec_enum("flip", "Display flip",
4814 GST_TYPE_EVASPIXMAPSINK_FLIP, DEF_DISPLAY_FLIP,
4815 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
4818 * GstEvasPixmapSink:rotate
4820 * draw rotation angle setting
4822 g_object_class_install_property(gobject_class, PROP_ROTATE_ANGLE,
4823 g_param_spec_enum("rotate", "Rotate angle", "Rotate angle of display output",GST_TYPE_EVASPIXMAPSINK_ROTATE_ANGLE, DEGREE_0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
4826 * GstEvasPixmapSink:visible
4828 * visible setting for a evas image object
4830 g_object_class_install_property (gobject_class, PROP_VISIBLE,
4831 g_param_spec_boolean ("visible", "Visible", "When setting it false, evas image object does not show", TRUE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
4834 * GstEvasPixmapSink:origin-size
4836 * Set pixmap size with media source's width and height
4838 g_object_class_install_property (gobject_class, PROP_ORIGIN_SIZE,
4839 g_param_spec_boolean ("origin-size", "Origin-Size", "When setting it true, pixmap will be created with media source's width and height", FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
4841 gobject_class->finalize = gst_evaspixmapsink_finalize;
4843 gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_evaspixmapsink_change_state);
4844 gstbasesink_class->get_caps = GST_DEBUG_FUNCPTR (gst_evaspixmapsink_getcaps);
4845 gstbasesink_class->set_caps = GST_DEBUG_FUNCPTR (gst_evaspixmapsink_setcaps);
4846 gstbasesink_class->get_times = GST_DEBUG_FUNCPTR (gst_evaspixmapsink_get_times);
4847 gstbasesink_class->event = GST_DEBUG_FUNCPTR (gst_evaspixmapsink_event);
4848 videosink_class->show_frame = GST_DEBUG_FUNCPTR (gst_evaspixmapsink_show_frame);
4851 /* Object typing & Creation */
4853 gst_evaspixmapsink_get_type (void)
4855 static GType evaspixmapsink_type = 0;
4857 if (!evaspixmapsink_type) {
4858 static const GTypeInfo evaspixmapsink_info = {
4859 sizeof (GstEvasPixmapSinkClass),
4860 gst_evaspixmapsink_base_init,
4862 (GClassInitFunc) gst_evaspixmapsink_class_init,
4865 sizeof (GstEvasPixmapSink),
4867 (GInstanceInitFunc) gst_evaspixmapsink_init,
4869 static const GInterfaceInfo iface_info = {
4870 (GInterfaceInitFunc) gst_evaspixmapsink_interface_init,
4874 static const GInterfaceInfo navigation_info = {
4875 (GInterfaceInitFunc) gst_evaspixmapsink_navigation_init,
4879 static const GInterfaceInfo colorbalance_info = {
4880 (GInterfaceInitFunc) gst_evaspixmapsink_colorbalance_init,
4884 static const GInterfaceInfo propertyprobe_info = {
4885 (GInterfaceInitFunc) gst_evaspixmapsink_property_probe_interface_init,
4889 evaspixmapsink_type = g_type_register_static (GST_TYPE_VIDEO_SINK, "GstEvasPixmapSink", &evaspixmapsink_info, 0);
4891 g_type_add_interface_static (evaspixmapsink_type, GST_TYPE_IMPLEMENTS_INTERFACE, &iface_info);
4892 g_type_add_interface_static (evaspixmapsink_type, GST_TYPE_NAVIGATION, &navigation_info);
4893 g_type_add_interface_static (evaspixmapsink_type, GST_TYPE_COLOR_BALANCE, &colorbalance_info);
4894 g_type_add_interface_static (evaspixmapsink_type, GST_TYPE_PROPERTY_PROBE, &propertyprobe_info);
4896 /* register type and create class in a more safe place instead of at
4897 * runtime since the type registration and class creation is not
4899 g_type_class_ref (gst_evaspixmap_buffer_get_type ());
4902 return evaspixmapsink_type;
4906 plugin_init (GstPlugin *plugin)
4908 if (!gst_element_register (plugin, "evaspixmapsink", GST_RANK_NONE, GST_TYPE_EVASPIXMAPSINK)) {
4911 GST_DEBUG_CATEGORY_INIT (gst_debug_evaspixmapsink, "evaspixmapsink", 0, "evaspixmapsink element");
4912 GST_DEBUG_CATEGORY_GET (GST_CAT_PERFORMANCE, "GST_PERFORMANCE");
4917 GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, GST_VERSION_MINOR,
4918 "evaspixmapsink","Evas image object render plugin using Xv extension", plugin_init,
4919 VERSION, GST_LICENSE, GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN)