mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-01-24 08:08:22 +00:00
sys/ximage/ximagesink.c: Add debug macros on functions.
Original commit message from CVS: 2005-11-22 Julien MOUTTE <julien@moutte.net> * sys/ximage/ximagesink.c: (gst_ximagesink_event_thread), (gst_ximagesink_class_init): Add debug macros on functions. * sys/xvimage/xvimagesink.c: (gst_xvimagesink_xvimage_new), (gst_xvimagesink_xwindow_draw_borders), (gst_xvimagesink_xvimage_put), (gst_xvimagesink_xwindow_update_geometry), (gst_xvimagesink_handle_xevents), (gst_xvimagesink_get_xv_support), (gst_xvimagesink_event_thread), (gst_xvimagesink_xcontext_get), (gst_xvimagesink_xcontext_clear), (gst_xvimagesink_get_format_from_caps), (gst_xvimagesink_setcaps), (gst_xvimagesink_change_state), (gst_xvimagesink_show_frame), (gst_xvimagesink_buffer_alloc), (gst_xvimagesink_set_xwindow_id), (gst_xvimagesink_expose), (gst_xvimagesink_set_property), (gst_xvimagesink_get_property), (gst_xvimagesink_finalize), (gst_xvimagesink_init), (gst_xvimagesink_class_init): * sys/xvimage/xvimagesink.h: Refactoring to handle aspect ratio, expose while being PAUSED, out of data flow navigation events, etc..
This commit is contained in:
parent
1c3b6d42a9
commit
cc3190e666
4 changed files with 243 additions and 185 deletions
20
ChangeLog
20
ChangeLog
|
@ -1,3 +1,23 @@
|
|||
2005-11-22 Julien MOUTTE <julien@moutte.net>
|
||||
|
||||
* sys/ximage/ximagesink.c: (gst_ximagesink_event_thread),
|
||||
(gst_ximagesink_class_init): Add debug macros on functions.
|
||||
* sys/xvimage/xvimagesink.c: (gst_xvimagesink_xvimage_new),
|
||||
(gst_xvimagesink_xwindow_draw_borders),
|
||||
(gst_xvimagesink_xvimage_put),
|
||||
(gst_xvimagesink_xwindow_update_geometry),
|
||||
(gst_xvimagesink_handle_xevents), (gst_xvimagesink_get_xv_support),
|
||||
(gst_xvimagesink_event_thread), (gst_xvimagesink_xcontext_get),
|
||||
(gst_xvimagesink_xcontext_clear),
|
||||
(gst_xvimagesink_get_format_from_caps), (gst_xvimagesink_setcaps),
|
||||
(gst_xvimagesink_change_state), (gst_xvimagesink_show_frame),
|
||||
(gst_xvimagesink_buffer_alloc), (gst_xvimagesink_set_xwindow_id),
|
||||
(gst_xvimagesink_expose), (gst_xvimagesink_set_property),
|
||||
(gst_xvimagesink_get_property), (gst_xvimagesink_finalize),
|
||||
(gst_xvimagesink_init), (gst_xvimagesink_class_init):
|
||||
* sys/xvimage/xvimagesink.h: Refactoring to handle aspect ratio,
|
||||
expose while being PAUSED, out of data flow navigation events, etc..
|
||||
|
||||
2005-11-22 Thomas Vander Stichele <thomas at apestaart dot org>
|
||||
|
||||
* gst-libs/gst/audio/audio.c: (gst_audio_duration_from_pad_buffer):
|
||||
|
|
|
@ -792,7 +792,6 @@ gst_ximagesink_handle_xevents (GstXImageSink * ximagesink)
|
|||
static gpointer
|
||||
gst_ximagesink_event_thread (GstXImageSink * ximagesink)
|
||||
{
|
||||
|
||||
g_return_val_if_fail (GST_IS_XIMAGESINK (ximagesink), NULL);
|
||||
|
||||
while (ximagesink->running) {
|
||||
|
@ -1791,12 +1790,13 @@ gst_ximagesink_class_init (GstXImageSinkClass * klass)
|
|||
|
||||
gstelement_class->change_state = gst_ximagesink_change_state;
|
||||
|
||||
gstbasesink_class->get_caps = gst_ximagesink_getcaps;
|
||||
gstbasesink_class->set_caps = gst_ximagesink_setcaps;
|
||||
gstbasesink_class->buffer_alloc = gst_ximagesink_buffer_alloc;
|
||||
gstbasesink_class->get_times = gst_ximagesink_get_times;
|
||||
gstbasesink_class->preroll = gst_ximagesink_show_frame;
|
||||
gstbasesink_class->render = gst_ximagesink_show_frame;
|
||||
gstbasesink_class->get_caps = GST_DEBUG_FUNCPTR (gst_ximagesink_getcaps);
|
||||
gstbasesink_class->set_caps = GST_DEBUG_FUNCPTR (gst_ximagesink_setcaps);
|
||||
gstbasesink_class->buffer_alloc =
|
||||
GST_DEBUG_FUNCPTR (gst_ximagesink_buffer_alloc);
|
||||
gstbasesink_class->get_times = GST_DEBUG_FUNCPTR (gst_ximagesink_get_times);
|
||||
gstbasesink_class->preroll = GST_DEBUG_FUNCPTR (gst_ximagesink_show_frame);
|
||||
gstbasesink_class->render = GST_DEBUG_FUNCPTR (gst_ximagesink_show_frame);
|
||||
}
|
||||
|
||||
/* ============================================================= */
|
||||
|
|
|
@ -48,6 +48,12 @@ MotifWmHints, MwmHints;
|
|||
|
||||
static void gst_xvimage_buffer_finalize (GstXvImageBuffer * xvimage);
|
||||
|
||||
static void gst_xvimagesink_xwindow_update_geometry (GstXvImageSink *
|
||||
xvimagesink, GstXWindow * xwindow);
|
||||
static gint gst_xvimagesink_get_format_from_caps (GstXvImageSink * xvimagesink,
|
||||
GstCaps * caps);
|
||||
static void gst_xvimagesink_expose (GstXOverlay * overlay);
|
||||
|
||||
//static void gst_xvimagesink_send_pending_navigation (GstXvImageSink * xvimagesink);
|
||||
|
||||
/* ElementFactory information */
|
||||
|
@ -81,7 +87,8 @@ enum
|
|||
ARG_SATURATION,
|
||||
ARG_DISPLAY,
|
||||
ARG_SYNCHRONOUS,
|
||||
ARG_PIXEL_ASPECT_RATIO
|
||||
ARG_PIXEL_ASPECT_RATIO,
|
||||
ARG_FORCE_ASPECT_RATIO
|
||||
/* FILL ME */
|
||||
};
|
||||
|
||||
|
@ -328,20 +335,33 @@ beach:
|
|||
|
||||
/* This function handles GstXvImage creation depending on XShm availability */
|
||||
static GstXvImageBuffer *
|
||||
gst_xvimagesink_xvimage_new (GstXvImageSink * xvimagesink,
|
||||
gint width, gint height)
|
||||
gst_xvimagesink_xvimage_new (GstXvImageSink * xvimagesink, GstCaps * caps)
|
||||
{
|
||||
GstXvImageBuffer *xvimage = NULL;
|
||||
GstStructure *structure = NULL;
|
||||
gboolean succeeded = FALSE;
|
||||
|
||||
g_return_val_if_fail (GST_IS_XVIMAGESINK (xvimagesink), NULL);
|
||||
GST_LOG_OBJECT (xvimagesink, "creating %dx%d", width, height);
|
||||
|
||||
|
||||
xvimage = (GstXvImageBuffer *) gst_mini_object_new (GST_TYPE_XVIMAGE_BUFFER);
|
||||
|
||||
xvimage->width = width;
|
||||
xvimage->height = height;
|
||||
xvimage->im_format = xvimagesink->xcontext->im_format;
|
||||
structure = gst_caps_get_structure (caps, 0);
|
||||
|
||||
if (!gst_structure_get_int (structure, "width", &xvimage->width) ||
|
||||
!gst_structure_get_int (structure, "height", &xvimage->height)) {
|
||||
GST_WARNING ("failed getting geometry from caps %" GST_PTR_FORMAT, caps);
|
||||
}
|
||||
|
||||
GST_LOG_OBJECT (xvimagesink, "creating %dx%d", xvimage->width,
|
||||
xvimage->height);
|
||||
|
||||
/* We should probably get that from the caps as well */
|
||||
xvimage->im_format = gst_xvimagesink_get_format_from_caps (xvimagesink, caps);
|
||||
if (!xvimage->im_format) {
|
||||
GST_WARNING_OBJECT (xvimagesink, "failed to get format from caps %"
|
||||
GST_PTR_FORMAT, caps);
|
||||
}
|
||||
xvimage->xvimagesink = gst_object_ref (xvimagesink);
|
||||
|
||||
g_mutex_lock (xvimagesink->x_lock);
|
||||
|
@ -421,21 +441,89 @@ beach:
|
|||
return xvimage;
|
||||
}
|
||||
|
||||
/* We are called with the x_lock taken */
|
||||
static void
|
||||
gst_xvimagesink_xwindow_draw_borders (GstXvImageSink * xvimagesink,
|
||||
GstXWindow * xwindow, GstVideoRectangle rect)
|
||||
{
|
||||
g_return_if_fail (GST_IS_XVIMAGESINK (xvimagesink));
|
||||
g_return_if_fail (xwindow != NULL);
|
||||
|
||||
XSetForeground (xvimagesink->xcontext->disp, xwindow->gc,
|
||||
xvimagesink->xcontext->black);
|
||||
|
||||
/* Left border */
|
||||
if (rect.x > 0) {
|
||||
XFillRectangle (xvimagesink->xcontext->disp, xwindow->win, xwindow->gc,
|
||||
0, 0, rect.x, xwindow->height);
|
||||
}
|
||||
|
||||
/* Right border */
|
||||
if ((rect.x + rect.w) < xwindow->width) {
|
||||
XFillRectangle (xvimagesink->xcontext->disp, xwindow->win, xwindow->gc,
|
||||
rect.x + rect.w, 0, xwindow->width, xwindow->height);
|
||||
}
|
||||
|
||||
/* Top border */
|
||||
if (rect.y > 0) {
|
||||
XFillRectangle (xvimagesink->xcontext->disp, xwindow->win, xwindow->gc,
|
||||
0, 0, xwindow->width, rect.y);
|
||||
}
|
||||
|
||||
/* Bottom border */
|
||||
if ((rect.y + rect.h) < xwindow->height) {
|
||||
XFillRectangle (xvimagesink->xcontext->disp, xwindow->win, xwindow->gc,
|
||||
0, rect.y + rect.h, xwindow->width, xwindow->height);
|
||||
}
|
||||
}
|
||||
|
||||
/* This function puts a GstXvImage on a GstXvImageSink's window */
|
||||
static void
|
||||
gst_xvimagesink_xvimage_put (GstXvImageSink * xvimagesink,
|
||||
GstXvImageBuffer * xvimage)
|
||||
{
|
||||
g_return_if_fail (xvimage != NULL);
|
||||
GstVideoRectangle src, dst, result;
|
||||
|
||||
g_return_if_fail (GST_IS_XVIMAGESINK (xvimagesink));
|
||||
g_return_if_fail (xvimagesink->xwindow != NULL);
|
||||
|
||||
/* Store a reference to the last image we put */
|
||||
if (xvimagesink->cur_image != xvimage)
|
||||
xvimagesink->cur_image = xvimage;
|
||||
if (!xvimage) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* We take the flow_lock. If expose is in there we don't want to run
|
||||
concurrently from the data flow thread */
|
||||
g_mutex_lock (xvimagesink->flow_lock);
|
||||
|
||||
/* Store a reference to the last image we put, loose the previous one */
|
||||
if (xvimagesink->cur_image != xvimage) {
|
||||
if (xvimagesink->cur_image) {
|
||||
GST_DEBUG_OBJECT (xvimagesink, "unreffing %p", xvimagesink->cur_image);
|
||||
gst_buffer_unref (xvimagesink->cur_image);
|
||||
}
|
||||
xvimagesink->cur_image = GST_XVIMAGE_BUFFER (gst_buffer_ref (xvimage));
|
||||
}
|
||||
|
||||
gst_xvimagesink_xwindow_update_geometry (xvimagesink, xvimagesink->xwindow);
|
||||
|
||||
src.w = xvimage->width;
|
||||
src.h = xvimage->height;
|
||||
dst.w = xvimagesink->xwindow->width;
|
||||
dst.h = xvimagesink->xwindow->height;
|
||||
|
||||
if (xvimagesink->keep_aspect) {
|
||||
gst_video_sink_center_rect (src, dst, &result, TRUE);
|
||||
} else {
|
||||
result.x = result.y = 0;
|
||||
result.w = dst.w;
|
||||
result.h = dst.h;
|
||||
}
|
||||
|
||||
g_mutex_lock (xvimagesink->x_lock);
|
||||
|
||||
gst_xvimagesink_xwindow_draw_borders (xvimagesink, xvimagesink->xwindow,
|
||||
result);
|
||||
|
||||
/* We scale to the window's geometry */
|
||||
#ifdef HAVE_XSHM
|
||||
if (xvimagesink->xcontext->use_xshm) {
|
||||
|
@ -448,7 +536,7 @@ gst_xvimagesink_xvimage_put (GstXvImageSink * xvimagesink,
|
|||
xvimagesink->xwindow->win,
|
||||
xvimagesink->xwindow->gc, xvimage->xvimage,
|
||||
0, 0, xvimage->width, xvimage->height,
|
||||
0, 0, xvimagesink->xwindow->width, xvimagesink->xwindow->height, FALSE);
|
||||
result.x, result.y, result.w, result.h, FALSE);
|
||||
} else
|
||||
#endif /* HAVE_XSHM */
|
||||
{
|
||||
|
@ -457,12 +545,14 @@ gst_xvimagesink_xvimage_put (GstXvImageSink * xvimagesink,
|
|||
xvimagesink->xwindow->win,
|
||||
xvimagesink->xwindow->gc, xvimage->xvimage,
|
||||
0, 0, xvimage->width, xvimage->height,
|
||||
0, 0, xvimagesink->xwindow->width, xvimagesink->xwindow->height);
|
||||
result.x, result.y, result.w, result.h);
|
||||
}
|
||||
|
||||
XSync (xvimagesink->xcontext->disp, FALSE);
|
||||
|
||||
g_mutex_unlock (xvimagesink->x_lock);
|
||||
|
||||
g_mutex_unlock (xvimagesink->flow_lock);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
|
@ -574,24 +664,23 @@ gst_xvimagesink_xwindow_destroy (GstXvImageSink * xvimagesink,
|
|||
g_free (xwindow);
|
||||
}
|
||||
|
||||
/* This function resizes a GstXWindow.
|
||||
* The width and height are the actual pixel size on the display. */
|
||||
static void
|
||||
gst_xvimagesink_xwindow_resize (GstXvImageSink * xvimagesink,
|
||||
GstXWindow * xwindow, guint width, guint height)
|
||||
gst_xvimagesink_xwindow_update_geometry (GstXvImageSink * xvimagesink,
|
||||
GstXWindow * xwindow)
|
||||
{
|
||||
XWindowAttributes attr;
|
||||
|
||||
g_return_if_fail (xwindow != NULL);
|
||||
g_return_if_fail (GST_IS_XVIMAGESINK (xvimagesink));
|
||||
|
||||
/* Update the window geometry */
|
||||
g_mutex_lock (xvimagesink->x_lock);
|
||||
|
||||
xwindow->width = width;
|
||||
xwindow->height = height;
|
||||
XGetWindowAttributes (xvimagesink->xcontext->disp,
|
||||
xvimagesink->xwindow->win, &attr);
|
||||
|
||||
XResizeWindow (xvimagesink->xcontext->disp, xwindow->win,
|
||||
xwindow->width, xwindow->height);
|
||||
|
||||
XSync (xvimagesink->xcontext->disp, FALSE);
|
||||
xvimagesink->xwindow->width = attr.width;
|
||||
xvimagesink->xwindow->height = attr.height;
|
||||
|
||||
g_mutex_unlock (xvimagesink->x_lock);
|
||||
}
|
||||
|
@ -684,7 +773,7 @@ gst_xvimagesink_update_colorbalance (GstXvImageSink * xvimagesink)
|
|||
and navigation. It will also listen for configure events on the window to
|
||||
trigger caps renegotiation so on the fly software scaling can work. */
|
||||
static void
|
||||
gst_xvimagesink_handle_xevents (GstXvImageSink * xvimagesink, GstPad * pad)
|
||||
gst_xvimagesink_handle_xevents (GstXvImageSink * xvimagesink)
|
||||
{
|
||||
XEvent e;
|
||||
guint pointer_x = 0, pointer_y = 0;
|
||||
|
@ -724,22 +813,14 @@ gst_xvimagesink_handle_xevents (GstXvImageSink * xvimagesink, GstPad * pad)
|
|||
g_mutex_lock (xvimagesink->x_lock);
|
||||
while (XCheckWindowEvent (xvimagesink->xcontext->disp,
|
||||
xvimagesink->xwindow->win,
|
||||
StructureNotifyMask | KeyPressMask |
|
||||
KeyReleaseMask | ButtonPressMask | ButtonReleaseMask, &e)) {
|
||||
KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask,
|
||||
&e)) {
|
||||
KeySym keysym;
|
||||
|
||||
/* We lock only for the X function call */
|
||||
g_mutex_unlock (xvimagesink->x_lock);
|
||||
|
||||
switch (e.type) {
|
||||
case ConfigureNotify:
|
||||
/* Window got resized or moved. We update our data. */
|
||||
GST_DEBUG ("xvimagesink window is at %d, %d with geometry : %d,%d",
|
||||
e.xconfigure.x, e.xconfigure.y,
|
||||
e.xconfigure.width, e.xconfigure.height);
|
||||
xvimagesink->xwindow->width = e.xconfigure.width;
|
||||
xvimagesink->xwindow->height = e.xconfigure.height;
|
||||
break;
|
||||
case ButtonPress:
|
||||
/* Mouse button pressed over our window. We send upstream
|
||||
events for interactivity/navigation */
|
||||
|
@ -780,6 +861,35 @@ gst_xvimagesink_handle_xevents (GstXvImageSink * xvimagesink, GstPad * pad)
|
|||
g_mutex_lock (xvimagesink->x_lock);
|
||||
}
|
||||
g_mutex_unlock (xvimagesink->x_lock);
|
||||
|
||||
/* Handle Expose */
|
||||
{
|
||||
gboolean exposed = FALSE, configured = FALSE;
|
||||
|
||||
g_mutex_lock (xvimagesink->x_lock);
|
||||
while (XCheckWindowEvent (xvimagesink->xcontext->disp,
|
||||
xvimagesink->xwindow->win, ExposureMask | StructureNotifyMask,
|
||||
&e)) {
|
||||
g_mutex_unlock (xvimagesink->x_lock);
|
||||
|
||||
switch (e.type) {
|
||||
case Expose:
|
||||
exposed = TRUE;
|
||||
break;
|
||||
case ConfigureNotify:
|
||||
configured = TRUE;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
g_mutex_lock (xvimagesink->x_lock);
|
||||
}
|
||||
g_mutex_unlock (xvimagesink->x_lock);
|
||||
|
||||
if (exposed || configured) {
|
||||
gst_xvimagesink_expose (GST_X_OVERLAY (xvimagesink));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* This function generates a caps with all supported format by the first
|
||||
|
@ -889,22 +999,6 @@ gst_xvimagesink_get_xv_support (GstXvImageSink * xvimagesink,
|
|||
"width", GST_TYPE_INT_RANGE, 1, G_MAXINT,
|
||||
"height", GST_TYPE_INT_RANGE, 1, G_MAXINT,
|
||||
"framerate", GST_TYPE_DOUBLE_RANGE, 0.0, G_MAXDOUBLE, NULL);
|
||||
|
||||
/* For RGB caps we store them and the image
|
||||
format so that we can get back the format
|
||||
when sinkconnect will give us a caps without
|
||||
format property */
|
||||
if (format_caps) {
|
||||
GstXvImageFormat *format = NULL;
|
||||
|
||||
format = g_new0 (GstXvImageFormat, 1);
|
||||
if (format) {
|
||||
format->format = formats[i].id;
|
||||
format->caps = gst_caps_copy (format_caps);
|
||||
xcontext->formats_list =
|
||||
g_list_append (xcontext->formats_list, format);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case XvYUV:
|
||||
|
@ -919,6 +1013,17 @@ gst_xvimagesink_get_xv_support (GstXvImageSink * xvimagesink,
|
|||
break;
|
||||
}
|
||||
|
||||
if (format_caps) {
|
||||
GstXvImageFormat *format = NULL;
|
||||
|
||||
format = g_new0 (GstXvImageFormat, 1);
|
||||
if (format) {
|
||||
format->format = formats[i].id;
|
||||
format->caps = gst_caps_copy (format_caps);
|
||||
xcontext->formats_list = g_list_append (xcontext->formats_list, format);
|
||||
}
|
||||
}
|
||||
|
||||
gst_caps_append (caps, format_caps);
|
||||
}
|
||||
|
||||
|
@ -938,6 +1043,21 @@ gst_xvimagesink_get_xv_support (GstXvImageSink * xvimagesink,
|
|||
return caps;
|
||||
}
|
||||
|
||||
static gpointer
|
||||
gst_xvimagesink_event_thread (GstXvImageSink * xvimagesink)
|
||||
{
|
||||
g_return_val_if_fail (GST_IS_XVIMAGESINK (xvimagesink), NULL);
|
||||
|
||||
while (xvimagesink->running) {
|
||||
if (xvimagesink->xwindow) {
|
||||
gst_xvimagesink_handle_xevents (xvimagesink);
|
||||
}
|
||||
g_usleep (50000);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* This function calculates the pixel aspect ratio based on the properties
|
||||
* in the xcontext structure and stores it there. */
|
||||
static void
|
||||
|
@ -1155,6 +1275,10 @@ gst_xvimagesink_xcontext_get (GstXvImageSink * xvimagesink)
|
|||
|
||||
g_mutex_unlock (xvimagesink->x_lock);
|
||||
|
||||
/* Setup our event listening thread */
|
||||
xvimagesink->event_thread = g_thread_create (
|
||||
(GThreadFunc) gst_xvimagesink_event_thread, xvimagesink, TRUE, NULL);
|
||||
|
||||
return xcontext;
|
||||
}
|
||||
|
||||
|
@ -1168,6 +1292,12 @@ gst_xvimagesink_xcontext_clear (GstXvImageSink * xvimagesink)
|
|||
g_return_if_fail (GST_IS_XVIMAGESINK (xvimagesink));
|
||||
g_return_if_fail (xvimagesink->xcontext != NULL);
|
||||
|
||||
/* Wait for our event thread */
|
||||
if (xvimagesink->event_thread) {
|
||||
g_thread_join (xvimagesink->event_thread);
|
||||
xvimagesink->event_thread = NULL;
|
||||
}
|
||||
|
||||
formats_list = xvimagesink->xcontext->formats_list;
|
||||
|
||||
while (formats_list) {
|
||||
|
@ -1227,38 +1357,10 @@ gst_xvimagesink_imagepool_clear (GstXvImageSink * xvimagesink)
|
|||
|
||||
/* Element stuff */
|
||||
|
||||
#if 0
|
||||
static GstCaps *
|
||||
gst_xvimagesink_fixate (GstPad * pad, const GstCaps * caps)
|
||||
{
|
||||
GstStructure *structure;
|
||||
GstCaps *newcaps;
|
||||
|
||||
if (gst_caps_get_size (caps) > 1)
|
||||
return NULL;
|
||||
|
||||
newcaps = gst_caps_copy (caps);
|
||||
structure = gst_caps_get_structure (newcaps, 0);
|
||||
|
||||
if (gst_structure_fixate_field_nearest_int (structure, "width", 320)) {
|
||||
return newcaps;
|
||||
}
|
||||
if (gst_structure_fixate_field_nearest_int (structure, "height", 240)) {
|
||||
return newcaps;
|
||||
}
|
||||
if (gst_structure_fixate_field_nearest_double (structure, "framerate", 30.0)) {
|
||||
return newcaps;
|
||||
}
|
||||
|
||||
gst_caps_unref (newcaps);
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* This function tries to get a format matching with a given caps in the
|
||||
supported list of formats we generated in gst_xvimagesink_get_xv_support */
|
||||
static gint
|
||||
gst_xvimagesink_get_fourcc_from_caps (GstXvImageSink * xvimagesink,
|
||||
gst_xvimagesink_get_format_from_caps (GstXvImageSink * xvimagesink,
|
||||
GstCaps * caps)
|
||||
{
|
||||
GList *list = NULL;
|
||||
|
@ -1274,9 +1376,11 @@ gst_xvimagesink_get_fourcc_from_caps (GstXvImageSink * xvimagesink,
|
|||
GstCaps *icaps = NULL;
|
||||
|
||||
icaps = gst_caps_intersect (caps, format->caps);
|
||||
if (!gst_caps_is_empty (icaps))
|
||||
if (!gst_caps_is_empty (icaps)) {
|
||||
gst_caps_unref (icaps);
|
||||
return format->format;
|
||||
}
|
||||
}
|
||||
list = g_list_next (list);
|
||||
}
|
||||
|
||||
|
@ -1338,11 +1442,7 @@ gst_xvimagesink_setcaps (GstBaseSink * bsink, GstCaps * caps)
|
|||
|
||||
xvimagesink->video_width = video_width;
|
||||
xvimagesink->video_height = video_height;
|
||||
if (!gst_structure_get_fourcc (structure, "format", &im_format)) {
|
||||
im_format =
|
||||
gst_xvimagesink_get_fourcc_from_caps (xvimagesink,
|
||||
gst_caps_copy (caps));
|
||||
}
|
||||
im_format = gst_xvimagesink_get_format_from_caps (xvimagesink, caps);
|
||||
if (im_format == 0) {
|
||||
return FALSE;
|
||||
}
|
||||
|
@ -1410,12 +1510,6 @@ gst_xvimagesink_setcaps (GstBaseSink * bsink, GstCaps * caps)
|
|||
xvimagesink->xwindow = gst_xvimagesink_xwindow_new (xvimagesink,
|
||||
GST_VIDEO_SINK_WIDTH (xvimagesink),
|
||||
GST_VIDEO_SINK_HEIGHT (xvimagesink));
|
||||
else {
|
||||
if (xvimagesink->xwindow->internal)
|
||||
gst_xvimagesink_xwindow_resize (xvimagesink, xvimagesink->xwindow,
|
||||
GST_VIDEO_SINK_WIDTH (xvimagesink),
|
||||
GST_VIDEO_SINK_HEIGHT (xvimagesink));
|
||||
}
|
||||
|
||||
/* We renew our xvimage only if size or format changed;
|
||||
* the xvimage is the same size as the video pixel size */
|
||||
|
@ -1447,6 +1541,7 @@ gst_xvimagesink_change_state (GstElement * element, GstStateChange transition)
|
|||
|
||||
switch (transition) {
|
||||
case GST_STATE_CHANGE_NULL_TO_READY:
|
||||
xvimagesink->running = TRUE;
|
||||
/* Initializing the XContext */
|
||||
if (!xvimagesink->xcontext &&
|
||||
!(xvimagesink->xcontext = gst_xvimagesink_xcontext_get (xvimagesink)))
|
||||
|
@ -1486,6 +1581,7 @@ gst_xvimagesink_change_state (GstElement * element, GstStateChange transition)
|
|||
GST_VIDEO_SINK_HEIGHT (xvimagesink) = 0;
|
||||
break;
|
||||
case GST_STATE_CHANGE_READY_TO_NULL:
|
||||
xvimagesink->running = FALSE;
|
||||
if (xvimagesink->xvimage) {
|
||||
gst_xvimage_buffer_free (xvimagesink->xvimage);
|
||||
xvimagesink->xvimage = NULL;
|
||||
|
@ -1551,7 +1647,7 @@ gst_xvimagesink_show_frame (GstBaseSink * bsink, GstBuffer * buf)
|
|||
GST_DEBUG_OBJECT (xvimagesink, "creating our xvimage");
|
||||
|
||||
xvimagesink->xvimage = gst_xvimagesink_xvimage_new (xvimagesink,
|
||||
xvimagesink->video_width, xvimagesink->video_height);
|
||||
GST_BUFFER_CAPS (buf));
|
||||
|
||||
if (!xvimagesink->xvimage)
|
||||
goto no_image;
|
||||
|
@ -1564,9 +1660,6 @@ gst_xvimagesink_show_frame (GstBaseSink * bsink, GstBuffer * buf)
|
|||
gst_xvimagesink_xvimage_put (xvimagesink, xvimagesink->xvimage);
|
||||
}
|
||||
|
||||
gst_xvimagesink_handle_xevents (xvimagesink,
|
||||
GST_VIDEO_SINK_PAD (xvimagesink));
|
||||
|
||||
return GST_FLOW_OK;
|
||||
|
||||
/* ERRORS */
|
||||
|
@ -1582,13 +1675,6 @@ no_image:
|
|||
|
||||
/* Buffer management */
|
||||
|
||||
#if 0
|
||||
static void
|
||||
gst_xvimagesink_buffer_free (GstBuffer * buffer)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
static GstFlowReturn
|
||||
gst_xvimagesink_buffer_alloc (GstBaseSink * bsink, guint64 offset, guint size,
|
||||
GstCaps * caps, GstBuffer ** buf)
|
||||
|
@ -1598,14 +1684,6 @@ gst_xvimagesink_buffer_alloc (GstBaseSink * bsink, guint64 offset, guint size,
|
|||
|
||||
xvimagesink = GST_XVIMAGESINK (bsink);
|
||||
|
||||
/* FIXME, we should just parse the caps, and provide a buffer in this format,
|
||||
* we should not just reconfigure ourselves yet */
|
||||
if (caps && caps != GST_PAD_CAPS (GST_VIDEO_SINK_PAD (xvimagesink))) {
|
||||
if (!gst_xvimagesink_setcaps (bsink, caps)) {
|
||||
return GST_FLOW_NOT_NEGOTIATED;
|
||||
}
|
||||
}
|
||||
|
||||
g_mutex_lock (xvimagesink->pool_lock);
|
||||
|
||||
/* Walking through the pool cleaning unusable images and searching for a
|
||||
|
@ -1638,8 +1716,7 @@ gst_xvimagesink_buffer_alloc (GstBaseSink * bsink, guint64 offset, guint size,
|
|||
if (!xvimage) {
|
||||
/* We found no suitable image in the pool. Creating... */
|
||||
GST_DEBUG_OBJECT (xvimagesink, "no usable image in pool, creating xvimage");
|
||||
xvimage = gst_xvimagesink_xvimage_new (xvimagesink,
|
||||
xvimagesink->video_width, xvimagesink->video_height);
|
||||
xvimage = gst_xvimagesink_xvimage_new (xvimagesink, caps);
|
||||
}
|
||||
if (xvimage) {
|
||||
gst_buffer_set_caps (GST_BUFFER (xvimage), caps);
|
||||
|
@ -1665,58 +1742,6 @@ gst_xvimagesink_interface_init (GstImplementsInterfaceClass * klass)
|
|||
klass->supported = gst_xvimagesink_interface_supported;
|
||||
}
|
||||
|
||||
#if 0
|
||||
/*
|
||||
* This function is called with the stream-lock held
|
||||
*/
|
||||
static void
|
||||
gst_xvimagesink_send_pending_navigation (GstXvImageSink * xvimagesink)
|
||||
{
|
||||
GSList *cur;
|
||||
GSList *pend_events;
|
||||
|
||||
g_mutex_lock (xvimagesink->nav_lock);
|
||||
pend_events = xvimagesink->pend_nav_events;
|
||||
xvimagesink->pend_nav_events = NULL;
|
||||
g_mutex_unlock (xvimagesink->nav_lock);
|
||||
|
||||
cur = pend_events;
|
||||
while (cur) {
|
||||
GstEvent *event = cur->data;
|
||||
GstStructure *structure;
|
||||
double x, y;
|
||||
|
||||
if (event) {
|
||||
structure = event->event_data.structure.structure;
|
||||
|
||||
if (!GST_PAD_PEER (GST_VIDEO_SINK_PAD (xvimagesink))) {
|
||||
gst_event_unref (event);
|
||||
cur = g_slist_next (cur);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Converting pointer coordinates to the non scaled geometry */
|
||||
if (gst_structure_get_double (structure, "pointer_x", &x)) {
|
||||
x *= xvimagesink->video_width;
|
||||
x /= xvimagesink->xwindow->width;
|
||||
gst_structure_set (structure, "pointer_x", G_TYPE_DOUBLE, x, NULL);
|
||||
}
|
||||
if (gst_structure_get_double (structure, "pointer_y", &y)) {
|
||||
y *= xvimagesink->video_height;
|
||||
y /= xvimagesink->xwindow->height;
|
||||
gst_structure_set (structure, "pointer_y", G_TYPE_DOUBLE, y, NULL);
|
||||
}
|
||||
|
||||
gst_pad_send_event (gst_pad_get_peer (GST_VIDEO_SINK_PAD (xvimagesink)),
|
||||
event);
|
||||
}
|
||||
cur = g_slist_next (cur);
|
||||
}
|
||||
|
||||
g_slist_free (pend_events);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
gst_xvimagesink_navigation_send_event (GstNavigation * navigation,
|
||||
GstStructure * structure)
|
||||
|
@ -1776,6 +1801,8 @@ gst_xvimagesink_set_xwindow_id (GstXOverlay * overlay, XID xwindow_id)
|
|||
/* we have thrown a GST_ELEMENT_ERROR now */
|
||||
return;
|
||||
|
||||
g_mutex_lock (xvimagesink->flow_lock);
|
||||
|
||||
gst_xvimagesink_update_colorbalance (xvimagesink);
|
||||
|
||||
/* Clear image pool as the images are unusable anyway */
|
||||
|
@ -1827,30 +1854,20 @@ gst_xvimagesink_set_xwindow_id (GstXOverlay * overlay, XID xwindow_id)
|
|||
|
||||
if (xwindow)
|
||||
xvimagesink->xwindow = xwindow;
|
||||
|
||||
g_mutex_unlock (xvimagesink->flow_lock);
|
||||
}
|
||||
|
||||
static void
|
||||
gst_xvimagesink_expose (GstXOverlay * overlay)
|
||||
{
|
||||
XWindowAttributes attr;
|
||||
GstXvImageSink *xvimagesink = GST_XVIMAGESINK (overlay);
|
||||
|
||||
if (!xvimagesink->xwindow)
|
||||
return;
|
||||
|
||||
/* Update the window geometry */
|
||||
g_mutex_lock (xvimagesink->x_lock);
|
||||
XGetWindowAttributes (xvimagesink->xcontext->disp,
|
||||
xvimagesink->xwindow->win, &attr);
|
||||
g_mutex_unlock (xvimagesink->x_lock);
|
||||
|
||||
xvimagesink->xwindow->width = attr.width;
|
||||
xvimagesink->xwindow->height = attr.height;
|
||||
|
||||
if (xvimagesink->cur_image) {
|
||||
gst_xvimagesink_xvimage_put (xvimagesink, xvimagesink->cur_image);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gst_xvimagesink_xoverlay_init (GstXOverlayClass * iface)
|
||||
|
@ -2001,6 +2018,9 @@ gst_xvimagesink_set_property (GObject * object, guint prop_id,
|
|||
gst_value_get_fraction_numerator (xvimagesink->par),
|
||||
gst_value_get_fraction_denominator (xvimagesink->par));
|
||||
break;
|
||||
case ARG_FORCE_ASPECT_RATIO:
|
||||
xvimagesink->keep_aspect = g_value_get_boolean (value);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
|
@ -2040,6 +2060,9 @@ gst_xvimagesink_get_property (GObject * object, guint prop_id,
|
|||
if (xvimagesink->par)
|
||||
g_value_transform (xvimagesink->par, value);
|
||||
break;
|
||||
case ARG_FORCE_ASPECT_RATIO:
|
||||
g_value_set_boolean (value, xvimagesink->keep_aspect);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
|
@ -2069,6 +2092,10 @@ gst_xvimagesink_finalize (GObject * object)
|
|||
g_mutex_free (xvimagesink->x_lock);
|
||||
xvimagesink->x_lock = NULL;
|
||||
}
|
||||
if (xvimagesink->flow_lock) {
|
||||
g_mutex_free (xvimagesink->flow_lock);
|
||||
xvimagesink->flow_lock = NULL;
|
||||
}
|
||||
if (xvimagesink->pool_lock) {
|
||||
g_mutex_free (xvimagesink->pool_lock);
|
||||
xvimagesink->pool_lock = NULL;
|
||||
|
@ -2095,11 +2122,14 @@ gst_xvimagesink_init (GstXvImageSink * xvimagesink)
|
|||
xvimagesink->video_height = 0;
|
||||
|
||||
xvimagesink->x_lock = g_mutex_new ();
|
||||
xvimagesink->flow_lock = g_mutex_new ();
|
||||
|
||||
xvimagesink->image_pool = NULL;
|
||||
xvimagesink->pool_lock = g_mutex_new ();
|
||||
|
||||
xvimagesink->synchronous = FALSE;
|
||||
xvimagesink->running = FALSE;
|
||||
xvimagesink->keep_aspect = FALSE;
|
||||
xvimagesink->par = NULL;
|
||||
}
|
||||
|
||||
|
@ -2153,13 +2183,16 @@ gst_xvimagesink_class_init (GstXvImageSinkClass * klass)
|
|||
g_object_class_install_property (gobject_class, ARG_PIXEL_ASPECT_RATIO,
|
||||
g_param_spec_string ("pixel-aspect-ratio", "Pixel Aspect Ratio",
|
||||
"The pixel aspect ratio of the device", "1/1", G_PARAM_READWRITE));
|
||||
g_object_class_install_property (gobject_class, ARG_FORCE_ASPECT_RATIO,
|
||||
g_param_spec_boolean ("force-aspect-ratio", "Force aspect ratio",
|
||||
"When enabled, scaling will respect original aspect ratio", FALSE,
|
||||
G_PARAM_READWRITE));
|
||||
|
||||
gobject_class->finalize = gst_xvimagesink_finalize;
|
||||
|
||||
gstelement_class->change_state =
|
||||
GST_DEBUG_FUNCPTR (gst_xvimagesink_change_state);
|
||||
|
||||
//gstbasesink_class->get_template = GST_DEBUG_FUNCPTR (gst_xvimagesink_get_template);
|
||||
gstbasesink_class->get_caps = GST_DEBUG_FUNCPTR (gst_xvimagesink_getcaps);
|
||||
gstbasesink_class->set_caps = GST_DEBUG_FUNCPTR (gst_xvimagesink_setcaps);
|
||||
gstbasesink_class->buffer_alloc =
|
||||
|
|
|
@ -145,6 +145,9 @@ struct _GstXvImageSink {
|
|||
gboolean cb_changed;
|
||||
|
||||
GMutex *x_lock;
|
||||
GMutex *flow_lock;
|
||||
|
||||
GThread *event_thread;
|
||||
|
||||
guint video_width, video_height; /* size of incoming video;
|
||||
* used as the size for XvImage */
|
||||
|
@ -154,6 +157,8 @@ struct _GstXvImageSink {
|
|||
GSList *image_pool;
|
||||
|
||||
gboolean synchronous;
|
||||
gboolean running;
|
||||
gboolean keep_aspect;
|
||||
};
|
||||
|
||||
struct _GstXvImageSinkClass {
|
||||
|
|
Loading…
Reference in a new issue