mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-04-26 06:54:49 +00:00
X11: port imagesinks to new miniobjects
Remove the subbuffer from X11 sinks and use the private pointer to store a single buffer metadata with the extra info.
This commit is contained in:
parent
03c710d6cd
commit
e78903e662
4 changed files with 360 additions and 433 deletions
|
@ -130,7 +130,7 @@ MotifWmHints, MwmHints;
|
||||||
|
|
||||||
static void gst_ximagesink_reset (GstXImageSink * ximagesink);
|
static void gst_ximagesink_reset (GstXImageSink * ximagesink);
|
||||||
static void gst_ximagesink_ximage_destroy (GstXImageSink * ximagesink,
|
static void gst_ximagesink_ximage_destroy (GstXImageSink * ximagesink,
|
||||||
GstXImageBuffer * ximage);
|
GstBuffer * ximage);
|
||||||
static void gst_ximagesink_xwindow_update_geometry (GstXImageSink * ximagesink);
|
static void gst_ximagesink_xwindow_update_geometry (GstXImageSink * ximagesink);
|
||||||
static void gst_ximagesink_expose (GstXOverlay * overlay);
|
static void gst_ximagesink_expose (GstXOverlay * overlay);
|
||||||
|
|
||||||
|
@ -165,36 +165,24 @@ static GstVideoSinkClass *parent_class = NULL;
|
||||||
/* ============================================================= */
|
/* ============================================================= */
|
||||||
|
|
||||||
/* ximage buffers */
|
/* ximage buffers */
|
||||||
|
#define GET_XDATA(buf) ((GstXImageData *) (GST_BUFFER_CAST(buf)->owner_priv))
|
||||||
|
|
||||||
static GstBufferClass *ximage_buffer_parent_class = NULL;
|
|
||||||
|
|
||||||
#define GST_TYPE_XIMAGE_BUFFER (gst_ximage_buffer_get_type())
|
|
||||||
|
|
||||||
#define GST_IS_XIMAGE_BUFFER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_XIMAGE_BUFFER))
|
|
||||||
#define GST_XIMAGE_BUFFER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_XIMAGE_BUFFER, GstXImageBuffer))
|
|
||||||
#define GST_XIMAGE_BUFFER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_XIMAGE_BUFFER, GstXImageBufferClass))
|
|
||||||
|
|
||||||
/* So some words about GstMiniObject, this is pretty messy...
|
|
||||||
GstMiniObject does not use the standard finalizing of GObjects, you are
|
|
||||||
supposed to call gst_buffer_unref that's going to call gst_mini_objec_unref
|
|
||||||
which will handle its own refcount system and call gst_mini_object_free.
|
|
||||||
gst_mini_object_free will call the class finalize method which is not the
|
|
||||||
one from GObject, after calling this finalize method it will free the object
|
|
||||||
instance for you if the refcount is still 0 so you should not chain up */
|
|
||||||
static void
|
static void
|
||||||
gst_ximage_buffer_finalize (GstXImageBuffer * ximage)
|
gst_ximage_buffer_dispose (GstBuffer * ximage)
|
||||||
{
|
{
|
||||||
|
GstXImageData *data = NULL;
|
||||||
GstXImageSink *ximagesink = NULL;
|
GstXImageSink *ximagesink = NULL;
|
||||||
gboolean recycled = FALSE;
|
gboolean recycled = FALSE;
|
||||||
gboolean running;
|
gboolean running;
|
||||||
|
|
||||||
g_return_if_fail (ximage != NULL);
|
data = GET_XDATA (ximage);
|
||||||
|
g_return_if_fail (data != NULL);
|
||||||
|
|
||||||
ximagesink = ximage->ximagesink;
|
ximagesink = data->ximagesink;
|
||||||
if (G_UNLIKELY (ximagesink == NULL)) {
|
if (G_UNLIKELY (ximagesink == NULL))
|
||||||
GST_WARNING_OBJECT (ximagesink, "no sink found");
|
goto no_sink;
|
||||||
goto beach;
|
|
||||||
}
|
g_return_if_fail (GST_IS_XIMAGESINK (ximagesink));
|
||||||
|
|
||||||
GST_OBJECT_LOCK (ximagesink);
|
GST_OBJECT_LOCK (ximagesink);
|
||||||
running = ximagesink->running;
|
running = ximagesink->running;
|
||||||
|
@ -205,84 +193,44 @@ gst_ximage_buffer_finalize (GstXImageBuffer * ximage)
|
||||||
GST_DEBUG_OBJECT (ximagesink,
|
GST_DEBUG_OBJECT (ximagesink,
|
||||||
"destroy image %p because the sink is shutting down", ximage);
|
"destroy image %p because the sink is shutting down", ximage);
|
||||||
gst_ximagesink_ximage_destroy (ximagesink, ximage);
|
gst_ximagesink_ximage_destroy (ximagesink, ximage);
|
||||||
} else if ((ximage->width != GST_VIDEO_SINK_WIDTH (ximagesink)) ||
|
} else if ((data->width != GST_VIDEO_SINK_WIDTH (ximagesink)) ||
|
||||||
(ximage->height != GST_VIDEO_SINK_HEIGHT (ximagesink))) {
|
(data->height != GST_VIDEO_SINK_HEIGHT (ximagesink))) {
|
||||||
/* If our geometry changed we can't reuse that image. */
|
/* If our geometry changed we can't reuse that image. */
|
||||||
GST_DEBUG_OBJECT (ximagesink,
|
GST_DEBUG_OBJECT (ximagesink,
|
||||||
"destroy image %p as its size changed %dx%d vs current %dx%d",
|
"destroy image %p as its size changed %dx%d vs current %dx%d",
|
||||||
ximage, ximage->width, ximage->height,
|
ximage, data->width, data->height,
|
||||||
GST_VIDEO_SINK_WIDTH (ximagesink), GST_VIDEO_SINK_HEIGHT (ximagesink));
|
GST_VIDEO_SINK_WIDTH (ximagesink), GST_VIDEO_SINK_HEIGHT (ximagesink));
|
||||||
gst_ximagesink_ximage_destroy (ximagesink, ximage);
|
gst_ximagesink_ximage_destroy (ximagesink, ximage);
|
||||||
} else {
|
} else {
|
||||||
/* In that case we can reuse the image and add it to our image pool. */
|
/* In that case we can reuse the image and add it to our image pool. */
|
||||||
GST_LOG_OBJECT (ximagesink, "recycling image %p in pool", ximage);
|
GST_LOG_OBJECT (ximagesink, "recycling image %p in pool", ximage);
|
||||||
/* need to increment the refcount again to recycle */
|
/* need to increment the refcount again to recycle */
|
||||||
gst_buffer_ref (GST_BUFFER_CAST (ximage));
|
gst_buffer_ref (ximage);
|
||||||
g_mutex_lock (ximagesink->pool_lock);
|
g_mutex_lock (ximagesink->pool_lock);
|
||||||
ximagesink->buffer_pool = g_slist_prepend (ximagesink->buffer_pool, ximage);
|
ximagesink->buffer_pool = g_slist_prepend (ximagesink->buffer_pool, ximage);
|
||||||
g_mutex_unlock (ximagesink->pool_lock);
|
g_mutex_unlock (ximagesink->pool_lock);
|
||||||
recycled = TRUE;
|
recycled = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!recycled)
|
|
||||||
GST_MINI_OBJECT_CLASS (ximage_buffer_parent_class)->finalize
|
|
||||||
(GST_MINI_OBJECT (ximage));
|
|
||||||
|
|
||||||
beach:
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
no_sink:
|
||||||
gst_ximage_buffer_free (GstXImageBuffer * ximage)
|
{
|
||||||
{
|
GST_WARNING ("no sink found");
|
||||||
/* make sure it is not recycled */
|
return;
|
||||||
ximage->width = -1;
|
|
||||||
ximage->height = -1;
|
|
||||||
gst_buffer_unref (GST_BUFFER_CAST (ximage));
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
gst_ximage_buffer_init (GstXImageBuffer * ximage_buffer, gpointer g_class)
|
|
||||||
{
|
|
||||||
#ifdef HAVE_XSHM
|
|
||||||
ximage_buffer->SHMInfo.shmaddr = ((void *) -1);
|
|
||||||
ximage_buffer->SHMInfo.shmid = -1;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
gst_ximage_buffer_class_init (gpointer g_class, gpointer class_data)
|
|
||||||
{
|
|
||||||
GstMiniObjectClass *mini_object_class = GST_MINI_OBJECT_CLASS (g_class);
|
|
||||||
|
|
||||||
ximage_buffer_parent_class = g_type_class_peek_parent (g_class);
|
|
||||||
|
|
||||||
mini_object_class->finalize = (GstMiniObjectFinalizeFunction)
|
|
||||||
gst_ximage_buffer_finalize;
|
|
||||||
}
|
|
||||||
|
|
||||||
static GType
|
|
||||||
gst_ximage_buffer_get_type (void)
|
|
||||||
{
|
|
||||||
static GType _gst_ximage_buffer_type;
|
|
||||||
|
|
||||||
if (G_UNLIKELY (_gst_ximage_buffer_type == 0)) {
|
|
||||||
static const GTypeInfo ximage_buffer_info = {
|
|
||||||
sizeof (GstBufferClass),
|
|
||||||
NULL,
|
|
||||||
NULL,
|
|
||||||
gst_ximage_buffer_class_init,
|
|
||||||
NULL,
|
|
||||||
NULL,
|
|
||||||
sizeof (GstXImageBuffer),
|
|
||||||
0,
|
|
||||||
(GInstanceInitFunc) gst_ximage_buffer_init,
|
|
||||||
NULL
|
|
||||||
};
|
|
||||||
_gst_ximage_buffer_type = g_type_register_static (GST_TYPE_BUFFER,
|
|
||||||
"GstXImageBuffer", &ximage_buffer_info, 0);
|
|
||||||
}
|
}
|
||||||
return _gst_ximage_buffer_type;
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_ximage_buffer_free (GstBuffer * ximage)
|
||||||
|
{
|
||||||
|
GstXImageData *data = GET_XDATA (ximage);
|
||||||
|
|
||||||
|
g_return_if_fail (data != NULL);
|
||||||
|
|
||||||
|
/* make sure it is not recycled */
|
||||||
|
data->width = -1;
|
||||||
|
data->height = -1;
|
||||||
|
gst_buffer_unref (ximage);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* X11 stuff */
|
/* X11 stuff */
|
||||||
|
@ -398,27 +346,37 @@ beach:
|
||||||
#endif /* HAVE_XSHM */
|
#endif /* HAVE_XSHM */
|
||||||
|
|
||||||
/* This function handles GstXImageBuffer creation depending on XShm availability */
|
/* This function handles GstXImageBuffer creation depending on XShm availability */
|
||||||
static GstXImageBuffer *
|
static GstBuffer *
|
||||||
gst_ximagesink_ximage_new (GstXImageSink * ximagesink, GstCaps * caps)
|
gst_ximagesink_ximage_new (GstXImageSink * ximagesink, GstCaps * caps)
|
||||||
{
|
{
|
||||||
GstXImageBuffer *ximage = NULL;
|
GstBuffer *buffer = NULL;
|
||||||
|
GstXImageData *data = NULL;
|
||||||
GstStructure *structure = NULL;
|
GstStructure *structure = NULL;
|
||||||
gboolean succeeded = FALSE;
|
gboolean succeeded = FALSE;
|
||||||
int (*handler) (Display *, XErrorEvent *);
|
int (*handler) (Display *, XErrorEvent *);
|
||||||
|
|
||||||
g_return_val_if_fail (GST_IS_XIMAGESINK (ximagesink), NULL);
|
g_return_val_if_fail (GST_IS_XIMAGESINK (ximagesink), NULL);
|
||||||
|
|
||||||
ximage = (GstXImageBuffer *) gst_mini_object_new (GST_TYPE_XIMAGE_BUFFER);
|
data = g_slice_new0 (GstXImageData);
|
||||||
|
#ifdef HAVE_XSHM
|
||||||
|
data->SHMInfo.shmaddr = ((void *) -1);
|
||||||
|
data->SHMInfo.shmid = -1;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
buffer = gst_buffer_new ();
|
||||||
|
GST_MINI_OBJECT_CAST (buffer)->dispose =
|
||||||
|
(GstMiniObjectDisposeFunction) gst_ximage_buffer_dispose;
|
||||||
|
buffer->owner_priv = data;
|
||||||
|
|
||||||
structure = gst_caps_get_structure (caps, 0);
|
structure = gst_caps_get_structure (caps, 0);
|
||||||
|
|
||||||
if (!gst_structure_get_int (structure, "width", &ximage->width) ||
|
if (!gst_structure_get_int (structure, "width", &data->width) ||
|
||||||
!gst_structure_get_int (structure, "height", &ximage->height)) {
|
!gst_structure_get_int (structure, "height", &data->height)) {
|
||||||
GST_WARNING ("failed getting geometry from caps %" GST_PTR_FORMAT, caps);
|
GST_WARNING ("failed getting geometry from caps %" GST_PTR_FORMAT, caps);
|
||||||
}
|
}
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (ximagesink, "creating image %p (%dx%d)", ximage,
|
GST_DEBUG_OBJECT (ximagesink, "creating image %p (%dx%d)", data,
|
||||||
ximage->width, ximage->height);
|
data->width, data->height);
|
||||||
|
|
||||||
g_mutex_lock (ximagesink->x_lock);
|
g_mutex_lock (ximagesink->x_lock);
|
||||||
|
|
||||||
|
@ -428,11 +386,11 @@ gst_ximagesink_ximage_new (GstXImageSink * ximagesink, GstCaps * caps)
|
||||||
|
|
||||||
#ifdef HAVE_XSHM
|
#ifdef HAVE_XSHM
|
||||||
if (ximagesink->xcontext->use_xshm) {
|
if (ximagesink->xcontext->use_xshm) {
|
||||||
ximage->ximage = XShmCreateImage (ximagesink->xcontext->disp,
|
data->ximage = XShmCreateImage (ximagesink->xcontext->disp,
|
||||||
ximagesink->xcontext->visual,
|
ximagesink->xcontext->visual,
|
||||||
ximagesink->xcontext->depth,
|
ximagesink->xcontext->depth,
|
||||||
ZPixmap, NULL, &ximage->SHMInfo, ximage->width, ximage->height);
|
ZPixmap, NULL, &data->SHMInfo, data->width, data->height);
|
||||||
if (!ximage->ximage || error_caught) {
|
if (!data->ximage || error_caught) {
|
||||||
g_mutex_unlock (ximagesink->x_lock);
|
g_mutex_unlock (ximagesink->x_lock);
|
||||||
/* Reset error handler */
|
/* Reset error handler */
|
||||||
error_caught = FALSE;
|
error_caught = FALSE;
|
||||||
|
@ -440,53 +398,52 @@ gst_ximagesink_ximage_new (GstXImageSink * ximagesink, GstCaps * caps)
|
||||||
/* Push an error */
|
/* Push an error */
|
||||||
GST_ELEMENT_ERROR (ximagesink, RESOURCE, WRITE,
|
GST_ELEMENT_ERROR (ximagesink, RESOURCE, WRITE,
|
||||||
("Failed to create output image buffer of %dx%d pixels",
|
("Failed to create output image buffer of %dx%d pixels",
|
||||||
ximage->width, ximage->height),
|
data->width, data->height),
|
||||||
("could not XShmCreateImage a %dx%d image",
|
("could not XShmCreateImage a %dx%d image",
|
||||||
ximage->width, ximage->height));
|
data->width, data->height));
|
||||||
goto beach;
|
goto beach;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* we have to use the returned bytes_per_line for our shm size */
|
/* we have to use the returned bytes_per_line for our shm size */
|
||||||
ximage->size = ximage->ximage->bytes_per_line * ximage->ximage->height;
|
data->size = data->ximage->bytes_per_line * data->ximage->height;
|
||||||
GST_LOG_OBJECT (ximagesink,
|
GST_LOG_OBJECT (ximagesink,
|
||||||
"XShm image size is %" G_GSIZE_FORMAT ", width %d, stride %d",
|
"XShm image size is %" G_GSIZE_FORMAT ", width %d, stride %d",
|
||||||
ximage->size, ximage->width, ximage->ximage->bytes_per_line);
|
data->size, data->width, data->ximage->bytes_per_line);
|
||||||
|
|
||||||
ximage->SHMInfo.shmid = shmget (IPC_PRIVATE, ximage->size,
|
data->SHMInfo.shmid = shmget (IPC_PRIVATE, data->size, IPC_CREAT | 0777);
|
||||||
IPC_CREAT | 0777);
|
if (data->SHMInfo.shmid == -1) {
|
||||||
if (ximage->SHMInfo.shmid == -1) {
|
|
||||||
g_mutex_unlock (ximagesink->x_lock);
|
g_mutex_unlock (ximagesink->x_lock);
|
||||||
GST_ELEMENT_ERROR (ximagesink, RESOURCE, WRITE,
|
GST_ELEMENT_ERROR (ximagesink, RESOURCE, WRITE,
|
||||||
("Failed to create output image buffer of %dx%d pixels",
|
("Failed to create output image buffer of %dx%d pixels",
|
||||||
ximage->width, ximage->height),
|
data->width, data->height),
|
||||||
("could not get shared memory of %" G_GSIZE_FORMAT " bytes",
|
("could not get shared memory of %" G_GSIZE_FORMAT " bytes",
|
||||||
ximage->size));
|
data->size));
|
||||||
goto beach;
|
goto beach;
|
||||||
}
|
}
|
||||||
|
|
||||||
ximage->SHMInfo.shmaddr = shmat (ximage->SHMInfo.shmid, NULL, 0);
|
data->SHMInfo.shmaddr = shmat (data->SHMInfo.shmid, NULL, 0);
|
||||||
if (ximage->SHMInfo.shmaddr == ((void *) -1)) {
|
if (data->SHMInfo.shmaddr == ((void *) -1)) {
|
||||||
g_mutex_unlock (ximagesink->x_lock);
|
g_mutex_unlock (ximagesink->x_lock);
|
||||||
GST_ELEMENT_ERROR (ximagesink, RESOURCE, WRITE,
|
GST_ELEMENT_ERROR (ximagesink, RESOURCE, WRITE,
|
||||||
("Failed to create output image buffer of %dx%d pixels",
|
("Failed to create output image buffer of %dx%d pixels",
|
||||||
ximage->width, ximage->height),
|
data->width, data->height),
|
||||||
("Failed to shmat: %s", g_strerror (errno)));
|
("Failed to shmat: %s", g_strerror (errno)));
|
||||||
/* Clean up the shared memory segment */
|
/* Clean up the shared memory segment */
|
||||||
shmctl (ximage->SHMInfo.shmid, IPC_RMID, NULL);
|
shmctl (data->SHMInfo.shmid, IPC_RMID, NULL);
|
||||||
goto beach;
|
goto beach;
|
||||||
}
|
}
|
||||||
|
|
||||||
ximage->ximage->data = ximage->SHMInfo.shmaddr;
|
data->ximage->data = data->SHMInfo.shmaddr;
|
||||||
ximage->SHMInfo.readOnly = FALSE;
|
data->SHMInfo.readOnly = FALSE;
|
||||||
|
|
||||||
if (XShmAttach (ximagesink->xcontext->disp, &ximage->SHMInfo) == 0) {
|
if (XShmAttach (ximagesink->xcontext->disp, &data->SHMInfo) == 0) {
|
||||||
/* Clean up shm seg */
|
/* Clean up shm seg */
|
||||||
shmctl (ximage->SHMInfo.shmid, IPC_RMID, NULL);
|
shmctl (data->SHMInfo.shmid, IPC_RMID, NULL);
|
||||||
|
|
||||||
g_mutex_unlock (ximagesink->x_lock);
|
g_mutex_unlock (ximagesink->x_lock);
|
||||||
GST_ELEMENT_ERROR (ximagesink, RESOURCE, WRITE,
|
GST_ELEMENT_ERROR (ximagesink, RESOURCE, WRITE,
|
||||||
("Failed to create output image buffer of %dx%d pixels",
|
("Failed to create output image buffer of %dx%d pixels",
|
||||||
ximage->width, ximage->height), ("Failed to XShmAttach"));
|
data->width, data->height), ("Failed to XShmAttach"));
|
||||||
goto beach;
|
goto beach;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -495,19 +452,19 @@ gst_ximagesink_ximage_new (GstXImageSink * ximagesink, GstCaps * caps)
|
||||||
/* Now that everyone has attached, we can delete the shared memory segment.
|
/* Now that everyone has attached, we can delete the shared memory segment.
|
||||||
* This way, it will be deleted as soon as we detach later, and not
|
* This way, it will be deleted as soon as we detach later, and not
|
||||||
* leaked if we crash. */
|
* leaked if we crash. */
|
||||||
shmctl (ximage->SHMInfo.shmid, IPC_RMID, NULL);
|
shmctl (data->SHMInfo.shmid, IPC_RMID, NULL);
|
||||||
|
|
||||||
} else
|
} else
|
||||||
#endif /* HAVE_XSHM */
|
#endif /* HAVE_XSHM */
|
||||||
{
|
{
|
||||||
guint allocsize;
|
guint allocsize;
|
||||||
|
|
||||||
ximage->ximage = XCreateImage (ximagesink->xcontext->disp,
|
data->ximage = XCreateImage (ximagesink->xcontext->disp,
|
||||||
ximagesink->xcontext->visual,
|
ximagesink->xcontext->visual,
|
||||||
ximagesink->xcontext->depth,
|
ximagesink->xcontext->depth,
|
||||||
ZPixmap, 0, NULL,
|
ZPixmap, 0, NULL,
|
||||||
ximage->width, ximage->height, ximagesink->xcontext->bpp, 0);
|
data->width, data->height, ximagesink->xcontext->bpp, 0);
|
||||||
if (!ximage->ximage || error_caught) {
|
if (!data->ximage || error_caught) {
|
||||||
g_mutex_unlock (ximagesink->x_lock);
|
g_mutex_unlock (ximagesink->x_lock);
|
||||||
/* Reset error handler */
|
/* Reset error handler */
|
||||||
error_caught = FALSE;
|
error_caught = FALSE;
|
||||||
|
@ -515,33 +472,31 @@ gst_ximagesink_ximage_new (GstXImageSink * ximagesink, GstCaps * caps)
|
||||||
/* Push an error */
|
/* Push an error */
|
||||||
GST_ELEMENT_ERROR (ximagesink, RESOURCE, WRITE,
|
GST_ELEMENT_ERROR (ximagesink, RESOURCE, WRITE,
|
||||||
("Failed to create output image buffer of %dx%d pixels",
|
("Failed to create output image buffer of %dx%d pixels",
|
||||||
ximage->width, ximage->height),
|
data->width, data->height),
|
||||||
("could not XCreateImage a %dx%d image",
|
("could not XCreateImage a %dx%d image", data->width, data->height));
|
||||||
ximage->width, ximage->height));
|
|
||||||
goto beach;
|
goto beach;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* upstream will assume that rowstrides are multiples of 4, but this
|
/* upstream will assume that rowstrides are multiples of 4, but this
|
||||||
* doesn't always seem to be the case with XCreateImage() */
|
* doesn't always seem to be the case with XCreateImage() */
|
||||||
if ((ximage->ximage->bytes_per_line % 4) != 0) {
|
if ((data->ximage->bytes_per_line % 4) != 0) {
|
||||||
GST_WARNING_OBJECT (ximagesink, "returned stride not a multiple of 4 as "
|
GST_WARNING_OBJECT (ximagesink, "returned stride not a multiple of 4 as "
|
||||||
"usually assumed");
|
"usually assumed");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* we have to use the returned bytes_per_line for our image size */
|
/* we have to use the returned bytes_per_line for our image size */
|
||||||
ximage->size = ximage->ximage->bytes_per_line * ximage->ximage->height;
|
data->size = data->ximage->bytes_per_line * data->ximage->height;
|
||||||
|
|
||||||
/* alloc a bit more for unexpected strides to avoid crashes upstream.
|
/* alloc a bit more for unexpected strides to avoid crashes upstream.
|
||||||
* FIXME: if we get an unrounded stride, the image will be displayed
|
* FIXME: if we get an unrounded stride, the image will be displayed
|
||||||
* distorted, since all upstream elements assume a rounded stride */
|
* distorted, since all upstream elements assume a rounded stride */
|
||||||
allocsize =
|
allocsize =
|
||||||
GST_ROUND_UP_4 (ximage->ximage->bytes_per_line) *
|
GST_ROUND_UP_4 (data->ximage->bytes_per_line) * data->ximage->height;
|
||||||
ximage->ximage->height;
|
data->ximage->data = g_malloc (allocsize);
|
||||||
ximage->ximage->data = g_malloc (allocsize);
|
|
||||||
GST_LOG_OBJECT (ximagesink,
|
GST_LOG_OBJECT (ximagesink,
|
||||||
"non-XShm image size is %" G_GSIZE_FORMAT " (alloced: %u), width %d, "
|
"non-XShm image size is %" G_GSIZE_FORMAT " (alloced: %u), width %d, "
|
||||||
"stride %d", ximage->size, allocsize, ximage->width,
|
"stride %d", data->size, allocsize, data->width,
|
||||||
ximage->ximage->bytes_per_line);
|
data->ximage->bytes_per_line);
|
||||||
|
|
||||||
XSync (ximagesink->xcontext->disp, FALSE);
|
XSync (ximagesink->xcontext->disp, FALSE);
|
||||||
}
|
}
|
||||||
|
@ -552,30 +507,35 @@ gst_ximagesink_ximage_new (GstXImageSink * ximagesink, GstCaps * caps)
|
||||||
|
|
||||||
succeeded = TRUE;
|
succeeded = TRUE;
|
||||||
|
|
||||||
GST_BUFFER_DATA (ximage) = (guchar *) ximage->ximage->data;
|
|
||||||
GST_BUFFER_SIZE (ximage) = ximage->size;
|
|
||||||
|
|
||||||
/* Keep a ref to our sink */
|
/* Keep a ref to our sink */
|
||||||
ximage->ximagesink = gst_object_ref (ximagesink);
|
data->ximagesink = gst_object_ref (ximagesink);
|
||||||
|
|
||||||
|
GST_BUFFER_DATA (buffer) = (guchar *) data->ximage->data;
|
||||||
|
GST_BUFFER_SIZE (buffer) = data->size;
|
||||||
|
|
||||||
g_mutex_unlock (ximagesink->x_lock);
|
g_mutex_unlock (ximagesink->x_lock);
|
||||||
|
|
||||||
beach:
|
beach:
|
||||||
if (!succeeded) {
|
if (!succeeded) {
|
||||||
gst_ximage_buffer_free (ximage);
|
gst_ximage_buffer_free (buffer);
|
||||||
ximage = NULL;
|
buffer = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ximage;
|
return buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This function destroys a GstXImageBuffer handling XShm availability */
|
/* This function destroys a GstBuffer with GstXImageData handling XShm availability */
|
||||||
static void
|
static void
|
||||||
gst_ximagesink_ximage_destroy (GstXImageSink * ximagesink,
|
gst_ximagesink_ximage_destroy (GstXImageSink * ximagesink, GstBuffer * ximage)
|
||||||
GstXImageBuffer * ximage)
|
|
||||||
{
|
{
|
||||||
|
GstXImageData *data;
|
||||||
|
|
||||||
g_return_if_fail (ximage != NULL);
|
g_return_if_fail (ximage != NULL);
|
||||||
g_return_if_fail (GST_IS_XIMAGESINK (ximagesink));
|
g_return_if_fail (GST_IS_XIMAGESINK (ximagesink));
|
||||||
|
|
||||||
|
data = GET_XDATA (ximage);
|
||||||
|
g_return_if_fail (data != NULL);
|
||||||
|
|
||||||
/* Hold the object lock to ensure the XContext doesn't disappear */
|
/* Hold the object lock to ensure the XContext doesn't disappear */
|
||||||
GST_OBJECT_LOCK (ximagesink);
|
GST_OBJECT_LOCK (ximagesink);
|
||||||
|
|
||||||
|
@ -588,8 +548,8 @@ gst_ximagesink_ximage_destroy (GstXImageSink * ximagesink,
|
||||||
if (!ximagesink->xcontext) {
|
if (!ximagesink->xcontext) {
|
||||||
GST_DEBUG_OBJECT (ximagesink, "Destroying XImage after XContext");
|
GST_DEBUG_OBJECT (ximagesink, "Destroying XImage after XContext");
|
||||||
#ifdef HAVE_XSHM
|
#ifdef HAVE_XSHM
|
||||||
if (ximage->SHMInfo.shmaddr != ((void *) -1)) {
|
if (data->SHMInfo.shmaddr != ((void *) -1)) {
|
||||||
shmdt (ximage->SHMInfo.shmaddr);
|
shmdt (data->SHMInfo.shmaddr);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
goto beach;
|
goto beach;
|
||||||
|
@ -599,19 +559,19 @@ gst_ximagesink_ximage_destroy (GstXImageSink * ximagesink,
|
||||||
|
|
||||||
#ifdef HAVE_XSHM
|
#ifdef HAVE_XSHM
|
||||||
if (ximagesink->xcontext->use_xshm) {
|
if (ximagesink->xcontext->use_xshm) {
|
||||||
if (ximage->SHMInfo.shmaddr != ((void *) -1)) {
|
if (data->SHMInfo.shmaddr != ((void *) -1)) {
|
||||||
XShmDetach (ximagesink->xcontext->disp, &ximage->SHMInfo);
|
XShmDetach (ximagesink->xcontext->disp, &data->SHMInfo);
|
||||||
XSync (ximagesink->xcontext->disp, 0);
|
XSync (ximagesink->xcontext->disp, 0);
|
||||||
shmdt (ximage->SHMInfo.shmaddr);
|
shmdt (data->SHMInfo.shmaddr);
|
||||||
}
|
}
|
||||||
if (ximage->ximage)
|
if (data->ximage)
|
||||||
XDestroyImage (ximage->ximage);
|
XDestroyImage (data->ximage);
|
||||||
|
|
||||||
} else
|
} else
|
||||||
#endif /* HAVE_XSHM */
|
#endif /* HAVE_XSHM */
|
||||||
{
|
{
|
||||||
if (ximage->ximage) {
|
if (data->ximage) {
|
||||||
XDestroyImage (ximage->ximage);
|
XDestroyImage (data->ximage);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -622,11 +582,13 @@ gst_ximagesink_ximage_destroy (GstXImageSink * ximagesink,
|
||||||
beach:
|
beach:
|
||||||
GST_OBJECT_UNLOCK (ximagesink);
|
GST_OBJECT_UNLOCK (ximagesink);
|
||||||
|
|
||||||
if (ximage->ximagesink) {
|
if (data->ximagesink) {
|
||||||
/* Release the ref to our sink */
|
/* Release the ref to our sink */
|
||||||
ximage->ximagesink = NULL;
|
data->ximagesink = NULL;
|
||||||
gst_object_unref (ximagesink);
|
gst_object_unref (ximagesink);
|
||||||
}
|
}
|
||||||
|
g_slice_free (GstXImageData, data);
|
||||||
|
ximage->owner_priv = NULL;
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -669,8 +631,9 @@ gst_ximagesink_xwindow_draw_borders (GstXImageSink * ximagesink,
|
||||||
|
|
||||||
/* This function puts a GstXImageBuffer on a GstXImageSink's window */
|
/* This function puts a GstXImageBuffer on a GstXImageSink's window */
|
||||||
static gboolean
|
static gboolean
|
||||||
gst_ximagesink_ximage_put (GstXImageSink * ximagesink, GstXImageBuffer * ximage)
|
gst_ximagesink_ximage_put (GstXImageSink * ximagesink, GstBuffer * ximage)
|
||||||
{
|
{
|
||||||
|
GstXImageData *data;
|
||||||
GstVideoRectangle src, dst, result;
|
GstVideoRectangle src, dst, result;
|
||||||
gboolean draw_border = FALSE;
|
gboolean draw_border = FALSE;
|
||||||
|
|
||||||
|
@ -698,8 +661,7 @@ gst_ximagesink_ximage_put (GstXImageSink * ximagesink, GstXImageBuffer * ximage)
|
||||||
gst_buffer_unref (GST_BUFFER_CAST (ximagesink->cur_image));
|
gst_buffer_unref (GST_BUFFER_CAST (ximagesink->cur_image));
|
||||||
}
|
}
|
||||||
GST_LOG_OBJECT (ximagesink, "reffing %p as our current image", ximage);
|
GST_LOG_OBJECT (ximagesink, "reffing %p as our current image", ximage);
|
||||||
ximagesink->cur_image =
|
ximagesink->cur_image = gst_buffer_ref (ximage);
|
||||||
GST_XIMAGE_BUFFER (gst_buffer_ref (GST_BUFFER_CAST (ximage)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Expose sends a NULL image, we take the latest frame */
|
/* Expose sends a NULL image, we take the latest frame */
|
||||||
|
@ -713,8 +675,9 @@ gst_ximagesink_ximage_put (GstXImageSink * ximagesink, GstXImageBuffer * ximage)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
src.w = ximage->width;
|
data = GET_XDATA (ximage);
|
||||||
src.h = ximage->height;
|
src.w = data->width;
|
||||||
|
src.h = data->height;
|
||||||
dst.w = ximagesink->xwindow->width;
|
dst.w = ximagesink->xwindow->width;
|
||||||
dst.h = ximagesink->xwindow->height;
|
dst.h = ximagesink->xwindow->height;
|
||||||
|
|
||||||
|
@ -734,7 +697,7 @@ gst_ximagesink_ximage_put (GstXImageSink * ximagesink, GstXImageBuffer * ximage)
|
||||||
ximage, 0, 0, result.x, result.y, result.w, result.h,
|
ximage, 0, 0, result.x, result.y, result.w, result.h,
|
||||||
ximagesink->xwindow->width, ximagesink->xwindow->height);
|
ximagesink->xwindow->width, ximagesink->xwindow->height);
|
||||||
XShmPutImage (ximagesink->xcontext->disp, ximagesink->xwindow->win,
|
XShmPutImage (ximagesink->xcontext->disp, ximagesink->xwindow->win,
|
||||||
ximagesink->xwindow->gc, ximage->ximage, 0, 0, result.x, result.y,
|
ximagesink->xwindow->gc, data->ximage, 0, 0, result.x, result.y,
|
||||||
result.w, result.h, FALSE);
|
result.w, result.h, FALSE);
|
||||||
} else
|
} else
|
||||||
#endif /* HAVE_XSHM */
|
#endif /* HAVE_XSHM */
|
||||||
|
@ -744,7 +707,7 @@ gst_ximagesink_ximage_put (GstXImageSink * ximagesink, GstXImageBuffer * ximage)
|
||||||
ximage, 0, 0, result.x, result.y, result.w, result.h,
|
ximage, 0, 0, result.x, result.y, result.w, result.h,
|
||||||
ximagesink->xwindow->width, ximagesink->xwindow->height);
|
ximagesink->xwindow->width, ximagesink->xwindow->height);
|
||||||
XPutImage (ximagesink->xcontext->disp, ximagesink->xwindow->win,
|
XPutImage (ximagesink->xcontext->disp, ximagesink->xwindow->win,
|
||||||
ximagesink->xwindow->gc, ximage->ximage, 0, 0, result.x, result.y,
|
ximagesink->xwindow->gc, data->ximage, 0, 0, result.x, result.y,
|
||||||
result.w, result.h);
|
result.w, result.h);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -853,7 +816,7 @@ gst_ximagesink_xwindow_new (GstXImageSink * ximagesink, gint width, gint height)
|
||||||
|
|
||||||
xwindow->win = XCreateSimpleWindow (ximagesink->xcontext->disp,
|
xwindow->win = XCreateSimpleWindow (ximagesink->xcontext->disp,
|
||||||
ximagesink->xcontext->root,
|
ximagesink->xcontext->root,
|
||||||
0, 0, xwindow->width, xwindow->height, 0, 0, ximagesink->xcontext->black);
|
0, 0, width, height, 0, 0, ximagesink->xcontext->black);
|
||||||
|
|
||||||
/* We have to do that to prevent X from redrawing the background on
|
/* We have to do that to prevent X from redrawing the background on
|
||||||
ConfigureNotify. This takes away flickering of video when resizing. */
|
ConfigureNotify. This takes away flickering of video when resizing. */
|
||||||
|
@ -1413,11 +1376,10 @@ gst_ximagesink_xcontext_clear (GstXImageSink * ximagesink)
|
||||||
static void
|
static void
|
||||||
gst_ximagesink_bufferpool_clear (GstXImageSink * ximagesink)
|
gst_ximagesink_bufferpool_clear (GstXImageSink * ximagesink)
|
||||||
{
|
{
|
||||||
|
|
||||||
g_mutex_lock (ximagesink->pool_lock);
|
g_mutex_lock (ximagesink->pool_lock);
|
||||||
|
|
||||||
while (ximagesink->buffer_pool) {
|
while (ximagesink->buffer_pool) {
|
||||||
GstXImageBuffer *ximage = ximagesink->buffer_pool->data;
|
GstBuffer *ximage = ximagesink->buffer_pool->data;
|
||||||
|
|
||||||
ximagesink->buffer_pool = g_slist_delete_link (ximagesink->buffer_pool,
|
ximagesink->buffer_pool = g_slist_delete_link (ximagesink->buffer_pool,
|
||||||
ximagesink->buffer_pool);
|
ximagesink->buffer_pool);
|
||||||
|
@ -1541,13 +1503,16 @@ gst_ximagesink_setcaps (GstBaseSink * bsink, GstCaps * caps)
|
||||||
|
|
||||||
/* If our ximage has changed we destroy it, next chain iteration will create
|
/* If our ximage has changed we destroy it, next chain iteration will create
|
||||||
a new one */
|
a new one */
|
||||||
if ((ximagesink->ximage) &&
|
if ((ximagesink->ximage)) {
|
||||||
((GST_VIDEO_SINK_WIDTH (ximagesink) != ximagesink->ximage->width) ||
|
GstXImageData *data = GET_XDATA (ximagesink->ximage);
|
||||||
(GST_VIDEO_SINK_HEIGHT (ximagesink) != ximagesink->ximage->height))) {
|
|
||||||
GST_DEBUG_OBJECT (ximagesink, "our image is not usable anymore, unref %p",
|
if (((GST_VIDEO_SINK_WIDTH (ximagesink) != data->width) ||
|
||||||
ximagesink->ximage);
|
(GST_VIDEO_SINK_HEIGHT (ximagesink) != data->height))) {
|
||||||
gst_buffer_unref (GST_BUFFER_CAST (ximagesink->ximage));
|
GST_DEBUG_OBJECT (ximagesink, "our image is not usable anymore, unref %p",
|
||||||
ximagesink->ximage = NULL;
|
ximagesink->ximage);
|
||||||
|
gst_buffer_unref (ximagesink->ximage);
|
||||||
|
ximagesink->ximage = NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
@ -1668,13 +1633,16 @@ gst_ximagesink_show_frame (GstVideoSink * vsink, GstBuffer * buf)
|
||||||
if (!ximagesink->xcontext)
|
if (!ximagesink->xcontext)
|
||||||
return GST_FLOW_ERROR;
|
return GST_FLOW_ERROR;
|
||||||
|
|
||||||
|
#if 0
|
||||||
/* If this buffer has been allocated using our buffer management we simply
|
/* If this buffer has been allocated using our buffer management we simply
|
||||||
put the ximage which is in the PRIVATE pointer */
|
put the ximage which is in the PRIVATE pointer */
|
||||||
if (GST_IS_XIMAGE_BUFFER (buf)) {
|
if (GST_IS_XIMAGE_BUFFER (buf)) {
|
||||||
GST_LOG_OBJECT (ximagesink, "buffer from our pool, writing directly");
|
GST_LOG_OBJECT (ximagesink, "buffer from our pool, writing directly");
|
||||||
if (!gst_ximagesink_ximage_put (ximagesink, GST_XIMAGE_BUFFER (buf)))
|
if (!gst_ximagesink_ximage_put (ximagesink, GST_XIMAGE_BUFFER (buf)))
|
||||||
goto no_window;
|
goto no_window;
|
||||||
} else {
|
} else
|
||||||
|
#endif
|
||||||
|
{
|
||||||
/* Else we have to copy the data into our private image, */
|
/* Else we have to copy the data into our private image, */
|
||||||
/* if we have one... */
|
/* if we have one... */
|
||||||
GST_LOG_OBJECT (ximagesink, "normal buffer, copying from it");
|
GST_LOG_OBJECT (ximagesink, "normal buffer, copying from it");
|
||||||
|
@ -1686,10 +1654,11 @@ gst_ximagesink_show_frame (GstVideoSink * vsink, GstBuffer * buf)
|
||||||
/* The create method should have posted an informative error */
|
/* The create method should have posted an informative error */
|
||||||
goto no_ximage;
|
goto no_ximage;
|
||||||
|
|
||||||
if (ximagesink->ximage->size < GST_BUFFER_SIZE (buf)) {
|
if (GST_BUFFER_SIZE (ximagesink->ximage) < GST_BUFFER_SIZE (buf)) {
|
||||||
GST_ELEMENT_ERROR (ximagesink, RESOURCE, WRITE,
|
GST_ELEMENT_ERROR (ximagesink, RESOURCE, WRITE,
|
||||||
("Failed to create output image buffer of %dx%d pixels",
|
("Failed to create output image buffer of %dx%d pixels",
|
||||||
ximagesink->ximage->width, ximagesink->ximage->height),
|
GET_XDATA (ximagesink->ximage)->width,
|
||||||
|
GET_XDATA (ximagesink->ximage)->height),
|
||||||
("XServer allocated buffer size did not match input buffer"));
|
("XServer allocated buffer size did not match input buffer"));
|
||||||
|
|
||||||
gst_ximagesink_ximage_destroy (ximagesink, ximagesink->ximage);
|
gst_ximagesink_ximage_destroy (ximagesink, ximagesink->ximage);
|
||||||
|
@ -1698,7 +1667,7 @@ gst_ximagesink_show_frame (GstVideoSink * vsink, GstBuffer * buf)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
memcpy (GST_BUFFER_DATA (ximagesink->ximage), GST_BUFFER_DATA (buf),
|
memcpy (GST_BUFFER_DATA (ximagesink->ximage), GST_BUFFER_DATA (buf),
|
||||||
MIN (GST_BUFFER_SIZE (buf), ximagesink->ximage->size));
|
MIN (GST_BUFFER_SIZE (buf), GST_BUFFER_SIZE (ximagesink->ximage)));
|
||||||
if (!gst_ximagesink_ximage_put (ximagesink, ximagesink->ximage))
|
if (!gst_ximagesink_ximage_put (ximagesink, ximagesink->ximage))
|
||||||
goto no_window;
|
goto no_window;
|
||||||
}
|
}
|
||||||
|
@ -1752,7 +1721,7 @@ gst_ximagesink_event (GstBaseSink * sink, GstEvent * event)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
/* Buffer management
|
/* Buffer management
|
||||||
*
|
*
|
||||||
* The buffer_alloc function must either return a buffer with given size and
|
* The buffer_alloc function must either return a buffer with given size and
|
||||||
|
@ -1938,6 +1907,7 @@ alloc:
|
||||||
beach:
|
beach:
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Interfaces stuff */
|
/* Interfaces stuff */
|
||||||
|
|
||||||
|
@ -2436,8 +2406,10 @@ gst_ximagesink_class_init (GstXImageSinkClass * klass)
|
||||||
|
|
||||||
gstbasesink_class->get_caps = GST_DEBUG_FUNCPTR (gst_ximagesink_getcaps);
|
gstbasesink_class->get_caps = GST_DEBUG_FUNCPTR (gst_ximagesink_getcaps);
|
||||||
gstbasesink_class->set_caps = GST_DEBUG_FUNCPTR (gst_ximagesink_setcaps);
|
gstbasesink_class->set_caps = GST_DEBUG_FUNCPTR (gst_ximagesink_setcaps);
|
||||||
|
#if 0
|
||||||
gstbasesink_class->buffer_alloc =
|
gstbasesink_class->buffer_alloc =
|
||||||
GST_DEBUG_FUNCPTR (gst_ximagesink_buffer_alloc);
|
GST_DEBUG_FUNCPTR (gst_ximagesink_buffer_alloc);
|
||||||
|
#endif
|
||||||
gstbasesink_class->get_times = GST_DEBUG_FUNCPTR (gst_ximagesink_get_times);
|
gstbasesink_class->get_times = GST_DEBUG_FUNCPTR (gst_ximagesink_get_times);
|
||||||
gstbasesink_class->event = GST_DEBUG_FUNCPTR (gst_ximagesink_event);
|
gstbasesink_class->event = GST_DEBUG_FUNCPTR (gst_ximagesink_event);
|
||||||
|
|
||||||
|
@ -2490,11 +2462,6 @@ gst_ximagesink_get_type (void)
|
||||||
&navigation_info);
|
&navigation_info);
|
||||||
g_type_add_interface_static (ximagesink_type, GST_TYPE_X_OVERLAY,
|
g_type_add_interface_static (ximagesink_type, GST_TYPE_X_OVERLAY,
|
||||||
&overlay_info);
|
&overlay_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_ximage_buffer_get_type ());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return ximagesink_type;
|
return ximagesink_type;
|
||||||
|
|
|
@ -52,8 +52,7 @@ G_BEGIN_DECLS
|
||||||
typedef struct _GstXContext GstXContext;
|
typedef struct _GstXContext GstXContext;
|
||||||
typedef struct _GstXWindow GstXWindow;
|
typedef struct _GstXWindow GstXWindow;
|
||||||
|
|
||||||
typedef struct _GstXImageBuffer GstXImageBuffer;
|
typedef struct _GstXImageData GstXImageData;
|
||||||
typedef struct _GstXImageBufferClass GstXImageBufferClass;
|
|
||||||
|
|
||||||
typedef struct _GstXImageSink GstXImageSink;
|
typedef struct _GstXImageSink GstXImageSink;
|
||||||
typedef struct _GstXImageSinkClass GstXImageSinkClass;
|
typedef struct _GstXImageSinkClass GstXImageSinkClass;
|
||||||
|
@ -129,20 +128,19 @@ struct _GstXWindow
|
||||||
GC gc;
|
GC gc;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* GstXImageBuffer:
|
* GstXImageData:
|
||||||
* @ximagesink: a reference to our #GstXImageSink
|
* @ximagesink: a reference to our #GstXImageSink
|
||||||
* @ximage: the XImage of this buffer
|
* @ximage: the XImage of this buffer
|
||||||
* @width: the width in pixels of XImage @ximage
|
* @width: the width in pixels of XImage @ximage
|
||||||
* @height: the height in pixels of XImage @ximage
|
* @height: the height in pixels of XImage @ximage
|
||||||
* @size: the size in bytes of XImage @ximage
|
* @size: the size in bytes of XImage @ximage
|
||||||
*
|
*
|
||||||
* Subclass of #GstBuffer containing additional information about an XImage.
|
* Structure with additional information about an XImage.
|
||||||
*/
|
*/
|
||||||
struct _GstXImageBuffer
|
struct _GstXImageData
|
||||||
{
|
{
|
||||||
GstBuffer buffer;
|
|
||||||
|
|
||||||
/* Reference to the ximagesink we belong to */
|
/* Reference to the ximagesink we belong to */
|
||||||
GstXImageSink *ximagesink;
|
GstXImageSink *ximagesink;
|
||||||
|
|
||||||
|
@ -194,8 +192,8 @@ struct _GstXImageSink
|
||||||
|
|
||||||
GstXContext *xcontext;
|
GstXContext *xcontext;
|
||||||
GstXWindow *xwindow;
|
GstXWindow *xwindow;
|
||||||
GstXImageBuffer *ximage;
|
GstBuffer *ximage;
|
||||||
GstXImageBuffer *cur_image;
|
GstBuffer *cur_image;
|
||||||
|
|
||||||
GThread *event_thread;
|
GThread *event_thread;
|
||||||
gboolean running;
|
gboolean running;
|
||||||
|
|
|
@ -143,10 +143,8 @@ MotifWmHints, MwmHints;
|
||||||
#define MWM_HINTS_DECORATIONS (1L << 1)
|
#define MWM_HINTS_DECORATIONS (1L << 1)
|
||||||
|
|
||||||
static void gst_xvimagesink_reset (GstXvImageSink * xvimagesink);
|
static void gst_xvimagesink_reset (GstXvImageSink * xvimagesink);
|
||||||
|
static void gst_xvimagesink_xvimage_destroy (GstXvImageSink * xvimagesink,
|
||||||
static GstBufferClass *xvimage_buffer_parent_class = NULL;
|
GstBuffer * xvimage);
|
||||||
static void gst_xvimage_buffer_finalize (GstXvImageBuffer * xvimage);
|
|
||||||
|
|
||||||
static void gst_xvimagesink_xwindow_update_geometry (GstXvImageSink *
|
static void gst_xvimagesink_xwindow_update_geometry (GstXvImageSink *
|
||||||
xvimagesink);
|
xvimagesink);
|
||||||
static gint gst_xvimagesink_get_format_from_caps (GstXvImageSink * xvimagesink,
|
static gint gst_xvimagesink_get_format_from_caps (GstXvImageSink * xvimagesink,
|
||||||
|
@ -200,99 +198,19 @@ static GstVideoSinkClass *parent_class = NULL;
|
||||||
/* ============================================================= */
|
/* ============================================================= */
|
||||||
|
|
||||||
/* xvimage buffers */
|
/* xvimage buffers */
|
||||||
|
#define GET_XVDATA(buf) ((GstXvImageData *) (GST_BUFFER_CAST(buf)->owner_priv))
|
||||||
#define GST_TYPE_XVIMAGE_BUFFER (gst_xvimage_buffer_get_type())
|
|
||||||
|
|
||||||
#define GST_IS_XVIMAGE_BUFFER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_XVIMAGE_BUFFER))
|
|
||||||
#define GST_XVIMAGE_BUFFER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_XVIMAGE_BUFFER, GstXvImageBuffer))
|
|
||||||
#define GST_XVIMAGE_BUFFER_CAST(obj) ((GstXvImageBuffer *)(obj))
|
|
||||||
|
|
||||||
/* This function destroys a GstXvImage handling XShm availability */
|
|
||||||
static void
|
|
||||||
gst_xvimage_buffer_destroy (GstXvImageBuffer * xvimage)
|
|
||||||
{
|
|
||||||
GstXvImageSink *xvimagesink;
|
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (xvimage, "Destroying buffer");
|
|
||||||
|
|
||||||
xvimagesink = xvimage->xvimagesink;
|
|
||||||
if (G_UNLIKELY (xvimagesink == NULL))
|
|
||||||
goto no_sink;
|
|
||||||
|
|
||||||
g_return_if_fail (GST_IS_XVIMAGESINK (xvimagesink));
|
|
||||||
|
|
||||||
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 (xvimage->SHMInfo.shmaddr != ((void *) -1)) {
|
|
||||||
shmdt (xvimage->SHMInfo.shmaddr);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
goto beach;
|
|
||||||
}
|
|
||||||
|
|
||||||
g_mutex_lock (xvimagesink->x_lock);
|
|
||||||
|
|
||||||
#ifdef HAVE_XSHM
|
|
||||||
if (xvimagesink->xcontext->use_xshm) {
|
|
||||||
if (xvimage->SHMInfo.shmaddr != ((void *) -1)) {
|
|
||||||
GST_DEBUG_OBJECT (xvimagesink, "XServer ShmDetaching from 0x%x id 0x%lx",
|
|
||||||
xvimage->SHMInfo.shmid, xvimage->SHMInfo.shmseg);
|
|
||||||
XShmDetach (xvimagesink->xcontext->disp, &xvimage->SHMInfo);
|
|
||||||
XSync (xvimagesink->xcontext->disp, FALSE);
|
|
||||||
|
|
||||||
shmdt (xvimage->SHMInfo.shmaddr);
|
|
||||||
}
|
|
||||||
if (xvimage->xvimage)
|
|
||||||
XFree (xvimage->xvimage);
|
|
||||||
} else
|
|
||||||
#endif /* HAVE_XSHM */
|
|
||||||
{
|
|
||||||
if (xvimage->xvimage) {
|
|
||||||
if (xvimage->xvimage->data) {
|
|
||||||
g_free (xvimage->xvimage->data);
|
|
||||||
}
|
|
||||||
XFree (xvimage->xvimage);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
XSync (xvimagesink->xcontext->disp, FALSE);
|
|
||||||
|
|
||||||
g_mutex_unlock (xvimagesink->x_lock);
|
|
||||||
|
|
||||||
beach:
|
|
||||||
GST_OBJECT_UNLOCK (xvimagesink);
|
|
||||||
xvimage->xvimagesink = NULL;
|
|
||||||
gst_object_unref (xvimagesink);
|
|
||||||
|
|
||||||
GST_MINI_OBJECT_CLASS (xvimage_buffer_parent_class)->finalize (GST_MINI_OBJECT
|
|
||||||
(xvimage));
|
|
||||||
|
|
||||||
return;
|
|
||||||
|
|
||||||
no_sink:
|
|
||||||
{
|
|
||||||
GST_WARNING ("no sink found");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gst_xvimage_buffer_finalize (GstXvImageBuffer * xvimage)
|
gst_xvimage_buffer_dispose (GstBuffer * xvimage)
|
||||||
{
|
{
|
||||||
|
GstXvImageData *data = NULL;
|
||||||
GstXvImageSink *xvimagesink;
|
GstXvImageSink *xvimagesink;
|
||||||
gboolean running;
|
gboolean running;
|
||||||
|
|
||||||
xvimagesink = xvimage->xvimagesink;
|
data = GET_XVDATA (xvimage);
|
||||||
|
g_return_if_fail (data != NULL);
|
||||||
|
|
||||||
|
xvimagesink = data->xvimagesink;
|
||||||
if (G_UNLIKELY (xvimagesink == NULL))
|
if (G_UNLIKELY (xvimagesink == NULL))
|
||||||
goto no_sink;
|
goto no_sink;
|
||||||
|
|
||||||
|
@ -302,22 +220,22 @@ gst_xvimage_buffer_finalize (GstXvImageBuffer * xvimage)
|
||||||
running = xvimagesink->running;
|
running = xvimagesink->running;
|
||||||
GST_OBJECT_UNLOCK (xvimagesink);
|
GST_OBJECT_UNLOCK (xvimagesink);
|
||||||
|
|
||||||
/* If our geometry changed we can't reuse that image. */
|
|
||||||
if (running == FALSE) {
|
if (running == FALSE) {
|
||||||
GST_LOG_OBJECT (xvimage, "destroy image as sink is shutting down");
|
GST_LOG_OBJECT (xvimage, "destroy image as sink is shutting down");
|
||||||
gst_xvimage_buffer_destroy (xvimage);
|
gst_xvimagesink_xvimage_destroy (xvimagesink, xvimage);
|
||||||
} else if ((xvimage->width != xvimagesink->video_width) ||
|
} else if ((data->width != xvimagesink->video_width) ||
|
||||||
(xvimage->height != xvimagesink->video_height)) {
|
(data->height != xvimagesink->video_height)) {
|
||||||
|
/* If our geometry changed we can't reuse that image. */
|
||||||
GST_LOG_OBJECT (xvimage,
|
GST_LOG_OBJECT (xvimage,
|
||||||
"destroy image as its size changed %dx%d vs current %dx%d",
|
"destroy image as its size changed %dx%d vs current %dx%d",
|
||||||
xvimage->width, xvimage->height,
|
data->width, data->height,
|
||||||
xvimagesink->video_width, xvimagesink->video_height);
|
xvimagesink->video_width, xvimagesink->video_height);
|
||||||
gst_xvimage_buffer_destroy (xvimage);
|
gst_xvimagesink_xvimage_destroy (xvimagesink, xvimage);
|
||||||
} else {
|
} else {
|
||||||
/* In that case we can reuse the image and add it to our image pool. */
|
/* In that case we can reuse the image and add it to our image pool. */
|
||||||
GST_LOG_OBJECT (xvimage, "recycling image in pool");
|
GST_LOG_OBJECT (xvimage, "recycling image in pool");
|
||||||
/* need to increment the refcount again to recycle */
|
/* need to increment the refcount again to recycle */
|
||||||
gst_buffer_ref (GST_BUFFER_CAST (xvimage));
|
gst_buffer_ref (xvimage);
|
||||||
g_mutex_lock (xvimagesink->pool_lock);
|
g_mutex_lock (xvimagesink->pool_lock);
|
||||||
xvimagesink->image_pool = g_slist_prepend (xvimagesink->image_pool,
|
xvimagesink->image_pool = g_slist_prepend (xvimagesink->image_pool,
|
||||||
xvimage);
|
xvimage);
|
||||||
|
@ -333,56 +251,16 @@ no_sink:
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gst_xvimage_buffer_free (GstXvImageBuffer * xvimage)
|
gst_xvimage_buffer_free (GstBuffer * xvimage)
|
||||||
{
|
{
|
||||||
|
GstXvImageData *data = GET_XVDATA (xvimage);
|
||||||
|
|
||||||
|
g_return_if_fail (data != NULL);
|
||||||
|
|
||||||
/* make sure it is not recycled */
|
/* make sure it is not recycled */
|
||||||
xvimage->width = -1;
|
data->width = -1;
|
||||||
xvimage->height = -1;
|
data->height = -1;
|
||||||
gst_buffer_unref (GST_BUFFER (xvimage));
|
gst_buffer_unref (xvimage);
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
gst_xvimage_buffer_init (GstXvImageBuffer * xvimage, gpointer g_class)
|
|
||||||
{
|
|
||||||
#ifdef HAVE_XSHM
|
|
||||||
xvimage->SHMInfo.shmaddr = ((void *) -1);
|
|
||||||
xvimage->SHMInfo.shmid = -1;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
gst_xvimage_buffer_class_init (gpointer g_class, gpointer class_data)
|
|
||||||
{
|
|
||||||
GstMiniObjectClass *mini_object_class = GST_MINI_OBJECT_CLASS (g_class);
|
|
||||||
|
|
||||||
xvimage_buffer_parent_class = g_type_class_peek_parent (g_class);
|
|
||||||
|
|
||||||
mini_object_class->finalize = (GstMiniObjectFinalizeFunction)
|
|
||||||
gst_xvimage_buffer_finalize;
|
|
||||||
}
|
|
||||||
|
|
||||||
static GType
|
|
||||||
gst_xvimage_buffer_get_type (void)
|
|
||||||
{
|
|
||||||
static GType _gst_xvimage_buffer_type;
|
|
||||||
|
|
||||||
if (G_UNLIKELY (_gst_xvimage_buffer_type == 0)) {
|
|
||||||
static const GTypeInfo xvimage_buffer_info = {
|
|
||||||
sizeof (GstBufferClass),
|
|
||||||
NULL,
|
|
||||||
NULL,
|
|
||||||
gst_xvimage_buffer_class_init,
|
|
||||||
NULL,
|
|
||||||
NULL,
|
|
||||||
sizeof (GstXvImageBuffer),
|
|
||||||
0,
|
|
||||||
(GInstanceInitFunc) gst_xvimage_buffer_init,
|
|
||||||
NULL
|
|
||||||
};
|
|
||||||
_gst_xvimage_buffer_type = g_type_register_static (GST_TYPE_BUFFER,
|
|
||||||
"GstXvImageBuffer", &xvimage_buffer_info, 0);
|
|
||||||
}
|
|
||||||
return _gst_xvimage_buffer_type;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* X11 stuff */
|
/* X11 stuff */
|
||||||
|
@ -505,10 +383,11 @@ beach:
|
||||||
#endif /* HAVE_XSHM */
|
#endif /* HAVE_XSHM */
|
||||||
|
|
||||||
/* This function handles GstXvImage creation depending on XShm availability */
|
/* This function handles GstXvImage creation depending on XShm availability */
|
||||||
static GstXvImageBuffer *
|
static GstBuffer *
|
||||||
gst_xvimagesink_xvimage_new (GstXvImageSink * xvimagesink, GstCaps * caps)
|
gst_xvimagesink_xvimage_new (GstXvImageSink * xvimagesink, GstCaps * caps)
|
||||||
{
|
{
|
||||||
GstXvImageBuffer *xvimage = NULL;
|
GstBuffer *buffer = NULL;
|
||||||
|
GstXvImageData *data = NULL;
|
||||||
GstStructure *structure = NULL;
|
GstStructure *structure = NULL;
|
||||||
gboolean succeeded = FALSE;
|
gboolean succeeded = FALSE;
|
||||||
int (*handler) (Display *, XErrorEvent *);
|
int (*handler) (Display *, XErrorEvent *);
|
||||||
|
@ -518,29 +397,37 @@ gst_xvimagesink_xvimage_new (GstXvImageSink * xvimagesink, GstCaps * caps)
|
||||||
if (caps == NULL)
|
if (caps == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
xvimage = (GstXvImageBuffer *) gst_mini_object_new (GST_TYPE_XVIMAGE_BUFFER);
|
data = g_slice_new0 (GstXvImageData);
|
||||||
GST_DEBUG_OBJECT (xvimage, "Creating new XvImageBuffer");
|
#ifdef HAVE_XSHM
|
||||||
|
data->SHMInfo.shmaddr = ((void *) -1);
|
||||||
|
data->SHMInfo.shmid = -1;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
buffer = gst_buffer_new ();
|
||||||
|
GST_DEBUG_OBJECT (xvimagesink, "Creating new XvImageBuffer");
|
||||||
|
GST_MINI_OBJECT_CAST (buffer)->dispose =
|
||||||
|
(GstMiniObjectDisposeFunction) gst_xvimage_buffer_dispose;
|
||||||
|
buffer->owner_priv = data;
|
||||||
|
|
||||||
structure = gst_caps_get_structure (caps, 0);
|
structure = gst_caps_get_structure (caps, 0);
|
||||||
|
|
||||||
if (!gst_structure_get_int (structure, "width", &xvimage->width) ||
|
if (!gst_structure_get_int (structure, "width", &data->width) ||
|
||||||
!gst_structure_get_int (structure, "height", &xvimage->height)) {
|
!gst_structure_get_int (structure, "height", &data->height)) {
|
||||||
GST_WARNING ("failed getting geometry from caps %" GST_PTR_FORMAT, caps);
|
GST_WARNING ("failed getting geometry from caps %" GST_PTR_FORMAT, caps);
|
||||||
}
|
}
|
||||||
|
|
||||||
GST_LOG_OBJECT (xvimagesink, "creating %dx%d", xvimage->width,
|
GST_LOG_OBJECT (xvimagesink, "creating %dx%d", data->width, data->height);
|
||||||
xvimage->height);
|
|
||||||
|
|
||||||
xvimage->im_format = gst_xvimagesink_get_format_from_caps (xvimagesink, caps);
|
data->im_format = gst_xvimagesink_get_format_from_caps (xvimagesink, caps);
|
||||||
if (xvimage->im_format == -1) {
|
if (data->im_format == -1) {
|
||||||
GST_WARNING_OBJECT (xvimagesink, "failed to get format from caps %"
|
GST_WARNING_OBJECT (xvimagesink, "failed to get format from caps %"
|
||||||
GST_PTR_FORMAT, caps);
|
GST_PTR_FORMAT, caps);
|
||||||
GST_ELEMENT_ERROR (xvimagesink, RESOURCE, WRITE,
|
GST_ELEMENT_ERROR (xvimagesink, RESOURCE, WRITE,
|
||||||
("Failed to create output image buffer of %dx%d pixels",
|
("Failed to create output image buffer of %dx%d pixels",
|
||||||
xvimage->width, xvimage->height), ("Invalid input caps"));
|
data->width, data->height), ("Invalid input caps"));
|
||||||
goto beach_unlocked;
|
goto beach_unlocked;
|
||||||
}
|
}
|
||||||
xvimage->xvimagesink = gst_object_ref (xvimagesink);
|
data->xvimagesink = gst_object_ref (xvimagesink);
|
||||||
|
|
||||||
g_mutex_lock (xvimagesink->x_lock);
|
g_mutex_lock (xvimagesink->x_lock);
|
||||||
|
|
||||||
|
@ -552,11 +439,10 @@ gst_xvimagesink_xvimage_new (GstXvImageSink * xvimagesink, GstCaps * caps)
|
||||||
if (xvimagesink->xcontext->use_xshm) {
|
if (xvimagesink->xcontext->use_xshm) {
|
||||||
int expected_size;
|
int expected_size;
|
||||||
|
|
||||||
xvimage->xvimage = XvShmCreateImage (xvimagesink->xcontext->disp,
|
data->xvimage = XvShmCreateImage (xvimagesink->xcontext->disp,
|
||||||
xvimagesink->xcontext->xv_port_id,
|
xvimagesink->xcontext->xv_port_id,
|
||||||
xvimage->im_format, NULL,
|
data->im_format, NULL, data->width, data->height, &data->SHMInfo);
|
||||||
xvimage->width, xvimage->height, &xvimage->SHMInfo);
|
if (!data->xvimage || error_caught) {
|
||||||
if (!xvimage->xvimage || error_caught) {
|
|
||||||
g_mutex_unlock (xvimagesink->x_lock);
|
g_mutex_unlock (xvimagesink->x_lock);
|
||||||
/* Reset error handler */
|
/* Reset error handler */
|
||||||
error_caught = FALSE;
|
error_caught = FALSE;
|
||||||
|
@ -564,20 +450,20 @@ gst_xvimagesink_xvimage_new (GstXvImageSink * xvimagesink, GstCaps * caps)
|
||||||
/* Push an error */
|
/* Push an error */
|
||||||
GST_ELEMENT_ERROR (xvimagesink, RESOURCE, WRITE,
|
GST_ELEMENT_ERROR (xvimagesink, RESOURCE, WRITE,
|
||||||
("Failed to create output image buffer of %dx%d pixels",
|
("Failed to create output image buffer of %dx%d pixels",
|
||||||
xvimage->width, xvimage->height),
|
data->width, data->height),
|
||||||
("could not XvShmCreateImage a %dx%d image",
|
("could not XvShmCreateImage a %dx%d image",
|
||||||
xvimage->width, xvimage->height));
|
data->width, data->height));
|
||||||
goto beach_unlocked;
|
goto beach_unlocked;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* we have to use the returned data_size for our shm size */
|
/* we have to use the returned data_size for our shm size */
|
||||||
xvimage->size = xvimage->xvimage->data_size;
|
data->size = data->xvimage->data_size;
|
||||||
GST_LOG_OBJECT (xvimagesink, "XShm image size is %" G_GSIZE_FORMAT,
|
GST_LOG_OBJECT (xvimagesink, "XShm image size is %" G_GSIZE_FORMAT,
|
||||||
xvimage->size);
|
data->size);
|
||||||
|
|
||||||
/* calculate the expected size. This is only for sanity checking the
|
/* calculate the expected size. This is only for sanity checking the
|
||||||
* number we get from X. */
|
* number we get from X. */
|
||||||
switch (xvimage->im_format) {
|
switch (data->im_format) {
|
||||||
case GST_MAKE_FOURCC ('I', '4', '2', '0'):
|
case GST_MAKE_FOURCC ('I', '4', '2', '0'):
|
||||||
case GST_MAKE_FOURCC ('Y', 'V', '1', '2'):
|
case GST_MAKE_FOURCC ('Y', 'V', '1', '2'):
|
||||||
{
|
{
|
||||||
|
@ -586,17 +472,17 @@ gst_xvimagesink_xvimage_new (GstXvImageSink * xvimagesink, GstCaps * caps)
|
||||||
guint plane;
|
guint plane;
|
||||||
|
|
||||||
offsets[0] = 0;
|
offsets[0] = 0;
|
||||||
pitches[0] = GST_ROUND_UP_4 (xvimage->width);
|
pitches[0] = GST_ROUND_UP_4 (data->width);
|
||||||
offsets[1] = offsets[0] + pitches[0] * GST_ROUND_UP_2 (xvimage->height);
|
offsets[1] = offsets[0] + pitches[0] * GST_ROUND_UP_2 (data->height);
|
||||||
pitches[1] = GST_ROUND_UP_8 (xvimage->width) / 2;
|
pitches[1] = GST_ROUND_UP_8 (data->width) / 2;
|
||||||
offsets[2] =
|
offsets[2] =
|
||||||
offsets[1] + pitches[1] * GST_ROUND_UP_2 (xvimage->height) / 2;
|
offsets[1] + pitches[1] * GST_ROUND_UP_2 (data->height) / 2;
|
||||||
pitches[2] = GST_ROUND_UP_8 (pitches[0]) / 2;
|
pitches[2] = GST_ROUND_UP_8 (pitches[0]) / 2;
|
||||||
|
|
||||||
expected_size =
|
expected_size =
|
||||||
offsets[2] + pitches[2] * GST_ROUND_UP_2 (xvimage->height) / 2;
|
offsets[2] + pitches[2] * GST_ROUND_UP_2 (data->height) / 2;
|
||||||
|
|
||||||
for (plane = 0; plane < xvimage->xvimage->num_planes; plane++) {
|
for (plane = 0; plane < data->xvimage->num_planes; plane++) {
|
||||||
GST_DEBUG_OBJECT (xvimagesink,
|
GST_DEBUG_OBJECT (xvimagesink,
|
||||||
"Plane %u has a expected pitch of %d bytes, " "offset of %d",
|
"Plane %u has a expected pitch of %d bytes, " "offset of %d",
|
||||||
plane, pitches[plane], offsets[plane]);
|
plane, pitches[plane], offsets[plane]);
|
||||||
|
@ -605,64 +491,63 @@ gst_xvimagesink_xvimage_new (GstXvImageSink * xvimagesink, GstCaps * caps)
|
||||||
}
|
}
|
||||||
case GST_MAKE_FOURCC ('Y', 'U', 'Y', '2'):
|
case GST_MAKE_FOURCC ('Y', 'U', 'Y', '2'):
|
||||||
case GST_MAKE_FOURCC ('U', 'Y', 'V', 'Y'):
|
case GST_MAKE_FOURCC ('U', 'Y', 'V', 'Y'):
|
||||||
expected_size = xvimage->height * GST_ROUND_UP_4 (xvimage->width * 2);
|
expected_size = data->height * GST_ROUND_UP_4 (data->width * 2);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
expected_size = 0;
|
expected_size = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (expected_size != 0 && xvimage->size != expected_size) {
|
if (expected_size != 0 && data->size != expected_size) {
|
||||||
GST_WARNING_OBJECT (xvimagesink,
|
GST_WARNING_OBJECT (xvimagesink,
|
||||||
"unexpected XShm image size (got %" G_GSIZE_FORMAT ", expected %d)",
|
"unexpected XShm image size (got %" G_GSIZE_FORMAT ", expected %d)",
|
||||||
xvimage->size, expected_size);
|
data->size, expected_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Be verbose about our XvImage stride */
|
/* Be verbose about our XvImage stride */
|
||||||
{
|
{
|
||||||
guint plane;
|
guint plane;
|
||||||
|
|
||||||
for (plane = 0; plane < xvimage->xvimage->num_planes; plane++) {
|
for (plane = 0; plane < data->xvimage->num_planes; plane++) {
|
||||||
GST_DEBUG_OBJECT (xvimagesink, "Plane %u has a pitch of %d bytes, "
|
GST_DEBUG_OBJECT (xvimagesink, "Plane %u has a pitch of %d bytes, "
|
||||||
"offset of %d", plane, xvimage->xvimage->pitches[plane],
|
"offset of %d", plane, data->xvimage->pitches[plane],
|
||||||
xvimage->xvimage->offsets[plane]);
|
data->xvimage->offsets[plane]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
xvimage->SHMInfo.shmid = shmget (IPC_PRIVATE, xvimage->size,
|
data->SHMInfo.shmid = shmget (IPC_PRIVATE, data->size, IPC_CREAT | 0777);
|
||||||
IPC_CREAT | 0777);
|
if (data->SHMInfo.shmid == -1) {
|
||||||
if (xvimage->SHMInfo.shmid == -1) {
|
|
||||||
g_mutex_unlock (xvimagesink->x_lock);
|
g_mutex_unlock (xvimagesink->x_lock);
|
||||||
GST_ELEMENT_ERROR (xvimagesink, RESOURCE, WRITE,
|
GST_ELEMENT_ERROR (xvimagesink, RESOURCE, WRITE,
|
||||||
("Failed to create output image buffer of %dx%d pixels",
|
("Failed to create output image buffer of %dx%d pixels",
|
||||||
xvimage->width, xvimage->height),
|
data->width, data->height),
|
||||||
("could not get shared memory of %" G_GSIZE_FORMAT " bytes",
|
("could not get shared memory of %" G_GSIZE_FORMAT " bytes",
|
||||||
xvimage->size));
|
data->size));
|
||||||
goto beach_unlocked;
|
goto beach_unlocked;
|
||||||
}
|
}
|
||||||
|
|
||||||
xvimage->SHMInfo.shmaddr = shmat (xvimage->SHMInfo.shmid, NULL, 0);
|
data->SHMInfo.shmaddr = shmat (data->SHMInfo.shmid, NULL, 0);
|
||||||
if (xvimage->SHMInfo.shmaddr == ((void *) -1)) {
|
if (data->SHMInfo.shmaddr == ((void *) -1)) {
|
||||||
g_mutex_unlock (xvimagesink->x_lock);
|
g_mutex_unlock (xvimagesink->x_lock);
|
||||||
GST_ELEMENT_ERROR (xvimagesink, RESOURCE, WRITE,
|
GST_ELEMENT_ERROR (xvimagesink, RESOURCE, WRITE,
|
||||||
("Failed to create output image buffer of %dx%d pixels",
|
("Failed to create output image buffer of %dx%d pixels",
|
||||||
xvimage->width, xvimage->height),
|
data->width, data->height),
|
||||||
("Failed to shmat: %s", g_strerror (errno)));
|
("Failed to shmat: %s", g_strerror (errno)));
|
||||||
/* Clean up the shared memory segment */
|
/* Clean up the shared memory segment */
|
||||||
shmctl (xvimage->SHMInfo.shmid, IPC_RMID, NULL);
|
shmctl (data->SHMInfo.shmid, IPC_RMID, NULL);
|
||||||
goto beach_unlocked;
|
goto beach_unlocked;
|
||||||
}
|
}
|
||||||
|
|
||||||
xvimage->xvimage->data = xvimage->SHMInfo.shmaddr;
|
data->xvimage->data = data->SHMInfo.shmaddr;
|
||||||
xvimage->SHMInfo.readOnly = FALSE;
|
data->SHMInfo.readOnly = FALSE;
|
||||||
|
|
||||||
if (XShmAttach (xvimagesink->xcontext->disp, &xvimage->SHMInfo) == 0) {
|
if (XShmAttach (xvimagesink->xcontext->disp, &data->SHMInfo) == 0) {
|
||||||
/* Clean up the shared memory segment */
|
/* Clean up the shared memory segment */
|
||||||
shmctl (xvimage->SHMInfo.shmid, IPC_RMID, NULL);
|
shmctl (data->SHMInfo.shmid, IPC_RMID, NULL);
|
||||||
|
|
||||||
g_mutex_unlock (xvimagesink->x_lock);
|
g_mutex_unlock (xvimagesink->x_lock);
|
||||||
GST_ELEMENT_ERROR (xvimagesink, RESOURCE, WRITE,
|
GST_ELEMENT_ERROR (xvimagesink, RESOURCE, WRITE,
|
||||||
("Failed to create output image buffer of %dx%d pixels",
|
("Failed to create output image buffer of %dx%d pixels",
|
||||||
xvimage->width, xvimage->height), ("Failed to XShmAttach"));
|
data->width, data->height), ("Failed to XShmAttach"));
|
||||||
goto beach_unlocked;
|
goto beach_unlocked;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -671,17 +556,17 @@ gst_xvimagesink_xvimage_new (GstXvImageSink * xvimagesink, GstCaps * caps)
|
||||||
/* Delete the shared memory segment as soon as we everyone is attached.
|
/* 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
|
* This way, it will be deleted as soon as we detach later, and not
|
||||||
* leaked if we crash. */
|
* leaked if we crash. */
|
||||||
shmctl (xvimage->SHMInfo.shmid, IPC_RMID, NULL);
|
shmctl (data->SHMInfo.shmid, IPC_RMID, NULL);
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (xvimagesink, "XServer ShmAttached to 0x%x, id 0x%lx",
|
GST_DEBUG_OBJECT (xvimagesink, "XServer ShmAttached to 0x%x, id 0x%lx",
|
||||||
xvimage->SHMInfo.shmid, xvimage->SHMInfo.shmseg);
|
data->SHMInfo.shmid, data->SHMInfo.shmseg);
|
||||||
} else
|
} else
|
||||||
#endif /* HAVE_XSHM */
|
#endif /* HAVE_XSHM */
|
||||||
{
|
{
|
||||||
xvimage->xvimage = XvCreateImage (xvimagesink->xcontext->disp,
|
data->xvimage = XvCreateImage (xvimagesink->xcontext->disp,
|
||||||
xvimagesink->xcontext->xv_port_id,
|
xvimagesink->xcontext->xv_port_id,
|
||||||
xvimage->im_format, NULL, xvimage->width, xvimage->height);
|
data->im_format, NULL, data->width, data->height);
|
||||||
if (!xvimage->xvimage || error_caught) {
|
if (!data->xvimage || error_caught) {
|
||||||
g_mutex_unlock (xvimagesink->x_lock);
|
g_mutex_unlock (xvimagesink->x_lock);
|
||||||
/* Reset error handler */
|
/* Reset error handler */
|
||||||
error_caught = FALSE;
|
error_caught = FALSE;
|
||||||
|
@ -689,15 +574,14 @@ gst_xvimagesink_xvimage_new (GstXvImageSink * xvimagesink, GstCaps * caps)
|
||||||
/* Push an error */
|
/* Push an error */
|
||||||
GST_ELEMENT_ERROR (xvimagesink, RESOURCE, WRITE,
|
GST_ELEMENT_ERROR (xvimagesink, RESOURCE, WRITE,
|
||||||
("Failed to create outputimage buffer of %dx%d pixels",
|
("Failed to create outputimage buffer of %dx%d pixels",
|
||||||
xvimage->width, xvimage->height),
|
data->width, data->height),
|
||||||
("could not XvCreateImage a %dx%d image",
|
("could not XvCreateImage a %dx%d image", data->width, data->height));
|
||||||
xvimage->width, xvimage->height));
|
|
||||||
goto beach_unlocked;
|
goto beach_unlocked;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* we have to use the returned data_size for our image size */
|
/* we have to use the returned data_size for our image size */
|
||||||
xvimage->size = xvimage->xvimage->data_size;
|
data->size = data->xvimage->data_size;
|
||||||
xvimage->xvimage->data = g_malloc (xvimage->size);
|
data->xvimage->data = g_malloc (data->size);
|
||||||
|
|
||||||
XSync (xvimagesink->xcontext->disp, FALSE);
|
XSync (xvimagesink->xcontext->disp, FALSE);
|
||||||
}
|
}
|
||||||
|
@ -708,18 +592,93 @@ gst_xvimagesink_xvimage_new (GstXvImageSink * xvimagesink, GstCaps * caps)
|
||||||
|
|
||||||
succeeded = TRUE;
|
succeeded = TRUE;
|
||||||
|
|
||||||
GST_BUFFER_DATA (xvimage) = (guchar *) xvimage->xvimage->data;
|
GST_BUFFER_DATA (buffer) = (guchar *) data->xvimage->data;
|
||||||
GST_BUFFER_SIZE (xvimage) = xvimage->size;
|
GST_BUFFER_SIZE (buffer) = data->size;
|
||||||
|
|
||||||
g_mutex_unlock (xvimagesink->x_lock);
|
g_mutex_unlock (xvimagesink->x_lock);
|
||||||
|
|
||||||
beach_unlocked:
|
beach_unlocked:
|
||||||
if (!succeeded) {
|
if (!succeeded) {
|
||||||
gst_xvimage_buffer_free (xvimage);
|
gst_xvimage_buffer_free (buffer);
|
||||||
xvimage = NULL;
|
buffer = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
return xvimage;
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* This function destroys a GstXvImage handling XShm availability */
|
||||||
|
static void
|
||||||
|
gst_xvimagesink_xvimage_destroy (GstXvImageSink * xvimagesink,
|
||||||
|
GstBuffer * xvimage)
|
||||||
|
{
|
||||||
|
GstXvImageData *data = NULL;
|
||||||
|
|
||||||
|
GST_DEBUG_OBJECT (xvimage, "Destroying buffer");
|
||||||
|
|
||||||
|
g_return_if_fail (xvimage != NULL);
|
||||||
|
g_return_if_fail (GST_IS_XVIMAGESINK (xvimagesink));
|
||||||
|
|
||||||
|
data = GET_XVDATA (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);
|
||||||
|
|
||||||
|
g_slice_free (GstXvImageData, data);
|
||||||
|
xvimage->owner_priv = NULL;
|
||||||
|
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We are called with the x_lock taken */
|
/* We are called with the x_lock taken */
|
||||||
|
@ -769,9 +728,9 @@ gst_xvimagesink_xwindow_draw_borders (GstXvImageSink * xvimagesink,
|
||||||
/* This function puts a GstXvImage on a GstXvImageSink's window. Returns FALSE
|
/* This function puts a GstXvImage on a GstXvImageSink's window. Returns FALSE
|
||||||
* if no window was available */
|
* if no window was available */
|
||||||
static gboolean
|
static gboolean
|
||||||
gst_xvimagesink_xvimage_put (GstXvImageSink * xvimagesink,
|
gst_xvimagesink_xvimage_put (GstXvImageSink * xvimagesink, GstBuffer * xvimage)
|
||||||
GstXvImageBuffer * xvimage)
|
|
||||||
{
|
{
|
||||||
|
GstXvImageData *data;
|
||||||
GstVideoRectangle result;
|
GstVideoRectangle result;
|
||||||
gboolean draw_border = FALSE;
|
gboolean draw_border = FALSE;
|
||||||
|
|
||||||
|
@ -794,11 +753,10 @@ gst_xvimagesink_xvimage_put (GstXvImageSink * xvimagesink,
|
||||||
if (xvimage && xvimagesink->cur_image != xvimage) {
|
if (xvimage && xvimagesink->cur_image != xvimage) {
|
||||||
if (xvimagesink->cur_image) {
|
if (xvimagesink->cur_image) {
|
||||||
GST_LOG_OBJECT (xvimagesink, "unreffing %p", xvimagesink->cur_image);
|
GST_LOG_OBJECT (xvimagesink, "unreffing %p", xvimagesink->cur_image);
|
||||||
gst_buffer_unref (GST_BUFFER_CAST (xvimagesink->cur_image));
|
gst_buffer_unref (xvimagesink->cur_image);
|
||||||
}
|
}
|
||||||
GST_LOG_OBJECT (xvimagesink, "reffing %p as our current image", xvimage);
|
GST_LOG_OBJECT (xvimagesink, "reffing %p as our current image", xvimage);
|
||||||
xvimagesink->cur_image =
|
xvimagesink->cur_image = gst_buffer_ref (xvimage);
|
||||||
GST_XVIMAGE_BUFFER_CAST (gst_buffer_ref (GST_BUFFER_CAST (xvimage)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Expose sends a NULL image, we take the latest frame */
|
/* Expose sends a NULL image, we take the latest frame */
|
||||||
|
@ -837,19 +795,21 @@ gst_xvimagesink_xvimage_put (GstXvImageSink * xvimagesink,
|
||||||
xvimagesink->redraw_border = FALSE;
|
xvimagesink->redraw_border = FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
data = GET_XVDATA (xvimage);
|
||||||
|
|
||||||
/* We scale to the window's geometry */
|
/* We scale to the window's geometry */
|
||||||
#ifdef HAVE_XSHM
|
#ifdef HAVE_XSHM
|
||||||
if (xvimagesink->xcontext->use_xshm) {
|
if (xvimagesink->xcontext->use_xshm) {
|
||||||
GST_LOG_OBJECT (xvimagesink,
|
GST_LOG_OBJECT (xvimagesink,
|
||||||
"XvShmPutImage with image %dx%d and window %dx%d, from xvimage %"
|
"XvShmPutImage with image %dx%d and window %dx%d, from xvimage %"
|
||||||
GST_PTR_FORMAT,
|
GST_PTR_FORMAT,
|
||||||
xvimage->width, xvimage->height,
|
data->width, data->height,
|
||||||
xvimagesink->render_rect.w, xvimagesink->render_rect.h, xvimage);
|
xvimagesink->render_rect.w, xvimagesink->render_rect.h, xvimage);
|
||||||
|
|
||||||
XvShmPutImage (xvimagesink->xcontext->disp,
|
XvShmPutImage (xvimagesink->xcontext->disp,
|
||||||
xvimagesink->xcontext->xv_port_id,
|
xvimagesink->xcontext->xv_port_id,
|
||||||
xvimagesink->xwindow->win,
|
xvimagesink->xwindow->win,
|
||||||
xvimagesink->xwindow->gc, xvimage->xvimage,
|
xvimagesink->xwindow->gc, data->xvimage,
|
||||||
xvimagesink->disp_x, xvimagesink->disp_y,
|
xvimagesink->disp_x, xvimagesink->disp_y,
|
||||||
xvimagesink->disp_width, xvimagesink->disp_height,
|
xvimagesink->disp_width, xvimagesink->disp_height,
|
||||||
result.x, result.y, result.w, result.h, FALSE);
|
result.x, result.y, result.w, result.h, FALSE);
|
||||||
|
@ -859,7 +819,7 @@ gst_xvimagesink_xvimage_put (GstXvImageSink * xvimagesink,
|
||||||
XvPutImage (xvimagesink->xcontext->disp,
|
XvPutImage (xvimagesink->xcontext->disp,
|
||||||
xvimagesink->xcontext->xv_port_id,
|
xvimagesink->xcontext->xv_port_id,
|
||||||
xvimagesink->xwindow->win,
|
xvimagesink->xwindow->win,
|
||||||
xvimagesink->xwindow->gc, xvimage->xvimage,
|
xvimagesink->xwindow->gc, data->xvimage,
|
||||||
xvimagesink->disp_x, xvimagesink->disp_y,
|
xvimagesink->disp_x, xvimagesink->disp_y,
|
||||||
xvimagesink->disp_width, xvimagesink->disp_height,
|
xvimagesink->disp_width, xvimagesink->disp_height,
|
||||||
result.x, result.y, result.w, result.h);
|
result.x, result.y, result.w, result.h);
|
||||||
|
@ -1734,6 +1694,7 @@ gst_xvimagesink_calculate_pixel_aspect_ratio (GstXContext * xcontext)
|
||||||
ratio = 4.0 * 576 / (3.0 * 720);
|
ratio = 4.0 * 576 / (3.0 * 720);
|
||||||
}
|
}
|
||||||
GST_DEBUG ("calculated pixel aspect ratio: %f", ratio);
|
GST_DEBUG ("calculated pixel aspect ratio: %f", ratio);
|
||||||
|
|
||||||
/* now find the one from par[][2] with the lowest delta to the real one */
|
/* now find the one from par[][2] with the lowest delta to the real one */
|
||||||
delta = DELTA (0);
|
delta = DELTA (0);
|
||||||
index = 0;
|
index = 0;
|
||||||
|
@ -2013,7 +1974,7 @@ gst_xvimagesink_imagepool_clear (GstXvImageSink * xvimagesink)
|
||||||
g_mutex_lock (xvimagesink->pool_lock);
|
g_mutex_lock (xvimagesink->pool_lock);
|
||||||
|
|
||||||
while (xvimagesink->image_pool) {
|
while (xvimagesink->image_pool) {
|
||||||
GstXvImageBuffer *xvimage = xvimagesink->image_pool->data;
|
GstBuffer *xvimage = xvimagesink->image_pool->data;
|
||||||
|
|
||||||
xvimagesink->image_pool = g_slist_delete_link (xvimagesink->image_pool,
|
xvimagesink->image_pool = g_slist_delete_link (xvimagesink->image_pool,
|
||||||
xvimagesink->image_pool);
|
xvimagesink->image_pool);
|
||||||
|
@ -2212,17 +2173,18 @@ gst_xvimagesink_setcaps (GstBaseSink * bsink, GstCaps * caps)
|
||||||
|
|
||||||
/* We renew our xvimage only if size or format changed;
|
/* We renew our xvimage only if size or format changed;
|
||||||
* the xvimage is the same size as the video pixel size */
|
* the xvimage is the same size as the video pixel size */
|
||||||
if ((xvimagesink->xvimage) &&
|
if ((xvimagesink->xvimage)) {
|
||||||
((im_format != xvimagesink->xvimage->im_format) ||
|
GstXvImageData *data = GET_XVDATA (xvimagesink->xvimage);
|
||||||
(video_width != xvimagesink->xvimage->width) ||
|
|
||||||
(video_height != xvimagesink->xvimage->height))) {
|
if (((im_format != data->im_format) ||
|
||||||
GST_DEBUG_OBJECT (xvimagesink,
|
(video_width != data->width) || (video_height != data->height))) {
|
||||||
"old format %" GST_FOURCC_FORMAT ", new format %" GST_FOURCC_FORMAT,
|
GST_DEBUG_OBJECT (xvimagesink,
|
||||||
GST_FOURCC_ARGS (xvimagesink->xvimage->im_format),
|
"old format %" GST_FOURCC_FORMAT ", new format %" GST_FOURCC_FORMAT,
|
||||||
GST_FOURCC_ARGS (im_format));
|
GST_FOURCC_ARGS (data->im_format), GST_FOURCC_ARGS (im_format));
|
||||||
GST_DEBUG_OBJECT (xvimagesink, "renewing xvimage");
|
GST_DEBUG_OBJECT (xvimagesink, "renewing xvimage");
|
||||||
gst_buffer_unref (GST_BUFFER (xvimagesink->xvimage));
|
gst_buffer_unref (xvimagesink->xvimage);
|
||||||
xvimagesink->xvimage = NULL;
|
xvimagesink->xvimage = NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
g_mutex_unlock (xvimagesink->flow_lock);
|
g_mutex_unlock (xvimagesink->flow_lock);
|
||||||
|
@ -2362,6 +2324,7 @@ gst_xvimagesink_show_frame (GstVideoSink * vsink, GstBuffer * buf)
|
||||||
|
|
||||||
xvimagesink = GST_XVIMAGESINK (vsink);
|
xvimagesink = GST_XVIMAGESINK (vsink);
|
||||||
|
|
||||||
|
#if 0
|
||||||
/* If this buffer has been allocated using our buffer management we simply
|
/* If this buffer has been allocated using our buffer management we simply
|
||||||
put the ximage which is in the PRIVATE pointer */
|
put the ximage which is in the PRIVATE pointer */
|
||||||
if (GST_IS_XVIMAGE_BUFFER (buf)) {
|
if (GST_IS_XVIMAGE_BUFFER (buf)) {
|
||||||
|
@ -2369,7 +2332,9 @@ gst_xvimagesink_show_frame (GstVideoSink * vsink, GstBuffer * buf)
|
||||||
if (!gst_xvimagesink_xvimage_put (xvimagesink,
|
if (!gst_xvimagesink_xvimage_put (xvimagesink,
|
||||||
GST_XVIMAGE_BUFFER_CAST (buf)))
|
GST_XVIMAGE_BUFFER_CAST (buf)))
|
||||||
goto no_window;
|
goto no_window;
|
||||||
} else {
|
} else
|
||||||
|
#endif
|
||||||
|
{
|
||||||
GST_CAT_LOG_OBJECT (GST_CAT_PERFORMANCE, xvimagesink,
|
GST_CAT_LOG_OBJECT (GST_CAT_PERFORMANCE, xvimagesink,
|
||||||
"slow copy into bufferpool buffer %p", buf);
|
"slow copy into bufferpool buffer %p", buf);
|
||||||
/* Else we have to copy the data into our private image, */
|
/* Else we have to copy the data into our private image, */
|
||||||
|
@ -2384,21 +2349,22 @@ gst_xvimagesink_show_frame (GstVideoSink * vsink, GstBuffer * buf)
|
||||||
/* The create method should have posted an informative error */
|
/* The create method should have posted an informative error */
|
||||||
goto no_image;
|
goto no_image;
|
||||||
|
|
||||||
if (xvimagesink->xvimage->size < GST_BUFFER_SIZE (buf)) {
|
if (GST_BUFFER_SIZE (xvimagesink->xvimage) < GST_BUFFER_SIZE (buf)) {
|
||||||
GST_ELEMENT_ERROR (xvimagesink, RESOURCE, WRITE,
|
GST_ELEMENT_ERROR (xvimagesink, RESOURCE, WRITE,
|
||||||
("Failed to create output image buffer of %dx%d pixels",
|
("Failed to create output image buffer of %dx%d pixels",
|
||||||
xvimagesink->xvimage->width, xvimagesink->xvimage->height),
|
GET_XVDATA (xvimagesink->xvimage)->width,
|
||||||
|
GET_XVDATA (xvimagesink->xvimage)->height),
|
||||||
("XServer allocated buffer size did not match input buffer"));
|
("XServer allocated buffer size did not match input buffer"));
|
||||||
|
|
||||||
gst_xvimage_buffer_destroy (xvimagesink->xvimage);
|
gst_xvimagesink_xvimage_destroy (xvimagesink, xvimagesink->xvimage);
|
||||||
xvimagesink->xvimage = NULL;
|
xvimagesink->xvimage = NULL;
|
||||||
goto no_image;
|
goto no_image;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy (xvimagesink->xvimage->xvimage->data,
|
memcpy (GST_BUFFER_DATA (xvimagesink->xvimage),
|
||||||
GST_BUFFER_DATA (buf),
|
GST_BUFFER_DATA (buf),
|
||||||
MIN (GST_BUFFER_SIZE (buf), xvimagesink->xvimage->size));
|
MIN (GST_BUFFER_SIZE (buf), GST_BUFFER_SIZE (xvimagesink->xvimage)));
|
||||||
|
|
||||||
if (!gst_xvimagesink_xvimage_put (xvimagesink, xvimagesink->xvimage))
|
if (!gst_xvimagesink_xvimage_put (xvimagesink, xvimagesink->xvimage))
|
||||||
goto no_window;
|
goto no_window;
|
||||||
|
@ -2452,6 +2418,7 @@ gst_xvimagesink_event (GstBaseSink * sink, GstEvent * event)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
/* Buffer management */
|
/* Buffer management */
|
||||||
|
|
||||||
static GstCaps *
|
static GstCaps *
|
||||||
|
@ -2508,7 +2475,7 @@ gst_xvimagesink_buffer_alloc (GstBaseSink * bsink, guint64 offset, guint size,
|
||||||
{
|
{
|
||||||
GstFlowReturn ret = GST_FLOW_OK;
|
GstFlowReturn ret = GST_FLOW_OK;
|
||||||
GstXvImageSink *xvimagesink;
|
GstXvImageSink *xvimagesink;
|
||||||
GstXvImageBuffer *xvimage = NULL;
|
GstXvImageData *xvimage = NULL;
|
||||||
GstCaps *intersection = NULL;
|
GstCaps *intersection = NULL;
|
||||||
GstStructure *structure = NULL;
|
GstStructure *structure = NULL;
|
||||||
gint width, height, image_format;
|
gint width, height, image_format;
|
||||||
|
@ -2709,6 +2676,7 @@ invalid_caps:
|
||||||
goto beach;
|
goto beach;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Interfaces stuff */
|
/* Interfaces stuff */
|
||||||
|
|
||||||
|
@ -3674,8 +3642,10 @@ gst_xvimagesink_class_init (GstXvImageSinkClass * klass)
|
||||||
|
|
||||||
gstbasesink_class->get_caps = GST_DEBUG_FUNCPTR (gst_xvimagesink_getcaps);
|
gstbasesink_class->get_caps = GST_DEBUG_FUNCPTR (gst_xvimagesink_getcaps);
|
||||||
gstbasesink_class->set_caps = GST_DEBUG_FUNCPTR (gst_xvimagesink_setcaps);
|
gstbasesink_class->set_caps = GST_DEBUG_FUNCPTR (gst_xvimagesink_setcaps);
|
||||||
|
#if 0
|
||||||
gstbasesink_class->buffer_alloc =
|
gstbasesink_class->buffer_alloc =
|
||||||
GST_DEBUG_FUNCPTR (gst_xvimagesink_buffer_alloc);
|
GST_DEBUG_FUNCPTR (gst_xvimagesink_buffer_alloc);
|
||||||
|
#endif
|
||||||
gstbasesink_class->get_times = GST_DEBUG_FUNCPTR (gst_xvimagesink_get_times);
|
gstbasesink_class->get_times = GST_DEBUG_FUNCPTR (gst_xvimagesink_get_times);
|
||||||
gstbasesink_class->event = GST_DEBUG_FUNCPTR (gst_xvimagesink_event);
|
gstbasesink_class->event = GST_DEBUG_FUNCPTR (gst_xvimagesink_event);
|
||||||
|
|
||||||
|
@ -3749,12 +3719,6 @@ gst_xvimagesink_get_type (void)
|
||||||
&colorbalance_info);
|
&colorbalance_info);
|
||||||
g_type_add_interface_static (xvimagesink_type, GST_TYPE_PROPERTY_PROBE,
|
g_type_add_interface_static (xvimagesink_type, GST_TYPE_PROPERTY_PROBE,
|
||||||
&propertyprobe_info);
|
&propertyprobe_info);
|
||||||
|
|
||||||
|
|
||||||
/* register type and create class in a more safe place instead of at
|
|
||||||
* runtime since the type registration and class creation is not
|
|
||||||
* threadsafe. */
|
|
||||||
g_type_class_ref (gst_xvimage_buffer_get_type ());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return xvimagesink_type;
|
return xvimagesink_type;
|
||||||
|
|
|
@ -58,8 +58,7 @@ G_BEGIN_DECLS
|
||||||
typedef struct _GstXContext GstXContext;
|
typedef struct _GstXContext GstXContext;
|
||||||
typedef struct _GstXWindow GstXWindow;
|
typedef struct _GstXWindow GstXWindow;
|
||||||
typedef struct _GstXvImageFormat GstXvImageFormat;
|
typedef struct _GstXvImageFormat GstXvImageFormat;
|
||||||
typedef struct _GstXvImageBuffer GstXvImageBuffer;
|
typedef struct _GstXvImageData GstXvImageData;
|
||||||
typedef struct _GstXvImageBufferClass GstXvImageBufferClass;
|
|
||||||
|
|
||||||
typedef struct _GstXvImageSink GstXvImageSink;
|
typedef struct _GstXvImageSink GstXvImageSink;
|
||||||
typedef struct _GstXvImageSinkClass GstXvImageSinkClass;
|
typedef struct _GstXvImageSinkClass GstXvImageSinkClass;
|
||||||
|
@ -163,7 +162,7 @@ struct _GstXvImageFormat {
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* GstXImageBuffer:
|
* GstXImageData:
|
||||||
* @xvimagesink: a reference to our #GstXvImageSink
|
* @xvimagesink: a reference to our #GstXvImageSink
|
||||||
* @xvimage: the XvImage of this buffer
|
* @xvimage: the XvImage of this buffer
|
||||||
* @width: the width in pixels of XvImage @xvimage
|
* @width: the width in pixels of XvImage @xvimage
|
||||||
|
@ -171,11 +170,9 @@ struct _GstXvImageFormat {
|
||||||
* @im_format: the image format of XvImage @xvimage
|
* @im_format: the image format of XvImage @xvimage
|
||||||
* @size: the size in bytes of XvImage @xvimage
|
* @size: the size in bytes of XvImage @xvimage
|
||||||
*
|
*
|
||||||
* Subclass of #GstBuffer containing additional information about an XvImage.
|
* Structure with additional information about an XvImage.
|
||||||
*/
|
*/
|
||||||
struct _GstXvImageBuffer {
|
struct _GstXvImageData {
|
||||||
GstBuffer buffer;
|
|
||||||
|
|
||||||
/* Reference to the xvimagesink we belong to */
|
/* Reference to the xvimagesink we belong to */
|
||||||
GstXvImageSink *xvimagesink;
|
GstXvImageSink *xvimagesink;
|
||||||
|
|
||||||
|
@ -234,12 +231,13 @@ struct _GstXvImageSink {
|
||||||
|
|
||||||
GstXContext *xcontext;
|
GstXContext *xcontext;
|
||||||
GstXWindow *xwindow;
|
GstXWindow *xwindow;
|
||||||
GstXvImageBuffer *xvimage;
|
GstBuffer *xvimage;
|
||||||
GstXvImageBuffer *cur_image;
|
GstBuffer *cur_image;
|
||||||
|
|
||||||
GThread *event_thread;
|
GThread *event_thread;
|
||||||
gboolean running;
|
gboolean running;
|
||||||
|
|
||||||
|
/* Framerate numerator and denominator */
|
||||||
gint fps_n;
|
gint fps_n;
|
||||||
gint fps_d;
|
gint fps_d;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue