summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbenjamin gaignard <benjamin.gaignard@linaro.org>2011-04-06 12:26:47 +0200
committerWim Taymans <wim.taymans@collabora.co.uk>2011-04-06 12:28:46 +0200
commit15c49a4d6344a35463fa129de6a419699e89852f (patch)
tree15544e43b8a969eb2185400e2342586ad5041fcf
parent0f3fdf18e0f20cc281e62e5379a3b9e262ba2476 (diff)
xvimagesink: use bufferpool
Improve bufferpool handling in ximagesink. Implement bufferpool handling on xvimagesink. Based on patches from benjamin gaignard <benjamin.gaignard@linaro.org>
-rw-r--r--sys/ximage/ximage.c5
-rw-r--r--sys/ximage/ximagepool.c37
-rw-r--r--sys/ximage/ximagepool.h3
-rw-r--r--sys/ximage/ximagesink.c40
-rw-r--r--sys/ximage/ximagesink.h1
-rw-r--r--sys/xvimage/Makefile.am4
-rw-r--r--sys/xvimage/xvimage.c51
-rw-r--r--sys/xvimage/xvimagepool.c642
-rw-r--r--sys/xvimage/xvimagepool.h120
-rw-r--r--sys/xvimage/xvimagesink.c824
-rw-r--r--sys/xvimage/xvimagesink.h70
11 files changed, 1007 insertions, 790 deletions
diff --git a/sys/ximage/ximage.c b/sys/ximage/ximage.c
index 6e541fd4c..24a9e619e 100644
--- a/sys/ximage/ximage.c
+++ b/sys/ximage/ximage.c
@@ -17,8 +17,6 @@
* Boston, MA 02111-1307, USA.
*/
-
-
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
@@ -27,6 +25,7 @@
GST_DEBUG_CATEGORY (gst_debug_ximagepool);
GST_DEBUG_CATEGORY (gst_debug_ximagesink);
+GST_DEBUG_CATEGORY_STATIC (GST_CAT_PERFORMANCE);
static gboolean
plugin_init (GstPlugin * plugin)
@@ -40,6 +39,8 @@ plugin_init (GstPlugin * plugin)
GST_DEBUG_CATEGORY_INIT (gst_debug_ximagepool, "ximagepool", 0,
"ximagepool object");
+ GST_DEBUG_CATEGORY_GET (GST_CAT_PERFORMANCE, "GST_PERFORMANCE");
+
return TRUE;
}
diff --git a/sys/ximage/ximagepool.c b/sys/ximage/ximagepool.c
index 365324b87..0041348a7 100644
--- a/sys/ximage/ximagepool.c
+++ b/sys/ximage/ximagepool.c
@@ -32,7 +32,7 @@ GST_DEBUG_CATEGORY_EXTERN (gst_debug_ximagepool);
static void gst_meta_ximage_free (GstMetaXImage * meta, GstBuffer * buffer);
-/* ximage buffers */
+/* ximage metadata */
const GstMetaInfo *
gst_meta_ximage_get_info (void)
{
@@ -51,7 +51,7 @@ gst_meta_ximage_get_info (void)
}
/* X11 stuff */
-static gboolean error_caught;
+static gboolean error_caught = FALSE;
static int
gst_ximagesink_handle_xerror (Display * display, XErrorEvent * xevent)
@@ -133,6 +133,9 @@ gst_buffer_add_meta_ximage (GstBuffer * buffer, GstXImageSink * ximagesink,
* This way, it will be deleted as soon as we detach later, and not
* leaked if we crash. */
shmctl (meta->SHMInfo.shmid, IPC_RMID, NULL);
+
+ GST_DEBUG_OBJECT (ximagesink, "XServer ShmAttached to 0x%x, id 0x%lx",
+ meta->SHMInfo.shmid, meta->SHMInfo.shmseg);
} else
#endif /* HAVE_XSHM */
{
@@ -225,7 +228,7 @@ shmat_failed:
}
xattach_failed:
{
- /* Clean up shm seg */
+ /* Clean up the shared memory segment */
shmctl (meta->SHMInfo.shmid, IPC_RMID, NULL);
g_mutex_unlock (ximagesink->x_lock);
@@ -248,9 +251,11 @@ gst_meta_ximage_free (GstMetaXImage * meta, GstBuffer * buffer)
/* Hold the object lock to ensure the XContext doesn't disappear */
GST_OBJECT_LOCK (ximagesink);
/* We might have some buffers destroyed after changing state to NULL */
- if (!ximagesink->xcontext) {
+ if (ximagesink->xcontext == NULL) {
GST_DEBUG_OBJECT (ximagesink, "Destroying XImage after XContext");
#ifdef HAVE_XSHM
+ /* Need to free the shared memory segment even if the x context
+ * was already cleaned up */
if (meta->SHMInfo.shmaddr != ((void *) -1)) {
shmdt (meta->SHMInfo.shmaddr);
}
@@ -263,14 +268,15 @@ gst_meta_ximage_free (GstMetaXImage * meta, GstBuffer * buffer)
#ifdef HAVE_XSHM
if (ximagesink->xcontext->use_xshm) {
if (meta->SHMInfo.shmaddr != ((void *) -1)) {
+ GST_DEBUG_OBJECT (ximagesink, "XServer ShmDetaching from 0x%x id 0x%lx",
+ meta->SHMInfo.shmid, meta->SHMInfo.shmseg);
XShmDetach (ximagesink->xcontext->disp, &meta->SHMInfo);
- XSync (ximagesink->xcontext->disp, 0);
+ XSync (ximagesink->xcontext->disp, FALSE);
shmdt (meta->SHMInfo.shmaddr);
meta->SHMInfo.shmaddr = (void *) -1;
}
if (meta->ximage)
XDestroyImage (meta->ximage);
-
} else
#endif /* HAVE_XSHM */
{
@@ -302,7 +308,9 @@ gst_ximage_buffer_new (GstXImageSink * ximagesink, gint width, gint height)
return buffer;
}
-#ifdef HAVE_XSHM /* Check that XShm calls actually work */
+#ifdef HAVE_XSHM
+/* This function checks that it is actually really possible to create an image
+ using XShm */
gboolean
gst_ximagesink_check_xshm_calls (GstXImageSink * ximagesink,
GstXContext * xcontext)
@@ -351,7 +359,7 @@ gst_ximagesink_check_xshm_calls (GstXImageSink * ximagesink,
SHMInfo.shmaddr = shmat (SHMInfo.shmid, NULL, 0);
if (SHMInfo.shmaddr == ((void *) -1)) {
GST_WARNING ("Failed to shmat: %s", g_strerror (errno));
- /* Clean up shm seg */
+ /* Clean up the shared memory segment */
shmctl (SHMInfo.shmid, IPC_RMID, NULL);
goto beach;
}
@@ -361,7 +369,7 @@ gst_ximagesink_check_xshm_calls (GstXImageSink * ximagesink,
if (XShmAttach (xcontext->disp, &SHMInfo) == 0) {
GST_WARNING ("Failed to XShmAttach");
- /* Clean up shm seg */
+ /* Clean up the shared memory segment */
shmctl (SHMInfo.shmid, IPC_RMID, NULL);
goto beach;
}
@@ -369,24 +377,33 @@ gst_ximagesink_check_xshm_calls (GstXImageSink * ximagesink,
/* Sync to ensure we see any errors we caused */
XSync (xcontext->disp, FALSE);
- /* Delete the shared memory segment as soon as everyone is attached.
+ /* Delete the shared memory segment as soon as everyone is attached.
* This way, it will be deleted as soon as we detach later, and not
* leaked if we crash. */
shmctl (SHMInfo.shmid, IPC_RMID, NULL);
if (!error_caught) {
+ GST_DEBUG ("XServer ShmAttached to 0x%x, id 0x%lx", SHMInfo.shmid,
+ SHMInfo.shmseg);
+
did_attach = TRUE;
/* store whether we succeeded in result */
result = TRUE;
+ } else {
+ GST_WARNING ("MIT-SHM extension check failed at XShmAttach. "
+ "Not using shared memory.");
}
beach:
/* Sync to ensure we swallow any errors we caused and reset error_caught */
XSync (xcontext->disp, FALSE);
+
error_caught = FALSE;
XSetErrorHandler (handler);
if (did_attach) {
+ GST_DEBUG ("XServer ShmDetaching from 0x%x id 0x%lx",
+ SHMInfo.shmid, SHMInfo.shmseg);
XShmDetach (xcontext->disp, &SHMInfo);
XSync (xcontext->disp, FALSE);
}
diff --git a/sys/ximage/ximagepool.h b/sys/ximage/ximagepool.h
index 273ed6663..7f12bdc20 100644
--- a/sys/ximage/ximagepool.h
+++ b/sys/ximage/ximagepool.h
@@ -62,12 +62,13 @@ GstMetaXImage * gst_buffer_add_meta_ximage (GstBuffer *buffer, GstXImageSink *
* @height: the height in pixels of XImage @ximage
* @size: the size in bytes of XImage @ximage
*
- * Subclass of #GstBuffer containing additional information about an XImage.
+ * Subclass of #GstMeta containing additional information about an XImage.
*/
struct _GstMetaXImage
{
GstMeta meta;
+ /* Reference to the ximagesink we belong to */
GstXImageSink *sink;
XImage *ximage;
diff --git a/sys/ximage/ximagesink.c b/sys/ximage/ximagesink.c
index 6e60fcff1..54b26345e 100644
--- a/sys/ximage/ximagesink.c
+++ b/sys/ximage/ximagesink.c
@@ -208,8 +208,6 @@ gst_ximagesink_ximage_put (GstXImageSink * ximagesink, GstBuffer * ximage)
GstVideoRectangle src, dst, result;
gboolean draw_border = FALSE;
- g_return_val_if_fail (GST_IS_XIMAGESINK (ximagesink), FALSE);
-
/* 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 (ximagesink->flow_lock);
@@ -229,7 +227,7 @@ gst_ximagesink_ximage_put (GstXImageSink * ximagesink, GstBuffer * ximage)
if (ximage && ximagesink->cur_image != ximage) {
if (ximagesink->cur_image) {
GST_LOG_OBJECT (ximagesink, "unreffing %p", ximagesink->cur_image);
- gst_buffer_unref (GST_BUFFER_CAST (ximagesink->cur_image));
+ gst_buffer_unref (ximagesink->cur_image);
}
GST_LOG_OBJECT (ximagesink, "reffing %p as our current image", ximage);
ximagesink->cur_image = gst_buffer_ref (ximage);
@@ -247,6 +245,7 @@ gst_ximagesink_ximage_put (GstXImageSink * ximagesink, GstBuffer * ximage)
}
meta = gst_buffer_get_meta_ximage (ximage);
+
src.w = meta->width;
src.h = meta->height;
dst.w = ximagesink->xwindow->width;
@@ -303,7 +302,8 @@ gst_ximagesink_xwindow_decorate (GstXImageSink * ximagesink,
g_mutex_lock (ximagesink->x_lock);
- hints_atom = XInternAtom (ximagesink->xcontext->disp, "_MOTIF_WM_HINTS", 1);
+ hints_atom = XInternAtom (ximagesink->xcontext->disp, "_MOTIF_WM_HINTS",
+ True);
if (hints_atom == None) {
g_mutex_unlock (ximagesink->x_lock);
return FALSE;
@@ -586,7 +586,6 @@ gst_ximagesink_handle_xevents (GstXImageSink * ximagesink)
g_mutex_unlock (ximagesink->x_lock);
gst_navigation_send_key_event (GST_NAVIGATION (ximagesink),
e.type == KeyPress ? "key-press" : "key-release", key_str);
-
} else {
gst_navigation_send_key_event (GST_NAVIGATION (ximagesink),
e.type == KeyPress ? "key-press" : "key-release", "unknown");
@@ -600,6 +599,7 @@ gst_ximagesink_handle_xevents (GstXImageSink * ximagesink)
g_mutex_lock (ximagesink->x_lock);
}
+ /* Handle Expose */
while (XCheckWindowEvent (ximagesink->xcontext->disp,
ximagesink->xwindow->win, ExposureMask | StructureNotifyMask, &e)) {
switch (e.type) {
@@ -830,7 +830,7 @@ gst_ximagesink_xcontext_get (GstXImageSink * ximagesink)
g_mutex_unlock (ximagesink->x_lock);
g_free (xcontext->par);
g_free (xcontext);
- GST_ELEMENT_ERROR (ximagesink, RESOURCE, WRITE,
+ GST_ELEMENT_ERROR (ximagesink, RESOURCE, SETTINGS,
("Could not get supported pixmap formats"), (NULL));
return NULL;
}
@@ -854,7 +854,7 @@ gst_ximagesink_xcontext_get (GstXImageSink * ximagesink)
xcontext->use_xshm = TRUE;
GST_DEBUG ("ximagesink is using XShm extension");
} else
-#endif
+#endif /* HAVE_XSHM */
{
xcontext->use_xshm = FALSE;
GST_DEBUG ("ximagesink is not using XShm extension");
@@ -982,9 +982,9 @@ static gboolean
gst_ximagesink_setcaps (GstBaseSink * bsink, GstCaps * caps)
{
GstXImageSink *ximagesink;
- gboolean ret = TRUE;
GstStructure *structure;
GstBufferPool *newpool, *oldpool;
+ gboolean ret = TRUE;
const GValue *par;
gint new_width, new_height;
const GValue *fps;
@@ -1008,6 +1008,7 @@ gst_ximagesink_setcaps (GstBaseSink * bsink, GstCaps * caps)
ret &= gst_structure_get_int (structure, "height", &new_height);
fps = gst_structure_get_value (structure, "framerate");
ret &= (fps != NULL);
+
if (!ret)
return FALSE;
@@ -1052,7 +1053,6 @@ gst_ximagesink_setcaps (GstBaseSink * bsink, GstCaps * caps)
}
/* Remember to draw borders for next frame */
ximagesink->draw_border = TRUE;
- g_mutex_unlock (ximagesink->flow_lock);
/* create a new pool for the new configuration */
newpool = gst_ximage_buffer_pool_new (ximagesink);
@@ -1074,6 +1074,8 @@ gst_ximagesink_setcaps (GstBaseSink * bsink, GstCaps * caps)
gst_buffer_pool_set_active (oldpool, FALSE);
gst_object_unref (oldpool);
}
+ g_mutex_unlock (ximagesink->flow_lock);
+
return TRUE;
/* ERRORS */
@@ -1096,11 +1098,13 @@ invalid_size:
config_failed:
{
GST_ERROR_OBJECT (ximagesink, "failed to set config.");
+ g_mutex_unlock (ximagesink->flow_lock);
return FALSE;
}
activate_failed:
{
GST_ERROR_OBJECT (ximagesink, "failed to activate bufferpool.");
+ g_mutex_unlock (ximagesink->flow_lock);
return FALSE;
}
}
@@ -1108,15 +1112,14 @@ activate_failed:
static GstStateChangeReturn
gst_ximagesink_change_state (GstElement * element, GstStateChange transition)
{
- GstXImageSink *ximagesink;
GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
+ GstXImageSink *ximagesink;
GstXContext *xcontext = NULL;
ximagesink = GST_XIMAGESINK (element);
switch (transition) {
case GST_STATE_CHANGE_NULL_TO_READY:
-
/* Initializing the XContext */
if (ximagesink->xcontext == NULL) {
xcontext = gst_ximagesink_xcontext_get (ximagesink);
@@ -1160,6 +1163,9 @@ gst_ximagesink_change_state (GstElement * element, GstStateChange transition)
ximagesink->fps_d = 1;
GST_VIDEO_SINK_WIDTH (ximagesink) = 0;
GST_VIDEO_SINK_HEIGHT (ximagesink) = 0;
+ g_mutex_lock (ximagesink->flow_lock);
+ gst_buffer_pool_set_active (ximagesink->pool, FALSE);
+ g_mutex_unlock (ximagesink->flow_lock);
break;
case GST_STATE_CHANGE_READY_TO_NULL:
gst_ximagesink_reset (ximagesink);
@@ -1201,15 +1207,8 @@ gst_ximagesink_show_frame (GstVideoSink * vsink, GstBuffer * buf)
GstXImageSink *ximagesink;
GstMetaXImage *meta;
- g_return_val_if_fail (buf != NULL, GST_FLOW_ERROR);
-
ximagesink = GST_XIMAGESINK (vsink);
- /* This shouldn't really happen because state changes will fail
- * if the xcontext can't be allocated */
- if (!ximagesink->xcontext)
- return GST_FLOW_ERROR;
-
meta = gst_buffer_get_meta_ximage (buf);
if (meta) {
@@ -1811,16 +1810,17 @@ gst_ximagesink_reset (GstXImageSink * ximagesink)
g_thread_join (thread);
if (ximagesink->cur_image) {
- gst_buffer_unref (GST_BUFFER_CAST (ximagesink->cur_image));
+ gst_buffer_unref (ximagesink->cur_image);
ximagesink->cur_image = NULL;
}
+ g_mutex_lock (ximagesink->flow_lock);
+
if (ximagesink->pool) {
gst_object_unref (ximagesink->pool);
ximagesink->pool = NULL;
}
- g_mutex_lock (ximagesink->flow_lock);
if (ximagesink->xwindow) {
gst_ximagesink_xwindow_clear (ximagesink, ximagesink->xwindow);
gst_ximagesink_xwindow_destroy (ximagesink, ximagesink->xwindow);
diff --git a/sys/ximage/ximagesink.h b/sys/ximage/ximagesink.h
index b4ccfb41a..b47dcde0c 100644
--- a/sys/ximage/ximagesink.h
+++ b/sys/ximage/ximagesink.h
@@ -129,7 +129,6 @@ struct _GstXWindow
GC gc;
};
-
/**
* GstXImageSink:
* @display_name: the name of the Display we want to render to
diff --git a/sys/xvimage/Makefile.am b/sys/xvimage/Makefile.am
index fbff4d8c8..9669e72ca 100644
--- a/sys/xvimage/Makefile.am
+++ b/sys/xvimage/Makefile.am
@@ -1,6 +1,6 @@
plugin_LTLIBRARIES = libgstxvimagesink.la
-libgstxvimagesink_la_SOURCES = xvimagesink.c
+libgstxvimagesink_la_SOURCES = xvimagesink.c xvimage.c xvimagepool.c
libgstxvimagesink_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_BASE_CFLAGS) $(GST_CFLAGS) $(X_CFLAGS)
libgstxvimagesink_la_LIBADD = \
$(top_builddir)/gst-libs/gst/interfaces/libgstinterfaces-$(GST_MAJORMINOR).la \
@@ -12,4 +12,4 @@ libgstxvimagesink_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
libgstxvimagesink_la_DEPENDENCIES = $(top_builddir)/gst-libs/gst/video/libgstvideo-$(GST_MAJORMINOR).la
libgstxvimagesink_la_LIBTOOLFLAGS = --tag=disable-static
-noinst_HEADERS = xvimagesink.h
+noinst_HEADERS = xvimagesink.h xvimagepool.h
diff --git a/sys/xvimage/xvimage.c b/sys/xvimage/xvimage.c
new file mode 100644
index 000000000..5e2d6196e
--- /dev/null
+++ b/sys/xvimage/xvimage.c
@@ -0,0 +1,51 @@
+/* GStreamer
+ * Copyright (C) <2003> Julien Moutte <julien@moutte.net>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "xvimagesink.h"
+
+GST_DEBUG_CATEGORY (gst_debug_xvimagepool);
+GST_DEBUG_CATEGORY (gst_debug_xvimagesink);
+GST_DEBUG_CATEGORY_STATIC (GST_CAT_PERFORMANCE);
+
+static gboolean
+plugin_init (GstPlugin * plugin)
+{
+ if (!gst_element_register (plugin, "xvimagesink",
+ GST_RANK_PRIMARY, GST_TYPE_XVIMAGESINK))
+ return FALSE;
+
+ GST_DEBUG_CATEGORY_INIT (gst_debug_xvimagesink, "xvimagesink", 0,
+ "xvimagesink element");
+ GST_DEBUG_CATEGORY_INIT (gst_debug_xvimagepool, "xvimagepool", 0,
+ "xvimagepool object");
+
+ GST_DEBUG_CATEGORY_GET (GST_CAT_PERFORMANCE, "GST_PERFORMANCE");
+
+ return TRUE;
+}
+
+GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
+ GST_VERSION_MINOR,
+ "xvimagesink",
+ "XFree86 video output plugin using Xv extension",
+ plugin_init, VERSION, GST_LICENSE, GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN)
diff --git a/sys/xvimage/xvimagepool.c b/sys/xvimage/xvimagepool.c
new file mode 100644
index 000000000..0c37761b2
--- /dev/null
+++ b/sys/xvimage/xvimagepool.c
@@ -0,0 +1,642 @@
+/* GStreamer
+ * Copyright (C) <2005> Julien Moutte <julien@moutte.net>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+/* Object header */
+#include "xvimagesink.h"
+
+/* Debugging category */
+#include <gst/gstinfo.h>
+
+GST_DEBUG_CATEGORY_EXTERN (gst_debug_xvimagepool);
+#define GST_CAT_DEFAULT gst_debug_xvimagepool
+
+static void gst_meta_xvimage_free (GstMetaXvImage * meta, GstBuffer * buffer);
+
+/* xvimage metadata */
+const GstMetaInfo *
+gst_meta_xvimage_get_info (void)
+{
+ static const GstMetaInfo *meta_xvimage_info = NULL;
+
+ if (meta_xvimage_info == NULL) {
+ meta_xvimage_info = gst_meta_register ("GstMetaXvImage", "GstMetaXvImage",
+ sizeof (GstMetaXvImage),
+ (GstMetaInitFunction) NULL,
+ (GstMetaFreeFunction) gst_meta_xvimage_free,
+ (GstMetaCopyFunction) NULL,
+ (GstMetaTransformFunction) NULL,
+ (GstMetaSerializeFunction) NULL, (GstMetaDeserializeFunction) NULL);
+ }
+ return meta_xvimage_info;
+}
+
+/* X11 stuff */
+static gboolean error_caught = FALSE;
+
+static int
+gst_xvimagesink_handle_xerror (Display * display, XErrorEvent * xevent)
+{
+ char error_msg[1024];
+
+ XGetErrorText (display, xevent->error_code, error_msg, 1024);
+ GST_DEBUG ("xvimagesink triggered an XError. error: %s", error_msg);
+ error_caught = TRUE;
+ return 0;
+}
+
+GstMetaXvImage *
+gst_buffer_add_meta_xvimage (GstBuffer * buffer, GstXvImageSink * xvimagesink,
+ gint width, gint height, gint im_format)
+{
+ int (*handler) (Display *, XErrorEvent *);
+ gboolean success = FALSE;
+ GstXContext *xcontext;
+ GstMetaXvImage *meta;
+
+ xcontext = xvimagesink->xcontext;
+
+ meta =
+ (GstMetaXvImage *) gst_buffer_add_meta (buffer, GST_META_INFO_XVIMAGE,
+ NULL);
+#ifdef HAVE_XSHM
+ meta->SHMInfo.shmaddr = ((void *) -1);
+ meta->SHMInfo.shmid = -1;
+#endif
+ meta->width = width;
+ meta->height = height;
+ meta->sink = gst_object_ref (xvimagesink);
+ meta->im_format = im_format;
+
+ GST_DEBUG_OBJECT (xvimagesink, "creating image %p (%dx%d)", buffer,
+ meta->width, meta->height);
+
+ g_mutex_lock (xvimagesink->x_lock);
+
+ /* Setting an error handler to catch failure */
+ error_caught = FALSE;
+ handler = XSetErrorHandler (gst_xvimagesink_handle_xerror);
+
+#ifdef HAVE_XSHM
+ if (xcontext->use_xshm) {
+ int expected_size;
+
+ meta->xvimage = XvShmCreateImage (xcontext->disp,
+ xcontext->xv_port_id,
+ meta->im_format, NULL, meta->width, meta->height, &meta->SHMInfo);
+ if (!meta->xvimage || error_caught)
+ goto create_failed;
+
+ /* we have to use the returned data_size for our shm size */
+ meta->size = meta->xvimage->data_size;
+ GST_LOG_OBJECT (xvimagesink, "XShm image size is %" G_GSIZE_FORMAT,
+ meta->size);
+
+ /* calculate the expected size. This is only for sanity checking the
+ * number we get from X. */
+ switch (meta->im_format) {
+ case GST_MAKE_FOURCC ('I', '4', '2', '0'):
+ case GST_MAKE_FOURCC ('Y', 'V', '1', '2'):
+ {
+ gint pitches[3];
+ gint offsets[3];
+ guint plane;
+
+ offsets[0] = 0;
+ pitches[0] = GST_ROUND_UP_4 (meta->width);
+ offsets[1] = offsets[0] + pitches[0] * GST_ROUND_UP_2 (meta->height);
+ pitches[1] = GST_ROUND_UP_8 (meta->width) / 2;
+ offsets[2] =
+ offsets[1] + pitches[1] * GST_ROUND_UP_2 (meta->height) / 2;
+ pitches[2] = GST_ROUND_UP_8 (pitches[0]) / 2;
+
+ expected_size =
+ offsets[2] + pitches[2] * GST_ROUND_UP_2 (meta->height) / 2;
+
+ for (plane = 0; plane < meta->xvimage->num_planes; plane++) {
+ GST_DEBUG_OBJECT (xvimagesink,
+ "Plane %u has a expected pitch of %d bytes, " "offset of %d",
+ plane, pitches[plane], offsets[plane]);
+ }
+ break;
+ }
+ case GST_MAKE_FOURCC ('Y', 'U', 'Y', '2'):
+ case GST_MAKE_FOURCC ('U', 'Y', 'V', 'Y'):
+ expected_size = meta->height * GST_ROUND_UP_4 (meta->width * 2);
+ break;
+ default:
+ expected_size = 0;
+ break;
+ }
+ if (expected_size != 0 && meta->size != expected_size) {
+ GST_WARNING_OBJECT (xvimagesink,
+ "unexpected XShm image size (got %" G_GSIZE_FORMAT ", expected %d)",
+ meta->size, expected_size);
+ }
+
+ /* Be verbose about our XvImage stride */
+ {
+ guint plane;
+
+ for (plane = 0; plane < meta->xvimage->num_planes; plane++) {
+ GST_DEBUG_OBJECT (xvimagesink, "Plane %u has a pitch of %d bytes, "
+ "offset of %d", plane, meta->xvimage->pitches[plane],
+ meta->xvimage->offsets[plane]);
+ }
+ }
+
+ /* get shared memory */
+ meta->SHMInfo.shmid = shmget (IPC_PRIVATE, meta->size, IPC_CREAT | 0777);
+ if (meta->SHMInfo.shmid == -1)
+ goto shmget_failed;
+
+ /* attach */
+ meta->SHMInfo.shmaddr = shmat (meta->SHMInfo.shmid, NULL, 0);
+ if (meta->SHMInfo.shmaddr == ((void *) -1))
+ goto shmat_failed;
+
+ /* now we can set up the image data */
+ meta->xvimage->data = meta->SHMInfo.shmaddr;
+ meta->SHMInfo.readOnly = FALSE;
+
+ if (XShmAttach (xcontext->disp, &meta->SHMInfo) == 0)
+ goto xattach_failed;
+
+ XSync (xcontext->disp, FALSE);
+
+ /* Delete the shared memory segment as soon as we everyone is attached.
+ * This way, it will be deleted as soon as we detach later, and not
+ * leaked if we crash. */
+ shmctl (meta->SHMInfo.shmid, IPC_RMID, NULL);
+
+ GST_DEBUG_OBJECT (xvimagesink, "XServer ShmAttached to 0x%x, id 0x%lx",
+ meta->SHMInfo.shmid, meta->SHMInfo.shmseg);
+ } else
+#endif /* HAVE_XSHM */
+ {
+ meta->xvimage = XvCreateImage (xcontext->disp,
+ xcontext->xv_port_id, meta->im_format, NULL, meta->width, meta->height);
+ if (!meta->xvimage || error_caught)
+ goto create_failed;
+
+ /* we have to use the returned data_size for our image size */
+ meta->size = meta->xvimage->data_size;
+ meta->xvimage->data = g_malloc (meta->size);
+
+ XSync (xcontext->disp, FALSE);
+ }
+
+ /* Reset error handler */
+ error_caught = FALSE;
+ XSetErrorHandler (handler);
+
+ gst_buffer_take_memory (buffer,
+ gst_memory_new_wrapped (0, meta->xvimage->data, NULL,
+ meta->size, 0, meta->size));
+
+ g_mutex_unlock (xvimagesink->x_lock);
+
+ success = TRUE;
+
+beach:
+ if (!success)
+ meta = NULL;
+
+ return meta;
+
+ /* ERRORS */
+create_failed:
+ {
+ g_mutex_unlock (xvimagesink->x_lock);
+ /* Reset error handler */
+ error_caught = FALSE;
+ XSetErrorHandler (handler);
+ /* Push an error */
+ GST_ELEMENT_ERROR (xvimagesink, RESOURCE, WRITE,
+ ("Failed to create output image buffer of %dx%d pixels",
+ meta->width, meta->height),
+ ("could not XvShmCreateImage a %dx%d image", meta->width,
+ meta->height));
+ goto beach;
+ }
+shmget_failed:
+ {
+ g_mutex_unlock (xvimagesink->x_lock);
+ GST_ELEMENT_ERROR (xvimagesink, RESOURCE, WRITE,
+ ("Failed to create output image buffer of %dx%d pixels",
+ meta->width, meta->height),
+ ("could not get shared memory of %" G_GSIZE_FORMAT " bytes",
+ meta->size));
+ goto beach;
+ }
+shmat_failed:
+ {
+ g_mutex_unlock (xvimagesink->x_lock);
+ GST_ELEMENT_ERROR (xvimagesink, RESOURCE, WRITE,
+ ("Failed to create output image buffer of %dx%d pixels",
+ meta->width, meta->height),
+ ("Failed to shmat: %s", g_strerror (errno)));
+ /* Clean up the shared memory segment */
+ shmctl (meta->SHMInfo.shmid, IPC_RMID, NULL);
+ goto beach;
+ }
+xattach_failed:
+ {
+ /* Clean up the shared memory segment */
+ shmctl (meta->SHMInfo.shmid, IPC_RMID, NULL);
+ g_mutex_unlock (xvimagesink->x_lock);
+
+ GST_ELEMENT_ERROR (xvimagesink, RESOURCE, WRITE,
+ ("Failed to create output image buffer of %dx%d pixels",
+ meta->width, meta->height), ("Failed to XShmAttach"));
+ goto beach;
+ }
+}
+
+static void
+gst_meta_xvimage_free (GstMetaXvImage * meta, GstBuffer * buffer)
+{
+ GstXvImageSink *xvimagesink;
+
+ xvimagesink = meta->sink;
+
+ GST_DEBUG_OBJECT (xvimagesink, "free meta on buffer %p", buffer);
+
+ /* Hold the object lock to ensure the XContext doesn't disappear */
+ GST_OBJECT_LOCK (xvimagesink);
+ /* We might have some buffers destroyed after changing state to NULL */
+ if (xvimagesink->xcontext == NULL) {
+ GST_DEBUG_OBJECT (xvimagesink, "Destroying XvImage after Xcontext");
+#ifdef HAVE_XSHM
+ /* Need to free the shared memory segment even if the x context
+ * was already cleaned up */
+ if (meta->SHMInfo.shmaddr != ((void *) -1)) {
+ shmdt (meta->SHMInfo.shmaddr);
+ }
+#endif
+ goto beach;
+ }
+
+ g_mutex_lock (xvimagesink->x_lock);
+
+#ifdef HAVE_XSHM
+ if (xvimagesink->xcontext->use_xshm) {
+ if (meta->SHMInfo.shmaddr != ((void *) -1)) {
+ GST_DEBUG_OBJECT (xvimagesink, "XServer ShmDetaching from 0x%x id 0x%lx",
+ meta->SHMInfo.shmid, meta->SHMInfo.shmseg);
+ XShmDetach (xvimagesink->xcontext->disp, &meta->SHMInfo);
+ XSync (xvimagesink->xcontext->disp, FALSE);
+ shmdt (meta->SHMInfo.shmaddr);
+ meta->SHMInfo.shmaddr = (void *) -1;
+ }
+ if (meta->xvimage)
+ XFree (meta->xvimage);
+ } else
+#endif /* HAVE_XSHM */
+ {
+ if (meta->xvimage) {
+ g_free (meta->xvimage->data);
+ XFree (meta->xvimage);
+ }
+ }
+
+ XSync (xvimagesink->xcontext->disp, FALSE);
+
+ g_mutex_unlock (xvimagesink->x_lock);
+
+beach:
+ GST_OBJECT_UNLOCK (xvimagesink);
+}
+
+GstBuffer *
+gst_xvimage_buffer_new (GstXvImageSink * xvimagesink, gint width, gint height,
+ gint im_format)
+{
+ GstBuffer *buffer;
+ GstMetaXvImage *meta;
+
+ buffer = gst_buffer_new ();
+ meta =
+ gst_buffer_add_meta_xvimage (buffer, xvimagesink, width, height,
+ im_format);
+ if (meta == NULL) {
+ gst_buffer_unref (buffer);
+ buffer = NULL;
+ }
+ return buffer;
+}
+
+#ifdef HAVE_XSHM
+/* This function checks that it is actually really possible to create an image
+ using XShm */
+gboolean
+gst_xvimagesink_check_xshm_calls (GstXvImageSink * xvimagesink,
+ GstXContext * xcontext)
+{
+ XvImage *xvimage;
+ XShmSegmentInfo SHMInfo;
+ size_t size;
+ int (*handler) (Display *, XErrorEvent *);
+ gboolean result = FALSE;
+ gboolean did_attach = FALSE;
+
+ g_return_val_if_fail (xcontext != NULL, FALSE);
+
+ /* Sync to ensure any older errors are already processed */
+ XSync (xcontext->disp, FALSE);
+
+ /* Set defaults so we don't free these later unnecessarily */
+ SHMInfo.shmaddr = ((void *) -1);
+ SHMInfo.shmid = -1;
+
+ /* Setting an error handler to catch failure */
+ error_caught = FALSE;
+ handler = XSetErrorHandler (gst_xvimagesink_handle_xerror);
+
+ /* Trying to create a 1x1 picture */
+ GST_DEBUG ("XvShmCreateImage of 1x1");
+ xvimage = XvShmCreateImage (xcontext->disp, xcontext->xv_port_id,
+ xcontext->im_format, NULL, 1, 1, &SHMInfo);
+
+ /* Might cause an error, sync to ensure it is noticed */
+ XSync (xcontext->disp, FALSE);
+ if (!xvimage || error_caught) {
+ GST_WARNING ("could not XvShmCreateImage a 1x1 image");
+ goto beach;
+ }
+ size = xvimage->data_size;
+
+ SHMInfo.shmid = shmget (IPC_PRIVATE, size, IPC_CREAT | 0777);
+ if (SHMInfo.shmid == -1) {
+ GST_WARNING ("could not get shared memory of %" G_GSIZE_FORMAT " bytes",
+ size);
+ goto beach;
+ }
+
+ SHMInfo.shmaddr = shmat (SHMInfo.shmid, NULL, 0);
+ if (SHMInfo.shmaddr == ((void *) -1)) {
+ GST_WARNING ("Failed to shmat: %s", g_strerror (errno));
+ /* Clean up the shared memory segment */
+ shmctl (SHMInfo.shmid, IPC_RMID, NULL);
+ goto beach;
+ }
+
+ xvimage->data = SHMInfo.shmaddr;
+ SHMInfo.readOnly = FALSE;
+
+ if (XShmAttach (xcontext->disp, &SHMInfo) == 0) {
+ GST_WARNING ("Failed to XShmAttach");
+ /* Clean up the shared memory segment */
+ shmctl (SHMInfo.shmid, IPC_RMID, NULL);
+ goto beach;
+ }
+
+ /* Sync to ensure we see any errors we caused */
+ XSync (xcontext->disp, FALSE);
+
+ /* Delete the shared memory segment as soon as everyone is attached.
+ * This way, it will be deleted as soon as we detach later, and not
+ * leaked if we crash. */
+ shmctl (SHMInfo.shmid, IPC_RMID, NULL);
+
+ if (!error_caught) {
+ GST_DEBUG ("XServer ShmAttached to 0x%x, id 0x%lx", SHMInfo.shmid,
+ SHMInfo.shmseg);
+
+ did_attach = TRUE;
+ /* store whether we succeeded in result */
+ result = TRUE;
+ } else {
+ GST_WARNING ("MIT-SHM extension check failed at XShmAttach. "
+ "Not using shared memory.");
+ }
+
+beach:
+ /* Sync to ensure we swallow any errors we caused and reset error_caught */
+ XSync (xcontext->disp, FALSE);
+
+ error_caught = FALSE;
+ XSetErrorHandler (handler);
+
+ if (did_attach) {
+ GST_DEBUG ("XServer ShmDetaching from 0x%x id 0x%lx",
+ SHMInfo.shmid, SHMInfo.shmseg);
+ XShmDetach (xcontext->disp, &SHMInfo);
+ XSync (xcontext->disp, FALSE);
+ }
+ if (SHMInfo.shmaddr != ((void *) -1))
+ shmdt (SHMInfo.shmaddr);
+ if (xvimage)
+ XFree (xvimage);
+ return result;
+}
+#endif /* HAVE_XSHM */
+
+/* bufferpool */
+static void gst_xvimage_buffer_pool_finalize (GObject * object);
+
+#define GST_XVIMAGE_BUFFER_POOL_GET_PRIVATE(obj) \
+ (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GST_TYPE_XVIMAGE_BUFFER_POOL, GstXvImageBufferPoolPrivate))
+
+struct _GstXvImageBufferPoolPrivate
+{
+ GstCaps *caps;
+ gint width, height;
+ gint im_format;
+};
+
+G_DEFINE_TYPE (GstXvImageBufferPool, gst_xvimage_buffer_pool,
+ GST_TYPE_BUFFER_POOL);
+
+static gboolean
+xvimage_buffer_pool_set_config (GstBufferPool * pool, GstStructure * config)
+{
+ GstXvImageBufferPool *xvpool = GST_XVIMAGE_BUFFER_POOL_CAST (pool);
+ GstXvImageBufferPoolPrivate *priv = xvpool->priv;
+ GstStructure *structure;
+ gint width, height;
+ const GstCaps *caps;
+
+ if (!gst_buffer_pool_config_get (config, &caps, NULL, NULL, NULL, NULL,
+ NULL, NULL))
+ goto wrong_config;
+
+ if (caps == NULL)
+ goto no_caps;
+
+ /* now parse the caps from the config */
+ structure = gst_caps_get_structure (caps, 0);
+
+ if (!gst_structure_get_int (structure, "width", &width) ||
+ !gst_structure_get_int (structure, "height", &height))
+ goto wrong_caps;
+
+ GST_LOG_OBJECT (pool, "%dx%d, caps %" GST_PTR_FORMAT, width, height, caps);
+
+ /* keep track of the width and height and caps */
+ if (priv->caps)
+ gst_caps_unref (priv->caps);
+ priv->caps = gst_caps_copy (caps);
+ priv->width = width;
+ priv->height = height;
+ priv->im_format =
+ gst_xvimagesink_get_format_from_caps (xvpool->sink, (GstCaps *) caps);
+
+ if (priv->im_format == -1) {
+ GST_WARNING_OBJECT (xvpool->sink, "failed to get format from caps %"
+ GST_PTR_FORMAT, caps);
+ GST_ELEMENT_ERROR (xvpool->sink, RESOURCE, WRITE,
+ ("Failed to create output image buffer of %dx%d pixels",
+ priv->width, priv->height), ("Invalid input caps"));
+ goto wrong_config;
+ }
+
+ return TRUE;
+
+ /* ERRORS */
+wrong_config:
+ {
+ GST_WARNING_OBJECT (pool, "invalid config");
+ return FALSE;
+ }
+no_caps:
+ {
+ GST_WARNING_OBJECT (pool, "no caps in config");
+ return FALSE;
+ }
+wrong_caps:
+ {
+ GST_WARNING_OBJECT (pool,
+ "failed getting geometry from caps %" GST_PTR_FORMAT, caps);
+ return FALSE;
+ }
+}
+
+/* This function handles GstXImageBuffer creation depending on XShm availability */
+static GstFlowReturn
+xvimage_buffer_pool_alloc (GstBufferPool * pool, GstBuffer ** buffer,
+ GstBufferPoolParams * params)
+{
+ GstXvImageBufferPool *xvpool = GST_XVIMAGE_BUFFER_POOL_CAST (pool);
+ GstXvImageBufferPoolPrivate *priv = xvpool->priv;
+ GstBuffer *xvimage;
+
+ xvimage =
+ gst_xvimage_buffer_new (xvpool->sink, priv->width, priv->height,
+ priv->im_format);
+ if (xvimage == NULL)
+ goto no_buffer;
+
+ *buffer = xvimage;
+
+ return GST_FLOW_OK;
+
+ /* ERROR */
+no_buffer:
+ {
+ GST_WARNING_OBJECT (pool, "can't create image");
+ return GST_FLOW_ERROR;
+ }
+}
+
+static void
+xvimage_buffer_pool_free (GstBufferPool * pool, GstBuffer * buffer)
+{
+ gst_buffer_unref (buffer);
+}
+
+GstBufferPool *
+gst_xvimage_buffer_pool_new (GstXvImageSink * xvimagesink)
+{
+ GstXvImageBufferPool *pool;
+
+ g_return_val_if_fail (GST_IS_XVIMAGESINK (xvimagesink), NULL);
+
+ pool = g_object_new (GST_TYPE_XVIMAGE_BUFFER_POOL, NULL);
+ pool->sink = gst_object_ref (xvimagesink);
+
+ GST_LOG_OBJECT (pool, "new XvImage buffer pool %p", pool);
+
+ return GST_BUFFER_POOL_CAST (pool);
+}
+
+static void
+gst_xvimage_buffer_pool_class_init (GstXvImageBufferPoolClass * klass)
+{
+ GObjectClass *gobject_class = (GObjectClass *) klass;
+ GstBufferPoolClass *gstbufferpool_class = (GstBufferPoolClass *) klass;
+
+ g_type_class_add_private (klass, sizeof (GstXvImageBufferPoolPrivate));
+
+ gobject_class->finalize = gst_xvimage_buffer_pool_finalize;
+
+ gstbufferpool_class->set_config = xvimage_buffer_pool_set_config;
+ gstbufferpool_class->alloc_buffer = xvimage_buffer_pool_alloc;
+ gstbufferpool_class->free_buffer = xvimage_buffer_pool_free;
+}
+
+static void
+gst_xvimage_buffer_pool_init (GstXvImageBufferPool * pool)
+{
+ pool->priv = GST_XVIMAGE_BUFFER_POOL_GET_PRIVATE (pool);
+}
+
+static void
+gst_xvimage_buffer_pool_finalize (GObject * object)
+{
+ GstXvImageBufferPool *pool = GST_XVIMAGE_BUFFER_POOL_CAST (object);
+ GstXvImageBufferPoolPrivate *priv = pool->priv;
+
+ GST_LOG_OBJECT (pool, "finalize XvImage buffer pool %p", pool);
+
+ if (priv->caps)
+ gst_caps_unref (priv->caps);
+ gst_object_unref (pool->sink);
+
+ G_OBJECT_CLASS (gst_xvimage_buffer_pool_parent_class)->finalize (object);
+}
+
+/* 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 */
+gint
+gst_xvimagesink_get_format_from_caps (GstXvImageSink * xvimagesink,
+ GstCaps * caps)
+{
+ GList *list = NULL;
+
+ g_return_val_if_fail (GST_IS_XVIMAGESINK (xvimagesink), 0);
+
+ list = xvimagesink->xcontext->formats_list;
+
+ while (list) {
+ GstXvImageFormat *format = list->data;
+
+ if (format) {
+ if (gst_caps_can_intersect (caps, format->caps)) {
+ return format->format;
+ }
+ }
+ list = g_list_next (list);
+ }
+
+ return -1;
+}
diff --git a/sys/xvimage/xvimagepool.h b/sys/xvimage/xvimagepool.h
new file mode 100644
index 000000000..d927251f6
--- /dev/null
+++ b/sys/xvimage/xvimagepool.h
@@ -0,0 +1,120 @@
+/* GStreamer
+ * Copyright (C) <2005> Julien Moutte <julien@moutte.net>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __GST_XVIMAGEPOOL_H__
+#define __GST_XVIMAGEPOOL_H__
+
+#ifdef HAVE_XSHM
+#include <sys/types.h>
+#include <sys/ipc.h>
+#include <sys/shm.h>
+#endif /* HAVE_XSHM */
+
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+
+#ifdef HAVE_XSHM
+#include <X11/extensions/XShm.h>
+#endif /* HAVE_XSHM */
+
+#include <string.h>
+#include <math.h>
+
+
+G_BEGIN_DECLS
+
+typedef struct _GstMetaXvImage GstMetaXvImage;
+
+typedef struct _GstXvImageBufferPool GstXvImageBufferPool;
+typedef struct _GstXvImageBufferPoolClass GstXvImageBufferPoolClass;
+typedef struct _GstXvImageBufferPoolPrivate GstXvImageBufferPoolPrivate;
+
+#include "xvimagesink.h"
+
+const GstMetaInfo * gst_meta_xvimage_get_info (void);
+#define GST_META_INFO_XVIMAGE (gst_meta_xvimage_get_info())
+
+#define gst_buffer_get_meta_xvimage(b) ((GstMetaXvImage*)gst_buffer_get_meta((b),GST_META_INFO_XVIMAGE))
+GstMetaXvImage * gst_buffer_add_meta_xvimage (GstBuffer *buffer, GstXvImageSink * xvimagesink,
+ gint width, gint height, gint im_format);
+
+/**
+ * GstMetaXvImage:
+ * @sink: a reference to the our #GstXvImageSink
+ * @xvimage: the XvImage of this buffer
+ * @width: the width in pixels of XvImage @xvimage
+ * @height: the height in pixels of XvImage @xvimage
+ * @im_format: the format of XvImage @xvimage
+ * @size: the size in bytes of XvImage @xvimage
+ *
+ * Subclass of #GstMeta containing additional information about an XvImage.
+ */
+struct _GstMetaXvImage
+{
+ GstMeta meta;
+
+ /* Reference to the xvimagesink we belong to */
+ GstXvImageSink *sink;
+
+ XvImage *xvimage;
+
+#ifdef HAVE_XSHM
+ XShmSegmentInfo SHMInfo;
+#endif /* HAVE_XSHM */
+
+ gint width, height, im_format;
+ size_t size;
+};
+
+GstBuffer *gst_xvimage_buffer_new (GstXvImageSink *xvimagesink, gint width, gint height,
+ gint in_format);
+
+/* buffer pool functions */
+#define GST_TYPE_XVIMAGE_BUFFER_POOL (gst_xvimage_buffer_pool_get_type())
+#define GST_IS_XVIMAGE_BUFFER_POOL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_XVIMAGE_BUFFER_POOL))
+#define GST_XVIMAGE_BUFFER_POOL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_XVIMAGE_BUFFER_POOL, GstXvImageBufferPool))
+#define GST_XVIMAGE_BUFFER_POOL_CAST(obj) ((GstXvImageBufferPool*)(obj))
+
+struct _GstXvImageBufferPool
+{
+ GstBufferPool bufferpool;
+
+ GstXvImageSink *sink;
+
+ GstXvImageBufferPoolPrivate *priv;
+};
+
+struct _GstXvImageBufferPoolClass
+{
+ GstBufferPoolClass parent_class;
+};
+
+GType gst_xvimage_buffer_pool_get_type (void);
+
+GstBufferPool *gst_xvimage_buffer_pool_new (GstXvImageSink * xvimagesink);
+
+gboolean gst_xvimagesink_check_xshm_calls (GstXvImageSink * xvimagesink,
+ GstXContext * xcontext);
+
+gint gst_xvimagesink_get_format_from_caps (GstXvImageSink * xvimagesink,
+ GstCaps * caps);
+
+G_END_DECLS
+
+#endif /*__GST_XVIMAGEPOOL_H__*/
diff --git a/sys/xvimage/xvimagesink.c b/sys/xvimage/xvimagesink.c
index de21d5c1c..a7d34d70b 100644
--- a/sys/xvimage/xvimagesink.c
+++ b/sys/xvimage/xvimagesink.c
@@ -126,9 +126,10 @@
/* Debugging category */
#include <gst/gstinfo.h>
-GST_DEBUG_CATEGORY_STATIC (gst_debug_xvimagesink);
+
+GST_DEBUG_CATEGORY_EXTERN (gst_debug_xvimagesink);
+GST_DEBUG_CATEGORY_EXTERN (GST_CAT_PERFORMANCE);
#define GST_CAT_DEFAULT gst_debug_xvimagesink
-GST_DEBUG_CATEGORY_STATIC (GST_CAT_PERFORMANCE);
typedef struct
{
@@ -143,12 +144,8 @@ MotifWmHints, MwmHints;
#define MWM_HINTS_DECORATIONS (1L << 1)
static void gst_xvimagesink_reset (GstXvImageSink * xvimagesink);
-static void gst_xvimagesink_xvimage_destroy (GstXvImageSink * xvimagesink,
- GstBuffer * xvimage);
static void gst_xvimagesink_xwindow_update_geometry (GstXvImageSink *
xvimagesink);
-static gint gst_xvimagesink_get_format_from_caps (GstXvImageSink * xvimagesink,
- GstCaps * caps);
static void gst_xvimagesink_expose (GstXOverlay * overlay);
/* Default template - initiated with class struct to allow gst-register to work
@@ -197,501 +194,6 @@ static GstVideoSinkClass *parent_class = NULL;
/* */
/* ============================================================= */
-/* xvimage buffers */
-const GstMetaInfo *
-gst_meta_xvimage_get_info (void)
-{
- static const GstMetaInfo *meta_xvimage_info = NULL;
-
- if (meta_xvimage_info == NULL) {
- meta_xvimage_info = gst_meta_register ("GstMetaXvImage", "GstMetaXvImage",
- sizeof (GstMetaXvImage),
- (GstMetaInitFunction) NULL,
- (GstMetaFreeFunction) NULL,
- (GstMetaCopyFunction) NULL,
- (GstMetaTransformFunction) NULL,
- (GstMetaSerializeFunction) NULL, (GstMetaDeserializeFunction) NULL);
- }
- return meta_xvimage_info;
-}
-
-static void
-gst_xvimage_buffer_dispose (GstBuffer * xvimage)
-{
- GstMetaXvImage *data = NULL;
- GstXvImageSink *xvimagesink;
- gboolean running;
-
- data = GST_META_XVIMAGE_GET (xvimage);
- g_return_if_fail (data != NULL);
-
- xvimagesink = data->xvimagesink;
- if (G_UNLIKELY (xvimagesink == NULL))
- goto no_sink;
-
- g_return_if_fail (GST_IS_XVIMAGESINK (xvimagesink));
-
- GST_OBJECT_LOCK (xvimagesink);
- running = xvimagesink->running;
- GST_OBJECT_UNLOCK (xvimagesink);
-
- if (running == FALSE) {
- GST_LOG_OBJECT (xvimage, "destroy image as sink is shutting down");
- gst_xvimagesink_xvimage_destroy (xvimagesink, xvimage);
- } else if ((data->width != xvimagesink->video_width) ||
- (data->height != xvimagesink->video_height)) {
- /* If our geometry changed we can't reuse that image. */
- GST_LOG_OBJECT (xvimage,
- "destroy image as its size changed %dx%d vs current %dx%d",
- data->width, data->height,
- xvimagesink->video_width, 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. */
- GST_LOG_OBJECT (xvimage, "recycling image in pool");
- /* need to increment the refcount again to recycle */
- gst_buffer_ref (xvimage);
- g_mutex_lock (xvimagesink->pool_lock);
- xvimagesink->image_pool = g_slist_prepend (xvimagesink->image_pool,
- xvimage);
- g_mutex_unlock (xvimagesink->pool_lock);
- }
- return;
-
-no_sink:
- {
- GST_WARNING ("no sink found");
- return;
- }
-}
-
-static void
-gst_xvimage_buffer_free (GstBuffer * xvimage)
-{
- GstMetaXvImage *data = GST_META_XVIMAGE_GET (xvimage);
-
- g_return_if_fail (data != NULL);
-
- /* make sure it is not recycled */
- data->width = -1;
- data->height = -1;
- gst_buffer_unref (xvimage);
-}
-
-/* X11 stuff */
-
-static gboolean error_caught = FALSE;
-
-static int
-gst_xvimagesink_handle_xerror (Display * display, XErrorEvent * xevent)
-{
- char error_msg[1024];
-
- XGetErrorText (display, xevent->error_code, error_msg, 1024);
- GST_DEBUG ("xvimagesink triggered an XError. error: %s", error_msg);
- error_caught = TRUE;
- return 0;
-}
-
-#ifdef HAVE_XSHM
-/* This function checks that it is actually really possible to create an image
- using XShm */
-static gboolean
-gst_xvimagesink_check_xshm_calls (GstXContext * xcontext)
-{
- XvImage *xvimage;
- XShmSegmentInfo SHMInfo;
- gint size;
- int (*handler) (Display *, XErrorEvent *);
- gboolean result = FALSE;
- gboolean did_attach = FALSE;
-
- g_return_val_if_fail (xcontext != NULL, FALSE);
-
- /* Sync to ensure any older errors are already processed */
- XSync (xcontext->disp, FALSE);
-
- /* Set defaults so we don't free these later unnecessarily */
- SHMInfo.shmaddr = ((void *) -1);
- SHMInfo.shmid = -1;
-
- /* Setting an error handler to catch failure */
- error_caught = FALSE;
- handler = XSetErrorHandler (gst_xvimagesink_handle_xerror);
-
- /* Trying to create a 1x1 picture */
- GST_DEBUG ("XvShmCreateImage of 1x1");
- xvimage = XvShmCreateImage (xcontext->disp, xcontext->xv_port_id,
- xcontext->im_format, NULL, 1, 1, &SHMInfo);
-
- /* Might cause an error, sync to ensure it is noticed */
- XSync (xcontext->disp, FALSE);
- if (!xvimage || error_caught) {
- GST_WARNING ("could not XvShmCreateImage a 1x1 image");
- goto beach;
- }
- size = xvimage->data_size;
-
- SHMInfo.shmid = shmget (IPC_PRIVATE, size, IPC_CREAT | 0777);
- if (SHMInfo.shmid == -1) {
- GST_WARNING ("could not get shared memory of %d bytes", size);
- goto beach;
- }
-
- SHMInfo.shmaddr = shmat (SHMInfo.shmid, NULL, 0);
- if (SHMInfo.shmaddr == ((void *) -1)) {
- GST_WARNING ("Failed to shmat: %s", g_strerror (errno));
- /* Clean up the shared memory segment */
- shmctl (SHMInfo.shmid, IPC_RMID, NULL);
- goto beach;
- }
-
- xvimage->data = SHMInfo.shmaddr;
- SHMInfo.readOnly = FALSE;
-
- if (XShmAttach (xcontext->disp, &SHMInfo) == 0) {
- GST_WARNING ("Failed to XShmAttach");
- /* Clean up the shared memory segment */
- shmctl (SHMInfo.shmid, IPC_RMID, NULL);
- goto beach;
- }
-
- /* Sync to ensure we see any errors we caused */
- XSync (xcontext->disp, FALSE);
-
- /* Delete the shared memory segment as soon as everyone is attached.
- * This way, it will be deleted as soon as we detach later, and not
- * leaked if we crash. */
- shmctl (SHMInfo.shmid, IPC_RMID, NULL);
-
- if (!error_caught) {
- GST_DEBUG ("XServer ShmAttached to 0x%x, id 0x%lx", SHMInfo.shmid,
- SHMInfo.shmseg);
-
- did_attach = TRUE;
- /* store whether we succeeded in result */
- result = TRUE;
- } else {
- GST_WARNING ("MIT-SHM extension check failed at XShmAttach. "
- "Not using shared memory.");
- }
-
-beach:
- /* Sync to ensure we swallow any errors we caused and reset error_caught */
- XSync (xcontext->disp, FALSE);
-
- error_caught = FALSE;
- XSetErrorHandler (handler);
-
- if (did_attach) {
- GST_DEBUG ("XServer ShmDetaching from 0x%x id 0x%lx",
- SHMInfo.shmid, SHMInfo.shmseg);
- XShmDetach (xcontext->disp, &SHMInfo);
- XSync (xcontext->disp, FALSE);
- }
- if (SHMInfo.shmaddr != ((void *) -1))
- shmdt (SHMInfo.shmaddr);
- if (xvimage)
- XFree (xvimage);
- return result;
-}
-#endif /* HAVE_XSHM */
-
-/* This function handles GstXvImage creation depending on XShm availability */
-static GstBuffer *
-gst_xvimagesink_xvimage_new (GstXvImageSink * xvimagesink, GstCaps * caps)
-{
- GstBuffer *buffer = NULL;
- GstMetaXvImage *meta = NULL;
- GstStructure *structure = NULL;
- gboolean succeeded = FALSE;
- int (*handler) (Display *, XErrorEvent *);
-
- g_return_val_if_fail (GST_IS_XVIMAGESINK (xvimagesink), NULL);
-
- if (caps == NULL)
- return NULL;
-
- buffer = gst_buffer_new ();
- GST_DEBUG_OBJECT (xvimagesink, "Creating new XvImageBuffer");
- GST_MINI_OBJECT_CAST (buffer)->dispose =
- (GstMiniObjectDisposeFunction) gst_xvimage_buffer_dispose;
-
- meta = GST_META_XVIMAGE_ADD (buffer);
-#ifdef HAVE_XSHM
- meta->SHMInfo.shmaddr = ((void *) -1);
- meta->SHMInfo.shmid = -1;
-#endif
-
- structure = gst_caps_get_structure (caps, 0);
-
- if (!gst_structure_get_int (structure, "width", &meta->width) ||
- !gst_structure_get_int (structure, "height", &meta->height)) {
- GST_WARNING ("failed getting geometry from caps %" GST_PTR_FORMAT, caps);
- }
-
- GST_LOG_OBJECT (xvimagesink, "creating %dx%d", meta->width, meta->height);
-
- meta->im_format = gst_xvimagesink_get_format_from_caps (xvimagesink, caps);
- if (meta->im_format == -1) {
- GST_WARNING_OBJECT (xvimagesink, "failed to get format from caps %"
- GST_PTR_FORMAT, caps);
- GST_ELEMENT_ERROR (xvimagesink, RESOURCE, WRITE,
- ("Failed to create output image buffer of %dx%d pixels",
- meta->width, meta->height), ("Invalid input caps"));
- goto beach_unlocked;
- }
- meta->xvimagesink = gst_object_ref (xvimagesink);
-
- g_mutex_lock (xvimagesink->x_lock);
-
- /* Setting an error handler to catch failure */
- error_caught = FALSE;
- handler = XSetErrorHandler (gst_xvimagesink_handle_xerror);
-
-#ifdef HAVE_XSHM
- if (xvimagesink->xcontext->use_xshm) {
- int expected_size;
-
- meta->xvimage = XvShmCreateImage (xvimagesink->xcontext->disp,
- xvimagesink->xcontext->xv_port_id,
- meta->im_format, NULL, meta->width, meta->height, &meta->SHMInfo);
- if (!meta->xvimage || error_caught) {
- g_mutex_unlock (xvimagesink->x_lock);
- /* Reset error handler */
- error_caught = FALSE;
- XSetErrorHandler (handler);
- /* Push an error */
- GST_ELEMENT_ERROR (xvimagesink, RESOURCE, WRITE,
- ("Failed to create output image buffer of %dx%d pixels",
- meta->width, meta->height),
- ("could not XvShmCreateImage a %dx%d image",
- meta->width, meta->height));
- goto beach_unlocked;
- }
-
- /* we have to use the returned data_size for our shm size */
- meta->size = meta->xvimage->data_size;
- GST_LOG_OBJECT (xvimagesink, "XShm image size is %" G_GSIZE_FORMAT,
- meta->size);
-
- /* calculate the expected size. This is only for sanity checking the
- * number we get from X. */
- switch (meta->im_format) {
- case GST_MAKE_FOURCC ('I', '4', '2', '0'):
- case GST_MAKE_FOURCC ('Y', 'V', '1', '2'):
- {
- gint pitches[3];
- gint offsets[3];
- guint plane;
-
- offsets[0] = 0;
- pitches[0] = GST_ROUND_UP_4 (meta->width);
- offsets[1] = offsets[0] + pitches[0] * GST_ROUND_UP_2 (meta->height);
- pitches[1] = GST_ROUND_UP_8 (meta->width) / 2;
- offsets[2] =
- offsets[1] + pitches[1] * GST_ROUND_UP_2 (meta->height) / 2;
- pitches[2] = GST_ROUND_UP_8 (pitches[0]) / 2;
-
- expected_size =
- offsets[2] + pitches[2] * GST_ROUND_UP_2 (meta->height) / 2;
-
- for (plane = 0; plane < meta->xvimage->num_planes; plane++) {
- GST_DEBUG_OBJECT (xvimagesink,
- "Plane %u has a expected pitch of %d bytes, " "offset of %d",
- plane, pitches[plane], offsets[plane]);
- }
- break;
- }
- case GST_MAKE_FOURCC ('Y', 'U', 'Y', '2'):
- case GST_MAKE_FOURCC ('U', 'Y', 'V', 'Y'):
- expected_size = meta->height * GST_ROUND_UP_4 (meta->width * 2);
- break;
- default:
- expected_size = 0;
- break;
- }
- if (expected_size != 0 && meta->size != expected_size) {
- GST_WARNING_OBJECT (xvimagesink,
- "unexpected XShm image size (got %" G_GSIZE_FORMAT ", expected %d)",
- meta->size, expected_size);
- }
-
- /* Be verbose about our XvImage stride */
- {
- guint plane;
-
- for (plane = 0; plane < meta->xvimage->num_planes; plane++) {
- GST_DEBUG_OBJECT (xvimagesink, "Plane %u has a pitch of %d bytes, "
- "offset of %d", plane, meta->xvimage->pitches[plane],
- meta->xvimage->offsets[plane]);
- }
- }
-
- meta->SHMInfo.shmid = shmget (IPC_PRIVATE, meta->size, IPC_CREAT | 0777);
- if (meta->SHMInfo.shmid == -1) {
- g_mutex_unlock (xvimagesink->x_lock);
- GST_ELEMENT_ERROR (xvimagesink, RESOURCE, WRITE,
- ("Failed to create output image buffer of %dx%d pixels",
- meta->width, meta->height),
- ("could not get shared memory of %" G_GSIZE_FORMAT " bytes",
- meta->size));
- goto beach_unlocked;
- }
-
- meta->SHMInfo.shmaddr = shmat (meta->SHMInfo.shmid, NULL, 0);
- if (meta->SHMInfo.shmaddr == ((void *) -1)) {
- g_mutex_unlock (xvimagesink->x_lock);
- GST_ELEMENT_ERROR (xvimagesink, RESOURCE, WRITE,
- ("Failed to create output image buffer of %dx%d pixels",
- meta->width, meta->height),
- ("Failed to shmat: %s", g_strerror (errno)));
- /* Clean up the shared memory segment */
- shmctl (meta->SHMInfo.shmid, IPC_RMID, NULL);
- goto beach_unlocked;
- }
-
- meta->xvimage->data = meta->SHMInfo.shmaddr;
- meta->SHMInfo.readOnly = FALSE;
-
- if (XShmAttach (xvimagesink->xcontext->disp, &meta->SHMInfo) == 0) {
- /* Clean up the shared memory segment */
- shmctl (meta->SHMInfo.shmid, IPC_RMID, NULL);
-
- g_mutex_unlock (xvimagesink->x_lock);
- GST_ELEMENT_ERROR (xvimagesink, RESOURCE, WRITE,
- ("Failed to create output image buffer of %dx%d pixels",
- meta->width, meta->height), ("Failed to XShmAttach"));
- goto beach_unlocked;
- }
-
- XSync (xvimagesink->xcontext->disp, FALSE);
-
- /* Delete the shared memory segment as soon as we everyone is attached.
- * This way, it will be deleted as soon as we detach later, and not
- * leaked if we crash. */
- shmctl (meta->SHMInfo.shmid, IPC_RMID, NULL);
-
- GST_DEBUG_OBJECT (xvimagesink, "XServer ShmAttached to 0x%x, id 0x%lx",
- meta->SHMInfo.shmid, meta->SHMInfo.shmseg);
- } else
-#endif /* HAVE_XSHM */
- {
- meta->xvimage = XvCreateImage (xvimagesink->xcontext->disp,
- xvimagesink->xcontext->xv_port_id,
- meta->im_format, NULL, meta->width, meta->height);
- if (!meta->xvimage || error_caught) {
- g_mutex_unlock (xvimagesink->x_lock);
- /* Reset error handler */
- error_caught = FALSE;
- XSetErrorHandler (handler);
- /* Push an error */
- GST_ELEMENT_ERROR (xvimagesink, RESOURCE, WRITE,
- ("Failed to create outputimage buffer of %dx%d pixels",
- meta->width, meta->height),
- ("could not XvCreateImage a %dx%d image", meta->width, meta->height));
- goto beach_unlocked;
- }
-
- /* we have to use the returned data_size for our image size */
- meta->size = meta->xvimage->data_size;
- meta->xvimage->data = g_malloc (meta->size);
-
- XSync (xvimagesink->xcontext->disp, FALSE);
- }
-
- /* Reset error handler */
- error_caught = FALSE;
- XSetErrorHandler (handler);
-
- succeeded = TRUE;
-
- gst_buffer_take_memory (buffer,
- gst_memory_new_wrapped (0, meta->xvimage->data, NULL,
- meta->size, 0, meta->size));
-
- g_mutex_unlock (xvimagesink->x_lock);
-
-beach_unlocked:
- if (!succeeded) {
- gst_xvimage_buffer_free (buffer);
- buffer = NULL;
- }
-
- return buffer;
-}
-
-/* This function destroys a GstXvImage handling XShm availability */
-static void
-gst_xvimagesink_xvimage_destroy (GstXvImageSink * xvimagesink,
- GstBuffer * xvimage)
-{
- GstMetaXvImage *data = NULL;
-
- GST_DEBUG_OBJECT (xvimage, "Destroying buffer");
-
- g_return_if_fail (xvimage != NULL);
- g_return_if_fail (GST_IS_XVIMAGESINK (xvimagesink));
-
- data = GST_META_XVIMAGE_GET (xvimage);
- g_return_if_fail (data != NULL);
-
- GST_OBJECT_LOCK (xvimagesink);
-
- /* If the destroyed image is the current one we destroy our reference too */
- if (xvimagesink->cur_image == xvimage)
- xvimagesink->cur_image = NULL;
-
- /* We might have some buffers destroyed after changing state to NULL */
- if (xvimagesink->xcontext == NULL) {
- GST_DEBUG_OBJECT (xvimagesink, "Destroying XvImage after Xcontext");
-#ifdef HAVE_XSHM
- /* Need to free the shared memory segment even if the x context
- * was already cleaned up */
- if (data->SHMInfo.shmaddr != ((void *) -1)) {
- shmdt (data->SHMInfo.shmaddr);
- }
-#endif
- goto beach;
- }
-
- g_mutex_lock (xvimagesink->x_lock);
-
-#ifdef HAVE_XSHM
- if (xvimagesink->xcontext->use_xshm) {
- if (data->SHMInfo.shmaddr != ((void *) -1)) {
- GST_DEBUG_OBJECT (xvimagesink, "XServer ShmDetaching from 0x%x id 0x%lx",
- data->SHMInfo.shmid, data->SHMInfo.shmseg);
- XShmDetach (xvimagesink->xcontext->disp, &data->SHMInfo);
- XSync (xvimagesink->xcontext->disp, FALSE);
-
- shmdt (data->SHMInfo.shmaddr);
- }
- if (data->xvimage)
- XFree (data->xvimage);
- } else
-#endif /* HAVE_XSHM */
- {
- if (data->xvimage) {
- if (data->xvimage->data) {
- g_free (data->xvimage->data);
- }
- XFree (data->xvimage);
- }
- }
-
- XSync (xvimagesink->xcontext->disp, FALSE);
-
- g_mutex_unlock (xvimagesink->x_lock);
-
-beach:
- GST_OBJECT_UNLOCK (xvimagesink);
-
- data->xvimagesink = NULL;
- gst_object_unref (xvimagesink);
-
- return;
-}
/* We are called with the x_lock taken */
static void
@@ -742,7 +244,7 @@ gst_xvimagesink_xwindow_draw_borders (GstXvImageSink * xvimagesink,
static gboolean
gst_xvimagesink_xvimage_put (GstXvImageSink * xvimagesink, GstBuffer * xvimage)
{
- GstMetaXvImage *data;
+ GstMetaXvImage *meta;
GstVideoRectangle result;
gboolean draw_border = FALSE;
@@ -782,6 +284,8 @@ gst_xvimagesink_xvimage_put (GstXvImageSink * xvimagesink, GstBuffer * xvimage)
}
}
+ meta = gst_buffer_get_meta_xvimage (xvimage);
+
if (xvimagesink->keep_aspect) {
GstVideoRectangle src, dst;
@@ -806,23 +310,18 @@ gst_xvimagesink_xvimage_put (GstXvImageSink * xvimagesink, GstBuffer * xvimage)
result);
xvimagesink->redraw_border = FALSE;
}
-
- data = GST_META_XVIMAGE_GET (xvimage);
- g_assert (data != NULL);
-
- /* We scale to the window's geometry */
#ifdef HAVE_XSHM
if (xvimagesink->xcontext->use_xshm) {
GST_LOG_OBJECT (xvimagesink,
"XvShmPutImage with image %dx%d and window %dx%d, from xvimage %"
GST_PTR_FORMAT,
- data->width, data->height,
+ meta->width, meta->height,
xvimagesink->render_rect.w, xvimagesink->render_rect.h, xvimage);
XvShmPutImage (xvimagesink->xcontext->disp,
xvimagesink->xcontext->xv_port_id,
xvimagesink->xwindow->win,
- xvimagesink->xwindow->gc, data->xvimage,
+ xvimagesink->xwindow->gc, meta->xvimage,
xvimagesink->disp_x, xvimagesink->disp_y,
xvimagesink->disp_width, xvimagesink->disp_height,
result.x, result.y, result.w, result.h, FALSE);
@@ -832,7 +331,7 @@ gst_xvimagesink_xvimage_put (GstXvImageSink * xvimagesink, GstBuffer * xvimage)
XvPutImage (xvimagesink->xcontext->disp,
xvimagesink->xcontext->xv_port_id,
xvimagesink->xwindow->win,
- xvimagesink->xwindow->gc, data->xvimage,
+ xvimagesink->xwindow->gc, meta->xvimage,
xvimagesink->disp_x, xvimagesink->disp_y,
xvimagesink->disp_width, xvimagesink->disp_height,
result.x, result.y, result.w, result.h);
@@ -1176,6 +675,7 @@ gst_xvimagesink_handle_xevents (GstXvImageSink * xvimagesink)
g_mutex_lock (xvimagesink->flow_lock);
g_mutex_lock (xvimagesink->x_lock);
}
+
if (pointer_moved) {
g_mutex_unlock (xvimagesink->x_lock);
g_mutex_unlock (xvimagesink->flow_lock);
@@ -1241,7 +741,8 @@ gst_xvimagesink_handle_xevents (GstXvImageSink * xvimagesink)
}
break;
default:
- GST_DEBUG ("xvimagesink unhandled X event (%d)", e.type);
+ GST_DEBUG_OBJECT (xvimagesink, "xvimagesink unhandled X event (%d)",
+ e.type);
}
g_mutex_lock (xvimagesink->flow_lock);
g_mutex_lock (xvimagesink->x_lock);
@@ -1824,18 +1325,10 @@ gst_xvimagesink_xcontext_get (GstXvImageSink * xvimagesink)
xcontext->caps = gst_xvimagesink_get_xv_support (xvimagesink, xcontext);
- if (!xcontext->caps) {
- XCloseDisplay (xcontext->disp);
- g_mutex_unlock (xvimagesink->x_lock);
- g_free (xcontext->par);
- g_free (xcontext);
- /* GST_ELEMENT_ERROR is thrown by gst_xvimagesink_get_xv_support */
- return NULL;
- }
-#ifdef HAVE_XSHM
/* Search for XShm extension support */
+#ifdef HAVE_XSHM
if (XShmQueryExtension (xcontext->disp) &&
- gst_xvimagesink_check_xshm_calls (xcontext)) {
+ gst_xvimagesink_check_xshm_calls (xvimagesink, xcontext)) {
xcontext->use_xshm = TRUE;
GST_DEBUG ("xvimagesink is using XShm extension");
} else
@@ -1845,6 +1338,15 @@ gst_xvimagesink_xcontext_get (GstXvImageSink * xvimagesink)
GST_DEBUG ("xvimagesink is not using XShm extension");
}
+ if (!xcontext->caps) {
+ XCloseDisplay (xcontext->disp);
+ g_mutex_unlock (xvimagesink->x_lock);
+ g_free (xcontext->par);
+ g_free (xcontext);
+ /* GST_ELEMENT_ERROR is thrown by gst_xvimagesink_get_xv_support */
+ return NULL;
+ }
+
xv_attr = XvQueryPortAttributes (xcontext->disp,
xcontext->xv_port_id, &N_attr);
@@ -1981,50 +1483,8 @@ gst_xvimagesink_xcontext_clear (GstXvImageSink * xvimagesink)
g_free (xcontext);
}
-static void
-gst_xvimagesink_imagepool_clear (GstXvImageSink * xvimagesink)
-{
- g_mutex_lock (xvimagesink->pool_lock);
-
- while (xvimagesink->image_pool) {
- GstBuffer *xvimage = xvimagesink->image_pool->data;
-
- xvimagesink->image_pool = g_slist_delete_link (xvimagesink->image_pool,
- xvimagesink->image_pool);
- gst_xvimage_buffer_free (xvimage);
- }
-
- g_mutex_unlock (xvimagesink->pool_lock);
-}
-
/* Element stuff */
-/* 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_format_from_caps (GstXvImageSink * xvimagesink,
- GstCaps * caps)
-{
- GList *list = NULL;
-
- g_return_val_if_fail (GST_IS_XVIMAGESINK (xvimagesink), 0);
-
- list = xvimagesink->xcontext->formats_list;
-
- while (list) {
- GstXvImageFormat *format = list->data;
-
- if (format) {
- if (gst_caps_can_intersect (caps, format->caps)) {
- return format->format;
- }
- }
- list = g_list_next (list);
- }
-
- return -1;
-}
-
static GstCaps *
gst_xvimagesink_getcaps (GstBaseSink * bsink)
{
@@ -2045,8 +1505,9 @@ gst_xvimagesink_setcaps (GstBaseSink * bsink, GstCaps * caps)
{
GstXvImageSink *xvimagesink;
GstStructure *structure;
- guint32 im_format = 0;
+ GstBufferPool *newpool, *oldpool;
gboolean ret;
+ guint32 im_format = 0;
gint video_width, video_height;
gint disp_x, disp_y;
gint disp_width, disp_height;
@@ -2184,22 +1645,26 @@ gst_xvimagesink_setcaps (GstBaseSink * bsink, GstCaps * caps)
* doesn't cover the same area */
xvimagesink->redraw_border = TRUE;
- /* We renew our xvimage only if size or format changed;
- * the xvimage is the same size as the video pixel size */
- if ((xvimagesink->xvimage)) {
- GstMetaXvImage *data = GST_META_XVIMAGE_GET (xvimagesink->xvimage);
+ /* create a new pool for the new configuration */
+ newpool = gst_xvimage_buffer_pool_new (xvimagesink);
- if (((im_format != data->im_format) ||
- (video_width != data->width) || (video_height != data->height))) {
- GST_DEBUG_OBJECT (xvimagesink,
- "old format %" GST_FOURCC_FORMAT ", new format %" GST_FOURCC_FORMAT,
- GST_FOURCC_ARGS (data->im_format), GST_FOURCC_ARGS (im_format));
- GST_DEBUG_OBJECT (xvimagesink, "renewing xvimage");
- gst_buffer_unref (xvimagesink->xvimage);
- xvimagesink->xvimage = NULL;
- }
- }
+ structure = gst_buffer_pool_get_config (newpool);
+ gst_buffer_pool_config_set (structure, caps, 0, 0, 0, 0, 0, 16);
+ if (!gst_buffer_pool_set_config (newpool, structure))
+ goto config_failed;
+
+ if (!gst_buffer_pool_set_active (newpool, TRUE))
+ goto activate_failed;
+
+ oldpool = xvimagesink->pool;
+ xvimagesink->pool = newpool;
+ /* unref the old sink */
+ if (oldpool) {
+ /* deactivate */
+ gst_buffer_pool_set_active (oldpool, FALSE);
+ gst_object_unref (oldpool);
+ }
g_mutex_unlock (xvimagesink->flow_lock);
return TRUE;
@@ -2234,6 +1699,18 @@ no_display_size:
("Error calculating the output display ratio of the video."));
return FALSE;
}
+config_failed:
+ {
+ GST_ERROR_OBJECT (xvimagesink, "failed to set config.");
+ g_mutex_unlock (xvimagesink->flow_lock);
+ return FALSE;
+ }
+activate_failed:
+ {
+ GST_ERROR_OBJECT (xvimagesink, "failed to activate bufferpool.");
+ g_mutex_unlock (xvimagesink->flow_lock);
+ return FALSE;
+ }
}
static GstStateChangeReturn
@@ -2272,16 +1749,10 @@ gst_xvimagesink_change_state (GstElement * element, GstStateChange transition)
gst_xvimagesink_manage_event_thread (xvimagesink);
break;
case GST_STATE_CHANGE_READY_TO_PAUSED:
- g_mutex_lock (xvimagesink->pool_lock);
- xvimagesink->pool_invalid = FALSE;
- g_mutex_unlock (xvimagesink->pool_lock);
break;
case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
break;
case GST_STATE_CHANGE_PAUSED_TO_READY:
- g_mutex_lock (xvimagesink->pool_lock);
- xvimagesink->pool_invalid = TRUE;
- g_mutex_unlock (xvimagesink->pool_lock);
break;
default:
break;
@@ -2297,6 +1768,9 @@ gst_xvimagesink_change_state (GstElement * element, GstStateChange transition)
xvimagesink->fps_d = 1;
GST_VIDEO_SINK_WIDTH (xvimagesink) = 0;
GST_VIDEO_SINK_HEIGHT (xvimagesink) = 0;
+ g_mutex_lock (xvimagesink->flow_lock);
+ gst_buffer_pool_set_active (xvimagesink->pool, FALSE);
+ g_mutex_lock (xvimagesink->flow_lock);
break;
case GST_STATE_CHANGE_READY_TO_NULL:
gst_xvimagesink_reset (xvimagesink);
@@ -2333,20 +1807,21 @@ gst_xvimagesink_get_times (GstBaseSink * bsink, GstBuffer * buf,
static GstFlowReturn
gst_xvimagesink_show_frame (GstVideoSink * vsink, GstBuffer * buf)
{
+ GstFlowReturn res;
GstXvImageSink *xvimagesink;
GstMetaXvImage *meta;
xvimagesink = GST_XVIMAGESINK (vsink);
- meta = GST_META_XVIMAGE_GET (buf);
+ meta = gst_buffer_get_meta_xvimage (buf);
if (meta) {
/* If this buffer has been allocated using our buffer management we simply
put the ximage which is in the PRIVATE pointer */
- GST_LOG_OBJECT (xvimagesink, "fast put of bufferpool buffer %p", buf);
- if (!gst_xvimagesink_xvimage_put (xvimagesink, buf))
- goto no_window;
+ GST_LOG_OBJECT (xvimagesink, "buffer from our pool, writing directly");
+ res = GST_FLOW_OK;
} else {
+ GstBuffer *temp;
guint8 *data;
gsize size;
@@ -2354,36 +1829,51 @@ gst_xvimagesink_show_frame (GstVideoSink * vsink, GstBuffer * buf)
"slow copy into bufferpool buffer %p", buf);
/* Else we have to copy the data into our private image, */
/* if we have one... */
- if (!xvimagesink->xvimage) {
- GST_DEBUG_OBJECT (xvimagesink, "creating our xvimage");
+ GST_LOG_OBJECT (xvimagesink, "buffer not from our pool, copying");
- xvimagesink->xvimage = gst_xvimagesink_xvimage_new (xvimagesink,
- GST_BUFFER_CAPS (buf));
+ /* we should have a pool, configured in setcaps */
+ if (xvimagesink->pool == NULL)
+ goto no_pool;
- if (!xvimagesink->xvimage)
- /* The create method should have posted an informative error */
- goto no_image;
+ /* take a buffer form our pool */
+ res = gst_buffer_pool_acquire_buffer (xvimagesink->pool, &temp, NULL);
+ if (res != GST_FLOW_OK)
+ goto no_buffer;
- if (gst_buffer_get_size (xvimagesink->xvimage) <
- gst_buffer_get_size (buf))
- goto wrong_size;
- }
+ if (gst_buffer_get_size (temp) < gst_buffer_get_size (buf))
+ goto wrong_size;
- data = gst_buffer_map (xvimagesink->xvimage, &size, NULL, GST_MAP_WRITE);
+ data = gst_buffer_map (temp, &size, NULL, GST_MAP_WRITE);
gst_buffer_extract (buf, 0, data, size);
- gst_buffer_unmap (xvimagesink->xvimage, data, size);
+ gst_buffer_unmap (temp, data, size);
- if (!gst_xvimagesink_xvimage_put (xvimagesink, xvimagesink->xvimage))
- goto no_window;
+ buf = temp;
}
- return GST_FLOW_OK;
+ if (!gst_xvimagesink_xvimage_put (xvimagesink, buf))
+ goto no_window;
+
+ return res;
/* ERRORS */
-no_image:
+no_pool:
+ {
+ GST_ELEMENT_ERROR (xvimagesink, RESOURCE, WRITE,
+ ("Internal error: can't allocate images"),
+ ("We don't have a bufferpool negotiated"));
+ return GST_FLOW_ERROR;
+ }
+no_buffer:
{
/* No image available. That's very bad ! */
GST_WARNING_OBJECT (xvimagesink, "could not create image");
+ return res;
+ }
+wrong_size:
+ {
+ GST_ELEMENT_ERROR (xvimagesink, RESOURCE, WRITE,
+ ("Failed to create output image buffer"),
+ ("XServer allocated buffer size did not match input buffer"));
return GST_FLOW_ERROR;
}
no_window:
@@ -2392,19 +1882,6 @@ no_window:
GST_WARNING_OBJECT (xvimagesink, "could not output image - no window");
return GST_FLOW_ERROR;
}
-wrong_size:
- {
- meta = GST_META_XVIMAGE_GET (xvimagesink->xvimage);
-
- GST_ELEMENT_ERROR (xvimagesink, RESOURCE, WRITE,
- ("Failed to create output image buffer of %dx%d pixels",
- meta->width, meta->height),
- ("XServer allocated buffer size did not match input buffer"));
-
- gst_xvimagesink_xvimage_destroy (xvimagesink, xvimagesink->xvimage);
- xvimagesink->xvimage = NULL;
- goto no_image;
- }
}
static gboolean
@@ -2491,20 +1968,15 @@ static GstFlowReturn
gst_xvimagesink_buffer_alloc (GstBaseSink * bsink, guint64 offset, guint size,
GstCaps * caps, GstBuffer ** buf)
{
- GstFlowReturn ret = GST_FLOW_OK;
GstXvImageSink *xvimagesink;
GstBuffer *xvimage = NULL;
- GstMetaXvImage *meta = NULL;
- GstCaps *intersection = NULL;
GstStructure *structure = NULL;
+ GstFlowReturn ret = GST_FLOW_OK;
+ GstCaps *intersection = NULL;
gint width, height, image_format;
xvimagesink = GST_XVIMAGESINK (bsink);
- g_mutex_lock (xvimagesink->pool_lock);
- if (G_UNLIKELY (xvimagesink->pool_invalid))
- goto invalid;
-
if (G_LIKELY (xvimagesink->xcontext->last_caps &&
gst_caps_is_equal (caps, xvimagesink->xcontext->last_caps))) {
GST_LOG_OBJECT (xvimagesink,
@@ -2622,38 +2094,22 @@ gst_xvimagesink_buffer_alloc (GstBaseSink * bsink, guint64 offset, guint size,
reuse_last_caps:
- /* Walking through the pool cleaning unusable images and searching for a
- suitable one */
- while (xvimagesink->image_pool) {
- xvimage = xvimagesink->image_pool->data;
-
- if (xvimage) {
- meta = GST_META_XVIMAGE_GET (xvimage);
-
- /* Removing from the pool */
- xvimagesink->image_pool = g_slist_delete_link (xvimagesink->image_pool,
- xvimagesink->image_pool);
+ if (gst_caps_is_equal (GST_PAD_CAPS (bsink->sinkpad), caps)) {
+ /* we negotiated this format before, use the pool */
+ if (xvimagesink->pool) {
+ GstBuffer *tmp;
- /* We check for geometry or image format changes */
- if ((meta->width != width) ||
- (meta->height != height) || (meta->im_format != image_format)) {
- /* This image is unusable. Destroying... */
- gst_xvimage_buffer_free (xvimage);
- xvimage = NULL;
- } else {
- /* We found a suitable image */
- GST_LOG_OBJECT (xvimagesink, "found usable image in pool");
- break;
- }
+ GST_LOG_OBJECT (xvimagesink, "retrieving buffer from pool");
+ ret = gst_buffer_pool_acquire_buffer (xvimagesink->pool, &tmp, NULL);
+ xvimage = tmp;
}
}
- 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, intersection);
+ if (xvimage == NULL) {
+ /* Something new make a new image a new one */
+ GST_LOG_OBJECT (xvimagesink, "allocating new image");
+ xvimage = gst_xvimage_buffer_new (xvimagesink, width, height, image_format);
}
- g_mutex_unlock (xvimagesink->pool_lock);
if (xvimage) {
/* Make sure the buffer is cleared of any previously used flags */
@@ -2675,7 +2131,6 @@ invalid:
{
GST_DEBUG_OBJECT (xvimagesink, "the pool is flushing");
ret = GST_FLOW_WRONG_STATE;
- g_mutex_unlock (xvimagesink->pool_lock);
goto beach;
}
incompatible:
@@ -2685,7 +2140,6 @@ incompatible:
" are completely incompatible with those caps", caps,
xvimagesink->xcontext->caps);
ret = GST_FLOW_NOT_NEGOTIATED;
- g_mutex_unlock (xvimagesink->pool_lock);
goto beach;
}
invalid_caps:
@@ -2693,7 +2147,6 @@ invalid_caps:
GST_WARNING_OBJECT (xvimagesink, "invalid caps for buffer allocation %"
GST_PTR_FORMAT, intersection);
ret = GST_FLOW_NOT_NEGOTIATED;
- g_mutex_unlock (xvimagesink->pool_lock);
goto beach;
}
}
@@ -2810,15 +2263,6 @@ gst_xvimagesink_set_window_handle (GstXOverlay * overlay, guintptr id)
gst_xvimagesink_update_colorbalance (xvimagesink);
- /* Clear image pool as the images are unusable anyway */
- gst_xvimagesink_imagepool_clear (xvimagesink);
-
- /* Clear the xvimage */
- if (xvimagesink->xvimage) {
- gst_xvimage_buffer_free (xvimagesink->xvimage);
- xvimagesink->xvimage = NULL;
- }
-
/* If a window is there already we destroy it */
if (xvimagesink->xwindow) {
gst_xvimagesink_xwindow_destroy (xvimagesink, xvimagesink->xwindow);
@@ -3382,32 +2826,28 @@ gst_xvimagesink_reset (GstXvImageSink * xvimagesink)
xvimagesink->event_thread = NULL;
GST_OBJECT_UNLOCK (xvimagesink);
- /* invalidate the pool, current allocations continue, new buffer_alloc fails
- * with wrong_state */
- g_mutex_lock (xvimagesink->pool_lock);
- xvimagesink->pool_invalid = TRUE;
- g_mutex_unlock (xvimagesink->pool_lock);
-
/* Wait for our event thread to finish before we clean up our stuff. */
if (thread)
g_thread_join (thread);
if (xvimagesink->cur_image) {
- gst_buffer_unref (GST_BUFFER_CAST (xvimagesink->cur_image));
+ gst_buffer_unref (xvimagesink->cur_image);
xvimagesink->cur_image = NULL;
}
- if (xvimagesink->xvimage) {
- gst_buffer_unref (GST_BUFFER_CAST (xvimagesink->xvimage));
- xvimagesink->xvimage = NULL;
- }
- gst_xvimagesink_imagepool_clear (xvimagesink);
+ g_mutex_lock (xvimagesink->flow_lock);
+
+ if (xvimagesink->pool) {
+ gst_object_unref (xvimagesink->pool);
+ xvimagesink->pool = NULL;
+ }
if (xvimagesink->xwindow) {
gst_xvimagesink_xwindow_clear (xvimagesink, xvimagesink->xwindow);
gst_xvimagesink_xwindow_destroy (xvimagesink, xvimagesink->xwindow);
xvimagesink->xwindow = NULL;
}
+ g_mutex_unlock (xvimagesink->flow_lock);
xvimagesink->render_rect.x = xvimagesink->render_rect.y =
xvimagesink->render_rect.w = xvimagesink->render_rect.h = 0;
@@ -3445,10 +2885,6 @@ gst_xvimagesink_finalize (GObject * object)
g_mutex_free (xvimagesink->flow_lock);
xvimagesink->flow_lock = NULL;
}
- if (xvimagesink->pool_lock) {
- g_mutex_free (xvimagesink->pool_lock);
- xvimagesink->pool_lock = NULL;
- }
g_free (xvimagesink->media_title);
@@ -3462,7 +2898,6 @@ gst_xvimagesink_init (GstXvImageSink * xvimagesink)
xvimagesink->adaptor_no = 0;
xvimagesink->xcontext = NULL;
xvimagesink->xwindow = NULL;
- xvimagesink->xvimage = NULL;
xvimagesink->cur_image = NULL;
xvimagesink->hue = xvimagesink->saturation = 0;
@@ -3477,8 +2912,7 @@ gst_xvimagesink_init (GstXvImageSink * xvimagesink)
xvimagesink->x_lock = g_mutex_new ();
xvimagesink->flow_lock = g_mutex_new ();
- xvimagesink->image_pool = NULL;
- xvimagesink->pool_lock = g_mutex_new ();
+ xvimagesink->pool = NULL;
xvimagesink->synchronous = FALSE;
xvimagesink->double_buffer = TRUE;
@@ -3737,27 +3171,11 @@ gst_xvimagesink_get_type (void)
&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_pool_get_type ());
}
return xvimagesink_type;
}
-
-static gboolean
-plugin_init (GstPlugin * plugin)
-{
- if (!gst_element_register (plugin, "xvimagesink",
- GST_RANK_PRIMARY, GST_TYPE_XVIMAGESINK))
- return FALSE;
-
- GST_DEBUG_CATEGORY_INIT (gst_debug_xvimagesink, "xvimagesink", 0,
- "xvimagesink element");
- GST_DEBUG_CATEGORY_GET (GST_CAT_PERFORMANCE, "GST_PERFORMANCE");
-
- return TRUE;
-}
-
-GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
- GST_VERSION_MINOR,
- "xvimagesink",
- "XFree86 video output plugin using Xv extension",
- plugin_init, VERSION, GST_LICENSE, GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN)
diff --git a/sys/xvimage/xvimagesink.h b/sys/xvimage/xvimagesink.h
index 88c6e402a..5eb4e7030 100644
--- a/sys/xvimage/xvimagesink.h
+++ b/sys/xvimage/xvimagesink.h
@@ -43,7 +43,6 @@
#include <stdlib.h>
G_BEGIN_DECLS
-
#define GST_TYPE_XVIMAGESINK \
(gst_xvimagesink_get_type())
#define GST_XVIMAGESINK(obj) \
@@ -54,15 +53,15 @@ G_BEGIN_DECLS
(G_TYPE_CHECK_INSTANCE_TYPE((obj), GST_TYPE_XVIMAGESINK))
#define GST_IS_XVIMAGESINK_CLASS(klass) \
(G_TYPE_CHECK_CLASS_TYPE((klass), GST_TYPE_XVIMAGESINK))
-
typedef struct _GstXContext GstXContext;
typedef struct _GstXWindow GstXWindow;
typedef struct _GstXvImageFormat GstXvImageFormat;
-typedef struct _GstMetaXvImage GstMetaXvImage;
typedef struct _GstXvImageSink GstXvImageSink;
typedef struct _GstXvImageSinkClass GstXvImageSinkClass;
+#include "xvimagepool.h"
+
/*
* GstXContext:
* @disp: the X11 Display of this context
@@ -92,7 +91,8 @@ typedef struct _GstXvImageSinkClass GstXvImageSinkClass;
* Structure used to store various informations collected/calculated for a
* Display.
*/
-struct _GstXContext {
+struct _GstXContext
+{
Display *disp;
Screen *screen;
@@ -116,7 +116,7 @@ struct _GstXContext {
XvPortID xv_port_id;
guint nb_adaptors;
- gchar ** adaptors;
+ gchar **adaptors;
gint im_format;
GList *formats_list;
@@ -142,7 +142,8 @@ struct _GstXContext {
*
* Structure used to store informations about a Window.
*/
-struct _GstXWindow {
+struct _GstXWindow
+{
Window win;
gint width, height;
gboolean internal;
@@ -156,51 +157,18 @@ struct _GstXWindow {
*
* Structure storing image format to #GstCaps association.
*/
-struct _GstXvImageFormat {
+struct _GstXvImageFormat
+{
gint format;
GstCaps *caps;
};
-/**
- * GstXImageData:
- * @xvimagesink: a reference to our #GstXvImageSink
- * @xvimage: the XvImage of this buffer
- * @width: the width in pixels of XvImage @xvimage
- * @height: the height in pixels of XvImage @xvimage
- * @im_format: the image format of XvImage @xvimage
- * @size: the size in bytes of XvImage @xvimage
- *
- * Structure with additional information about an XvImage.
- */
-struct _GstMetaXvImage {
- GstMeta meta;
-
- /* Reference to the xvimagesink we belong to */
- GstXvImageSink *xvimagesink;
-
- XvImage *xvimage;
-
-#ifdef HAVE_XSHM
- XShmSegmentInfo SHMInfo;
-#endif /* HAVE_XSHM */
-
- gint width, height, im_format;
- size_t size;
-};
-
-const GstMetaInfo * gst_meta_xvimage_get_info (void);
-
-#define GST_META_XVIMAGE_GET(buf) ((GstMetaXvImage *)gst_buffer_get_meta(buf,gst_meta_xvimage_get_info()))
-#define GST_META_XVIMAGE_ADD(buf) ((GstMetaXvImage *)gst_buffer_add_meta(buf,gst_meta_xvimage_get_info(), NULL))
-
/**
* GstXvImageSink:
* @display_name: the name of the Display we want to render to
* @xcontext: our instance's #GstXContext
* @xwindow: the #GstXWindow we are rendering to
- * @xvimage: internal #GstXvImage used to store incoming buffers and render when
- * not using the buffer_alloc optimization mechanism
* @cur_image: a reference to the last #GstXvImage that was put to @xwindow. It
* is used when Expose events are received to redraw the latest video frame
* @event_thread: a thread listening for events on @xwindow and handling them
@@ -230,7 +198,8 @@ const GstMetaInfo * gst_meta_xvimage_get_info (void);
*
* The #GstXvImageSink data structure.
*/
-struct _GstXvImageSink {
+struct _GstXvImageSink
+{
/* Our element stuff */
GstVideoSink videosink;
@@ -255,9 +224,8 @@ struct _GstXvImageSink {
/* object-set pixel aspect ratio */
GValue *par;
- GMutex *pool_lock;
- gboolean pool_invalid;
- GSList *image_pool;
+ /* the buffer pool */
+ GstBufferPool *pool;
gboolean synchronous;
gboolean double_buffer;
@@ -282,14 +250,14 @@ struct _GstXvImageSink {
/* port attributes */
gboolean autopaint_colorkey;
gint colorkey;
-
+
gboolean draw_borders;
-
+
/* port features */
gboolean have_autopaint_colorkey;
gboolean have_colorkey;
gboolean have_double_buffer;
-
+
/* stream metadata */
gchar *media_title;
@@ -298,12 +266,12 @@ struct _GstXvImageSink {
gboolean have_render_rect;
};
-struct _GstXvImageSinkClass {
+struct _GstXvImageSinkClass
+{
GstVideoSinkClass parent_class;
};
-GType gst_xvimagesink_get_type(void);
+GType gst_xvimagesink_get_type (void);
G_END_DECLS
-
#endif /* __GST_XVIMAGESINK_H__ */