/* GStreamer
* Copyright (C) <2005> Julien Moutte <julien@moutte.net>
- * <2009>,<2010> Stefan Kost <stefan.kost@nokia.com>
+ * <2009>,<2010> Stefan Kost <stefan.kost@nokia.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* SECTION:element-xvimagesink
*
* XvImageSink renders video frames to a drawable (XWindow) on a local display
- * using the XVideo extension. Rendering to a remote display is theorically
+ * using the XVideo extension. Rendering to a remote display is theoretically
* possible but i doubt that the XVideo extension is actually available when
* connecting to a remote display. This element can receive a Window ID from the
* application through the XOverlay interface and will then render video frames
/* arbitrary data */
int data[16];
} SCMN_IMGB;
-
-#endif
+#endif /* GST_EXT_XV_ENHANCEMENT */
/* Debugging category */
#include <gst/gstinfo.h>
+
+#include "gst/glib-compat-private.h"
+
GST_DEBUG_CATEGORY_STATIC (gst_debug_xvimagesink);
#define GST_CAT_DEFAULT gst_debug_xvimagesink
GST_DEBUG_CATEGORY_STATIC (GST_CAT_PERFORMANCE);
{
static GType xvimagesink_display_mode_type = 0;
static const GEnumValue display_mode_type[] = {
- { 1, "Display to both TV and LCD", "BOTH"},
- { 2, "Display to TV", "TVONLY"},
- { 3, "Display to LCD", "LCDONLY"},
- { 4, "Display caption on TV", "TVCAPTION"},
- { 5, NULL, NULL},
+ { 0, "Default mode", "DEFAULT"},
+ { 1, "Primary video ON and Secondary video FULL SCREEN mode", "PRI_VIDEO_ON_AND_SEC_VIDEO_FULL_SCREEN"},
+ { 2, "Primary video OFF and Secondary video FULL SCREEN mode", "PRI_VIDEO_OFF_AND_SEC_VIDEO_FULL_SCREEN"},
+ { 3, NULL, NULL},
};
if (!xvimagesink_display_mode_type) {
#ifdef GST_EXT_XV_ENHANCEMENT
static XImage *make_transparent_image(Display *d, Window win, int w, int h);
-#endif
+static gboolean set_display_mode(GstXContext *xcontext, int set_mode);
+#endif /* GST_EXT_XV_ENHANCEMENT */
/* Default template - initiated with class struct to allow gst-register to work
without X running */
PROP_DST_ROI_W,
PROP_DST_ROI_H,
PROP_STOP_VIDEO,
-#endif
+#endif /* GST_EXT_XV_ENHANCEMENT */
};
-static GstVideoSinkClass *parent_class = NULL;
+static void gst_xvimagesink_init_interfaces (GType type);
+
+GST_BOILERPLATE_FULL (GstXvImageSink, gst_xvimagesink, GstVideoSink,
+ GST_TYPE_VIDEO_SINK, gst_xvimagesink_init_interfaces);
+
/* ============================================================= */
/* */
xvimagesink->aligned_width = xvimage->width;
xvimagesink->aligned_height = xvimage->height;
}
-#endif
+#endif /* GST_EXT_XV_ENHANCEMENT */
xvimage->im_format = gst_xvimagesink_get_format_from_caps (xvimagesink, caps);
if (xvimage->im_format == -1) {
xvimage->im_format, NULL,
#ifdef GST_EXT_XV_ENHANCEMENT
xvimagesink->aligned_width, xvimagesink->aligned_height, &xvimage->SHMInfo);
-#else
+#else /* GST_EXT_XV_ENHANCEMENT */
xvimage->width, xvimage->height, &xvimage->SHMInfo);
-#endif
+#endif /* GST_EXT_XV_ENHANCEMENT */
if (!xvimage->xvimage || error_caught) {
g_mutex_unlock (xvimagesink->x_lock);
- /* Reset error handler */
+
+ /* Reset error flag */
error_caught = FALSE;
- XSetErrorHandler (handler);
- /* Push an error */
- GST_ELEMENT_ERROR (xvimagesink, RESOURCE, WRITE,
+
+ /* Push a warning */
+ GST_ELEMENT_WARNING (xvimagesink, RESOURCE, WRITE,
("Failed to create output image buffer of %dx%d pixels",
xvimage->width, xvimage->height),
("could not XvShmCreateImage a %dx%d image",
xvimage->width, xvimage->height));
- goto beach_unlocked;
+
+ /* Retry without XShm */
+ xvimagesink->xcontext->use_xshm = FALSE;
+
+ /* Hold X mutex again to try without XShm */
+ g_mutex_lock (xvimagesink->x_lock);
+ goto no_xshm;
}
/* we have to use the returned data_size for our shm size */
case GST_MAKE_FOURCC ('S', 'Y', 'V', 'Y'):
expected_size = sizeof(SCMN_IMGB);
break;
-#endif
+#endif /* GST_EXT_XV_ENHANCEMENT */
default:
expected_size = 0;
break;
GST_DEBUG_OBJECT (xvimagesink, "XServer ShmAttached to 0x%x, id 0x%lx",
xvimage->SHMInfo.shmid, xvimage->SHMInfo.shmseg);
} else
+ no_xshm:
#endif /* HAVE_XSHM */
{
xvimage->xvimage = XvCreateImage (xvimagesink->xcontext->disp,
xvimagesink->xcontext->xv_port_id,
#ifdef GST_EXT_XV_ENHANCEMENT
xvimage->im_format, NULL, xvimagesink->aligned_width, xvimagesink->aligned_height);
-#else
+#else /* GST_EXT_XV_ENHANCEMENT */
xvimage->im_format, NULL, xvimage->width, xvimage->height);
-#endif
+#endif /* GST_EXT_XV_ENHANCEMENT */
if (!xvimage->xvimage || error_caught) {
g_mutex_unlock (xvimagesink->x_lock);
/* Reset error handler */
gboolean draw_border = FALSE;
#ifdef GST_EXT_XV_ENHANCEMENT
- static Atom atom = None;
+ static Atom atom_rotation = None;
GstVideoRectangle src_origin = { 0, 0, 0, 0};
GstVideoRectangle src_input = { 0, 0, 0, 0};
int rotate = 0;
int ret = 0;
- //int window_rotate = 0;
-#endif
+#endif /* GST_EXT_XV_ENHANCEMENT */
/* We take the flow_lock. If expose is in there we don't want to run
concurrently from the data flow thread */
if (G_UNLIKELY (xvimagesink->xwindow == NULL)) {
#ifdef GST_EXT_XV_ENHANCEMENT
GST_INFO_OBJECT( xvimagesink, "xwindow is NULL. Skip xvimage_put." );
-#endif
+#endif /* GST_EXT_XV_ENHANCEMENT */
g_mutex_unlock (xvimagesink->flow_lock);
return FALSE;
}
#ifdef GST_EXT_XV_ENHANCEMENT
- if( xvimagesink->visible == FALSE )
- {
- GST_INFO_OBJECT( xvimagesink, "visible is FALSE. Skip xvimage_put." );
- g_mutex_unlock( xvimagesink->flow_lock );
+ if (xvimagesink->visible == FALSE) {
+ GST_INFO_OBJECT(xvimagesink, "visible is FALSE. Skip xvimage_put.");
+ g_mutex_unlock(xvimagesink->flow_lock);
return TRUE;
}
-#endif
+#endif /* GST_EXT_XV_ENHANCEMENT */
/* Draw borders when displaying the first frame. After this
draw borders only on expose event or after a size change. */
xvimage = xvimagesink->cur_image;
} else {
#ifdef GST_EXT_XV_ENHANCEMENT
- GST_INFO_OBJECT( xvimagesink, "cur_image is NULL. Skip xvimage_put." );
-#endif
+ GST_INFO_OBJECT(xvimagesink, "cur_image is NULL. Skip xvimage_put.");
+#endif /* GST_EXT_XV_ENHANCEMENT */
g_mutex_unlock (xvimagesink->flow_lock);
return TRUE;
}
break;
case DISP_GEO_METHOD_CUSTOM_ROI:
+#ifdef GST_EXT_XV_ENHANCEMENT_ROI_MODE
+ switch (xvimagesink->rotate_angle) {
+ case DEGREE_90:
+ result.w = xvimagesink->dst_roi.h;
+ result.h = xvimagesink->dst_roi.w;
+
+ result.x = xvimagesink->dst_roi.y;
+ result.y = xvimagesink->xwindow->height - xvimagesink->dst_roi.x - xvimagesink->dst_roi.w;
+ break;
+ case DEGREE_180:
+ result.w = xvimagesink->dst_roi.w;
+ result.h = xvimagesink->dst_roi.h;
+
+ result.x = xvimagesink->xwindow->width - result.w - xvimagesink->dst_roi.x;
+ result.y = xvimagesink->xwindow->height - result.h - xvimagesink->dst_roi.y;
+ break;
+ case DEGREE_270:
+ result.w = xvimagesink->dst_roi.h;
+ result.h = xvimagesink->dst_roi.w;
+
+ result.x = xvimagesink->xwindow->width - xvimagesink->dst_roi.y - xvimagesink->dst_roi.h;
+ result.y = xvimagesink->dst_roi.x;
+ break;
+ default:
+ result.x = xvimagesink->dst_roi.x;
+ result.y = xvimagesink->dst_roi.y;
+ result.w = xvimagesink->dst_roi.w;
+ result.h = xvimagesink->dst_roi.h;
+ break;
+ }
+
+ GST_LOG_OBJECT(xvimagesink, "rotate[%d], ROI input[%d,%d,%dx%d] > result[%d,%d,%dx%d]",
+ xvimagesink->rotate_angle,
+ xvimagesink->dst_roi.x, xvimagesink->dst_roi.y, xvimagesink->dst_roi.w, xvimagesink->dst_roi.h,
+ result.x, result.y, result.w, result.h);
+#else /* GST_EXT_XV_ENHANCEMENT_ROI_MODE */
result.x = xvimagesink->dst_roi.x;
result.y = xvimagesink->dst_roi.y;
result.w = xvimagesink->dst_roi.w;
result.w = xvimagesink->dst_roi.h;
result.h = xvimagesink->dst_roi.w;
}
+#endif /* GST_EXT_XV_ENHANCEMENT_ROI_MODE */
break;
default:
src_input.w /= xvimagesink->zoom;
src_input.h /= xvimagesink->zoom;
}
-#else
+#else /* GST_EXT_XV_ENHANCEMENT */
if (xvimagesink->keep_aspect) {
GstVideoRectangle src, dst;
} else {
memcpy (&result, &xvimagesink->render_rect, sizeof (GstVideoRectangle));
}
-#endif
+#endif /* GST_EXT_XV_ENHANCEMENT */
g_mutex_lock (xvimagesink->x_lock);
src_input.h += 1;
}
- GST_LOG_OBJECT( xvimagesink, "screen[%dx%d],window[%d,%d,%dx%d],method[%d],rotate[%d],zoom[%d],src[%dx%d],dst[%d,%d,%dx%d],input[%d,%d,%dx%d],result[%d,%d,%dx%d]",
+ GST_LOG_OBJECT( xvimagesink, "screen[%dx%d],window[%d,%d,%dx%d],method[%d],rotate[%d],zoom[%d],dp_mode[%d],src[%dx%d],dst[%d,%d,%dx%d],input[%d,%d,%dx%d],result[%d,%d,%dx%d]",
xvimagesink->scr_w, xvimagesink->scr_h,
xvimagesink->xwindow->x, xvimagesink->xwindow->y, xvimagesink->xwindow->width, xvimagesink->xwindow->height,
- xvimagesink->display_geometry_method, rotate, xvimagesink->zoom,
+ xvimagesink->display_geometry_method, rotate, xvimagesink->zoom, xvimagesink->display_mode,
src_origin.w, src_origin.h,
dst.x, dst.y, dst.w, dst.h,
src_input.x, src_input.y, src_input.w, src_input.h,
result.x, result.y, result.w, result.h );
- if (atom == None) {
- atom = XInternAtom( xvimagesink->xcontext->disp,
- "_USER_WM_PORT_ATTRIBUTE_ROTATION", False );
+ if (atom_rotation == None) {
+ atom_rotation = XInternAtom(xvimagesink->xcontext->disp,
+ "_USER_WM_PORT_ATTRIBUTE_ROTATION", False);
}
- ret = XvSetPortAttribute(xvimagesink->xcontext->disp, xvimagesink->xcontext->xv_port_id, atom, rotate );
+ ret = XvSetPortAttribute(xvimagesink->xcontext->disp, xvimagesink->xcontext->xv_port_id, atom_rotation, rotate);
if (ret != Success) {
GST_ERROR_OBJECT( xvimagesink, "XvSetPortAttribute failed[%d]. disp[%x],xv_port_id[%d],atom[%x],rotate[%d]",
- ret, xvimagesink->xcontext->disp, xvimagesink->xcontext->xv_port_id, atom, rotate );
+ ret, xvimagesink->xcontext->disp, xvimagesink->xcontext->xv_port_id, atom_rotation, rotate );
return FALSE;
}
return xim;
}
-#endif
+
+
+static gboolean set_display_mode(GstXContext *xcontext, int set_mode)
+{
+ int ret = 0;
+ static gboolean is_exist = FALSE;
+ static XvPortID current_port_id = -1;
+ Atom atom_output = None;
+
+ if (xcontext == NULL) {
+ GST_WARNING("xcontext is NULL");
+ return FALSE;
+ }
+
+ /* check once per one xv_port_id */
+ if (current_port_id != xcontext->xv_port_id) {
+ /* check whether _USER_WM_PORT_ATTRIBUTE_OUTPUT attribute is existed */
+ int i = 0;
+ int count = 0;
+ XvAttribute *const attr = XvQueryPortAttributes(xcontext->disp,
+ xcontext->xv_port_id, &count);
+ is_exist = FALSE;
+ current_port_id = xcontext->xv_port_id;
+ for (i = 0 ; i < count ; i++) {
+ if (!strcmp(attr[i].name, "_USER_WM_PORT_ATTRIBUTE_OUTPUT")) {
+ is_exist = TRUE;
+ GST_INFO("_USER_WM_PORT_ATTRIBUTE_OUTPUT[index %d] found", i);
+ break;
+ }
+ }
+ }
+
+ if (is_exist) {
+ GST_INFO("set display mode %d", set_mode);
+ atom_output = XInternAtom(xcontext->disp,
+ "_USER_WM_PORT_ATTRIBUTE_OUTPUT", False);
+ ret = XvSetPortAttribute(xcontext->disp, xcontext->xv_port_id,
+ atom_output, set_mode);
+ if (ret == Success) {
+ return TRUE;
+ } else {
+ GST_WARNING("display mode[%d] set failed.", set_mode);
+ }
+ } else {
+ GST_WARNING("_USER_WM_PORT_ATTRIBUTE_OUTPUT is not existed");
+ }
+
+ return FALSE;
+}
+#endif /* GST_EXT_XV_ENHANCEMENT */
/* This function handles a GstXWindow creation
* The width and height are the actual pixel size on the display */
#ifdef GST_EXT_XV_ENHANCEMENT
XSetWindowAttributes win_attr;
XWindowAttributes root_attr;
-#endif
+#endif /* GST_EXT_XV_ENHANCEMENT */
g_return_val_if_fail (GST_IS_XVIMAGESINK (xvimagesink), NULL);
/* Make window manager not to change window size as Full screen */
win_attr.override_redirect = True;
XChangeWindowAttributes(xvimagesink->xcontext->disp, xwindow->win, CWOverrideRedirect, &win_attr);
-#else
+#else /* GST_EXT_XV_ENHANCEMENT */
xvimagesink->render_rect.w = width;
xvimagesink->render_rect.h = height;
xwindow->win = XCreateSimpleWindow (xvimagesink->xcontext->disp,
xvimagesink->xcontext->root,
0, 0, width, height, 0, 0, xvimagesink->xcontext->black);
-#endif
+#endif /* GST_EXT_XV_ENHANCEMENT */
/* We have to do that to prevent X from redrawing the background on
* ConfigureNotify. This takes away flickering of video when resizing. */
g_mutex_lock (xvimagesink->x_lock);
/* If we did not create that window we just free the GC and let it live */
- if (xwindow->internal)
+ if (xwindow->internal) {
XDestroyWindow (xvimagesink->xcontext->disp, xwindow->win);
- else
+ if (xvimagesink->xim_transparenter) {
+ XDestroyImage(xvimagesink->xim_transparenter);
+ xvimagesink->xim_transparenter = NULL;
+ }
+ } else {
XSelectInput (xvimagesink->xcontext->disp, xwindow->win, 0);
+ }
XFreeGC (xvimagesink->xcontext->disp, xwindow->gc);
unsigned int cur_win_height = 0;
unsigned int cur_win_border_width = 0;
unsigned int cur_win_depth = 0;
-#else
+#else /* GST_EXT_XV_ENHANCEMENT */
XWindowAttributes attr;
-#endif
+#endif /* GST_EXT_XV_ENHANCEMENT */
g_return_if_fail (GST_IS_XVIMAGESINK (xvimagesink));
xvimagesink->xwindow->width, xvimagesink->xwindow->height,
xvimagesink->render_rect.x, xvimagesink->render_rect.y,
xvimagesink->render_rect.w, xvimagesink->render_rect.h);
-#else
+#else /* GST_EXT_XV_ENHANCEMENT */
XGetWindowAttributes (xvimagesink->xcontext->disp,
xvimagesink->xwindow->win, &attr);
xvimagesink->xwindow->width = attr.width;
xvimagesink->xwindow->height = attr.height;
-
if (!xvimagesink->have_render_rect) {
xvimagesink->render_rect.x = xvimagesink->render_rect.y = 0;
xvimagesink->render_rect.w = attr.width;
xvimagesink->render_rect.h = attr.height;
}
-#endif
+#endif /* GST_EXT_XV_ENHANCEMENT */
g_mutex_unlock (xvimagesink->x_lock);
}
XFillRectangle (xvimagesink->xcontext->disp, xwindow->win, xwindow->gc,
xvimagesink->render_rect.x, xvimagesink->render_rect.y,
xvimagesink->render_rect.w, xvimagesink->render_rect.h);
-#endif
+#endif /* GST_EXT_XV_ENHANCEMENT */
XSync (xvimagesink->xcontext->disp, FALSE);
break;
case ConfigureNotify:
g_mutex_unlock (xvimagesink->x_lock);
+#ifdef GST_EXT_XV_ENHANCEMENT
GST_INFO_OBJECT (xvimagesink, "Call gst_xvimagesink_xwindow_update_geometry!");
+#endif /* GST_EXT_XV_ENHANCEMENT */
gst_xvimagesink_xwindow_update_geometry (xvimagesink);
g_mutex_lock (xvimagesink->x_lock);
configured = TRUE;
/* Handle Display events */
while (XPending (xvimagesink->xcontext->disp)) {
XNextEvent (xvimagesink->xcontext->disp, &e);
+
switch (e.type) {
case ClientMessage:{
#ifdef GST_EXT_XV_ENHANCEMENT
Atom active_win_atom;
Atom deactive_win_atom;
Atom atom_stream;
-#endif
+#endif /* GST_EXT_XV_ENHANCEMENT */
Atom wm_delete;
wm_delete = XInternAtom (xvimagesink->xcontext->disp,
active_win_atom = XInternAtom (xvimagesink->xcontext->disp, "_X_ILLUME_ACTIVATE_WINDOW", False);
deactive_win_atom = XInternAtom (xvimagesink->xcontext->disp, "_X_ILLUME_DEACTIVATE_WINDOW", False);
- if( !active_win_atom || !deactive_win_atom )
- {
+ if (!active_win_atom || !deactive_win_atom) {
GST_WARNING_OBJECT( xvimagesink, "Can NOT get active[%d] or deactive[%d] win atom",
active_win_atom, deactive_win_atom );
- }
- else
- {
- /* Window is DEACTIVATED */
- if( e.xclient.message_type == deactive_win_atom )
- {
+ } else {
+ if (e.xclient.message_type == deactive_win_atom) {
+ /* Window is DEACTIVATED */
/* Get pid of activated/deactivated window */
active_pid = e.xclient.data.l[1];
deactive_pid = e.xclient.data.l[3];
- if( active_pid != deactive_pid )
- {
+ if (active_pid != deactive_pid) {
GST_INFO_OBJECT( xvimagesink, "XClientMessage : Window DEACTIVATED" );
xvimagesink->is_hided = TRUE;
atom_stream = XInternAtom( xvimagesink->xcontext->disp,
"_USER_WM_PORT_ATTRIBUTE_STREAM_OFF", False );
- if( atom_stream != None )
- {
- if( XvSetPortAttribute( xvimagesink->xcontext->disp,
- xvimagesink->xcontext->xv_port_id,
- atom_stream, 0 ) != Success )
- {
+ if (atom_stream != None) {
+ if (XvSetPortAttribute(xvimagesink->xcontext->disp,
+ xvimagesink->xcontext->xv_port_id,
+ atom_stream, 0 ) != Success) {
GST_WARNING_OBJECT( xvimagesink, "STREAM OFF failed" );
}
XSync( xvimagesink->xcontext->disp, FALSE );
}
- }
- else
- {
+ } else {
GST_INFO_OBJECT( xvimagesink, "Window is DEACTIVATED, but same process. so Do not clear screen." );
}
- }
- /* Window is ACTIVATED */
- else if( e.xclient.message_type == active_win_atom )
- {
+ } else if (e.xclient.message_type == active_win_atom) {
+ /* Window is ACTIVATED */
/* Get pid of activated/deactivated window */
active_pid = e.xclient.data.l[1];
deactive_pid = e.xclient.data.l[3];
- if( active_pid != deactive_pid )
- {
+ if (active_pid != deactive_pid) {
GST_INFO_OBJECT( xvimagesink, "XClientMessage : Window ACTIVATED" );
g_mutex_unlock (xvimagesink->x_lock);
g_mutex_lock (xvimagesink->flow_lock);
g_mutex_lock (xvimagesink->x_lock);
- }
- else
- {
+ } else {
GST_INFO_OBJECT( xvimagesink, "Window is ACTIVATED, but same process. so Do not redraw screen." );
}
}
}
-#endif
- }
+#endif /* GST_EXT_XV_ENHANCEMENT */
break;
+ }
default:
break;
}
#ifdef GST_EXT_XV_ENHANCEMENT
xvimagesink->scr_w = max_w;
xvimagesink->scr_h = max_h;
-#endif
+#endif /* GST_EXT_XV_ENHANCEMENT */
}
}
GST_DEBUG_OBJECT (xvimagesink, "run xevent thread, expose %d, events %d",
xvimagesink->handle_expose, xvimagesink->handle_events);
xvimagesink->running = TRUE;
+#if !GLIB_CHECK_VERSION (2, 31, 0)
xvimagesink->event_thread = g_thread_create (
(GThreadFunc) gst_xvimagesink_event_thread, xvimagesink, TRUE, NULL);
+#else
+ xvimagesink->event_thread = g_thread_try_new ("xvimagesink-events",
+ (GThreadFunc) gst_xvimagesink_event_thread, xvimagesink, NULL);
+#endif
}
} else {
if (xvimagesink->event_thread) {
for (i = 0; i < (sizeof (channels) / sizeof (char *)); i++) {
XvAttribute *matching_attr = NULL;
- /* Retrieve the property atom if it exists. If it doesn't exist,
+ /* Retrieve the property atom if it exists. If it doesn't exist,
* the attribute itself must not either, so we can skip */
prop_atom = XInternAtom (xcontext->disp, channels[i], True);
if (prop_atom == None)
channel = g_object_new (GST_TYPE_COLOR_BALANCE_CHANNEL, NULL);
channel->label = g_strdup (channels[i]);
- channel->min_value = matching_attr ? matching_attr->min_value : -1000;
- channel->max_value = matching_attr ? matching_attr->max_value : 1000;
+ channel->min_value = matching_attr->min_value;
+ channel->max_value = matching_attr->max_value;
xcontext->channels_list = g_list_append (xcontext->channels_list,
channel);
if (xv_attr)
XFree (xv_attr);
+#ifdef GST_EXT_XV_ENHANCEMENT
+ set_display_mode(xcontext, xvimagesink->display_mode);
+#endif /* GST_EXT_XV_ENHANCEMENT */
+
g_mutex_unlock (xvimagesink->x_lock);
return xcontext;
const GValue *caps_disp_reg;
const GValue *fps;
guint num, den;
+#ifdef GST_EXT_XV_ENHANCEMENT
+ gboolean enable_last_buffer;
+#endif /* #ifdef GST_EXT_XV_ENHANCEMENT */
xvimagesink = GST_XVIMAGESINK (bsink);
#ifdef GST_EXT_XV_ENHANCEMENT
xvimagesink->aligned_width = video_width;
xvimagesink->aligned_height = video_height;
-#endif
+
+ /* get enable-last-buffer */
+ g_object_get(G_OBJECT(xvimagesink), "enable-last-buffer", &enable_last_buffer, NULL);
+ GST_INFO_OBJECT(xvimagesink, "current enable-last-buffer : %d", enable_last_buffer);
+
+ /* flush if enable-last-buffer is TRUE */
+ if (enable_last_buffer) {
+ GST_INFO_OBJECT(xvimagesink, "flush last-buffer");
+ g_object_set(G_OBJECT(xvimagesink), "enable-last-buffer", FALSE, NULL);
+ g_object_set(G_OBJECT(xvimagesink), "enable-last-buffer", TRUE, NULL);
+ }
+#endif /* GST_EXT_XV_ENHANCEMENT */
xvimagesink->fps_n = gst_value_get_fraction_numerator (fps);
xvimagesink->fps_d = gst_value_get_fraction_denominator (fps);
GST_VIDEO_SINK_HEIGHT (xvimagesink));
}
- /* After a resize, we want to redraw the borders in case the new frame size
+ /* After a resize, we want to redraw the borders in case the new frame size
* doesn't cover the same area */
xvimagesink->redraw_border = TRUE;
GstXContext *xcontext = NULL;
#ifdef GST_EXT_XV_ENHANCEMENT
Atom atom_preemption = None;
-#endif
+#endif /* GST_EXT_XV_ENHANCEMENT */
xvimagesink = GST_XVIMAGESINK (element);
g_mutex_lock (xvimagesink->x_lock);
atom_preemption = XInternAtom( xvimagesink->xcontext->disp,
"_USER_WM_PORT_ATTRIBUTE_PREEMPTION", False );
- if(atom_preemption != None)
- {
- if( XvSetPortAttribute( xvimagesink->xcontext->disp,
- xvimagesink->xcontext->xv_port_id,
- atom_preemption, 1 ) != Success )
- {
+ if (atom_preemption != None) {
+ if (XvSetPortAttribute(xvimagesink->xcontext->disp,
+ xvimagesink->xcontext->xv_port_id,
+ atom_preemption, 1 ) != Success) {
GST_ERROR_OBJECT(xvimagesink, "%d: XvSetPortAttribute: preemption failed.\n", atom_preemption);
}
XSync (xvimagesink->xcontext->disp, FALSE);
}
g_mutex_unlock (xvimagesink->x_lock);
-#endif
+#endif /* GST_EXT_XV_ENHANCEMENT */
break;
case GST_STATE_CHANGE_PAUSED_TO_READY:
g_mutex_lock (xvimagesink->pool_lock);
g_mutex_lock (xvimagesink->x_lock);
atom_preemption = XInternAtom( xvimagesink->xcontext->disp,
"_USER_WM_PORT_ATTRIBUTE_PREEMPTION", False );
- if(atom_preemption != None)
- {
- if( XvSetPortAttribute( xvimagesink->xcontext->disp,
- xvimagesink->xcontext->xv_port_id,
- atom_preemption, 0 ) != Success )
- {
+ if (atom_preemption != None) {
+ if (XvSetPortAttribute(xvimagesink->xcontext->disp,
+ xvimagesink->xcontext->xv_port_id,
+ atom_preemption, 0 ) != Success) {
GST_ERROR_OBJECT(xvimagesink, "%d: XvSetPortAttribute: preemption failed.\n", atom_preemption);
}
XSync (xvimagesink->xcontext->disp, FALSE);
}
g_mutex_unlock (xvimagesink->x_lock);
-#endif
+#endif /* GST_EXT_XV_ENHANCEMENT */
break;
case GST_STATE_CHANGE_PAUSED_TO_READY:
xvimagesink->fps_n = 0;
#ifdef GST_EXT_XV_ENHANCEMENT
XV_PUTIMAGE_DATA_PTR img_data = NULL;
SCMN_IMGB *scmn_imgb = NULL;
- GstMultiPlaneImageBuffer* mp_buf = NULL;
- int ret = 0;
gint format = 0;
-#endif
+#endif /* GST_EXT_XV_ENHANCEMENT */
xvimagesink = GST_XVIMAGESINK (vsink);
#ifdef GST_EXT_XV_ENHANCEMENT
- if( xvimagesink->stop_video )
- {
+ if (xvimagesink->stop_video) {
GST_INFO( "Stop video is TRUE. so skip show frame..." );
return GST_FLOW_OK;
}
-#endif
+#endif /* GST_EXT_XV_ENHANCEMENT */
/* If this buffer has been allocated using our buffer management we simply
put the ximage which is in the PRIVATE pointer */
GST_DEBUG_OBJECT( xvimagesink, "scmn_imgb is NULL. Skip xvimage put..." );
return GST_FLOW_OK;
}
+
+ /* skip buffer if aligned size is smaller than size of caps */
+ if (scmn_imgb->s[0] < xvimagesink->video_width ||
+ scmn_imgb->e[0] < xvimagesink->video_height) {
+ GST_WARNING_OBJECT(xvimagesink, "invalid size[caps:%dx%d,aligned:%dx%d]. Skip this buffer...",
+ xvimagesink->video_width, xvimagesink->video_height,
+ scmn_imgb->s[0], scmn_imgb->e[0]);
+ return GST_FLOW_OK;
+ }
+
xvimagesink->aligned_width = scmn_imgb->s[0];
xvimagesink->aligned_height = scmn_imgb->e[0];
GST_INFO_OBJECT(xvimagesink, "Use aligned width,height[%dx%d]",
GST_INFO_OBJECT(xvimagesink, "Use original width,height of caps");
break;
}
-#endif
+#endif /* GST_EXT_XV_ENHANCEMENT */
xvimagesink->xvimage = gst_xvimagesink_xvimage_new (xvimagesink,
GST_BUFFER_CAPS (buf));
}
#ifdef GST_EXT_XV_ENHANCEMENT
-
switch (xvimagesink->xvimage->im_format) {
/* Cases for specified formats of Samsung extension */
case GST_MAKE_FOURCC('S', 'T', '1', '2'):
case GST_MAKE_FOURCC('S', 'U', 'Y', '2'):
case GST_MAKE_FOURCC('S', 'U', 'Y', 'V'):
case GST_MAKE_FOURCC('S', 'Y', 'V', 'Y'):
+ case GST_MAKE_FOURCC('I', 'T', 'L', 'V'):
{
GST_DEBUG("Samsung extension display format activated. fourcc:%d,display mode:%d,Rotate angle:%d",
xvimagesink->xvimage->im_format, xvimagesink->display_mode, xvimagesink->rotate_angle);
break;
}
}
-#else
+#else /* GST_EXT_XV_ENHANCEMENT */
memcpy (xvimagesink->xvimage->xvimage->data,
GST_BUFFER_DATA (buf),
MIN (GST_BUFFER_SIZE (buf), xvimagesink->xvimage->size));
-#endif
+#endif /* GST_EXT_XV_ENHANCEMENT */
+
if (!gst_xvimagesink_xvimage_put (xvimagesink, xvimagesink->xvimage))
goto no_window;
}
suitable one */
while (xvimagesink->image_pool) {
xvimage = xvimagesink->image_pool->data;
+
if (xvimage) {
/* Removing from the pool */
xvimagesink->image_pool = g_slist_delete_link (xvimagesink->image_pool,
static gboolean
gst_xvimagesink_interface_supported (GstImplementsInterface * iface, GType type)
{
- g_assert (type == GST_TYPE_NAVIGATION || type == GST_TYPE_X_OVERLAY ||
- type == GST_TYPE_COLOR_BALANCE || type == GST_TYPE_PROPERTY_PROBE);
- return TRUE;
+ if (type == GST_TYPE_NAVIGATION || type == GST_TYPE_X_OVERLAY ||
+ type == GST_TYPE_COLOR_BALANCE || type == GST_TYPE_PROPERTY_PROBE)
+ return TRUE;
+ else
+ return FALSE;
}
static void
#ifdef GST_EXT_XV_ENHANCEMENT
GST_INFO_OBJECT( xvimagesink, "ENTER, id : %d", xwindow_id );
-#endif
+#endif /* GST_EXT_XV_ENHANCEMENT */
/* If we already use that window return */
if (xvimagesink->xwindow && (xwindow_id == xvimagesink->xwindow->win)) {
#ifdef GST_EXT_XV_ENHANCEMENT
GST_INFO_OBJECT( xvimagesink, "xid is 0. create window[%dx%d]",
GST_VIDEO_SINK_WIDTH (xvimagesink), GST_VIDEO_SINK_HEIGHT (xvimagesink) );
-#endif
+#endif /* GST_EXT_XV_ENHANCEMENT */
if (GST_VIDEO_SINK_WIDTH (xvimagesink)
&& GST_VIDEO_SINK_HEIGHT (xvimagesink)) {
xwindow =
#ifdef GST_EXT_XV_ENHANCEMENT
GST_INFO_OBJECT( xvimagesink, "Overlay window exposed. update it");
gst_xvimagesink_xvimage_put (xvimagesink, xvimagesink->xvimage);
-#else
+#else /* GST_EXT_XV_ENHANCEMENT */
gst_xvimagesink_xvimage_put (xvimagesink, NULL);
-#endif
+#endif /* GST_EXT_XV_ENHANCEMENT */
}
static void
break;
#ifdef GST_EXT_XV_ENHANCEMENT
case PROP_DISPLAY_MODE:
- xvimagesink->display_mode = g_value_get_enum (value);
+ {
+ int set_mode = g_value_get_enum (value);
+
+ g_mutex_lock(xvimagesink->flow_lock);
+ g_mutex_lock(xvimagesink->x_lock);
+
+ if (xvimagesink->display_mode != set_mode) {
+ if (xvimagesink->xcontext) {
+ /* set display mode */
+ if (set_display_mode(xvimagesink->xcontext, set_mode)) {
+ xvimagesink->display_mode = set_mode;
+ } else {
+ GST_WARNING_OBJECT(xvimagesink, "display mode[%d] set failed.", set_mode);
+ }
+ } else {
+ /* "xcontext" is not created yet. It will be applied when xcontext is created. */
+ GST_INFO_OBJECT(xvimagesink, "xcontext is NULL. display-mode will be set later.");
+ xvimagesink->display_mode = set_mode;
+ }
+ } else {
+ GST_INFO_OBJECT(xvimagesink, "skip display mode %d, because current mode is same", set_mode);
+ }
+
+ g_mutex_unlock(xvimagesink->x_lock);
+ g_mutex_unlock(xvimagesink->flow_lock);
+ }
break;
case PROP_DISPLAY_GEOMETRY_METHOD:
xvimagesink->display_geometry_method = g_value_get_enum (value);
g_mutex_lock( xvimagesink->flow_lock );
g_mutex_lock( xvimagesink->x_lock );
- if( xvimagesink->visible && ( g_value_get_boolean( value ) == FALSE ) )
- {
+ if (xvimagesink->visible && (g_value_get_boolean(value) == FALSE)) {
Atom atom_stream = XInternAtom( xvimagesink->xcontext->disp,
"_USER_WM_PORT_ATTRIBUTE_STREAM_OFF", False );
- if( atom_stream != None )
- {
- if( XvSetPortAttribute( xvimagesink->xcontext->disp,
- xvimagesink->xcontext->xv_port_id,
- atom_stream, 0 ) != Success )
- {
+ if (atom_stream != None) {
+ if (XvSetPortAttribute(xvimagesink->xcontext->disp,
+ xvimagesink->xcontext->xv_port_id,
+ atom_stream, 0 ) != Success) {
GST_WARNING_OBJECT( xvimagesink, "Set visible FALSE failed" );
}
XSync( xvimagesink->xcontext->disp, FALSE );
}
- }
- else if( !xvimagesink->visible && ( g_value_get_boolean( value ) == TRUE ) )
- {
+ } else if (!xvimagesink->visible && (g_value_get_boolean(value) == TRUE)) {
g_mutex_unlock( xvimagesink->x_lock );
g_mutex_unlock( xvimagesink->flow_lock );
GST_INFO_OBJECT( xvimagesink, "Set visible as TRUE. Update it." );
g_mutex_unlock( xvimagesink->flow_lock );
break;
-#endif
+#endif /* GST_EXT_XV_ENHANCEMENT */
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
case PROP_STOP_VIDEO:
g_value_set_int (value, xvimagesink->stop_video);
break;
-#endif
+#endif /* GST_EXT_XV_ENHANCEMENT */
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
G_OBJECT_CLASS (parent_class)->finalize (object);
}
-
static void
-gst_xvimagesink_init (GstXvImageSink * xvimagesink)
+gst_xvimagesink_init (GstXvImageSink * xvimagesink,
+ GstXvImageSinkClass * xvimagesinkclass)
{
xvimagesink->display_name = NULL;
xvimagesink->adaptor_no = 0;
xvimagesink->draw_borders = TRUE;
#ifdef GST_EXT_XV_ENHANCEMENT
- xvimagesink->display_mode = VIDEO_MODE_LCDONLY;
+ xvimagesink->display_mode = DISPLAY_MODE_DEFAULT;
xvimagesink->rotate_changed = TRUE;
xvimagesink->display_geometry_method = DEF_DISPLAY_GEOMETRY_METHOD;
xvimagesink->rotate_angle = DEGREE_270;
xvimagesink->aligned_height = 0;
xvimagesink->stop_video = FALSE;
xvimagesink->is_hided = FALSE;
-#endif
+#endif /* GST_EXT_XV_ENHANCEMENT */
}
static void
"Video sink", "Sink/Video",
"A Xv based videosink", "Julien Moutte <julien@moutte.net>");
- gst_element_class_add_pad_template (element_class,
- gst_static_pad_template_get (&gst_xvimagesink_sink_template_factory));
+ gst_element_class_add_static_pad_template (element_class,
+ &gst_xvimagesink_sink_template_factory);
}
static void
gstbasesink_class = (GstBaseSinkClass *) klass;
videosink_class = (GstVideoSinkClass *) klass;
- parent_class = g_type_class_peek_parent (klass);
-
gobject_class->set_property = gst_xvimagesink_set_property;
gobject_class->get_property = gst_xvimagesink_get_property;
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
g_object_class_install_property (gobject_class, PROP_SYNCHRONOUS,
g_param_spec_boolean ("synchronous", "Synchronous",
- "When enabled, runs "
- "the X display in synchronous mode. (used only for debugging)", FALSE,
+ "When enabled, runs the X display in synchronous mode. "
+ "(unrelated to A/V sync, used only for debugging)", FALSE,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
g_object_class_install_property (gobject_class, PROP_PIXEL_ASPECT_RATIO,
g_param_spec_string ("pixel-aspect-ratio", "Pixel Aspect Ratio",
g_object_class_install_property(gobject_class, PROP_DISPLAY_MODE,
g_param_spec_enum("display-mode", "Display Mode",
"Display device setting",
- GST_TYPE_XVIMAGESINK_DISPLAY_MODE, VIDEO_MODE_LCDONLY,
+ GST_TYPE_XVIMAGESINK_DISPLAY_MODE, DISPLAY_MODE_DEFAULT,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
/**
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));
-#endif
+#endif /* GST_EXT_XV_ENHANCEMENT */
gobject_class->finalize = gst_xvimagesink_finalize;
/* Object typing & Creation */
/* */
/* =========================================== */
-
-GType
-gst_xvimagesink_get_type (void)
+static void
+gst_xvimagesink_init_interfaces (GType type)
{
- static GType xvimagesink_type = 0;
-
- if (!xvimagesink_type) {
- static const GTypeInfo xvimagesink_info = {
- sizeof (GstXvImageSinkClass),
- gst_xvimagesink_base_init,
- NULL,
- (GClassInitFunc) gst_xvimagesink_class_init,
- NULL,
- NULL,
- sizeof (GstXvImageSink),
- 0,
- (GInstanceInitFunc) gst_xvimagesink_init,
- };
- static const GInterfaceInfo iface_info = {
- (GInterfaceInitFunc) gst_xvimagesink_interface_init,
- NULL,
- NULL,
- };
- static const GInterfaceInfo navigation_info = {
- (GInterfaceInitFunc) gst_xvimagesink_navigation_init,
- NULL,
- NULL,
- };
- static const GInterfaceInfo overlay_info = {
- (GInterfaceInitFunc) gst_xvimagesink_xoverlay_init,
- NULL,
- NULL,
- };
- static const GInterfaceInfo colorbalance_info = {
- (GInterfaceInitFunc) gst_xvimagesink_colorbalance_init,
- NULL,
- NULL,
- };
- static const GInterfaceInfo propertyprobe_info = {
- (GInterfaceInitFunc) gst_xvimagesink_property_probe_interface_init,
- NULL,
- NULL,
- };
- xvimagesink_type = g_type_register_static (GST_TYPE_VIDEO_SINK,
- "GstXvImageSink", &xvimagesink_info, 0);
-
- g_type_add_interface_static (xvimagesink_type,
- GST_TYPE_IMPLEMENTS_INTERFACE, &iface_info);
- g_type_add_interface_static (xvimagesink_type, GST_TYPE_NAVIGATION,
- &navigation_info);
- g_type_add_interface_static (xvimagesink_type, GST_TYPE_X_OVERLAY,
- &overlay_info);
- g_type_add_interface_static (xvimagesink_type, GST_TYPE_COLOR_BALANCE,
- &colorbalance_info);
- g_type_add_interface_static (xvimagesink_type, GST_TYPE_PROPERTY_PROBE,
- &propertyprobe_info);
-
-
- /* register type and create class in a more safe place instead of at
- * runtime since the type registration and class creation is not
- * threadsafe. */
- g_type_class_ref (gst_xvimage_buffer_get_type ());
- }
+ static const GInterfaceInfo iface_info = {
+ (GInterfaceInitFunc) gst_xvimagesink_interface_init,
+ NULL,
+ NULL,
+ };
+ static const GInterfaceInfo navigation_info = {
+ (GInterfaceInitFunc) gst_xvimagesink_navigation_init,
+ NULL,
+ NULL,
+ };
+ static const GInterfaceInfo overlay_info = {
+ (GInterfaceInitFunc) gst_xvimagesink_xoverlay_init,
+ NULL,
+ NULL,
+ };
+ static const GInterfaceInfo colorbalance_info = {
+ (GInterfaceInitFunc) gst_xvimagesink_colorbalance_init,
+ NULL,
+ NULL,
+ };
+ static const GInterfaceInfo propertyprobe_info = {
+ (GInterfaceInitFunc) gst_xvimagesink_property_probe_interface_init,
+ NULL,
+ NULL,
+ };
- return xvimagesink_type;
+ g_type_add_interface_static (type,
+ GST_TYPE_IMPLEMENTS_INTERFACE, &iface_info);
+ g_type_add_interface_static (type, GST_TYPE_NAVIGATION, &navigation_info);
+ g_type_add_interface_static (type, GST_TYPE_X_OVERLAY, &overlay_info);
+ g_type_add_interface_static (type, GST_TYPE_COLOR_BALANCE,
+ &colorbalance_info);
+ g_type_add_interface_static (type, GST_TYPE_PROPERTY_PROBE,
+ &propertyprobe_info);
+
+ /* register type and create class in a more safe place instead of at
+ * runtime since the type registration and class creation is not
+ * threadsafe. */
+ g_type_class_ref (gst_xvimage_buffer_get_type ());
}
static gboolean