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>
54 BUF_SHARE_METHOD_PADDR = 0,
58 /* max channel count *********************************************************/
59 #define SCMN_IMGB_MAX_PLANE (4)
61 /* image buffer definition ***************************************************
63 +------------------------------------------+ ---
66 | +---------------------------+ --- | |
68 | |<---------- w[] ---------->| | | |
76 | +---------------------------+ --- | |
78 +------------------------------------------+ ---
80 |<----------------- s[] ------------------>|
85 /* width of each image plane */
86 int w[SCMN_IMGB_MAX_PLANE];
87 /* height of each image plane */
88 int h[SCMN_IMGB_MAX_PLANE];
89 /* stride of each image plane */
90 int s[SCMN_IMGB_MAX_PLANE];
91 /* elevation of each image plane */
92 int e[SCMN_IMGB_MAX_PLANE];
93 /* user space address of each image plane */
94 void * a[SCMN_IMGB_MAX_PLANE];
95 /* physical address of each image plane, if needs */
96 void * p[SCMN_IMGB_MAX_PLANE];
97 /* color space type of image */
99 /* left postion, if needs */
101 /* top position, if needs */
103 /* to align memory */
108 int dma_buf_fd[SCMN_IMGB_MAX_PLANE];
109 /* buffer share method */
110 int buf_share_method;
113 /* Debugging category */
114 #include <gst/gstinfo.h>
115 GST_DEBUG_CATEGORY_STATIC (gst_debug_evaspixmapsink);
116 #define GST_CAT_DEFAULT gst_debug_evaspixmapsink
117 GST_DEBUG_CATEGORY_STATIC (GST_CAT_PERFORMANCE);
128 DISP_GEO_METHOD_LETTER_BOX = 0,
129 DISP_GEO_METHOD_ORIGIN_SIZE,
130 DISP_GEO_METHOD_FULL_SCREEN,
131 DISP_GEO_METHOD_CROPPED_FULL_SCREEN,
132 DISP_GEO_METHOD_CUSTOM_ROI,
144 #define DEF_DISPLAY_GEOMETRY_METHOD DISP_GEO_METHOD_LETTER_BOX
145 #define DEF_DISPLAY_FLIP FLIP_NONE
146 #define GST_TYPE_EVASPIXMAPSINK_FLIP (gst_evaspixmapsink_flip_get_type())
147 #define GST_TYPE_EVASPIXMAPSINK_ROTATE_ANGLE (gst_evaspixmapsink_rotate_angle_get_type())
148 #define GST_TYPE_EVASPIXMAPSINK_DISPLAY_GEOMETRY_METHOD (gst_evaspixmapsink_display_geometry_method_get_type())
151 gst_evaspixmapsink_flip_get_type(void)
153 static GType evaspixmapsink_flip_type = 0;
154 static const GEnumValue flip_type[] = {
155 { FLIP_NONE, "Flip NONE", "FLIP_NONE"},
156 { FLIP_HORIZONTAL, "Flip HORIZONTAL", "FLIP_HORIZONTAL"},
157 { FLIP_VERTICAL, "Flip VERTICAL", "FLIP_VERTICAL"},
158 { FLIP_BOTH, "Flip BOTH", "FLIP_BOTH"},
159 { FLIP_NUM, NULL, NULL},
162 if (!evaspixmapsink_flip_type) {
163 evaspixmapsink_flip_type = g_enum_register_static("GstEvasPixmapSinkFlipType", flip_type);
166 return evaspixmapsink_flip_type;
170 gst_evaspixmapsink_rotate_angle_get_type(void)
172 static GType evaspixmapsink_rotate_angle_type = 0;
173 static const GEnumValue rotate_angle_type[] = {
174 { 0, "No rotate", "DEGREE_0"},
175 { 1, "Rotate 90 degree", "DEGREE_90"},
176 { 2, "Rotate 180 degree", "DEGREE_180"},
177 { 3, "Rotate 270 degree", "DEGREE_270"},
181 if (!evaspixmapsink_rotate_angle_type) {
182 evaspixmapsink_rotate_angle_type = g_enum_register_static("GstEvasPixmapSinkRotateAngleType", rotate_angle_type);
185 return evaspixmapsink_rotate_angle_type;
189 gst_evaspixmapsink_display_geometry_method_get_type(void)
191 static GType evaspixmapsink_display_geometry_method_type = 0;
192 static const GEnumValue display_geometry_method_type[] = {
193 { 0, "Letter box", "LETTER_BOX"},
194 { 1, "Origin size", "ORIGIN_SIZE"},
195 { 2, "Full-screen", "FULL_SCREEN"},
196 { 3, "Cropped Full-screen", "CROPPED_FULL_SCREEN"},
197 { 4, "Explicitely described destination ROI", "CUSTOM_ROI"},
201 if (!evaspixmapsink_display_geometry_method_type) {
202 evaspixmapsink_display_geometry_method_type = g_enum_register_static("GstEvasPixmapSinkDisplayGeometryMethodType", display_geometry_method_type);
205 return evaspixmapsink_display_geometry_method_type;
211 unsigned long functions;
212 unsigned long decorations;
214 unsigned long status;
216 MotifWmHints, MwmHints;
218 #define MWM_HINTS_DECORATIONS (1L << 1)
220 static void gst_evaspixmapsink_reset (GstEvasPixmapSink *evaspixmapsink);
221 static GstBufferClass *evaspixmap_buffer_parent_class = NULL;
222 static void gst_evaspixmap_buffer_finalize (GstEvasPixmapBuffer *evaspixmapbuf);
223 static void gst_evaspixmapsink_xcontext_clear (GstEvasPixmapSink *evaspixmapsink);
224 static void gst_evaspixmapsink_xpixmap_destroy (GstEvasPixmapSink *evaspixmapsink, GstXPixmap *xpixmap);
225 static void gst_evaspixmapsink_xpixmap_update_geometry (GstEvasPixmapSink *evaspixmapsink, int idx);
226 static gboolean gst_evaspixmap_buffer_put (GstEvasPixmapSink *evaspixmapsink, GstEvasPixmapBuffer *evaspixmapbuf);
227 static gboolean gst_evaspixmapsink_xpixmap_link (GstEvasPixmapSink *evaspixmapsink);
228 static void gst_evaspixmapsink_xpixmap_clear (GstEvasPixmapSink *evaspixmapsink, GstXPixmap *xpixmap);
229 static gint gst_evaspixmapsink_get_format_from_caps (GstEvasPixmapSink *evaspixmapsink, GstCaps *caps);
230 static void drm_close_gem(GstEvasPixmapSink *evaspixmapsink, unsigned int gem_handle);
232 /* Default template - initiated with class struct to allow gst-register to work
234 static GstStaticPadTemplate gst_evaspixmapsink_sink_template_factory =
235 GST_STATIC_PAD_TEMPLATE ("sink",
238 GST_STATIC_CAPS ("video/x-raw-rgb, "
239 "framerate = (fraction) [ 0, MAX ], "
240 "width = (int) [ 1, MAX ], "
241 "height = (int) [ 1, MAX ]; "
243 "framerate = (fraction) [ 0, MAX ], "
244 "width = (int) [ 1, MAX ], " "height = (int) [ 1, MAX ]")
256 PROP_PIXEL_ASPECT_RATIO,
260 PROP_AUTOPAINT_COLORKEY,
266 PROP_DISPLAY_GEOMETRY_METHOD,
278 static GstVideoSinkClass *parent_class = NULL;
280 /* ============================================================= */
282 /* Private Methods */
284 /* ============================================================= */
286 /* evaspixmap buffers */
288 #define GST_TYPE_EVASPIXMAP_BUFFER (gst_evaspixmap_buffer_get_type())
290 #define GST_IS_EVASPIXMAP_BUFFER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_EVASPIXMAP_BUFFER))
291 #define GST_EVASPIXMAP_BUFFER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_EVASPIXMAP_BUFFER, GstEvasPixmapBuffer))
293 static int get_millis_time()
296 clock_gettime(CLOCK_MONOTONIC, &tp);
297 return (tp.tv_sec * 1000) + (tp.tv_nsec / 1000000L);
302 ecore_evas_post_render_callback_handler(Ecore_Evas *ee)
307 GstXPixmap *xpixmap = NULL;
309 GstEvasPixmapSink *evaspixmapsink = ecore_evas_data_get (ee, "evaspixmapsink_handle");
310 if (!evaspixmapsink) {
311 GST_WARNING ("could not get an evaspixmapsink handle");
314 if (evaspixmapsink->last_updated_idx == -1) {
315 GST_WARNING_OBJECT (evaspixmapsink, "last_updated_id = -1, skip it");
319 GST_DEBUG_OBJECT (evaspixmapsink, "[START] Ecore_Evas(0x%x), Evas_Object(0x%x)", ee, evaspixmapsink->eo);
321 MMTA_ACUM_ITEM_BEGIN("evaspixmapsink - ecore evas post render cb : TOTAL", FALSE);
323 g_mutex_lock (evaspixmapsink->pixmap_ref_lock);
324 /* find a oldest damaged pixmap */
325 for (i = 0; i < evaspixmapsink->num_of_pixmaps; i++) {
326 xpixmap = evaspixmapsink->xpixmap[i];
328 g_mutex_unlock (evaspixmapsink->pixmap_ref_lock);
329 GST_WARNING_OBJECT (evaspixmapsink, "xpixmap is null..");
330 MMTA_ACUM_ITEM_END("evaspixmapsink - ecore evas post render cb : TOTAL", FALSE);
333 if ((xpixmap->ref == 2) && xpixmap->damaged_time) {
334 if (temp_time == 0) {
335 temp_time = xpixmap->damaged_time;
338 if (temp_time > xpixmap->damaged_time) {
339 temp_time = xpixmap->damaged_time;
346 xpixmap = evaspixmapsink->xpixmap[idx];
347 if ((xpixmap->ref == 2) && xpixmap->damaged_time) {
348 GST_INFO_OBJECT (evaspixmapsink,"pixmap ref-count DECREASED : pixmap(%d), refcount(%d), damaged_time(%d), idx(%d)",
349 xpixmap->pixmap, xpixmap->ref, xpixmap->damaged_time, idx);
351 xpixmap->damaged_time = 0;
353 GST_LOG_OBJECT (evaspixmapsink, "There's nothing to update");
356 g_mutex_unlock (evaspixmapsink->pixmap_ref_lock);
358 MMTA_ACUM_ITEM_END("evaspixmapsink - ecore evas post render cb : TOTAL", FALSE);
360 GST_DEBUG_OBJECT (evaspixmapsink, "[END]");
366 ecore_pipe_callback_handler (void *data, void *buffer, unsigned int nbyte)
368 GstEvasPixmapSink *evaspixmapsink = (GstEvasPixmapSink*)data;
369 GST_DEBUG_OBJECT (evaspixmapsink,"[START] Evas_Object(0x%x)", evaspixmapsink->eo);
370 MMTA_ACUM_ITEM_BEGIN("evaspixmapsink - ecore thread cb : TOTAL", FALSE);
373 GstXPixmap *xpixmap = NULL;
376 GST_WARNING_OBJECT (evaspixmapsink,"data is NULL..");
379 if (!evaspixmapsink->eo) {
380 GST_WARNING_OBJECT (evaspixmapsink,"evas object is NULL..");
384 g_mutex_lock (evaspixmapsink->pixmap_ref_lock);
386 /* mapping evas object with xpixmap */
387 if (evaspixmapsink->do_link) {
388 GST_DEBUG_OBJECT (evaspixmapsink,"do link");
389 evas_object_image_size_set(evaspixmapsink->eo, evaspixmapsink->w, evaspixmapsink->h);
390 if (evaspixmapsink->xpixmap[idx]->pixmap) {
391 Evas_Native_Surface surf;
392 surf.version = EVAS_NATIVE_SURFACE_VERSION;
393 surf.type = EVAS_NATIVE_SURFACE_X11;
394 surf.data.x11.visual = ecore_x_default_visual_get(ecore_x_display_get(), ecore_x_default_screen_get());
395 surf.data.x11.pixmap = evaspixmapsink->xpixmap[idx]->pixmap;
396 __ta__("evaspixmapsink - ecore thread cb : _native_surface_set(LINK)", evas_object_image_native_surface_set(evaspixmapsink->eo, &surf); );
397 evaspixmapsink->do_link = FALSE;
398 evaspixmapsink->last_updated_idx = -1;
400 GST_WARNING_OBJECT (evaspixmapsink,"pixmap is NULL..");
401 g_mutex_unlock (evaspixmapsink->pixmap_ref_lock);
405 GST_DEBUG_OBJECT (evaspixmapsink,"update");
406 /* update evas image object size */
407 if (evaspixmapsink->use_origin_size) {
408 evas_object_geometry_get(evaspixmapsink->eo, NULL, NULL, &evaspixmapsink->w, &evaspixmapsink->h);
411 /* find a oldest damaged pixmap */
413 for (i = 0; i < evaspixmapsink->num_of_pixmaps; i++) {
414 xpixmap = evaspixmapsink->xpixmap[i];
415 if (xpixmap->ref == 1 && xpixmap->damaged_time) {
416 if (temp_time == 0) {
417 temp_time = xpixmap->damaged_time;
420 if (temp_time > xpixmap->damaged_time) {
421 temp_time = xpixmap->damaged_time;
428 xpixmap = evaspixmapsink->xpixmap[idx];
429 if (xpixmap->damaged_time == 0 || xpixmap->ref > 1) {
430 GST_WARNING_OBJECT (evaspixmapsink,"skip update.. idx[%d] : damaged_time[%d], ref[%d]",idx, xpixmap->damaged_time, xpixmap->ref);
432 if (xpixmap->pixmap) {
433 if (evaspixmapsink->last_updated_idx != idx) {
434 Evas_Native_Surface surf;
435 surf.version = EVAS_NATIVE_SURFACE_VERSION;
436 surf.type = EVAS_NATIVE_SURFACE_X11;
437 surf.data.x11.visual = ecore_x_default_visual_get(ecore_x_display_get(), ecore_x_default_screen_get());
438 surf.data.x11.pixmap = xpixmap->pixmap;
439 if (evaspixmapsink->eo) {
440 evas_object_image_native_surface_set(evaspixmapsink->eo, NULL);
442 __ta__("evaspixmapsink - ecore thread cb : _native_surface_set", evas_object_image_native_surface_set(evaspixmapsink->eo, &surf); );
443 GST_LOG_OBJECT (evaspixmapsink,"update, native_surface_set of xpixmap[%d]",idx);
444 evaspixmapsink->last_updated_idx = idx;
448 MMTA_ACUM_ITEM_BEGIN("evaspixmapsink evas_object_image update", FALSE);
449 evas_object_image_pixels_dirty_set (evaspixmapsink->eo, 1);
450 evas_object_image_fill_set(evaspixmapsink->eo, 0, 0, evaspixmapsink->w, evaspixmapsink->h);
451 evas_object_image_data_update_add(evaspixmapsink->eo, 0, 0, evaspixmapsink->w, evaspixmapsink->h);
452 MMTA_ACUM_ITEM_END("evaspixmapsink evas_object_image update", FALSE);
454 GST_LOG_OBJECT (evaspixmapsink,"request to update : pixmap idx(%d), ref(%d)", idx, xpixmap->ref);
456 GST_ERROR_OBJECT (evaspixmapsink,"pixmap is NULL..");
457 g_mutex_unlock (evaspixmapsink->pixmap_ref_lock);
462 g_mutex_unlock (evaspixmapsink->pixmap_ref_lock);
464 MMTA_ACUM_ITEM_END("evaspixmapsink - ecore thread cb : TOTAL", FALSE);
466 GST_DEBUG_OBJECT (evaspixmapsink,"[END]");
470 evas_callback_resize_event (void *data, Evas *e, Evas_Object *obj, void *event_info)
474 float former_ratio = 0;
476 float abs_margin = 0;
479 GstEvasPixmapSink *evaspixmapsink = (GstEvasPixmapSink *)data;
480 GST_DEBUG_OBJECT (evaspixmapsink,"[START]");
482 evas_object_geometry_get(evaspixmapsink->eo, NULL, NULL, &w, &h);
483 GST_DEBUG_OBJECT (evaspixmapsink,"resized : w(%d), h(%d)", w, h);
484 if (!evaspixmapsink->use_origin_size &&
485 (evaspixmapsink->w != w || evaspixmapsink->h != h)) {
486 former_ratio = (float)evaspixmapsink->w / evaspixmapsink->h;
487 ratio = (float)w / h;
488 evaspixmapsink->w = w;
489 evaspixmapsink->h = h;
492 GST_DEBUG_OBJECT (evaspixmapsink,"resized : ratio(%.3f=>%.3f)", former_ratio, ratio);
493 if ( former_ratio >= ratio ) {
494 abs_margin = former_ratio - ratio;
496 abs_margin = ratio - former_ratio;
498 /* re-link_pixmap can only be set when ratio is changed */
499 if ( abs_margin >= MARGIN_OF_ERROR ) {
501 if (!gst_evaspixmapsink_xpixmap_link(evaspixmapsink)) {
502 GST_ERROR_OBJECT (evaspixmapsink,"link evas image object with pixmap failed...");
510 for (i = 0; i < evaspixmapsink->num_of_pixmaps; i++) {
511 if (evaspixmapsink->xpixmap[i]->ref == 0) {
515 if (GST_STATE(evaspixmapsink) == GST_STATE_PAUSED && i < evaspixmapsink->num_of_pixmaps) {
516 gst_evaspixmap_buffer_put (evaspixmapsink, evaspixmapsink->evas_pixmap_buf);
519 GST_DEBUG_OBJECT (evaspixmapsink,"[END]");
522 static inline gboolean
523 is_evas_image_object (Evas_Object *obj)
529 type = evas_object_type_get (obj);
533 if (strcmp (type, "image") == 0) {
540 evas_callback_del_event (void *data, Evas *e, Evas_Object *obj, void *event_info)
542 GstEvasPixmapSink *evaspixmapsink = data;
543 if (!evaspixmapsink) {
544 GST_WARNING ("evaspixmapsink is NULL..");
547 GST_DEBUG_OBJECT (evaspixmapsink,"[START]");
549 evas_object_event_callback_del(evaspixmapsink->eo, EVAS_CALLBACK_RESIZE, evas_callback_resize_event);
550 if (evaspixmapsink->eo) {
551 evas_object_image_native_surface_set(evaspixmapsink->eo, NULL);
552 evaspixmapsink->eo = NULL;
555 GST_DEBUG_OBJECT (evaspixmapsink,"[END]");
559 static gboolean error_caught = FALSE;
562 gst_evaspixmapsink_handle_xerror (Display * display, XErrorEvent * xevent)
564 char error_msg[1024];
566 XGetErrorText (display, xevent->error_code, error_msg, 1024);
567 GST_DEBUG ("evaspixmapsink triggered an XError. error: %s", error_msg);
573 /* This function checks that it is actually really possible to create an image
576 gst_evaspixmapsink_check_xshm_calls (GstXContext * xcontext)
579 XShmSegmentInfo SHMInfo;
581 int (*handler) (Display *, XErrorEvent *);
582 gboolean result = FALSE;
583 gboolean did_attach = FALSE;
585 g_return_val_if_fail (xcontext != NULL, FALSE);
587 /* Sync to ensure any older errors are already processed */
588 XSync (xcontext->disp, FALSE);
590 /* Set defaults so we don't free these later unnecessarily */
591 SHMInfo.shmaddr = ((void *) -1);
594 /* Setting an error handler to catch failure */
595 error_caught = FALSE;
596 handler = XSetErrorHandler (gst_evaspixmapsink_handle_xerror);
598 /* Trying to create a 1x1 picture */
599 GST_DEBUG ("XvShmCreateImage of 1x1");
600 xvimage = XvShmCreateImage (xcontext->disp, xcontext->xv_port_id,
601 xcontext->im_format, NULL, 1, 1, &SHMInfo);
603 /* Might cause an error, sync to ensure it is noticed */
604 XSync (xcontext->disp, FALSE);
605 if (!xvimage || error_caught) {
606 GST_WARNING ("could not XvShmCreateImage a 1x1 image");
609 size = xvimage->data_size;
611 SHMInfo.shmid = shmget (IPC_PRIVATE, size, IPC_CREAT | 0777);
612 if (SHMInfo.shmid == -1) {
613 GST_WARNING ("could not get shared memory of %d bytes", size);
617 SHMInfo.shmaddr = shmat (SHMInfo.shmid, NULL, 0);
618 if (SHMInfo.shmaddr == ((void *) -1)) {
619 GST_WARNING ("Failed to shmat: %s", g_strerror (errno));
620 /* Clean up the shared memory segment */
621 shmctl (SHMInfo.shmid, IPC_RMID, NULL);
625 xvimage->data = SHMInfo.shmaddr;
626 SHMInfo.readOnly = FALSE;
628 if (XShmAttach (xcontext->disp, &SHMInfo) == 0) {
629 GST_WARNING ("Failed to XShmAttach");
630 /* Clean up the shared memory segment */
631 shmctl (SHMInfo.shmid, IPC_RMID, NULL);
635 /* Sync to ensure we see any errors we caused */
636 XSync (xcontext->disp, FALSE);
638 /* Delete the shared memory segment as soon as everyone is attached.
639 * This way, it will be deleted as soon as we detach later, and not
640 * leaked if we crash. */
641 shmctl (SHMInfo.shmid, IPC_RMID, NULL);
644 GST_DEBUG ("XServer ShmAttached to 0x%x, id 0x%lx", SHMInfo.shmid,
648 /* store whether we succeeded in result */
651 GST_WARNING ("MIT-SHM extension check failed at XShmAttach. "
652 "Not using shared memory.");
656 /* Sync to ensure we swallow any errors we caused and reset error_caught */
657 XSync (xcontext->disp, FALSE);
659 error_caught = FALSE;
660 XSetErrorHandler (handler);
663 GST_DEBUG ("XServer ShmDetaching from 0x%x id 0x%lx",
664 SHMInfo.shmid, SHMInfo.shmseg);
665 XShmDetach (xcontext->disp, &SHMInfo);
666 XSync (xcontext->disp, FALSE);
668 if (SHMInfo.shmaddr != ((void *) -1))
669 shmdt (SHMInfo.shmaddr);
674 #endif /* HAVE_XSHM */
676 /* This function destroys a GstEvasPixmap handling XShm availability */
678 gst_evaspixmap_buffer_destroy (GstEvasPixmapBuffer *evaspixmapbuf)
680 GstEvasPixmapSink *evaspixmapsink;
682 GST_DEBUG_OBJECT (evaspixmapsink,"Destroying buffer");
684 evaspixmapsink = evaspixmapbuf->evaspixmapsink;
685 if (G_UNLIKELY (evaspixmapsink == NULL)) {
689 g_return_if_fail (GST_IS_EVASPIXMAPSINK (evaspixmapsink));
691 GST_OBJECT_LOCK (evaspixmapsink);
693 /* We might have some buffers destroyed after changing state to NULL */
694 if (evaspixmapsink->xcontext == NULL) {
695 GST_DEBUG_OBJECT (evaspixmapsink,"Destroying XvImage after Xcontext");
697 /* Need to free the shared memory segment even if the x context
698 * was already cleaned up */
699 if (evaspixmapbuf->SHMInfo.shmaddr != ((void *) -1)) {
700 shmdt (evaspixmapbuf->SHMInfo.shmaddr);
705 g_mutex_lock (evaspixmapsink->x_lock);
708 if (evaspixmapsink->xcontext->use_xshm) {
709 if (evaspixmapbuf->SHMInfo.shmaddr != ((void *) -1)) {
710 GST_DEBUG_OBJECT (evaspixmapsink,"XServer ShmDetaching from 0x%x id 0x%lx", evaspixmapbuf->SHMInfo.shmid, evaspixmapbuf->SHMInfo.shmseg);
711 XShmDetach (evaspixmapsink->xcontext->disp, &evaspixmapbuf->SHMInfo);
712 XSync (evaspixmapsink->xcontext->disp, FALSE);
713 shmdt (evaspixmapbuf->SHMInfo.shmaddr);
715 if (evaspixmapbuf->xvimage)
716 XFree (evaspixmapbuf->xvimage);
718 #endif /* HAVE_XSHM */
720 if (evaspixmapbuf->xvimage) {
721 if (evaspixmapbuf->xvimage->data) {
722 g_free (evaspixmapbuf->xvimage->data);
724 XFree (evaspixmapbuf->xvimage);
728 XSync (evaspixmapsink->xcontext->disp, FALSE);
730 g_mutex_unlock (evaspixmapsink->x_lock);
733 GST_OBJECT_UNLOCK (evaspixmapsink);
734 evaspixmapbuf->evaspixmapsink = NULL;
735 gst_object_unref (evaspixmapsink);
737 GST_MINI_OBJECT_CLASS (evaspixmap_buffer_parent_class)->finalize (GST_MINI_OBJECT(evaspixmapbuf));
743 GST_WARNING_OBJECT (evaspixmapsink,"no sink found");
749 gst_evaspixmap_buffer_finalize (GstEvasPixmapBuffer *evaspixmapbuf)
751 GstEvasPixmapSink *evaspixmapsink;
753 evaspixmapsink = evaspixmapbuf->evaspixmapsink;
754 if (G_UNLIKELY (evaspixmapsink == NULL)) {
755 GST_WARNING_OBJECT (evaspixmapsink,"no sink found");
758 g_return_if_fail (GST_IS_EVASPIXMAPSINK (evaspixmapsink));
760 /* If our geometry changed we can't reuse that image. */
761 GST_LOG_OBJECT (evaspixmapsink,"destroy image as sink is shutting down");
762 gst_evaspixmap_buffer_destroy (evaspixmapbuf);
766 gst_evaspixmap_buffer_free (GstEvasPixmapBuffer *evaspixmapbuf)
768 /* make sure it is not recycled */
769 evaspixmapbuf->width = -1;
770 evaspixmapbuf->height = -1;
771 gst_buffer_unref (GST_BUFFER (evaspixmapbuf));
775 gst_evaspixmap_buffer_init (GstEvasPixmapBuffer *evaspixmapbuf, gpointer g_class)
778 evaspixmapbuf->SHMInfo.shmaddr = ((void *) -1);
779 evaspixmapbuf->SHMInfo.shmid = -1;
784 gst_evaspixmap_buffer_class_init (gpointer g_class, gpointer class_data)
786 GstMiniObjectClass *mini_object_class = GST_MINI_OBJECT_CLASS (g_class);
788 evaspixmap_buffer_parent_class = g_type_class_peek_parent (g_class);
790 mini_object_class->finalize = (GstMiniObjectFinalizeFunction) gst_evaspixmap_buffer_finalize;
794 gst_evaspixmap_buffer_get_type (void)
796 static GType _gst_evaspixmap_buffer_type;
798 if (G_UNLIKELY (_gst_evaspixmap_buffer_type == 0)) {
799 static const GTypeInfo evaspixmap_buffer_info = {
800 sizeof (GstBufferClass),
803 gst_evaspixmap_buffer_class_init,
806 sizeof (GstEvasPixmapBuffer),
808 (GInstanceInitFunc) gst_evaspixmap_buffer_init,
811 _gst_evaspixmap_buffer_type = g_type_register_static (GST_TYPE_BUFFER,
812 "GstEvasPixmapBuffer", &evaspixmap_buffer_info, 0);
814 return _gst_evaspixmap_buffer_type;
817 /* This function handles GstEvasPixmapBuffer creation depending on XShm availability */
818 static GstEvasPixmapBuffer*
819 gst_evaspixmap_buffer_new (GstEvasPixmapSink *evaspixmapsink, GstCaps *caps)
821 GstEvasPixmapBuffer *evaspixmapbuf = NULL;
822 GstStructure *structure = NULL;
823 gboolean succeeded = FALSE;
824 int (*handler) (Display *, XErrorEvent *);
826 g_return_val_if_fail (GST_IS_EVASPIXMAPSINK (evaspixmapsink), NULL);
832 evaspixmapbuf = (GstEvasPixmapBuffer*) gst_mini_object_new (GST_TYPE_EVASPIXMAP_BUFFER);
833 GST_DEBUG_OBJECT (evaspixmapsink,"Creating new EvasPixmapBuffer");
835 structure = gst_caps_get_structure (caps, 0);
837 if (!gst_structure_get_int (structure, "width", &evaspixmapbuf->width) || !gst_structure_get_int (structure, "height", &evaspixmapbuf->height)) {
838 GST_WARNING_OBJECT (evaspixmapsink,"failed getting geometry from caps %" GST_PTR_FORMAT, caps);
841 GST_LOG_OBJECT (evaspixmapsink,"creating %dx%d", evaspixmapbuf->width, evaspixmapbuf->height);
843 GST_LOG_OBJECT (evaspixmapsink,"aligned size %dx%d", evaspixmapsink->aligned_width, evaspixmapsink->aligned_height);
844 if (evaspixmapsink->aligned_width == 0 || evaspixmapsink->aligned_height == 0) {
845 GST_INFO_OBJECT (evaspixmapsink,"aligned size is zero. set size of caps.");
846 evaspixmapsink->aligned_width = evaspixmapbuf->width;
847 evaspixmapsink->aligned_height = evaspixmapbuf->height;
850 evaspixmapbuf->im_format = gst_evaspixmapsink_get_format_from_caps (evaspixmapsink, caps);
851 if (evaspixmapbuf->im_format == -1) {
852 GST_WARNING_OBJECT (evaspixmapsink,"failed to get format from caps %"GST_PTR_FORMAT, caps);
853 GST_ELEMENT_ERROR (evaspixmapsink, RESOURCE, WRITE,("Failed to create output image buffer of %dx%d pixels",
854 evaspixmapbuf->width, evaspixmapbuf->height), ("Invalid input caps"));
857 evaspixmapbuf->evaspixmapsink = gst_object_ref (evaspixmapsink);
859 g_mutex_lock (evaspixmapsink->x_lock);
861 /* Setting an error handler to catch failure */
862 error_caught = FALSE;
863 handler = XSetErrorHandler (gst_evaspixmapsink_handle_xerror);
866 if (evaspixmapsink->xcontext->use_xshm) {
868 evaspixmapbuf->xvimage = XvShmCreateImage (evaspixmapsink->xcontext->disp, evaspixmapsink->xcontext->xv_port_id, evaspixmapbuf->im_format, NULL,
869 evaspixmapsink->aligned_width, evaspixmapsink->aligned_height, &evaspixmapbuf->SHMInfo);
870 if(!evaspixmapbuf->xvimage) {
871 GST_ERROR_OBJECT (evaspixmapsink,"XvShmCreateImage() failed");
874 if (!evaspixmapbuf->xvimage || error_caught) {
876 GST_ERROR_OBJECT (evaspixmapsink,"error_caught!");
878 g_mutex_unlock (evaspixmapsink->x_lock);
879 /* Reset error handler */
880 error_caught = FALSE;
881 XSetErrorHandler (handler);
883 GST_ELEMENT_ERROR (evaspixmapsink, RESOURCE, WRITE,("Failed to create output image buffer of %dx%d pixels",evaspixmapbuf->width,
884 evaspixmapbuf->height),("could not XvShmCreateImage a %dx%d image",evaspixmapbuf->width, evaspixmapbuf->height));
888 /* we have to use the returned data_size for our shm size */
889 evaspixmapbuf->size = evaspixmapbuf->xvimage->data_size;
890 GST_LOG_OBJECT (evaspixmapsink,"XShm image size is %" G_GSIZE_FORMAT, evaspixmapbuf->size);
892 /* calculate the expected size. This is only for sanity checking the
893 * number we get from X. */
894 switch (evaspixmapbuf->im_format) {
895 case GST_MAKE_FOURCC ('I', '4', '2', '0'):
896 case GST_MAKE_FOURCC ('Y', 'V', '1', '2'):
903 pitches[0] = GST_ROUND_UP_4 (evaspixmapbuf->width);
904 offsets[1] = offsets[0] + pitches[0] * GST_ROUND_UP_2 (evaspixmapbuf->height);
905 pitches[1] = GST_ROUND_UP_8 (evaspixmapbuf->width) / 2;
907 offsets[1] + pitches[1] * GST_ROUND_UP_2 (evaspixmapbuf->height) / 2;
908 pitches[2] = GST_ROUND_UP_8 (pitches[0]) / 2;
910 expected_size = offsets[2] + pitches[2] * GST_ROUND_UP_2 (evaspixmapbuf->height) / 2;
912 for (plane = 0; plane < evaspixmapbuf->xvimage->num_planes; plane++) {
913 GST_DEBUG_OBJECT (evaspixmapsink,"Plane %u has a expected pitch of %d bytes, " "offset of %d",
914 plane, pitches[plane], offsets[plane]);
918 case GST_MAKE_FOURCC ('Y', 'U', 'Y', '2'):
919 case GST_MAKE_FOURCC ('U', 'Y', 'V', 'Y'):
920 expected_size = evaspixmapbuf->height * GST_ROUND_UP_4 (evaspixmapbuf->width * 2);
922 case GST_MAKE_FOURCC ('S', 'T', '1', '2'):
923 case GST_MAKE_FOURCC ('S', 'N', '1', '2'):
924 case GST_MAKE_FOURCC ('S', 'U', 'Y', 'V'):
925 case GST_MAKE_FOURCC ('S', 'U', 'Y', '2'):
926 case GST_MAKE_FOURCC ('S', '4', '2', '0'):
927 case GST_MAKE_FOURCC ('S', 'Y', 'V', 'Y'):
928 expected_size = sizeof(SCMN_IMGB);
934 if (expected_size != 0 && evaspixmapbuf->size != expected_size) {
935 GST_WARNING_OBJECT (evaspixmapsink,"unexpected XShm image size (got %" G_GSIZE_FORMAT ", expected %d)", evaspixmapbuf->size, expected_size);
938 /* Be verbose about our XvImage stride */
941 for (plane = 0; plane < evaspixmapbuf->xvimage->num_planes; plane++) {
942 GST_DEBUG_OBJECT (evaspixmapsink,"Plane %u has a pitch of %d bytes, ""offset of %d", plane,
943 evaspixmapbuf->xvimage->pitches[plane], evaspixmapbuf->xvimage->offsets[plane]);
947 evaspixmapbuf->SHMInfo.shmid = shmget (IPC_PRIVATE, evaspixmapbuf->size,IPC_CREAT | 0777);
948 if (evaspixmapbuf->SHMInfo.shmid == -1) {
949 g_mutex_unlock (evaspixmapsink->x_lock);
950 GST_ELEMENT_ERROR (evaspixmapsink, RESOURCE, WRITE,
951 ("Failed to create output image buffer of %dx%d pixels", evaspixmapbuf->width, evaspixmapbuf->height),
952 ("could not get shared memory of %" G_GSIZE_FORMAT " bytes",evaspixmapbuf->size));
956 evaspixmapbuf->SHMInfo.shmaddr = shmat (evaspixmapbuf->SHMInfo.shmid, NULL, 0);
957 if (evaspixmapbuf->SHMInfo.shmaddr == ((void *) -1)) {
958 g_mutex_unlock (evaspixmapsink->x_lock);
959 GST_ELEMENT_ERROR (evaspixmapsink, RESOURCE, WRITE,
960 ("Failed to create output image buffer of %dx%d pixels",
961 evaspixmapbuf->width, evaspixmapbuf->height),
962 ("Failed to shmat: %s", g_strerror (errno)));
963 /* Clean up the shared memory segment */
964 shmctl (evaspixmapbuf->SHMInfo.shmid, IPC_RMID, NULL);
968 evaspixmapbuf->xvimage->data = evaspixmapbuf->SHMInfo.shmaddr;
969 evaspixmapbuf->SHMInfo.readOnly = FALSE;
971 if (XShmAttach (evaspixmapsink->xcontext->disp, &evaspixmapbuf->SHMInfo) == 0) {
972 /* Clean up the shared memory segment */
973 shmctl (evaspixmapbuf->SHMInfo.shmid, IPC_RMID, NULL);
975 g_mutex_unlock (evaspixmapsink->x_lock);
976 GST_ELEMENT_ERROR (evaspixmapsink, RESOURCE, WRITE,
977 ("Failed to create output image buffer of %dx%d pixels",
978 evaspixmapbuf->width, evaspixmapbuf->height), ("Failed to XShmAttach"));
982 XSync (evaspixmapsink->xcontext->disp, FALSE);
984 /* Delete the shared memory segment as soon as we everyone is attached.
985 * This way, it will be deleted as soon as we detach later, and not
986 * leaked if we crash. */
987 shmctl (evaspixmapbuf->SHMInfo.shmid, IPC_RMID, NULL);
989 GST_DEBUG_OBJECT (evaspixmapsink,"XServer ShmAttached to 0x%x, id 0x%lx", evaspixmapbuf->SHMInfo.shmid, evaspixmapbuf->SHMInfo.shmseg);
991 #endif /* HAVE_XSHM */
993 evaspixmapbuf->xvimage = XvCreateImage (evaspixmapsink->xcontext->disp, evaspixmapsink->xcontext->xv_port_id,
994 evaspixmapbuf->im_format, NULL, evaspixmapsink->aligned_width, evaspixmapsink->aligned_height);
995 if (!evaspixmapbuf->xvimage || error_caught) {
996 g_mutex_unlock (evaspixmapsink->x_lock);
997 /* Reset error handler */
998 error_caught = FALSE;
999 XSetErrorHandler (handler);
1001 GST_ELEMENT_ERROR (evaspixmapsink, RESOURCE, WRITE,
1002 ("Failed to create outputimage buffer of %dx%d pixels",
1003 evaspixmapbuf->width, evaspixmapbuf->height),
1004 ("could not XvCreateImage a %dx%d image",
1005 evaspixmapbuf->width, evaspixmapbuf->height));
1006 goto beach_unlocked;
1009 /* we have to use the returned data_size for our image size */
1010 evaspixmapbuf->size = evaspixmapbuf->xvimage->data_size;
1011 evaspixmapbuf->xvimage->data = g_malloc (evaspixmapbuf->size);
1013 XSync (evaspixmapsink->xcontext->disp, FALSE);
1016 /* Reset error handler */
1017 error_caught = FALSE;
1018 XSetErrorHandler (handler);
1022 GST_BUFFER_DATA (evaspixmapbuf) = (guchar *) evaspixmapbuf->xvimage->data;
1023 GST_BUFFER_SIZE (evaspixmapbuf) = evaspixmapbuf->size;
1025 g_mutex_unlock (evaspixmapsink->x_lock);
1029 gst_evaspixmap_buffer_free (evaspixmapbuf);
1030 evaspixmapbuf = NULL;
1033 return evaspixmapbuf;
1036 /* This function puts a GstEvasPixmapBuffer on a GstEvasPixmapSink's pixmap. Returns FALSE
1037 * if no pixmap was available */
1039 gst_evaspixmap_buffer_put (GstEvasPixmapSink *evaspixmapsink, GstEvasPixmapBuffer *evaspixmapbuf)
1041 GstVideoRectangle result;
1043 GstVideoRectangle src_origin = { 0, 0, 0, 0};
1044 GstVideoRectangle src_input = { 0, 0, 0, 0};
1045 GstVideoRectangle src = { 0, 0, 0, 0};
1046 GstVideoRectangle dst = { 0, 0, 0, 0};
1051 MMTA_ACUM_ITEM_BEGIN("evaspixmapsink evaspixmap_buffer_put()", FALSE);
1053 /* We take the flow_lock. If expose is in there we don't want to run
1054 concurrently from the data flow thread */
1055 g_mutex_lock (evaspixmapsink->flow_lock);
1057 if (G_UNLIKELY (evaspixmapsink->xpixmap[idx] == NULL)) {
1058 GST_WARNING_OBJECT (evaspixmapsink, "xpixmap is NULL. Skip buffer_put." );
1059 g_mutex_unlock(evaspixmapsink->flow_lock);
1062 if (evaspixmapsink->visible == FALSE) {
1063 GST_WARNING_OBJECT (evaspixmapsink, "visible is FALSE. Skip buffer_put." );
1064 g_mutex_unlock(evaspixmapsink->flow_lock);
1067 if (!evaspixmapbuf) {
1068 GST_WARNING_OBJECT (evaspixmapsink, "evaspixmapbuf is NULL. Skip buffer_put." );
1069 g_mutex_unlock(evaspixmapsink->flow_lock);
1073 /* check whether if a pixmap buffer is available, or wait here */
1074 gboolean wait = TRUE;
1075 int timeout_count = 3 * 1; /* 3 frames */
1076 GstXPixmap *xpixmap = NULL;
1078 for (idx = 0; idx < evaspixmapsink->num_of_pixmaps; idx++) {
1079 g_mutex_lock (evaspixmapsink->pixmap_ref_lock);
1080 if (idx <= evaspixmapsink->last_damaged_pixmap_idx) {
1081 if (evaspixmapsink->last_damaged_pixmap_idx == evaspixmapsink->num_of_pixmaps - 1) {
1084 g_mutex_unlock (evaspixmapsink->pixmap_ref_lock);
1088 xpixmap = evaspixmapsink->xpixmap[idx];
1089 if (xpixmap->ref == 0 && xpixmap->damaged_time == 0) {
1092 GST_INFO_OBJECT (evaspixmapsink, "found an available pixmap(%d) : xpixmap[%d]", xpixmap->pixmap, idx);
1093 GST_INFO_OBJECT (evaspixmapsink,"pixmap ref-count INCREASED : pixmap(%d), refcount(%d)", xpixmap->pixmap, xpixmap->ref);
1094 g_mutex_unlock (evaspixmapsink->pixmap_ref_lock);
1097 g_mutex_unlock (evaspixmapsink->pixmap_ref_lock);
1100 GST_WARNING_OBJECT (evaspixmapsink, "wait until a pixmap is available");
1102 g_usleep (G_USEC_PER_SEC / 30);
1104 //timeout_count = 0;
1105 if (timeout_count == 0) {
1106 GST_WARNING_OBJECT (evaspixmapsink, "TIME OUT..");
1107 g_mutex_unlock(evaspixmapsink->flow_lock);
1113 gst_evaspixmapsink_xpixmap_update_geometry(evaspixmapsink, idx);
1116 src_origin.x = src_origin.y = src_input.x = src_input.y = 0;
1117 src_input.w = src_origin.w = evaspixmapsink->video_width;
1118 src_input.h = src_origin.h = evaspixmapsink->video_height;
1119 if (evaspixmapsink->use_origin_size ||
1120 (evaspixmapsink->rotate_angle == DEGREE_0 ||
1121 evaspixmapsink->rotate_angle == DEGREE_180)) {
1122 src.w = src_origin.w;
1123 src.h = src_origin.h;
1125 src.w = src_origin.h;
1126 src.h = src_origin.w;
1129 dst.w = evaspixmapsink->render_rect.w; /* pixmap width */
1130 dst.h = evaspixmapsink->render_rect.h; /* pixmap height */
1132 if (!evaspixmapsink->use_origin_size) {
1133 static Atom atom_rotation = None;
1134 static Atom atom_hflip = None;
1135 static Atom atom_vflip = None;
1136 gboolean set_hflip = FALSE;
1137 gboolean set_vflip = FALSE;
1139 /* compensation of size information (between evas image object's and pixmap's) */
1140 if (evaspixmapsink->sizediff_width > 1) {
1141 if (evaspixmapsink->sizediff_height > 1) {
1142 dst.w -= (evaspixmapsink->sizediff_width >> 1) << 1;
1143 dst.h -= (evaspixmapsink->sizediff_height >> 1) << 1;
1145 dst.w -= (evaspixmapsink->sizediff_width >> 1) << 1;
1147 } else if (evaspixmapsink->sizediff_height > 1) {
1148 dst.h -= (evaspixmapsink->sizediff_height >> 1) << 1;
1151 switch (evaspixmapsink->display_geometry_method) {
1152 case DISP_GEO_METHOD_LETTER_BOX:
1153 gst_video_sink_center_rect (src, dst, &result, TRUE);
1154 result.x += evaspixmapsink->render_rect.x;
1155 result.y += evaspixmapsink->render_rect.y;
1156 GST_DEBUG_OBJECT (evaspixmapsink, "GEO_METHOD : letter box");
1158 case DISP_GEO_METHOD_ORIGIN_SIZE:
1159 gst_video_sink_center_rect (src, dst, &result, FALSE);
1160 gst_video_sink_center_rect (dst, src, &src_input, FALSE);
1161 GST_DEBUG_OBJECT (evaspixmapsink, "GEO_METHOD : origin size");
1162 if (evaspixmapsink->rotate_angle == DEGREE_90 ||
1163 evaspixmapsink->rotate_angle == DEGREE_270) {
1164 src_input.x = src_input.x ^ src_input.y;
1165 src_input.y = src_input.x ^ src_input.y;
1166 src_input.x = src_input.x ^ src_input.y;
1167 src_input.w = src_input.w ^ src_input.h;
1168 src_input.h = src_input.w ^ src_input.h;
1169 src_input.w = src_input.w ^ src_input.h;
1172 case DISP_GEO_METHOD_FULL_SCREEN:
1173 result.x = result.y = 0;
1174 result.w = evaspixmapsink->xpixmap[idx]->width;
1175 result.h = evaspixmapsink->xpixmap[idx]->height;
1176 GST_DEBUG_OBJECT (evaspixmapsink, "GEO_METHOD : full screen");
1178 case DISP_GEO_METHOD_CROPPED_FULL_SCREEN:
1179 GST_DEBUG_OBJECT (evaspixmapsink, "GEO_METHOD : cropped full screen");
1180 gst_video_sink_center_rect(dst, src, &src_input, TRUE);
1181 result.x = result.y = 0;
1184 if (evaspixmapsink->rotate_angle == DEGREE_90 ||
1185 evaspixmapsink->rotate_angle == DEGREE_270) {
1186 src_input.x = src_input.x ^ src_input.y;
1187 src_input.y = src_input.x ^ src_input.y;
1188 src_input.x = src_input.x ^ src_input.y;
1189 src_input.w = src_input.w ^ src_input.h;
1190 src_input.h = src_input.w ^ src_input.h;
1191 src_input.w = src_input.w ^ src_input.h;
1194 case DISP_GEO_METHOD_CUSTOM_ROI:
1195 switch (evaspixmapsink->rotate_angle) {
1197 result.w = evaspixmapsink->dst_roi.h;
1198 result.h = evaspixmapsink->dst_roi.w;
1199 result.x = evaspixmapsink->dst_roi.y;
1200 result.y = evaspixmapsink->xpixmap[idx]->height - evaspixmapsink->dst_roi.x - evaspixmapsink->dst_roi.w;
1203 result.w = evaspixmapsink->dst_roi.w;
1204 result.h = evaspixmapsink->dst_roi.h;
1205 result.x = evaspixmapsink->xpixmap[idx]->width - result.w - evaspixmapsink->dst_roi.x;
1206 result.y = evaspixmapsink->xpixmap[idx]->height - result.h - evaspixmapsink->dst_roi.y;
1209 result.w = evaspixmapsink->dst_roi.h;
1210 result.h = evaspixmapsink->dst_roi.w;
1211 result.x = evaspixmapsink->xpixmap[idx]->width - evaspixmapsink->dst_roi.y - evaspixmapsink->dst_roi.h;
1212 result.y = evaspixmapsink->dst_roi.x;
1215 result.x = evaspixmapsink->dst_roi.x;
1216 result.y = evaspixmapsink->dst_roi.y;
1217 result.w = evaspixmapsink->dst_roi.w;
1218 result.h = evaspixmapsink->dst_roi.h;
1221 GST_LOG_OBJECT(evaspixmapsink, "rotate[%d], ROI input[%d,%d,%dx%d] > result[%d,%d,%dx%d]",
1222 evaspixmapsink->rotate_angle,
1223 evaspixmapsink->dst_roi.x, evaspixmapsink->dst_roi.y, evaspixmapsink->dst_roi.w, evaspixmapsink->dst_roi.h,
1224 result.x, result.y, result.w, result.h);
1229 GST_DEBUG_OBJECT (evaspixmapsink, "GEO_METHOD : src(%dx%d), dst(%dx%d), result(%dx%d), result_x(%d), result_y(%d)",
1230 src.w,src.h,dst.w,dst.h,result.w,result.h,result.x,result.y);
1232 switch( evaspixmapsink->rotate_angle ) {
1245 GST_WARNING_OBJECT( evaspixmapsink, "Unsupported rotation [%d]... set DEGREE 0.",
1246 evaspixmapsink->rotate_angle );
1250 /* set display rotation */
1251 if (atom_rotation == None) {
1252 atom_rotation = XInternAtom(evaspixmapsink->xcontext->disp, "_USER_WM_PORT_ATTRIBUTE_ROTATION", False);
1255 ret = XvSetPortAttribute(evaspixmapsink->xcontext->disp, evaspixmapsink->xcontext->xv_port_id, atom_rotation, rotate);
1256 if (ret != Success) {
1257 GST_ERROR_OBJECT( evaspixmapsink, "XvSetPortAttribute failed[%d]. disp[%x],xv_port_id[%d],atom[%x],rotate[%d]",
1258 ret, evaspixmapsink->xcontext->disp, evaspixmapsink->xcontext->xv_port_id, atom_rotation, rotate );
1262 /* set display flip */
1263 if (atom_hflip == None) {
1264 atom_hflip = XInternAtom(evaspixmapsink->xcontext->disp, "_USER_WM_PORT_ATTRIBUTE_HFLIP", False);
1266 if (atom_vflip == None) {
1267 atom_vflip = XInternAtom(evaspixmapsink->xcontext->disp, "_USER_WM_PORT_ATTRIBUTE_VFLIP", False);
1270 switch (evaspixmapsink->flip) {
1271 case FLIP_HORIZONTAL:
1289 GST_INFO_OBJECT(evaspixmapsink, "set rotate %d HFLIP %d, VFLIP %d", rotate, set_hflip, set_vflip);
1291 ret = XvSetPortAttribute(evaspixmapsink->xcontext->disp, evaspixmapsink->xcontext->xv_port_id, atom_hflip, set_hflip);
1292 if (ret != Success) {
1293 GST_WARNING("set HFLIP failed[%d]. disp[%x],xv_port_id[%d],atom[%x],hflip[%d]",
1294 ret, evaspixmapsink->xcontext->disp, evaspixmapsink->xcontext->xv_port_id, atom_hflip, set_hflip);
1296 ret = XvSetPortAttribute(evaspixmapsink->xcontext->disp, evaspixmapsink->xcontext->xv_port_id, atom_vflip, set_vflip);
1297 if (ret != Success) {
1298 GST_WARNING("set VFLIP failed[%d]. disp[%x],xv_port_id[%d],atom[%x],vflip[%d]",
1299 ret, evaspixmapsink->xcontext->disp, evaspixmapsink->xcontext->xv_port_id, atom_vflip, set_vflip);
1303 result.x = result.y = 0;
1304 result.w = evaspixmapsink->xpixmap[idx]->width;
1305 result.h = evaspixmapsink->xpixmap[idx]->height;
1306 GST_INFO_OBJECT (evaspixmapsink, "USE ORIGIN SIZE, no geometry method, no rotation/flip" );
1309 g_mutex_lock (evaspixmapsink->x_lock);
1311 /* We scale to the pixmap's geometry */
1313 if (evaspixmapsink->xcontext->use_xshm) {
1314 GST_LOG_OBJECT (evaspixmapsink,"XvShmPutImage with image %dx%d and pixmap %dx%d, from xvimage %"
1316 evaspixmapbuf->width, evaspixmapbuf->height,
1317 evaspixmapsink->render_rect.w, evaspixmapsink->render_rect.h, evaspixmapbuf);
1319 /* Trim as proper size */
1320 if (src_input.w % 2 == 1) {
1323 if (src_input.h % 2 == 1) {
1327 GST_LOG_OBJECT (evaspixmapsink, "screen[%dx%d],pixmap[%d,%d,%dx%d],method[%d],rotate[%d],src[%dx%d],dst[%d,%d,%dx%d],input[%d,%d,%dx%d],result[%d,%d,%dx%d]",
1328 evaspixmapsink->scr_w, evaspixmapsink->scr_h,
1329 evaspixmapsink->xpixmap[idx]->x, evaspixmapsink->xpixmap[idx]->y, evaspixmapsink->xpixmap[idx]->width, evaspixmapsink->xpixmap[idx]->height,
1330 evaspixmapsink->display_geometry_method, rotate,
1331 src_origin.w, src_origin.h,
1332 dst.x, dst.y, dst.w, dst.h,
1333 src_input.x, src_input.y, src_input.w, src_input.h,
1334 result.x, result.y, result.w, result.h );
1336 if (evaspixmapsink->visible) {
1337 ret = XvShmPutImage (evaspixmapsink->xcontext->disp,
1338 evaspixmapsink->xcontext->xv_port_id,
1339 evaspixmapsink->xpixmap[idx]->pixmap,
1340 evaspixmapsink->xpixmap[idx]->gc, evaspixmapbuf->xvimage,
1341 src_input.x, src_input.y, src_input.w, src_input.h,
1342 result.x, result.y, result.w, result.h, FALSE);
1343 GST_LOG_OBJECT (evaspixmapsink, "XvShmPutImage return value [%d]", ret );
1346 GST_WARNING_OBJECT (evaspixmapsink, "visible is FALSE. skip this image..." );
1349 #endif /* HAVE_XSHM */
1351 if (evaspixmapsink->visible) {
1352 XvPutImage (evaspixmapsink->xcontext->disp,
1353 evaspixmapsink->xcontext->xv_port_id,
1354 evaspixmapsink->xpixmap[idx]->pixmap,
1355 evaspixmapsink->xpixmap[idx]->gc, evaspixmapbuf->xvimage,
1356 evaspixmapsink->disp_x, evaspixmapsink->disp_y,
1357 evaspixmapsink->disp_width, evaspixmapsink->disp_height,
1358 result.x, result.y, result.w, result.h);
1360 GST_WARNING_OBJECT (evaspixmapsink, "visible is FALSE. skip this image..." );
1363 XSync (evaspixmapsink->xcontext->disp, FALSE);
1365 g_mutex_unlock (evaspixmapsink->x_lock);
1366 g_mutex_unlock (evaspixmapsink->flow_lock);
1368 MMTA_ACUM_ITEM_END("evaspixmapsink evaspixmap_buffer_put()", FALSE);
1374 drm_init(GstEvasPixmapSink *evaspixmapsink)
1382 char *driverName = NULL;
1383 char *deviceName = NULL;
1384 struct drm_auth auth_arg = {0};
1386 evaspixmapsink->drm_fd = -1;
1388 dpy = XOpenDisplay(0);
1391 if (!DRI2QueryExtension(dpy, &eventBase, &errorBase)) {
1392 GST_ERROR_OBJECT (evaspixmapsink,"failed to DRI2QueryExtension()");
1396 if (!DRI2QueryVersion(dpy, &dri2Major, &dri2Minor)) {
1397 GST_ERROR_OBJECT (evaspixmapsink,"failed to DRI2QueryVersion");
1401 if (!DRI2Connect(dpy, RootWindow(dpy, DefaultScreen(dpy)), &driverName, &deviceName)) {
1402 GST_ERROR_OBJECT (evaspixmapsink,"failed to DRI2Connect");
1406 if (!driverName || !deviceName) {
1407 GST_ERROR_OBJECT (evaspixmapsink,"driverName or deviceName is not valid");
1411 GST_INFO_OBJECT (evaspixmapsink,"Open drm device : %s", deviceName);
1413 /* get the drm_fd though opening the deviceName */
1414 evaspixmapsink->drm_fd = open(deviceName, O_RDWR);
1415 if (evaspixmapsink->drm_fd < 0) {
1416 GST_ERROR_OBJECT (evaspixmapsink,"cannot open drm device (%s)", deviceName);
1420 /* get magic from drm to authentication */
1421 if (ioctl(evaspixmapsink->drm_fd, DRM_IOCTL_GET_MAGIC, &auth_arg)) {
1422 GST_ERROR_OBJECT (evaspixmapsink,"cannot get drm auth magic");
1423 close(evaspixmapsink->drm_fd);
1424 evaspixmapsink->drm_fd = -1;
1428 if (!DRI2Authenticate(dpy, RootWindow(dpy, DefaultScreen(dpy)), auth_arg.magic)) {
1429 GST_ERROR_OBJECT (evaspixmapsink,"cannot get drm authentication from X");
1430 close(evaspixmapsink->drm_fd);
1431 evaspixmapsink->drm_fd = -1;
1435 /* init gem handle */
1436 for (i = 0; i < MAX_GEM_BUFFER_NUM; i++) {
1437 evaspixmapsink->gem_info[i].dmabuf_fd = 0;
1438 evaspixmapsink->gem_info[i].gem_handle = 0;
1439 evaspixmapsink->gem_info[i].gem_name = 0;
1461 drm_fini(GstEvasPixmapSink *evaspixmapsink)
1463 if (evaspixmapsink->drm_fd >= 0) {
1464 GST_INFO_OBJECT (evaspixmapsink,"close drm_fd(%d)", evaspixmapsink->drm_fd);
1465 close(evaspixmapsink->drm_fd);
1466 evaspixmapsink->drm_fd = -1;
1471 drm_init_convert_dmabuf_gemname(GstEvasPixmapSink *evaspixmapsink, int dmabuf_fd)
1473 struct drm_prime_handle prime_arg = {0,};
1474 struct drm_gem_flink flink_arg = {0,};
1477 if (evaspixmapsink->drm_fd < 0) {
1478 GST_ERROR_OBJECT (evaspixmapsink,"DRM is not opened");
1482 if (dmabuf_fd <= 0) {
1483 GST_DEBUG_OBJECT (evaspixmapsink,"Ignore wrong dmabuf fd(%d)", dmabuf_fd); /* temporarily change log level to DEBUG for reducing WARNING level log */
1487 /* check duplicated dmabuf fd */
1488 for (i = 0 ; i < MAX_GEM_BUFFER_NUM ; i++) {
1489 if (evaspixmapsink->gem_info[i].dmabuf_fd == dmabuf_fd) {
1490 GST_LOG_OBJECT (evaspixmapsink,"already got fd(%u) with name(%u)", dmabuf_fd, evaspixmapsink->gem_info[i].gem_name);
1491 return evaspixmapsink->gem_info[i].gem_name;
1494 if (evaspixmapsink->gem_info[i].dmabuf_fd == 0) {
1495 GST_LOG_OBJECT (evaspixmapsink,"empty gem_info[%d] found", i);
1500 if (i == MAX_GEM_BUFFER_NUM) {
1501 GST_WARNING_OBJECT (evaspixmapsink,"too many buffers[dmabuf_fd(%d). skip it]", dmabuf_fd);
1505 evaspixmapsink->gem_info[i].dmabuf_fd = dmabuf_fd;
1506 prime_arg.fd = dmabuf_fd;
1507 if (ioctl(evaspixmapsink->drm_fd, DRM_IOCTL_PRIME_FD_TO_HANDLE, &prime_arg)) {
1508 GST_ERROR_OBJECT (evaspixmapsink,"non dmabuf fd(%d)", dmabuf_fd);
1512 evaspixmapsink->gem_info[i].gem_handle = prime_arg.handle;
1513 GST_LOG_OBJECT (evaspixmapsink,"gem_info[%d].gem_handle = %u", i, prime_arg.handle);
1515 flink_arg.handle = prime_arg.handle;
1516 if (ioctl(evaspixmapsink->drm_fd, DRM_IOCTL_GEM_FLINK, &flink_arg)) {
1517 GST_ERROR_OBJECT (evaspixmapsink,"cannot convert drm handle to name");
1521 evaspixmapsink->gem_info[i].gem_name = flink_arg.name;
1522 GST_LOG_OBJECT (evaspixmapsink,"gem_info[%d].gem_name = %u", i, flink_arg.name);
1524 return flink_arg.name;
1528 drm_fini_close_gem_handle(GstEvasPixmapSink *evaspixmapsink)
1531 if (evaspixmapsink->drm_fd >= 0) {
1532 for (i = 0; i < MAX_GEM_BUFFER_NUM; i++) {
1533 if (evaspixmapsink->gem_info[i].dmabuf_fd > 0) {
1534 GST_INFO_OBJECT (evaspixmapsink,"close gem_handle(%u)", evaspixmapsink->gem_info[i].gem_handle);
1535 drm_close_gem(evaspixmapsink, evaspixmapsink->gem_info[i].gem_handle);
1536 evaspixmapsink->gem_info[i].dmabuf_fd = 0;
1537 evaspixmapsink->gem_info[i].gem_handle = 0;
1538 evaspixmapsink->gem_info[i].gem_name = 0;
1547 drm_close_gem(GstEvasPixmapSink *evaspixmapsink, unsigned int gem_handle)
1549 struct drm_gem_close close_arg = {0,};
1551 if (evaspixmapsink->drm_fd < 0) {
1552 GST_ERROR_OBJECT (evaspixmapsink,"DRM is not opened");
1556 if (gem_handle == 0) {
1557 GST_ERROR_OBJECT (evaspixmapsink,"invalid gem_handle(%d)",gem_handle);
1561 close_arg.handle = gem_handle;
1562 if (gem_handle > 0 && ioctl(evaspixmapsink->drm_fd, DRM_IOCTL_GEM_CLOSE, &close_arg)) {
1563 GST_ERROR_OBJECT (evaspixmapsink,"cannot close drm gem handle(%d)", gem_handle);
1570 /* This function destroys a GstXPixmap */
1572 gst_evaspixmapsink_xpixmap_destroy (GstEvasPixmapSink *evaspixmapsink, GstXPixmap *xpixmap)
1574 g_return_if_fail (xpixmap != NULL);
1575 g_return_if_fail (GST_IS_EVASPIXMAPSINK (evaspixmapsink));
1577 g_mutex_lock (evaspixmapsink->x_lock);
1579 if(xpixmap->pixmap) {
1580 GST_LOG_OBJECT (evaspixmapsink,"Free pixmap(%d)", xpixmap->pixmap);
1581 XFreePixmap(evaspixmapsink->xcontext->disp, xpixmap->pixmap);
1582 xpixmap->pixmap = NULL;
1586 XFreeGC (evaspixmapsink->xcontext->disp, xpixmap->gc);
1589 XSync (evaspixmapsink->xcontext->disp, FALSE);
1591 g_mutex_unlock (evaspixmapsink->x_lock);
1597 gst_evaspixmapsink_xpixmap_update_geometry (GstEvasPixmapSink *evaspixmapsink, int idx)
1600 XWindowAttributes root_attr;
1602 int cur_pixmap_x = 0;
1603 int cur_pixmap_y = 0;
1604 unsigned int cur_pixmap_width = 0;
1605 unsigned int cur_pixmap_height = 0;
1606 unsigned int cur_pixmap_border_width = 0;
1607 unsigned int cur_pixmap_depth = 0;
1609 g_return_if_fail (GST_IS_EVASPIXMAPSINK (evaspixmapsink));
1611 /* Update the window geometry */
1612 g_mutex_lock (evaspixmapsink->x_lock);
1613 if (G_UNLIKELY (evaspixmapsink->xpixmap[idx] == NULL)) {
1614 g_mutex_unlock (evaspixmapsink->x_lock);
1618 /* Get root window and size of current pixmap */
1619 XGetGeometry( evaspixmapsink->xcontext->disp, evaspixmapsink->xpixmap[idx]->pixmap, &root_window,
1620 &cur_pixmap_x, &cur_pixmap_y, /* relative x, y, for pixmap these are alway 0 */
1621 &cur_pixmap_width, &cur_pixmap_height,
1622 &cur_pixmap_border_width, &cur_pixmap_depth ); /* cur_pixmap_border_width, cur_pixmap_depth are not used */
1624 evaspixmapsink->xpixmap[idx]->width = cur_pixmap_width;
1625 evaspixmapsink->xpixmap[idx]->height = cur_pixmap_height;
1627 evaspixmapsink->xpixmap[idx]->x = cur_pixmap_x;
1628 evaspixmapsink->xpixmap[idx]->y = cur_pixmap_y;
1630 /* Get size of root window == size of screen */
1631 XGetWindowAttributes(evaspixmapsink->xcontext->disp, root_window, &root_attr);
1633 evaspixmapsink->scr_w = root_attr.width;
1634 evaspixmapsink->scr_h = root_attr.height;
1636 if (!evaspixmapsink->have_render_rect) {
1637 evaspixmapsink->render_rect.x = evaspixmapsink->render_rect.y = 0;
1638 evaspixmapsink->render_rect.w = cur_pixmap_width;
1639 evaspixmapsink->render_rect.h = cur_pixmap_height;
1642 GST_LOG_OBJECT (evaspixmapsink,"screen size %dx%d, current pixmap geometry %d,%d,%dx%d, render_rect %d,%d,%dx%d",
1643 evaspixmapsink->scr_w, evaspixmapsink->scr_h,
1644 evaspixmapsink->xpixmap[idx]->x, evaspixmapsink->xpixmap[idx]->y,
1645 evaspixmapsink->xpixmap[idx]->width, evaspixmapsink->xpixmap[idx]->height,
1646 evaspixmapsink->render_rect.x, evaspixmapsink->render_rect.y,
1647 evaspixmapsink->render_rect.w, evaspixmapsink->render_rect.h);
1649 g_mutex_unlock (evaspixmapsink->x_lock);
1653 gst_evaspixmapsink_xpixmap_clear (GstEvasPixmapSink *evaspixmapsink, GstXPixmap *xpixmap)
1655 g_return_if_fail (xpixmap != NULL);
1656 g_return_if_fail (GST_IS_EVASPIXMAPSINK (evaspixmapsink));
1658 if (!xpixmap->pixmap) {
1659 GST_WARNING_OBJECT (evaspixmapsink,"pixmap was not created..");
1663 g_mutex_lock (evaspixmapsink->x_lock);
1665 if (!evaspixmapsink->xcontext) {
1666 GST_WARNING_OBJECT (evaspixmapsink,"xcontext is null..");
1669 if (evaspixmapsink->stop_video) {
1670 XvStopVideo (evaspixmapsink->xcontext->disp, evaspixmapsink->xcontext->xv_port_id, xpixmap->pixmap);
1672 XSetForeground (evaspixmapsink->xcontext->disp, xpixmap->gc, evaspixmapsink->xcontext->black);
1673 XFillRectangle (evaspixmapsink->xcontext->disp, xpixmap->pixmap, xpixmap->gc,
1674 evaspixmapsink->render_rect.x, evaspixmapsink->render_rect.y, evaspixmapsink->render_rect.w, evaspixmapsink->render_rect.h);
1676 XSync (evaspixmapsink->xcontext->disp, FALSE);
1678 g_mutex_unlock (evaspixmapsink->x_lock);
1681 /* This function commits our internal colorbalance settings to our grabbed Xv
1682 port. If the xcontext is not initialized yet it simply returns */
1684 gst_evaspixmapsink_update_colorbalance (GstEvasPixmapSink *evaspixmapsink)
1686 GList *channels = NULL;
1688 g_return_if_fail (GST_IS_EVASPIXMAPSINK (evaspixmapsink));
1690 /* If we haven't initialized the X context we can't update anything */
1691 if (evaspixmapsink->xcontext == NULL)
1694 /* Don't set the attributes if they haven't been changed, to avoid
1695 * rounding errors changing the values */
1696 if (!evaspixmapsink->cb_changed)
1699 /* For each channel of the colorbalance we calculate the correct value
1700 doing range conversion and then set the Xv port attribute to match our
1702 channels = evaspixmapsink->xcontext->channels_list;
1705 if (channels->data && GST_IS_COLOR_BALANCE_CHANNEL (channels->data)) {
1706 GstColorBalanceChannel *channel = NULL;
1709 gdouble convert_coef;
1711 channel = GST_COLOR_BALANCE_CHANNEL (channels->data);
1712 g_object_ref (channel);
1714 /* Our range conversion coef */
1715 convert_coef = (channel->max_value - channel->min_value) / 2000.0;
1717 if (g_ascii_strcasecmp (channel->label, "XV_HUE") == 0) {
1718 value = evaspixmapsink->hue;
1719 } else if (g_ascii_strcasecmp (channel->label, "XV_SATURATION") == 0) {
1720 value = evaspixmapsink->saturation;
1721 } else if (g_ascii_strcasecmp (channel->label, "XV_CONTRAST") == 0) {
1722 value = evaspixmapsink->contrast;
1723 } else if (g_ascii_strcasecmp (channel->label, "XV_BRIGHTNESS") == 0) {
1724 value = evaspixmapsink->brightness;
1726 g_warning ("got an unknown channel %s", channel->label);
1727 g_object_unref (channel);
1731 /* Committing to Xv port */
1732 g_mutex_lock (evaspixmapsink->x_lock);
1734 XInternAtom (evaspixmapsink->xcontext->disp, channel->label, True);
1735 if (prop_atom != None) {
1738 floor (0.5 + (value + 1000) * convert_coef + channel->min_value);
1739 XvSetPortAttribute (evaspixmapsink->xcontext->disp,
1740 evaspixmapsink->xcontext->xv_port_id, prop_atom, xv_value);
1742 g_mutex_unlock (evaspixmapsink->x_lock);
1744 g_object_unref (channel);
1746 channels = g_list_next (channels);
1751 gst_lookup_xv_port_from_adaptor (GstXContext *xcontext, XvAdaptorInfo *adaptors, int adaptor_no)
1756 /* Do we support XvImageMask ? */
1757 if (!(adaptors[adaptor_no].type & XvImageMask)) {
1758 GST_DEBUG ("XV Adaptor %s has no support for XvImageMask", adaptors[adaptor_no].name);
1762 /* We found such an adaptor, looking for an available port */
1763 for (j = 0; j < adaptors[adaptor_no].num_ports && !xcontext->xv_port_id; j++) {
1764 /* We try to grab the port */
1765 res = XvGrabPort (xcontext->disp, adaptors[adaptor_no].base_id + j, 0);
1766 if (Success == res) {
1767 xcontext->xv_port_id = adaptors[adaptor_no].base_id + j;
1768 GST_DEBUG ("XV Adaptor %s with %ld ports", adaptors[adaptor_no].name, adaptors[adaptor_no].num_ports);
1770 GST_DEBUG ("GrabPort %d for XV Adaptor %s failed: %d", j, adaptors[adaptor_no].name, res);
1775 /* This function generates a caps with all supported format by the first
1776 Xv grabable port we find. We store each one of the supported formats in a
1777 format list and append the format to a newly created caps that we return
1778 If this function does not return NULL because of an error, it also grabs
1779 the port via XvGrabPort */
1781 gst_evaspixmapsink_get_xv_support (GstEvasPixmapSink *evaspixmapsink, GstXContext *xcontext)
1784 XvAdaptorInfo *adaptors;
1786 XvImageFormatValues *formats = NULL;
1788 XvEncodingInfo *encodings = NULL;
1789 gulong max_w = G_MAXINT, max_h = G_MAXINT;
1790 GstCaps *caps = NULL;
1791 GstCaps *rgb_caps = NULL;
1793 g_return_val_if_fail (xcontext != NULL, NULL);
1795 /* First let's check that XVideo extension is available */
1796 if (!XQueryExtension (xcontext->disp, "XVideo", &i, &i, &i)) {
1797 GST_ELEMENT_ERROR (evaspixmapsink, RESOURCE, SETTINGS,
1798 ("Could not initialise Xv output"),
1799 ("XVideo extension is not available"));
1803 /* Then we get adaptors list */
1804 if (Success != XvQueryAdaptors (xcontext->disp, xcontext->root,
1805 &xcontext->nb_adaptors, &adaptors)) {
1806 GST_ELEMENT_ERROR (evaspixmapsink, RESOURCE, SETTINGS,
1807 ("Could not initialise Xv output"),
1808 ("Failed getting XV adaptors list"));
1812 xcontext->xv_port_id = 0;
1814 GST_DEBUG_OBJECT (evaspixmapsink,"Found %u XV adaptor(s)", xcontext->nb_adaptors);
1816 xcontext->adaptors =
1817 (gchar **) g_malloc0 (xcontext->nb_adaptors * sizeof (gchar *));
1819 /* Now fill up our adaptor name array */
1820 for (i = 0; i < xcontext->nb_adaptors; i++) {
1821 xcontext->adaptors[i] = g_strdup (adaptors[i].name);
1824 if (evaspixmapsink->adaptor_no < xcontext->nb_adaptors) {
1825 /* Find xv port from user defined adaptor */
1826 gst_lookup_xv_port_from_adaptor (xcontext, adaptors, evaspixmapsink->adaptor_no);
1829 if (!xcontext->xv_port_id) {
1830 /* Now search for an adaptor that supports XvImageMask */
1831 for (i = 0; i < xcontext->nb_adaptors && !xcontext->xv_port_id; i++) {
1832 gst_lookup_xv_port_from_adaptor (xcontext, adaptors, i);
1833 evaspixmapsink->adaptor_no = i;
1837 XvFreeAdaptorInfo (adaptors);
1839 if (!xcontext->xv_port_id) {
1840 evaspixmapsink->adaptor_no = -1;
1841 GST_ELEMENT_ERROR (evaspixmapsink, RESOURCE, BUSY,
1842 ("Could not initialise Xv output"), ("No port available"));
1846 /* Set XV_AUTOPAINT_COLORKEY and XV_DOUBLE_BUFFER and XV_COLORKEY */
1848 int count, todo = 3;
1849 XvAttribute *const attr = XvQueryPortAttributes (xcontext->disp,
1850 xcontext->xv_port_id, &count);
1851 static const char autopaint[] = "XV_AUTOPAINT_COLORKEY";
1852 static const char dbl_buffer[] = "XV_DOUBLE_BUFFER";
1853 static const char colorkey[] = "XV_COLORKEY";
1855 GST_DEBUG_OBJECT (evaspixmapsink,"Checking %d Xv port attributes", count);
1857 evaspixmapsink->have_autopaint_colorkey = FALSE;
1858 evaspixmapsink->have_double_buffer = FALSE;
1859 evaspixmapsink->have_colorkey = FALSE;
1861 for (i = 0; ((i < count) && todo); i++)
1862 if (!strcmp (attr[i].name, autopaint)) {
1863 const Atom atom = XInternAtom (xcontext->disp, autopaint, False);
1865 /* turn on autopaint colorkey */
1866 XvSetPortAttribute (xcontext->disp, xcontext->xv_port_id, atom,
1867 (evaspixmapsink->autopaint_colorkey ? 1 : 0));
1869 evaspixmapsink->have_autopaint_colorkey = TRUE;
1870 } else if (!strcmp (attr[i].name, dbl_buffer)) {
1871 const Atom atom = XInternAtom (xcontext->disp, dbl_buffer, False);
1873 XvSetPortAttribute (xcontext->disp, xcontext->xv_port_id, atom,
1874 (evaspixmapsink->double_buffer ? 1 : 0));
1876 evaspixmapsink->have_double_buffer = TRUE;
1877 } else if (!strcmp (attr[i].name, colorkey)) {
1878 /* Set the colorkey, default is something that is dark but hopefully
1879 * won't randomly appear on the screen elsewhere (ie not black or greys)
1880 * can be overridden by setting "colorkey" property
1882 const Atom atom = XInternAtom (xcontext->disp, colorkey, False);
1884 gboolean set_attr = TRUE;
1887 /* set a colorkey in the right format RGB565/RGB888
1888 * We only handle these 2 cases, because they're the only types of
1889 * devices we've encountered. If we don't recognise it, leave it alone
1891 cr = (evaspixmapsink->colorkey >> 16);
1892 cg = (evaspixmapsink->colorkey >> 8) & 0xFF;
1893 cb = (evaspixmapsink->colorkey) & 0xFF;
1894 switch (xcontext->depth) {
1895 case 16: /* RGB 565 */
1899 ckey = (cr << 11) | (cg << 5) | cb;
1902 case 32: /* RGB 888 / ARGB 8888 */
1903 ckey = (cr << 16) | (cg << 8) | cb;
1906 GST_DEBUG_OBJECT (evaspixmapsink,"Unknown bit depth %d for Xv Colorkey - not adjusting", xcontext->depth);
1912 ckey = CLAMP (ckey, (guint32) attr[i].min_value,
1913 (guint32) attr[i].max_value);
1914 GST_LOG_OBJECT (evaspixmapsink,"Setting color key for display depth %d to 0x%x", xcontext->depth, ckey);
1916 XvSetPortAttribute (xcontext->disp, xcontext->xv_port_id, atom,
1920 evaspixmapsink->have_colorkey = TRUE;
1926 /* Get the list of encodings supported by the adapter and look for the
1927 * XV_IMAGE encoding so we can determine the maximum width and height
1929 XvQueryEncodings (xcontext->disp, xcontext->xv_port_id, &nb_encodings,
1932 for (i = 0; i < nb_encodings; i++) {
1933 GST_LOG_OBJECT (evaspixmapsink,
1934 "Encoding %d, name %s, max wxh %lux%lu rate %d/%d",
1935 i, encodings[i].name, encodings[i].width, encodings[i].height,
1936 encodings[i].rate.numerator, encodings[i].rate.denominator);
1937 if (strcmp (encodings[i].name, "XV_IMAGE") == 0) {
1938 max_w = encodings[i].width;
1939 max_h = encodings[i].height;
1940 evaspixmapsink->scr_w = max_w;
1941 evaspixmapsink->scr_h = max_h;
1945 XvFreeEncodingInfo (encodings);
1947 /* We get all image formats supported by our port */
1948 formats = XvListImageFormats (xcontext->disp,
1949 xcontext->xv_port_id, &nb_formats);
1950 caps = gst_caps_new_empty ();
1951 for (i = 0; i < nb_formats; i++) {
1952 GstCaps *format_caps = NULL;
1953 gboolean is_rgb_format = FALSE;
1955 /* We set the image format of the xcontext to an existing one. This
1956 is just some valid image format for making our xshm calls check before
1957 caps negotiation really happens. */
1958 xcontext->im_format = formats[i].id;
1960 switch (formats[i].type) {
1963 XvImageFormatValues *fmt = &(formats[i]);
1964 gint endianness = G_BIG_ENDIAN;
1966 if (fmt->byte_order == LSBFirst) {
1967 /* our caps system handles 24/32bpp RGB as big-endian. */
1968 if (fmt->bits_per_pixel == 24 || fmt->bits_per_pixel == 32) {
1969 fmt->red_mask = GUINT32_TO_BE (fmt->red_mask);
1970 fmt->green_mask = GUINT32_TO_BE (fmt->green_mask);
1971 fmt->blue_mask = GUINT32_TO_BE (fmt->blue_mask);
1973 if (fmt->bits_per_pixel == 24) {
1974 fmt->red_mask >>= 8;
1975 fmt->green_mask >>= 8;
1976 fmt->blue_mask >>= 8;
1979 endianness = G_LITTLE_ENDIAN;
1982 format_caps = gst_caps_new_simple ("video/x-raw-rgb",
1983 "endianness", G_TYPE_INT, endianness,
1984 "depth", G_TYPE_INT, fmt->depth,
1985 "bpp", G_TYPE_INT, fmt->bits_per_pixel,
1986 "red_mask", G_TYPE_INT, fmt->red_mask,
1987 "green_mask", G_TYPE_INT, fmt->green_mask,
1988 "blue_mask", G_TYPE_INT, fmt->blue_mask,
1989 "width", GST_TYPE_INT_RANGE, 1, max_w,
1990 "height", GST_TYPE_INT_RANGE, 1, max_h,
1991 "framerate", GST_TYPE_FRACTION_RANGE, 0, 1, G_MAXINT, 1, NULL);
1993 is_rgb_format = TRUE;
1997 format_caps = gst_caps_new_simple ("video/x-raw-yuv",
1998 "format", GST_TYPE_FOURCC, formats[i].id,
1999 "width", GST_TYPE_INT_RANGE, 1, max_w,
2000 "height", GST_TYPE_INT_RANGE, 1, max_h,
2001 "framerate", GST_TYPE_FRACTION_RANGE, 0, 1, G_MAXINT, 1, NULL);
2004 g_assert_not_reached ();
2009 GstEvasPixmapFormat *format = NULL;
2011 format = g_new0 (GstEvasPixmapFormat, 1);
2013 format->format = formats[i].id;
2014 format->caps = gst_caps_copy (format_caps);
2015 xcontext->formats_list = g_list_append (xcontext->formats_list, format);
2018 if (is_rgb_format) {
2019 if (rgb_caps == NULL)
2020 rgb_caps = format_caps;
2022 gst_caps_append (rgb_caps, format_caps);
2024 gst_caps_append (caps, format_caps);
2028 /* Collected all caps into either the caps or rgb_caps structures.
2029 * Append rgb_caps on the end of YUV, so that YUV is always preferred */
2031 gst_caps_append (caps, rgb_caps);
2036 GST_DEBUG_OBJECT (evaspixmapsink,"Generated the following caps: %" GST_PTR_FORMAT, caps);
2038 if (gst_caps_is_empty (caps)) {
2039 gst_caps_unref (caps);
2040 XvUngrabPort (xcontext->disp, xcontext->xv_port_id, 0);
2041 GST_ELEMENT_ERROR (evaspixmapsink, STREAM, WRONG_TYPE, (NULL),
2042 ("No supported format found"));
2050 gst_evaspixmapsink_event_thread (GstEvasPixmapSink * evaspixmapsink)
2052 g_return_val_if_fail (GST_IS_EVASPIXMAPSINK (evaspixmapsink), NULL);
2053 int damage_base = 0;
2054 int damage_err_base = 0;
2055 int damage_case = 0;
2058 Display *disp = NULL;
2060 GST_OBJECT_LOCK (evaspixmapsink);
2062 if (evaspixmapsink->xcontext && evaspixmapsink->xcontext->disp) {
2063 disp = evaspixmapsink->xcontext->disp;
2065 GST_ERROR_OBJECT (evaspixmapsink,"evaspixmapsink->xcontext(->disp) is not ready");
2069 if (!XDamageQueryExtension(evaspixmapsink->xcontext->disp, &damage_base, &damage_err_base)) {
2070 GST_ERROR_OBJECT (evaspixmapsink,"XDamageQueryExtension() failed");
2073 damage_case = (int)damage_base + XDamageNotify;
2075 while (evaspixmapsink->running) {
2076 GST_OBJECT_UNLOCK (evaspixmapsink);
2078 g_mutex_lock (evaspixmapsink->x_lock);
2079 while (XPending (disp)) {
2080 XNextEvent (disp, &e);
2081 if (e.type == damage_case ) {
2082 XDamageNotifyEvent *damage_ev = (XDamageNotifyEvent *)&e;
2083 for (i = 0; i < evaspixmapsink->num_of_pixmaps; i++) {
2084 GstXPixmap *xpixmap = evaspixmapsink->xpixmap[i];
2085 if (xpixmap && damage_ev->drawable == xpixmap->pixmap) {
2086 g_mutex_lock(evaspixmapsink->pixmap_ref_lock);
2088 /* set it only if damage event comes from _buffer_put() */
2089 xpixmap->damaged_time = (gint)get_millis_time();
2091 GST_LOG_OBJECT (evaspixmapsink,"event_handler : got a damage event for pixmap(%d), refcount(%d), damaged_time(%d)",
2092 xpixmap->pixmap, xpixmap->ref, xpixmap->damaged_time);
2093 evaspixmapsink->last_damaged_pixmap_idx = i;
2094 g_mutex_unlock(evaspixmapsink->pixmap_ref_lock);
2096 __ta__("evaspixmapsink ecore_pipe_write", ecore_pipe_write(evaspixmapsink->epipe, evaspixmapsink, sizeof(GstEvasPixmapSink)););
2097 GST_DEBUG_OBJECT (evaspixmapsink,"event_handler : after call ecore_pipe_write() for pixmap(%d)", xpixmap->pixmap);
2098 XDamageSubtract (evaspixmapsink->xcontext->disp, evaspixmapsink->damage[i], None, None );
2103 if (i == evaspixmapsink->num_of_pixmaps) {
2104 GST_WARNING_OBJECT (evaspixmapsink,"event_handler : could not find corresponding pixmap with this damage event(%d)", damage_ev->drawable);
2107 GST_LOG_OBJECT (evaspixmapsink,"event_handler : unidentified event(%d)", e.type);
2111 //XSync (disp, FALSE);
2112 g_mutex_unlock (evaspixmapsink->x_lock);
2114 g_usleep (G_USEC_PER_SEC / 40);
2115 GST_OBJECT_LOCK (evaspixmapsink);
2117 GST_OBJECT_UNLOCK (evaspixmapsink);
2122 gst_evaspixmapsink_manage_event_thread (GstEvasPixmapSink *evaspixmapsink)
2124 GThread *thread = NULL;
2126 /* don't start the thread too early */
2127 if (evaspixmapsink->xcontext == NULL) {
2128 GST_ERROR_OBJECT (evaspixmapsink,"xcontext is NULL..");
2132 GST_OBJECT_LOCK (evaspixmapsink);
2134 if (!evaspixmapsink->event_thread) {
2135 /* Setup our event listening thread */
2136 GST_DEBUG_OBJECT (evaspixmapsink,"run xevent thread");
2137 evaspixmapsink->running = TRUE;
2138 evaspixmapsink->event_thread = g_thread_create ( (GThreadFunc) gst_evaspixmapsink_event_thread, evaspixmapsink, TRUE, NULL);
2140 GST_WARNING_OBJECT (evaspixmapsink,"there already existed the event_thread.. keep going");
2141 /* Do not finalize the thread in here, Only finalize the thread by calling gst_evaspixmapsink_reset() */
2144 GST_OBJECT_UNLOCK (evaspixmapsink);
2148 /* This function calculates the pixel aspect ratio based on the properties
2149 * in the xcontext structure and stores it there. */
2151 gst_evaspixmapsink_calculate_pixel_aspect_ratio (GstXContext *xcontext)
2153 static const gint par[][2] = {
2154 {1, 1}, /* regular screen */
2155 {16, 15}, /* PAL TV */
2156 {11, 10}, /* 525 line Rec.601 video */
2157 {54, 59}, /* 625 line Rec.601 video */
2158 {64, 45}, /* 1280x1024 on 16:9 display */
2159 {5, 3}, /* 1280x1024 on 4:3 display */
2160 {4, 3} /* 800x600 on 16:9 display */
2167 #define DELTA(idx) (ABS (ratio - ((gdouble) par[idx][0] / par[idx][1])))
2169 /* first calculate the "real" ratio based on the X values;
2170 * which is the "physical" w/h divided by the w/h in pixels of the display */
2171 ratio = (gdouble) (xcontext->widthmm * xcontext->height)
2172 / (xcontext->heightmm * xcontext->width);
2174 /* DirectFB's X in 720x576 reports the physical dimensions wrong, so
2176 if (xcontext->width == 720 && xcontext->height == 576) {
2177 ratio = 4.0 * 576 / (3.0 * 720);
2179 GST_DEBUG ("calculated pixel aspect ratio: %f", ratio);
2180 /* now find the one from par[][2] with the lowest delta to the real one */
2184 for (i = 1; i < sizeof (par) / (sizeof (gint) * 2); ++i) {
2185 gdouble this_delta = DELTA (i);
2187 if (this_delta < delta) {
2193 GST_DEBUG ("Decided on index %d (%d/%d)", index,
2194 par[index][0], par[index][1]);
2196 g_free (xcontext->par);
2197 xcontext->par = g_new0 (GValue, 1);
2198 g_value_init (xcontext->par, GST_TYPE_FRACTION);
2199 gst_value_set_fraction (xcontext->par, par[index][0], par[index][1]);
2200 GST_DEBUG ("set xcontext PAR to %d/%d",
2201 gst_value_get_fraction_numerator (xcontext->par),
2202 gst_value_get_fraction_denominator (xcontext->par));
2205 /* This function gets the X Display and global info about it. Everything is
2206 stored in our object and will be cleaned when the object is disposed. Note
2207 here that caps for supported format are generated without any window or
2210 gst_evaspixmapsink_xcontext_get (GstEvasPixmapSink *evaspixmapsink)
2212 GstXContext *xcontext = NULL;
2213 XPixmapFormatValues *px_formats = NULL;
2214 gint nb_formats = 0, i, j, N_attr;
2215 XvAttribute *xv_attr;
2217 const char *channels[4] = { "XV_HUE", "XV_SATURATION", "XV_BRIGHTNESS", "XV_CONTRAST"};
2219 g_return_val_if_fail (GST_IS_EVASPIXMAPSINK (evaspixmapsink), NULL);
2221 xcontext = g_new0 (GstXContext, 1);
2222 xcontext->im_format = 0;
2224 g_mutex_lock (evaspixmapsink->x_lock);
2226 xcontext->disp = XOpenDisplay (evaspixmapsink->display_name);
2228 if (!xcontext->disp) {
2229 g_mutex_unlock (evaspixmapsink->x_lock);
2231 GST_ELEMENT_ERROR (evaspixmapsink, RESOURCE, WRITE, ("Could not initialise Xv output"), ("Could not open display"));
2235 xcontext->screen = DefaultScreenOfDisplay (xcontext->disp);
2236 xcontext->screen_num = DefaultScreen (xcontext->disp);
2237 xcontext->visual = DefaultVisual (xcontext->disp, xcontext->screen_num);
2238 xcontext->root = DefaultRootWindow (xcontext->disp);
2239 xcontext->white = XWhitePixel (xcontext->disp, xcontext->screen_num);
2240 xcontext->black = XBlackPixel (xcontext->disp, xcontext->screen_num);
2241 xcontext->depth = DefaultDepthOfScreen (xcontext->screen);
2243 xcontext->width = DisplayWidth (xcontext->disp, xcontext->screen_num);
2244 xcontext->height = DisplayHeight (xcontext->disp, xcontext->screen_num);
2245 xcontext->widthmm = DisplayWidthMM (xcontext->disp, xcontext->screen_num);
2246 xcontext->heightmm = DisplayHeightMM (xcontext->disp, xcontext->screen_num);
2248 GST_DEBUG_OBJECT (evaspixmapsink,"X reports %dx%d pixels and %d mm x %d mm", xcontext->width, xcontext->height, xcontext->widthmm, xcontext->heightmm);
2250 gst_evaspixmapsink_calculate_pixel_aspect_ratio (xcontext);
2251 /* We get supported pixmap formats at supported depth */
2252 px_formats = XListPixmapFormats (xcontext->disp, &nb_formats);
2255 XCloseDisplay (xcontext->disp);
2256 g_mutex_unlock (evaspixmapsink->x_lock);
2257 g_free (xcontext->par);
2259 GST_ELEMENT_ERROR (evaspixmapsink, RESOURCE, SETTINGS,
2260 ("Could not initialise Xv output"), ("Could not get pixel formats"));
2264 /* We get bpp value corresponding to our running depth */
2265 for (i = 0; i < nb_formats; i++) {
2266 if (px_formats[i].depth == xcontext->depth)
2267 xcontext->bpp = px_formats[i].bits_per_pixel;
2272 xcontext->endianness = (ImageByteOrder (xcontext->disp) == LSBFirst) ? G_LITTLE_ENDIAN : G_BIG_ENDIAN;
2274 /* our caps system handles 24/32bpp RGB as big-endian. */
2275 if ((xcontext->bpp == 24 || xcontext->bpp == 32) && xcontext->endianness == G_LITTLE_ENDIAN) {
2276 xcontext->endianness = G_BIG_ENDIAN;
2277 xcontext->visual->red_mask = GUINT32_TO_BE (xcontext->visual->red_mask);
2278 xcontext->visual->green_mask = GUINT32_TO_BE (xcontext->visual->green_mask);
2279 xcontext->visual->blue_mask = GUINT32_TO_BE (xcontext->visual->blue_mask);
2280 if (xcontext->bpp == 24) {
2281 xcontext->visual->red_mask >>= 8;
2282 xcontext->visual->green_mask >>= 8;
2283 xcontext->visual->blue_mask >>= 8;
2287 xcontext->caps = gst_evaspixmapsink_get_xv_support (evaspixmapsink, xcontext);
2289 if (!xcontext->caps) {
2290 XCloseDisplay (xcontext->disp);
2291 g_mutex_unlock (evaspixmapsink->x_lock);
2292 g_free (xcontext->par);
2294 /* GST_ELEMENT_ERROR is thrown by gst_evaspixmapsink_get_xv_support */
2298 /* Search for XShm extension support */
2299 if (XShmQueryExtension (xcontext->disp) && gst_evaspixmapsink_check_xshm_calls (xcontext)) {
2300 xcontext->use_xshm = TRUE;
2301 GST_DEBUG_OBJECT (evaspixmapsink,"evaspixmapsink is using XShm extension");
2303 #endif /* HAVE_XSHM */
2305 xcontext->use_xshm = FALSE;
2306 GST_DEBUG_OBJECT (evaspixmapsink,"evaspixmapsink is not using XShm extension");
2309 xv_attr = XvQueryPortAttributes (xcontext->disp, xcontext->xv_port_id, &N_attr);
2311 /* Generate the channels list */
2312 for (i = 0; i < (sizeof (channels) / sizeof (char *)); i++) {
2313 XvAttribute *matching_attr = NULL;
2315 /* Retrieve the property atom if it exists. If it doesn't exist,
2316 * the attribute itself must not either, so we can skip */
2317 prop_atom = XInternAtom (xcontext->disp, channels[i], True);
2318 if (prop_atom == None) {
2322 if (xv_attr != NULL) {
2323 for (j = 0; j < N_attr && matching_attr == NULL; ++j) {
2324 if (!g_ascii_strcasecmp (channels[i], xv_attr[j].name)) {
2325 matching_attr = xv_attr + j;
2330 if (matching_attr) {
2331 GstColorBalanceChannel *channel;
2332 channel = g_object_new (GST_TYPE_COLOR_BALANCE_CHANNEL, NULL);
2333 channel->label = g_strdup (channels[i]);
2334 channel->min_value = matching_attr->min_value;
2335 channel->max_value = matching_attr->max_value;
2337 xcontext->channels_list = g_list_append (xcontext->channels_list, channel);
2339 /* If the colorbalance settings have not been touched we get Xv values
2340 as defaults and update our internal variables */
2341 if (!evaspixmapsink->cb_changed) {
2343 XvGetPortAttribute (xcontext->disp, xcontext->xv_port_id, prop_atom, &val);
2344 /* Normalize val to [-1000, 1000] */
2345 val = floor (0.5 + -1000 + 2000 * (val - channel->min_value) / (double) (channel->max_value - channel->min_value));
2347 if (!g_ascii_strcasecmp (channels[i], "XV_HUE")) {
2348 evaspixmapsink->hue = val;
2349 } else if (!g_ascii_strcasecmp (channels[i], "XV_SATURATION")) {
2350 evaspixmapsink->saturation = val;
2351 } else if (!g_ascii_strcasecmp (channels[i], "XV_BRIGHTNESS")) {
2352 evaspixmapsink->brightness = val;
2353 } else if (!g_ascii_strcasecmp (channels[i], "XV_CONTRAST")) {
2354 evaspixmapsink->contrast = val;
2364 g_mutex_unlock (evaspixmapsink->x_lock);
2369 /* This function cleans the X context. Closing the Display, releasing the XV
2370 port and unrefing the caps for supported formats. */
2372 gst_evaspixmapsink_xcontext_clear (GstEvasPixmapSink *evaspixmapsink)
2374 GList *formats_list, *channels_list;
2375 GstXContext *xcontext;
2378 g_return_if_fail (GST_IS_EVASPIXMAPSINK (evaspixmapsink));
2380 GST_OBJECT_LOCK (evaspixmapsink);
2381 if (evaspixmapsink->xcontext == NULL) {
2382 GST_OBJECT_UNLOCK (evaspixmapsink);
2386 /* Take the XContext from the sink and clean it up */
2387 xcontext = evaspixmapsink->xcontext;
2388 evaspixmapsink->xcontext = NULL;
2390 GST_OBJECT_UNLOCK (evaspixmapsink);
2392 formats_list = xcontext->formats_list;
2394 while (formats_list) {
2395 GstEvasPixmapFormat *format = formats_list->data;
2397 gst_caps_unref (format->caps);
2399 formats_list = g_list_next (formats_list);
2402 if (xcontext->formats_list)
2403 g_list_free (xcontext->formats_list);
2405 channels_list = xcontext->channels_list;
2407 while (channels_list) {
2408 GstColorBalanceChannel *channel = channels_list->data;
2410 g_object_unref (channel);
2411 channels_list = g_list_next (channels_list);
2414 if (xcontext->channels_list)
2415 g_list_free (xcontext->channels_list);
2417 gst_caps_unref (xcontext->caps);
2419 for (i = 0; i < xcontext->nb_adaptors; i++) {
2420 g_free (xcontext->adaptors[i]);
2423 g_free (xcontext->adaptors);
2425 g_free (xcontext->par);
2427 g_mutex_lock (evaspixmapsink->x_lock);
2429 GST_DEBUG_OBJECT (evaspixmapsink,"Closing display and freeing X Context");
2431 XvUngrabPort (xcontext->disp, xcontext->xv_port_id, 0);
2433 XCloseDisplay (xcontext->disp);
2435 g_mutex_unlock (evaspixmapsink->x_lock);
2442 /* This function tries to get a format matching with a given caps in the
2443 supported list of formats we generated in gst_evaspixmapsink_get_xv_support */
2445 gst_evaspixmapsink_get_format_from_caps (GstEvasPixmapSink *evaspixmapsink, GstCaps *caps)
2449 g_return_val_if_fail (GST_IS_EVASPIXMAPSINK (evaspixmapsink), 0);
2451 list = evaspixmapsink->xcontext->formats_list;
2454 GstEvasPixmapFormat *format = list->data;
2457 if (gst_caps_can_intersect (caps, format->caps)) {
2458 return format->format;
2461 list = g_list_next (list);
2468 gst_evaspixmapsink_getcaps (GstBaseSink *bsink)
2470 GstEvasPixmapSink *evaspixmapsink;
2472 evaspixmapsink = GST_EVASPIXMAPSINK (bsink);
2474 if (evaspixmapsink->xcontext)
2475 return gst_caps_ref (evaspixmapsink->xcontext->caps);
2478 gst_caps_copy (gst_pad_get_pad_template_caps (GST_VIDEO_SINK_PAD
2483 gst_evaspixmapsink_setcaps (GstBaseSink *bsink, GstCaps *caps)
2485 GstEvasPixmapSink *evaspixmapsink;
2486 GstStructure *structure;
2487 guint32 im_format = 0;
2489 gint video_width, video_height;
2490 gint disp_x, disp_y;
2491 gint disp_width, disp_height;
2492 gint video_par_n, video_par_d; /* video's PAR */
2493 gint display_par_n, display_par_d; /* display's PAR */
2494 const GValue *caps_par;
2495 const GValue *caps_disp_reg;
2498 gboolean enable_last_buffer;
2500 evaspixmapsink = GST_EVASPIXMAPSINK (bsink);
2502 GST_DEBUG_OBJECT (evaspixmapsink,"In setcaps. Possible caps %" GST_PTR_FORMAT ", setting caps %" GST_PTR_FORMAT, evaspixmapsink->xcontext->caps, caps);
2504 if (!gst_caps_can_intersect (evaspixmapsink->xcontext->caps, caps)) {
2505 goto incompatible_caps;
2508 structure = gst_caps_get_structure (caps, 0);
2509 ret = gst_structure_get_int (structure, "width", &video_width);
2510 ret &= gst_structure_get_int (structure, "height", &video_height);
2511 fps = gst_structure_get_value (structure, "framerate");
2512 ret &= (fps != NULL);
2515 goto incomplete_caps;
2518 evaspixmapsink->aligned_width = video_width;
2519 evaspixmapsink->aligned_height = video_height;
2521 /* get enable-last-buffer */
2522 g_object_get(G_OBJECT(evaspixmapsink), "enable-last-buffer", &enable_last_buffer, NULL);
2523 GST_INFO_OBJECT (evaspixmapsink,"current enable-last-buffer : %d", enable_last_buffer);
2524 /* flush if enable-last-buffer is TRUE */
2525 if (enable_last_buffer) {
2526 GST_INFO_OBJECT (evaspixmapsink,"flush last-buffer");
2527 g_object_set(G_OBJECT(evaspixmapsink), "enable-last-buffer", FALSE, NULL);
2528 g_object_set(G_OBJECT(evaspixmapsink), "enable-last-buffer", TRUE, NULL);
2531 evaspixmapsink->fps_n = gst_value_get_fraction_numerator (fps);
2532 evaspixmapsink->fps_d = gst_value_get_fraction_denominator (fps);
2534 evaspixmapsink->video_width = video_width;
2535 evaspixmapsink->video_height = video_height;
2537 im_format = gst_evaspixmapsink_get_format_from_caps (evaspixmapsink, caps);
2538 if (im_format == -1) {
2539 goto invalid_format;
2542 /* get aspect ratio from caps if it's present, and
2543 * convert video width and height to a display width and height
2544 * using wd / hd = wv / hv * PARv / PARd */
2546 /* get video's PAR */
2547 caps_par = gst_structure_get_value (structure, "pixel-aspect-ratio");
2549 video_par_n = gst_value_get_fraction_numerator (caps_par);
2550 video_par_d = gst_value_get_fraction_denominator (caps_par);
2555 /* get display's PAR */
2556 if (evaspixmapsink->par) {
2557 display_par_n = gst_value_get_fraction_numerator (evaspixmapsink->par);
2558 display_par_d = gst_value_get_fraction_denominator (evaspixmapsink->par);
2564 /* get the display region */
2565 caps_disp_reg = gst_structure_get_value (structure, "display-region");
2566 if (caps_disp_reg) {
2567 disp_x = g_value_get_int (gst_value_array_get_value (caps_disp_reg, 0));
2568 disp_y = g_value_get_int (gst_value_array_get_value (caps_disp_reg, 1));
2569 disp_width = g_value_get_int (gst_value_array_get_value (caps_disp_reg, 2));
2570 disp_height = g_value_get_int (gst_value_array_get_value (caps_disp_reg, 3));
2572 disp_x = disp_y = 0;
2573 disp_width = video_width;
2574 disp_height = video_height;
2577 if (!gst_video_calculate_display_ratio (&num, &den, video_width, video_height, video_par_n, video_par_d, display_par_n, display_par_d)) {
2581 evaspixmapsink->disp_x = disp_x;
2582 evaspixmapsink->disp_y = disp_y;
2583 evaspixmapsink->disp_width = disp_width;
2584 evaspixmapsink->disp_height = disp_height;
2586 GST_DEBUG_OBJECT (evaspixmapsink,"video width/height: %dx%d, calculated display ratio: %d/%d", video_width, video_height, num, den);
2588 /* now find a width x height that respects this display ratio.
2589 * prefer those that have one of w/h the same as the incoming video
2590 * using wd / hd = num / den */
2592 /* start with same height, because of interlaced video */
2593 /* check hd / den is an integer scale factor, and scale wd with the PAR */
2594 if (video_height % den == 0) {
2595 GST_DEBUG_OBJECT (evaspixmapsink,"keeping video height");
2596 GST_VIDEO_SINK_WIDTH (evaspixmapsink) = (guint) gst_util_uint64_scale_int (video_height, num, den);
2597 GST_VIDEO_SINK_HEIGHT (evaspixmapsink) = video_height;
2598 } else if (video_width % num == 0) {
2599 GST_DEBUG_OBJECT (evaspixmapsink,"keeping video width");
2600 GST_VIDEO_SINK_WIDTH (evaspixmapsink) = video_width;
2601 GST_VIDEO_SINK_HEIGHT (evaspixmapsink) = (guint) gst_util_uint64_scale_int (video_width, den, num);
2603 GST_DEBUG_OBJECT (evaspixmapsink,"approximating while keeping video height");
2604 GST_VIDEO_SINK_WIDTH (evaspixmapsink) = (guint) gst_util_uint64_scale_int (video_height, num, den);
2605 GST_VIDEO_SINK_HEIGHT (evaspixmapsink) = video_height;
2607 GST_DEBUG_OBJECT (evaspixmapsink,"scaling to %dx%d", GST_VIDEO_SINK_WIDTH (evaspixmapsink), GST_VIDEO_SINK_HEIGHT (evaspixmapsink));
2609 /* Creating our window and our image with the display size in pixels */
2610 if (GST_VIDEO_SINK_WIDTH (evaspixmapsink) <= 0 || GST_VIDEO_SINK_HEIGHT (evaspixmapsink) <= 0) {
2611 goto no_display_size;
2614 g_mutex_lock (evaspixmapsink->flow_lock);
2616 /* We renew our evaspixmap buffer only if size or format changed;
2617 * the evaspixmap buffer is the same size as the video pixel size */
2618 if ((evaspixmapsink->evas_pixmap_buf) && ((im_format != evaspixmapsink->evas_pixmap_buf->im_format)
2619 || (video_width != evaspixmapsink->evas_pixmap_buf->width) || (video_height != evaspixmapsink->evas_pixmap_buf->height))) {
2620 GST_DEBUG_OBJECT (evaspixmapsink,"old format %" GST_FOURCC_FORMAT ", new format %" GST_FOURCC_FORMAT,
2621 GST_FOURCC_ARGS (evaspixmapsink->evas_pixmap_buf->im_format), GST_FOURCC_ARGS (im_format));
2622 GST_DEBUG_OBJECT (evaspixmapsink,"renewing evaspixmap buffer");
2623 gst_buffer_unref (GST_BUFFER (evaspixmapsink->evas_pixmap_buf));
2624 evaspixmapsink->evas_pixmap_buf = NULL;
2627 g_mutex_unlock (evaspixmapsink->flow_lock);
2629 if (evaspixmapsink->eo) {
2630 if (!gst_evaspixmapsink_xpixmap_link (evaspixmapsink)) {
2631 GST_ERROR_OBJECT (evaspixmapsink,"link evas image object with pixmap failed...");
2634 gst_evaspixmapsink_manage_event_thread (evaspixmapsink);
2637 GST_ERROR_OBJECT (evaspixmapsink,"setcaps success, but there is no evas image object..");
2646 GST_ERROR_OBJECT (evaspixmapsink,"caps incompatible");
2651 GST_DEBUG_OBJECT (evaspixmapsink,"Failed to retrieve either width, ""height or framerate from intersected caps");
2656 GST_DEBUG_OBJECT (evaspixmapsink,"Could not locate image format from caps %" GST_PTR_FORMAT, caps);
2661 GST_ELEMENT_ERROR (evaspixmapsink, CORE, NEGOTIATION, (NULL), ("Error calculating the output display ratio of the video."));
2666 GST_ELEMENT_ERROR (evaspixmapsink, CORE, NEGOTIATION, (NULL), ("Error calculating the output display ratio of the video."));
2671 static GstStateChangeReturn
2672 gst_evaspixmapsink_change_state (GstElement *element, GstStateChange transition)
2674 GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
2675 GstEvasPixmapSink *evaspixmapsink;
2677 evaspixmapsink = GST_EVASPIXMAPSINK (element);
2679 switch (transition) {
2680 case GST_STATE_CHANGE_NULL_TO_READY:
2681 GST_DEBUG_OBJECT (evaspixmapsink,"GST_STATE_CHANGE_NULL_TO_READY");
2683 /* open drm to use gem */
2684 if (drm_init(evaspixmapsink)) {
2685 GST_ERROR_OBJECT (evaspixmapsink,"drm_init() failure");
2686 return GST_STATE_CHANGE_FAILURE;
2689 /* check if there exist evas image object, need to write code related to making internal evas image object */
2690 if (!is_evas_image_object (evaspixmapsink->eo)) {
2691 GST_ERROR_OBJECT (evaspixmapsink,"There is no evas image object..");
2692 return GST_STATE_CHANGE_FAILURE;
2695 /* Set xcontext and display */
2696 if (!evaspixmapsink->xcontext) {
2697 evaspixmapsink->xcontext = gst_evaspixmapsink_xcontext_get (evaspixmapsink);
2698 if (!evaspixmapsink->xcontext) {
2699 GST_ERROR_OBJECT (evaspixmapsink,"could not get xcontext..");
2700 return GST_STATE_CHANGE_FAILURE;
2704 /* update object's par with calculated one if not set yet */
2705 if (!evaspixmapsink->par) {
2706 evaspixmapsink->par = g_new0 (GValue, 1);
2707 gst_value_init_and_copy (evaspixmapsink->par, evaspixmapsink->xcontext->par);
2708 GST_DEBUG_OBJECT (evaspixmapsink,"set calculated PAR on object's PAR");
2711 /* call XSynchronize with the current value of synchronous */
2712 GST_DEBUG_OBJECT (evaspixmapsink,"XSynchronize called with %s", evaspixmapsink->synchronous ? "TRUE" : "FALSE");
2713 XSynchronize (evaspixmapsink->xcontext->disp, evaspixmapsink->synchronous);
2714 gst_evaspixmapsink_update_colorbalance (evaspixmapsink);
2717 case GST_STATE_CHANGE_READY_TO_PAUSED:
2718 GST_DEBUG_OBJECT (evaspixmapsink,"GST_STATE_CHANGE_READY_TO_PAUSED");
2721 case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
2722 GST_DEBUG_OBJECT (evaspixmapsink,"GST_STATE_CHANGE_PAUSED_TO_PLAYING");
2729 ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
2731 switch (transition) {
2732 case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
2733 GST_DEBUG_OBJECT (evaspixmapsink,"GST_STATE_CHANGE_PLAYING_TO_PAUSED");
2736 case GST_STATE_CHANGE_PAUSED_TO_READY:
2737 GST_DEBUG_OBJECT (evaspixmapsink,"GST_STATE_CHANGE_PAUSED_TO_READY");
2738 evaspixmapsink->fps_n = 0;
2739 evaspixmapsink->fps_d = 1;
2740 GST_VIDEO_SINK_WIDTH (evaspixmapsink) = 0;
2741 GST_VIDEO_SINK_HEIGHT (evaspixmapsink) = 0;
2742 drm_fini_close_gem_handle(evaspixmapsink);
2745 case GST_STATE_CHANGE_READY_TO_NULL:
2746 GST_DEBUG_OBJECT (evaspixmapsink,"GST_STATE_CHANGE_READY_TO_NULL");
2747 gst_evaspixmapsink_reset(evaspixmapsink);
2749 drm_fini(evaspixmapsink);
2759 gst_evaspixmapsink_get_times (GstBaseSink *bsink, GstBuffer *buf, GstClockTime *start, GstClockTime *end)
2761 GstEvasPixmapSink *evaspixmapsink;
2763 evaspixmapsink = GST_EVASPIXMAPSINK (bsink);
2765 if (GST_BUFFER_TIMESTAMP_IS_VALID (buf)) {
2766 *start = GST_BUFFER_TIMESTAMP (buf);
2767 if (GST_BUFFER_DURATION_IS_VALID (buf)) {
2768 *end = *start + GST_BUFFER_DURATION (buf);
2770 if (evaspixmapsink->fps_n > 0) {
2772 gst_util_uint64_scale_int (GST_SECOND, evaspixmapsink->fps_d,
2773 evaspixmapsink->fps_n);
2779 static GstFlowReturn
2780 gst_evaspixmapsink_show_frame (GstVideoSink *vsink, GstBuffer *buf)
2782 GstEvasPixmapSink *evaspixmapsink;
2783 XV_PUTIMAGE_DATA_PTR img_data = NULL;
2784 SCMN_IMGB *scmn_imgb = NULL;
2787 MMTA_ACUM_ITEM_BEGIN("evaspixmapsink gst_evaspixmapsink_show_frame()", FALSE);
2789 evaspixmapsink = GST_EVASPIXMAPSINK (vsink);
2791 if( evaspixmapsink->stop_video ) {
2792 GST_INFO_OBJECT (evaspixmapsink, "Stop video is TRUE. so skip show frame..." );
2796 if (!evaspixmapsink->evas_pixmap_buf) {
2797 GST_DEBUG_OBJECT (evaspixmapsink,"creating our evaspixmap buffer");
2798 format = gst_evaspixmapsink_get_format_from_caps(evaspixmapsink, GST_BUFFER_CAPS(buf));
2800 case GST_MAKE_FOURCC('S', 'T', '1', '2'):
2801 case GST_MAKE_FOURCC('S', 'N', '1', '2'):
2802 case GST_MAKE_FOURCC('S', '4', '2', '0'):
2803 case GST_MAKE_FOURCC('S', 'U', 'Y', '2'):
2804 case GST_MAKE_FOURCC('S', 'U', 'Y', 'V'):
2805 case GST_MAKE_FOURCC('S', 'Y', 'V', 'Y'):
2806 scmn_imgb = (SCMN_IMGB *)GST_BUFFER_MALLOCDATA(buf);
2807 if(scmn_imgb == NULL) {
2808 GST_DEBUG_OBJECT (evaspixmapsink, "scmn_imgb is NULL. Skip buffer put..." );
2811 /* skip buffer if aligned size is smaller than size of caps */
2812 if (scmn_imgb->s[0] < evaspixmapsink->video_width || scmn_imgb->e[0] < evaspixmapsink->video_height) {
2813 GST_WARNING_OBJECT (evaspixmapsink,"invalid size[caps:%dx%d,aligned:%dx%d]. Skip this buffer...",
2814 evaspixmapsink->video_width, evaspixmapsink->video_height, scmn_imgb->s[0], scmn_imgb->e[0]);
2817 evaspixmapsink->aligned_width = scmn_imgb->s[0];
2818 evaspixmapsink->aligned_height = scmn_imgb->e[0];
2819 GST_DEBUG_OBJECT (evaspixmapsink,"video width,height[%dx%d]",evaspixmapsink->video_width, evaspixmapsink->video_height);
2820 GST_INFO_OBJECT (evaspixmapsink,"Use aligned width,height[%dx%d]",evaspixmapsink->aligned_width, evaspixmapsink->aligned_height);
2823 GST_INFO_OBJECT (evaspixmapsink,"Use original width,height of caps");
2826 evaspixmapsink->evas_pixmap_buf = gst_evaspixmap_buffer_new (evaspixmapsink, GST_BUFFER_CAPS (buf));
2827 if (!evaspixmapsink->evas_pixmap_buf) {
2828 /* The create method should have posted an informative error */
2831 if (evaspixmapsink->evas_pixmap_buf->size < GST_BUFFER_SIZE (buf)) {
2832 GST_ELEMENT_ERROR (evaspixmapsink, RESOURCE, WRITE, ("Failed to create output image buffer of %dx%d pixels", evaspixmapsink->evas_pixmap_buf->width, evaspixmapsink->evas_pixmap_buf->height),("XServer allocated buffer size did not match input buffer"));
2833 gst_evaspixmap_buffer_destroy (evaspixmapsink->evas_pixmap_buf);
2834 evaspixmapsink->evas_pixmap_buf = NULL;
2839 switch (evaspixmapsink->evas_pixmap_buf->im_format) {
2840 /* Cases for specified formats of Samsung extension */
2841 case GST_MAKE_FOURCC('S', 'T', '1', '2'):
2842 case GST_MAKE_FOURCC('S', 'N', '1', '2'):
2843 case GST_MAKE_FOURCC('S', '4', '2', '0'):
2844 case GST_MAKE_FOURCC('S', 'U', 'Y', '2'):
2845 case GST_MAKE_FOURCC('S', 'U', 'Y', 'V'):
2846 case GST_MAKE_FOURCC('S', 'Y', 'V', 'Y'):
2847 case GST_MAKE_FOURCC('I', 'T', 'L', 'V'):
2849 GST_DEBUG_OBJECT (evaspixmapsink,"Samsung extension display format activated. fourcc:%d", evaspixmapsink->evas_pixmap_buf->im_format);
2851 if (evaspixmapsink->evas_pixmap_buf->xvimage->data) {
2852 img_data = (XV_PUTIMAGE_DATA_PTR) evaspixmapsink->evas_pixmap_buf->xvimage->data;
2853 XV_PUTIMAGE_INIT_DATA(img_data);
2854 scmn_imgb = (SCMN_IMGB *)GST_BUFFER_MALLOCDATA(buf);
2855 if (scmn_imgb == NULL) {
2856 GST_DEBUG_OBJECT (evaspixmapsink, "scmn_imgb is NULL. Skip buffer put..." );
2860 if (scmn_imgb->buf_share_method == BUF_SHARE_METHOD_PADDR) {
2861 img_data->YBuf = (unsigned int)scmn_imgb->p[0];
2862 img_data->CbBuf = (unsigned int)scmn_imgb->p[1];
2863 img_data->CrBuf = (unsigned int)scmn_imgb->p[2];
2864 img_data->BufType = XV_BUF_TYPE_LEGACY;
2865 if (!img_data->YBuf) {
2866 GST_WARNING_OBJECT (evaspixmapsink, "img_data->YBuf is NULL. skip buffer put..." );
2869 } else { /* BUF_SHARE_METHOD_FD */
2870 /* set gem information to gem_info structure of handle and convert dma-buf fd into drm gem name */
2871 img_data->YBuf = drm_init_convert_dmabuf_gemname(evaspixmapsink, (int)scmn_imgb->dma_buf_fd[0]);
2872 img_data->CbBuf = drm_init_convert_dmabuf_gemname(evaspixmapsink, (int)scmn_imgb->dma_buf_fd[1]);
2873 img_data->CrBuf = drm_init_convert_dmabuf_gemname(evaspixmapsink, (int)scmn_imgb->dma_buf_fd[2]);
2874 img_data->BufType = XV_BUF_TYPE_DMABUF;
2875 if (!img_data->YBuf) {
2876 GST_WARNING_OBJECT (evaspixmapsink, "img_data->YBuf is NULL. skip buffer put..." );
2880 GST_LOG_OBJECT(evaspixmapsink, "YBuf[%d], CbBuf[%d], CrBuf[%d]",
2881 img_data->YBuf, img_data->CbBuf, img_data->CrBuf );
2883 GST_WARNING_OBJECT (evaspixmapsink, "xvimage->data is NULL. skip buffer put..." );
2890 GST_DEBUG_OBJECT (evaspixmapsink,"Normal format activated. fourcc = %d", evaspixmapsink->evas_pixmap_buf->im_format);
2891 __ta__("evaspixmapsink memcpy in _show_frame", memcpy (evaspixmapsink->evas_pixmap_buf->xvimage->data, GST_BUFFER_DATA (buf),
2892 MIN (GST_BUFFER_SIZE (buf), evaspixmapsink->evas_pixmap_buf->size)););
2896 if (!gst_evaspixmap_buffer_put (evaspixmapsink, evaspixmapsink->evas_pixmap_buf)) {
2897 MMTA_ACUM_ITEM_END("evaspixmapsink gst_evaspixmapsink_show_frame()", FALSE);
2901 MMTA_ACUM_ITEM_END("evaspixmapsink gst_evaspixmapsink_show_frame()", FALSE);
2908 /* No image available. That's very bad ! */
2909 GST_WARNING_OBJECT (evaspixmapsink,"could not create image");
2910 return GST_FLOW_ERROR;
2914 /* No Pixmap available to put our image into */
2915 GST_WARNING_OBJECT (evaspixmapsink,"could not output image - no pixmap");
2916 return GST_FLOW_ERROR;
2921 gst_evaspixmapsink_event (GstBaseSink *sink, GstEvent *event)
2923 GstEvasPixmapSink *evaspixmapsink = GST_EVASPIXMAPSINK (sink);
2925 switch (GST_EVENT_TYPE (event)) {
2926 case GST_EVENT_FLUSH_START:
2927 GST_DEBUG_OBJECT (evaspixmapsink,"GST_EVENT_FLUSH_START");
2929 case GST_EVENT_FLUSH_STOP:
2930 GST_DEBUG_OBJECT (evaspixmapsink,"GST_EVENT_FLUSH_STOP");
2935 if (GST_BASE_SINK_CLASS (parent_class)->event) {
2936 return GST_BASE_SINK_CLASS (parent_class)->event (sink, event);
2942 /* Interfaces stuff */
2945 gst_evaspixmapsink_interface_supported (GstImplementsInterface *iface, GType type)
2947 g_assert (type == GST_TYPE_NAVIGATION || type == GST_TYPE_COLOR_BALANCE || type == GST_TYPE_PROPERTY_PROBE);
2952 gst_evaspixmapsink_interface_init (GstImplementsInterfaceClass *klass)
2954 klass->supported = gst_evaspixmapsink_interface_supported;
2958 gst_evaspixmapsink_navigation_send_event (GstNavigation *navigation, GstStructure *structure)
2960 GstEvasPixmapSink *evaspixmapsink = GST_EVASPIXMAPSINK (navigation);
2963 if ((peer = gst_pad_get_peer (GST_VIDEO_SINK_PAD (evaspixmapsink)))) {
2965 GstVideoRectangle src, dst, result;
2966 gdouble x, y, xscale = 1.0, yscale = 1.0;
2968 event = gst_event_new_navigation (structure);
2970 /* We take the flow_lock while we look at the window */
2971 g_mutex_lock (evaspixmapsink->flow_lock);
2973 if (!evaspixmapsink->xpixmap) {
2974 g_mutex_unlock (evaspixmapsink->flow_lock);
2978 memcpy (&result, &evaspixmapsink->render_rect, sizeof (GstVideoRectangle));
2980 g_mutex_unlock (evaspixmapsink->flow_lock);
2982 /* We calculate scaling using the original video frames geometry to include
2983 pixel aspect ratio scaling. */
2984 xscale = (gdouble) evaspixmapsink->video_width / result.w;
2985 yscale = (gdouble) evaspixmapsink->video_height / result.h;
2987 /* Converting pointer coordinates to the non scaled geometry */
2988 if (gst_structure_get_double (structure, "pointer_x", &x)) {
2989 x = MIN (x, result.x + result.w);
2990 x = MAX (x - result.x, 0);
2991 gst_structure_set (structure, "pointer_x", G_TYPE_DOUBLE,
2992 (gdouble) x * xscale, NULL);
2994 if (gst_structure_get_double (structure, "pointer_y", &y)) {
2995 y = MIN (y, result.y + result.h);
2996 y = MAX (y - result.y, 0);
2997 gst_structure_set (structure, "pointer_y", G_TYPE_DOUBLE,
2998 (gdouble) y * yscale, NULL);
3001 gst_pad_send_event (peer, event);
3002 gst_object_unref (peer);
3007 gst_evaspixmapsink_navigation_init (GstNavigationInterface *iface)
3009 iface->send_event = gst_evaspixmapsink_navigation_send_event;
3013 gst_evaspixmapsink_colorbalance_list_channels (GstColorBalance *balance)
3015 GstEvasPixmapSink *evaspixmapsink = GST_EVASPIXMAPSINK (balance);
3017 g_return_val_if_fail (GST_IS_EVASPIXMAPSINK (evaspixmapsink), NULL);
3019 if (evaspixmapsink->xcontext)
3020 return evaspixmapsink->xcontext->channels_list;
3026 gst_evaspixmapsink_colorbalance_set_value (GstColorBalance *balance, GstColorBalanceChannel *channel, gint value)
3028 GstEvasPixmapSink *evaspixmapsink = GST_EVASPIXMAPSINK (balance);
3030 g_return_if_fail (GST_IS_EVASPIXMAPSINK (evaspixmapsink));
3031 g_return_if_fail (channel->label != NULL);
3033 evaspixmapsink->cb_changed = TRUE;
3035 /* Normalize val to [-1000, 1000] */
3036 value = floor (0.5 + -1000 + 2000 * (value - channel->min_value) /
3037 (double) (channel->max_value - channel->min_value));
3039 if (g_ascii_strcasecmp (channel->label, "XV_HUE") == 0) {
3040 evaspixmapsink->hue = value;
3041 } else if (g_ascii_strcasecmp (channel->label, "XV_SATURATION") == 0) {
3042 evaspixmapsink->saturation = value;
3043 } else if (g_ascii_strcasecmp (channel->label, "XV_CONTRAST") == 0) {
3044 evaspixmapsink->contrast = value;
3045 } else if (g_ascii_strcasecmp (channel->label, "XV_BRIGHTNESS") == 0) {
3046 evaspixmapsink->brightness = value;
3048 g_warning ("got an unknown channel %s", channel->label);
3052 gst_evaspixmapsink_update_colorbalance (evaspixmapsink);
3056 gst_evaspixmapsink_colorbalance_get_value (GstColorBalance *balance, GstColorBalanceChannel *channel)
3058 GstEvasPixmapSink *evaspixmapsink = GST_EVASPIXMAPSINK (balance);
3061 g_return_val_if_fail (GST_IS_EVASPIXMAPSINK (evaspixmapsink), 0);
3062 g_return_val_if_fail (channel->label != NULL, 0);
3064 if (g_ascii_strcasecmp (channel->label, "XV_HUE") == 0) {
3065 value = evaspixmapsink->hue;
3066 } else if (g_ascii_strcasecmp (channel->label, "XV_SATURATION") == 0) {
3067 value = evaspixmapsink->saturation;
3068 } else if (g_ascii_strcasecmp (channel->label, "XV_CONTRAST") == 0) {
3069 value = evaspixmapsink->contrast;
3070 } else if (g_ascii_strcasecmp (channel->label, "XV_BRIGHTNESS") == 0) {
3071 value = evaspixmapsink->brightness;
3073 g_warning ("got an unknown channel %s", channel->label);
3076 /* Normalize val to [channel->min_value, channel->max_value] */
3077 value = channel->min_value + (channel->max_value - channel->min_value) * (value + 1000) / 2000;
3083 gst_evaspixmapsink_colorbalance_init (GstColorBalanceClass *iface)
3085 GST_COLOR_BALANCE_TYPE (iface) = GST_COLOR_BALANCE_HARDWARE;
3086 iface->list_channels = gst_evaspixmapsink_colorbalance_list_channels;
3087 iface->set_value = gst_evaspixmapsink_colorbalance_set_value;
3088 iface->get_value = gst_evaspixmapsink_colorbalance_get_value;
3091 static const GList *
3092 gst_evaspixmapsink_probe_get_properties (GstPropertyProbe *probe)
3094 GObjectClass *klass = G_OBJECT_GET_CLASS (probe);
3095 static GList *list = NULL;
3098 list = g_list_append (NULL, g_object_class_find_property (klass, "device"));
3099 list = g_list_append (list, g_object_class_find_property (klass, "autopaint-colorkey"));
3100 list = g_list_append (list, g_object_class_find_property (klass, "double-buffer"));
3101 list = g_list_append (list, g_object_class_find_property (klass, "colorkey"));
3108 gst_evaspixmapsink_probe_probe_property (GstPropertyProbe *probe, guint prop_id, const GParamSpec *pspec)
3110 GstEvasPixmapSink *evaspixmapsink = GST_EVASPIXMAPSINK (probe);
3114 case PROP_AUTOPAINT_COLORKEY:
3115 case PROP_DOUBLE_BUFFER:
3117 GST_DEBUG_OBJECT (evaspixmapsink,"probing device list and get capabilities");
3118 if (!evaspixmapsink->xcontext) {
3119 GST_DEBUG_OBJECT (evaspixmapsink,"generating xcontext");
3120 evaspixmapsink->xcontext = gst_evaspixmapsink_xcontext_get (evaspixmapsink);
3121 if (!evaspixmapsink->xcontext) {
3122 GST_ERROR_OBJECT (evaspixmapsink,"could not get xcontext..");
3127 G_OBJECT_WARN_INVALID_PROPERTY_ID (probe, prop_id, pspec);
3133 gst_evaspixmapsink_probe_needs_probe (GstPropertyProbe *probe, guint prop_id, const GParamSpec *pspec)
3135 GstEvasPixmapSink *evaspixmapsink = GST_EVASPIXMAPSINK (probe);
3136 gboolean ret = FALSE;
3140 case PROP_AUTOPAINT_COLORKEY:
3141 case PROP_DOUBLE_BUFFER:
3143 if (evaspixmapsink->xcontext != NULL) {
3150 G_OBJECT_WARN_INVALID_PROPERTY_ID (probe, prop_id, pspec);
3157 static GValueArray *
3158 gst_evaspixmapsink_probe_get_values (GstPropertyProbe *probe, guint prop_id, const GParamSpec *pspec)
3160 GstEvasPixmapSink *evaspixmapsink = GST_EVASPIXMAPSINK (probe);
3161 GValueArray *array = NULL;
3163 if (G_UNLIKELY (!evaspixmapsink->xcontext)) {
3164 GST_WARNING_OBJECT (evaspixmapsink,"we don't have any xcontext, can't "
3173 GValue value = { 0 };
3175 array = g_value_array_new (evaspixmapsink->xcontext->nb_adaptors);
3176 g_value_init (&value, G_TYPE_STRING);
3178 for (i = 0; i < evaspixmapsink->xcontext->nb_adaptors; i++) {
3179 gchar *adaptor_id_s = g_strdup_printf ("%u", i);
3181 g_value_set_string (&value, adaptor_id_s);
3182 g_value_array_append (array, &value);
3183 g_free (adaptor_id_s);
3185 g_value_unset (&value);
3188 case PROP_AUTOPAINT_COLORKEY:
3189 if (evaspixmapsink->have_autopaint_colorkey) {
3190 GValue value = { 0 };
3192 array = g_value_array_new (2);
3193 g_value_init (&value, G_TYPE_BOOLEAN);
3194 g_value_set_boolean (&value, FALSE);
3195 g_value_array_append (array, &value);
3196 g_value_set_boolean (&value, TRUE);
3197 g_value_array_append (array, &value);
3198 g_value_unset (&value);
3201 case PROP_DOUBLE_BUFFER:
3202 if (evaspixmapsink->have_double_buffer) {
3203 GValue value = { 0 };
3205 array = g_value_array_new (2);
3206 g_value_init (&value, G_TYPE_BOOLEAN);
3207 g_value_set_boolean (&value, FALSE);
3208 g_value_array_append (array, &value);
3209 g_value_set_boolean (&value, TRUE);
3210 g_value_array_append (array, &value);
3211 g_value_unset (&value);
3215 if (evaspixmapsink->have_colorkey) {
3216 GValue value = { 0 };
3218 array = g_value_array_new (1);
3219 g_value_init (&value, GST_TYPE_INT_RANGE);
3220 gst_value_set_int_range (&value, 0, 0xffffff);
3221 g_value_array_append (array, &value);
3222 g_value_unset (&value);
3226 G_OBJECT_WARN_INVALID_PROPERTY_ID (probe, prop_id, pspec);
3235 gst_evaspixmapsink_property_probe_interface_init (GstPropertyProbeInterface *iface)
3237 iface->get_properties = gst_evaspixmapsink_probe_get_properties;
3238 iface->probe_property = gst_evaspixmapsink_probe_probe_property;
3239 iface->needs_probe = gst_evaspixmapsink_probe_needs_probe;
3240 iface->get_values = gst_evaspixmapsink_probe_get_values;
3244 gst_evaspixmapsink_xpixmap_link (GstEvasPixmapSink *evaspixmapsink)
3247 Pixmap *pixmap_id[NUM_OF_PIXMAP];
3248 int evas_object_width = 0;
3249 int evas_object_height = 0;
3250 int pixmap_width = 0;
3251 int pixmap_height = 0;
3256 GST_DEBUG_OBJECT (evaspixmapsink,"[START]");
3258 if (!evaspixmapsink) {
3259 GST_ERROR_OBJECT (evaspixmapsink,"could not get evaspixmapsink..");
3262 g_mutex_lock (evaspixmapsink->flow_lock);
3264 /* Set xcontext and display */
3265 if (!evaspixmapsink->xcontext) {
3266 GST_WARNING_OBJECT (evaspixmapsink,"there's no xcontext, try to get one..");
3267 evaspixmapsink->xcontext = gst_evaspixmapsink_xcontext_get (evaspixmapsink);
3268 if (!evaspixmapsink->xcontext) {
3269 GST_ERROR_OBJECT (evaspixmapsink,"could not get xcontext..");
3274 dpy = evaspixmapsink->xcontext->disp;
3276 /* Set evas image object size */
3277 evas_object_geometry_get(evaspixmapsink->eo, NULL, NULL, &evas_object_width, &evas_object_height);
3278 if (evaspixmapsink->use_origin_size || !evas_object_width || !evas_object_height) {
3279 pixmap_width = evaspixmapsink->video_width;
3280 pixmap_height = evaspixmapsink->video_height;
3281 GST_INFO_OBJECT (evaspixmapsink,"set size to media src size(%dx%d)", pixmap_width, pixmap_height);
3284 g_mutex_lock (evaspixmapsink->x_lock);
3285 evaspixmapsink->sizediff_width = 0;
3286 evaspixmapsink->sizediff_height = 0;
3287 if (evaspixmapsink->use_origin_size || !evas_object_width || !evas_object_height) {
3288 XvQueryBestSize(dpy, evaspixmapsink->xcontext->xv_port_id,0,0,0, pixmap_width, pixmap_height, &xw, &xh);
3289 if (!evas_object_width || !evas_object_height) {
3290 evaspixmapsink->w = xw;
3291 evaspixmapsink->h = xh;
3293 evaspixmapsink->w = evas_object_width;
3294 evaspixmapsink->h = evas_object_height;
3296 GST_DEBUG_OBJECT (evaspixmapsink,"XvQueryBestSize : xv_port_id(%d), w(%d),h(%d) => xw(%d),xh(%d)", evaspixmapsink->xcontext->xv_port_id, pixmap_width, pixmap_height, xw, xh);
3298 XvQueryBestSize(dpy, evaspixmapsink->xcontext->xv_port_id,0,0,0, evas_object_width, evas_object_height, &xw, &xh);
3299 GST_DEBUG_OBJECT (evaspixmapsink,"XvQueryBestSize : xv_port_id(%d), w(%d),h(%d) => xw(%d),xh(%d)", evaspixmapsink->xcontext->xv_port_id, evas_object_width, evas_object_height, xw, xh);
3300 evaspixmapsink->w = xw;
3301 evaspixmapsink->h = xh;
3302 /* update difference of size information (between evas image object's and pixmap's) */
3303 evaspixmapsink->sizediff_width = xw - evas_object_width;
3304 evaspixmapsink->sizediff_height = xh - evas_object_height;
3307 /* create xpixmap structure */
3308 for (i = 0; i < evaspixmapsink->num_of_pixmaps; i++) {
3309 if (!evaspixmapsink->xpixmap[i]) {
3310 /* xpixmap can be created in this function only */
3311 evaspixmapsink->xpixmap[i] = g_new0 (GstXPixmap, 1);
3312 if(!evaspixmapsink->xpixmap[i]) {
3313 GST_ERROR_OBJECT (evaspixmapsink,"xpixmap is not valid..");
3315 for (j = 0; j < i; j++) {
3316 g_free(evaspixmapsink->xpixmap[j]);
3318 goto GO_OUT_OF_FUNC;
3325 GST_WARNING_OBJECT (evaspixmapsink,"skip creating pixmap..xw(%d),xh(%d)",xw,xh);
3326 goto GO_OUT_OF_FUNC;
3328 /* multiple pixmaps creation */
3329 for (i = 0; i < evaspixmapsink->num_of_pixmaps; i++) {
3330 pixmap_id[i] = XCreatePixmap(dpy, DefaultRootWindow(dpy), xw, xh, DefaultDepth(dpy, DefaultScreen(dpy)));
3331 if ( (int)pixmap_id[i] == BadAlloc || (int)pixmap_id[i] == BadDrawable || (int)pixmap_id[i] == BadValue ) {
3332 GST_ERROR_OBJECT (evaspixmapsink,"pixmap[%d] allocation error..", i);
3334 for (j = 0; j < i; j++) {
3335 XFreePixmap(dpy, pixmap_id[j]);
3337 goto GO_OUT_OF_FUNC;
3339 GST_INFO_OBJECT (evaspixmapsink,"creation pixmap_id[%d]:%d success", i, pixmap_id[i]);
3340 GST_DEBUG_OBJECT (evaspixmapsink,"evas_object_width(%d),evas_object_height(%d),pixmap:%d,depth:%d",
3341 evas_object_width,evas_object_height,pixmap_id[i],DefaultDepth(dpy, DefaultScreen(dpy)));
3345 for (i = 0; i < evaspixmapsink->num_of_pixmaps; i++) {
3346 if (evaspixmapsink->xpixmap[i]->pixmap && pixmap_id[i] != evaspixmapsink->xpixmap[i]->pixmap) {
3347 /* If we reset another pixmap, do below */
3348 GST_DEBUG_OBJECT (evaspixmapsink,"destroy previous pixmap(%d)",evaspixmapsink->xpixmap[i]->pixmap);
3349 if (evaspixmapsink->eo) {
3350 evas_object_image_native_surface_set(evaspixmapsink->eo, NULL);
3353 GST_LOG_OBJECT (evaspixmapsink,"Free pixmap(%d)", evaspixmapsink->xpixmap[i]->pixmap);
3354 XFreePixmap(dpy, evaspixmapsink->xpixmap[i]->pixmap);
3355 evaspixmapsink->xpixmap[i]->pixmap = NULL;
3356 evaspixmapsink->xpixmap[i]->ref = 0;
3357 evaspixmapsink->xpixmap[i]->damaged_time = 0;
3359 XFreeGC (evaspixmapsink->xcontext->disp, evaspixmapsink->xpixmap[i]->gc);
3360 XSync (evaspixmapsink->xcontext->disp, FALSE);
3364 for (i = 0; i < evaspixmapsink->num_of_pixmaps; i++) {
3365 /* Set pixmap id and create GC */
3366 evaspixmapsink->xpixmap[i]->pixmap = pixmap_id[i];
3367 evaspixmapsink->xpixmap[i]->gc = XCreateGC(dpy, evaspixmapsink->xpixmap[i]->pixmap, 0,0);
3368 XSetForeground(dpy, evaspixmapsink->xpixmap[i]->gc,evaspixmapsink->xcontext->black);
3369 XFillRectangle(dpy, evaspixmapsink->xpixmap[i]->pixmap, evaspixmapsink->xpixmap[i]->gc, 0, 0, xw, xh);
3372 /* Create XDamage */
3373 if (evaspixmapsink->damage[i]) {
3374 GST_DEBUG_OBJECT (evaspixmapsink,"destroy previous damage(%d)",evaspixmapsink->damage[i]);
3375 XDamageDestroy(dpy, evaspixmapsink->damage[i]);
3376 evaspixmapsink->damage[i] = NULL;
3378 evaspixmapsink->damage[i] = XDamageCreate (dpy, evaspixmapsink->xpixmap[i]->pixmap, XDamageReportRawRectangles);
3380 GST_WARNING_OBJECT (evaspixmapsink,"xpixmap[%d]->(pixmap:%d,gc:%p), damage[%d]:%d",
3381 i, evaspixmapsink->xpixmap[i]->pixmap, evaspixmapsink->xpixmap[i]->gc, i, evaspixmapsink->damage[i]);
3383 evaspixmapsink->last_damaged_pixmap_idx = -1;
3387 /* Set flag for mapping evas object with xpixmap */
3388 evaspixmapsink->do_link = TRUE;
3389 ecore_pipe_write(evaspixmapsink->epipe, evaspixmapsink, sizeof(GstEvasPixmapSink));
3391 gst_evaspixmapsink_update_colorbalance (evaspixmapsink);
3393 g_mutex_unlock (evaspixmapsink->x_lock);
3394 g_mutex_unlock (evaspixmapsink->flow_lock);
3396 GST_DEBUG_OBJECT (evaspixmapsink,"[END]");
3401 g_mutex_unlock (evaspixmapsink->x_lock);
3402 g_mutex_unlock (evaspixmapsink->flow_lock);
3407 gst_evaspixmapsink_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
3409 GstEvasPixmapSink *evaspixmapsink;
3410 g_return_if_fail (GST_IS_EVASPIXMAPSINK (object));
3411 evaspixmapsink = GST_EVASPIXMAPSINK (object);
3415 evaspixmapsink->hue = g_value_get_int (value);
3416 evaspixmapsink->cb_changed = TRUE;
3417 gst_evaspixmapsink_update_colorbalance (evaspixmapsink);
3420 evaspixmapsink->contrast = g_value_get_int (value);
3421 evaspixmapsink->cb_changed = TRUE;
3422 gst_evaspixmapsink_update_colorbalance (evaspixmapsink);
3424 case PROP_BRIGHTNESS:
3425 evaspixmapsink->brightness = g_value_get_int (value);
3426 evaspixmapsink->cb_changed = TRUE;
3427 gst_evaspixmapsink_update_colorbalance (evaspixmapsink);
3429 case PROP_SATURATION:
3430 evaspixmapsink->saturation = g_value_get_int (value);
3431 evaspixmapsink->cb_changed = TRUE;
3432 gst_evaspixmapsink_update_colorbalance (evaspixmapsink);
3435 evaspixmapsink->display_name = g_strdup (g_value_get_string (value));
3437 case PROP_SYNCHRONOUS:
3438 evaspixmapsink->synchronous = g_value_get_boolean (value);
3439 if (evaspixmapsink->xcontext) {
3440 XSynchronize (evaspixmapsink->xcontext->disp, evaspixmapsink->synchronous);
3441 GST_DEBUG_OBJECT (evaspixmapsink,"XSynchronize called with %s", evaspixmapsink->synchronous ? "TRUE" : "FALSE");
3444 case PROP_PIXEL_ASPECT_RATIO:
3445 g_free (evaspixmapsink->par);
3446 evaspixmapsink->par = g_new0 (GValue, 1);
3447 g_value_init (evaspixmapsink->par, GST_TYPE_FRACTION);
3448 if (!g_value_transform (value, evaspixmapsink->par)) {
3449 g_warning ("Could not transform string to aspect ratio");
3450 gst_value_set_fraction (evaspixmapsink->par, 1, 1);
3452 GST_DEBUG_OBJECT (evaspixmapsink,"set PAR to %d/%d", gst_value_get_fraction_numerator (evaspixmapsink->par), gst_value_get_fraction_denominator (evaspixmapsink->par));
3455 evaspixmapsink->adaptor_no = atoi (g_value_get_string (value));
3457 case PROP_DOUBLE_BUFFER:
3458 evaspixmapsink->double_buffer = g_value_get_boolean (value);
3460 case PROP_AUTOPAINT_COLORKEY:
3461 evaspixmapsink->autopaint_colorkey = g_value_get_boolean (value);
3464 evaspixmapsink->colorkey = g_value_get_int (value);
3466 case PROP_PIXMAP_WIDTH:
3469 if (evaspixmapsink->xpixmap) {
3470 /* To do : code related to pixmap re-link */
3471 //evaspixmapsink->xpixmap[i]->width = g_value_get_uint64 (value);
3475 case PROP_PIXMAP_HEIGHT:
3478 if (evaspixmapsink->xpixmap) {
3479 /* To do : code related to pixmap re-link */
3480 //evaspixmapsink->xpixmap[i]->height = g_value_get_uint64 (value);
3484 case PROP_DISPLAY_GEOMETRY_METHOD:
3486 guint new_val = g_value_get_enum (value);
3487 if (evaspixmapsink->display_geometry_method != new_val) {
3488 evaspixmapsink->display_geometry_method = new_val;
3489 GST_INFO_OBJECT (evaspixmapsink,"Overlay geometry method update, display_geometry_method(%d)",evaspixmapsink->display_geometry_method);
3490 if( evaspixmapsink->display_geometry_method != DISP_GEO_METHOD_FULL_SCREEN &&
3491 evaspixmapsink->display_geometry_method != DISP_GEO_METHOD_CROPPED_FULL_SCREEN ) {
3492 if( evaspixmapsink->xcontext && evaspixmapsink->xpixmap ) {
3493 g_mutex_lock( evaspixmapsink->flow_lock );
3495 for (i = 0; i < evaspixmapsink->num_of_pixmaps; i++) {
3496 if (evaspixmapsink->xpixmap[i]) {
3497 gst_evaspixmapsink_xpixmap_clear (evaspixmapsink, evaspixmapsink->xpixmap[i]);
3500 g_mutex_unlock( evaspixmapsink->flow_lock );
3503 if (evaspixmapsink->xcontext) {
3504 gst_evaspixmap_buffer_put (evaspixmapsink, evaspixmapsink->evas_pixmap_buf);
3509 case PROP_DST_ROI_X:
3510 evaspixmapsink->dst_roi.x = g_value_get_int (value);
3511 GST_INFO_OBJECT (evaspixmapsink, "ROI_X(%d)",evaspixmapsink->dst_roi.x );
3513 case PROP_DST_ROI_Y:
3514 evaspixmapsink->dst_roi.y = g_value_get_int (value);
3515 GST_INFO_OBJECT (evaspixmapsink, "ROI_Y(%d)",evaspixmapsink->dst_roi.y );
3517 case PROP_DST_ROI_W:
3518 evaspixmapsink->dst_roi.w = g_value_get_int (value);
3519 GST_INFO_OBJECT (evaspixmapsink, "ROI_W(%d)",evaspixmapsink->dst_roi.w );
3521 case PROP_DST_ROI_H:
3522 evaspixmapsink->dst_roi.h = g_value_get_int (value);
3523 GST_INFO_OBJECT (evaspixmapsink, "ROI_H(%d)",evaspixmapsink->dst_roi.h );
3525 case PROP_STOP_VIDEO:
3526 evaspixmapsink->stop_video = g_value_get_int (value);
3527 g_mutex_lock( evaspixmapsink->flow_lock );
3528 if( evaspixmapsink->stop_video ) {
3529 GST_INFO_OBJECT (evaspixmapsink, "XPixmap CLEAR when set video-stop property" );
3531 for (i = 0; i < evaspixmapsink->num_of_pixmaps; i++) {
3532 if (evaspixmapsink->xpixmap[i]) {
3533 gst_evaspixmapsink_xpixmap_clear (evaspixmapsink, evaspixmapsink->xpixmap[i]);
3537 g_mutex_unlock( evaspixmapsink->flow_lock );
3539 case PROP_EVAS_OBJECT:
3541 Evas_Object *eo = g_value_get_pointer (value);
3542 Ecore_Evas *ee = NULL;
3544 if ( is_evas_image_object (eo)) {
3545 if (!evaspixmapsink->epipe) {
3546 evaspixmapsink->epipe = ecore_pipe_add (ecore_pipe_callback_handler, evaspixmapsink);
3547 if (!evaspixmapsink->epipe) {
3548 GST_ERROR_OBJECT (evaspixmapsink,"Cannot set evas-object property: ecore_pipe_add() failed");
3552 if (eo != evaspixmapsink->eo) {
3553 /* delete evas object callbacks registrated on a former evas image object */
3554 evas_object_event_callback_del (evaspixmapsink->eo, EVAS_CALLBACK_DEL, evas_callback_del_event);
3555 evas_object_event_callback_del (evaspixmapsink->eo, EVAS_CALLBACK_RESIZE, evas_callback_resize_event);
3556 if (evaspixmapsink->eo) {
3557 if (!gst_evaspixmapsink_xpixmap_link(evaspixmapsink)) {
3558 GST_WARNING_OBJECT (evaspixmapsink,"link evas image object with pixmap failed...");
3562 evaspixmapsink->eo = eo;
3563 /* add evas object callbacks on a new evas image object */
3564 evas_object_event_callback_add (evaspixmapsink->eo, EVAS_CALLBACK_DEL, evas_callback_del_event, evaspixmapsink);
3565 evas_object_event_callback_add (evaspixmapsink->eo, EVAS_CALLBACK_RESIZE, evas_callback_resize_event, evaspixmapsink);
3566 e = evas_object_evas_get(eo);
3568 GST_ERROR_OBJECT (evaspixmapsink,"could not get evas(0x%x) from evas image object(0x%x)",e, eo);
3570 ee = ecore_evas_ecore_evas_get(e);
3572 GST_ERROR_OBJECT (evaspixmapsink,"could not get ecore_evas(0x%x)",ee);
3574 evaspixmapsink->ee = ee;
3575 ecore_evas_data_set (evaspixmapsink->ee, "evaspixmapsink_handle", evaspixmapsink);
3576 ecore_evas_callback_post_render_set(ee, ecore_evas_post_render_callback_handler);
3577 GST_INFO_OBJECT (evaspixmapsink,"ecore_evas_callback_post_render_set() success, Ecore_Evas(0x%x), Evas_Object(0x%x)", ee, eo);
3580 GST_INFO_OBJECT (evaspixmapsink,"Evas Image Object(%x) is set", evaspixmapsink->eo);
3583 GST_ERROR_OBJECT (evaspixmapsink,"Cannot set evas-object property: value is not an evas image object");
3588 evaspixmapsink->flip = g_value_get_enum(value);
3590 case PROP_ROTATE_ANGLE:
3591 evaspixmapsink->rotate_angle = g_value_get_enum (value);
3595 gboolean visible = g_value_get_boolean (value);
3596 if (evaspixmapsink->visible != visible) {
3597 if (evaspixmapsink->eo) {
3598 g_mutex_lock( evaspixmapsink->flow_lock );
3601 for (i = 0; i < evaspixmapsink->num_of_pixmaps; i++) {
3602 if (evaspixmapsink->xpixmap[i]) {
3603 gst_evaspixmapsink_xpixmap_clear (evaspixmapsink, evaspixmapsink->xpixmap[i]);
3606 evas_object_hide(evaspixmapsink->eo);
3607 GST_INFO_OBJECT (evaspixmapsink,"object hide..");
3609 evas_object_show(evaspixmapsink->eo);
3610 GST_INFO_OBJECT (evaspixmapsink,"object show..");
3612 evaspixmapsink->visible = visible;
3613 g_mutex_unlock( evaspixmapsink->flow_lock );
3615 GST_WARNING_OBJECT (evaspixmapsink,"evas image object was not set");
3620 case PROP_ORIGIN_SIZE:
3621 evaspixmapsink->use_origin_size = g_value_get_boolean (value);
3622 GST_INFO_OBJECT (evaspixmapsink,"set origin-size (%d)",evaspixmapsink->use_origin_size);
3623 if (evaspixmapsink->previous_origin_size != evaspixmapsink->use_origin_size) {
3624 if (!gst_evaspixmapsink_xpixmap_link(evaspixmapsink)) {
3625 GST_WARNING_OBJECT (evaspixmapsink,"link evas image object with pixmap failed...");
3627 evaspixmapsink->previous_origin_size = evaspixmapsink->use_origin_size;
3631 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
3637 gst_evaspixmapsink_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
3639 GstEvasPixmapSink *evaspixmapsink;
3641 g_return_if_fail (GST_IS_EVASPIXMAPSINK (object));
3643 evaspixmapsink = GST_EVASPIXMAPSINK (object);
3647 g_value_set_int (value, evaspixmapsink->hue);
3650 g_value_set_int (value, evaspixmapsink->contrast);
3652 case PROP_BRIGHTNESS:
3653 g_value_set_int (value, evaspixmapsink->brightness);
3655 case PROP_SATURATION:
3656 g_value_set_int (value, evaspixmapsink->saturation);
3659 g_value_set_string (value, evaspixmapsink->display_name);
3661 case PROP_SYNCHRONOUS:
3662 g_value_set_boolean (value, evaspixmapsink->synchronous);
3664 case PROP_PIXEL_ASPECT_RATIO:
3665 if (evaspixmapsink->par) {
3666 if (!g_value_transform (evaspixmapsink->par, value)) {
3667 g_warning ("g_value_transform() failure");
3673 char *adaptor_no_s = g_strdup_printf ("%u", evaspixmapsink->adaptor_no);
3674 g_value_set_string (value, adaptor_no_s);
3675 g_free (adaptor_no_s);
3678 case PROP_DEVICE_NAME:
3679 if (evaspixmapsink->xcontext && evaspixmapsink->xcontext->adaptors) {
3680 g_value_set_string (value,
3681 evaspixmapsink->xcontext->adaptors[evaspixmapsink->adaptor_no]);
3683 g_value_set_string (value, NULL);
3686 case PROP_DOUBLE_BUFFER:
3687 g_value_set_boolean (value, evaspixmapsink->double_buffer);
3689 case PROP_AUTOPAINT_COLORKEY:
3690 g_value_set_boolean (value, evaspixmapsink->autopaint_colorkey);
3693 g_value_set_int (value, evaspixmapsink->colorkey);
3695 case PROP_PIXMAP_WIDTH:
3696 if (evaspixmapsink->xpixmap) {
3697 // g_value_set_uint64 (value, evaspixmapsink->xpixmap->width);
3699 g_value_set_uint64 (value, 0);
3702 case PROP_PIXMAP_HEIGHT:
3703 if (evaspixmapsink->xpixmap) {
3704 // g_value_set_uint64 (value, evaspixmapsink->xpixmap->height);
3706 g_value_set_uint64 (value, 0);
3709 case PROP_DISPLAY_GEOMETRY_METHOD:
3710 g_value_set_enum (value, evaspixmapsink->display_geometry_method);
3712 case PROP_DST_ROI_X:
3713 g_value_set_int (value, evaspixmapsink->dst_roi.x);
3715 case PROP_DST_ROI_Y:
3716 g_value_set_int (value, evaspixmapsink->dst_roi.y);
3718 case PROP_DST_ROI_W:
3719 g_value_set_int (value, evaspixmapsink->dst_roi.w);
3721 case PROP_DST_ROI_H:
3722 g_value_set_int (value, evaspixmapsink->dst_roi.h);
3724 case PROP_STOP_VIDEO:
3725 g_value_set_int (value, evaspixmapsink->stop_video);
3727 case PROP_EVAS_OBJECT:
3728 g_value_set_pointer (value, evaspixmapsink->eo);
3731 g_value_set_enum(value, evaspixmapsink->flip);
3733 case PROP_ROTATE_ANGLE:
3734 g_value_set_enum (value, evaspixmapsink->rotate_angle);
3737 g_value_set_boolean (value, evaspixmapsink->visible);
3739 case PROP_ORIGIN_SIZE:
3740 g_value_set_boolean (value, evaspixmapsink->use_origin_size);
3743 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
3749 gst_evaspixmapsink_reset (GstEvasPixmapSink *evaspixmapsink)
3751 GST_DEBUG_OBJECT (evaspixmapsink,"[START]");
3754 GST_OBJECT_LOCK (evaspixmapsink);
3755 evaspixmapsink->running = FALSE;
3758 /* grab thread and mark it as NULL */
3759 thread = evaspixmapsink->event_thread;
3760 evaspixmapsink->event_thread = NULL;
3761 GST_OBJECT_UNLOCK (evaspixmapsink);
3763 /* Wait for our event thread to finish before we clean up our stuff. */
3765 g_thread_join (thread);
3768 for (i = 0; i < evaspixmapsink->num_of_pixmaps; i++) {
3769 if(evaspixmapsink->damage[i]) {
3770 XDamageDestroy(evaspixmapsink->xcontext->disp, evaspixmapsink->damage[i]);
3771 evaspixmapsink->damage[i] = NULL;
3774 evas_object_event_callback_del (evaspixmapsink->eo, EVAS_CALLBACK_RESIZE, evas_callback_resize_event);
3775 evas_object_event_callback_del (evaspixmapsink->eo, EVAS_CALLBACK_DEL, evas_callback_del_event);
3777 if (evaspixmapsink->evas_pixmap_buf) {
3778 gst_buffer_unref (GST_BUFFER_CAST (evaspixmapsink->evas_pixmap_buf));
3779 evaspixmapsink->evas_pixmap_buf = NULL;
3782 for (i = 0; i < evaspixmapsink->num_of_pixmaps; i++) {
3783 gst_evaspixmapsink_xpixmap_clear (evaspixmapsink, evaspixmapsink->xpixmap[i]);
3784 gst_evaspixmapsink_xpixmap_destroy (evaspixmapsink, evaspixmapsink->xpixmap[i]);
3785 evaspixmapsink->xpixmap[i] = NULL;
3787 if (evaspixmapsink->eo) {
3788 evas_object_image_native_surface_set(evaspixmapsink->eo, NULL);
3789 evaspixmapsink->eo = NULL;
3792 evaspixmapsink->render_rect.x = evaspixmapsink->render_rect.y =
3793 evaspixmapsink->render_rect.w = evaspixmapsink->render_rect.h = 0;
3794 evaspixmapsink->have_render_rect = FALSE;
3796 gst_evaspixmapsink_xcontext_clear (evaspixmapsink);
3798 GST_DEBUG_OBJECT (evaspixmapsink,"[END]");
3801 /* Finalize is called only once, dispose can be called multiple times.
3802 * We use mutexes and don't reset stuff to NULL here so let's register
3805 gst_evaspixmapsink_finalize (GObject *object)
3807 GstEvasPixmapSink *evaspixmapsink;
3808 evaspixmapsink = GST_EVASPIXMAPSINK (object);
3809 GST_DEBUG_OBJECT (evaspixmapsink,"[START]");
3811 if (evaspixmapsink->display_name) {
3812 g_free (evaspixmapsink->display_name);
3813 evaspixmapsink->display_name = NULL;
3815 if (evaspixmapsink->par) {
3816 g_free (evaspixmapsink->par);
3817 evaspixmapsink->par = NULL;
3819 if (evaspixmapsink->x_lock) {
3820 g_mutex_free (evaspixmapsink->x_lock);
3821 evaspixmapsink->x_lock = NULL;
3823 if (evaspixmapsink->flow_lock) {
3824 g_mutex_free (evaspixmapsink->flow_lock);
3825 evaspixmapsink->flow_lock = NULL;
3827 if (evaspixmapsink->pixmap_ref_lock) {
3828 g_mutex_free (evaspixmapsink->pixmap_ref_lock);
3829 evaspixmapsink->pixmap_ref_lock = NULL;
3831 if (evaspixmapsink->epipe) {
3832 ecore_pipe_del (evaspixmapsink->epipe);
3833 evaspixmapsink->epipe = NULL;
3835 if (evaspixmapsink->ee) {
3836 ecore_evas_callback_post_render_set(evaspixmapsink->ee, NULL);
3839 GST_DEBUG_OBJECT (evaspixmapsink,"[END]");
3841 G_OBJECT_CLASS (parent_class)->finalize (object);
3843 MMTA_ACUM_ITEM_SHOW_RESULT_TO(MMTA_SHOW_FILE);
3848 gst_evaspixmapsink_init (GstEvasPixmapSink *evaspixmapsink)
3851 evaspixmapsink->display_name = NULL;
3852 evaspixmapsink->adaptor_no = 0;
3853 evaspixmapsink->xcontext = NULL;
3855 for (i = 0; i < NUM_OF_PIXMAP; i++) {
3856 evaspixmapsink->xpixmap[i] = NULL;
3857 evaspixmapsink->damage[i] = 0;
3860 evaspixmapsink->evas_pixmap_buf = NULL;
3862 evaspixmapsink->hue = evaspixmapsink->saturation = 0;
3863 evaspixmapsink->contrast = evaspixmapsink->brightness = 0;
3864 evaspixmapsink->cb_changed = FALSE;
3866 evaspixmapsink->fps_n = 0;
3867 evaspixmapsink->fps_d = 0;
3868 evaspixmapsink->video_width = 0;
3869 evaspixmapsink->video_height = 0;
3871 evaspixmapsink->x_lock = g_mutex_new ();
3872 evaspixmapsink->flow_lock = g_mutex_new ();
3873 evaspixmapsink->pixmap_ref_lock = g_mutex_new();
3875 evaspixmapsink->synchronous = FALSE;
3876 evaspixmapsink->double_buffer = TRUE;
3877 evaspixmapsink->par = NULL;
3878 evaspixmapsink->autopaint_colorkey = TRUE;
3879 evaspixmapsink->running = FALSE;
3881 /* on 16bit displays this becomes r,g,b = 1,2,3
3882 * on 24bit displays this becomes r,g,b = 8,8,16
3883 * as a port atom value
3885 evaspixmapsink->colorkey = (8 << 16) | (8 << 8) | 16;
3887 evaspixmapsink->display_geometry_method = DEF_DISPLAY_GEOMETRY_METHOD;
3888 evaspixmapsink->dst_roi.x = 0;
3889 evaspixmapsink->dst_roi.y = 0;
3890 evaspixmapsink->dst_roi.w = 0;
3891 evaspixmapsink->dst_roi.h = 0;
3892 evaspixmapsink->scr_w = 0;
3893 evaspixmapsink->scr_h = 0;
3894 evaspixmapsink->aligned_width = 0;
3895 evaspixmapsink->aligned_height = 0;
3896 evaspixmapsink->stop_video = FALSE;
3897 evaspixmapsink->eo = NULL;
3898 evaspixmapsink->ee = NULL;
3899 evaspixmapsink->epipe = NULL;
3900 evaspixmapsink->do_link = FALSE;
3901 evaspixmapsink->flip = DEF_DISPLAY_FLIP;
3902 evaspixmapsink->rotate_angle = DEGREE_0;
3903 evaspixmapsink->visible = TRUE;
3904 evaspixmapsink->use_origin_size = FALSE;
3905 evaspixmapsink->previous_origin_size = FALSE;
3907 evaspixmapsink->num_of_pixmaps = NUM_OF_PIXMAP;
3908 evaspixmapsink->last_damaged_pixmap_idx = -1;
3914 gst_evaspixmapsink_base_init (gpointer g_class)
3916 GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
3918 gst_element_class_set_details_simple (element_class,
3919 "EvasPixmapSink", "Sink/Video",
3920 "evas image object videosink based on Xv extension", "Sangchul Lee <sc11.lee@samsung.com>");
3922 gst_element_class_add_pad_template (element_class,
3923 gst_static_pad_template_get (&gst_evaspixmapsink_sink_template_factory));
3927 gst_evaspixmapsink_class_init (GstEvasPixmapSinkClass *klass)
3929 GObjectClass *gobject_class;
3930 GstElementClass *gstelement_class;
3931 GstBaseSinkClass *gstbasesink_class;
3932 GstVideoSinkClass *videosink_class;
3934 gobject_class = (GObjectClass *) klass;
3935 gstelement_class = (GstElementClass *) klass;
3936 gstbasesink_class = (GstBaseSinkClass *) klass;
3937 videosink_class = (GstVideoSinkClass *) klass;
3939 parent_class = g_type_class_peek_parent (klass);
3941 gobject_class->set_property = gst_evaspixmapsink_set_property;
3942 gobject_class->get_property = gst_evaspixmapsink_get_property;
3944 g_object_class_install_property (gobject_class, PROP_CONTRAST,
3945 g_param_spec_int ("contrast", "Contrast", "The contrast of the video",
3946 -1000, 1000, 0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
3947 g_object_class_install_property (gobject_class, PROP_BRIGHTNESS,
3948 g_param_spec_int ("brightness", "Brightness",
3949 "The brightness of the video", -1000, 1000, 0,
3950 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
3951 g_object_class_install_property (gobject_class, PROP_HUE,
3952 g_param_spec_int ("hue", "Hue", "The hue of the video", -1000, 1000, 0,
3953 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
3954 g_object_class_install_property (gobject_class, PROP_SATURATION,
3955 g_param_spec_int ("saturation", "Saturation",
3956 "The saturation of the video", -1000, 1000, 0,
3957 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
3958 g_object_class_install_property (gobject_class, PROP_DISPLAY,
3959 g_param_spec_string ("display", "Display", "X Display name", NULL,
3960 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
3961 g_object_class_install_property (gobject_class, PROP_SYNCHRONOUS,
3962 g_param_spec_boolean ("synchronous", "Synchronous",
3963 "When enabled, runs "
3964 "the X display in synchronous mode. (used only for debugging)", FALSE,
3965 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
3966 g_object_class_install_property (gobject_class, PROP_PIXEL_ASPECT_RATIO,
3967 g_param_spec_string ("pixel-aspect-ratio", "Pixel Aspect Ratio",
3968 "The pixel aspect ratio of the device", "1/1",
3969 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
3970 g_object_class_install_property (gobject_class, PROP_DEVICE,
3971 g_param_spec_string ("device", "Adaptor number",
3972 "The number of the video adaptor", "0",
3973 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
3974 g_object_class_install_property (gobject_class, PROP_DEVICE_NAME,
3975 g_param_spec_string ("device-name", "Adaptor name",
3976 "The name of the video adaptor", NULL,
3977 G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
3980 * GstEvasPixmapSink:double-buffer
3982 * Whether to double-buffer the output.
3986 g_object_class_install_property (gobject_class, PROP_DOUBLE_BUFFER,
3987 g_param_spec_boolean ("double-buffer", "Double-buffer",
3988 "Whether to double-buffer the output", TRUE,
3989 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
3991 * GstEvasPixmapSink:autopaint-colorkey
3993 * Whether to autofill overlay with colorkey
3997 g_object_class_install_property (gobject_class, PROP_AUTOPAINT_COLORKEY,
3998 g_param_spec_boolean ("autopaint-colorkey", "Autofill with colorkey",
3999 "Whether to autofill overlay with colorkey", TRUE,
4000 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
4002 * GstEvasPixmapSink:colorkey
4004 * Color to use for the overlay mask.
4008 g_object_class_install_property (gobject_class, PROP_COLORKEY,
4009 g_param_spec_int ("colorkey", "Colorkey",
4010 "Color to use for the overlay mask", G_MININT, G_MAXINT, 0,
4011 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
4014 * GstEvasPixmapSink:pixmap-width
4016 * Actual width of the pixmap.
4018 g_object_class_install_property (gobject_class, PROP_PIXMAP_WIDTH,
4019 g_param_spec_uint64 ("pixmap-width", "pixmap-width", "Width of the pixmap", 0, G_MAXUINT64, 0, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
4022 * GstEvasPixmapSink:pixmap-height
4024 * Actual height of the pixmap.
4026 g_object_class_install_property (gobject_class, PROP_PIXMAP_HEIGHT,
4027 g_param_spec_uint64 ("pixmap-height", "pixmap-height", "Height of the pixmap", 0, G_MAXUINT64, 0, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
4030 * GstEvasPixmapSink:display-geometry-method
4032 * Display geometrical method setting
4034 g_object_class_install_property(gobject_class, PROP_DISPLAY_GEOMETRY_METHOD,
4035 g_param_spec_enum("display-geometry-method", "Display geometry method",
4036 "Geometrical method for display",
4037 GST_TYPE_EVASPIXMAPSINK_DISPLAY_GEOMETRY_METHOD, DEF_DISPLAY_GEOMETRY_METHOD,
4038 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
4041 * GstEvasPixmapSink:dst-roi-x
4043 * X value of Destination ROI
4045 g_object_class_install_property (gobject_class, PROP_DST_ROI_X,
4046 g_param_spec_int ("dst-roi-x", "Dst-ROI-X",
4047 "X value of Destination ROI(only effective \"CUSTOM_ROI\")", 0, XV_SCREEN_SIZE_WIDTH, 0,
4048 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
4051 * GstEvasPixmapSink:dst-roi-y
4053 * Y value of Destination ROI
4055 g_object_class_install_property (gobject_class, PROP_DST_ROI_Y,
4056 g_param_spec_int ("dst-roi-y", "Dst-ROI-Y",
4057 "Y value of Destination ROI(only effective \"CUSTOM_ROI\")", 0, XV_SCREEN_SIZE_HEIGHT, 0,
4058 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
4061 * GstEvasPixmapSink:dst-roi-w
4063 * W value of Destination ROI
4065 g_object_class_install_property (gobject_class, PROP_DST_ROI_W,
4066 g_param_spec_int ("dst-roi-w", "Dst-ROI-W",
4067 "W value of Destination ROI(only effective \"CUSTOM_ROI\")", 0, XV_SCREEN_SIZE_WIDTH, 0,
4068 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
4071 * GstEvasPixmapSink:dst-roi-h
4073 * H value of Destination ROI
4075 g_object_class_install_property (gobject_class, PROP_DST_ROI_H,
4076 g_param_spec_int ("dst-roi-h", "Dst-ROI-H",
4077 "H value of Destination ROI(only effective \"CUSTOM_ROI\")", 0, XV_SCREEN_SIZE_HEIGHT, 0,
4078 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
4081 * GstEvasPixmapSink:stop-video
4083 * Stop video for releasing video source buffer
4085 g_object_class_install_property (gobject_class, PROP_STOP_VIDEO,
4086 g_param_spec_int ("stop-video", "Stop-Video", "Stop video for releasing video source buffer", 0, 1, 0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
4089 * GstEvasPixmapSink:evas-object
4091 * Evas image object for rendering
4093 g_object_class_install_property (gobject_class, PROP_EVAS_OBJECT,
4094 g_param_spec_pointer ("evas-object", "Destination Evas Object", "Destination evas image object", G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
4097 * GstEvasPixmapSink:display-flip
4099 * Display flip setting
4101 g_object_class_install_property(gobject_class, PROP_FLIP,
4102 g_param_spec_enum("flip", "Display flip",
4104 GST_TYPE_EVASPIXMAPSINK_FLIP, DEF_DISPLAY_FLIP,
4105 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
4108 * GstEvasPixmapSink:rotate
4110 * draw rotation angle setting
4112 g_object_class_install_property(gobject_class, PROP_ROTATE_ANGLE,
4113 g_param_spec_enum("rotate", "Rotate angle", "Rotate angle of display output",GST_TYPE_EVASPIXMAPSINK_ROTATE_ANGLE, DEGREE_0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
4116 * GstEvasPixmapSink:visible
4118 * visible setting for a evas image object
4120 g_object_class_install_property (gobject_class, PROP_VISIBLE,
4121 g_param_spec_boolean ("visible", "Visible", "When setting it false, evas image object does not show", TRUE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
4124 * GstEvasPixmapSink:origin-size
4126 * Set pixmap size with media source's width and height
4128 g_object_class_install_property (gobject_class, PROP_ORIGIN_SIZE,
4129 g_param_spec_boolean ("origin-size", "Origin-Size", "When setting it true, pixmap will be created with media source's width and height", FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
4131 gobject_class->finalize = gst_evaspixmapsink_finalize;
4133 gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_evaspixmapsink_change_state);
4134 gstbasesink_class->get_caps = GST_DEBUG_FUNCPTR (gst_evaspixmapsink_getcaps);
4135 gstbasesink_class->set_caps = GST_DEBUG_FUNCPTR (gst_evaspixmapsink_setcaps);
4136 gstbasesink_class->get_times = GST_DEBUG_FUNCPTR (gst_evaspixmapsink_get_times);
4137 gstbasesink_class->event = GST_DEBUG_FUNCPTR (gst_evaspixmapsink_event);
4138 videosink_class->show_frame = GST_DEBUG_FUNCPTR (gst_evaspixmapsink_show_frame);
4141 /* Object typing & Creation */
4143 gst_evaspixmapsink_get_type (void)
4145 static GType evaspixmapsink_type = 0;
4147 if (!evaspixmapsink_type) {
4148 static const GTypeInfo evaspixmapsink_info = {
4149 sizeof (GstEvasPixmapSinkClass),
4150 gst_evaspixmapsink_base_init,
4152 (GClassInitFunc) gst_evaspixmapsink_class_init,
4155 sizeof (GstEvasPixmapSink),
4157 (GInstanceInitFunc) gst_evaspixmapsink_init,
4159 static const GInterfaceInfo iface_info = {
4160 (GInterfaceInitFunc) gst_evaspixmapsink_interface_init,
4164 static const GInterfaceInfo navigation_info = {
4165 (GInterfaceInitFunc) gst_evaspixmapsink_navigation_init,
4169 static const GInterfaceInfo colorbalance_info = {
4170 (GInterfaceInitFunc) gst_evaspixmapsink_colorbalance_init,
4174 static const GInterfaceInfo propertyprobe_info = {
4175 (GInterfaceInitFunc) gst_evaspixmapsink_property_probe_interface_init,
4179 evaspixmapsink_type = g_type_register_static (GST_TYPE_VIDEO_SINK, "GstEvasPixmapSink", &evaspixmapsink_info, 0);
4181 g_type_add_interface_static (evaspixmapsink_type, GST_TYPE_IMPLEMENTS_INTERFACE, &iface_info);
4182 g_type_add_interface_static (evaspixmapsink_type, GST_TYPE_NAVIGATION, &navigation_info);
4183 g_type_add_interface_static (evaspixmapsink_type, GST_TYPE_COLOR_BALANCE, &colorbalance_info);
4184 g_type_add_interface_static (evaspixmapsink_type, GST_TYPE_PROPERTY_PROBE, &propertyprobe_info);
4186 /* register type and create class in a more safe place instead of at
4187 * runtime since the type registration and class creation is not
4189 g_type_class_ref (gst_evaspixmap_buffer_get_type ());
4192 return evaspixmapsink_type;
4196 plugin_init (GstPlugin *plugin)
4198 if (!gst_element_register (plugin, "evaspixmapsink", GST_RANK_NONE, GST_TYPE_EVASPIXMAPSINK)) {
4201 GST_DEBUG_CATEGORY_INIT (gst_debug_evaspixmapsink, "evaspixmapsink", 0, "evaspixmapsink element");
4202 GST_DEBUG_CATEGORY_GET (GST_CAT_PERFORMANCE, "GST_PERFORMANCE");
4207 GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, GST_VERSION_MINOR,
4208 "evaspixmapsink","Evas image object render plugin using Xv extension", plugin_init,
4209 VERSION, GST_LICENSE, GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN)