{
g_return_if_fail (xvimage != NULL);
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)
if (!ret)
return GST_PAD_LINK_REFUSED;
+ g_mutex_lock (xvimagesink->stream_lock);
+
xvimagesink->video_width = video_width;
xvimagesink->video_height = video_height;
if (!gst_structure_get_fourcc (structure, "format", &im_format)) {
gst_caps_copy (caps));
}
if (im_format == 0) {
+ g_mutex_unlock (xvimagesink->stream_lock);
return GST_PAD_LINK_REFUSED;
}
xvimagesink->xcontext->im_format = im_format;
+ g_mutex_unlock (xvimagesink->stream_lock);
+
gst_x_overlay_got_desired_size (GST_X_OVERLAY (xvimagesink),
GST_VIDEOSINK_WIDTH (xvimagesink), GST_VIDEOSINK_HEIGHT (xvimagesink));
/* call XSynchronize with the current value of synchronous */
GST_DEBUG_OBJECT (xvimagesink, "XSynchronize called with %s",
xvimagesink->synchronous ? "TRUE" : "FALSE");
+ g_mutex_lock (xvimagesink->x_lock);
XSynchronize (xvimagesink->xcontext->disp, xvimagesink->synchronous);
+ g_mutex_unlock (xvimagesink->x_lock);
gst_xvimagesink_update_colorbalance (xvimagesink);
break;
case GST_STATE_READY_TO_PAUSED:
case GST_STATE_PLAYING_TO_PAUSED:
break;
case GST_STATE_PAUSED_TO_READY:
+ g_mutex_lock (xvimagesink->stream_lock);
if (xvimagesink->xwindow)
gst_xvimagesink_xwindow_clear (xvimagesink, xvimagesink->xwindow);
xvimagesink->framerate = 0;
GST_VIDEOSINK_WIDTH (xvimagesink) = 0;
GST_VIDEOSINK_HEIGHT (xvimagesink) = 0;
+ g_mutex_unlock (xvimagesink->stream_lock);
break;
case GST_STATE_READY_TO_NULL:
+ /* We are cleaning our resources here, yes i know chain is not running
+ but the interface can be called to set a window from a different thread
+ and that would crash */
+ g_mutex_lock (xvimagesink->stream_lock);
if (xvimagesink->xvimage) {
gst_xvimagesink_xvimage_destroy (xvimagesink, xvimagesink->xvimage);
xvimagesink->xvimage = NULL;
gst_xvimagesink_xcontext_clear (xvimagesink);
xvimagesink->xcontext = NULL;
}
+ g_mutex_unlock (xvimagesink->stream_lock);
break;
}
return;
}
+ g_mutex_lock (xvimagesink->stream_lock);
+
buf = GST_BUFFER (data);
/* update time */
if (GST_BUFFER_TIMESTAMP_IS_VALID (buf)) {
gst_buffer_unref (buf);
GST_ELEMENT_ERROR (xvimagesink, CORE, NEGOTIATION, (NULL),
("Failed creating an XvImage in xvimagesink chain function."));
+ g_mutex_unlock (xvimagesink->stream_lock);
return;
}
}
gst_buffer_unref (buf);
gst_xvimagesink_handle_xevents (xvimagesink, pad);
+
+ g_mutex_unlock (xvimagesink->stream_lock);
}
/* Buffer management */
xvimagesink = xvimage->xvimagesink;
/* If our geometry changed we can't reuse that image. */
- if ((xvimage->width != GST_VIDEOSINK_WIDTH (xvimagesink)) ||
- (xvimage->height != GST_VIDEOSINK_HEIGHT (xvimagesink)))
+ if ((xvimage->width != xvimagesink->video_width) ||
+ (xvimage->height != xvimagesink->video_height))
gst_xvimagesink_xvimage_destroy (xvimagesink, xvimage);
else {
/* In that case we can reuse the image and add it to our image pool. */
xvimagesink->image_pool);
/* We check for geometry or image format changes */
- if ((xvimage->width != GST_VIDEOSINK_WIDTH (xvimagesink)) ||
- (xvimage->height != GST_VIDEOSINK_HEIGHT (xvimagesink)) ||
+ if ((xvimage->width != xvimagesink->video_width) ||
+ (xvimage->height != xvimagesink->video_height) ||
(xvimage->im_format != xvimagesink->xcontext->im_format)) {
/* This image is unusable. Destroying... */
gst_xvimagesink_xvimage_destroy (xvimagesink, xvimage);
gst_xvimagesink_update_colorbalance (xvimagesink);
+ /* We acquire the stream lock while setting this window in the element.
+ We are basically cleaning tons of stuff replacing the old window, putting
+ images while we do that would surely crash */
+ g_mutex_lock (xvimagesink->stream_lock);
+
/* Clear image pool as the images are unusable anyway */
gst_xvimagesink_imagepool_clear (xvimagesink);
if (xwindow)
xvimagesink->xwindow = xwindow;
+
+ g_mutex_unlock (xvimagesink->stream_lock);
}
static void
if (!xvimagesink->xwindow)
return;
+ /* We don't want chain to iterate while we do that. We might act on random
+ cur_image and different geometry */
+ g_mutex_lock (xvimagesink->stream_lock);
+
/* Update the window geometry */
g_mutex_lock (xvimagesink->x_lock);
XGetWindowAttributes (xvimagesink->xcontext->disp,
if (xvimagesink->cur_image) {
gst_xvimagesink_xvimage_put (xvimagesink, xvimagesink->cur_image);
}
+
+ g_mutex_unlock (xvimagesink->stream_lock);
}
static void
case ARG_SYNCHRONOUS:
xvimagesink->synchronous = g_value_get_boolean (value);
if (xvimagesink->xcontext) {
+ g_mutex_lock (xvimagesink->x_lock);
XSynchronize (xvimagesink->xcontext->disp, xvimagesink->synchronous);
GST_DEBUG_OBJECT (xvimagesink, "XSynchronize called with %s",
xvimagesink->synchronous ? "TRUE" : "FALSE");
+ g_mutex_unlock (xvimagesink->x_lock);
}
break;
case ARG_PIXEL_ASPECT_RATIO:
g_mutex_free (xvimagesink->x_lock);
xvimagesink->x_lock = NULL;
}
+ if (xvimagesink->stream_lock) {
+ g_mutex_free (xvimagesink->stream_lock);
+ xvimagesink->stream_lock = NULL;
+ }
if (xvimagesink->pool_lock) {
g_mutex_free (xvimagesink->pool_lock);
xvimagesink->pool_lock = NULL;
xvimagesink->video_height = 0;
xvimagesink->x_lock = g_mutex_new ();
+ xvimagesink->stream_lock = g_mutex_new ();
xvimagesink->image_pool = NULL;
xvimagesink->pool_lock = g_mutex_new ();